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

Windows10 guest support #204

Merged
merged 3 commits into from
Mar 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you think pat_msr is better?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, there is already _efer named in the same way in the same struct. There are other PATs - in vcpu it is called cr_pat and in hstate_compare it is called pat_msr. It helps to distinct them by names. If it is necessary to use common names, it should be done as a standalone feature for the entire code.

};

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 @@ -173,6 +173,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 @@ -262,6 +263,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 @@ -62,6 +62,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 @@ -1229,6 +1229,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 @@ -1395,15 +1398,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 @@ -1475,6 +1478,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 @@ -2070,6 +2076,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 @@ -2575,7 +2583,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 @@ -2705,10 +2713,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 @@ -3605,6 +3616,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 @@ -3763,7 +3783,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 @@ -3964,6 +3992,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 @@ -3999,6 +4034,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 @@ -4124,6 +4162,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

// EPT2 refers to the new memory virtualization engine, which implements lazy
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