Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: x86: BSP in MSR_IA32_APICBASE is writable

After reset, the CPU can change the BSP, which will be used upon INIT. Reset
should return the BSP which QEMU asked for, and therefore handled accordingly.

To quote: "If the MP protocol has completed and a BSP is chosen, subsequent
INITs (either to a specific processor or system wide) do not cause the MP
protocol to be repeated."
[Intel SDM 8.4.2: MP Initialization Protocol Requirements and Restrictions]

Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
Message-Id: <1427933438-12782-3-git-send-email-namit@cs.technion.ac.il>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

authored by

Nadav Amit and committed by
Paolo Bonzini
58d269d8 3b5a5ffa

+9 -6
-2
arch/x86/kvm/lapic.c
··· 1523 1523 return; 1524 1524 } 1525 1525 1526 - if (!kvm_vcpu_is_bsp(apic->vcpu)) 1527 - value &= ~MSR_IA32_APICBASE_BSP; 1528 1526 vcpu->arch.apic_base = value; 1529 1527 1530 1528 /* update jump label if enable bit changes */
+1 -1
arch/x86/kvm/svm.c
··· 1261 1261 1262 1262 svm->vcpu.arch.apic_base = APIC_DEFAULT_PHYS_BASE | 1263 1263 MSR_IA32_APICBASE_ENABLE; 1264 - if (kvm_vcpu_is_bsp(&svm->vcpu)) 1264 + if (kvm_vcpu_is_reset_bsp(&svm->vcpu)) 1265 1265 svm->vcpu.arch.apic_base |= MSR_IA32_APICBASE_BSP; 1266 1266 1267 1267 svm_init_osvw(&svm->vcpu);
+1 -1
arch/x86/kvm/vmx.c
··· 4706 4706 vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val(); 4707 4707 kvm_set_cr8(&vmx->vcpu, 0); 4708 4708 apic_base_msr.data = APIC_DEFAULT_PHYS_BASE | MSR_IA32_APICBASE_ENABLE; 4709 - if (kvm_vcpu_is_bsp(&vmx->vcpu)) 4709 + if (kvm_vcpu_is_reset_bsp(&vmx->vcpu)) 4710 4710 apic_base_msr.data |= MSR_IA32_APICBASE_BSP; 4711 4711 apic_base_msr.host_initiated = true; 4712 4712 kvm_set_apic_base(&vmx->vcpu, &apic_base_msr);
+1 -1
arch/x86/kvm/x86.c
··· 7269 7269 7270 7270 vcpu->arch.pv.pv_unhalted = false; 7271 7271 vcpu->arch.emulate_ctxt.ops = &emulate_ops; 7272 - if (!irqchip_in_kernel(kvm) || kvm_vcpu_is_bsp(vcpu)) 7272 + if (!irqchip_in_kernel(kvm) || kvm_vcpu_is_reset_bsp(vcpu)) 7273 7273 vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE; 7274 7274 else 7275 7275 vcpu->arch.mp_state = KVM_MP_STATE_UNINITIALIZED;
+6 -1
include/linux/kvm_host.h
··· 982 982 #endif /* CONFIG_HAVE_KVM_EVENTFD */ 983 983 984 984 #ifdef CONFIG_KVM_APIC_ARCHITECTURE 985 - static inline bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu) 985 + static inline bool kvm_vcpu_is_reset_bsp(struct kvm_vcpu *vcpu) 986 986 { 987 987 return vcpu->kvm->bsp_vcpu_id == vcpu->vcpu_id; 988 + } 989 + 990 + static inline bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu) 991 + { 992 + return (vcpu->arch.apic_base & MSR_IA32_APICBASE_BSP) != 0; 988 993 } 989 994 990 995 bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu);