Skip to content
This repository has been archived by the owner on Jan 28, 2023. It is now read-only.

Commit

Permalink
Merge pull request #204 from nevilad/win10_support
Browse files Browse the repository at this point in the history
Windows 10 guest support
  • Loading branch information
wcwang authored Mar 6, 2020
2 parents 7faf8ef + 5c4b6cb commit 7f3aaab
Show file tree
Hide file tree
Showing 11 changed files with 66 additions and 13 deletions.
2 changes: 1 addition & 1 deletion core/include/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
// a non-POD structure.
// We have to use 1 instead of 0 so the compiler doesn't generate an error.
#define offsetof(type, mem) \
((uint32)((char *)&((const type *)1)->mem - (char *)((const type *)1)))
((uint32_t)((char *)&((const type *)1)->mem - (char *)((const type *)1)))

#define ALWAYS_INLINE __attribute__ ((always_inline))
#define NOINLINE __attribute__ ((noinline))
Expand Down
1 change: 1 addition & 0 deletions core/include/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ struct hstate {
uint64_t dr7;
// CR0
bool cr0_ts;
uint64_t _pat;
};

struct hstate_compare {
Expand Down
1 change: 1 addition & 0 deletions core/include/hax_core_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ int vcpu_put_fpu(struct vcpu_t *vcpu, struct fx_layout *fl);
int vcpu_get_fpu(struct vcpu_t *vcpu, struct fx_layout *fl);
int vcpu_set_regs(struct vcpu_t *vcpu, struct vcpu_state_t *vs);
int vcpu_get_regs(struct vcpu_t *vcpu, struct vcpu_state_t *vs);
int vcpu_get_state_size(struct vcpu_t *vcpu);
void vcpu_debug(struct vcpu_t *vcpu, struct hax_debug_t *debug);

void * get_vcpu_host(struct vcpu_t *vcpu);
Expand Down
2 changes: 2 additions & 0 deletions core/include/vcpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ struct vcpu_t {
struct vm_t *vm;
struct hax_mmu *mmu;
struct vcpu_state_t *state;
uint64_t _cr8;
struct hax_tunnel *tunnel;
uint8_t *io_buf;
struct hax_page *vmcs_page;
Expand Down Expand Up @@ -258,6 +259,7 @@ int vcpu_get_fpu(struct vcpu_t *vcpu, struct fx_layout *fl);
int vcpu_put_fpu(struct vcpu_t *vcpu, struct fx_layout *fl);
int vcpu_get_msr(struct vcpu_t *vcpu, uint64_t entry, uint64_t *val);
int vcpu_put_msr(struct vcpu_t *vcpu, uint64_t entry, uint64_t val);
int vcpu_get_state_size(struct vcpu_t *vcpu);
void vcpu_debug(struct vcpu_t *vcpu, struct hax_debug_t *debug);

/* The declaration for OS wrapper code */
Expand Down
1 change: 1 addition & 0 deletions core/include/vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ struct vm_t {
uint64_t flags;
#define VM_FEATURES_FASTMMIO_BASIC 0x1
#define VM_FEATURES_FASTMMIO_EXTRA 0x2
#define VM_FEATURES_CR8 0x4
uint32_t features;
int vm_id;
#define VPID_SEED_BITS 64
Expand Down
53 changes: 47 additions & 6 deletions core/vcpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1227,6 +1227,9 @@ void vcpu_save_host_state(struct vcpu_t *vcpu)
vmwrite(vcpu, HOST_EFER, hstate->_efer);
}

hstate->_pat = ia32_rdmsr(IA32_CR_PAT);
vmwrite(vcpu, HOST_PAT, hstate->_pat);

#ifdef HAX_ARCH_X86_64
vmwrite(vcpu, HOST_CS_SELECTOR, get_kernel_cs());
#else
Expand Down Expand Up @@ -1393,15 +1396,15 @@ static void fill_common_vmcs(struct vcpu_t *vcpu)

#ifdef HAX_ARCH_X86_64
exit_ctls = EXIT_CONTROL_HOST_ADDR_SPACE_SIZE | EXIT_CONTROL_LOAD_EFER |
EXIT_CONTROL_SAVE_DEBUG_CONTROLS;
EXIT_CONTROL_SAVE_DEBUG_CONTROLS | EXIT_CONTROL_LOAD_PAT;
#endif

#ifdef HAX_ARCH_X86_32
if (is_compatible()) {
exit_ctls = EXIT_CONTROL_HOST_ADDR_SPACE_SIZE | EXIT_CONTROL_LOAD_EFER |
EXIT_CONTROL_SAVE_DEBUG_CONTROLS;
EXIT_CONTROL_SAVE_DEBUG_CONTROLS | EXIT_CONTROL_LOAD_PAT;
} else {
exit_ctls = EXIT_CONTROL_SAVE_DEBUG_CONTROLS;
exit_ctls = EXIT_CONTROL_SAVE_DEBUG_CONTROLS | EXIT_CONTROL_LOAD_PAT;
}
#endif

Expand Down Expand Up @@ -1473,6 +1476,9 @@ static void fill_common_vmcs(struct vcpu_t *vcpu)
vmwrite(vcpu, HOST_EFER, ia32_rdmsr(IA32_EFER));
}

vmwrite(vcpu, HOST_PAT, ia32_rdmsr(IA32_CR_PAT));
vmwrite(vcpu, GUEST_PAT, vcpu->cr_pat);

WRITE_CONTROLS(vcpu, VMX_ENTRY_CONTROLS, entry_ctls);

vmwrite(vcpu, VMX_PAGE_FAULT_ERROR_CODE_MASK, 0);
Expand Down Expand Up @@ -2040,6 +2046,8 @@ static void vmwrite_cr(struct vcpu_t *vcpu)
entry_ctls &= ~ENTRY_CONTROL_LOAD_EFER;
}

