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

Commit 69d5462

Browse files
committed
Add PAT and IA32_PAT VMX handling
Signed-off-by: Alexey Romko <[email protected]>
1 parent 77926e7 commit 69d5462

File tree

3 files changed

+30
-5
lines changed

3 files changed

+30
-5
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/vcpu.c

+28-4
Original file line numberDiff line numberDiff line change
@@ -1229,6 +1229,9 @@ void vcpu_save_host_state(struct vcpu_t *vcpu)
12291229
vmwrite(vcpu, HOST_EFER, hstate->_efer);
12301230
}
12311231

1232+
hstate->_pat = ia32_rdmsr(IA32_CR_PAT);
1233+
vmwrite(vcpu, HOST_PAT, hstate->_pat);
1234+
12321235
#ifdef HAX_ARCH_X86_64
12331236
vmwrite(vcpu, HOST_CS_SELECTOR, get_kernel_cs());
12341237
#else
@@ -1395,15 +1398,15 @@ static void fill_common_vmcs(struct vcpu_t *vcpu)
13951398

13961399
#ifdef HAX_ARCH_X86_64
13971400
exit_ctls = EXIT_CONTROL_HOST_ADDR_SPACE_SIZE | EXIT_CONTROL_LOAD_EFER |
1398-
EXIT_CONTROL_SAVE_DEBUG_CONTROLS;
1401+
EXIT_CONTROL_SAVE_DEBUG_CONTROLS | EXIT_CONTROL_LOAD_PAT;
13991402
#endif
14001403

14011404
#ifdef HAX_ARCH_X86_32
14021405
if (is_compatible()) {
14031406
exit_ctls = EXIT_CONTROL_HOST_ADDR_SPACE_SIZE | EXIT_CONTROL_LOAD_EFER |
1404-
EXIT_CONTROL_SAVE_DEBUG_CONTROLS;
1407+
EXIT_CONTROL_SAVE_DEBUG_CONTROLS | EXIT_CONTROL_LOAD_PAT;
14051408
} else {
1406-
exit_ctls = EXIT_CONTROL_SAVE_DEBUG_CONTROLS;
1409+
exit_ctls = EXIT_CONTROL_SAVE_DEBUG_CONTROLS | EXIT_CONTROL_LOAD_PAT;
14071410
}
14081411
#endif
14091412

@@ -1474,6 +1477,8 @@ static void fill_common_vmcs(struct vcpu_t *vcpu)
14741477
if (exit_ctls & EXIT_CONTROL_LOAD_EFER) {
14751478
vmwrite(vcpu, HOST_EFER, ia32_rdmsr(IA32_EFER));
14761479
}
1480+
vmwrite(vcpu, HOST_PAT, ia32_rdmsr(IA32_CR_PAT));
1481+
vmwrite(vcpu, GUEST_PAT, vcpu->cr_pat);
14771482

14781483
WRITE_CONTROLS(vcpu, VMX_ENTRY_CONTROLS, entry_ctls);
14791484

@@ -2070,6 +2075,8 @@ static void vmwrite_cr(struct vcpu_t *vcpu)
20702075
entry_ctls &= ~ENTRY_CONTROL_LOAD_EFER;
20712076
}
20722077

2078+
entry_ctls |= ENTRY_CONTROL_LOAD_PAT;
2079+
20732080
if (pcpu_ctls != vmx(vcpu, pcpu_ctls)) {
20742081
vmx(vcpu, pcpu_ctls) = pcpu_ctls;
20752082
vcpu->pcpu_ctls_dirty = 1;
@@ -2575,7 +2582,7 @@ static void handle_cpuid_virtual(struct vcpu_t *vcpu, uint32_t a, uint32_t c)
25752582
uint8_t physical_address_size;
25762583

25772584
static uint32_t cpuid_1_features_edx =
2578-
// pat is disabled!
2585+
FEATURE(PAT) |
25792586
FEATURE(FPU) |
25802587
FEATURE(VME) |
25812588
FEATURE(DE) |
@@ -3605,6 +3612,15 @@ static int misc_msr_write(struct vcpu_t *vcpu, uint32_t msr, uint64_t val)
36053612
return 1;
36063613
}
36073614

3615+
static inline bool pat_valid(uint64_t val)
3616+
{
3617+
if (val & 0xF8F8F8F8F8F8F8F8)
3618+
return false;
3619+
3620+
/* 0, 1, 4, 5, 6, 7 are valid values. */
3621+
return (val | ((val & 0x0202020202020202) << 1)) == val;
3622+
}
3623+
36083624
static int handle_msr_write(struct vcpu_t *vcpu, uint32_t msr, uint64_t val,
36093625
bool by_host)
36103626
{
@@ -3763,7 +3779,15 @@ static int handle_msr_write(struct vcpu_t *vcpu, uint32_t msr, uint64_t val,
37633779
break;
37643780
}
37653781
case IA32_CR_PAT: {
3782+
//Attempting to write an undefined memory type encoding into the PAT causes a
3783+
//general-protection (#GP) exception to be generated.
3784+
if (!pat_valid(val)) {
3785+
r = 1;
3786+
break;
3787+
}
3788+
37663789
vcpu->cr_pat = val;
3790+
vmwrite(vcpu, GUEST_PAT, vcpu->cr_pat);
37673791
break;
37683792
}
37693793
case IA32_MTRR_DEF_TYPE: {

0 commit comments

Comments
 (0)