Skip to content

Commit e943f98

Browse files
sean-jcgregkh
authored andcommitted
KVM: SVM: Don't put/load AVIC when setting virtual APIC mode
commit e0bead9 upstream. Move the VMCB updates from avic_refresh_apicv_exec_ctrl() into avic_set_virtual_apic_mode() and invert the dependency being said functions to avoid calling avic_vcpu_{load,put}() and avic_set_pi_irte_mode() when "only" setting the virtual APIC mode. avic_set_virtual_apic_mode() is invoked from common x86 with preemption enabled, which makes avic_vcpu_{load,put}() unhappy. Luckily, calling those and updating IRTE stuff is unnecessary as the only reason avic_set_virtual_apic_mode() is called is to handle transitions between xAPIC and x2APIC that don't also toggle APICv activation. And if activation doesn't change, there's no need to fiddle with the physical APIC ID table or update IRTE. The "full" refresh is guaranteed to be called if activation changes in this case as the only call to the "set" path is: kvm_vcpu_update_apicv(vcpu); static_call_cond(kvm_x86_set_virtual_apic_mode)(vcpu); and kvm_vcpu_update_apicv() invokes the refresh if activation changes: if (apic->apicv_active == activate) goto out; apic->apicv_active = activate; kvm_apic_update_apicv(vcpu); static_call(kvm_x86_refresh_apicv_exec_ctrl)(vcpu); Rename the helper to reflect that it is also called during "refresh". WARNING: CPU: 183 PID: 49186 at arch/x86/kvm/svm/avic.c:1081 avic_vcpu_put+0xde/0xf0 [kvm_amd] CPU: 183 PID: 49186 Comm: stable Tainted: G O 6.0.0-smp--fcddbca45f0a-sink #34 Hardware name: Google, Inc. Arcadia_IT_80/Arcadia_IT_80, BIOS 10.48.0 01/27/2022 RIP: 0010:avic_vcpu_put+0xde/0xf0 [kvm_amd] avic_refresh_apicv_exec_ctrl+0x142/0x1c0 [kvm_amd] avic_set_virtual_apic_mode+0x5a/0x70 [kvm_amd] kvm_lapic_set_base+0x149/0x1a0 [kvm] kvm_set_apic_base+0x8f/0xd0 [kvm] kvm_set_msr_common+0xa3a/0xdc0 [kvm] svm_set_msr+0x364/0x6b0 [kvm_amd] __kvm_set_msr+0xb8/0x1c0 [kvm] kvm_emulate_wrmsr+0x58/0x1d0 [kvm] msr_interception+0x1c/0x30 [kvm_amd] svm_invoke_exit_handler+0x31/0x100 [kvm_amd] svm_handle_exit+0xfc/0x160 [kvm_amd] vcpu_enter_guest+0x21bb/0x23e0 [kvm] vcpu_run+0x92/0x450 [kvm] kvm_arch_vcpu_ioctl_run+0x43e/0x6e0 [kvm] kvm_vcpu_ioctl+0x559/0x620 [kvm] Fixes: 05c4fe8 ("KVM: SVM: Refresh AVIC configuration when changing APIC mode") Cc: [email protected] Cc: Suravee Suthikulpanit <[email protected]> Reviewed-by: Maxim Levitsky <[email protected]> Signed-off-by: Sean Christopherson <[email protected]> Message-Id: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent ac46aca commit e943f98

File tree

3 files changed

+17
-18
lines changed

3 files changed

+17
-18
lines changed

arch/x86/kvm/svm/avic.c

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -747,18 +747,6 @@ void avic_apicv_post_state_restore(struct kvm_vcpu *vcpu)
747747
avic_handle_ldr_update(vcpu);
748748
}
749749

750-
void avic_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
751-
{
752-
if (!lapic_in_kernel(vcpu) || avic_mode == AVIC_MODE_NONE)
753-
return;
754-
755-
if (kvm_get_apic_mode(vcpu) == LAPIC_MODE_INVALID) {
756-
WARN_ONCE(true, "Invalid local APIC state (vcpu_id=%d)", vcpu->vcpu_id);
757-
return;
758-
}
759-
avic_refresh_apicv_exec_ctrl(vcpu);
760-
}
761-
762750
static int avic_set_pi_irte_mode(struct kvm_vcpu *vcpu, bool activate)
763751
{
764752
int ret = 0;
@@ -1100,17 +1088,18 @@ void avic_vcpu_put(struct kvm_vcpu *vcpu)
11001088
WRITE_ONCE(*(svm->avic_physical_id_cache), entry);
11011089
}
11021090

1103-
1104-
void avic_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
1091+
void avic_refresh_virtual_apic_mode(struct kvm_vcpu *vcpu)
11051092
{
11061093
struct vcpu_svm *svm = to_svm(vcpu);
11071094
struct vmcb *vmcb = svm->vmcb01.ptr;
1108-
bool activated = kvm_vcpu_apicv_active(vcpu);
1095+
1096+
if (!lapic_in_kernel(vcpu) || avic_mode == AVIC_MODE_NONE)
1097+
return;
11091098

11101099
if (!enable_apicv)
11111100
return;
11121101

1113-
if (activated) {
1102+
if (kvm_vcpu_apicv_active(vcpu)) {
11141103
/**
11151104
* During AVIC temporary deactivation, guest could update
11161105
* APIC ID, DFR and LDR registers, which would not be trapped
@@ -1124,6 +1113,16 @@ void avic_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
11241113
avic_deactivate_vmcb(svm);
11251114
}
11261115
vmcb_mark_dirty(vmcb, VMCB_AVIC);
1116+
}
1117+
1118+
void avic_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
1119+
{
1120+
bool activated = kvm_vcpu_apicv_active(vcpu);
1121+
1122+
if (!enable_apicv)
1123+
return;
1124+
1125+
avic_refresh_virtual_apic_mode(vcpu);
11271126

11281127
if (activated)
11291128
avic_vcpu_load(vcpu, vcpu->cpu);

arch/x86/kvm/svm/svm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4771,7 +4771,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
47714771
.enable_nmi_window = svm_enable_nmi_window,
47724772
.enable_irq_window = svm_enable_irq_window,
47734773
.update_cr8_intercept = svm_update_cr8_intercept,
4774-
.set_virtual_apic_mode = avic_set_virtual_apic_mode,
4774+
.set_virtual_apic_mode = avic_refresh_virtual_apic_mode,
47754775
.refresh_apicv_exec_ctrl = avic_refresh_apicv_exec_ctrl,
47764776
.check_apicv_inhibit_reasons = avic_check_apicv_inhibit_reasons,
47774777
.apicv_post_state_restore = avic_apicv_post_state_restore,

arch/x86/kvm/svm/svm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,7 @@ void avic_vcpu_blocking(struct kvm_vcpu *vcpu);
648648
void avic_vcpu_unblocking(struct kvm_vcpu *vcpu);
649649
void avic_ring_doorbell(struct kvm_vcpu *vcpu);
650650
unsigned long avic_vcpu_get_apicv_inhibit_reasons(struct kvm_vcpu *vcpu);
651-
void avic_set_virtual_apic_mode(struct kvm_vcpu *vcpu);
651+
void avic_refresh_virtual_apic_mode(struct kvm_vcpu *vcpu);
652652

653653

654654
/* sev.c */

0 commit comments

Comments
 (0)