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

Commit 7f3aaab

Browse files
authored
Merge pull request #204 from nevilad/win10_support
Windows 10 guest support
2 parents 7faf8ef + 5c4b6cb commit 7f3aaab

File tree

11 files changed

+66
-13
lines changed

11 files changed

+66
-13
lines changed

core/include/compiler.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
// a non-POD structure.
4444
// We have to use 1 instead of 0 so the compiler doesn't generate an error.
4545
#define offsetof(type, mem) \
46-
((uint32)((char *)&((const type *)1)->mem - (char *)((const type *)1)))
46+
((uint32_t)((char *)&((const type *)1)->mem - (char *)((const type *)1)))
4747

4848
#define ALWAYS_INLINE __attribute__ ((always_inline))
4949
#define NOINLINE __attribute__ ((noinline))

core/include/cpu.h

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ struct hstate {
8484
uint64_t dr7;
8585
// CR0
8686
bool cr0_ts;
87+
uint64_t _pat;
8788
};
8889

8990
struct hstate_compare {

core/include/hax_core_interface.h

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ int vcpu_put_fpu(struct vcpu_t *vcpu, struct fx_layout *fl);
4545
int vcpu_get_fpu(struct vcpu_t *vcpu, struct fx_layout *fl);
4646
int vcpu_set_regs(struct vcpu_t *vcpu, struct vcpu_state_t *vs);
4747
int vcpu_get_regs(struct vcpu_t *vcpu, struct vcpu_state_t *vs);
48+
int vcpu_get_state_size(struct vcpu_t *vcpu);
4849
void vcpu_debug(struct vcpu_t *vcpu, struct hax_debug_t *debug);
4950

5051
void * get_vcpu_host(struct vcpu_t *vcpu);

core/include/vcpu.h

+2
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ struct vcpu_t {
171171
struct vm_t *vm;
172172
struct hax_mmu *mmu;
173173
struct vcpu_state_t *state;
174+
uint64_t _cr8;
174175
struct hax_tunnel *tunnel;
175176
uint8_t *io_buf;
176177
struct hax_page *vmcs_page;
@@ -258,6 +259,7 @@ int vcpu_get_fpu(struct vcpu_t *vcpu, struct fx_layout *fl);
258259
int vcpu_put_fpu(struct vcpu_t *vcpu, struct fx_layout *fl);
259260
int vcpu_get_msr(struct vcpu_t *vcpu, uint64_t entry, uint64_t *val);
260261
int vcpu_put_msr(struct vcpu_t *vcpu, uint64_t entry, uint64_t val);
262+
int vcpu_get_state_size(struct vcpu_t *vcpu);
261263
void vcpu_debug(struct vcpu_t *vcpu, struct hax_debug_t *debug);
262264

263265
/* The declaration for OS wrapper code */

core/include/vm.h

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ struct vm_t {
6060
uint64_t flags;
6161
#define VM_FEATURES_FASTMMIO_BASIC 0x1
6262
#define VM_FEATURES_FASTMMIO_EXTRA 0x2
63+
#define VM_FEATURES_CR8 0x4
6364
uint32_t features;
6465
int vm_id;
6566
#define VPID_SEED_BITS 64

core/vcpu.c

+47-6
Original file line numberDiff line numberDiff line change
@@ -1227,6 +1227,9 @@ void vcpu_save_host_state(struct vcpu_t *vcpu)
12271227
vmwrite(vcpu, HOST_EFER, hstate->_efer);
12281228
}
12291229

1230+
hstate->_pat = ia32_rdmsr(IA32_CR_PAT);
1231+
vmwrite(vcpu, HOST_PAT, hstate->_pat);
1232+
12301233
#ifdef HAX_ARCH_X86_64
12311234
vmwrite(vcpu, HOST_CS_SELECTOR, get_kernel_cs());
12321235
#else
@@ -1393,15 +1396,15 @@ static void fill_common_vmcs(struct vcpu_t *vcpu)
13931396

13941397
#ifdef HAX_ARCH_X86_64
13951398
exit_ctls = EXIT_CONTROL_HOST_ADDR_SPACE_SIZE | EXIT_CONTROL_LOAD_EFER |
1396-
EXIT_CONTROL_SAVE_DEBUG_CONTROLS;
1399+
EXIT_CONTROL_SAVE_DEBUG_CONTROLS | EXIT_CONTROL_LOAD_PAT;
13971400
#endif
13981401

13991402
#ifdef HAX_ARCH_X86_32
14001403
if (is_compatible()) {
14011404
exit_ctls = EXIT_CONTROL_HOST_ADDR_SPACE_SIZE | EXIT_CONTROL_LOAD_EFER |
1402-
EXIT_CONTROL_SAVE_DEBUG_CONTROLS;
1405+
EXIT_CONTROL_SAVE_DEBUG_CONTROLS | EXIT_CONTROL_LOAD_PAT;
14031406
} else {
1404-
exit_ctls = EXIT_CONTROL_SAVE_DEBUG_CONTROLS;
1407+
exit_ctls = EXIT_CONTROL_SAVE_DEBUG_CONTROLS | EXIT_CONTROL_LOAD_PAT;
14051408
}
14061409
#endif
14071410

@@ -1473,6 +1476,9 @@ static void fill_common_vmcs(struct vcpu_t *vcpu)
14731476
vmwrite(vcpu, HOST_EFER, ia32_rdmsr(IA32_EFER));
14741477
}
14751478

1479+
vmwrite(vcpu, HOST_PAT, ia32_rdmsr(IA32_CR_PAT));
1480+
vmwrite(vcpu, GUEST_PAT, vcpu->cr_pat);
1481+
14761482
WRITE_CONTROLS(vcpu, VMX_ENTRY_CONTROLS, entry_ctls);
14771483

14781484
vmwrite(vcpu, VMX_PAGE_FAULT_ERROR_CODE_MASK, 0);
@@ -2040,6 +2046,8 @@ static void vmwrite_cr(struct vcpu_t *vcpu)
20402046
entry_ctls &= ~ENTRY_CONTROL_LOAD_EFER;
20412047
}
20422048

