[RFC PATCH part-4 3/4] pkvm: x86: Support get_pcpu_id

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux