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:
@ -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)
|
||||
{
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
#include "../SALInst.hpp"
|
||||
#include "BochsListener.hpp"
|
||||
#include "../SALInst.hpp"
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
};
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user