@@ -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+
35633583static 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+
39153950int 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" ,
0 commit comments