提交 8fda37cf 编写于 作者: V Vitaly Kuznetsov 提交者: Paolo Bonzini

KVM: selftests: Stuff RAX/RCX with 'safe' values in vmmcall()/vmcall()

vmmcall()/vmcall() are used to exit from L2 to L1 and no concrete hypercall
ABI is currenty followed. With the introduction of Hyper-V L2 TLB flush
it becomes (theoretically) possible that L0 will take responsibility for
handling the call and no L1 exit will happen. Prevent this by stuffing RAX
(KVM ABI) and RCX (Hyper-V ABI) with 'safe' values.

While on it, convert vmmcall() to 'static inline', make it setup stack
frame and move to include/x86_64/svm_util.h.
Signed-off-by: NVitaly Kuznetsov <vkuznets@redhat.com>
Reviewed-by: NSean Christopherson <seanjc@google.com>
Signed-off-by: NPaolo Bonzini <pbonzini@redhat.com>
Message-Id: <20221101145426.251680-45-vkuznets@redhat.com>
Signed-off-by: NPaolo Bonzini <pbonzini@redhat.com>
上级 6c15c3c4
...@@ -677,11 +677,6 @@ static inline void cpu_relax(void) ...@@ -677,11 +677,6 @@ static inline void cpu_relax(void)
asm volatile("rep; nop" ::: "memory"); asm volatile("rep; nop" ::: "memory");
} }
#define vmmcall() \
__asm__ __volatile__( \
"vmmcall\n" \
)
#define ud2() \ #define ud2() \
__asm__ __volatile__( \ __asm__ __volatile__( \
"ud2\n" \ "ud2\n" \
......
...@@ -32,6 +32,20 @@ struct svm_test_data { ...@@ -32,6 +32,20 @@ struct svm_test_data {
uint64_t msr_gpa; uint64_t msr_gpa;
}; };
static inline void vmmcall(void)
{
/*
* Stuff RAX and RCX with "safe" values to make sure L0 doesn't handle
* it as a valid hypercall (e.g. Hyper-V L2 TLB flush) as the intended
* use of this function is to exit to L1 from L2. Clobber all other
* GPRs as L1 doesn't correctly preserve them during vmexits.
*/
__asm__ __volatile__("push %%rbp; vmmcall; pop %%rbp"
: : "a"(0xdeadbeef), "c"(0xbeefdead)
: "rbx", "rdx", "rsi", "rdi", "r8", "r9",
"r10", "r11", "r12", "r13", "r14", "r15");
}
#define stgi() \ #define stgi() \
__asm__ __volatile__( \ __asm__ __volatile__( \
"stgi\n" \ "stgi\n" \
......
...@@ -437,11 +437,16 @@ static inline int vmresume(void) ...@@ -437,11 +437,16 @@ static inline int vmresume(void)
static inline void vmcall(void) static inline void vmcall(void)
{ {
/* Currently, L1 destroys our GPRs during vmexits. */ /*
__asm__ __volatile__("push %%rbp; vmcall; pop %%rbp" : : : * Stuff RAX and RCX with "safe" values to make sure L0 doesn't handle
"rax", "rbx", "rcx", "rdx", * it as a valid hypercall (e.g. Hyper-V L2 TLB flush) as the intended
"rsi", "rdi", "r8", "r9", "r10", "r11", "r12", * use of this function is to exit to L1 from L2. Clobber all other
"r13", "r14", "r15"); * GPRs as L1 doesn't correctly preserve them during vmexits.
*/
__asm__ __volatile__("push %%rbp; vmcall; pop %%rbp"
: : "a"(0xdeadbeef), "c"(0xbeefdead)
: "rbx", "rdx", "rsi", "rdi", "r8", "r9",
"r10", "r11", "r12", "r13", "r14", "r15");
} }
static inline int vmread(uint64_t encoding, uint64_t *value) static inline int vmread(uint64_t encoding, uint64_t *value)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册