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

Commit 192cd52

Browse files
authored
Merge pull request #145 from intel/cr8-trap
Do not allow guest direct access to CR8
2 parents 746ed03 + 2ed3796 commit 192cd52

File tree

1 file changed

+24
-23
lines changed

1 file changed

+24
-23
lines changed

core/vcpu.c

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ static uint64_t vcpu_read_cr(struct vcpu_state_t *state, uint32_t n)
194194
break;
195195
}
196196
default: {
197-
hax_error("Unsupported CR%d access\n", n);
197+
hax_warning("Ignored unsupported CR%d read, returning 0\n", n);
198198
break;
199199
}
200200
}
@@ -1324,7 +1324,7 @@ static void fill_common_vmcs(struct vcpu_t *vcpu)
13241324

13251325
pcpu_ctls = IO_BITMAP_ACTIVE | MSR_BITMAP_ACTIVE | DR_EXITING |
13261326
INTERRUPT_WINDOW_EXITING | USE_TSC_OFFSETTING | HLT_EXITING |
1327-
SECONDARY_CONTROLS;
1327+
CR8_LOAD_EXITING | CR8_STORE_EXITING | SECONDARY_CONTROLS;
13281328

13291329
scpu_ctls = ENABLE_EPT;
13301330

@@ -2778,7 +2778,6 @@ static void check_flush(struct vcpu_t *vcpu, uint32_t bits)
27782778

