Documentation / corrected Bochs timer

git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1718 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
unzner
2012-10-05 09:41:41 +00:00
parent 0c3d365368
commit 42a75fa128
5 changed files with 107 additions and 48 deletions

View File

@ -37,8 +37,10 @@ aspect BochsListener {
{
assert(pev != NULL && "FATAL ERROR: TimerListener object ptr cannot be NULL!");
return static_cast<timer_id_t>(
bx_pc_system.register_timer(pev, fail::onTimerTrigger, pev->getTimeout(),
false, 1/*start immediately*/, "Fail*: BochsController"/*name*/));
bx_pc_system.register_timer(pev, fail::onTimerTrigger,
pev->getTimeout() * 1000 /*timeout in microseconds*/,
false /*non-continuous*/,
true /*start immediately*/, "Fail*: BochsController"/*name*/));
}
bool m_unregisterTimer(TimerListener* pev)
{

View File

@ -1,3 +1,4 @@
#include "../SALInst.hpp"
#include "BochsListener.hpp"
#include "../SALInst.hpp"

View File

@ -45,47 +45,45 @@ void BochsALUInstructions::buildEquivalenceClasses() {
}
}
void BochsALUInstructions::bochsInstrToInstrStruct(bxInstruction_c const *src, BochsALUInstr *dest) const {
if (dest == NULL) return;
void BochsALUInstructions::bochsInstrToInstrStruct(bxInstruction_c const &src, BochsALUInstr &dest) const {
//Note: it may be necessary to introduce a solution for two-byte
//opcodes once they overlap with one-byte ones
for (size_t i = 0; i < allInstrSize; i++) {
// first, check the opcode
if (allInstr[i].opcodeRegisterOffset <= BochsALUInstr::REG_COUNT) {
// the opcode listed in allInstr is the starting value for a range
if (src->b1() < allInstr[i].opcode ||
src->b1() > allInstr[i].opcode + BochsALUInstr::REG_COUNT) {
if (src.b1() < allInstr[i].opcode ||
src.b1() > allInstr[i].opcode + BochsALUInstr::REG_COUNT) {
continue;
}
} else if (src->b1() != allInstr[i].opcode) {
} else if (src.b1() != allInstr[i].opcode) {
// normal case -- just compare the opcode
continue;
}
// second, check the opcode extension
if (allInstr[i].reg < BochsALUInstr::REG_COUNT &&
allInstr[i].reg != src->nnn()) {
allInstr[i].reg != src.nnn()) {
continue;
}
// found it - now copy
if (allInstr[i].opcodeRegisterOffset <= BochsALUInstr::REG_COUNT) {
BochsALUInstr result = { allInstr[i].bochs_operation,
src->b1(),
allInstr[i].reg,
src->rm(),
allInstr[i].aluClass};
memcpy(dest, &result, sizeof(BochsALUInstr));
dest.bochs_operation = allInstr[i].bochs_operation;
dest.opcode = src.b1();
dest.reg = allInstr[i].reg;
dest.opcodeRegisterOffset = src.rm();
dest.aluClass = allInstr[i].aluClass;
} else {
memcpy(dest, &allInstr[i], sizeof(BochsALUInstr));
dest = allInstr[i];
}
return;
}
// not found - marking it undefined
dest->aluClass = ALU_UNDEF;
dest.aluClass = ALU_UNDEF;
}
bool BochsALUInstructions::isALUInstruction(const bxInstruction_c *src) {
lastOrigInstr = src;
bochsInstrToInstrStruct(src, &lastInstr);
bool BochsALUInstructions::isALUInstruction(bxInstruction_c const *src) {
memcpy(&lastOrigInstr, src, sizeof(bxInstruction_c));
bochsInstrToInstrStruct(lastOrigInstr, lastInstr);
if (lastInstr.aluClass != ALU_UNDEF) {
return true;
}
@ -97,7 +95,7 @@ bxInstruction_c BochsALUInstructions::randomEquivalent() const {
X86AluClass equClassID = lastInstr.aluClass;
if (equClassID == ALU_UNDEF) {
// something went wrong - just return the original instruction
return *lastOrigInstr;
return lastOrigInstr;
}
InstrList const &destList = equivalenceClasses.at(equClassID);
@ -106,11 +104,10 @@ bxInstruction_c BochsALUInstructions::randomEquivalent() const {
do {
int index = rand() % destList.size();
dest = destList[index];
} while (!memcmp(&dest, &lastInstr, sizeof(BochsALUInstr)));
} while (memcmp(&dest, &lastInstr, sizeof(BochsALUInstr)) == 0);
// first, copy everything
bxInstruction_c result;
memcpy(&result, lastOrigInstr, sizeof(bxInstruction_c));
bxInstruction_c result = lastOrigInstr;
// then change what has to be different
// execute functions

View File

@ -8,12 +8,16 @@
#include "cpu/instr.h"
/**
* Trying to order X86 ALU instructions.
* \enum X86AluClass
*
* \brief An attempt to order X86 ALU instructions.
*
* An attempt to order X86 ALU instructions.
* Each instruction class contains instructions
* of roughly equal length and operands, so that
* all the bxInstruction_c structures residing within
* one class contain the same member fields (except for
* b1, rm and the execute pointers).
* b1, rm and the execute function pointers).
*/
enum X86AluClass {
ALU_UNDEF = 0,
@ -32,6 +36,8 @@ enum X86AluClass {
};
/**
* \struct BochsALUInstr
*
* A struct describing a specific x86
* ALU instruction in terms of Bochs.
*/
@ -73,11 +79,9 @@ struct BochsALUInstr {
/**
* Array containing most (all?) Bochs ALU commands.
* Attention: here, \a reg and \a opcodeRegisterOffset, if less than 8,
* define the maximum value possible in this field,
* according to the Bochs instruction decoder function.
* (see the BxOpcodeInfoG... arrays in cpu/fetchdecode.h)
* \var aluInstructions
*
* Array containing the Bochs IA-32 Integer ALU commands.
*/
const BochsALUInstr aluInstructions [] = {
// Now is a great time to open Volume 2 of Intel's IA-32 documentation.
@ -266,33 +270,81 @@ const BochsALUInstr aluInstructions [] = {
/* --- \\\ BINARY OPERATIONS /// --- */
};
const size_t aluInstructionsSize = sizeof(aluInstructions);
/**
* \var aluInstructionsSize
*
* the size of aluInstructions, in bytes
*/
size_t const aluInstructionsSize = sizeof(aluInstructions);
/**
* \class BochsALUInstructions
*
* \brfief This class handles Bochs ALU instructions.
*
* This class analyses a given bxInstruction_c object:
* if it belongs to the instructions listed in
* \a allInstr, the user can request a random
* ALU instruction with an equivalent addressing mode.
*/
class BochsALUInstructions {
public:
/**
*
* A list of Bochs instructions
*/
typedef std::vector<BochsALUInstr> InstrList;
/**
* This data structure assigns lists of instructions on their ALU equivalence
* class.
*
* \see X86AluClass
*/
typedef std::map<X86AluClass, InstrList> EquivClassMap;
/**
*
* Creates a new BochsALUInstructions object.
* @param initial_array initialises \a allInstr
* @param array_size the size of initial_array
*/
BochsALUInstructions(const BochsALUInstr *initial_array, size_t array_size);
/**
* Destroys the BochsALUInstructions object.
*/
~BochsALUInstructions() { free(allInstr); }
/**
* Determines if a given Bochs instruction is an ALU instruction.
* @param src the instruction to examine. It is stored internally
* to be reused with \a randomEquivalent
* @returns \c true if the given instruction is an ALU instruction,
* \c false otherwise
*/
bool isALUInstruction(const bxInstruction_c *src);
/**
* Determines a new bxInstruction_c object with an equivalent
* addressing mode.
* @returns a bxInstruction_c object as described above
*/
bxInstruction_c randomEquivalent() const;
protected:
void bochsInstrToInstrStruct(const bxInstruction_c *src, BochsALUInstr *dest) const;
/**
* Convert a bxInstruction_c object into its matching BochsALUInstr object.
* @params src the Bochs instruction to examine
* @params dest the resulting BochsALUInstr object. Its \a aluClass field
* is set to \c ALU_UNDEF in case no matching ALU instruction
* could be found. In this case, all other fields of dest are invalid.
*/
void bochsInstrToInstrStruct(bxInstruction_c const &src, BochsALUInstr &dest) const;
private:
BochsALUInstr *allInstr;
BochsALUInstr lastInstr;
const bxInstruction_c *lastOrigInstr;
size_t allInstrSize;
EquivClassMap equivalenceClasses;
BochsALUInstr *allInstr; //<! array that contains all known ALU instructions of the object
size_t allInstrSize; //<! the element count of the allInstr array
BochsALUInstr lastInstr; //<! a buffer for the last generated ALU instruction
bxInstruction_c lastOrigInstr; //!< a buffer for the last examined Bochs instruction
EquivClassMap equivalenceClasses; //!< the object's \a EquivClassMap (see there)
/**
* A function to build the equivalence classes from the given instructions.
*/
void buildEquivalenceClasses();
#ifdef DEBUG
void printNestedMap();
void printNestedMap(); //!< prints the \a EquivClassMap of the oject
#endif
};

View File

@ -163,8 +163,9 @@ void L4SysExperiment::injectInstruction(bxInstruction_c *oldInstr, bxInstruction
}
unsigned L4SysExperiment::calculateTimeout() {
// the timeout in seconds, plus one backup second (avoids rounding overhead)
// [instr] / [instr / s] = [s]
unsigned seconds = L4SYS_NUMINSTR / L4SYS_BOCHS_IPS;
unsigned seconds = L4SYS_NUMINSTR / L4SYS_BOCHS_IPS + 1;
// 1.1 (+10 percent) * 1000 ms/s * [s]
return 1100 * seconds;
}
@ -200,9 +201,11 @@ bool L4SysExperiment::run() {
} else {
kernel++;
}
// log << "EIP = " << hex << simulator.getRegisterManager().getInstructionPointer() << endl;
}
log << "test function calculation position reached after " << dec << count << " instructions; "
log << "EIP = " << hex
<< simulator.getRegisterManager().getInstructionPointer() << endl;
log << "test function calculation position reached after "
<< dec << count << " instructions; "
<< "ul: " << ul << ", kernel: " << kernel << endl;
#elif PREPARATION_STEP == 3
// STEP 3: determine the output of a "golden run"
@ -222,7 +225,8 @@ bool L4SysExperiment::run() {
log << "Output successfully logged!" << endl;
} else {
log
<< "Obviously, there is some trouble with the events registered - aborting simulation!"
<< "Obviously, there is some trouble with"
<< " the events registered - aborting simulation!"
<< endl;
golden_run_file.close();
simulator.terminate(10);
@ -238,7 +242,8 @@ bool L4SysExperiment::run() {
* You would probably need some kind of loop detection,
* but for the moment, I have to focus on different issues.
*/
if (stat(L4SYS_INSTRUCTION_LIST, &teststruct) == -1 || stat(L4SYS_ALU_INSTRUCTIONS, &teststruct) == -1) {
if (stat(L4SYS_INSTRUCTION_LIST, &teststruct) == -1 ||
stat(L4SYS_ALU_INSTRUCTIONS, &teststruct) == -1) {
log << "restoring state" << endl;
simulator.restore(L4SYS_STATE_FOLDER);
log << "EIP = " << hex
@ -296,7 +301,8 @@ bool L4SysExperiment::run() {
#elif PREPARATION_STEP == 0
// LAST STEP: The actual experiment.
struct stat teststruct;
if (stat(L4SYS_STATE_FOLDER, &teststruct) == -1 || stat(L4SYS_CORRECT_OUTPUT, &teststruct) == -1) {
if (stat(L4SYS_STATE_FOLDER, &teststruct) == -1 ||
stat(L4SYS_CORRECT_OUTPUT, &teststruct) == -1) {
log << "Important data missing - call \"prepare\" first." << endl;
simulator.terminate(10);
}
@ -526,7 +532,7 @@ bool L4SysExperiment::run() {
}
} else if (exp_type == param.msg.ALUINSTR) {
BochsALUInstructions aluInstrObject(aluInstructions, aluInstructionsSize);
static BochsALUInstructions aluInstrObject(aluInstructions, aluInstructionsSize);
// find the closest ALU instruction after the current IP
bxInstruction_c *currInstr;
@ -536,7 +542,7 @@ bool L4SysExperiment::run() {
}
// now exchange it with a random equivalent
bxInstruction_c newInstr = aluInstrObject.randomEquivalent();
if (!memcmp(&newInstr, currInstr, sizeof(bxInstruction_c))) {
if (memcmp(&newInstr, currInstr, sizeof(bxInstruction_c)) == 0) {
// something went wrong - exit experiment
param.msg.set_resulttype(param.msg.UNKNOWN);
param.msg.set_resultdata(
@ -561,6 +567,7 @@ bool L4SysExperiment::run() {
BPSingleListener ev_incomplete(ANY_ADDR, L4SYS_ADDRESS_SPACE);
ev_incomplete.setCounter(static_cast<unsigned>(L4SYS_NUMINSTR * 1.1));
simulator.addListener(&ev_incomplete);
log << calculateTimeout() << endl;
TimerListener ev_timeout(calculateTimeout());
simulator.addListener(&ev_timeout);