2049+
entry_ctls |= ENTRY_CONTROL_LOAD_PAT;
2050+
20432051
if (pcpu_ctls != vmx(vcpu, pcpu_ctls)) {
20442052
vmx(vcpu, pcpu_ctls) = pcpu_ctls;
20452053
vcpu->pcpu_ctls_dirty = 1;
@@ -2530,7 +2538,7 @@ static void handle_cpuid_virtual(struct vcpu_t *vcpu, uint32_t a, uint32_t c)
25302538
uint8_t physical_address_size;
25312539

25322540
static uint32_t cpuid_1_features_edx =
2533-
// pat is disabled!
2541+
FEATURE(PAT) |
25342542
FEATURE(FPU) |
25352543
FEATURE(VME) |
25362544
FEATURE(DE) |
@@ -2660,10 +2668,13 @@ static void handle_cpuid_virtual(struct vcpu_t *vcpu, uint32_t a, uint32_t c)
26602668
state->_edx = 0x0c040844;
26612669
return;
26622670
}
2663-
case 3: // Reserved
2671+
case 3: { // Reserved
2672+
state->_eax = state->_ebx = state->_ecx = state->_edx = 0;
2673+
return;
2674+
}
26642675
case 4: { // Deterministic Cache Parameters
26652676
// [31:26] cores per package - 1
2666-
state->_eax = state->_ebx = state->_ecx = state->_edx = 0;
2677+
// Use host cache values.
26672678
return;
26682679
}
26692680
case 5: // MONITOR/MWAIT
@@ -3560,6 +3571,15 @@ static int misc_msr_write(struct vcpu_t *vcpu, uint32_t msr, uint64_t val)
35603571
return 1;
35613572
}
35623573

