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:
Zide Chen 2021-08-18 11:54:33 -07:00 committed by wenlingz
parent b5b109dc64
commit 11c2f3eabb
2 changed files with 51 additions and 33 deletions

View File

@ -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) {

View File

@ -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,