introducr new class for VMCS mapping so it can be customized per cpuid
This commit is contained in:
parent
3b87e71346
commit
5fe1423ab6
@ -823,7 +823,6 @@ typedef struct
|
||||
} bx_regs_msr_t;
|
||||
#endif
|
||||
|
||||
#include "cpuid.h"
|
||||
#include "crregs.h"
|
||||
#include "descriptor.h"
|
||||
#include "instr.h"
|
||||
@ -1013,6 +1012,8 @@ struct BX_SMM_State;
|
||||
struct BxOpcodeInfo_t;
|
||||
struct bx_cpu_statistics;
|
||||
|
||||
#include "cpuid.h"
|
||||
|
||||
class BOCHSAPI BX_CPU_C : public logfunctions {
|
||||
|
||||
public: // for now...
|
||||
@ -1196,6 +1197,7 @@ public: // for now...
|
||||
|
||||
VMCS_CACHE vmcs;
|
||||
VMX_CAP vmx_cap;
|
||||
VMCS_Mapping *vmcs_map;
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_SVM
|
||||
|
@ -27,8 +27,20 @@
|
||||
#include "cpuid.h"
|
||||
|
||||
#define LOG_THIS cpu->
|
||||
|
||||
bx_cpuid_t::bx_cpuid_t(BX_CPU_C *_cpu): cpu(_cpu)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
bx_cpuid_t::bx_cpuid_t(BX_CPU_C *_cpu, Bit32u vmcs_revision, const char *filename):
|
||||
cpu(_cpu), vmcs_map(vmcs_revision, filename)
|
||||
{
|
||||
init();
|
||||
}
|
||||
#endif
|
||||
|
||||
void bx_cpuid_t::init()
|
||||
{
|
||||
#if BX_SUPPORT_SMP
|
||||
nthreads = SIM->get_param_num(BXPN_CPU_NTHREADS)->get();
|
||||
|
@ -121,11 +121,18 @@ enum {
|
||||
#error "ISA extensions array limit exceeded!"
|
||||
#endif
|
||||
|
||||
class VMCS_Mapping;
|
||||
|
||||
class bx_cpuid_t {
|
||||
public:
|
||||
bx_cpuid_t(BX_CPU_C *_cpu);
|
||||
#if BX_SUPPORT_VMX
|
||||
bx_cpuid_t(BX_CPU_C *_cpu, Bit32u vmcs_revision, const char *filename);
|
||||
#endif
|
||||
virtual ~bx_cpuid_t() {}
|
||||
|
||||
void init();
|
||||
|
||||
// return CPU name
|
||||
virtual const char *get_name(void) const = 0;
|
||||
|
||||
@ -155,10 +162,8 @@ public:
|
||||
virtual int wrmsr(Bit32u index, Bit64u msr) { return -1; }
|
||||
#endif
|
||||
|
||||
#define BX_VMX_VMCS_REVISION_ID 0x2B /* better to be unique bochs VMCS revision id */
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
virtual Bit32u get_vmcs_revision_id(void) const { return BX_VMX_VMCS_REVISION_ID; }
|
||||
VMCS_Mapping* get_vmcs() { return &vmcs_map; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@ -198,6 +203,10 @@ protected:
|
||||
|
||||
void dump_cpuid_leaf(unsigned function, unsigned subfunction = 0) const;
|
||||
void dump_cpuid(unsigned max_std_leaf, unsigned max_ext_leaf) const;
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
VMCS_Mapping vmcs_map;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef bx_cpuid_t* (*bx_create_cpuid_method)(BX_CPU_C *cpu);
|
||||
|
@ -24,47 +24,47 @@
|
||||
#define NEED_CPU_REG_SHORTCUTS 1
|
||||
#include "bochs.h"
|
||||
#include "cpu.h"
|
||||
#define LOG_THIS BX_CPU_THIS_PTR
|
||||
|
||||
#define LOG_THIS BX_CPU(0)->
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
|
||||
static unsigned vmcs_map[16][1+VMX_HIGHEST_VMCS_ENCODING];
|
||||
|
||||
void BX_CPU_C::init_VMCS(void)
|
||||
VMCS_Mapping::VMCS_Mapping(Bit32u revision): revision_id(revision)
|
||||
{
|
||||
static bx_bool vmcs_map_ready = 0;
|
||||
unsigned type, field;
|
||||
clear();
|
||||
init_generic_mapping();
|
||||
}
|
||||
|
||||
init_vmx_capabilities();
|
||||
VMCS_Mapping::VMCS_Mapping(Bit32u revision, const char *filename): revision_id(revision)
|
||||
{
|
||||
clear();
|
||||
// read mapping from file
|
||||
}
|
||||
|
||||
if (vmcs_map_ready) return;
|
||||
vmcs_map_ready = 1;
|
||||
|
||||
for (type=0; type<16; type++) {
|
||||
for (field=0; field <= VMX_HIGHEST_VMCS_ENCODING; field++) {
|
||||
vmcs_map[type][field] = 0xffffffff;
|
||||
}
|
||||
}
|
||||
BX_CPP_INLINE Bit32u vmcs_encoding(Bit32u type, Bit32u field)
|
||||
{
|
||||
Bit32u encoding = ((type & 0xc) << 11) + ((type & 0x3) << 10) + field;
|
||||
return encoding;
|
||||
}
|
||||
|
||||
void VMCS_Mapping::init_generic_mapping()
|
||||
{
|
||||
#if 1
|
||||
// try to build generic VMCS map
|
||||
for (type=0; type<16; type++) {
|
||||
for (field=0; field <= VMX_HIGHEST_VMCS_ENCODING; field++) {
|
||||
unsigned encoding = ((type & 0xc) << 11) + ((type & 3) << 10) + field;
|
||||
// 16 types, 48 encodings (0x30), 4 bytes each field => 3072 bytes
|
||||
// reserve VMCS_DATA_OFFSET bytes in the beginning for special (hidden) VMCS fields
|
||||
for (unsigned type=0; type<16; type++) {
|
||||
for (unsigned field=0; field < VMX_HIGHEST_VMCS_ENCODING; field++) {
|
||||
Bit32u encoding = vmcs_encoding(type, field);
|
||||
if (vmcs_map[type][field] != 0xffffffff) {
|
||||
BX_PANIC(("VMCS type %d field %d (encoding = 0x%08x) is already initialized", type, field, encoding));
|
||||
}
|
||||
if (vmcs_field_supported(encoding)) {
|
||||
// allocate 64 fields (4 byte each) per type
|
||||
vmcs_map[type][field] = VMCS_DATA_OFFSET + (type*64 + field) * 4;
|
||||
if(vmcs_map[type][field] >= VMX_VMCS_AREA_SIZE) {
|
||||
BX_PANIC(("VMCS type %d field %d (encoding = 0x%08x) is out of VMCS boundaries", type, field, encoding));
|
||||
}
|
||||
BX_DEBUG(("VMCS field 0x%08x located at 0x%08x", encoding, vmcs_map[type][field]));
|
||||
}
|
||||
else {
|
||||
BX_DEBUG(("VMCS field 0x%08x is not supported", encoding));
|
||||
// allocate 64 fields (4 byte each) per type (even more than 48 which is required now)
|
||||
vmcs_map[type][field] = VMCS_DATA_OFFSET + (type*64 + field) * 4;
|
||||
if(vmcs_map[type][field] >= VMX_VMCS_AREA_SIZE) {
|
||||
BX_PANIC(("VMCS type %d field %d (encoding = 0x%08x) is out of VMCS boundaries", type, field, encoding));
|
||||
}
|
||||
BX_DEBUG(("VMCS field 0x%08x located at 0x%08x", encoding, vmcs_map[type][field]));
|
||||
}
|
||||
}
|
||||
#else
|
||||
@ -73,12 +73,37 @@ void BX_CPU_C::init_VMCS(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#define VMCS_ENCODING_RESERVED_BITS (0xffff9000)
|
||||
|
||||
unsigned vmcs_field_offset(Bit32u encoding)
|
||||
void VMCS_Mapping::clear()
|
||||
{
|
||||
if (encoding & VMCS_ENCODING_RESERVED_BITS)
|
||||
for (unsigned type=0; type<16; type++) {
|
||||
for (unsigned field=0; field < VMX_HIGHEST_VMCS_ENCODING; field++) {
|
||||
vmcs_map[type][field] = 0xffffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VMCS_Mapping::clear_mapping(Bit32u encoding)
|
||||
{
|
||||
if (is_reserved(encoding))
|
||||
return;
|
||||
|
||||
unsigned field = VMCS_FIELD(encoding);
|
||||
if (field >= VMX_HIGHEST_VMCS_ENCODING)
|
||||
return;
|
||||
|
||||
vmcs_map[VMCS_FIELD_INDEX(encoding)][field] = 0xffffffff;
|
||||
}
|
||||
|
||||
unsigned VMCS_Mapping::vmcs_field_offset(Bit32u encoding) const
|
||||
{
|
||||
if (is_reserved(encoding)) {
|
||||
switch(encoding) {
|
||||
case VMCS_REVISION_ID_FIELD_ENCODING: return VMCS_REVISION_ID_FIELD_ADDR;
|
||||
case VMCS_VMX_ABORT_FIELD_ENCODING: return VMCS_VMX_ABORT_FIELD_ADDR;
|
||||
case VMCS_LAUNCH_STATE_FIELD_ENCODING: return VMCS_LAUNCH_STATE_FIELD_ADDR;
|
||||
}
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
unsigned field = VMCS_FIELD(encoding);
|
||||
if (field >= VMX_HIGHEST_VMCS_ENCODING)
|
||||
@ -87,6 +112,31 @@ unsigned vmcs_field_offset(Bit32u encoding)
|
||||
return vmcs_map[VMCS_FIELD_INDEX(encoding)][field];
|
||||
}
|
||||
|
||||
void BX_CPU_C::init_VMCS(void)
|
||||
{
|
||||
BX_CPU_THIS_PTR vmcs_map = BX_CPU_THIS_PTR cpuid->get_vmcs();
|
||||
|
||||
init_vmx_capabilities();
|
||||
|
||||
static bx_bool vmcs_map_ready = 0;
|
||||
if (vmcs_map_ready) return;
|
||||
vmcs_map_ready = 1;
|
||||
|
||||
// disable not supported encodings
|
||||
for (unsigned type=0; type<16; type++) {
|
||||
for (unsigned field=0; field <= VMX_HIGHEST_VMCS_ENCODING; field++) {
|
||||
Bit32u encoding = vmcs_encoding(type, field);
|
||||
if (! vmcs_field_supported(encoding)) {
|
||||
BX_CPU_THIS_PTR vmcs_map->clear_mapping(encoding);
|
||||
BX_DEBUG(("VMCS field 0x%08x is not supported", encoding));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef LOG_THIS
|
||||
#define LOG_THIS BX_CPU_THIS_PTR
|
||||
|
||||
bx_bool BX_CPU_C::vmcs_field_supported(Bit32u encoding)
|
||||
{
|
||||
switch(encoding)
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
|
||||
extern unsigned vmcs_field_offset(Bit32u encoding);
|
||||
extern VMCS_Mapping vmcs_map;
|
||||
|
||||
#if BX_SUPPORT_VMX >= 2
|
||||
extern bx_bool isValidMSR_PAT(Bit64u pat_msr);
|
||||
@ -136,7 +136,7 @@ Bit16u BX_CPP_AttrRegparmN(1) BX_CPU_C::VMread16(unsigned encoding)
|
||||
{
|
||||
Bit16u field;
|
||||
|
||||
unsigned offset = vmcs_field_offset(encoding);
|
||||
unsigned offset = BX_CPU_THIS_PTR vmcs_map->vmcs_field_offset(encoding);
|
||||
if(offset >= VMX_VMCS_AREA_SIZE)
|
||||
BX_PANIC(("VMread16: can't access encoding 0x%08x, offset=0x%x", encoding, offset));
|
||||
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcsptr + offset;
|
||||
@ -159,7 +159,7 @@ Bit16u BX_CPP_AttrRegparmN(1) BX_CPU_C::VMread16(unsigned encoding)
|
||||
// write 16-bit value into VMCS 16-bit field
|
||||
void BX_CPP_AttrRegparmN(2) BX_CPU_C::VMwrite16(unsigned encoding, Bit16u val_16)
|
||||
{
|
||||
unsigned offset = vmcs_field_offset(encoding);
|
||||
unsigned offset = BX_CPU_THIS_PTR vmcs_map->vmcs_field_offset(encoding);
|
||||
if(offset >= VMX_VMCS_AREA_SIZE)
|
||||
BX_PANIC(("VMwrite16: can't access encoding 0x%08x, offset=0x%x", encoding, offset));
|
||||
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcsptr + offset;
|
||||
@ -182,7 +182,7 @@ Bit32u BX_CPP_AttrRegparmN(1) BX_CPU_C::VMread32(unsigned encoding)
|
||||
{
|
||||
Bit32u field;
|
||||
|
||||
unsigned offset = vmcs_field_offset(encoding);
|
||||
unsigned offset = BX_CPU_THIS_PTR vmcs_map->vmcs_field_offset(encoding);
|
||||
if(offset >= VMX_VMCS_AREA_SIZE)
|
||||
BX_PANIC(("VMread32: can't access encoding 0x%08x, offset=0x%x", encoding, offset));
|
||||
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcsptr + offset;
|
||||
@ -203,7 +203,7 @@ Bit32u BX_CPP_AttrRegparmN(1) BX_CPU_C::VMread32(unsigned encoding)
|
||||
// write 32-bit value into VMCS field
|
||||
void BX_CPP_AttrRegparmN(2) BX_CPU_C::VMwrite32(unsigned encoding, Bit32u val_32)
|
||||
{
|
||||
unsigned offset = vmcs_field_offset(encoding);
|
||||
unsigned offset = BX_CPU_THIS_PTR vmcs_map->vmcs_field_offset(encoding);
|
||||
if(offset >= VMX_VMCS_AREA_SIZE)
|
||||
BX_PANIC(("VMwrite32: can't access encoding 0x%08x, offset=0x%x", encoding, offset));
|
||||
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcsptr + offset;
|
||||
@ -226,7 +226,7 @@ Bit64u BX_CPP_AttrRegparmN(1) BX_CPU_C::VMread64(unsigned encoding)
|
||||
|
||||
Bit64u field;
|
||||
|
||||
unsigned offset = vmcs_field_offset(encoding);
|
||||
unsigned offset = BX_CPU_THIS_PTR vmcs_map->vmcs_field_offset(encoding);
|
||||
if(offset >= VMX_VMCS_AREA_SIZE)
|
||||
BX_PANIC(("VMread64: can't access encoding 0x%08x, offset=0x%x", encoding, offset));
|
||||
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcsptr + offset;
|
||||
@ -249,7 +249,7 @@ void BX_CPP_AttrRegparmN(2) BX_CPU_C::VMwrite64(unsigned encoding, Bit64u val_64
|
||||
{
|
||||
BX_ASSERT(!IS_VMCS_FIELD_HI(encoding));
|
||||
|
||||
unsigned offset = vmcs_field_offset(encoding);
|
||||
unsigned offset = BX_CPU_THIS_PTR vmcs_map->vmcs_field_offset(encoding);
|
||||
if(offset >= VMX_VMCS_AREA_SIZE)
|
||||
BX_PANIC(("VMwrite64: can't access encoding 0x%08x, offset=0x%x", encoding, offset));
|
||||
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcsptr + offset;
|
||||
@ -296,7 +296,7 @@ void BX_CPP_AttrRegparmN(2) BX_CPU_C::VMwrite_natural(unsigned encoding, bx_addr
|
||||
|
||||
Bit16u BX_CPP_AttrRegparmN(1) BX_CPU_C::VMread16_Shadow(unsigned encoding)
|
||||
{
|
||||
unsigned offset = vmcs_field_offset(encoding);
|
||||
unsigned offset = BX_CPU_THIS_PTR vmcs_map->vmcs_field_offset(encoding);
|
||||
if(offset >= VMX_VMCS_AREA_SIZE)
|
||||
BX_PANIC(("VMread16_Shadow: can't access encoding 0x%08x, offset=0x%x", encoding, offset));
|
||||
|
||||
@ -313,7 +313,7 @@ Bit16u BX_CPP_AttrRegparmN(1) BX_CPU_C::VMread16_Shadow(unsigned encoding)
|
||||
// write 16-bit value into shadow VMCS 16-bit field
|
||||
void BX_CPP_AttrRegparmN(2) BX_CPU_C::VMwrite16_Shadow(unsigned encoding, Bit16u val_16)
|
||||
{
|
||||
unsigned offset = vmcs_field_offset(encoding);
|
||||
unsigned offset = BX_CPU_THIS_PTR vmcs_map->vmcs_field_offset(encoding);
|
||||
if(offset >= VMX_VMCS_AREA_SIZE)
|
||||
BX_PANIC(("VMwrite16_Shadow: can't access encoding 0x%08x, offset=0x%x", encoding, offset));
|
||||
|
||||
@ -326,7 +326,7 @@ void BX_CPP_AttrRegparmN(2) BX_CPU_C::VMwrite16_Shadow(unsigned encoding, Bit16u
|
||||
|
||||
Bit32u BX_CPP_AttrRegparmN(1) BX_CPU_C::VMread32_Shadow(unsigned encoding)
|
||||
{
|
||||
unsigned offset = vmcs_field_offset(encoding);
|
||||
unsigned offset = BX_CPU_THIS_PTR vmcs_map->vmcs_field_offset(encoding);
|
||||
if(offset >= VMX_VMCS_AREA_SIZE)
|
||||
BX_PANIC(("VMread32_Shadow: can't access encoding 0x%08x, offset=0x%x", encoding, offset));
|
||||
|
||||
@ -341,7 +341,7 @@ Bit32u BX_CPP_AttrRegparmN(1) BX_CPU_C::VMread32_Shadow(unsigned encoding)
|
||||
// write 32-bit value into shadow VMCS field
|
||||
void BX_CPP_AttrRegparmN(2) BX_CPU_C::VMwrite32_Shadow(unsigned encoding, Bit32u val_32)
|
||||
{
|
||||
unsigned offset = vmcs_field_offset(encoding);
|
||||
unsigned offset = BX_CPU_THIS_PTR vmcs_map->vmcs_field_offset(encoding);
|
||||
if(offset >= VMX_VMCS_AREA_SIZE)
|
||||
BX_PANIC(("VMwrite32_Shadow: can't access encoding 0x%08x, offset=0x%x", encoding, offset));
|
||||
|
||||
@ -354,7 +354,7 @@ Bit64u BX_CPP_AttrRegparmN(1) BX_CPU_C::VMread64_Shadow(unsigned encoding)
|
||||
{
|
||||
BX_ASSERT(!IS_VMCS_FIELD_HI(encoding));
|
||||
|
||||
unsigned offset = vmcs_field_offset(encoding);
|
||||
unsigned offset = BX_CPU_THIS_PTR vmcs_map->vmcs_field_offset(encoding);
|
||||
if(offset >= VMX_VMCS_AREA_SIZE)
|
||||
BX_PANIC(("VMread64_Shadow: can't access encoding 0x%08x, offset=0x%x", encoding, offset));
|
||||
|
||||
@ -371,7 +371,7 @@ void BX_CPP_AttrRegparmN(2) BX_CPU_C::VMwrite64_Shadow(unsigned encoding, Bit64u
|
||||
{
|
||||
BX_ASSERT(!IS_VMCS_FIELD_HI(encoding));
|
||||
|
||||
unsigned offset = vmcs_field_offset(encoding);
|
||||
unsigned offset = BX_CPU_THIS_PTR vmcs_map->vmcs_field_offset(encoding);
|
||||
if(offset >= VMX_VMCS_AREA_SIZE)
|
||||
BX_PANIC(("VMwrite64_Shadow: can't access encoding 0x%08x, offset=0x%x", encoding, offset));
|
||||
|
||||
@ -401,10 +401,7 @@ BX_CPP_INLINE void BX_CPU_C::VMfail(Bit32u error_code)
|
||||
|
||||
void BX_CPU_C::VMabort(VMX_vmabort_code error_code)
|
||||
{
|
||||
Bit32u abort = error_code;
|
||||
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcsptr + VMCS_VMX_ABORT_FIELD_ADDR;
|
||||
access_write_physical(pAddr, 4, &abort);
|
||||
BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 4, MEMTYPE(BX_CPU_THIS_PTR vmcs_memtype), BX_WRITE, BX_VMCS_ACCESS, (Bit8u*)(&abort));
|
||||
VMwrite32(VMCS_VMX_ABORT_FIELD_ENCODING, (Bit32u) error_code);
|
||||
|
||||
#if BX_SUPPORT_VMX >= 2
|
||||
// Deactivate VMX preemtion timer
|
||||
@ -1677,9 +1674,9 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification)
|
||||
}
|
||||
revision &= ~BX_VMCS_SHADOW_BIT_MASK;
|
||||
}
|
||||
if (revision != BX_CPU_THIS_PTR cpuid->get_vmcs_revision_id()) {
|
||||
if (revision != BX_CPU_THIS_PTR vmcs_map->get_vmcs_revision_id()) {
|
||||
*qualification = (Bit64u) VMENTER_ERR_GUEST_STATE_LINK_POINTER;
|
||||
BX_ERROR(("VMFAIL: VMCS link pointer incorrect revision ID %d != %d", revision, BX_CPU_THIS_PTR cpuid->get_vmcs_revision_id()));
|
||||
BX_ERROR(("VMFAIL: VMCS link pointer incorrect revision ID %d != %d", revision, BX_CPU_THIS_PTR vmcs_map->get_vmcs_revision_id()));
|
||||
return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE;
|
||||
}
|
||||
|
||||
@ -2580,8 +2577,8 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMXON(bxInstruction_c *i)
|
||||
|
||||
// not allowed to be shadow VMCS
|
||||
Bit32u revision = VMXReadRevisionID((bx_phy_address) pAddr);
|
||||
if (revision != BX_CPU_THIS_PTR cpuid->get_vmcs_revision_id()) {
|
||||
BX_ERROR(("VMXON: not expected (%d != %d) VMCS revision id !", revision, BX_CPU_THIS_PTR cpuid->get_vmcs_revision_id()));
|
||||
if (revision != BX_CPU_THIS_PTR vmcs_map->get_vmcs_revision_id()) {
|
||||
BX_ERROR(("VMXON: not expected (%d != %d) VMCS revision id !", revision, BX_CPU_THIS_PTR vmcs_map->get_vmcs_revision_id()));
|
||||
VMfailInvalid();
|
||||
BX_NEXT_INSTR(i);
|
||||
}
|
||||
@ -2687,11 +2684,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMCALL(bxInstruction_c *i)
|
||||
BX_NEXT_TRACE(i);
|
||||
}
|
||||
|
||||
Bit32u launch_state;
|
||||
access_read_physical(BX_CPU_THIS_PTR vmcsptr + VMCS_LAUNCH_STATE_FIELD_ADDR, 4, &launch_state);
|
||||
BX_NOTIFY_PHY_MEMORY_ACCESS(BX_CPU_THIS_PTR vmcsptr + VMCS_LAUNCH_STATE_FIELD_ADDR, 4,
|
||||
MEMTYPE(BX_CPU_THIS_PTR vmcs_memtype), BX_READ, BX_VMCS_ACCESS, (Bit8u*)(&launch_state));
|
||||
|
||||
Bit32u launch_state = VMread32(VMCS_LAUNCH_STATE_FIELD_ENCODING);
|
||||
if (launch_state != VMCS_STATE_CLEAR) {
|
||||
BX_ERROR(("VMFAIL: VMCALL with launched VMCS"));
|
||||
VMfail(VMXERR_VMCALL_NON_CLEAR_VMCS);
|
||||
@ -2763,10 +2756,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMLAUNCH(bxInstruction_c *i)
|
||||
BX_NEXT_TRACE(i);
|
||||
}
|
||||
|
||||
Bit32u launch_state;
|
||||
access_read_physical(BX_CPU_THIS_PTR vmcsptr + VMCS_LAUNCH_STATE_FIELD_ADDR, 4, &launch_state);
|
||||
BX_NOTIFY_PHY_MEMORY_ACCESS(BX_CPU_THIS_PTR vmcsptr + VMCS_LAUNCH_STATE_FIELD_ADDR, 4,
|
||||
MEMTYPE(BX_CPU_THIS_PTR vmcs_memtype), BX_READ, BX_VMCS_ACCESS, (Bit8u*)(&launch_state));
|
||||
Bit32u launch_state = VMread32(VMCS_LAUNCH_STATE_FIELD_ENCODING);
|
||||
|
||||
if (vmlaunch) {
|
||||
if (launch_state != VMCS_STATE_CLEAR) {
|
||||
@ -2826,12 +2816,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMLAUNCH(bxInstruction_c *i)
|
||||
// STEP 6: Update VMCS 'launched' state
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
if (vmlaunch) {
|
||||
launch_state = VMCS_STATE_LAUNCHED;
|
||||
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcsptr + VMCS_LAUNCH_STATE_FIELD_ADDR;
|
||||
access_write_physical(pAddr, 4, &launch_state);
|
||||
BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 4, MEMTYPE(BX_CPU_THIS_PTR vmcs_memtype), BX_WRITE, BX_VMCS_ACCESS, (Bit8u*)(&launch_state));
|
||||
}
|
||||
if (vmlaunch) VMwrite32(VMCS_LAUNCH_STATE_FIELD_ENCODING, VMCS_STATE_LAUNCHED);
|
||||
|
||||
/*
|
||||
Check settings of VMX controls and host-state area;
|
||||
@ -2952,8 +2937,8 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMPTRLD(bxInstruction_c *i)
|
||||
if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_VMCS_SHADOWING))
|
||||
revision &= ~BX_VMCS_SHADOW_BIT_MASK; // allowed to be shadow VMCS
|
||||
|
||||
if (revision != BX_CPU_THIS_PTR cpuid->get_vmcs_revision_id()) {
|
||||
BX_ERROR(("VMPTRLD: not expected (%d != %d) VMCS revision id !", revision, BX_CPU_THIS_PTR cpuid->get_vmcs_revision_id()));
|
||||
if (revision != BX_CPU_THIS_PTR vmcs_map->get_vmcs_revision_id()) {
|
||||
BX_ERROR(("VMPTRLD: not expected (%d != %d) VMCS revision id !", revision, BX_CPU_THIS_PTR vmcs_map->get_vmcs_revision_id()));
|
||||
VMfail(VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID);
|
||||
}
|
||||
else {
|
||||
@ -3135,7 +3120,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMREAD_EdGd(bxInstruction_c *i)
|
||||
|
||||
unsigned encoding = BX_READ_32BIT_REG(i->src());
|
||||
|
||||
if (vmcs_field_offset(encoding) == 0xffffffff) {
|
||||
if (! BX_CPU_THIS_PTR vmcs_map->is_valid(encoding)) {
|
||||
BX_ERROR(("VMREAD: not supported field 0x%08x", encoding));
|
||||
VMfail(VMXERR_UNSUPPORTED_VMCS_COMPONENT_ACCESS);
|
||||
BX_NEXT_INSTR(i);
|
||||
@ -3200,7 +3185,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMREAD_EqGq(bxInstruction_c *i)
|
||||
}
|
||||
unsigned encoding = BX_READ_32BIT_REG(i->src());
|
||||
|
||||
if (vmcs_field_offset(encoding) == 0xffffffff) {
|
||||
if (! BX_CPU_THIS_PTR vmcs_map->is_valid(encoding)) {
|
||||
BX_ERROR(("VMREAD: not supported field 0x%08x", encoding));
|
||||
VMfail(VMXERR_UNSUPPORTED_VMCS_COMPONENT_ACCESS);
|
||||
BX_NEXT_INSTR(i);
|
||||
@ -3270,7 +3255,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMWRITE_GdEd(bxInstruction_c *i)
|
||||
|
||||
Bit32u encoding = BX_READ_32BIT_REG(i->dst());
|
||||
|
||||
if (vmcs_field_offset(encoding) == 0xffffffff) {
|
||||
if (! BX_CPU_THIS_PTR vmcs_map->is_valid(encoding)) {
|
||||
BX_ERROR(("VMWRITE: not supported field 0x%08x", encoding));
|
||||
VMfail(VMXERR_UNSUPPORTED_VMCS_COMPONENT_ACCESS);
|
||||
BX_NEXT_INSTR(i);
|
||||
@ -3346,7 +3331,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMWRITE_GqEq(bxInstruction_c *i)
|
||||
|
||||
Bit32u encoding = BX_READ_32BIT_REG(i->dst());
|
||||
|
||||
if (vmcs_field_offset(encoding) == 0xffffffff) {
|
||||
if (! BX_CPU_THIS_PTR vmcs_map->is_valid(encoding)) {
|
||||
BX_ERROR(("VMWRITE: not supported field 0x%08x", encoding));
|
||||
VMfail(VMXERR_UNSUPPORTED_VMCS_COMPONENT_ACCESS);
|
||||
BX_NEXT_INSTR(i);
|
||||
|
@ -27,7 +27,7 @@
|
||||
#define VMX_VMCS_AREA_SIZE 4096
|
||||
|
||||
// VMCS pointer is always 64-bit variable
|
||||
#define BX_INVALID_VMCSPTR BX_CONST64(0xFFFFFFFFFFFFFFFF)
|
||||
const Bit64u BX_INVALID_VMCSPTR = BX_CONST64(0xFFFFFFFFFFFFFFFF);
|
||||
|
||||
// bits supported in IA32_FEATURE_CONTROL MSR
|
||||
#define BX_IA32_FEATURE_CONTROL_LOCK_BIT 0x1
|
||||
@ -450,15 +450,52 @@ enum VMFunctions {
|
||||
#define VMCS_FIELD_INDEX(encoding) \
|
||||
((VMCS_FIELD_WIDTH(encoding) << 2) + VMCS_FIELD_TYPE(encoding))
|
||||
|
||||
#define VMCS_ENCODING_RESERVED_BITS (0xffff9000)
|
||||
|
||||
// =============
|
||||
// VMCS layout
|
||||
// =============
|
||||
|
||||
#define BX_VMX_VMCS_REVISION_ID 0x2B /* better to be unique bochs VMCS revision id */
|
||||
|
||||
struct VMCS_Mapping {
|
||||
private:
|
||||
Bit32u revision_id;
|
||||
|
||||
// assume 16 VMCS field types (encoded with 4 bits: 2 bits for VMCS_FIELD_TYPE and 2 bits for VMCS_FIELD_WIDTH)
|
||||
unsigned vmcs_map[16][VMX_HIGHEST_VMCS_ENCODING];
|
||||
|
||||
void init_generic_mapping();
|
||||
|
||||
public:
|
||||
VMCS_Mapping(Bit32u revision_id = BX_VMX_VMCS_REVISION_ID); // default VMCS mapping
|
||||
VMCS_Mapping(Bit32u revision_id, const char *filename);
|
||||
|
||||
void clear();
|
||||
void clear_mapping(Bit32u encoding);
|
||||
|
||||
void set_vmcs_revision_id(Bit32u revision) { revision_id = revision; }
|
||||
Bit32u get_vmcs_revision_id() const { return revision_id; }
|
||||
|
||||
unsigned vmcs_field_offset(Bit32u encoding) const;
|
||||
|
||||
bx_bool is_reserved(Bit32u encoding) const {
|
||||
return (encoding & VMCS_ENCODING_RESERVED_BITS) != 0;
|
||||
}
|
||||
|
||||
bx_bool is_valid(Bit32u encoding) const {
|
||||
return ! is_reserved(encoding) && (vmcs_field_offset(encoding) != 0xffffffff);
|
||||
}
|
||||
};
|
||||
|
||||
#define VMCS_LAUNCH_STATE_FIELD_ENCODING (0xfffffffe)
|
||||
#define VMCS_VMX_ABORT_FIELD_ENCODING (0xfffffffc)
|
||||
#define VMCS_REVISION_ID_FIELD_ENCODING (0xfffffffa)
|
||||
|
||||
#define VMCS_REVISION_ID_FIELD_ADDR (0x0000)
|
||||
#define VMCS_VMX_ABORT_FIELD_ADDR (0x0004)
|
||||
#define VMCS_LAUNCH_STATE_FIELD_ADDR (0x0008)
|
||||
|
||||
// invent Bochs CPU VMCS layout - allocate 64 fields of each type
|
||||
#define VMCS_DATA_OFFSET (0x0010)
|
||||
|
||||
#if ((VMCS_DATA_OFFSET + 4*(64*15 + VMX_HIGHEST_VMCS_ENCODING)) > VMX_VMCS_AREA_SIZE)
|
||||
@ -819,7 +856,7 @@ typedef struct bx_VMCS
|
||||
// 56:63 reserved, must be zero
|
||||
//
|
||||
|
||||
#define VMX_MSR_VMX_BASIC_LO (BX_CPU_THIS_PTR cpuid->get_vmcs_revision_id())
|
||||
#define VMX_MSR_VMX_BASIC_LO (BX_CPU_THIS_PTR vmcs_map->get_vmcs_revision_id())
|
||||
#define VMX_MSR_VMX_BASIC_HI \
|
||||
(VMX_VMCS_AREA_SIZE | ((!is_cpu_extension_supported(BX_ISA_LONG_MODE)) << 16) | \
|
||||
(BX_MEMTYPE_WB << 18) | (1<<22)) | ((BX_SUPPORT_VMX >= 2) ? (1<<23) : 0)
|
||||
|
Loading…
x
Reference in New Issue
Block a user