There is use case to get pcpu id during pKVM runtime, especially within exception/irq context when it cannot get such information from current host vcpu. Use MSR_GS_BASE to record pcpu_id, and enable pKVM to get pcpu_id during its runtime. It is prepared for nmi handler, as when CPU is running in pKVM hypervisor, nmi is not able to block, so pKVM need to appropriately inject it back to host vcpu to avoid nmi lost. When nmi happen, its handler doesn't have context which host vcpu it shall do the following injection. get_pcpu_id() here can help the nmi handler get corresponding host vcpu. Signed-off-by: Jason Chen CJ <jason.cj.chen@xxxxxxxxx> --- arch/x86/kvm/vmx/pkvm/hyp/cpu.h | 30 ++++++++++++++++++++++++++++++ arch/x86/kvm/vmx/pkvm/pkvm_host.c | 12 +++++++----- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/vmx/pkvm/hyp/cpu.h b/arch/x86/kvm/vmx/pkvm/hyp/cpu.h new file mode 100644 index 000000000000..c49074292f7c --- /dev/null +++ b/arch/x86/kvm/vmx/pkvm/hyp/cpu.h @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 Intel Corporation + */ +#ifndef _PKVM_CPU_H_ +#define _PKVM_CPU_H_ + +static inline u64 pkvm_msr_read(u32 reg) +{ + u32 msrl, msrh; + + asm volatile (" rdmsr ":"=a"(msrl), "=d"(msrh) : "c" (reg)); + return (((u64)msrh << 32U) | msrl); +} + +#ifdef CONFIG_PKVM_INTEL_DEBUG +#include <linux/smp.h> +static inline u64 get_pcpu_id(void) +{ + return raw_smp_processor_id(); +} +#else +/* this function shall only be used during pkvm runtime */ +static inline u64 get_pcpu_id(void) +{ + return pkvm_msr_read(MSR_GS_BASE); +} +#endif + +#endif diff --git a/arch/x86/kvm/vmx/pkvm/pkvm_host.c b/arch/x86/kvm/vmx/pkvm/pkvm_host.c index c7768ee22e57..77cd7b654168 100644 --- a/arch/x86/kvm/vmx/pkvm/pkvm_host.c +++ b/arch/x86/kvm/vmx/pkvm/pkvm_host.c @@ -240,14 +240,13 @@ static __init void init_guest_state_area(struct pkvm_host_vcpu *vcpu, int cpu) vmcs_write64(VMCS_LINK_POINTER, -1ull); } -static __init void _init_host_state_area(struct pkvm_pcpu *pcpu) +static __init void _init_host_state_area(struct pkvm_pcpu *pcpu, int cpu) { unsigned long a; #ifdef CONFIG_PKVM_INTEL_DEBUG u32 high, low; struct desc_ptr dt; u16 selector; - int cpu = raw_smp_processor_id(); #endif vmcs_writel(HOST_CR0, read_cr0() & ~X86_CR0_TS); @@ -302,6 +301,9 @@ static __init void _init_host_state_area(struct pkvm_pcpu *pcpu) vmcs_writel(HOST_TR_BASE, (unsigned long)&pcpu->tss); vmcs_writel(HOST_GDTR_BASE, (unsigned long)(&pcpu->gdt_page)); vmcs_writel(HOST_IDTR_BASE, (unsigned long)(&pcpu->idt_page)); + + vmcs_write16(HOST_GS_SELECTOR, __KERNEL_DS); + vmcs_writel(HOST_GS_BASE, cpu); #endif /* MSR area */ @@ -312,11 +314,11 @@ static __init void _init_host_state_area(struct pkvm_pcpu *pcpu) vmcs_write64(HOST_IA32_PAT, a); } -static __init void init_host_state_area(struct pkvm_host_vcpu *vcpu) +static __init void init_host_state_area(struct pkvm_host_vcpu *vcpu, int cpu) { struct pkvm_pcpu *pcpu = vcpu->pcpu; - _init_host_state_area(pcpu); + _init_host_state_area(pcpu, cpu); /*host RIP*/ vmcs_writel(HOST_RIP, (unsigned long)pkvm_sym(__pkvm_vmx_vmexit)); @@ -403,7 +405,7 @@ static __init int pkvm_host_init_vmx(struct pkvm_host_vcpu *vcpu, int cpu) vmcs_load(vmx->loaded_vmcs->vmcs); init_guest_state_area(vcpu, cpu); - init_host_state_area(vcpu); + init_host_state_area(vcpu, cpu); init_execution_control(vmx, &pkvm->vmcs_config, &pkvm->vmx_cap); init_vmexit_control(vmx, &pkvm->vmcs_config); init_vmentry_control(vmx, &pkvm->vmcs_config); -- 2.25.1