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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.