mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
x86/HVM: move NOFLUSH handling out of hvm_set_cr3()
The bit is meaningful only for MOV-to-CR3 insns, not anywhere else, in particular not when loading nested guest state. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Paul Durrant <paul@xen.org> Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
This commit is contained in:
1 parent
ba7b169c9f
commit
18cc07b96f
8 files changed
+26
-21
No files matched your search
@@ -2169,8 +2169,14 @@ static int hvmemul_write_cr(
|
||||
break;
|
||||
|
||||
case 3:
|
||||
rc = hvm_set_cr3(val, true);
|
||||
{
|
||||
bool noflush = hvm_pcid_enabled(current) && (val & X86_CR3_NOFLUSH);
|
||||
|
||||
if ( noflush )
|
||||
val &= ~X86_CR3_NOFLUSH;
|
||||
rc = hvm_set_cr3(val, noflush, true);
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
rc = hvm_set_cr4(val, true);
|
||||
|
||||
+10
-10
@@ -2132,8 +2132,14 @@ int hvm_mov_to_cr(unsigned int cr, unsigned int gpr)
|
||||
break;
|
||||
|
||||
case 3:
|
||||
rc = hvm_set_cr3(val, true);
|
||||
{
|
||||
bool noflush = hvm_pcid_enabled(curr) && (val & X86_CR3_NOFLUSH);
|
||||
|
||||
if ( noflush )
|
||||
val &= ~X86_CR3_NOFLUSH;
|
||||
rc = hvm_set_cr3(val, noflush, true);
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
rc = hvm_set_cr4(val, true);
|
||||
@@ -2350,12 +2356,11 @@ int hvm_set_cr0(unsigned long value, bool may_defer)
|
||||
return X86EMUL_OKAY;
|
||||
}
|
||||
|
||||
int hvm_set_cr3(unsigned long value, bool may_defer)
|
||||
int hvm_set_cr3(unsigned long value, bool noflush, bool may_defer)
|
||||
{
|
||||
struct vcpu *v = current;
|
||||
struct page_info *page;
|
||||
unsigned long old = v->arch.hvm.guest_cr[3];
|
||||
bool noflush = false;
|
||||
|
||||
if ( may_defer && unlikely(v->domain->arch.monitor.write_ctrlreg_enabled &
|
||||
monitor_ctrlreg_bitmask(VM_EVENT_X86_CR3)) )
|
||||
@@ -2367,17 +2372,12 @@ int hvm_set_cr3(unsigned long value, bool may_defer)
|
||||
/* The actual write will occur in hvm_do_resume(), if permitted. */
|
||||
v->arch.vm_event->write_data.do_write.cr3 = 1;
|
||||
v->arch.vm_event->write_data.cr3 = value;
|
||||
v->arch.vm_event->write_data.cr3_noflush = noflush;
|
||||
|
||||
return X86EMUL_OKAY;
|
||||
}
|
||||
}
|
||||
|
||||
if ( hvm_pcid_enabled(v) ) /* Clear the noflush bit. */
|
||||
{
|
||||
noflush = value & X86_CR3_NOFLUSH;
|
||||
value &= ~X86_CR3_NOFLUSH;
|
||||
}
|
||||
|
||||
if ( hvm_paging_enabled(v) && !paging_mode_hap(v->domain) &&
|
||||
((value ^ v->arch.hvm.guest_cr[3]) >> PAGE_SHIFT) )
|
||||
{
|
||||
@@ -3073,7 +3073,7 @@ void hvm_task_switch(
|
||||
if ( task_switch_load_seg(x86_seg_ldtr, tss.ldt, new_cpl, 0) )
|
||||
goto out;
|
||||
|
||||
rc = hvm_set_cr3(tss.cr3, true);
|
||||
rc = hvm_set_cr3(tss.cr3, false, true);
|
||||
if ( rc == X86EMUL_EXCEPTION )
|
||||
hvm_inject_hw_exception(TRAP_gp_fault, 0);
|
||||
if ( rc != X86EMUL_OKAY )
|
||||
|
||||
@@ -39,9 +39,6 @@ bool hvm_monitor_cr(unsigned int index, unsigned long value, unsigned long old)
|
||||
struct arch_domain *ad = &curr->domain->arch;
|
||||
unsigned int ctrlreg_bitmask = monitor_ctrlreg_bitmask(index);
|
||||
|
||||
if ( index == VM_EVENT_X86_CR3 && hvm_pcid_enabled(curr) )
|
||||
value &= ~X86_CR3_NOFLUSH; /* Clear the noflush bit. */
|
||||
|
||||
if ( (ad->monitor.write_ctrlreg_enabled & ctrlreg_bitmask) &&
|
||||
(!(ad->monitor.write_ctrlreg_onchangeonly & ctrlreg_bitmask) ||
|
||||
value != old) &&
|
||||
|
||||
@@ -324,7 +324,7 @@ static int nsvm_vcpu_hostrestore(struct vcpu *v, struct cpu_user_regs *regs)
|
||||
v->arch.guest_table = pagetable_null();
|
||||
/* hvm_set_cr3() below sets v->arch.hvm.guest_cr[3] for us. */
|
||||
}
|
||||
rc = hvm_set_cr3(n1vmcb->_cr3, true);
|
||||
rc = hvm_set_cr3(n1vmcb->_cr3, false, true);
|
||||
if ( rc == X86EMUL_EXCEPTION )
|
||||
hvm_inject_hw_exception(TRAP_gp_fault, 0);
|
||||
if (rc != X86EMUL_OKAY)
|
||||
@@ -583,7 +583,7 @@ static int nsvm_vmcb_prepare4vmrun(struct vcpu *v, struct cpu_user_regs *regs)
|
||||
nestedsvm_vmcb_set_nestedp2m(v, ns_vmcb, n2vmcb);
|
||||
|
||||
/* hvm_set_cr3() below sets v->arch.hvm.guest_cr[3] for us. */
|
||||
rc = hvm_set_cr3(ns_vmcb->_cr3, true);
|
||||
rc = hvm_set_cr3(ns_vmcb->_cr3, false, true);
|
||||
if ( rc == X86EMUL_EXCEPTION )
|
||||
hvm_inject_hw_exception(TRAP_gp_fault, 0);
|
||||
if (rc != X86EMUL_OKAY)
|
||||
@@ -597,7 +597,7 @@ static int nsvm_vmcb_prepare4vmrun(struct vcpu *v, struct cpu_user_regs *regs)
|
||||
* we assume it intercepts page faults.
|
||||
*/
|
||||
/* hvm_set_cr3() below sets v->arch.hvm.guest_cr[3] for us. */
|
||||
rc = hvm_set_cr3(ns_vmcb->_cr3, true);
|
||||
rc = hvm_set_cr3(ns_vmcb->_cr3, false, true);
|
||||
if ( rc == X86EMUL_EXCEPTION )
|
||||
hvm_inject_hw_exception(TRAP_gp_fault, 0);
|
||||
if (rc != X86EMUL_OKAY)
|
||||
|
||||
@@ -111,7 +111,7 @@ void hvm_vm_event_do_resume(struct vcpu *v)
|
||||
|
||||
if ( unlikely(w->do_write.cr3) )
|
||||
{
|
||||
if ( hvm_set_cr3(w->cr3, false) == X86EMUL_EXCEPTION )
|
||||
if ( hvm_set_cr3(w->cr3, w->cr3_noflush, false) == X86EMUL_EXCEPTION )
|
||||
hvm_inject_hw_exception(TRAP_gp_fault, 0);
|
||||
|
||||
w->do_write.cr3 = 0;
|
||||
|
||||
@@ -1104,7 +1104,7 @@ static void load_shadow_guest_state(struct vcpu *v)
|
||||
if ( rc == X86EMUL_EXCEPTION )
|
||||
hvm_inject_hw_exception(TRAP_gp_fault, 0);
|
||||
|
||||
rc = hvm_set_cr3(get_vvmcs(v, GUEST_CR3), true);
|
||||
rc = hvm_set_cr3(get_vvmcs(v, GUEST_CR3), false, true);
|
||||
if ( rc == X86EMUL_EXCEPTION )
|
||||
hvm_inject_hw_exception(TRAP_gp_fault, 0);
|
||||
|
||||
@@ -1318,7 +1318,7 @@ static void load_vvmcs_host_state(struct vcpu *v)
|
||||
if ( rc == X86EMUL_EXCEPTION )
|
||||
hvm_inject_hw_exception(TRAP_gp_fault, 0);
|
||||
|
||||
rc = hvm_set_cr3(get_vvmcs(v, HOST_CR3), true);
|
||||
rc = hvm_set_cr3(get_vvmcs(v, HOST_CR3), false, true);
|
||||
if ( rc == X86EMUL_EXCEPTION )
|
||||
hvm_inject_hw_exception(TRAP_gp_fault, 0);
|
||||
|
||||
|
||||
@@ -285,6 +285,8 @@ struct monitor_write_data {
|
||||
unsigned int cr4 : 1;
|
||||
} do_write;
|
||||
|
||||
bool cr3_noflush;
|
||||
|
||||
uint32_t msr;
|
||||
uint64_t value;
|
||||
uint64_t cr0;
|
||||
|
||||
@@ -136,7 +136,7 @@ void hvm_shadow_handle_cd(struct vcpu *v, unsigned long value);
|
||||
*/
|
||||
int hvm_set_efer(uint64_t value);
|
||||
int hvm_set_cr0(unsigned long value, bool may_defer);
|
||||
int hvm_set_cr3(unsigned long value, bool may_defer);
|
||||
int hvm_set_cr3(unsigned long value, bool noflush, bool may_defer);
|
||||
int hvm_set_cr4(unsigned long value, bool may_defer);
|
||||
int hvm_descriptor_access_intercept(uint64_t exit_info,
|
||||
uint64_t vmx_exit_qualification,
|
||||
|
||||