Make FailBochs compile again (after changes in r1966).
For now, only breakpoints are working. Other event sources need to be revised, too. git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1981 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
@ -9,6 +9,7 @@ if(BUILD_BOCHS)
|
|||||||
SimulatorController.cc
|
SimulatorController.cc
|
||||||
bochs/BochsController.cc
|
bochs/BochsController.cc
|
||||||
bochs/BochsListener.cc
|
bochs/BochsListener.cc
|
||||||
|
bochs/BochsCPU.cc
|
||||||
)
|
)
|
||||||
elseif(BUILD_GEM5)
|
elseif(BUILD_GEM5)
|
||||||
set(SRCS
|
set(SRCS
|
||||||
@ -65,7 +66,7 @@ endif(BUILD_BOCHS)
|
|||||||
|
|
||||||
if(BUILD_X86)
|
if(BUILD_X86)
|
||||||
set(SRCS ${SRCS}
|
set(SRCS ${SRCS}
|
||||||
|
x86/Architecture.cc
|
||||||
)
|
)
|
||||||
elseif(BUILD_ARM)
|
elseif(BUILD_ARM)
|
||||||
set(SRCS ${SRCS}
|
set(SRCS ${SRCS}
|
||||||
|
|||||||
60
src/core/sal/bochs/BochsCPU.cc
Normal file
60
src/core/sal/bochs/BochsCPU.cc
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#include "BochsCPU.hpp"
|
||||||
|
#include "../SALConfig.hpp"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace fail {
|
||||||
|
|
||||||
|
regdata_t BochsCPU::getRegisterContent(Register* reg)
|
||||||
|
{
|
||||||
|
assert(reg != NULL && "FATAL ERROR: reg-ptr cannot be NULL!");
|
||||||
|
// TODO: BX_CPU(0) *always* correct?
|
||||||
|
|
||||||
|
if (reg->getId() == RID_FLAGS) // EFLAGS register?
|
||||||
|
return *reinterpret_cast<regdata_t*>(&(BX_CPU(id)->eflags));
|
||||||
|
|
||||||
|
#ifdef SIM_SUPPORT_64
|
||||||
|
if (reg->getId() == RID_PC) // program counter?
|
||||||
|
return static_cast<regdata_t>(BX_CPU(id)->gen_reg[BX_64BIT_REG_RIP].rrx);
|
||||||
|
else // 64 bit general purpose registers
|
||||||
|
return static_cast<regdata_t>(BX_CPU(id)->gen_reg[reg->getId()].rrx);
|
||||||
|
#else // 32 bit mode
|
||||||
|
if (reg->getId() == RID_PC)
|
||||||
|
return static_cast<regdata_t>(BX_CPU(id)->gen_reg[BX_32BIT_REG_EIP].dword.erx);
|
||||||
|
else // 32 bit general purpose registers
|
||||||
|
return static_cast<regdata_t>(BX_CPU(id)->gen_reg[reg->getId()].dword.erx);
|
||||||
|
#endif // SIM_SUPPORT_64
|
||||||
|
}
|
||||||
|
|
||||||
|
void BochsCPU::setRegisterContent(Register* reg, regdata_t value)
|
||||||
|
{
|
||||||
|
assert(reg != NULL && "FATAL ERROR: reg-ptr cannot be NULL!");
|
||||||
|
// TODO: BX_CPU(0) *always* correct?
|
||||||
|
|
||||||
|
if (reg->getId() == RID_FLAGS) { // EFLAGS register?
|
||||||
|
regdata_t* pData = reinterpret_cast<regdata_t*>(&(BX_CPU(id)->eflags));
|
||||||
|
#ifdef SIM_SUPPORT_64
|
||||||
|
// We are in 64 bit mode: Just assign the lower 32 bits!
|
||||||
|
*pData = ((*pData) & 0xFFFFFFFF00000000ULL) | (value & 0xFFFFFFFFULL);
|
||||||
|
#else
|
||||||
|
*pData = value;
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
regdata_t* pData;
|
||||||
|
#ifdef SIM_SUPPORT_64
|
||||||
|
if (reg->getId() == RID_PC) // program counter?
|
||||||
|
pData = &(BX_CPU(id)->gen_reg[BX_64BIT_REG_RIP].rrx);
|
||||||
|
else // 64 bit general purpose registers
|
||||||
|
pData = &(BX_CPU(id)->gen_reg[reg->getId()].rrx);
|
||||||
|
#else // 32 bit mode
|
||||||
|
if (reg->getId() == RID_PC)
|
||||||
|
pData = &(BX_CPU(id)->gen_reg[BX_32BIT_REG_EIP].dword.erx);
|
||||||
|
else // 32 bit general purpose registers
|
||||||
|
pData = &(BX_CPU(id)->gen_reg[reg->getId()].dword.erx);
|
||||||
|
#endif // SIM_SUPPORT_64
|
||||||
|
*pData = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end-of-namespace: fail
|
||||||
107
src/core/sal/bochs/BochsCPU.hpp
Normal file
107
src/core/sal/bochs/BochsCPU.hpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#ifndef __BOCHS_CPU_HPP__
|
||||||
|
#define __BOCHS_CPU_HPP__
|
||||||
|
|
||||||
|
#include "../x86/Architecture.hpp"
|
||||||
|
#include "../x86/CPUState.hpp"
|
||||||
|
|
||||||
|
#include "bochs.h"
|
||||||
|
#include "cpu/cpu.h"
|
||||||
|
|
||||||
|
namespace fail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class BochsCPU
|
||||||
|
* TODO.
|
||||||
|
*/
|
||||||
|
class BochsCPU : public X86Architecture, public X86CPUState {
|
||||||
|
private:
|
||||||
|
unsigned int m_Id; //!< TODO: Whats this for?
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Initializes the Bochs CPU with the provided \c id.
|
||||||
|
* @param id TODO
|
||||||
|
*/
|
||||||
|
BochsCPU(unsigned int id) : m_Id(id) { }
|
||||||
|
/**
|
||||||
|
* Retrieves the content of the register \c reg.
|
||||||
|
* @param reg the register pointer of interest (cannot be \c NULL)
|
||||||
|
* @return the content of the register \c reg
|
||||||
|
*/
|
||||||
|
regdata_t getRegisterContent(Register* reg);
|
||||||
|
/**
|
||||||
|
* Sets the content of the register \c reg to \c value.
|
||||||
|
* @param reg the destination register object pointer (cannot be \c NULL)
|
||||||
|
* @param value the new value to assign
|
||||||
|
*/
|
||||||
|
void setRegisterContent(Register* reg, regdata_t value);
|
||||||
|
/**
|
||||||
|
* Returns the current instruction pointer (aka program counter).
|
||||||
|
* @return the current (e)ip register content
|
||||||
|
*/
|
||||||
|
address_t getInstructionPointer() { return getRegisterContent(getRegister(RID_PC)); }
|
||||||
|
/**
|
||||||
|
* Returns the current stack pointer.
|
||||||
|
* @return the current (e)sp register content
|
||||||
|
*/
|
||||||
|
address_t getStackPointer() { return getRegisterContent(getRegister(RID_CSP)); }
|
||||||
|
/**
|
||||||
|
* Returns the current base pointer.
|
||||||
|
* @return the current (e)bp register content
|
||||||
|
*/
|
||||||
|
address_t getBasePointer() { return getRegisterContent(getRegister(RID_CBP)); }
|
||||||
|
/**
|
||||||
|
* Returns the current (E)FLAGS.
|
||||||
|
* @return the current (E)FLAGS processor register content
|
||||||
|
*/
|
||||||
|
regdata_t getFlagsRegister() { return getRegisterContent(getRegister(RID_FLAGS)); }
|
||||||
|
/**
|
||||||
|
* Returns \c true if the corresponding flag is set, or \c false
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
bool getCarryFlag() const { return BX_CPU(0)->get_CF(); }
|
||||||
|
bool getParityFlag() const { return BX_CPU(0)->get_PF(); }
|
||||||
|
bool getZeroFlag() const { return BX_CPU(0)->get_ZF(); }
|
||||||
|
bool getSignFlag() const { return BX_CPU(0)->get_SF(); }
|
||||||
|
bool getOverflowFlag() const { return BX_CPU(0)->get_OF(); }
|
||||||
|
bool getTrapFlag() const { return BX_CPU(0)->get_TF(); }
|
||||||
|
bool getInterruptFlag() const { return BX_CPU(0)->get_IF(); }
|
||||||
|
bool getDirectionFlag() const { return BX_CPU(0)->get_DF(); }
|
||||||
|
unsigned getIOPrivilegeLevel() const { return BX_CPU(0)->get_IOPL(); }
|
||||||
|
bool getNestedTaskFlag() const { return BX_CPU(0)->get_NT(); }
|
||||||
|
bool getResumeFlag() const { return BX_CPU(0)->get_RF(); }
|
||||||
|
bool getVMFlag() const { return BX_CPU(0)->get_VM(); }
|
||||||
|
bool getAlignmentCheckFlag() const { return BX_CPU(0)->get_AC(); }
|
||||||
|
bool getVInterruptFlag() const { return BX_CPU(0)->get_VIF(); }
|
||||||
|
bool getVInterruptPendingFlag() const { return BX_CPU(0)->get_VIP(); }
|
||||||
|
bool getIdentificationFlag() const { return BX_CPU(0)->get_ID(); }
|
||||||
|
/**
|
||||||
|
* Sets/resets various status FLAGS.
|
||||||
|
*/
|
||||||
|
void setCarryFlag(bool bit) { BX_CPU(0)->set_CF(bit); }
|
||||||
|
void setParityFlag(bool bit) { BX_CPU(0)->set_PF(bit); }
|
||||||
|
void setZeroFlag(bool bit) { BX_CPU(0)->set_ZF(bit); }
|
||||||
|
void setSignFlag(bool bit) { BX_CPU(0)->set_SF(bit); }
|
||||||
|
void setOverflowFlag(bool bit) { BX_CPU(0)->set_OF(bit); }
|
||||||
|
void setTrapFlag(bool bit) { BX_CPU(0)->set_TF(bit); }
|
||||||
|
void setInterruptFlag(bool bit) { BX_CPU(0)->set_IF(bit); }
|
||||||
|
void setDirectionFlag(bool bit) { BX_CPU(0)->set_DF(bit); }
|
||||||
|
void setIOPrivilegeLevel(unsigned lvl) { BX_CPU(0)->set_IOPL(lvl); }
|
||||||
|
void setNestedTaskFlag(bool bit) { BX_CPU(0)->set_NT(bit); }
|
||||||
|
void setResumeFlag(bool bit) { BX_CPU(0)->set_RF(bit); }
|
||||||
|
void setVMFlag(bool bit) { BX_CPU(0)->set_VM(bit); }
|
||||||
|
void setAlignmentCheckFlag(bool bit) { BX_CPU(0)->set_AC(bit); }
|
||||||
|
void setVInterruptFlag(bool bit) { BX_CPU(0)->set_VIF(bit); }
|
||||||
|
void setVInterruptPendingFlag(bool bit) { BX_CPU(0)->set_VIP(bit); }
|
||||||
|
void setIdentificationFlag(bool bit) { BX_CPU(0)->set_ID(bit); }
|
||||||
|
/**
|
||||||
|
* Returns the current id of this CPU.
|
||||||
|
* @return the current id
|
||||||
|
*/
|
||||||
|
unsigned int getId() { return m_Id; }
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef BochsCPU ConcreteCPU;
|
||||||
|
|
||||||
|
} // end-of-namespace: fail
|
||||||
|
|
||||||
|
#endif // __BOCHS_CPU_HPP__
|
||||||
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
#include "BochsController.hpp"
|
#include "BochsController.hpp"
|
||||||
#include "BochsMemory.hpp"
|
#include "BochsMemory.hpp"
|
||||||
#include "BochsRegister.hpp"
|
//#include "BochsRegister.hpp"
|
||||||
#include "../Register.hpp"
|
//#include "../Register.hpp"
|
||||||
#include "../SALInst.hpp"
|
#include "../SALInst.hpp"
|
||||||
#include "../Listener.hpp"
|
#include "../Listener.hpp"
|
||||||
|
|
||||||
@ -19,58 +19,15 @@ bx_bool reboot_bochs_request = false;
|
|||||||
bx_bool interrupt_injection_request = false;
|
bx_bool interrupt_injection_request = false;
|
||||||
|
|
||||||
BochsController::BochsController()
|
BochsController::BochsController()
|
||||||
: SimulatorController(new BochsRegisterManager(), new BochsMemoryManager()),
|
: SimulatorController(new BochsMemoryManager()),
|
||||||
m_CPUContext(NULL), m_CurrentInstruction(NULL)
|
m_CPUContext(NULL), m_CurrentInstruction(NULL)
|
||||||
{
|
{
|
||||||
// -------------------------------------
|
for (unsigned i = 0; i < BX_SMP_PROCESSORS; i++)
|
||||||
// Add the general purpose register:
|
addCPU(new ConcreteCPU(i));
|
||||||
#if BX_SUPPORT_X86_64
|
|
||||||
// -- 64 bit register --
|
|
||||||
const std::string names[] = { "RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI",
|
|
||||||
"RDI", "R8", "R9", "R10", "R11", "R12", "R13",
|
|
||||||
"R14", "R15" };
|
|
||||||
for (unsigned short i = 0; i < 16; i++) {
|
|
||||||
BxGPReg* pReg = new BxGPReg(i, 64, &(BX_CPU(0)->gen_reg[i].rrx));
|
|
||||||
pReg->setName(names[i]);
|
|
||||||
m_Regs->add(pReg);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// -- 32 bit register --
|
|
||||||
const std::string names[] = { "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI",
|
|
||||||
"EDI" };
|
|
||||||
for (unsigned short i = 0; i < 8; i++) {
|
|
||||||
BxGPReg* pReg = new BxGPReg(i, 32, &(BX_CPU(0)->gen_reg[i].dword.erx));
|
|
||||||
pReg->setName(names[i]);
|
|
||||||
m_Regs->add(pReg);
|
|
||||||
}
|
|
||||||
#endif // BX_SUPPORT_X86_64
|
|
||||||
// -------------------------------------
|
|
||||||
// Add the Program counter register:
|
|
||||||
#if BX_SUPPORT_X86_64
|
|
||||||
BxPCReg* pPCReg = new BxPCReg(RID_PC, 64, &(BX_CPU(0)->gen_reg[BX_64BIT_REG_RIP].rrx));
|
|
||||||
pPCReg->setName("RIP");
|
|
||||||
#else
|
|
||||||
BxPCReg* pPCReg = new BxPCReg(RID_PC, 32, &(BX_CPU(0)->gen_reg[BX_32BIT_REG_EIP].dword.erx));
|
|
||||||
pPCReg->setName("EIP");
|
|
||||||
#endif // BX_SUPPORT_X86_64
|
|
||||||
// -------------------------------------
|
|
||||||
// Add the Status register (x86 cpu FLAGS):
|
|
||||||
BxFlagsReg* pFlagReg = new BxFlagsReg(RID_FLAGS, reinterpret_cast<regdata_t*>(&(BX_CPU(0)->eflags)));
|
|
||||||
// Note: "eflags" is (always) of type Bit32u which matches the regdata_t only in
|
|
||||||
// case of the 32 bit version (id est !BX_SUPPORT_X86_64). Therefor we need
|
|
||||||
// to ensure to assign only 32 bit to the Bochs internal register variable
|
|
||||||
// (see SAL/bochs/BochsRegister.hpp, setData) if we are in 64 bit mode.
|
|
||||||
pFlagReg->setName("FLAGS");
|
|
||||||
m_Regs->add(pFlagReg);
|
|
||||||
m_Regs->add(pPCReg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BochsController::~BochsController()
|
BochsController::~BochsController()
|
||||||
{
|
{
|
||||||
for (RegisterManager::iterator it = m_Regs->begin(); it != m_Regs->end(); it++)
|
|
||||||
delete (*it); // free the memory, allocated in the constructor
|
|
||||||
m_Regs->clear();
|
|
||||||
delete m_Regs;
|
|
||||||
delete m_Mem;
|
delete m_Mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "iodev/iodev.h"
|
#include "iodev/iodev.h"
|
||||||
#include "pc_system.h"
|
#include "pc_system.h"
|
||||||
|
#include "gui/siminterface.h" // for BX_SMP_PROCESSORS
|
||||||
|
|
||||||
#define DEBUG
|
#define DEBUG
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
#if 0
|
||||||
#ifndef __BOCHS_REGISTER_HPP__
|
#ifndef __BOCHS_REGISTER_HPP__
|
||||||
#define __BOCHS_REGISTER_HPP__
|
#define __BOCHS_REGISTER_HPP__
|
||||||
|
|
||||||
@ -199,3 +200,4 @@ public:
|
|||||||
} // end-of-namespace: fail
|
} // end-of-namespace: fail
|
||||||
|
|
||||||
#endif // __BOCHS_REGISTER_HPP__
|
#endif // __BOCHS_REGISTER_HPP__
|
||||||
|
#endif
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
#if 0
|
||||||
#ifndef __BOCHS_REGISTER_IDS_HPP__
|
#ifndef __BOCHS_REGISTER_IDS_HPP__
|
||||||
#define __BOCHS_REGISTER_IDS_HPP__
|
#define __BOCHS_REGISTER_IDS_HPP__
|
||||||
|
|
||||||
@ -43,3 +44,4 @@ enum FlagsRegisterId { RID_FLAGS = RID_LAST_PC_ID };
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "bochs.h"
|
#include "bochs.h"
|
||||||
#include "cpu/cpu.h"
|
#include "cpu/cpu.h"
|
||||||
|
#include "gui/siminterface.h" // for BX_SMP_PROCESSORS
|
||||||
|
|
||||||
#include "../SALInst.hpp"
|
#include "../SALInst.hpp"
|
||||||
|
|
||||||
@ -22,9 +23,20 @@ aspect Breakpoints {
|
|||||||
// Points to the *current* bxInstruction-object
|
// Points to the *current* bxInstruction-object
|
||||||
bxInstruction_c* pInstr = *(tjp->arg<1>());
|
bxInstruction_c* pInstr = *(tjp->arg<1>());
|
||||||
|
|
||||||
|
// Detect the CPU that triggered the change:
|
||||||
|
unsigned i = 0;
|
||||||
|
#if BX_SUPPORT_SMP
|
||||||
|
for (; i < BX_SMP_PROCESSORS; i++) {
|
||||||
|
if (BX_CPU_C[i] == pThis) // cmp this ptr with all possible CPU objects
|
||||||
|
break; // index "i" found! -> stop!
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
fail::ConcreteCPU& triggerCPU = fail::simulator.getCPU(i);
|
||||||
|
// FIXME: slice ConcreteCPU object reference into BOCHS_CPU -> simplified
|
||||||
|
|
||||||
// Report this event to the Bochs controller:
|
// Report this event to the Bochs controller:
|
||||||
fail::simulator.updateBPEventInfo(pThis, pInstr);
|
fail::simulator.updateBPEventInfo(pThis, pInstr);
|
||||||
fail::simulator.onBreakpoint(pThis->get_instruction_pointer(), pThis->cr3);
|
fail::simulator.onBreakpoint(&triggerCPU, pThis->get_instruction_pointer(), pThis->cr3);
|
||||||
// Note: get_bx_opcode_name(pInstr->getIaOpcode()) retrieves the mnemonics.
|
// Note: get_bx_opcode_name(pInstr->getIaOpcode()) retrieves the mnemonics.
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user