mirror of
https://github.com/torvalds/linux.git
synced 2026-09-25 09:41:03 +02:00
KVM: selftests: Reuse GPR switching logic for nVMX
Reuse the GPR switching logic for nVMX by defining VMX_SWITCH_GPRS_ASM, which is essentially the same as SVM_SWITCH_GPRS_ASM but also switches RAX and doesn't switch RFLAGS, replacing the push/pop of a subset of the registers. The long clobber list of registers is no longer needed as registers are saved and restored appropriately (and not clobbered by L2). Define VMX_SWITCH_GPRS_ASM before including evmcs.h, such that it can be used by evmcs_vmlaunch() and evmcs_vmresume(). This replaces the apparently thread-safe push/pop sequence with the global GPR switching logic used by SVM, which isn't thread-safe at all. However this is still an improvement because: - The VMX logic is half-baked and prompts the UCALL clobber hack as it doesn't properly save/restore everything. Reusing the GPR switching logic used by SVM allows for dropping that hack. - Hitting a problem due to half-baked GPR save/restore logic is arguably more likely than thread-safety. Evidently, adding more involved stress tests fails on VMX with the existing push/pop sequence. OTOH, there are no known failures on SVM due to lack of thread-safety fo save/restore. Only one test currently uses more than one vCPU with nested (the memstress test). The logical next step is to move the guest_regs to be per-vCPU, making it thread-safe for both VMX and SVM in a proper way. Assisted-by: Gemini:gemini-3.1-pro Signed-off-by: Yosry Ahmed <yosry@kernel.org> Link: https://patch.msgid.link/20260728174232.2423257-6-yosry@kernel.org Signed-off-by: Sean Christopherson <seanjc@google.com>
This commit is contained in:
parent
9547309406
commit
3d31fea7b6
|
|
@ -1207,30 +1207,23 @@ static inline int evmcs_vmlaunch(void)
|
|||
|
||||
current_evmcs->hv_clean_fields = 0;
|
||||
|
||||
__asm__ __volatile__("push %%rbp;"
|
||||
"push %%rcx;"
|
||||
"push %%rdx;"
|
||||
"push %%rsi;"
|
||||
"push %%rdi;"
|
||||
"push $0;"
|
||||
__asm__ __volatile__("push $0;"
|
||||
"mov %%rsp, (%[host_rsp]);"
|
||||
"lea 1f(%%rip), %%rax;"
|
||||
"mov %%rax, (%[host_rip]);"
|
||||
VMX_SWITCH_GPRS_ASM
|
||||
"vmlaunch;"
|
||||
"incq (%%rsp);"
|
||||
"1: pop %%rax;"
|
||||
"pop %%rdi;"
|
||||
"pop %%rsi;"
|
||||
"pop %%rdx;"
|
||||
"pop %%rcx;"
|
||||
"pop %%rbp;"
|
||||
"1: ;"
|
||||
VMX_SWITCH_GPRS_ASM
|
||||
"pop %%rax;"
|
||||
: [ret]"=&a"(ret)
|
||||
: [host_rsp]"r"
|
||||
((u64)¤t_evmcs->host_rsp),
|
||||
[host_rip]"r"
|
||||
((u64)¤t_evmcs->host_rip)
|
||||
: "memory", "cc", "rbx", "r8", "r9", "r10",
|
||||
"r11", "r12", "r13", "r14", "r15");
|
||||
((u64)¤t_evmcs->host_rip),
|
||||
GUEST_REGS_OFFSETS
|
||||
: "memory", "cc");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1246,30 +1239,23 @@ static inline int evmcs_vmresume(void)
|
|||
/* HOST_RSP */
|
||||
current_evmcs->hv_clean_fields &= ~HV_VMX_ENLIGHTENED_CLEAN_FIELD_HOST_POINTER;
|
||||
|
||||
__asm__ __volatile__("push %%rbp;"
|
||||
"push %%rcx;"
|
||||
"push %%rdx;"
|
||||
"push %%rsi;"
|
||||
"push %%rdi;"
|
||||
"push $0;"
|
||||
__asm__ __volatile__("push $0;"
|
||||
"mov %%rsp, (%[host_rsp]);"
|
||||
"lea 1f(%%rip), %%rax;"
|
||||
"mov %%rax, (%[host_rip]);"
|
||||
VMX_SWITCH_GPRS_ASM
|
||||
"vmresume;"
|
||||
"incq (%%rsp);"
|
||||
"1: pop %%rax;"
|
||||
"pop %%rdi;"
|
||||
"pop %%rsi;"
|
||||
"pop %%rdx;"
|
||||
"pop %%rcx;"
|
||||
"pop %%rbp;"
|
||||
"1: ;"
|
||||
VMX_SWITCH_GPRS_ASM
|
||||
"pop %%rax;"
|
||||
: [ret]"=&a"(ret)
|
||||
: [host_rsp]"r"
|
||||
((u64)¤t_evmcs->host_rsp),
|
||||
[host_rip]"r"
|
||||
((u64)¤t_evmcs->host_rip)
|
||||
: "memory", "cc", "rbx", "r8", "r9", "r10",
|
||||
"r11", "r12", "r13", "r14", "r15");
|
||||
((u64)¤t_evmcs->host_rip),
|
||||
GUEST_REGS_OFFSETS
|
||||
: "memory", "cc");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -290,6 +290,23 @@ struct vmx_msr_entry {
|
|||
u64 value;
|
||||
} __attribute__ ((aligned(16)));
|
||||
|
||||
#define VMX_SWITCH_GPRS_ASM \
|
||||
GUEST_SWITCH_GPR_ASM(rax) \
|
||||
GUEST_SWITCH_GPR_ASM(rbx) \
|
||||
GUEST_SWITCH_GPR_ASM(rcx) \
|
||||
GUEST_SWITCH_GPR_ASM(rdx) \
|
||||
GUEST_SWITCH_GPR_ASM(rbp) \
|
||||
GUEST_SWITCH_GPR_ASM(rsi) \
|
||||
GUEST_SWITCH_GPR_ASM(rdi) \
|
||||
GUEST_SWITCH_GPR_ASM(r8) \
|
||||
GUEST_SWITCH_GPR_ASM(r9) \
|
||||
GUEST_SWITCH_GPR_ASM(r10) \
|
||||
GUEST_SWITCH_GPR_ASM(r11) \
|
||||
GUEST_SWITCH_GPR_ASM(r12) \
|
||||
GUEST_SWITCH_GPR_ASM(r13) \
|
||||
GUEST_SWITCH_GPR_ASM(r14) \
|
||||
GUEST_SWITCH_GPR_ASM(r15)
|
||||
|
||||
#include "evmcs.h"
|
||||
|
||||
static inline int vmxon(u64 phys)
|
||||
|
|
@ -363,9 +380,6 @@ static inline u64 vmptrstz(void)
|
|||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* No guest state (e.g. GPRs) is established by this vmlaunch.
|
||||
*/
|
||||
static inline int vmlaunch(void)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -373,34 +387,24 @@ static inline int vmlaunch(void)
|
|||
if (enable_evmcs)
|
||||
return evmcs_vmlaunch();
|
||||
|
||||
__asm__ __volatile__("push %%rbp;"
|
||||
"push %%rcx;"
|
||||
"push %%rdx;"
|
||||
"push %%rsi;"
|
||||
"push %%rdi;"
|
||||
"push $0;"
|
||||
__asm__ __volatile__("push $0;"
|
||||
"vmwrite %%rsp, %[host_rsp];"
|
||||
"lea 1f(%%rip), %%rax;"
|
||||
"vmwrite %%rax, %[host_rip];"
|
||||
VMX_SWITCH_GPRS_ASM
|
||||
"vmlaunch;"
|
||||
"incq (%%rsp);"
|
||||
"1: pop %%rax;"
|
||||
"pop %%rdi;"
|
||||
"pop %%rsi;"
|
||||
"pop %%rdx;"
|
||||
"pop %%rcx;"
|
||||
"pop %%rbp;"
|
||||
"1: ;"
|
||||
VMX_SWITCH_GPRS_ASM
|
||||
"pop %%rax;"
|
||||
: [ret]"=&a"(ret)
|
||||
: [host_rsp]"r"((u64)HOST_RSP),
|
||||
[host_rip]"r"((u64)HOST_RIP)
|
||||
: "memory", "cc", "rbx", "r8", "r9", "r10",
|
||||
"r11", "r12", "r13", "r14", "r15");
|
||||
[host_rip]"r"((u64)HOST_RIP),
|
||||
GUEST_REGS_OFFSETS
|
||||
: "memory", "cc");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* No guest state (e.g. GPRs) is established by this vmresume.
|
||||
*/
|
||||
static inline int vmresume(void)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -408,28 +412,21 @@ static inline int vmresume(void)
|
|||
if (enable_evmcs)
|
||||
return evmcs_vmresume();
|
||||
|
||||
__asm__ __volatile__("push %%rbp;"
|
||||
"push %%rcx;"
|
||||
"push %%rdx;"
|
||||
"push %%rsi;"
|
||||
"push %%rdi;"
|
||||
"push $0;"
|
||||
__asm__ __volatile__("push $0;"
|
||||
"vmwrite %%rsp, %[host_rsp];"
|
||||
"lea 1f(%%rip), %%rax;"
|
||||
"vmwrite %%rax, %[host_rip];"
|
||||
VMX_SWITCH_GPRS_ASM
|
||||
"vmresume;"
|
||||
"incq (%%rsp);"
|
||||
"1: pop %%rax;"
|
||||
"pop %%rdi;"
|
||||
"pop %%rsi;"
|
||||
"pop %%rdx;"
|
||||
"pop %%rcx;"
|
||||
"pop %%rbp;"
|
||||
"1: ;"
|
||||
VMX_SWITCH_GPRS_ASM
|
||||
"pop %%rax;"
|
||||
: [ret]"=&a"(ret)
|
||||
: [host_rsp]"r"((u64)HOST_RSP),
|
||||
[host_rip]"r"((u64)HOST_RIP)
|
||||
: "memory", "cc", "rbx", "r8", "r9", "r10",
|
||||
"r11", "r12", "r13", "r14", "r15");
|
||||
[host_rip]"r"((u64)HOST_RIP),
|
||||
GUEST_REGS_OFFSETS
|
||||
: "memory", "cc");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user