entry_ctls |= ENTRY_CONTROL_LOAD_PAT;

if (pcpu_ctls != vmx(vcpu, pcpu_ctls)) {
vmx(vcpu, pcpu_ctls) = pcpu_ctls;
vcpu->pcpu_ctls_dirty = 1;
Expand Down Expand Up @@ -2530,7 +2538,7 @@ static void handle_cpuid_virtual(struct vcpu_t *vcpu, uint32_t a, uint32_t c)
uint8_t physical_address_size;

static uint32_t cpuid_1_features_edx =
// pat is disabled!
FEATURE(PAT) |
FEATURE(FPU) |
FEATURE(VME) |
FEATURE(DE) |
Expand Down Expand Up @@ -2660,10 +2668,13 @@ static void handle_cpuid_virtual(struct vcpu_t *vcpu, uint32_t a, uint32_t c)
state->_edx = 0x0c040844;
return;
}
case 3: // Reserved
case 3: { // Reserved
state->_eax = state->_ebx = state->_ecx = state->_edx = 0;
return;
}
case 4: { // Deterministic Cache Parameters
// [31:26] cores per package - 1
state->_eax = state->_ebx = state->_ecx = state->_edx = 0;
// Use host cache values.
return;
}
case 5: // MONITOR/MWAIT
Expand Down Expand Up @@ -3560,6 +3571,15 @@ static int misc_msr_write(struct vcpu_t *vcpu, uint32_t msr, uint64_t val)
return 1;
}

static inline bool is_pat_valid(uint64_t val)
{
if (val & 0xF8F8F8F8F8F8F8F8)
return false;

// 0, 1, 4, 5, 6, 7 are valid values.
return (val | ((val & 0x0202020202020202) << 1)) == val;
}

static int handle_msr_write(struct vcpu_t *vcpu, uint32_t msr, uint64_t val,
bool by_host)
{
Expand Down Expand Up @@ -3718,7 +3738,15 @@ static int handle_msr_write(struct vcpu_t *vcpu, uint32_t msr, uint64_t val,
break;
}
case IA32_CR_PAT: {
// Attempting to write an undefined memory type encoding into the
// PAT causes a general-protection (#GP) exception to be generated
if (!is_pat_valid(val)) {
r = 1;
break;
}

vcpu->cr_pat = val;
vmwrite(vcpu, GUEST_PAT, vcpu->cr_pat);
break;
}
case IA32_MTRR_DEF_TYPE: {
Expand Down Expand Up @@ -3912,6 +3940,13 @@ static int _copy_desc(segment_desc_t *old, segment_desc_t *new)
return flags;
}

int vcpu_get_state_size(struct vcpu_t *vcpu)
{
if (vcpu->vm->features & VM_FEATURES_CR8)
return sizeof(struct vcpu_state_t);
return offsetof(struct vcpu_state_t, _cr8);
}

int vcpu_get_regs(struct vcpu_t *vcpu, struct vcpu_state_t *ustate)
{
struct vcpu_state_t *state = vcpu->state;
Expand Down Expand Up @@ -3947,6 +3982,9 @@ int vcpu_get_regs(struct vcpu_t *vcpu, struct vcpu_state_t *ustate)
_copy_desc(&state->_gdt, &ustate->_gdt);
_copy_desc(&state->_idt, &ustate->_idt);

if (vcpu->vm->features & VM_FEATURES_CR8)
ustate->_cr8 = state->_cr8;

return 0;
}

Expand Down Expand Up @@ -4072,6 +4110,9 @@ int vcpu_set_regs(struct vcpu_t *vcpu, struct vcpu_state_t *ustate)
VMWRITE_DESC(vcpu, IDTR, state->_idt);
}

if (vcpu->vm->features & VM_FEATURES_CR8)
state->_cr8 = ustate->_cr8;

if ((vmcs_err = put_vmcs(vcpu, &flags))) {
vcpu_set_panic(vcpu);
hax_log(HAX_LOGPANIC, "put_vmcs failed on vcpu_set_regs: %x\n",
Expand Down
3 changes: 3 additions & 0 deletions core/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ int hax_vm_set_qemuversion(struct vm_t *vm, struct hax_qemu_version *ver)
vm->features |= VM_FEATURES_FASTMMIO_BASIC;
if (ver->cur_version >= 0x4) {
vm->features |= VM_FEATURES_FASTMMIO_EXTRA;
if (ver->cur_version >= 0x5) {
vm->features |= VM_FEATURES_CR8;
}
}
}
return 0;
Expand Down
2 changes: 1 addition & 1 deletion include/hax.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
// declaration
struct vcpu_t;

#define HAX_CUR_VERSION 0x0004
#define HAX_CUR_VERSION 0x0005
#define HAX_COMPAT_VERSION 0x0001

/* TBD */
Expand Down
2 changes: 2 additions & 0 deletions include/vcpu_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ struct vcpu_state_t {
uint32_t _activity_state;
uint32_t pad;
interruptibility_state_t _interruptibility_state;

uint64_t _cr8;
} PACKED;

void dump(void);
Expand Down
6 changes: 4 additions & 2 deletions platforms/linux/components.c
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,8 @@ static long hax_vcpu_ioctl(struct file *filp, unsigned int cmd,
}
case HAX_VCPU_SET_REGS: {
struct vcpu_state_t vc_state;
if (copy_from_user(&vc_state, argp, sizeof(vc_state))) {
int size = vcpu_get_state_size(cvcpu);
if (copy_from_user(&vc_state, argp, size)) {
ret = -EFAULT;
break;
}
Expand All @@ -420,8 +421,9 @@ static long hax_vcpu_ioctl(struct file *filp, unsigned int cmd,
}
case HAX_VCPU_GET_REGS: {
struct vcpu_state_t vc_state;
int size = vcpu_get_state_size(cvcpu);
ret = vcpu_get_regs(cvcpu, &vc_state);
if (copy_to_user(argp, &vc_state, sizeof(vc_state))) {
if (copy_to_user(argp, &vc_state, size)) {
ret = -EFAULT;
break;
}
Expand Down
6 changes: 3 additions & 3 deletions platforms/windows/hax_entry.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ NTSTATUS HaxVcpuControl(PDEVICE_OBJECT DeviceObject,
}
case HAX_VCPU_SET_REGS: {
struct vcpu_state_t *vc_state;
if(inBufLength < sizeof(struct vcpu_state_t)) {
if (inBufLength < vcpu_get_state_size(cvcpu)) {
ret = STATUS_INVALID_PARAMETER;
goto done;
}
Expand All @@ -398,15 +398,15 @@ NTSTATUS HaxVcpuControl(PDEVICE_OBJECT DeviceObject,
}
case HAX_VCPU_GET_REGS: {
struct vcpu_state_t *vc_state;
if(outBufLength < sizeof(struct vcpu_state_t)) {
infret = vcpu_get_state_size(cvcpu);
if (outBufLength < infret) {
ret = STATUS_INVALID_PARAMETER;
goto done;

}
vc_state = (struct vcpu_state_t *)outBuf;
// vcpu_get_regs() cannot fail
vcpu_get_regs(cvcpu, vc_state);
infret = sizeof(struct vcpu_state_t);
break;
}
case HAX_VCPU_IOCTL_INTERRUPT: {
Expand Down

0 comments on commit 7f3aaab

Please sign in to comment.