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!");
|
assert(pev != NULL && "FATAL ERROR: TimerListener object ptr cannot be NULL!");
|
||||||
return static_cast<timer_id_t>(
|
return static_cast<timer_id_t>(
|
||||||
bx_pc_system.register_timer(pev, fail::onTimerTrigger, pev->getTimeout(),
|
bx_pc_system.register_timer(pev, fail::onTimerTrigger,
|
||||||
false, 1/*start immediately*/, "Fail*: BochsController"/*name*/));
|
pev->getTimeout() * 1000 /*timeout in microseconds*/,
|
||||||
|
false /*non-continuous*/,
|
||||||
|
true /*start immediately*/, "Fail*: BochsController"/*name*/));
|
||||||
}
|
}
|
||||||
bool m_unregisterTimer(TimerListener* pev)
|
bool m_unregisterTimer(TimerListener* pev)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
#include "../SALInst.hpp"
|
||||||
#include "BochsListener.hpp"
|
#include "BochsListener.hpp"
|
||||||
#include "../SALInst.hpp"
|
#include "../SALInst.hpp"
|
||||||
|
|
||||||
|
|||||||
@ -45,47 +45,45 @@ void BochsALUInstructions::buildEquivalenceClasses() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BochsALUInstructions::bochsInstrToInstrStruct(bxInstruction_c const *src, BochsALUInstr *dest) const {
|
void BochsALUInstructions::bochsInstrToInstrStruct(bxInstruction_c const &src, BochsALUInstr &dest) const {
|
||||||
if (dest == NULL) return;
|
|
||||||
//Note: it may be necessary to introduce a solution for two-byte
|
//Note: it may be necessary to introduce a solution for two-byte
|
||||||
//opcodes once they overlap with one-byte ones
|
//opcodes once they overlap with one-byte ones
|
||||||
for (size_t i = 0; i < allInstrSize; i++) {
|
for (size_t i = 0; i < allInstrSize; i++) {
|
||||||
// first, check the opcode
|
// first, check the opcode
|
||||||
if (allInstr[i].opcodeRegisterOffset <= BochsALUInstr::REG_COUNT) {
|
if (allInstr[i].opcodeRegisterOffset <= BochsALUInstr::REG_COUNT) {
|
||||||
// the opcode listed in allInstr is the starting value for a range
|
// the opcode listed in allInstr is the starting value for a range
|
||||||
if (src->b1() < allInstr[i].opcode ||
|
if (src.b1() < allInstr[i].opcode ||
|
||||||
src->b1() > allInstr[i].opcode + BochsALUInstr::REG_COUNT) {
|
src.b1() > allInstr[i].opcode + BochsALUInstr::REG_COUNT) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (src->b1() != allInstr[i].opcode) {
|
} else if (src.b1() != allInstr[i].opcode) {
|
||||||
// normal case -- just compare the opcode
|
// normal case -- just compare the opcode
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// second, check the opcode extension
|
// second, check the opcode extension
|
||||||
if (allInstr[i].reg < BochsALUInstr::REG_COUNT &&
|
if (allInstr[i].reg < BochsALUInstr::REG_COUNT &&
|
||||||
allInstr[i].reg != src->nnn()) {
|
allInstr[i].reg != src.nnn()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// found it - now copy
|
// found it - now copy
|
||||||
if (allInstr[i].opcodeRegisterOffset <= BochsALUInstr::REG_COUNT) {
|
if (allInstr[i].opcodeRegisterOffset <= BochsALUInstr::REG_COUNT) {
|
||||||
BochsALUInstr result = { allInstr[i].bochs_operation,
|
dest.bochs_operation = allInstr[i].bochs_operation;
|
||||||
src->b1(),
|
dest.opcode = src.b1();
|
||||||
allInstr[i].reg,
|
dest.reg = allInstr[i].reg;
|
||||||
src->rm(),
|
dest.opcodeRegisterOffset = src.rm();
|
||||||
allInstr[i].aluClass};
|
dest.aluClass = allInstr[i].aluClass;
|
||||||
memcpy(dest, &result, sizeof(BochsALUInstr));
|
|
||||||
} else {
|
} else {
|
||||||
memcpy(dest, &allInstr[i], sizeof(BochsALUInstr));
|
dest = allInstr[i];
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// not found - marking it undefined
|
// not found - marking it undefined
|
||||||
dest->aluClass = ALU_UNDEF;
|
dest.aluClass = ALU_UNDEF;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BochsALUInstructions::isALUInstruction(const bxInstruction_c *src) {
|
bool BochsALUInstructions::isALUInstruction(bxInstruction_c const *src) {
|
||||||
lastOrigInstr = src;
|
memcpy(&lastOrigInstr, src, sizeof(bxInstruction_c));
|
||||||
bochsInstrToInstrStruct(src, &lastInstr);
|
bochsInstrToInstrStruct(lastOrigInstr, lastInstr);
|
||||||
if (lastInstr.aluClass != ALU_UNDEF) {
|
if (lastInstr.aluClass != ALU_UNDEF) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -97,7 +95,7 @@ bxInstruction_c BochsALUInstructions::randomEquivalent() const {
|
|||||||
X86AluClass equClassID = lastInstr.aluClass;
|
X86AluClass equClassID = lastInstr.aluClass;
|
||||||
if (equClassID == ALU_UNDEF) {
|
if (equClassID == ALU_UNDEF) {
|
||||||
// something went wrong - just return the original instruction
|
// something went wrong - just return the original instruction
|
||||||
return *lastOrigInstr;
|
return lastOrigInstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstrList const &destList = equivalenceClasses.at(equClassID);
|
InstrList const &destList = equivalenceClasses.at(equClassID);
|
||||||
@ -106,11 +104,10 @@ bxInstruction_c BochsALUInstructions::randomEquivalent() const {
|
|||||||
do {
|
do {
|
||||||
int index = rand() % destList.size();
|
int index = rand() % destList.size();
|
||||||
dest = destList[index];
|
dest = destList[index];
|
||||||
} while (!memcmp(&dest, &lastInstr, sizeof(BochsALUInstr)));
|
} while (memcmp(&dest, &lastInstr, sizeof(BochsALUInstr)) == 0);
|
||||||
|
|
||||||
// first, copy everything
|
// first, copy everything
|
||||||
bxInstruction_c result;
|
bxInstruction_c result = lastOrigInstr;
|
||||||
memcpy(&result, lastOrigInstr, sizeof(bxInstruction_c));
|
|
||||||
|
|
||||||
// then change what has to be different
|
// then change what has to be different
|
||||||
// execute functions
|
// execute functions
|
||||||
|
|||||||
@ -8,12 +8,16 @@
|
|||||||
#include "cpu/instr.h"
|
#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
|
* Each instruction class contains instructions
|
||||||
* of roughly equal length and operands, so that
|
* of roughly equal length and operands, so that
|
||||||
* all the bxInstruction_c structures residing within
|
* all the bxInstruction_c structures residing within
|
||||||
* one class contain the same member fields (except for
|
* one class contain the same member fields (except for
|
||||||
* b1, rm and the execute pointers).
|
* b1, rm and the execute function pointers).
|
||||||
*/
|
*/
|
||||||
enum X86AluClass {
|
enum X86AluClass {
|
||||||
ALU_UNDEF = 0,
|
ALU_UNDEF = 0,
|
||||||
@ -32,6 +36,8 @@ enum X86AluClass {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* \struct BochsALUInstr
|
||||||
|
*
|
||||||
* A struct describing a specific x86
|
* A struct describing a specific x86
|
||||||
* ALU instruction in terms of Bochs.
|
* ALU instruction in terms of Bochs.
|
||||||
*/
|
*/
|
||||||
@ -73,11 +79,9 @@ struct BochsALUInstr {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array containing most (all?) Bochs ALU commands.
|
* \var aluInstructions
|
||||||
* Attention: here, \a reg and \a opcodeRegisterOffset, if less than 8,
|
*
|
||||||
* define the maximum value possible in this field,
|
* Array containing the Bochs IA-32 Integer ALU commands.
|
||||||
* according to the Bochs instruction decoder function.
|
|
||||||
* (see the BxOpcodeInfoG... arrays in cpu/fetchdecode.h)
|
|
||||||
*/
|
*/
|
||||||
const BochsALUInstr aluInstructions [] = {
|
const BochsALUInstr aluInstructions [] = {
|
||||||
// Now is a great time to open Volume 2 of Intel's IA-32 documentation.
|
// Now is a great time to open Volume 2 of Intel's IA-32 documentation.
|
||||||
@ -266,33 +270,81 @@ const BochsALUInstr aluInstructions [] = {
|
|||||||
/* --- \\\ BINARY OPERATIONS /// --- */
|
/* --- \\\ 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 {
|
class BochsALUInstructions {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
*
|
* A list of Bochs instructions
|
||||||
*/
|
*/
|
||||||
typedef std::vector<BochsALUInstr> InstrList;
|
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;
|
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);
|
BochsALUInstructions(const BochsALUInstr *initial_array, size_t array_size);
|
||||||
|
/**
|
||||||
|
* Destroys the BochsALUInstructions object.
|
||||||
|
*/
|
||||||
~BochsALUInstructions() { free(allInstr); }
|
~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);
|
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;
|
bxInstruction_c randomEquivalent() const;
|
||||||
protected:
|
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:
|
private:
|
||||||
BochsALUInstr *allInstr;
|
BochsALUInstr *allInstr; //<! array that contains all known ALU instructions of the object
|
||||||
BochsALUInstr lastInstr;
|
size_t allInstrSize; //<! the element count of the allInstr array
|
||||||
const bxInstruction_c *lastOrigInstr;
|
BochsALUInstr lastInstr; //<! a buffer for the last generated ALU instruction
|
||||||
size_t allInstrSize;
|
bxInstruction_c lastOrigInstr; //!< a buffer for the last examined Bochs instruction
|
||||||
EquivClassMap equivalenceClasses;
|
EquivClassMap equivalenceClasses; //!< the object's \a EquivClassMap (see there)
|
||||||
|
/**
|
||||||
|
* A function to build the equivalence classes from the given instructions.
|
||||||
|
*/
|
||||||
void buildEquivalenceClasses();
|
void buildEquivalenceClasses();
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void printNestedMap();
|
void printNestedMap(); //!< prints the \a EquivClassMap of the oject
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -163,8 +163,9 @@ void L4SysExperiment::injectInstruction(bxInstruction_c *oldInstr, bxInstruction
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned L4SysExperiment::calculateTimeout() {
|
unsigned L4SysExperiment::calculateTimeout() {
|
||||||
|
// the timeout in seconds, plus one backup second (avoids rounding overhead)
|
||||||
// [instr] / [instr / s] = [s]
|
// [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]
|
// 1.1 (+10 percent) * 1000 ms/s * [s]
|
||||||
return 1100 * seconds;
|
return 1100 * seconds;
|
||||||
}
|
}
|
||||||
@ -200,9 +201,11 @@ bool L4SysExperiment::run() {
|
|||||||
} else {
|
} else {
|
||||||
kernel++;
|
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;
|
<< "ul: " << ul << ", kernel: " << kernel << endl;
|
||||||
#elif PREPARATION_STEP == 3
|
#elif PREPARATION_STEP == 3
|
||||||
// STEP 3: determine the output of a "golden run"
|
// STEP 3: determine the output of a "golden run"
|
||||||
@ -222,7 +225,8 @@ bool L4SysExperiment::run() {
|
|||||||
log << "Output successfully logged!" << endl;
|
log << "Output successfully logged!" << endl;
|
||||||
} else {
|
} else {
|
||||||
log
|
log
|
||||||
<< "Obviously, there is some trouble with the events registered - aborting simulation!"
|
<< "Obviously, there is some trouble with"
|
||||||
|
<< " the events registered - aborting simulation!"
|
||||||
<< endl;
|
<< endl;
|
||||||
golden_run_file.close();
|
golden_run_file.close();
|
||||||
simulator.terminate(10);
|
simulator.terminate(10);
|
||||||
@ -238,7 +242,8 @@ bool L4SysExperiment::run() {
|
|||||||
* You would probably need some kind of loop detection,
|
* You would probably need some kind of loop detection,
|
||||||
* but for the moment, I have to focus on different issues.
|
* 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;
|
log << "restoring state" << endl;
|
||||||
simulator.restore(L4SYS_STATE_FOLDER);
|
simulator.restore(L4SYS_STATE_FOLDER);
|
||||||
log << "EIP = " << hex
|
log << "EIP = " << hex
|
||||||
@ -296,7 +301,8 @@ bool L4SysExperiment::run() {
|
|||||||
#elif PREPARATION_STEP == 0
|
#elif PREPARATION_STEP == 0
|
||||||
// LAST STEP: The actual experiment.
|
// LAST STEP: The actual experiment.
|
||||||
struct stat teststruct;
|
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;
|
log << "Important data missing - call \"prepare\" first." << endl;
|
||||||
simulator.terminate(10);
|
simulator.terminate(10);
|
||||||
}
|
}
|
||||||
@ -526,7 +532,7 @@ bool L4SysExperiment::run() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
} else if (exp_type == param.msg.ALUINSTR) {
|
} 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
|
// find the closest ALU instruction after the current IP
|
||||||
|
|
||||||
bxInstruction_c *currInstr;
|
bxInstruction_c *currInstr;
|
||||||
@ -536,7 +542,7 @@ bool L4SysExperiment::run() {
|
|||||||
}
|
}
|
||||||
// now exchange it with a random equivalent
|
// now exchange it with a random equivalent
|
||||||
bxInstruction_c newInstr = aluInstrObject.randomEquivalent();
|
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
|
// something went wrong - exit experiment
|
||||||
param.msg.set_resulttype(param.msg.UNKNOWN);
|
param.msg.set_resulttype(param.msg.UNKNOWN);
|
||||||
param.msg.set_resultdata(
|
param.msg.set_resultdata(
|
||||||
@ -561,6 +567,7 @@ bool L4SysExperiment::run() {
|
|||||||
BPSingleListener ev_incomplete(ANY_ADDR, L4SYS_ADDRESS_SPACE);
|
BPSingleListener ev_incomplete(ANY_ADDR, L4SYS_ADDRESS_SPACE);
|
||||||
ev_incomplete.setCounter(static_cast<unsigned>(L4SYS_NUMINSTR * 1.1));
|
ev_incomplete.setCounter(static_cast<unsigned>(L4SYS_NUMINSTR * 1.1));
|
||||||
simulator.addListener(&ev_incomplete);
|
simulator.addListener(&ev_incomplete);
|
||||||
|
log << calculateTimeout() << endl;
|
||||||
TimerListener ev_timeout(calculateTimeout());
|
TimerListener ev_timeout(calculateTimeout());
|
||||||
simulator.addListener(&ev_timeout);
|
simulator.addListener(&ev_timeout);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user