27792779
static int exit_cr_access(struct vcpu_t *vcpu, struct hax_tunnel *htun)
27802780
{
2781-
uint64_t cr_ptr;
27822781
int cr;
27832782
struct vcpu_state_t *state = vcpu->state;
27842783
bool is_ept_pae = false;
@@ -2788,19 +2787,25 @@ static int exit_cr_access(struct vcpu_t *vcpu, struct hax_tunnel *htun)
27882787
htun->_exit_reason = vmx(vcpu, exit_reason).basic_reason;
27892788

27902789
cr = vmx(vcpu, exit_qualification).cr.creg;
2791-
cr_ptr = vcpu_read_cr(state, cr);
27922790

27932791
switch (vmx(vcpu, exit_qualification).cr.type) {
27942792
case 0: { // MOV CR <- GPR
27952793
uint64_t val = state->_regs[(vmx(vcpu, exit_qualification).cr.gpr)];
2794+
uint64_t old_val = 0;
27962795

2797-
hax_debug("cr_access W CR%d: %08llx -> %08llx\n", cr, cr_ptr, val);
2796+
if (cr == 8) {
2797+
// TODO: Redirect CR8 write to user space (emulated APIC.TPR)
2798+
hax_warning("Ignored guest CR8 write, val=0x%llx\n", val);
2799+
break;
2800+
}
2801+
2802+
old_val = vcpu_read_cr(state, cr);
27982803
if (cr == 0) {
27992804
uint64_t cr0_pae_triggers;
28002805

28012806
hax_info("Guest writing to CR0[%u]: 0x%llx -> 0x%llx,"
28022807
" _cr4=0x%llx, _efer=0x%x\n", vcpu->vcpu_id,
2803-
state->_cr0, val, state->_cr4, state->_efer);
2808+
old_val, val, state->_cr4, state->_efer);
28042809
if ((val & CR0_PG) && !(val & CR0_PE)) {
28052810
hax_inject_exception(vcpu, VECTOR_GP, 0);
28062811
return HAX_RESUME;
@@ -2812,7 +2817,7 @@ static int exit_cr_access(struct vcpu_t *vcpu, struct hax_tunnel *htun)
28122817
return HAX_RESUME;
28132818
}
28142819
}
2815-
if (!hax->ug_enable_flag && (cr_ptr & CR0_PE) &&
2820+
if (!hax->ug_enable_flag && (old_val & CR0_PE) &&
28162821
!(val & CR0_PE)) {
28172822
htun->_exit_status = HAX_EXIT_REALMODE;
28182823
hax_debug("Enter NON-PE from PE\n");
@@ -2823,19 +2828,17 @@ static int exit_cr_access(struct vcpu_t *vcpu, struct hax_tunnel *htun)
28232828
cr0_pae_triggers = CR0_CD | CR0_NW | CR0_PG;
28242829
if ((val & CR0_PG) && (state->_cr4 & CR4_PAE) &&
28252830
!(state->_efer & IA32_EFER_LME) && !vtlb_active(vcpu) &&
2826-
((val ^ cr_ptr) & cr0_pae_triggers)) {
2831+
((val ^ old_val) & cr0_pae_triggers)) {
28272832
hax_info("%s: vCPU #%u triggers PDPT (re)load for EPT+PAE"
28282833
" mode (CR0 path)\n", __func__, vcpu->vcpu_id);
28292834
is_ept_pae = true;
28302835
}
2831-
}
2832-
2833-
if (cr == 4) {
2836+
} else if (cr == 4) {
28342837
uint64_t cr4_pae_triggers;
28352838

28362839
hax_info("Guest writing to CR4[%u]: 0x%llx -> 0x%llx,"
28372840
"_cr0=0x%llx, _efer=0x%x\n", vcpu->vcpu_id,
2838-
state->_cr4, val, state->_cr0, state->_efer);
2841+
old_val, val, state->_cr0, state->_efer);
28392842
if ((state->_efer & IA32_EFER_LMA) && !(val & CR4_PAE)) {
28402843
hax_inject_exception(vcpu, VECTOR_GP, 0);
28412844
return HAX_RESUME;
@@ -2846,18 +2849,16 @@ static int exit_cr_access(struct vcpu_t *vcpu, struct hax_tunnel *htun)
28462849
cr4_pae_triggers = CR4_PAE | CR4_PGE | CR4_PSE;
28472850
if ((val & CR4_PAE) && (state->_cr0 & CR0_PG) &&
28482851
!(state->_efer & IA32_EFER_LME) && !vtlb_active(vcpu) &&
2849-
((val ^ cr_ptr) & cr4_pae_triggers)) {
2852+
((val ^ old_val) & cr4_pae_triggers)) {
28502853
hax_info("%s: vCPU #%u triggers PDPT (re)load for EPT+PAE"
28512854
" mode (CR4 path)\n", __func__, vcpu->vcpu_id);
28522855
is_ept_pae = true;
28532856
}
2854-
}
2855-
2856-
if (cr == 8) {
2857-
hax_error("Unsupported CR%d access\n", cr);
2857+
} else {
2858+
hax_error("Unsupported CR%d write, val=0x%llx\n", cr, val);
28582859
break;
28592860
}
2860-
check_flush(vcpu, cr_ptr ^ val);
2861+
check_flush(vcpu, old_val ^ val);
28612862
vcpu_write_cr(state, cr, val);
28622863

28632864
if (is_ept_pae) {
@@ -2895,13 +2896,13 @@ static int exit_cr_access(struct vcpu_t *vcpu, struct hax_tunnel *htun)
28952896
break;
28962897
}
28972898
case 1: { // MOV CR -> GPR
2899+
uint64_t val;
2900+
28982901
hax_info("cr_access R CR%d\n", cr);
28992902

2900-
state->_regs[vmx(vcpu, exit_qualification).cr.gpr] = cr_ptr;
2901-
if (cr == 8) {
2902-
hax_info("Unsupported CR%d access\n", cr);
2903-
break;
2904-
}
2903+
val = vcpu_read_cr(state, cr);
2904+
// TODO: Redirect CR8 read to user space (emulated APIC.TPR)
2905+
state->_regs[vmx(vcpu, exit_qualification).cr.gpr] = val;
29052906
break;
29062907
}
29072908
case 2: { // CLTS

0 commit comments

Comments
 (0)