mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-05 03:26:29 +00:00
hv: split-lock: using MTF instead of TF(#DB)
The TF is visible to guest which may be modified by the guest, so it is not a safe method to emulate the split-lock. While MTF is specifically designed for single-stepping in x86/Intel hardware virtualization VT-x technology which is invisible to the guest. Use MTF to single step the VCPU during the emulation of split lock. Tracked-On: #5605 Signed-off-by: Jie Deng <jie.deng@intel.com>
This commit is contained in:
parent
6852438e3a
commit
f291997811
@ -432,7 +432,13 @@ int32_t acrn_handle_pending_request(struct acrn_vcpu *vcpu)
|
||||
}
|
||||
}
|
||||
|
||||
acrn_inject_pending_intr(vcpu, pending_req_bits, injected);
|
||||
/*
|
||||
* Defer injection of interrupt to be after MTF VM exit,
|
||||
* when emulating the split-lock.
|
||||
*/
|
||||
if (!vcpu->arch.emulating_lock) {
|
||||
acrn_inject_pending_intr(vcpu, pending_req_bits, injected);
|
||||
}
|
||||
|
||||
/*
|
||||
* If "virtual-interrupt delivered" is enabled, CPU will evaluate
|
||||
@ -548,6 +554,7 @@ static int32_t emulate_splitlock(struct acrn_vcpu *vcpu, uint32_t exception_vect
|
||||
uint8_t inst[1];
|
||||
uint32_t err_code = 0U;
|
||||
uint64_t fault_addr;
|
||||
uint32_t value32;
|
||||
|
||||
/* Queue the exception by default if the exception cannot be handled. */
|
||||
*queue_exception = true;
|
||||
@ -587,11 +594,11 @@ static int32_t emulate_splitlock(struct acrn_vcpu *vcpu, uint32_t exception_vect
|
||||
*/
|
||||
vcpu->arch.inst_len = 1U;
|
||||
if (vcpu->vm->hw.created_vcpus > 1U) {
|
||||
/*
|
||||
* Set the TF to have a #DB after running the split-lock
|
||||
* instruction and tag the emulating_lock to be true.
|
||||
*/
|
||||
vcpu_set_rflags(vcpu, vcpu_get_rflags(vcpu) | HV_ARCH_VCPU_RFLAGS_TF);
|
||||
/* Enable MTF to start single-stepping execution */
|
||||
value32 = exec_vmread32(VMX_PROC_VM_EXEC_CONTROLS);
|
||||
value32 |= VMX_PROCBASED_CTLS_MON_TRAP;
|
||||
exec_vmwrite32(VMX_PROC_VM_EXEC_CONTROLS, value32);
|
||||
|
||||
vcpu->arch.emulating_lock = true;
|
||||
}
|
||||
|
||||
@ -644,31 +651,6 @@ static int32_t emulate_splitlock(struct acrn_vcpu *vcpu, uint32_t exception_vect
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case IDT_DB:
|
||||
/*
|
||||
* We only handle #DB caused by split-lock emulation,
|
||||
* otherwise, inject it back.
|
||||
*/
|
||||
if (vcpu->arch.emulating_lock) {
|
||||
/*
|
||||
* The split-lock emulation has been completed, tag the emulating_lock
|
||||
* to be false, and clear the TF flag.
|
||||
*/
|
||||
vcpu->arch.emulating_lock = false;
|
||||
vcpu_set_rflags(vcpu, vcpu_get_rflags(vcpu) & (~HV_ARCH_VCPU_RFLAGS_TF));
|
||||
/*
|
||||
* Notify other vcpus of the guest to restart execution.
|
||||
*/
|
||||
vcpu_complete_splitlock_emulation(vcpu);
|
||||
|
||||
/* This #DB is for split-lock emulation, do not inject it */
|
||||
*queue_exception = false;
|
||||
|
||||
/* This case we should not skip the instruction */
|
||||
vcpu->arch.inst_len = 0U;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -368,11 +368,11 @@ static void init_exec_ctrl(struct acrn_vcpu *vcpu)
|
||||
/* Set up guest exception mask bitmap setting a bit * causes a VM exit
|
||||
* on corresponding guest * exception - pg 2902 24.6.3
|
||||
* enable VM exit on MC always
|
||||
* enable AC and DB for split lock emulation when split lock detection is enabled on physical platform.
|
||||
* enable AC for split-lock emulation when split-lock detection is enabled on physical platform.
|
||||
*/
|
||||
value32 = (1U << IDT_MC);
|
||||
if (is_ac_enabled()) {
|
||||
value32 = (value32 | (1U << IDT_AC) | (1U << IDT_DB));
|
||||
value32 = (value32 | (1U << IDT_AC));
|
||||
}
|
||||
exec_vmwrite32(VMX_EXCEPTION_BITMAP, value32);
|
||||
|
||||
|
@ -33,6 +33,7 @@ static int32_t wbinvd_vmexit_handler(struct acrn_vcpu *vcpu);
|
||||
static int32_t undefined_vmexit_handler(struct acrn_vcpu *vcpu);
|
||||
static int32_t pause_vmexit_handler(__unused struct acrn_vcpu *vcpu);
|
||||
static int32_t hlt_vmexit_handler(struct acrn_vcpu *vcpu);
|
||||
static int32_t mtf_vmexit_handler(struct acrn_vcpu *vcpu);
|
||||
|
||||
/* VM Dispatch table for Exit condition handling */
|
||||
static const struct vm_exit_dispatch dispatch_table[NR_VMX_EXIT_REASONS] = {
|
||||
@ -112,7 +113,7 @@ static const struct vm_exit_dispatch dispatch_table[NR_VMX_EXIT_REASONS] = {
|
||||
[VMX_EXIT_REASON_MWAIT] = {
|
||||
.handler = unhandled_vmexit_handler},
|
||||
[VMX_EXIT_REASON_MONITOR_TRAP] = {
|
||||
.handler = unhandled_vmexit_handler},
|
||||
.handler = mtf_vmexit_handler},
|
||||
[VMX_EXIT_REASON_MONITOR] = {
|
||||
.handler = unhandled_vmexit_handler},
|
||||
[VMX_EXIT_REASON_PAUSE] = {
|
||||
@ -271,6 +272,42 @@ static int32_t unhandled_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vcpu_complete_split_lock_emulation(struct acrn_vcpu *cur_vcpu)
|
||||
{
|
||||
struct acrn_vcpu *other;
|
||||
uint16_t i;
|
||||
|
||||
if (cur_vcpu->vm->hw.created_vcpus > 1U) {
|
||||
foreach_vcpu(i, cur_vcpu->vm, other) {
|
||||
if (other != cur_vcpu) {
|
||||
bitmap_clear_lock(ACRN_REQUEST_SPLIT_LOCK, &other->arch.pending_req);
|
||||
signal_event(&other->events[VCPU_EVENT_SPLIT_LOCK]);
|
||||
}
|
||||
}
|
||||
|
||||
put_vm_lock(cur_vcpu->vm);
|
||||
}
|
||||
}
|
||||
|
||||
/* MTF is currently only used for split-lock emulation */
|
||||
static int32_t mtf_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
{
|
||||
uint32_t value32;
|
||||
|
||||
value32 = exec_vmread32(VMX_PROC_VM_EXEC_CONTROLS);
|
||||
value32 &= ~(VMX_PROCBASED_CTLS_MON_TRAP);
|
||||
exec_vmwrite32(VMX_PROC_VM_EXEC_CONTROLS, value32);
|
||||
|
||||
vcpu_retain_rip(vcpu);
|
||||
|
||||
if (vcpu->arch.emulating_lock) {
|
||||
vcpu->arch.emulating_lock = false;
|
||||
vcpu_complete_split_lock_emulation(vcpu);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t triple_fault_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
{
|
||||
pr_fatal("VM%d: triple fault @ guest RIP 0x%016lx, exit qualification: 0x%016lx",
|
||||
|
Loading…
Reference in New Issue
Block a user