mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-22 05:30:24 +00:00
hv: check bitmap before calling bitmap_test_and_clear_lock()
The locked btr instruction is expensive. This patch changes the logic to ensure that the bitmap is non-zero before executing bitmap_test_and_clear_lock(). The VMX transition time gets significant improvement. SOS running on TGL, the CPUID roundtrip reduces from ~2400 cycles to ~2000 cycles. Tracked-On: #6289 Signed-off-by: Zide Chen <zide.chen@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
b5b109dc64
commit
11c2f3eabb
@ -603,16 +603,12 @@ int32_t create_vcpu(uint16_t pcpu_id, struct acrn_vm *vm, struct acrn_vcpu **rtn
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @pre vcpu != NULL
|
* @pre vcpu != NULL
|
||||||
*/
|
*/
|
||||||
int32_t run_vcpu(struct acrn_vcpu *vcpu)
|
static void write_cached_registers(struct acrn_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
uint32_t instlen, cs_attr;
|
|
||||||
uint64_t rip, ia32_efer, cr0;
|
|
||||||
struct run_context *ctx =
|
struct run_context *ctx =
|
||||||
&vcpu->arch.contexts[vcpu->arch.cur_context].run_ctx;
|
&vcpu->arch.contexts[vcpu->arch.cur_context].run_ctx;
|
||||||
int32_t status = 0;
|
|
||||||
int32_t ibrs_type = get_ibrs_type();
|
|
||||||
|
|
||||||
if (bitmap_test_and_clear_lock(CPU_REG_RIP, &vcpu->reg_updated)) {
|
if (bitmap_test_and_clear_lock(CPU_REG_RIP, &vcpu->reg_updated)) {
|
||||||
exec_vmwrite(VMX_GUEST_RIP, ctx->rip);
|
exec_vmwrite(VMX_GUEST_RIP, ctx->rip);
|
||||||
@ -639,6 +635,23 @@ int32_t run_vcpu(struct acrn_vcpu *vcpu)
|
|||||||
if (bitmap_test_and_clear_lock(CPU_REG_CR4, &vcpu->reg_updated)) {
|
if (bitmap_test_and_clear_lock(CPU_REG_CR4, &vcpu->reg_updated)) {
|
||||||
vcpu_set_cr4(vcpu, ctx->cr4);
|
vcpu_set_cr4(vcpu, ctx->cr4);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @pre vcpu != NULL
|
||||||
|
*/
|
||||||
|
int32_t run_vcpu(struct acrn_vcpu *vcpu)
|
||||||
|
{
|
||||||
|
uint32_t instlen, cs_attr;
|
||||||
|
uint64_t rip, ia32_efer, cr0;
|
||||||
|
struct run_context *ctx =
|
||||||
|
&vcpu->arch.contexts[vcpu->arch.cur_context].run_ctx;
|
||||||
|
int32_t status = 0;
|
||||||
|
int32_t ibrs_type = get_ibrs_type();
|
||||||
|
|
||||||
|
if (vcpu->reg_updated != 0UL) {
|
||||||
|
write_cached_registers(vcpu);
|
||||||
|
}
|
||||||
|
|
||||||
/* If this VCPU is not already launched, launch it */
|
/* If this VCPU is not already launched, launch it */
|
||||||
if (!vcpu->launched) {
|
if (!vcpu->launched) {
|
||||||
|
@ -376,38 +376,42 @@ int32_t acrn_handle_pending_request(struct acrn_vcpu *vcpu)
|
|||||||
struct acrn_vcpu_arch *arch = &vcpu->arch;
|
struct acrn_vcpu_arch *arch = &vcpu->arch;
|
||||||
uint64_t *pending_req_bits = &arch->pending_req;
|
uint64_t *pending_req_bits = &arch->pending_req;
|
||||||
|
|
||||||
/* make sure ACRN_REQUEST_INIT_VMCS handler as the first one */
|
if (*pending_req_bits != 0UL) {
|
||||||
if (bitmap_test_and_clear_lock(ACRN_REQUEST_INIT_VMCS, pending_req_bits)) {
|
/* make sure ACRN_REQUEST_INIT_VMCS handler as the first one */
|
||||||
init_vmcs(vcpu);
|
if (bitmap_test_and_clear_lock(ACRN_REQUEST_INIT_VMCS, pending_req_bits)) {
|
||||||
}
|
init_vmcs(vcpu);
|
||||||
|
|
||||||
if (bitmap_test_and_clear_lock(ACRN_REQUEST_TRP_FAULT, pending_req_bits)) {
|
|
||||||
pr_fatal("Triple fault happen -> shutdown!");
|
|
||||||
ret = -EFAULT;
|
|
||||||
} else {
|
|
||||||
if (bitmap_test_and_clear_lock(ACRN_REQUEST_WAIT_WBINVD, pending_req_bits)) {
|
|
||||||
wait_event(&vcpu->events[VCPU_EVENT_SYNC_WBINVD]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bitmap_test_and_clear_lock(ACRN_REQUEST_SPLIT_LOCK, pending_req_bits)) {
|
if (bitmap_test_and_clear_lock(ACRN_REQUEST_TRP_FAULT, pending_req_bits)) {
|
||||||
wait_event(&vcpu->events[VCPU_EVENT_SPLIT_LOCK]);
|
pr_fatal("Triple fault happen -> shutdown!");
|
||||||
}
|
ret = -EFAULT;
|
||||||
|
} else {
|
||||||
|
if (bitmap_test_and_clear_lock(ACRN_REQUEST_WAIT_WBINVD, pending_req_bits)) {
|
||||||
|
wait_event(&vcpu->events[VCPU_EVENT_SYNC_WBINVD]);
|
||||||
|
}
|
||||||
|
|
||||||
if (bitmap_test_and_clear_lock(ACRN_REQUEST_EPT_FLUSH, pending_req_bits)) {
|
if (bitmap_test_and_clear_lock(ACRN_REQUEST_SPLIT_LOCK, pending_req_bits)) {
|
||||||
invept(vcpu->vm->arch_vm.nworld_eptp);
|
wait_event(&vcpu->events[VCPU_EVENT_SPLIT_LOCK]);
|
||||||
if (vcpu->vm->sworld_control.flag.active != 0UL) {
|
}
|
||||||
invept(vcpu->vm->arch_vm.sworld_eptp);
|
|
||||||
|
if (bitmap_test_and_clear_lock(ACRN_REQUEST_EPT_FLUSH, pending_req_bits)) {
|
||||||
|
invept(vcpu->vm->arch_vm.nworld_eptp);
|
||||||
|
if (vcpu->vm->sworld_control.flag.active != 0UL) {
|
||||||
|
invept(vcpu->vm->arch_vm.sworld_eptp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bitmap_test_and_clear_lock(ACRN_REQUEST_VPID_FLUSH, pending_req_bits)) {
|
||||||
|
flush_vpid_single(arch->vpid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bitmap_test_and_clear_lock(ACRN_REQUEST_EOI_EXIT_BITMAP_UPDATE, pending_req_bits)) {
|
||||||
|
vcpu_set_vmcs_eoi_exit(vcpu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (bitmap_test_and_clear_lock(ACRN_REQUEST_VPID_FLUSH, pending_req_bits)) {
|
if (ret == 0) {
|
||||||
flush_vpid_single(arch->vpid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bitmap_test_and_clear_lock(ACRN_REQUEST_EOI_EXIT_BITMAP_UPDATE, pending_req_bits)) {
|
|
||||||
vcpu_set_vmcs_eoi_exit(vcpu);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Inject pending exception prior pending interrupt to complete the previous instruction.
|
* Inject pending exception prior pending interrupt to complete the previous instruction.
|
||||||
*/
|
*/
|
||||||
@ -415,7 +419,8 @@ int32_t acrn_handle_pending_request(struct acrn_vcpu *vcpu)
|
|||||||
if (!injected) {
|
if (!injected) {
|
||||||
/* inject NMI before maskable hardware interrupt */
|
/* inject NMI before maskable hardware interrupt */
|
||||||
|
|
||||||
if (bitmap_test_and_clear_lock(ACRN_REQUEST_NMI, pending_req_bits)) {
|
if ((*pending_req_bits != 0UL) &&
|
||||||
|
bitmap_test_and_clear_lock(ACRN_REQUEST_NMI, pending_req_bits)) {
|
||||||
if (is_nmi_injectable()) {
|
if (is_nmi_injectable()) {
|
||||||
/* Inject NMI vector = 2 */
|
/* Inject NMI vector = 2 */
|
||||||
exec_vmwrite32(VMX_ENTRY_INT_INFO_FIELD,
|
exec_vmwrite32(VMX_ENTRY_INT_INFO_FIELD,
|
||||||
|
Loading…
Reference in New Issue
Block a user