3574+
static inline bool is_pat_valid(uint64_t val)
3575+
{
3576+
if (val & 0xF8F8F8F8F8F8F8F8)
3577+
return false;
3578+
3579+
// 0, 1, 4, 5, 6, 7 are valid values.
3580+
return (val | ((val & 0x0202020202020202) << 1)) == val;
3581+
}
3582+
35633583
static int handle_msr_write(struct vcpu_t *vcpu, uint32_t msr, uint64_t val,
35643584
bool by_host)
35653585
{
@@ -3718,7 +3738,15 @@ static int handle_msr_write(struct vcpu_t *vcpu, uint32_t msr, uint64_t val,
37183738
break;
37193739
}
37203740
case IA32_CR_PAT: {
3741+
// Attempting to write an undefined memory type encoding into the
3742+
// PAT causes a general-protection (#GP) exception to be generated
3743+
if (!is_pat_valid(val)) {
3744+
r = 1;
3745+
break;
3746+
}
3747+
37213748
vcpu->cr_pat = val;
3749+
vmwrite(vcpu, GUEST_PAT, vcpu->cr_pat);
37223750
break;
37233751
}
37243752
case IA32_MTRR_DEF_TYPE: {
@@ -3912,6 +3940,13 @@ static int _copy_desc(segment_desc_t *old, segment_desc_t *new)
39123940
return flags;
39133941
}
39143942

3943+
int vcpu_get_state_size(struct vcpu_t *vcpu)
3944+
{
3945+
if (vcpu->vm->features & VM_FEATURES_CR8)
3946+
return sizeof(struct vcpu_state_t);
3947+
return offsetof(struct vcpu_state_t, _cr8);
3948+
}
3949+
39153950
int vcpu_get_regs(struct vcpu_t *vcpu, struct vcpu_state_t *ustate)
39163951
{
39173952
struct vcpu_state_t *state = vcpu->state;
@@ -3947,6 +3982,9 @@ int vcpu_get_regs(struct vcpu_t *vcpu, struct vcpu_state_t *ustate)
39473982
_copy_desc(&state->_gdt, &ustate->_gdt);
39483983
_copy_desc(&state->_idt, &ustate->_idt);
39493984

3985+
if (vcpu->vm->features & VM_FEATURES_CR8)
3986+
ustate->_cr8 = state->_cr8;
3987+
39503988
return 0;
39513989
}
39523990

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

4113+
if (vcpu->vm->features & VM_FEATURES_CR8)
4114+
state->_cr8 = ustate->_cr8;
4115+
40754116
if ((vmcs_err = put_vmcs(vcpu, &flags))) {
40764117
vcpu_set_panic(vcpu);
40774118
hax_log(HAX_LOGPANIC, "put_vmcs failed on vcpu_set_regs: %x\n",

core/vm.c

+3
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ int hax_vm_set_qemuversion(struct vm_t *vm, struct hax_qemu_version *ver)
7373
vm->features |= VM_FEATURES_FASTMMIO_BASIC;
7474
if (ver->cur_version >= 0x4) {
7575
vm->features |= VM_FEATURES_FASTMMIO_EXTRA;
76+
if (ver->cur_version >= 0x5) {
77+
vm->features |= VM_FEATURES_CR8;
78+
}
7679
}
7780
}
7881
return 0;

include/hax.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
// declaration
4040
struct vcpu_t;
4141

42-
#define HAX_CUR_VERSION 0x0004
42+
#define HAX_CUR_VERSION 0x0005
4343
#define HAX_COMPAT_VERSION 0x0001
4444

4545
/* TBD */

include/vcpu_state.h

+2
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ struct vcpu_state_t {
188188
uint32_t _activity_state;
189189
uint32_t pad;
190190
interruptibility_state_t _interruptibility_state;
191+
192+
uint64_t _cr8;
191193
} PACKED;
192194

193195
void dump(void);

platforms/linux/components.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,8 @@ static long hax_vcpu_ioctl(struct file *filp, unsigned int cmd,
411411
}
412412
case HAX_VCPU_SET_REGS: {
413413
struct vcpu_state_t vc_state;
414-
if (copy_from_user(&vc_state, argp, sizeof(vc_state))) {
414+
int size = vcpu_get_state_size(cvcpu);
415+
if (copy_from_user(&vc_state, argp, size)) {
415416
ret = -EFAULT;
416417
break;
417418
}
@@ -420,8 +421,9 @@ static long hax_vcpu_ioctl(struct file *filp, unsigned int cmd,
420421
}
421422
case HAX_VCPU_GET_REGS: {
422423
struct vcpu_state_t vc_state;
424+
int size = vcpu_get_state_size(cvcpu);
423425
ret = vcpu_get_regs(cvcpu, &vc_state);
424-
if (copy_to_user(argp, &vc_state, sizeof(vc_state))) {
426+
if (copy_to_user(argp, &vc_state, size)) {
425427
ret = -EFAULT;
426428
break;
427429
}

platforms/windows/hax_entry.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ NTSTATUS HaxVcpuControl(PDEVICE_OBJECT DeviceObject,
387387
}
388388
case HAX_VCPU_SET_REGS: {
389389
struct vcpu_state_t *vc_state;
390-
if(inBufLength < sizeof(struct vcpu_state_t)) {
390+
if (inBufLength < vcpu_get_state_size(cvcpu)) {
391391
ret = STATUS_INVALID_PARAMETER;
392392
goto done;
393393
}
@@ -398,15 +398,15 @@ NTSTATUS HaxVcpuControl(PDEVICE_OBJECT DeviceObject,
398398
}
399399
case HAX_VCPU_GET_REGS: {
400400
struct vcpu_state_t *vc_state;
401-
if(outBufLength < sizeof(struct vcpu_state_t)) {
401+
infret = vcpu_get_state_size(cvcpu);
402+
if (outBufLength < infret) {
402403
ret = STATUS_INVALID_PARAMETER;
403404
goto done;
404405

405406
}
406407
vc_state = (struct vcpu_state_t *)outBuf;
407408
// vcpu_get_regs() cannot fail
408409
vcpu_get_regs(cvcpu, vc_state);
409-
infret = sizeof(struct vcpu_state_t);
410410
break;
411411
}
412412
case HAX_VCPU_IOCTL_INTERRUPT: {

0 commit comments

Comments
 (0)