From: Anish Ghulati <aghulati@google.com>
To: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
Sean Christopherson <seanjc@google.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Thomas Gleixner <tglx@linutronix.de>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
x86@kernel.org, hpa@zytor.com,
Vitaly Kuznetsov <vkuznets@redhat.com>,
peterz@infradead.org, paulmck@kernel.org,
Mark Rutland <mark.rutland@arm.com>
Cc: Anish Ghulati <aghulati@google.com>
Subject: [RFC PATCH 11/14] KVM: SVM: Move SVM enable and disable into VAC
Date: Tue, 7 Nov 2023 20:19:59 +0000 [thread overview]
Message-ID: <20231107202002.667900-12-aghulati@google.com> (raw)
In-Reply-To: <20231107202002.667900-1-aghulati@google.com>
Move SVM's hardware enable and disable into VAC.
Similar to VMX this requires a temporary call to new init and exit
functions within VAC, and moving svm_init_erratum_383 into svm_init
instead of hardware enable.
Delete __svm_exit and make svm_module_exit a noop.
Signed-off-by: Anish Ghulati <aghulati@google.com>
---
arch/x86/kvm/svm/sev.c | 2 +-
arch/x86/kvm/svm/svm.c | 129 ++----------------------------------
arch/x86/kvm/svm/svm.h | 4 +-
arch/x86/kvm/svm/svm_data.h | 23 +++++++
arch/x86/kvm/svm/vac.c | 116 ++++++++++++++++++++++++++++++++
arch/x86/kvm/svm/vac.h | 23 +++----
arch/x86/kvm/vac.h | 12 ++++
arch/x86/kvm/vmx/vac.h | 5 ++
8 files changed, 175 insertions(+), 139 deletions(-)
create mode 100644 arch/x86/kvm/svm/svm_data.h
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index b9a0a939d59f..d7b76710ab0a 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -28,6 +28,7 @@
#include "mmu.h"
#include "x86.h"
#include "svm.h"
+#include "svm_data.h"
#include "svm_ops.h"
#include "cpuid.h"
#include "trace.h"
@@ -68,7 +69,6 @@ module_param_named(debug_swap, sev_es_debug_swap_enabled, bool, 0444);
static u8 sev_enc_bit;
static DECLARE_RWSEM(sev_deactivate_lock);
static DEFINE_MUTEX(sev_bitmap_lock);
-unsigned int max_sev_asid;
static unsigned int min_sev_asid;
static unsigned long sev_me_mask;
static unsigned int nr_asids;
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index d53808d8ec37..752f769c0333 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -5,11 +5,11 @@
#include "irq.h"
#include "mmu.h"
#include "kvm_cache_regs.h"
-#include "vac.h"
#include "x86.h"
#include "smm.h"
#include "cpuid.h"
#include "pmu.h"
+#include "vac.h"
#include <linux/module.h>
#include <linux/mod_devicetable.h>
@@ -68,12 +68,6 @@ static bool erratum_383_found __read_mostly;
u32 msrpm_offsets[MSRPM_OFFSETS] __read_mostly;
-/*
- * Set osvw_len to higher value when updated Revision Guides
- * are published and we know what the new status bits are
- */
-static uint64_t osvw_len = 4, osvw_status;
-
static DEFINE_PER_CPU(u64, current_tsc_ratio);
#define X2APIC_MSR(x) (APIC_BASE_MSR + (x >> 4))
@@ -211,9 +205,6 @@ module_param(vgif, int, 0444);
static int lbrv = true;
module_param(lbrv, int, 0444);
-static int tsc_scaling = true;
-module_param(tsc_scaling, int, 0444);
-
/*
* enable / disable AVIC. Because the defaults differ for APICv
* support between VMX and SVM we cannot use module_param_named.
@@ -584,106 +575,6 @@ static void __svm_write_tsc_multiplier(u64 multiplier)
__this_cpu_write(current_tsc_ratio, multiplier);
}
-static inline void kvm_cpu_svm_disable(void)
-{
- uint64_t efer;
-
- wrmsrl(MSR_VM_HSAVE_PA, 0);
- rdmsrl(MSR_EFER, efer);
- if (efer & EFER_SVME) {
- /*
- * Force GIF=1 prior to disabling SVM, e.g. to ensure INIT and
- * NMI aren't blocked.
- */
- stgi();
- wrmsrl(MSR_EFER, efer & ~EFER_SVME);
- }
-}
-
-static void svm_emergency_disable(void)
-{
- kvm_rebooting = true;
-
- kvm_cpu_svm_disable();
-}
-
-static void svm_hardware_disable(void)
-{
- /* Make sure we clean up behind us */
- if (tsc_scaling)
- __svm_write_tsc_multiplier(SVM_TSC_RATIO_DEFAULT);
-
- kvm_cpu_svm_disable();
-
- amd_pmu_disable_virt();
-}
-
-static int svm_hardware_enable(void)
-{
-
- struct svm_cpu_data *sd;
- uint64_t efer;
- int me = raw_smp_processor_id();
-
- rdmsrl(MSR_EFER, efer);
- if (efer & EFER_SVME)
- return -EBUSY;
-
- sd = per_cpu_ptr(&svm_data, me);
- sd->asid_generation = 1;
- sd->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1;
- sd->next_asid = sd->max_asid + 1;
- sd->min_asid = max_sev_asid + 1;
-
- wrmsrl(MSR_EFER, efer | EFER_SVME);
-
- wrmsrl(MSR_VM_HSAVE_PA, sd->save_area_pa);
-
- if (static_cpu_has(X86_FEATURE_TSCRATEMSR)) {
- /*
- * Set the default value, even if we don't use TSC scaling
- * to avoid having stale value in the msr
- */
- __svm_write_tsc_multiplier(SVM_TSC_RATIO_DEFAULT);
- }
-
-
- /*
- * Get OSVW bits.
- *
- * Note that it is possible to have a system with mixed processor
- * revisions and therefore different OSVW bits. If bits are not the same
- * on different processors then choose the worst case (i.e. if erratum
- * is present on one processor and not on another then assume that the
- * erratum is present everywhere).
- */
- if (cpu_has(&boot_cpu_data, X86_FEATURE_OSVW)) {
- uint64_t len, status = 0;
- int err;
-
- len = native_read_msr_safe(MSR_AMD64_OSVW_ID_LENGTH, &err);
- if (!err)
- status = native_read_msr_safe(MSR_AMD64_OSVW_STATUS,
- &err);
-
- if (err)
- osvw_status = osvw_len = 0;
- else {
- if (len < osvw_len)
- osvw_len = len;
- osvw_status |= status;
- osvw_status &= (1ULL << osvw_len) - 1;
- }
- } else
- osvw_status = osvw_len = 0;
-
- svm_init_erratum_383();
-
- amd_pmu_enable_virt();
-
- return 0;
-}
-
static void svm_cpu_uninit(int cpu)
{
struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, cpu);
@@ -4878,14 +4769,9 @@ static int svm_vm_init(struct kvm *kvm)
return 0;
}
-static void __svm_exit(void)
-{
- cpu_emergency_unregister_virt_callback(svm_emergency_disable);
-}
-
void svm_module_exit(void)
{
- __svm_exit();
+ return;
}
static struct kvm_x86_ops svm_x86_ops __initdata = {
@@ -5325,7 +5211,8 @@ int __init svm_init(void)
if (r)
return r;
- cpu_emergency_register_virt_callback(svm_emergency_disable);
+ //TODO: Remove this init call once VAC is a module
+ vac_svm_init();
/*
* Common KVM initialization _must_ come last, after this, /dev/kvm is
@@ -5334,11 +5221,9 @@ int __init svm_init(void)
r = kvm_init(sizeof(struct vcpu_svm), __alignof__(struct vcpu_svm),
THIS_MODULE);
if (r)
- goto err_kvm_init;
+ return r;
- return 0;
+ svm_init_erratum_383();
-err_kvm_init:
- __svm_exit();
- return r;
+ return 0;
}
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 7fc652b1b92d..7bd0dc0e000f 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -24,7 +24,7 @@
#include "cpuid.h"
#include "kvm_cache_regs.h"
-#include "vac.h"
+#include "svm_data.h"
#define __sme_page_pa(x) __sme_set(page_to_pfn(x) << PAGE_SHIFT)
@@ -651,8 +651,6 @@ void avic_refresh_virtual_apic_mode(struct kvm_vcpu *vcpu);
#define GHCB_VERSION_MIN 1ULL
-extern unsigned int max_sev_asid;
-
void sev_vm_destroy(struct kvm *kvm);
int sev_mem_enc_ioctl(struct kvm *kvm, void __user *argp);
int sev_mem_enc_register_region(struct kvm *kvm,
diff --git a/arch/x86/kvm/svm/svm_data.h b/arch/x86/kvm/svm/svm_data.h
new file mode 100644
index 000000000000..9605807fc9d4
--- /dev/null
+++ b/arch/x86/kvm/svm/svm_data.h
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#ifndef ARCH_X86_KVM_SVM_DATA_H
+#define ARCH_X86_KVM_SVM_DATA_H
+
+struct svm_cpu_data {
+ u64 asid_generation;
+ u32 max_asid;
+ u32 next_asid;
+ u32 min_asid;
+
+ struct page *save_area;
+ unsigned long save_area_pa;
+
+ struct vmcb *current_vmcb;
+
+ /* index = sev_asid, value = vmcb pointer */
+ struct vmcb **sev_vmcbs;
+};
+
+extern unsigned int max_sev_asid;
+
+#endif // ARCH_X86_KVM_SVM_DATA_H
diff --git a/arch/x86/kvm/svm/vac.c b/arch/x86/kvm/svm/vac.c
index 3e79279c6b34..2dd1c763f7d6 100644
--- a/arch/x86/kvm/svm/vac.c
+++ b/arch/x86/kvm/svm/vac.c
@@ -1,7 +1,123 @@
// SPDX-License-Identifier: GPL-2.0-only
+#include <asm/reboot.h>
+#include <asm/svm.h>
#include <linux/percpu-defs.h>
+#include "svm_ops.h"
#include "vac.h"
DEFINE_PER_CPU(struct svm_cpu_data, svm_data);
+unsigned int max_sev_asid;
+
+static inline void kvm_cpu_svm_disable(void)
+{
+ uint64_t efer;
+
+ wrmsrl(MSR_VM_HSAVE_PA, 0);
+ rdmsrl(MSR_EFER, efer);
+ if (efer & EFER_SVME) {
+ /*
+ * Force GIF=1 prior to disabling SVM, e.g. to ensure INIT and
+ * NMI aren't blocked.
+ */
+ stgi();
+ wrmsrl(MSR_EFER, efer & ~EFER_SVME);
+ }
+}
+
+static void svm_emergency_disable(void)
+{
+ kvm_rebooting = true;
+
+ kvm_cpu_svm_disable();
+}
+
+void svm_hardware_disable(void)
+{
+ /* Make sure we clean up behind us */
+ if (tsc_scaling)
+ // TODO: Fix everything TSC
+ // __svm_write_tsc_multiplier(SVM_TSC_RATIO_DEFAULT);
+
+ kvm_cpu_svm_disable();
+
+ amd_pmu_disable_virt();
+}
+
+int svm_hardware_enable(void)
+{
+
+ struct svm_cpu_data *sd;
+ uint64_t efer;
+ int me = raw_smp_processor_id();
+
+ rdmsrl(MSR_EFER, efer);
+ if (efer & EFER_SVME)
+ return -EBUSY;
+
+ sd = per_cpu_ptr(&svm_data, me);
+ sd->asid_generation = 1;
+ sd->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1;
+ sd->next_asid = sd->max_asid + 1;
+ sd->min_asid = max_sev_asid + 1;
+
+ wrmsrl(MSR_EFER, efer | EFER_SVME);
+
+ wrmsrl(MSR_VM_HSAVE_PA, sd->save_area_pa);
+
+ if (static_cpu_has(X86_FEATURE_TSCRATEMSR)) {
+ /*
+ * Set the default value, even if we don't use TSC scaling
+ * to avoid having stale value in the msr
+ */
+ // TODO: Fix everything TSC
+ // __svm_write_tsc_multiplier(SVM_TSC_RATIO_DEFAULT);
+ }
+
+
+ /*
+ * Get OSVW bits.
+ *
+ * Note that it is possible to have a system with mixed processor
+ * revisions and therefore different OSVW bits. If bits are not the same
+ * on different processors then choose the worst case (i.e. if erratum
+ * is present on one processor and not on another then assume that the
+ * erratum is present everywhere).
+ */
+ if (cpu_has(&boot_cpu_data, X86_FEATURE_OSVW)) {
+ uint64_t len, status = 0;
+ int err;
+
+ len = native_read_msr_safe(MSR_AMD64_OSVW_ID_LENGTH, &err);
+ if (!err)
+ status = native_read_msr_safe(MSR_AMD64_OSVW_STATUS,
+ &err);
+
+ if (err)
+ osvw_status = osvw_len = 0;
+ else {
+ if (len < osvw_len)
+ osvw_len = len;
+ osvw_status |= status;
+ osvw_status &= (1ULL << osvw_len) - 1;
+ }
+ } else
+ osvw_status = osvw_len = 0;
+
+ amd_pmu_enable_virt();
+
+ return 0;
+}
+
+int __init vac_svm_init(void)
+{
+ cpu_emergency_register_virt_callback(svm_emergency_disable);
+
+ return 0;
+}
+
+void vac_svm_exit(void)
+{
+ cpu_emergency_unregister_virt_callback(svm_emergency_disable);
+}
diff --git a/arch/x86/kvm/svm/vac.h b/arch/x86/kvm/svm/vac.h
index 2d42e4472703..870cb8a9c8d2 100644
--- a/arch/x86/kvm/svm/vac.h
+++ b/arch/x86/kvm/svm/vac.h
@@ -1,23 +1,20 @@
// SPDX-License-Identifier: GPL-2.0-only
-//
+
#ifndef ARCH_X86_KVM_SVM_VAC_H
#define ARCH_X86_KVM_SVM_VAC_H
#include "../vac.h"
+#include "svm_data.h"
-struct svm_cpu_data {
- u64 asid_generation;
- u32 max_asid;
- u32 next_asid;
- u32 min_asid;
-
- struct page *save_area;
- unsigned long save_area_pa;
+static int tsc_scaling = true;
- struct vmcb *current_vmcb;
+/*
+ * Set osvw_len to higher value when updated Revision Guides
+ * are published and we know what the new status bits are
+ */
+static uint64_t osvw_len = 4, osvw_status;
- /* index = sev_asid, value = vmcb pointer */
- struct vmcb **sev_vmcbs;
-};
+int svm_hardware_enable(void);
+void svm_hardware_disable(void);
#endif // ARCH_X86_KVM_SVM_VAC_H
diff --git a/arch/x86/kvm/vac.h b/arch/x86/kvm/vac.h
index 59cbf36ff8ce..6c0a480ee9e3 100644
--- a/arch/x86/kvm/vac.h
+++ b/arch/x86/kvm/vac.h
@@ -19,6 +19,18 @@ int __init vac_vmx_init(void)
void vac_vmx_exit(void) {}
#endif
+#ifdef CONFIG_KVM_AMD
+int __init vac_svm_init(void);
+void vac_svm_exit(void);
+#else
+int __init vac_svm_init(void)
+{
+ return 0;
+}
+void vac_svm_exit(void) {}
+#endif
+
+
/*
* Restoring the host value for MSRs that are only consumed when running in
* usermode, e.g. SYSCALL MSRs and TSC_AUX, can be deferred until the CPU
diff --git a/arch/x86/kvm/vmx/vac.h b/arch/x86/kvm/vmx/vac.h
index daeea8ef0d33..d5af0ca67e3f 100644
--- a/arch/x86/kvm/vmx/vac.h
+++ b/arch/x86/kvm/vmx/vac.h
@@ -1,5 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
+#ifndef ARCH_X86_KVM_VMX_VAC_H
+#define ARCH_X86_KVM_VMX_VAC_H
+
#include <asm/vmx.h>
#include "../vac.h"
@@ -15,3 +18,5 @@ void add_vmcs_to_loaded_vmcss_on_cpu(
void loaded_vmcs_clear(struct loaded_vmcs *loaded_vmcs);
int vmx_hardware_enable(void);
void vmx_hardware_disable(void);
+
+#endif // ARCH_X86_KVM_VMX_VAC_H
--
2.42.0.869.gea05f2083d-goog
next prev parent reply other threads:[~2023-11-07 20:20 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-07 20:19 [RFC PATCH 00/14] Support multiple KVM modules on the same host Anish Ghulati
2023-11-07 20:19 ` [RFC PATCH 01/14] KVM: x86: Move common module params from SVM/VMX to x86 Anish Ghulati
2023-11-07 20:19 ` [RFC PATCH 02/14] KVM: x86: Fold x86 vendor modules into the main KVM modules Anish Ghulati
2023-11-07 20:19 ` [RFC PATCH 03/14] KVM: x86: Remove unused exports Anish Ghulati
2023-11-07 20:19 ` [RFC PATCH 04/14] KVM: x86: Create stubs for a new VAC module Anish Ghulati
2023-11-07 20:19 ` [RFC PATCH 05/14] KVM: x86: Refactor hardware enable/disable operations into a new file Anish Ghulati
2023-11-07 20:19 ` [RFC PATCH 06/14] KVM: x86: Move user return msr operations out of KVM Anish Ghulati
2023-11-07 20:19 ` [RFC PATCH 07/14] KVM: SVM: Move shared SVM data structures into VAC Anish Ghulati
2023-11-07 20:19 ` [RFC PATCH 08/14] KVM: VMX: Move shared VMX " Anish Ghulati
2023-11-07 20:19 ` [RFC PATCH 09/14] KVM: x86: Move shared KVM state " Anish Ghulati
2023-11-17 8:54 ` Lai Jiangshan
2023-11-28 18:01 ` Sean Christopherson
2023-11-07 20:19 ` [RFC PATCH 10/14] KVM: VMX: Move VMX enable and disable " Anish Ghulati
2023-11-07 20:19 ` Anish Ghulati [this message]
2023-11-07 20:20 ` [RFC PATCH 12/14] KVM: x86: Move VMX and SVM support checks " Anish Ghulati
2023-11-07 20:20 ` [RFC PATCH 13/14] KVM: x86: VAC: Move all hardware enable/disable code " Anish Ghulati
2023-11-07 20:20 ` [RFC PATCH 14/14] KVM: VAC: Bring up VAC as a new module Anish Ghulati
2023-11-17 8:53 ` [RFC PATCH 00/14] Support multiple KVM modules on the same host Lai Jiangshan
2023-11-28 18:10 ` Sean Christopherson
2026-01-05 7:48 ` Hou Wenlong
2026-01-07 15:54 ` Sean Christopherson
2026-01-08 6:55 ` Hou Wenlong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231107202002.667900-12-aghulati@google.com \
--to=aghulati@google.com \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=hpa@zytor.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=mingo@redhat.com \
--cc=paulmck@kernel.org \
--cc=pbonzini@redhat.com \
--cc=peterz@infradead.org \
--cc=seanjc@google.com \
--cc=tglx@linutronix.de \
--cc=vkuznets@redhat.com \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox