* [PATCH v3 00/11] KVM: SVM: fixes for vmentry code
@ 2022-11-09 14:51 Paolo Bonzini
2022-11-09 14:51 ` [PATCH 01/11] KVM: x86: use a separate asm-offsets.c file Paolo Bonzini
` (10 more replies)
0 siblings, 11 replies; 24+ messages in thread
From: Paolo Bonzini @ 2022-11-09 14:51 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: thomas.lendacky, jmattson, seanjc
This series comprises two related fixes:
- the FILL_RETURN_BUFFER macro in -next needs to access percpu data,
hence the GS segment base needs to be loaded before FILL_RETURN_BUFFER.
This means moving guest vmload/vmsave and host vmload to assembly
(patches 8 and 9).
- because AMD wants the OS to set STIBP to 1 before executing the
return thunk (un)training sequence, IA32_SPEC_CTRL must be restored
before UNTRAIN_RET, too. This must also be moved to assembly and,
for consistency, the guest SPEC_CTRL is also loaded in there
(patch 10).
Neither is particularly hard, however because of 32-bit systems one needs
to keep the number of arguments to __svm_vcpu_run to three or fewer.
Therefore, patches 2 to 7 move various accesses to the vcpu_svm struct
and to percpu data to vmenter.S, cleaning up various bits along the way
to keep the assembly code nice. I think the code is simpler than before
after these prerequisites, and even at the end of the series it is not
much harder to follow despite doing a lot more stuff. Care has been
taken to keep the "normal" and SEV-ES code as similar as possible,
even though the latter would not hit the three argument barrier; even
the prototype is the same.
The above summary leaves patch 1, which introduces a separate asm-offsets.c
file for KVM, so that kernel/asm-offsets.c does not have to do ugly includes
with ../ paths; and patch 11, which is just more dead code removal.
Thanks,
Paolo
v2->v3: store SME-adjusted save_area physical address in svm_cpu_data,
access it with PER_CPU_VAR instead of an argument [Sean, sort of]
split out-of-line spec-ctrl restore macro in two parts [Sean]
adjust comments to point out clobbered registers [Sean]
Paolo Bonzini (11):
KVM: x86: use a separate asm-offsets.c file
KVM: SVM: replace regs argument of __svm_vcpu_run with vcpu_svm
KVM: SVM: adjust register allocation for __svm_vcpu_run
KVM: SVM: retrieve VMCB from assembly
KVM: SVM: remove unused field from struct vcpu_svm
KVM: SVM: remove dead field from struct svm_cpu_data
KVM: SVM: do not allocate struct svm_cpu_data dynamically
KVM: SVM: move guest vmsave/vmload back to assembly
KVM: SVM: restore host save area from assembly
KVM: SVM: move MSR_IA32_SPEC_CTRL save/restore to assembly
x86, KVM: remove unnecessary argument to x86_virt_spec_ctrl and
callers
arch/x86/include/asm/spec-ctrl.h | 10 +-
arch/x86/kernel/asm-offsets.c | 6 -
arch/x86/kernel/cpu/bugs.c | 15 +-
arch/x86/kvm/.gitignore | 2 +
arch/x86/kvm/Makefile | 12 ++
arch/x86/kvm/kvm-asm-offsets.c | 29 ++++
arch/x86/kvm/svm/sev.c | 4 +-
arch/x86/kvm/svm/svm.c | 105 +++++--------
arch/x86/kvm/svm/svm.h | 11 +-
arch/x86/kvm/svm/svm_ops.h | 5 -
arch/x86/kvm/svm/vmenter.S | 260 +++++++++++++++++++++++++------
arch/x86/kvm/vmx/vmenter.S | 2 +-
12 files changed, 305 insertions(+), 156 deletions(-)
create mode 100644 arch/x86/kvm/.gitignore
create mode 100644 arch/x86/kvm/kvm-asm-offsets.c
--
2.31.1
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 01/11] KVM: x86: use a separate asm-offsets.c file
2022-11-09 14:51 [PATCH v3 00/11] KVM: SVM: fixes for vmentry code Paolo Bonzini
@ 2022-11-09 14:51 ` Paolo Bonzini
2022-11-09 15:06 ` Sean Christopherson
2022-11-09 14:51 ` [PATCH 02/11] KVM: SVM: replace regs argument of __svm_vcpu_run with vcpu_svm Paolo Bonzini
` (9 subsequent siblings)
10 siblings, 1 reply; 24+ messages in thread
From: Paolo Bonzini @ 2022-11-09 14:51 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: thomas.lendacky, jmattson, seanjc, stable
This already removes the ugly #includes from asm-offsets.c, but especially
it avoids a future error when asm-offsets will try to include svm/svm.h.
This would not work for kernel/asm-offsets.c, because svm/svm.h
includes kvm_cache_regs.h which is not in the include path when
compiling asm-offsets.c. The problem is not there if the .c file is
in arch/x86/kvm.
Suggested-by: Sean Christopherson <seanjc@google.com>
Cc: stable@vger.kernel.org
Fixes: a149180fbcf3 ("x86: Add magic AMD return-thunk")
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kernel/asm-offsets.c | 6 ------
arch/x86/kvm/.gitignore | 2 ++
arch/x86/kvm/Makefile | 9 +++++++++
arch/x86/kvm/kvm-asm-offsets.c | 18 ++++++++++++++++++
arch/x86/kvm/vmx/vmenter.S | 2 +-
5 files changed, 30 insertions(+), 7 deletions(-)
create mode 100644 arch/x86/kvm/.gitignore
create mode 100644 arch/x86/kvm/kvm-asm-offsets.c
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index cb50589a7102..437308004ef2 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -19,7 +19,6 @@
#include <asm/suspend.h>
#include <asm/tlbflush.h>
#include <asm/tdx.h>
-#include "../kvm/vmx/vmx.h"
#ifdef CONFIG_XEN
#include <xen/interface/xen.h>
@@ -108,9 +107,4 @@ static void __used common(void)
OFFSET(TSS_sp0, tss_struct, x86_tss.sp0);
OFFSET(TSS_sp1, tss_struct, x86_tss.sp1);
OFFSET(TSS_sp2, tss_struct, x86_tss.sp2);
-
- if (IS_ENABLED(CONFIG_KVM_INTEL)) {
- BLANK();
- OFFSET(VMX_spec_ctrl, vcpu_vmx, spec_ctrl);
- }
}
diff --git a/arch/x86/kvm/.gitignore b/arch/x86/kvm/.gitignore
new file mode 100644
index 000000000000..615d6ff35c00
--- /dev/null
+++ b/arch/x86/kvm/.gitignore
@@ -0,0 +1,2 @@
+/kvm-asm-offsets.s
+/kvm-asm-offsets.h
diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
index 30f244b64523..a02cf9baacc8 100644
--- a/arch/x86/kvm/Makefile
+++ b/arch/x86/kvm/Makefile
@@ -34,3 +34,12 @@ endif
obj-$(CONFIG_KVM) += kvm.o
obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
obj-$(CONFIG_KVM_AMD) += kvm-amd.o
+
+AFLAGS_vmx/vmenter.o := -iquote $(obj)
+$(obj)/vmx/vmenter.o: $(obj)/kvm-asm-offsets.h
+
+$(obj)/kvm-asm-offsets.h: $(obj)/kvm-asm-offsets.s FORCE
+ $(call filechk,offsets,__KVM_ASM_OFFSETS_H__)
+
+targets += kvm-asm-offsets.s
+clean-files += kvm-asm-offsets.h
diff --git a/arch/x86/kvm/kvm-asm-offsets.c b/arch/x86/kvm/kvm-asm-offsets.c
new file mode 100644
index 000000000000..9d84f2b32d7f
--- /dev/null
+++ b/arch/x86/kvm/kvm-asm-offsets.c
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Generate definitions needed by assembly language modules.
+ * This code generates raw asm output which is post-processed to extract
+ * and format the required data.
+ */
+#define COMPILE_OFFSETS
+
+#include <linux/kbuild.h>
+#include "vmx/vmx.h"
+
+static void __used common(void)
+{
+ if (IS_ENABLED(CONFIG_KVM_INTEL)) {
+ BLANK();
+ OFFSET(VMX_spec_ctrl, vcpu_vmx, spec_ctrl);
+ }
+}
diff --git a/arch/x86/kvm/vmx/vmenter.S b/arch/x86/kvm/vmx/vmenter.S
index 8477d8bdd69c..0b5db4de4d09 100644
--- a/arch/x86/kvm/vmx/vmenter.S
+++ b/arch/x86/kvm/vmx/vmenter.S
@@ -1,12 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/linkage.h>
#include <asm/asm.h>
-#include <asm/asm-offsets.h>
#include <asm/bitsperlong.h>
#include <asm/kvm_vcpu_regs.h>
#include <asm/nospec-branch.h>
#include <asm/percpu.h>
#include <asm/segment.h>
+#include "kvm-asm-offsets.h"
#include "run_flags.h"
#define WORD_SIZE (BITS_PER_LONG / 8)
--
2.31.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 02/11] KVM: SVM: replace regs argument of __svm_vcpu_run with vcpu_svm
2022-11-09 14:51 [PATCH v3 00/11] KVM: SVM: fixes for vmentry code Paolo Bonzini
2022-11-09 14:51 ` [PATCH 01/11] KVM: x86: use a separate asm-offsets.c file Paolo Bonzini
@ 2022-11-09 14:51 ` Paolo Bonzini
2022-11-09 15:14 ` Sean Christopherson
2022-11-09 14:51 ` [PATCH 03/11] KVM: SVM: adjust register allocation for __svm_vcpu_run Paolo Bonzini
` (8 subsequent siblings)
10 siblings, 1 reply; 24+ messages in thread
From: Paolo Bonzini @ 2022-11-09 14:51 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: thomas.lendacky, jmattson, seanjc, stable
Since registers are reachable through vcpu_svm, and we will
need to access more fields of that struct, pass it instead
of the regs[] array.
No functional change intended.
Cc: stable@vger.kernel.org
Fixes: a149180fbcf3 ("x86: Add magic AMD return-thunk")
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/Makefile | 3 +++
arch/x86/kvm/kvm-asm-offsets.c | 6 ++++++
arch/x86/kvm/svm/svm.c | 2 +-
arch/x86/kvm/svm/svm.h | 2 +-
arch/x86/kvm/svm/vmenter.S | 37 +++++++++++++++++-----------------
5 files changed, 30 insertions(+), 20 deletions(-)
diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
index a02cf9baacc8..f453a0f96e24 100644
--- a/arch/x86/kvm/Makefile
+++ b/arch/x86/kvm/Makefile
@@ -35,6 +35,9 @@ obj-$(CONFIG_KVM) += kvm.o
obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
obj-$(CONFIG_KVM_AMD) += kvm-amd.o
+AFLAGS_svm/vmenter.o := -iquote $(obj)
+$(obj)/svm/vmenter.o: $(obj)/kvm-asm-offsets.h
+
AFLAGS_vmx/vmenter.o := -iquote $(obj)
$(obj)/vmx/vmenter.o: $(obj)/kvm-asm-offsets.h
diff --git a/arch/x86/kvm/kvm-asm-offsets.c b/arch/x86/kvm/kvm-asm-offsets.c
index 9d84f2b32d7f..30db96852e2d 100644
--- a/arch/x86/kvm/kvm-asm-offsets.c
+++ b/arch/x86/kvm/kvm-asm-offsets.c
@@ -8,9 +8,15 @@
#include <linux/kbuild.h>
#include "vmx/vmx.h"
+#include "svm/svm.h"
static void __used common(void)
{
+ if (IS_ENABLED(CONFIG_KVM_AMD)) {
+ BLANK();
+ OFFSET(SVM_vcpu_arch_regs, vcpu_svm, vcpu.arch.regs);
+ }
+
if (IS_ENABLED(CONFIG_KVM_INTEL)) {
BLANK();
OFFSET(VMX_spec_ctrl, vcpu_vmx, spec_ctrl);
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 58f0077d9357..b412bc5773c5 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -3930,7 +3930,7 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu)
* vmcb02 when switching vmcbs for nested virtualization.
*/
vmload(svm->vmcb01.pa);
- __svm_vcpu_run(vmcb_pa, (unsigned long *)&vcpu->arch.regs);
+ __svm_vcpu_run(vmcb_pa, svm);
vmsave(svm->vmcb01.pa);
vmload(__sme_page_pa(sd->save_area));
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 6a7686bf6900..447e25c9101a 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -684,6 +684,6 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm);
/* vmenter.S */
void __svm_sev_es_vcpu_run(unsigned long vmcb_pa);
-void __svm_vcpu_run(unsigned long vmcb_pa, unsigned long *regs);
+void __svm_vcpu_run(unsigned long vmcb_pa, struct vcpu_svm *svm);
#endif
diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S
index 723f8534986c..f0ff41103e4c 100644
--- a/arch/x86/kvm/svm/vmenter.S
+++ b/arch/x86/kvm/svm/vmenter.S
@@ -4,27 +4,28 @@
#include <asm/bitsperlong.h>
#include <asm/kvm_vcpu_regs.h>
#include <asm/nospec-branch.h>
+#include "kvm-asm-offsets.h"
#define WORD_SIZE (BITS_PER_LONG / 8)
/* Intentionally omit RAX as it's context switched by hardware */
-#define VCPU_RCX __VCPU_REGS_RCX * WORD_SIZE
-#define VCPU_RDX __VCPU_REGS_RDX * WORD_SIZE
-#define VCPU_RBX __VCPU_REGS_RBX * WORD_SIZE
+#define VCPU_RCX (SVM_vcpu_arch_regs + __VCPU_REGS_RCX * WORD_SIZE)
+#define VCPU_RDX (SVM_vcpu_arch_regs + __VCPU_REGS_RDX * WORD_SIZE)
+#define VCPU_RBX (SVM_vcpu_arch_regs + __VCPU_REGS_RBX * WORD_SIZE)
/* Intentionally omit RSP as it's context switched by hardware */
-#define VCPU_RBP __VCPU_REGS_RBP * WORD_SIZE
-#define VCPU_RSI __VCPU_REGS_RSI * WORD_SIZE
-#define VCPU_RDI __VCPU_REGS_RDI * WORD_SIZE
+#define VCPU_RBP (SVM_vcpu_arch_regs + __VCPU_REGS_RBP * WORD_SIZE)
+#define VCPU_RSI (SVM_vcpu_arch_regs + __VCPU_REGS_RSI * WORD_SIZE)
+#define VCPU_RDI (SVM_vcpu_arch_regs + __VCPU_REGS_RDI * WORD_SIZE)
#ifdef CONFIG_X86_64
-#define VCPU_R8 __VCPU_REGS_R8 * WORD_SIZE
-#define VCPU_R9 __VCPU_REGS_R9 * WORD_SIZE
-#define VCPU_R10 __VCPU_REGS_R10 * WORD_SIZE
-#define VCPU_R11 __VCPU_REGS_R11 * WORD_SIZE
-#define VCPU_R12 __VCPU_REGS_R12 * WORD_SIZE
-#define VCPU_R13 __VCPU_REGS_R13 * WORD_SIZE
-#define VCPU_R14 __VCPU_REGS_R14 * WORD_SIZE
-#define VCPU_R15 __VCPU_REGS_R15 * WORD_SIZE
+#define VCPU_R8 (SVM_vcpu_arch_regs + __VCPU_REGS_R8 * WORD_SIZE)
+#define VCPU_R9 (SVM_vcpu_arch_regs + __VCPU_REGS_R9 * WORD_SIZE)
+#define VCPU_R10 (SVM_vcpu_arch_regs + __VCPU_REGS_R10 * WORD_SIZE)
+#define VCPU_R11 (SVM_vcpu_arch_regs + __VCPU_REGS_R11 * WORD_SIZE)
+#define VCPU_R12 (SVM_vcpu_arch_regs + __VCPU_REGS_R12 * WORD_SIZE)
+#define VCPU_R13 (SVM_vcpu_arch_regs + __VCPU_REGS_R13 * WORD_SIZE)
+#define VCPU_R14 (SVM_vcpu_arch_regs + __VCPU_REGS_R14 * WORD_SIZE)
+#define VCPU_R15 (SVM_vcpu_arch_regs + __VCPU_REGS_R15 * WORD_SIZE)
#endif
.section .noinstr.text, "ax"
@@ -32,7 +33,7 @@
/**
* __svm_vcpu_run - Run a vCPU via a transition to SVM guest mode
* @vmcb_pa: unsigned long
- * @regs: unsigned long * (to guest registers)
+ * @svm: struct vcpu_svm *
*/
SYM_FUNC_START(__svm_vcpu_run)
push %_ASM_BP
@@ -47,13 +48,13 @@ SYM_FUNC_START(__svm_vcpu_run)
#endif
push %_ASM_BX
- /* Save @regs. */
+ /* Save @svm. */
push %_ASM_ARG2
/* Save @vmcb. */
push %_ASM_ARG1
- /* Move @regs to RAX. */
+ /* Move @svm to RAX. */
mov %_ASM_ARG2, %_ASM_AX
/* Load guest registers. */
@@ -89,7 +90,7 @@ SYM_FUNC_START(__svm_vcpu_run)
FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE
#endif
- /* "POP" @regs to RAX. */
+ /* "POP" @svm to RAX. */
pop %_ASM_AX
/* Save all guest registers. */
--
2.31.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 03/11] KVM: SVM: adjust register allocation for __svm_vcpu_run
2022-11-09 14:51 [PATCH v3 00/11] KVM: SVM: fixes for vmentry code Paolo Bonzini
2022-11-09 14:51 ` [PATCH 01/11] KVM: x86: use a separate asm-offsets.c file Paolo Bonzini
2022-11-09 14:51 ` [PATCH 02/11] KVM: SVM: replace regs argument of __svm_vcpu_run with vcpu_svm Paolo Bonzini
@ 2022-11-09 14:51 ` Paolo Bonzini
2022-11-09 15:20 ` Sean Christopherson
2022-11-09 14:51 ` [PATCH 04/11] KVM: SVM: retrieve VMCB from assembly Paolo Bonzini
` (7 subsequent siblings)
10 siblings, 1 reply; 24+ messages in thread
From: Paolo Bonzini @ 2022-11-09 14:51 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: thomas.lendacky, jmattson, seanjc, stable
In preparation for moving vmload/vmsave to __svm_vcpu_run,
keep the pointer to the struct vcpu_svm in %rdi. This way
it is possible to load svm->vmcb01.pa in %rax without
clobbering the pointer to svm itself.
No functional change intended.
Cc: stable@vger.kernel.org
Fixes: a149180fbcf3 ("x86: Add magic AMD return-thunk")
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/svm/vmenter.S | 38 +++++++++++++++++++-------------------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S
index f0ff41103e4c..531510ab6072 100644
--- a/arch/x86/kvm/svm/vmenter.S
+++ b/arch/x86/kvm/svm/vmenter.S
@@ -54,29 +54,29 @@ SYM_FUNC_START(__svm_vcpu_run)
/* Save @vmcb. */
push %_ASM_ARG1
- /* Move @svm to RAX. */
- mov %_ASM_ARG2, %_ASM_AX
+ /* Move @svm to RDI. */
+ mov %_ASM_ARG2, %_ASM_DI
+
+ /* "POP" @vmcb to RAX. */
+ pop %_ASM_AX
/* Load guest registers. */
- mov VCPU_RCX(%_ASM_AX), %_ASM_CX
- mov VCPU_RDX(%_ASM_AX), %_ASM_DX
- mov VCPU_RBX(%_ASM_AX), %_ASM_BX
- mov VCPU_RBP(%_ASM_AX), %_ASM_BP
- mov VCPU_RSI(%_ASM_AX), %_ASM_SI
- mov VCPU_RDI(%_ASM_AX), %_ASM_DI
+ mov VCPU_RCX(%_ASM_DI), %_ASM_CX
+ mov VCPU_RDX(%_ASM_DI), %_ASM_DX
+ mov VCPU_RBX(%_ASM_DI), %_ASM_BX
+ mov VCPU_RBP(%_ASM_DI), %_ASM_BP
+ mov VCPU_RSI(%_ASM_DI), %_ASM_SI
#ifdef CONFIG_X86_64
- mov VCPU_R8 (%_ASM_AX), %r8
- mov VCPU_R9 (%_ASM_AX), %r9
- mov VCPU_R10(%_ASM_AX), %r10
- mov VCPU_R11(%_ASM_AX), %r11
- mov VCPU_R12(%_ASM_AX), %r12
- mov VCPU_R13(%_ASM_AX), %r13
- mov VCPU_R14(%_ASM_AX), %r14
- mov VCPU_R15(%_ASM_AX), %r15
+ mov VCPU_R8 (%_ASM_DI), %r8
+ mov VCPU_R9 (%_ASM_DI), %r9
+ mov VCPU_R10(%_ASM_DI), %r10
+ mov VCPU_R11(%_ASM_DI), %r11
+ mov VCPU_R12(%_ASM_DI), %r12
+ mov VCPU_R13(%_ASM_DI), %r13
+ mov VCPU_R14(%_ASM_DI), %r14
+ mov VCPU_R15(%_ASM_DI), %r15
#endif
-
- /* "POP" @vmcb to RAX. */
- pop %_ASM_AX
+ mov VCPU_RDI(%_ASM_DI), %_ASM_DI
/* Enter guest mode */
sti
--
2.31.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 04/11] KVM: SVM: retrieve VMCB from assembly
2022-11-09 14:51 [PATCH v3 00/11] KVM: SVM: fixes for vmentry code Paolo Bonzini
` (2 preceding siblings ...)
2022-11-09 14:51 ` [PATCH 03/11] KVM: SVM: adjust register allocation for __svm_vcpu_run Paolo Bonzini
@ 2022-11-09 14:51 ` Paolo Bonzini
2022-11-09 15:25 ` Sean Christopherson
2022-11-09 14:51 ` [PATCH 05/11] KVM: SVM: remove unused field from struct vcpu_svm Paolo Bonzini
` (6 subsequent siblings)
10 siblings, 1 reply; 24+ messages in thread
From: Paolo Bonzini @ 2022-11-09 14:51 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: thomas.lendacky, jmattson, seanjc, stable
Continue moving all accesses to struct vcpu_svm directly in vmenter.S.
This limits the confusion due to different registers used for
argument passing in 32- and 64-bit ABIs.
It is not strictly necessary for __svm_sev_es_vcpu_run, but staying
consistent is a good idea since it makes __svm_sev_es_vcpu_run a
stripped version of _svm_vcpu_run.
No functional change intended.
Cc: stable@vger.kernel.org
Fixes: a149180fbcf3 ("x86: Add magic AMD return-thunk")
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/kvm-asm-offsets.c | 2 ++
arch/x86/kvm/svm/svm.c | 5 ++---
arch/x86/kvm/svm/svm.h | 4 ++--
arch/x86/kvm/svm/vmenter.S | 20 ++++++++++----------
4 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/arch/x86/kvm/kvm-asm-offsets.c b/arch/x86/kvm/kvm-asm-offsets.c
index 30db96852e2d..f1b694e431ae 100644
--- a/arch/x86/kvm/kvm-asm-offsets.c
+++ b/arch/x86/kvm/kvm-asm-offsets.c
@@ -15,6 +15,8 @@ static void __used common(void)
if (IS_ENABLED(CONFIG_KVM_AMD)) {
BLANK();
OFFSET(SVM_vcpu_arch_regs, vcpu_svm, vcpu.arch.regs);
+ OFFSET(SVM_current_vmcb, vcpu_svm, current_vmcb);
+ OFFSET(KVM_VMCB_pa, kvm_vmcb_info, pa);
}
if (IS_ENABLED(CONFIG_KVM_INTEL)) {
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index b412bc5773c5..0c86c435c51f 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -3914,12 +3914,11 @@ static fastpath_t svm_exit_handlers_fastpath(struct kvm_vcpu *vcpu)
static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
- unsigned long vmcb_pa = svm->current_vmcb->pa;
guest_state_enter_irqoff();
if (sev_es_guest(vcpu->kvm)) {
- __svm_sev_es_vcpu_run(vmcb_pa);
+ __svm_sev_es_vcpu_run(svm);
} else {
struct svm_cpu_data *sd = per_cpu(svm_data, vcpu->cpu);
@@ -3930,7 +3929,7 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu)
* vmcb02 when switching vmcbs for nested virtualization.
*/
vmload(svm->vmcb01.pa);
- __svm_vcpu_run(vmcb_pa, svm);
+ __svm_vcpu_run(svm);
vmsave(svm->vmcb01.pa);
vmload(__sme_page_pa(sd->save_area));
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 447e25c9101a..7ff1879e73c5 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -683,7 +683,7 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm);
/* vmenter.S */
-void __svm_sev_es_vcpu_run(unsigned long vmcb_pa);
-void __svm_vcpu_run(unsigned long vmcb_pa, struct vcpu_svm *svm);
+void __svm_sev_es_vcpu_run(struct vcpu_svm *svm);
+void __svm_vcpu_run(struct vcpu_svm *svm);
#endif
diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S
index 531510ab6072..d07bac1952c5 100644
--- a/arch/x86/kvm/svm/vmenter.S
+++ b/arch/x86/kvm/svm/vmenter.S
@@ -32,7 +32,6 @@
/**
* __svm_vcpu_run - Run a vCPU via a transition to SVM guest mode
- * @vmcb_pa: unsigned long
* @svm: struct vcpu_svm *
*/
SYM_FUNC_START(__svm_vcpu_run)
@@ -49,16 +48,16 @@ SYM_FUNC_START(__svm_vcpu_run)
push %_ASM_BX
/* Save @svm. */
- push %_ASM_ARG2
-
- /* Save @vmcb. */
push %_ASM_ARG1
+.ifnc _ASM_ARG1, _ASM_DI
/* Move @svm to RDI. */
- mov %_ASM_ARG2, %_ASM_DI
+ mov %_ASM_ARG1, %_ASM_DI
+.endif
- /* "POP" @vmcb to RAX. */
- pop %_ASM_AX
+ /* Get svm->current_vmcb->pa into RAX. */
+ mov SVM_current_vmcb(%_ASM_DI), %_ASM_AX
+ mov KVM_VMCB_pa(%_ASM_AX), %_ASM_AX
/* Load guest registers. */
mov VCPU_RCX(%_ASM_DI), %_ASM_CX
@@ -170,7 +169,7 @@ SYM_FUNC_END(__svm_vcpu_run)
/**
* __svm_sev_es_vcpu_run - Run a SEV-ES vCPU via a transition to SVM guest mode
- * @vmcb_pa: unsigned long
+ * @svm: struct vcpu_svm *
*/
SYM_FUNC_START(__svm_sev_es_vcpu_run)
push %_ASM_BP
@@ -185,8 +184,9 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run)
#endif
push %_ASM_BX
- /* Move @vmcb to RAX. */
- mov %_ASM_ARG1, %_ASM_AX
+ /* Get svm->current_vmcb->pa into RAX. */
+ mov SVM_current_vmcb(%_ASM_ARG1), %_ASM_AX
+ mov KVM_VMCB_pa(%_ASM_AX), %_ASM_AX
/* Enter guest mode */
sti
--
2.31.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 05/11] KVM: SVM: remove unused field from struct vcpu_svm
2022-11-09 14:51 [PATCH v3 00/11] KVM: SVM: fixes for vmentry code Paolo Bonzini
` (3 preceding siblings ...)
2022-11-09 14:51 ` [PATCH 04/11] KVM: SVM: retrieve VMCB from assembly Paolo Bonzini
@ 2022-11-09 14:51 ` Paolo Bonzini
2022-11-09 15:25 ` Sean Christopherson
2022-11-09 14:51 ` [PATCH 06/11] KVM: SVM: remove dead field from struct svm_cpu_data Paolo Bonzini
` (5 subsequent siblings)
10 siblings, 1 reply; 24+ messages in thread
From: Paolo Bonzini @ 2022-11-09 14:51 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: thomas.lendacky, jmattson, seanjc
The pointer to svm_cpu_data in struct vcpu_svm looks interesting from
the point of view of accessing it after vmexit, when the GSBASE is still
containing the guest value. However, despite existing since the very
first commit of drivers/kvm/svm.c (commit 6aa8b732ca01, "[PATCH] kvm:
userspace interface", 2006-12-10), it was never set to anything.
Ignore the opportunity to fix a 16 year old "bug" and delete it; doing
things the "harder" way makes it possible to remove more old cruft.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/svm/svm.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 7ff1879e73c5..626240707ba9 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -209,7 +209,6 @@ struct vcpu_svm {
struct vmcb *vmcb;
struct kvm_vmcb_info vmcb01;
struct kvm_vmcb_info *current_vmcb;
- struct svm_cpu_data *svm_data;
u32 asid;
u32 sysenter_esp_hi;
u32 sysenter_eip_hi;
--
2.31.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 06/11] KVM: SVM: remove dead field from struct svm_cpu_data
2022-11-09 14:51 [PATCH v3 00/11] KVM: SVM: fixes for vmentry code Paolo Bonzini
` (4 preceding siblings ...)
2022-11-09 14:51 ` [PATCH 05/11] KVM: SVM: remove unused field from struct vcpu_svm Paolo Bonzini
@ 2022-11-09 14:51 ` Paolo Bonzini
2022-11-09 15:26 ` Sean Christopherson
2022-11-09 14:51 ` [PATCH 07/11] KVM: SVM: do not allocate struct svm_cpu_data dynamically Paolo Bonzini
` (4 subsequent siblings)
10 siblings, 1 reply; 24+ messages in thread
From: Paolo Bonzini @ 2022-11-09 14:51 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: thomas.lendacky, jmattson, seanjc
The "cpu" field of struct svm_cpu_data has been write-only since commit
4b656b120249 ("KVM: SVM: force new asid on vcpu migration", 2009-08-05).
Remove it.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/svm/svm.c | 1 -
arch/x86/kvm/svm/svm.h | 2 --
2 files changed, 3 deletions(-)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 0c86c435c51f..0f873b298931 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -665,7 +665,6 @@ static int svm_cpu_init(int cpu)
sd = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL);
if (!sd)
return ret;
- sd->cpu = cpu;
sd->save_area = alloc_page(GFP_KERNEL | __GFP_ZERO);
if (!sd->save_area)
goto free_cpu_data;
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 626240707ba9..7540db9902a6 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -280,8 +280,6 @@ struct vcpu_svm {
};
struct svm_cpu_data {
- int cpu;
-
u64 asid_generation;
u32 max_asid;
u32 next_asid;
--
2.31.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 07/11] KVM: SVM: do not allocate struct svm_cpu_data dynamically
2022-11-09 14:51 [PATCH v3 00/11] KVM: SVM: fixes for vmentry code Paolo Bonzini
` (5 preceding siblings ...)
2022-11-09 14:51 ` [PATCH 06/11] KVM: SVM: remove dead field from struct svm_cpu_data Paolo Bonzini
@ 2022-11-09 14:51 ` Paolo Bonzini
2022-11-09 15:58 ` Sean Christopherson
2022-11-09 14:51 ` [PATCH 08/11] KVM: SVM: move guest vmsave/vmload back to assembly Paolo Bonzini
` (3 subsequent siblings)
10 siblings, 1 reply; 24+ messages in thread
From: Paolo Bonzini @ 2022-11-09 14:51 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: thomas.lendacky, jmattson, seanjc
The svm_data percpu variable is a pointer, but it is allocated when
KVM is loaded (via svm_hardware_setup), not at hardware_enable time.
Just allocate room for it statically, that is more efficient and
does not waste any memory compared to the status quo.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/svm/sev.c | 4 ++--
arch/x86/kvm/svm/svm.c | 41 +++++++++++++++--------------------------
arch/x86/kvm/svm/svm.h | 2 +-
3 files changed, 18 insertions(+), 29 deletions(-)
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 28064060413a..9b66ee34e264 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -196,7 +196,7 @@ static void sev_asid_free(struct kvm_sev_info *sev)
__set_bit(sev->asid, sev_reclaim_asid_bitmap);
for_each_possible_cpu(cpu) {
- sd = per_cpu(svm_data, cpu);
+ sd = per_cpu_ptr(&svm_data, cpu);
sd->sev_vmcbs[sev->asid] = NULL;
}
@@ -2600,7 +2600,7 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm)
void pre_sev_run(struct vcpu_svm *svm, int cpu)
{
- struct svm_cpu_data *sd = per_cpu(svm_data, cpu);
+ struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, cpu);
int asid = sev_get_asid(svm->vcpu.kvm);
/* Assign the asid allocated with this SEV guest */
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 0f873b298931..48274c93d78b 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -245,7 +245,7 @@ struct kvm_ldttss_desc {
u32 zero1;
} __attribute__((packed));
-DEFINE_PER_CPU(struct svm_cpu_data *, svm_data);
+DEFINE_PER_CPU(struct svm_cpu_data, svm_data);
/*
* Only MSR_TSC_AUX is switched via the user return hook. EFER is switched via
@@ -581,12 +581,7 @@ static int svm_hardware_enable(void)
pr_err("%s: err EOPNOTSUPP on %d\n", __func__, me);
return -EINVAL;
}
- sd = per_cpu(svm_data, me);
- if (!sd) {
- pr_err("%s: svm_data is NULL on %d\n", __func__, me);
- return -EINVAL;
- }
-
+ 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;
@@ -646,41 +641,35 @@ static int svm_hardware_enable(void)
static void svm_cpu_uninit(int cpu)
{
- struct svm_cpu_data *sd = per_cpu(svm_data, cpu);
+ struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, cpu);
- if (!sd)
+ if (!sd->save_area)
return;
- per_cpu(svm_data, cpu) = NULL;
kfree(sd->sev_vmcbs);
__free_page(sd->save_area);
- kfree(sd);
+ sd->save_area = NULL;
}
static int svm_cpu_init(int cpu)
{
- struct svm_cpu_data *sd;
+ struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, cpu);
int ret = -ENOMEM;
- sd = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL);
- if (!sd)
- return ret;
+ memset(sd, 0, sizeof(struct svm_cpu_data));
sd->save_area = alloc_page(GFP_KERNEL | __GFP_ZERO);
if (!sd->save_area)
- goto free_cpu_data;
+ return ret;
ret = sev_cpu_init(sd);
if (ret)
goto free_save_area;
- per_cpu(svm_data, cpu) = sd;
-
return 0;
free_save_area:
__free_page(sd->save_area);
-free_cpu_data:
- kfree(sd);
+ sd->save_area = NULL;
return ret;
}
@@ -1424,7 +1413,7 @@ static void svm_clear_current_vmcb(struct vmcb *vmcb)
int i;
for_each_online_cpu(i)
- cmpxchg(&per_cpu(svm_data, i)->current_vmcb, vmcb, NULL);
+ cmpxchg(per_cpu_ptr(&svm_data.current_vmcb, i), vmcb, NULL);
}
static void svm_vcpu_free(struct kvm_vcpu *vcpu)
@@ -1449,7 +1438,7 @@ static void svm_vcpu_free(struct kvm_vcpu *vcpu)
static void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
- struct svm_cpu_data *sd = per_cpu(svm_data, vcpu->cpu);
+ struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu);
if (sev_es_guest(vcpu->kvm))
sev_es_unmap_ghcb(svm);
@@ -1486,7 +1475,7 @@ static void svm_prepare_host_switch(struct kvm_vcpu *vcpu)
static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
- struct svm_cpu_data *sd = per_cpu(svm_data, cpu);
+ struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, cpu);
if (sd->current_vmcb != svm->vmcb) {
sd->current_vmcb = svm->vmcb;
@@ -3442,7 +3431,7 @@ static int svm_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
static void reload_tss(struct kvm_vcpu *vcpu)
{
- struct svm_cpu_data *sd = per_cpu(svm_data, vcpu->cpu);
+ struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu);
sd->tss_desc->type = 9; /* available 32/64-bit TSS */
load_TR_desc();
@@ -3450,7 +3439,7 @@ static void reload_tss(struct kvm_vcpu *vcpu)
static void pre_svm_run(struct kvm_vcpu *vcpu)
{
- struct svm_cpu_data *sd = per_cpu(svm_data, vcpu->cpu);
+ struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu);
struct vcpu_svm *svm = to_svm(vcpu);
/*
@@ -3919,7 +3908,7 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu)
if (sev_es_guest(vcpu->kvm)) {
__svm_sev_es_vcpu_run(svm);
} else {
- struct svm_cpu_data *sd = per_cpu(svm_data, vcpu->cpu);
+ struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu);
/*
* Use a single vmcb (vmcb01 because it's always valid) for
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 7540db9902a6..2af6a71126c1 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -293,7 +293,7 @@ struct svm_cpu_data {
struct vmcb **sev_vmcbs;
};
-DECLARE_PER_CPU(struct svm_cpu_data *, svm_data);
+DECLARE_PER_CPU(struct svm_cpu_data, svm_data);
void recalc_intercepts(struct vcpu_svm *svm);
--
2.31.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 08/11] KVM: SVM: move guest vmsave/vmload back to assembly
2022-11-09 14:51 [PATCH v3 00/11] KVM: SVM: fixes for vmentry code Paolo Bonzini
` (6 preceding siblings ...)
2022-11-09 14:51 ` [PATCH 07/11] KVM: SVM: do not allocate struct svm_cpu_data dynamically Paolo Bonzini
@ 2022-11-09 14:51 ` Paolo Bonzini
2022-11-09 15:29 ` Sean Christopherson
2022-11-09 14:51 ` [PATCH 09/11] KVM: SVM: restore host save area from assembly Paolo Bonzini
` (2 subsequent siblings)
10 siblings, 1 reply; 24+ messages in thread
From: Paolo Bonzini @ 2022-11-09 14:51 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: thomas.lendacky, jmattson, seanjc, stable
FILL_RETURN_BUFFER can access percpu data, therefore vmload of the
host save area must be executed first. First of all, move the VMCB
vmsave/vmload to assembly, essentially undoing commit fb0c4a4fee5a ("KVM:
SVM: move VMLOAD/VMSAVE to C code", 2021-03-15). The reason for that
commit was that it made it simpler to use a different VMCB for
VMLOAD/VMSAVE versus VMRUN; but that is not a big hassle anymore thanks
to the kvm-asm-offsets machinery.
The idea on how to number the exception tables is stolen from
a prototype patch by Peter Zijlstra.
Cc: stable@vger.kernel.org
Fixes: a149180fbcf3 ("x86: Add magic AMD return-thunk")
Link: <https://lore.kernel.org/all/f571e404-e625-bae1-10e9-449b2eb4cbd8@citrix.com/>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/kvm-asm-offsets.c | 1 +
arch/x86/kvm/svm/svm.c | 9 -------
arch/x86/kvm/svm/vmenter.S | 49 ++++++++++++++++++++++++++--------
3 files changed, 39 insertions(+), 20 deletions(-)
diff --git a/arch/x86/kvm/kvm-asm-offsets.c b/arch/x86/kvm/kvm-asm-offsets.c
index f1b694e431ae..f83e88b85bf2 100644
--- a/arch/x86/kvm/kvm-asm-offsets.c
+++ b/arch/x86/kvm/kvm-asm-offsets.c
@@ -16,6 +16,7 @@ static void __used common(void)
BLANK();
OFFSET(SVM_vcpu_arch_regs, vcpu_svm, vcpu.arch.regs);
OFFSET(SVM_current_vmcb, vcpu_svm, current_vmcb);
+ OFFSET(SVM_vmcb01, vcpu_svm, vmcb01);
OFFSET(KVM_VMCB_pa, kvm_vmcb_info, pa);
}
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 48274c93d78b..4e3a47eb5002 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -3910,16 +3910,7 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu)
} else {
struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu);
- /*
- * Use a single vmcb (vmcb01 because it's always valid) for
- * context switching guest state via VMLOAD/VMSAVE, that way
- * the state doesn't need to be copied between vmcb01 and
- * vmcb02 when switching vmcbs for nested virtualization.
- */
- vmload(svm->vmcb01.pa);
__svm_vcpu_run(svm);
- vmsave(svm->vmcb01.pa);
-
vmload(__sme_page_pa(sd->save_area));
}
diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S
index d07bac1952c5..5bc2ed7d79c0 100644
--- a/arch/x86/kvm/svm/vmenter.S
+++ b/arch/x86/kvm/svm/vmenter.S
@@ -28,6 +28,8 @@
#define VCPU_R15 (SVM_vcpu_arch_regs + __VCPU_REGS_R15 * WORD_SIZE)
#endif
+#define SVM_vmcb01_pa (SVM_vmcb01 + KVM_VMCB_pa)
+
.section .noinstr.text, "ax"
/**
@@ -55,6 +57,16 @@ SYM_FUNC_START(__svm_vcpu_run)
mov %_ASM_ARG1, %_ASM_DI
.endif
+ /*
+ * Use a single vmcb (vmcb01 because it's always valid) for
+ * context switching guest state via VMLOAD/VMSAVE, that way
+ * the state doesn't need to be copied between vmcb01 and
+ * vmcb02 when switching vmcbs for nested virtualization.
+ */
+ mov SVM_vmcb01_pa(%_ASM_DI), %_ASM_AX
+1: vmload %_ASM_AX
+2:
+
/* Get svm->current_vmcb->pa into RAX. */
mov SVM_current_vmcb(%_ASM_DI), %_ASM_AX
mov KVM_VMCB_pa(%_ASM_AX), %_ASM_AX
@@ -80,16 +92,11 @@ SYM_FUNC_START(__svm_vcpu_run)
/* Enter guest mode */
sti
-1: vmrun %_ASM_AX
-
-2: cli
-
-#ifdef CONFIG_RETPOLINE
- /* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
- FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE
-#endif
+3: vmrun %_ASM_AX
+4:
+ cli
- /* "POP" @svm to RAX. */
+ /* Pop @svm to RAX while it's the only available register. */
pop %_ASM_AX
/* Save all guest registers. */
@@ -110,6 +117,18 @@ SYM_FUNC_START(__svm_vcpu_run)
mov %r15, VCPU_R15(%_ASM_AX)
#endif
+ /* @svm can stay in RDI from now on. */
+ mov %_ASM_AX, %_ASM_DI
+
+ mov SVM_vmcb01_pa(%_ASM_DI), %_ASM_AX
+5: vmsave %_ASM_AX
+6:
+
+#ifdef CONFIG_RETPOLINE
+ /* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
+ FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE
+#endif
+
/*
* Mitigate RETBleed for AMD/Hygon Zen uarch. RET should be
* untrained as soon as we exit the VM and are back to the
@@ -159,11 +178,19 @@ SYM_FUNC_START(__svm_vcpu_run)
pop %_ASM_BP
RET
-3: cmpb $0, kvm_rebooting
+10: cmpb $0, kvm_rebooting
jne 2b
ud2
+30: cmpb $0, kvm_rebooting
+ jne 4b
+ ud2
+50: cmpb $0, kvm_rebooting
+ jne 6b
+ ud2
- _ASM_EXTABLE(1b, 3b)
+ _ASM_EXTABLE(1b, 10b)
+ _ASM_EXTABLE(3b, 30b)
+ _ASM_EXTABLE(5b, 50b)
SYM_FUNC_END(__svm_vcpu_run)
--
2.31.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 09/11] KVM: SVM: restore host save area from assembly
2022-11-09 14:51 [PATCH v3 00/11] KVM: SVM: fixes for vmentry code Paolo Bonzini
` (7 preceding siblings ...)
2022-11-09 14:51 ` [PATCH 08/11] KVM: SVM: move guest vmsave/vmload back to assembly Paolo Bonzini
@ 2022-11-09 14:51 ` Paolo Bonzini
2022-11-09 15:54 ` Sean Christopherson
2022-11-09 14:51 ` [PATCH 10/11] KVM: SVM: move MSR_IA32_SPEC_CTRL save/restore to assembly Paolo Bonzini
2022-11-09 14:51 ` [PATCH 11/11] x86, KVM: remove unnecessary argument to x86_virt_spec_ctrl and callers Paolo Bonzini
10 siblings, 1 reply; 24+ messages in thread
From: Paolo Bonzini @ 2022-11-09 14:51 UTC (permalink / raw)
To: linux-kernel, kvm
Cc: thomas.lendacky, jmattson, seanjc, stable, Nathan Chancellor,
Andrew Cooper
Allow access to the percpu area via the GS segment base, which is
needed in order to access the saved host spec_ctrl value. In linux-next
FILL_RETURN_BUFFER also needs to access percpu data.
For simplicity, the physical address of the save area is added to struct
svm_cpu_data.
Cc: stable@vger.kernel.org
Fixes: a149180fbcf3 ("x86: Add magic AMD return-thunk")
Reported-by: Nathan Chancellor <nathan@kernel.org>
Analyzed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Tested-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/kvm-asm-offsets.c | 1 +
arch/x86/kvm/svm/svm.c | 14 ++++++--------
arch/x86/kvm/svm/svm.h | 2 ++
arch/x86/kvm/svm/svm_ops.h | 5 -----
arch/x86/kvm/svm/vmenter.S | 17 +++++++++++++++++
5 files changed, 26 insertions(+), 13 deletions(-)
diff --git a/arch/x86/kvm/kvm-asm-offsets.c b/arch/x86/kvm/kvm-asm-offsets.c
index f83e88b85bf2..1b805cd24d66 100644
--- a/arch/x86/kvm/kvm-asm-offsets.c
+++ b/arch/x86/kvm/kvm-asm-offsets.c
@@ -18,6 +18,7 @@ static void __used common(void)
OFFSET(SVM_current_vmcb, vcpu_svm, current_vmcb);
OFFSET(SVM_vmcb01, vcpu_svm, vmcb01);
OFFSET(KVM_VMCB_pa, kvm_vmcb_info, pa);
+ OFFSET(SD_save_area_pa, svm_cpu_data, save_area_pa);
}
if (IS_ENABLED(CONFIG_KVM_INTEL)) {
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 4e3a47eb5002..469c1b5617af 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -592,7 +592,7 @@ static int svm_hardware_enable(void)
wrmsrl(MSR_EFER, efer | EFER_SVME);
- wrmsrl(MSR_VM_HSAVE_PA, __sme_page_pa(sd->save_area));
+ wrmsrl(MSR_VM_HSAVE_PA, sd->save_area_pa);
if (static_cpu_has(X86_FEATURE_TSCRATEMSR)) {
/*
@@ -648,6 +648,7 @@ static void svm_cpu_uninit(int cpu)
kfree(sd->sev_vmcbs);
__free_page(sd->save_area);
+ sd->save_area_pa = 0;
sd->save_area = NULL;
}
@@ -665,6 +666,7 @@ static int svm_cpu_init(int cpu)
if (ret)
goto free_save_area;
+ sd->save_area_pa = __sme_page_pa(sd->save_area);
return 0;
free_save_area:
@@ -1450,7 +1452,7 @@ static void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
* Save additional host state that will be restored on VMEXIT (sev-es)
* or subsequent vmload of host save area.
*/
- vmsave(__sme_page_pa(sd->save_area));
+ vmsave(sd->save_area_pa);
if (sev_es_guest(vcpu->kvm)) {
struct sev_es_save_area *hostsa;
hostsa = (struct sev_es_save_area *)(page_address(sd->save_area) + 0x400);
@@ -3905,14 +3907,10 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu)
guest_state_enter_irqoff();
- if (sev_es_guest(vcpu->kvm)) {
+ if (sev_es_guest(vcpu->kvm))
__svm_sev_es_vcpu_run(svm);
- } else {
- struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu);
-
+ else
__svm_vcpu_run(svm);
- vmload(__sme_page_pa(sd->save_area));
- }
guest_state_exit_irqoff();
}
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 2af6a71126c1..83955a4e520e 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -287,6 +287,8 @@ struct svm_cpu_data {
struct kvm_ldttss_desc *tss_desc;
struct page *save_area;
+ unsigned long save_area_pa;
+
struct vmcb *current_vmcb;
/* index = sev_asid, value = vmcb pointer */
diff --git a/arch/x86/kvm/svm/svm_ops.h b/arch/x86/kvm/svm/svm_ops.h
index 9430d6437c9f..36c8af87a707 100644
--- a/arch/x86/kvm/svm/svm_ops.h
+++ b/arch/x86/kvm/svm/svm_ops.h
@@ -61,9 +61,4 @@ static __always_inline void vmsave(unsigned long pa)
svm_asm1(vmsave, "a" (pa), "memory");
}
-static __always_inline void vmload(unsigned long pa)
-{
- svm_asm1(vmload, "a" (pa), "memory");
-}
-
#endif /* __KVM_X86_SVM_OPS_H */
diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S
index 5bc2ed7d79c0..57440acfc73e 100644
--- a/arch/x86/kvm/svm/vmenter.S
+++ b/arch/x86/kvm/svm/vmenter.S
@@ -49,6 +49,14 @@ SYM_FUNC_START(__svm_vcpu_run)
#endif
push %_ASM_BX
+ /*
+ * Save variables needed after vmexit on the stack, in inverse
+ * order compared to when they are needed.
+ */
+
+ /* Needed to restore access to percpu variables. */
+ __ASM_SIZE(push) PER_CPU_VAR(svm_data + SD_save_area_pa)
+
/* Save @svm. */
push %_ASM_ARG1
@@ -124,6 +132,11 @@ SYM_FUNC_START(__svm_vcpu_run)
5: vmsave %_ASM_AX
6:
+ /* Restores GSBASE among other things, allowing access to percpu data. */
+ pop %_ASM_AX
+7: vmload %_ASM_AX
+8:
+
#ifdef CONFIG_RETPOLINE
/* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE
@@ -187,10 +200,14 @@ SYM_FUNC_START(__svm_vcpu_run)
50: cmpb $0, kvm_rebooting
jne 6b
ud2
+70: cmpb $0, kvm_rebooting
+ jne 8b
+ ud2
_ASM_EXTABLE(1b, 10b)
_ASM_EXTABLE(3b, 30b)
_ASM_EXTABLE(5b, 50b)
+ _ASM_EXTABLE(7b, 70b)
SYM_FUNC_END(__svm_vcpu_run)
--
2.31.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 10/11] KVM: SVM: move MSR_IA32_SPEC_CTRL save/restore to assembly
2022-11-09 14:51 [PATCH v3 00/11] KVM: SVM: fixes for vmentry code Paolo Bonzini
` (8 preceding siblings ...)
2022-11-09 14:51 ` [PATCH 09/11] KVM: SVM: restore host save area from assembly Paolo Bonzini
@ 2022-11-09 14:51 ` Paolo Bonzini
2022-11-09 16:04 ` Sean Christopherson
2022-11-09 14:51 ` [PATCH 11/11] x86, KVM: remove unnecessary argument to x86_virt_spec_ctrl and callers Paolo Bonzini
10 siblings, 1 reply; 24+ messages in thread
From: Paolo Bonzini @ 2022-11-09 14:51 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: thomas.lendacky, jmattson, seanjc, stable
Restoration of the host IA32_SPEC_CTRL value is probably too late
with respect to the return thunk training sequence.
With respect to the user/kernel boundary, AMD says, "If software chooses
to toggle STIBP (e.g., set STIBP on kernel entry, and clear it on kernel
exit), software should set STIBP to 1 before executing the return thunk
training sequence." I assume the same requirements apply to the guest/host
boundary. The return thunk training sequence is in vmenter.S, quite close
to the VM-exit. On hosts without V_SPEC_CTRL, however, the host's
IA32_SPEC_CTRL value is not restored until much later.
To avoid this, move the restoration of host SPEC_CTRL to assembly and,
for consistency, move the restoration of the guest SPEC_CTRL as well.
This is not particularly difficult, apart from some care to cover both
32- and 64-bit, and to share code between SEV-ES and normal vmentry.
Cc: stable@vger.kernel.org
Fixes: a149180fbcf3 ("x86: Add magic AMD return-thunk")
Suggested-by: Jim Mattson <jmattson@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kernel/cpu/bugs.c | 13 +---
arch/x86/kvm/kvm-asm-offsets.c | 1 +
arch/x86/kvm/svm/svm.c | 37 ++++------
arch/x86/kvm/svm/svm.h | 4 +-
arch/x86/kvm/svm/vmenter.S | 119 ++++++++++++++++++++++++++++++++-
5 files changed, 136 insertions(+), 38 deletions(-)
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index da7c361f47e0..6ec0b7ce7453 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -196,22 +196,15 @@ void __init check_bugs(void)
}
/*
- * NOTE: This function is *only* called for SVM. VMX spec_ctrl handling is
- * done in vmenter.S.
+ * NOTE: This function is *only* called for SVM, since Intel uses
+ * MSR_IA32_SPEC_CTRL for SSBD.
*/
void
x86_virt_spec_ctrl(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl, bool setguest)
{
- u64 msrval, guestval = guest_spec_ctrl, hostval = spec_ctrl_current();
+ u64 guestval, hostval;
struct thread_info *ti = current_thread_info();
- if (static_cpu_has(X86_FEATURE_MSR_SPEC_CTRL)) {
- if (hostval != guestval) {
- msrval = setguest ? guestval : hostval;
- wrmsrl(MSR_IA32_SPEC_CTRL, msrval);
- }
- }
-
/*
* If SSBD is not handled in MSR_SPEC_CTRL on AMD, update
* MSR_AMD64_L2_CFG or MSR_VIRT_SPEC_CTRL if supported.
diff --git a/arch/x86/kvm/kvm-asm-offsets.c b/arch/x86/kvm/kvm-asm-offsets.c
index 1b805cd24d66..24a710d37323 100644
--- a/arch/x86/kvm/kvm-asm-offsets.c
+++ b/arch/x86/kvm/kvm-asm-offsets.c
@@ -16,6 +16,7 @@ static void __used common(void)
BLANK();
OFFSET(SVM_vcpu_arch_regs, vcpu_svm, vcpu.arch.regs);
OFFSET(SVM_current_vmcb, vcpu_svm, current_vmcb);
+ OFFSET(SVM_spec_ctrl, vcpu_svm, spec_ctrl);
OFFSET(SVM_vmcb01, vcpu_svm, vmcb01);
OFFSET(KVM_VMCB_pa, kvm_vmcb_info, pa);
OFFSET(SD_save_area_pa, svm_cpu_data, save_area_pa);
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 469c1b5617af..cf1aed25f4ab 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -720,6 +720,15 @@ static bool msr_write_intercepted(struct kvm_vcpu *vcpu, u32 msr)
u32 offset;
u32 *msrpm;
+ /*
+ * For non-nested case:
+ * If the L01 MSR bitmap does not intercept the MSR, then we need to
+ * save it.
+ *
+ * For nested case:
+ * If the L02 MSR bitmap does not intercept the MSR, then we need to
+ * save it.
+ */
msrpm = is_guest_mode(vcpu) ? to_svm(vcpu)->nested.msrpm:
to_svm(vcpu)->msrpm;
@@ -3901,16 +3910,16 @@ static fastpath_t svm_exit_handlers_fastpath(struct kvm_vcpu *vcpu)
return EXIT_FASTPATH_NONE;
}
-static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu)
+static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, bool spec_ctrl_intercepted)
{
struct vcpu_svm *svm = to_svm(vcpu);
guest_state_enter_irqoff();
if (sev_es_guest(vcpu->kvm))
- __svm_sev_es_vcpu_run(svm);
+ __svm_sev_es_vcpu_run(svm, spec_ctrl_intercepted);
else
- __svm_vcpu_run(svm);
+ __svm_vcpu_run(svm, spec_ctrl_intercepted);
guest_state_exit_irqoff();
}
@@ -3918,6 +3927,7 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu)
static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
+ bool spec_ctrl_intercepted = msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL);
trace_kvm_entry(vcpu);
@@ -3976,26 +3986,7 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
if (!static_cpu_has(X86_FEATURE_V_SPEC_CTRL))
x86_spec_ctrl_set_guest(svm->spec_ctrl, svm->virt_spec_ctrl);
- svm_vcpu_enter_exit(vcpu);
-
- /*
- * We do not use IBRS in the kernel. If this vCPU has used the
- * SPEC_CTRL MSR it may have left it on; save the value and
- * turn it off. This is much more efficient than blindly adding
- * it to the atomic save/restore list. Especially as the former
- * (Saving guest MSRs on vmexit) doesn't even exist in KVM.
- *
- * For non-nested case:
- * If the L01 MSR bitmap does not intercept the MSR, then we need to
- * save it.
- *
- * For nested case:
- * If the L02 MSR bitmap does not intercept the MSR, then we need to
- * save it.
- */
- if (!static_cpu_has(X86_FEATURE_V_SPEC_CTRL) &&
- unlikely(!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL)))
- svm->spec_ctrl = native_read_msr(MSR_IA32_SPEC_CTRL);
+ svm_vcpu_enter_exit(vcpu, spec_ctrl_intercepted);
if (!sev_es_guest(vcpu->kvm))
reload_tss(vcpu);
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 83955a4e520e..199a2ecef1ce 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -682,7 +682,7 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm);
/* vmenter.S */
-void __svm_sev_es_vcpu_run(struct vcpu_svm *svm);
-void __svm_vcpu_run(struct vcpu_svm *svm);
+void __svm_sev_es_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted);
+void __svm_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted);
#endif
diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S
index 57440acfc73e..34367dc203f2 100644
--- a/arch/x86/kvm/svm/vmenter.S
+++ b/arch/x86/kvm/svm/vmenter.S
@@ -32,9 +32,69 @@
.section .noinstr.text, "ax"
+.macro RESTORE_GUEST_SPEC_CTRL
+ /* No need to do anything if SPEC_CTRL is unset or V_SPEC_CTRL is set */
+ ALTERNATIVE_2 "", \
+ "jmp 800f", X86_FEATURE_MSR_SPEC_CTRL, \
+ "", X86_FEATURE_V_SPEC_CTRL
+801:
+.endm
+.macro RESTORE_GUEST_SPEC_CTRL_BODY
+800:
+ /*
+ * SPEC_CTRL handling: if the guest's SPEC_CTRL value differs from the
+ * host's, write the MSR. This is kept out-of-line so that the common
+ * case does not have to jump.
+ *
+ * IMPORTANT: To avoid RSB underflow attacks and any other nastiness,
+ * there must not be any returns or indirect branches between this code
+ * and vmentry.
+ */
+ movl SVM_spec_ctrl(%_ASM_DI), %eax
+ cmp PER_CPU_VAR(x86_spec_ctrl_current), %eax
+ je 801b
+ mov $MSR_IA32_SPEC_CTRL, %ecx
+ xor %edx, %edx
+ wrmsr
+ jmp 801b
+.endm
+
+.macro RESTORE_HOST_SPEC_CTRL
+ /* No need to do anything if SPEC_CTRL is unset or V_SPEC_CTRL is set */
+ ALTERNATIVE_2 "", \
+ "jmp 900f", X86_FEATURE_MSR_SPEC_CTRL, \
+ "", X86_FEATURE_V_SPEC_CTRL
+901:
+.endm
+.macro RESTORE_HOST_SPEC_CTRL_BODY
+900:
+ /* Same for after vmexit. */
+ mov $MSR_IA32_SPEC_CTRL, %ecx
+
+ /*
+ * Load the value that the guest had written into MSR_IA32_SPEC_CTRL,
+ * if it was not intercepted during guest execution.
+ */
+ cmpb $0, (%_ASM_SP)
+ jnz 998f
+ rdmsr
+ movl %eax, SVM_spec_ctrl(%_ASM_DI)
+998:
+
+ /* Now restore the host value of the MSR if different from the guest's. */
+ movl PER_CPU_VAR(x86_spec_ctrl_current), %eax
+ cmp SVM_spec_ctrl(%_ASM_DI), %eax
+ je 901b
+ xor %edx, %edx
+ wrmsr
+ jmp 901b
+.endm
+
+
/**
* __svm_vcpu_run - Run a vCPU via a transition to SVM guest mode
* @svm: struct vcpu_svm *
+ * @spec_ctrl_intercepted: bool
*/
SYM_FUNC_START(__svm_vcpu_run)
push %_ASM_BP
@@ -54,17 +114,26 @@ SYM_FUNC_START(__svm_vcpu_run)
* order compared to when they are needed.
*/
+ /* Accessed directly from the stack in RESTORE_HOST_SPEC_CTRL. */
+ push %_ASM_ARG2
+
/* Needed to restore access to percpu variables. */
__ASM_SIZE(push) PER_CPU_VAR(svm_data + SD_save_area_pa)
- /* Save @svm. */
+ /* Finally save @svm. */
push %_ASM_ARG1
.ifnc _ASM_ARG1, _ASM_DI
- /* Move @svm to RDI. */
+ /*
+ * Stash @svm in RDI early. On 32-bit, arguments are in RAX, RCX
+ * and RDX which are clobbered by RESTORE_GUEST_SPEC_CTRL.
+ */
mov %_ASM_ARG1, %_ASM_DI
.endif
+ /* Clobbers RAX, RCX, RDX. */
+ RESTORE_GUEST_SPEC_CTRL
+
/*
* Use a single vmcb (vmcb01 because it's always valid) for
* context switching guest state via VMLOAD/VMSAVE, that way
@@ -142,6 +211,9 @@ SYM_FUNC_START(__svm_vcpu_run)
FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE
#endif
+ /* Clobbers RAX, RCX, RDX. */
+ RESTORE_HOST_SPEC_CTRL
+
/*
* Mitigate RETBleed for AMD/Hygon Zen uarch. RET should be
* untrained as soon as we exit the VM and are back to the
@@ -177,6 +249,9 @@ SYM_FUNC_START(__svm_vcpu_run)
xor %r15d, %r15d
#endif
+ /* "Pop" @spec_ctrl_intercepted. */
+ pop %_ASM_BX
+
pop %_ASM_BX
#ifdef CONFIG_X86_64
@@ -191,6 +266,9 @@ SYM_FUNC_START(__svm_vcpu_run)
pop %_ASM_BP
RET
+ RESTORE_GUEST_SPEC_CTRL_BODY
+ RESTORE_HOST_SPEC_CTRL_BODY
+
10: cmpb $0, kvm_rebooting
jne 2b
ud2
@@ -214,6 +292,7 @@ SYM_FUNC_END(__svm_vcpu_run)
/**
* __svm_sev_es_vcpu_run - Run a SEV-ES vCPU via a transition to SVM guest mode
* @svm: struct vcpu_svm *
+ * @spec_ctrl_intercepted: bool
*/
SYM_FUNC_START(__svm_sev_es_vcpu_run)
push %_ASM_BP
@@ -228,8 +307,30 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run)
#endif
push %_ASM_BX
+ /*
+ * Save variables needed after vmexit on the stack, in inverse
+ * order compared to when they are needed.
+ */
+
+ /* Accessed directly from the stack in RESTORE_HOST_SPEC_CTRL. */
+ push %_ASM_ARG2
+
+ /* Save @svm. */
+ push %_ASM_ARG1
+
+.ifnc _ASM_ARG1, _ASM_DI
+ /*
+ * Stash @svm in RDI early. On 32-bit, arguments are in RAX, RCX
+ * and RDX which are clobbered by RESTORE_GUEST_SPEC_CTRL.
+ */
+ mov %_ASM_ARG1, %_ASM_DI
+.endif
+
+ /* Clobbers RAX, RCX, RDX. */
+ RESTORE_GUEST_SPEC_CTRL
+
/* Get svm->current_vmcb->pa into RAX. */
- mov SVM_current_vmcb(%_ASM_ARG1), %_ASM_AX
+ mov SVM_current_vmcb(%_ASM_DI), %_ASM_AX
mov KVM_VMCB_pa(%_ASM_AX), %_ASM_AX
/* Enter guest mode */
@@ -239,11 +340,17 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run)
2: cli
+ /* Pop @svm to RDI, guest registers have been saved already. */
+ pop %_ASM_DI
+
#ifdef CONFIG_RETPOLINE
/* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE
#endif
+ /* Clobbers RAX, RCX, RDX. */
+ RESTORE_HOST_SPEC_CTRL
+
/*
* Mitigate RETBleed for AMD/Hygon Zen uarch. RET should be
* untrained as soon as we exit the VM and are back to the
@@ -253,6 +360,9 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run)
*/
UNTRAIN_RET
+ /* "Pop" @spec_ctrl_intercepted. */
+ pop %_ASM_BX
+
pop %_ASM_BX
#ifdef CONFIG_X86_64
@@ -267,6 +377,9 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run)
pop %_ASM_BP
RET
+ RESTORE_GUEST_SPEC_CTRL_BODY
+ RESTORE_HOST_SPEC_CTRL_BODY
+
3: cmpb $0, kvm_rebooting
jne 2b
ud2
--
2.31.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 11/11] x86, KVM: remove unnecessary argument to x86_virt_spec_ctrl and callers
2022-11-09 14:51 [PATCH v3 00/11] KVM: SVM: fixes for vmentry code Paolo Bonzini
` (9 preceding siblings ...)
2022-11-09 14:51 ` [PATCH 10/11] KVM: SVM: move MSR_IA32_SPEC_CTRL save/restore to assembly Paolo Bonzini
@ 2022-11-09 14:51 ` Paolo Bonzini
10 siblings, 0 replies; 24+ messages in thread
From: Paolo Bonzini @ 2022-11-09 14:51 UTC (permalink / raw)
To: linux-kernel, kvm; +Cc: thomas.lendacky, jmattson, seanjc
x86_virt_spec_ctrl only deals with the paravirtualized
MSR_IA32_VIRT_SPEC_CTRL now and does not handle MSR_IA32_SPEC_CTRL
anymore; remove the corresponding, unused argument.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/include/asm/spec-ctrl.h | 10 +++++-----
arch/x86/kernel/cpu/bugs.c | 2 +-
arch/x86/kvm/svm/svm.c | 4 ++--
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/arch/x86/include/asm/spec-ctrl.h b/arch/x86/include/asm/spec-ctrl.h
index 5393babc0598..cb0386fc4dc3 100644
--- a/arch/x86/include/asm/spec-ctrl.h
+++ b/arch/x86/include/asm/spec-ctrl.h
@@ -13,7 +13,7 @@
* Takes the guest view of SPEC_CTRL MSR as a parameter and also
* the guest's version of VIRT_SPEC_CTRL, if emulated.
*/
-extern void x86_virt_spec_ctrl(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl, bool guest);
+extern void x86_virt_spec_ctrl(u64 guest_virt_spec_ctrl, bool guest);
/**
* x86_spec_ctrl_set_guest - Set speculation control registers for the guest
@@ -24,9 +24,9 @@ extern void x86_virt_spec_ctrl(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl, bo
* Avoids writing to the MSR if the content/bits are the same
*/
static inline
-void x86_spec_ctrl_set_guest(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl)
+void x86_spec_ctrl_set_guest(u64 guest_virt_spec_ctrl)
{
- x86_virt_spec_ctrl(guest_spec_ctrl, guest_virt_spec_ctrl, true);
+ x86_virt_spec_ctrl(guest_virt_spec_ctrl, true);
}
/**
@@ -38,9 +38,9 @@ void x86_spec_ctrl_set_guest(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl)
* Avoids writing to the MSR if the content/bits are the same
*/
static inline
-void x86_spec_ctrl_restore_host(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl)
+void x86_spec_ctrl_restore_host(u64 guest_virt_spec_ctrl)
{
- x86_virt_spec_ctrl(guest_spec_ctrl, guest_virt_spec_ctrl, false);
+ x86_virt_spec_ctrl(guest_virt_spec_ctrl, false);
}
/* AMD specific Speculative Store Bypass MSR data */
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 6ec0b7ce7453..3e3230cccaa7 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -200,7 +200,7 @@ void __init check_bugs(void)
* MSR_IA32_SPEC_CTRL for SSBD.
*/
void
-x86_virt_spec_ctrl(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl, bool setguest)
+x86_virt_spec_ctrl(u64 guest_virt_spec_ctrl, bool setguest)
{
u64 guestval, hostval;
struct thread_info *ti = current_thread_info();
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index cf1aed25f4ab..9f88c8e6766e 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -3984,7 +3984,7 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
* being speculatively taken.
*/
if (!static_cpu_has(X86_FEATURE_V_SPEC_CTRL))
- x86_spec_ctrl_set_guest(svm->spec_ctrl, svm->virt_spec_ctrl);
+ x86_spec_ctrl_set_guest(svm->virt_spec_ctrl);
svm_vcpu_enter_exit(vcpu, spec_ctrl_intercepted);
@@ -3992,7 +3992,7 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
reload_tss(vcpu);
if (!static_cpu_has(X86_FEATURE_V_SPEC_CTRL))
- x86_spec_ctrl_restore_host(svm->spec_ctrl, svm->virt_spec_ctrl);
+ x86_spec_ctrl_restore_host(svm->virt_spec_ctrl);
if (!sev_es_guest(vcpu->kvm)) {
vcpu->arch.cr2 = svm->vmcb->save.cr2;
--
2.31.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH 01/11] KVM: x86: use a separate asm-offsets.c file
2022-11-09 14:51 ` [PATCH 01/11] KVM: x86: use a separate asm-offsets.c file Paolo Bonzini
@ 2022-11-09 15:06 ` Sean Christopherson
0 siblings, 0 replies; 24+ messages in thread
From: Sean Christopherson @ 2022-11-09 15:06 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: linux-kernel, kvm, thomas.lendacky, jmattson, stable
On Wed, Nov 09, 2022, Paolo Bonzini wrote:
> This already removes the ugly #includes from asm-offsets.c, but especially
> it avoids a future error when asm-offsets will try to include svm/svm.h.
>
> This would not work for kernel/asm-offsets.c, because svm/svm.h
> includes kvm_cache_regs.h which is not in the include path when
> compiling asm-offsets.c. The problem is not there if the .c file is
> in arch/x86/kvm.
>
> Suggested-by: Sean Christopherson <seanjc@google.com>
> Cc: stable@vger.kernel.org
> Fixes: a149180fbcf3 ("x86: Add magic AMD return-thunk")
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
Reviewed-by: Sean Christopherson <seanjc@google.com>
> diff --git a/arch/x86/kvm/vmx/vmenter.S b/arch/x86/kvm/vmx/vmenter.S
> index 8477d8bdd69c..0b5db4de4d09 100644
> --- a/arch/x86/kvm/vmx/vmenter.S
> +++ b/arch/x86/kvm/vmx/vmenter.S
> @@ -1,12 +1,12 @@
> /* SPDX-License-Identifier: GPL-2.0 */
> #include <linux/linkage.h>
> #include <asm/asm.h>
> -#include <asm/asm-offsets.h>
> #include <asm/bitsperlong.h>
> #include <asm/kvm_vcpu_regs.h>
> #include <asm/nospec-branch.h>
> #include <asm/percpu.h>
> #include <asm/segment.h>
> +#include "kvm-asm-offsets.h"
Do you have a preference on KVM files using dashes or underscores? Outside of
kvm-x86-ops.h and kvm-x86-pmu-ops.h, KVM x86 uses underscores. I actually prefer
dashes because they're slightly easier to type, but when there are only a few
outliers I constantly mistype the names. If dashes are generally, maybe we could
gradually/opportunistically move in that direction?
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 02/11] KVM: SVM: replace regs argument of __svm_vcpu_run with vcpu_svm
2022-11-09 14:51 ` [PATCH 02/11] KVM: SVM: replace regs argument of __svm_vcpu_run with vcpu_svm Paolo Bonzini
@ 2022-11-09 15:14 ` Sean Christopherson
0 siblings, 0 replies; 24+ messages in thread
From: Sean Christopherson @ 2022-11-09 15:14 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: linux-kernel, kvm, thomas.lendacky, jmattson, stable
Nit, () on function names. Maybe I should offer to buy you a beer every time you
remember to add parantheses :-)
On Wed, Nov 09, 2022, Paolo Bonzini wrote:
> Since registers are reachable through vcpu_svm, and we will
> need to access more fields of that struct, pass it instead
> of the regs[] array.
>
> No functional change intended.
>
> Cc: stable@vger.kernel.org
> Fixes: a149180fbcf3 ("x86: Add magic AMD return-thunk")
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
Reviewed-by: Sean Christopherson <seanjc@google.com>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 03/11] KVM: SVM: adjust register allocation for __svm_vcpu_run
2022-11-09 14:51 ` [PATCH 03/11] KVM: SVM: adjust register allocation for __svm_vcpu_run Paolo Bonzini
@ 2022-11-09 15:20 ` Sean Christopherson
2022-11-09 16:04 ` Paolo Bonzini
0 siblings, 1 reply; 24+ messages in thread
From: Sean Christopherson @ 2022-11-09 15:20 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: linux-kernel, kvm, thomas.lendacky, jmattson, stable
On Wed, Nov 09, 2022, Paolo Bonzini wrote:
> In preparation for moving vmload/vmsave to __svm_vcpu_run,
__svm_vcpu_run()
> keep the pointer to the struct vcpu_svm in %rdi. This way
> it is possible to load svm->vmcb01.pa in %rax without
> clobbering the pointer to svm itself.
If you feel like doing fixup before pushing, add a note to call out that avoiding
RAX will also be "necessary" to play nice with loading/storing MSR_SPEC_CTRL?
When fiddling with this code, I found the RDMSR/WRMSR clobbers to be far more
problematic than the VMCB pointers.
> No functional change intended.
>
> Cc: stable@vger.kernel.org
> Fixes: a149180fbcf3 ("x86: Add magic AMD return-thunk")
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Sean Christopherson <seanjc@google.com>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 04/11] KVM: SVM: retrieve VMCB from assembly
2022-11-09 14:51 ` [PATCH 04/11] KVM: SVM: retrieve VMCB from assembly Paolo Bonzini
@ 2022-11-09 15:25 ` Sean Christopherson
0 siblings, 0 replies; 24+ messages in thread
From: Sean Christopherson @ 2022-11-09 15:25 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: linux-kernel, kvm, thomas.lendacky, jmattson, stable
On Wed, Nov 09, 2022, Paolo Bonzini wrote:
> Continue moving all accesses to struct vcpu_svm directly in vmenter.S.
> This limits the confusion due to different registers used for
> argument passing in 32- and 64-bit ABIs.
>
> It is not strictly necessary for __svm_sev_es_vcpu_run, but staying
It's not strictly necessary at all ;-)
__svm_sev_es_vcpu_run()
> consistent is a good idea since it makes __svm_sev_es_vcpu_run a
__svm_sev_es_vcpu_run()
> stripped version of _svm_vcpu_run.
Missed an underscore. And parantheses.
> No functional change intended.
>
> Cc: stable@vger.kernel.org
> Fixes: a149180fbcf3 ("x86: Add magic AMD return-thunk")
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
Reviewed-by: Sean Christopherson <seanjc@google.com>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 05/11] KVM: SVM: remove unused field from struct vcpu_svm
2022-11-09 14:51 ` [PATCH 05/11] KVM: SVM: remove unused field from struct vcpu_svm Paolo Bonzini
@ 2022-11-09 15:25 ` Sean Christopherson
0 siblings, 0 replies; 24+ messages in thread
From: Sean Christopherson @ 2022-11-09 15:25 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: linux-kernel, kvm, thomas.lendacky, jmattson
On Wed, Nov 09, 2022, Paolo Bonzini wrote:
> The pointer to svm_cpu_data in struct vcpu_svm looks interesting from
> the point of view of accessing it after vmexit, when the GSBASE is still
> containing the guest value. However, despite existing since the very
> first commit of drivers/kvm/svm.c (commit 6aa8b732ca01, "[PATCH] kvm:
> userspace interface", 2006-12-10), it was never set to anything.
>
> Ignore the opportunity to fix a 16 year old "bug" and delete it; doing
> things the "harder" way makes it possible to remove more old cruft.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
Reviewed-by: Sean Christopherson <seanjc@google.com>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 06/11] KVM: SVM: remove dead field from struct svm_cpu_data
2022-11-09 14:51 ` [PATCH 06/11] KVM: SVM: remove dead field from struct svm_cpu_data Paolo Bonzini
@ 2022-11-09 15:26 ` Sean Christopherson
0 siblings, 0 replies; 24+ messages in thread
From: Sean Christopherson @ 2022-11-09 15:26 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: linux-kernel, kvm, thomas.lendacky, jmattson
On Wed, Nov 09, 2022, Paolo Bonzini wrote:
> The "cpu" field of struct svm_cpu_data has been write-only since commit
> 4b656b120249 ("KVM: SVM: force new asid on vcpu migration", 2009-08-05).
> Remove it.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
Reviewed-by: Sean Christopherson <seanjc@google.com>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 08/11] KVM: SVM: move guest vmsave/vmload back to assembly
2022-11-09 14:51 ` [PATCH 08/11] KVM: SVM: move guest vmsave/vmload back to assembly Paolo Bonzini
@ 2022-11-09 15:29 ` Sean Christopherson
0 siblings, 0 replies; 24+ messages in thread
From: Sean Christopherson @ 2022-11-09 15:29 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: linux-kernel, kvm, thomas.lendacky, jmattson, stable
On Wed, Nov 09, 2022, Paolo Bonzini wrote:
> FILL_RETURN_BUFFER can access percpu data, therefore vmload of the
> host save area must be executed first. First of all, move the VMCB
> vmsave/vmload to assembly, essentially undoing commit fb0c4a4fee5a ("KVM:
Nit, similar to adding parantheses to function names, I prefer capitalizing instruction
mnemonics, i.e. VMSAVE and VMLOAD, to make it obvious that you're referring to a
specific instruction as opposed to a theme/flow.
> SVM: move VMLOAD/VMSAVE to C code", 2021-03-15). The reason for that
> commit was that it made it simpler to use a different VMCB for
> VMLOAD/VMSAVE versus VMRUN; but that is not a big hassle anymore thanks
> to the kvm-asm-offsets machinery.
>
> The idea on how to number the exception tables is stolen from
> a prototype patch by Peter Zijlstra.
>
> Cc: stable@vger.kernel.org
> Fixes: a149180fbcf3 ("x86: Add magic AMD return-thunk")
> Link: <https://lore.kernel.org/all/f571e404-e625-bae1-10e9-449b2eb4cbd8@citrix.com/>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
Reviewed-by: Sean Christopherson <seanjc@google.com>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 09/11] KVM: SVM: restore host save area from assembly
2022-11-09 14:51 ` [PATCH 09/11] KVM: SVM: restore host save area from assembly Paolo Bonzini
@ 2022-11-09 15:54 ` Sean Christopherson
0 siblings, 0 replies; 24+ messages in thread
From: Sean Christopherson @ 2022-11-09 15:54 UTC (permalink / raw)
To: Paolo Bonzini
Cc: linux-kernel, kvm, thomas.lendacky, jmattson, stable,
Nathan Chancellor, Andrew Cooper
On Wed, Nov 09, 2022, Paolo Bonzini wrote:
> Allow access to the percpu area via the GS segment base, which is
> needed in order to access the saved host spec_ctrl value. In linux-next
> FILL_RETURN_BUFFER also needs to access percpu data.
>
> For simplicity, the physical address of the save area is added to struct
> svm_cpu_data.
>
> Cc: stable@vger.kernel.org
> Fixes: a149180fbcf3 ("x86: Add magic AMD return-thunk")
> Reported-by: Nathan Chancellor <nathan@kernel.org>
> Analyzed-by: Andrew Cooper <andrew.cooper3@citrix.com>
> Tested-by: Nathan Chancellor <nathan@kernel.org>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
Reviewed-by: Sean Christopherson <seanjc@google.com>
> diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
> index 2af6a71126c1..83955a4e520e 100644
> --- a/arch/x86/kvm/svm/svm.h
> +++ b/arch/x86/kvm/svm/svm.h
> @@ -287,6 +287,8 @@ struct svm_cpu_data {
> struct kvm_ldttss_desc *tss_desc;
>
> struct page *save_area;
> + unsigned long save_area_pa;
I really dislike storing both the page and the address, but that's more about
storing the "struct page" instead of the virtual address, and that can be cleaned
up in a follow-up series.
Specifically, the ugly pointer arithmetic in svm_prepare_switch_to_guest() can
be avoided by updating "struct vmcb" to capture SEV-ES+, and by tracking the save
area as a VMCB (which it is).
E.g. as a very partial patch
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index 0361626841bc..64ba98d32689 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -513,7 +513,10 @@ static inline void __unused_size_checks(void)
struct vmcb {
struct vmcb_control_area control;
- struct vmcb_save_area save;
+ union {
+ struct sev_es_save_area sev_es_save;
+ struct vmcb_save_area save;
+ }
} __packed;
#define SVM_CPUID_FUNC 0x8000000a
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 9f88c8e6766e..b23b7633033b 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -1462,12 +1462,8 @@ static void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
* or subsequent vmload of host save area.
*/
vmsave(sd->save_area_pa);
- if (sev_es_guest(vcpu->kvm)) {
- struct sev_es_save_area *hostsa;
- hostsa = (struct sev_es_save_area *)(page_address(sd->save_area) + 0x400);
-
- sev_es_prepare_switch_to_guest(hostsa);
- }
+ if (sev_es_guest(vcpu->kvm))
+ sev_es_prepare_switch_to_guest(sd->save_area->sev_es_save);
if (tsc_scaling)
__svm_write_tsc_multiplier(vcpu->arch.tsc_scaling_ratio);
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 199a2ecef1ce..802ed393d860 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -286,7 +286,7 @@ struct svm_cpu_data {
u32 min_asid;
struct kvm_ldttss_desc *tss_desc;
- struct page *save_area;
+ struct vmcb *save_area;
unsigned long save_area_pa;
struct vmcb *current_vmcb;
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH 07/11] KVM: SVM: do not allocate struct svm_cpu_data dynamically
2022-11-09 14:51 ` [PATCH 07/11] KVM: SVM: do not allocate struct svm_cpu_data dynamically Paolo Bonzini
@ 2022-11-09 15:58 ` Sean Christopherson
2022-11-09 16:00 ` Paolo Bonzini
0 siblings, 1 reply; 24+ messages in thread
From: Sean Christopherson @ 2022-11-09 15:58 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: linux-kernel, kvm, thomas.lendacky, jmattson
On Wed, Nov 09, 2022, Paolo Bonzini wrote:
> The svm_data percpu variable is a pointer, but it is allocated when
> KVM is loaded (via svm_hardware_setup), not at hardware_enable time.
Parantheses.
> Just allocate room for it statically, that is more efficient and
> does not waste any memory compared to the status quo.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Sean Christopherson <seanjc@google.com>
> @@ -3442,7 +3431,7 @@ static int svm_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
>
> static void reload_tss(struct kvm_vcpu *vcpu)
> {
> - struct svm_cpu_data *sd = per_cpu(svm_data, vcpu->cpu);
> + struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu);
>
> sd->tss_desc->type = 9; /* available 32/64-bit TSS */
> load_TR_desc();
> @@ -3450,7 +3439,7 @@ static void reload_tss(struct kvm_vcpu *vcpu)
>
> static void pre_svm_run(struct kvm_vcpu *vcpu)
> {
> - struct svm_cpu_data *sd = per_cpu(svm_data, vcpu->cpu);
> + struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu);
> struct vcpu_svm *svm = to_svm(vcpu);
>
> /*
> @@ -3919,7 +3908,7 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu)
> if (sev_es_guest(vcpu->kvm)) {
> __svm_sev_es_vcpu_run(svm);
> } else {
> - struct svm_cpu_data *sd = per_cpu(svm_data, vcpu->cpu);
> + struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu);
At some point we should replace the vcpu->cpu usage with this_cpu_ptr(). All of
the code that does per_cpu_ptr(&svm_data, vcpu->cpu) is doomed if vcpu->cpu isn't
the current CPU.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 07/11] KVM: SVM: do not allocate struct svm_cpu_data dynamically
2022-11-09 15:58 ` Sean Christopherson
@ 2022-11-09 16:00 ` Paolo Bonzini
0 siblings, 0 replies; 24+ messages in thread
From: Paolo Bonzini @ 2022-11-09 16:00 UTC (permalink / raw)
To: Sean Christopherson; +Cc: linux-kernel, kvm, thomas.lendacky, jmattson
On 11/9/22 16:58, Sean Christopherson wrote:
> At some point we should replace the vcpu->cpu usage with this_cpu_ptr(). All of
> the code that does per_cpu_ptr(&svm_data, vcpu->cpu) is doomed if vcpu->cpu isn't
> the current CPU.
Yes, I agree with all your other comments but I think they're better
done in next.
Paolo
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 10/11] KVM: SVM: move MSR_IA32_SPEC_CTRL save/restore to assembly
2022-11-09 14:51 ` [PATCH 10/11] KVM: SVM: move MSR_IA32_SPEC_CTRL save/restore to assembly Paolo Bonzini
@ 2022-11-09 16:04 ` Sean Christopherson
0 siblings, 0 replies; 24+ messages in thread
From: Sean Christopherson @ 2022-11-09 16:04 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: linux-kernel, kvm, thomas.lendacky, jmattson, stable
On Wed, Nov 09, 2022, Paolo Bonzini wrote:
> Restoration of the host IA32_SPEC_CTRL value is probably too late
> with respect to the return thunk training sequence.
>
> With respect to the user/kernel boundary, AMD says, "If software chooses
> to toggle STIBP (e.g., set STIBP on kernel entry, and clear it on kernel
> exit), software should set STIBP to 1 before executing the return thunk
> training sequence." I assume the same requirements apply to the guest/host
> boundary. The return thunk training sequence is in vmenter.S, quite close
> to the VM-exit. On hosts without V_SPEC_CTRL, however, the host's
> IA32_SPEC_CTRL value is not restored until much later.
>
> To avoid this, move the restoration of host SPEC_CTRL to assembly and,
> for consistency, move the restoration of the guest SPEC_CTRL as well.
> This is not particularly difficult, apart from some care to cover both
> 32- and 64-bit, and to share code between SEV-ES and normal vmentry.
>
> Cc: stable@vger.kernel.org
> Fixes: a149180fbcf3 ("x86: Add magic AMD return-thunk")
> Suggested-by: Jim Mattson <jmattson@google.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
Reviewed-by: Sean Christopherson <seanjc@google.com>
> +.ifnc _ASM_ARG1, _ASM_DI
> + /*
> + * Stash @svm in RDI early. On 32-bit, arguments are in RAX, RCX
> + * and RDX which are clobbered by RESTORE_GUEST_SPEC_CTRL.
> + */
> + mov %_ASM_ARG1, %_ASM_DI
> +.endif
Not technically needed since SEV-ES is 64-bit only, but that's a pre-exisiting
mess. I'll send a follow-up patch to #ifdef out the entire function and drop all
of this internal ifdeffery, and provide a stub in C code stub in C code so that
32-bit can link (and kill the VM if if the stub is reached).
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 03/11] KVM: SVM: adjust register allocation for __svm_vcpu_run
2022-11-09 15:20 ` Sean Christopherson
@ 2022-11-09 16:04 ` Paolo Bonzini
0 siblings, 0 replies; 24+ messages in thread
From: Paolo Bonzini @ 2022-11-09 16:04 UTC (permalink / raw)
To: Sean Christopherson; +Cc: linux-kernel, kvm, thomas.lendacky, jmattson, stable
On 11/9/22 16:20, Sean Christopherson wrote:
>> keep the pointer to the struct vcpu_svm in %rdi. This way
>> it is possible to load svm->vmcb01.pa in %rax without
>> clobbering the pointer to svm itself.
>
> If you feel like doing fixup before pushing, add a note to call out that avoiding
> RAX will also be "necessary" to play nice with loading/storing MSR_SPEC_CTRL?
> When fiddling with this code, I found the RDMSR/WRMSR clobbers to be far more
> problematic than the VMCB pointers.
I tried to avoid the "in the future" phrasing which some people dislike.
I'll rephrase anyway. Even without taking
RDMSR/WRMSR/VMLOAD/VMRUN/VMSAVE into account, avoiding the potential
clash with 32-bit register arguments is a decent reason for the patch
anyway.
Paolo
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2022-11-09 16:05 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-11-09 14:51 [PATCH v3 00/11] KVM: SVM: fixes for vmentry code Paolo Bonzini
2022-11-09 14:51 ` [PATCH 01/11] KVM: x86: use a separate asm-offsets.c file Paolo Bonzini
2022-11-09 15:06 ` Sean Christopherson
2022-11-09 14:51 ` [PATCH 02/11] KVM: SVM: replace regs argument of __svm_vcpu_run with vcpu_svm Paolo Bonzini
2022-11-09 15:14 ` Sean Christopherson
2022-11-09 14:51 ` [PATCH 03/11] KVM: SVM: adjust register allocation for __svm_vcpu_run Paolo Bonzini
2022-11-09 15:20 ` Sean Christopherson
2022-11-09 16:04 ` Paolo Bonzini
2022-11-09 14:51 ` [PATCH 04/11] KVM: SVM: retrieve VMCB from assembly Paolo Bonzini
2022-11-09 15:25 ` Sean Christopherson
2022-11-09 14:51 ` [PATCH 05/11] KVM: SVM: remove unused field from struct vcpu_svm Paolo Bonzini
2022-11-09 15:25 ` Sean Christopherson
2022-11-09 14:51 ` [PATCH 06/11] KVM: SVM: remove dead field from struct svm_cpu_data Paolo Bonzini
2022-11-09 15:26 ` Sean Christopherson
2022-11-09 14:51 ` [PATCH 07/11] KVM: SVM: do not allocate struct svm_cpu_data dynamically Paolo Bonzini
2022-11-09 15:58 ` Sean Christopherson
2022-11-09 16:00 ` Paolo Bonzini
2022-11-09 14:51 ` [PATCH 08/11] KVM: SVM: move guest vmsave/vmload back to assembly Paolo Bonzini
2022-11-09 15:29 ` Sean Christopherson
2022-11-09 14:51 ` [PATCH 09/11] KVM: SVM: restore host save area from assembly Paolo Bonzini
2022-11-09 15:54 ` Sean Christopherson
2022-11-09 14:51 ` [PATCH 10/11] KVM: SVM: move MSR_IA32_SPEC_CTRL save/restore to assembly Paolo Bonzini
2022-11-09 16:04 ` Sean Christopherson
2022-11-09 14:51 ` [PATCH 11/11] x86, KVM: remove unnecessary argument to x86_virt_spec_ctrl and callers Paolo Bonzini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).