1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun#include <linux/linkage.h> 3*4882a593Smuzhiyun#include <asm/asm.h> 4*4882a593Smuzhiyun#include <asm/bitsperlong.h> 5*4882a593Smuzhiyun#include <asm/kvm_vcpu_regs.h> 6*4882a593Smuzhiyun#include <asm/nospec-branch.h> 7*4882a593Smuzhiyun#include <asm/segment.h> 8*4882a593Smuzhiyun#include "run_flags.h" 9*4882a593Smuzhiyun 10*4882a593Smuzhiyun#define WORD_SIZE (BITS_PER_LONG / 8) 11*4882a593Smuzhiyun 12*4882a593Smuzhiyun#define VCPU_RAX __VCPU_REGS_RAX * WORD_SIZE 13*4882a593Smuzhiyun#define VCPU_RCX __VCPU_REGS_RCX * WORD_SIZE 14*4882a593Smuzhiyun#define VCPU_RDX __VCPU_REGS_RDX * WORD_SIZE 15*4882a593Smuzhiyun#define VCPU_RBX __VCPU_REGS_RBX * WORD_SIZE 16*4882a593Smuzhiyun/* Intentionally omit RSP as it's context switched by hardware */ 17*4882a593Smuzhiyun#define VCPU_RBP __VCPU_REGS_RBP * WORD_SIZE 18*4882a593Smuzhiyun#define VCPU_RSI __VCPU_REGS_RSI * WORD_SIZE 19*4882a593Smuzhiyun#define VCPU_RDI __VCPU_REGS_RDI * WORD_SIZE 20*4882a593Smuzhiyun 21*4882a593Smuzhiyun#ifdef CONFIG_X86_64 22*4882a593Smuzhiyun#define VCPU_R8 __VCPU_REGS_R8 * WORD_SIZE 23*4882a593Smuzhiyun#define VCPU_R9 __VCPU_REGS_R9 * WORD_SIZE 24*4882a593Smuzhiyun#define VCPU_R10 __VCPU_REGS_R10 * WORD_SIZE 25*4882a593Smuzhiyun#define VCPU_R11 __VCPU_REGS_R11 * WORD_SIZE 26*4882a593Smuzhiyun#define VCPU_R12 __VCPU_REGS_R12 * WORD_SIZE 27*4882a593Smuzhiyun#define VCPU_R13 __VCPU_REGS_R13 * WORD_SIZE 28*4882a593Smuzhiyun#define VCPU_R14 __VCPU_REGS_R14 * WORD_SIZE 29*4882a593Smuzhiyun#define VCPU_R15 __VCPU_REGS_R15 * WORD_SIZE 30*4882a593Smuzhiyun#endif 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun.section .noinstr.text, "ax" 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun/** 35*4882a593Smuzhiyun * __vmx_vcpu_run - Run a vCPU via a transition to VMX guest mode 36*4882a593Smuzhiyun * @vmx: struct vcpu_vmx * 37*4882a593Smuzhiyun * @regs: unsigned long * (to guest registers) 38*4882a593Smuzhiyun * @flags: VMX_RUN_VMRESUME: use VMRESUME instead of VMLAUNCH 39*4882a593Smuzhiyun * VMX_RUN_SAVE_SPEC_CTRL: save guest SPEC_CTRL into vmx->spec_ctrl 40*4882a593Smuzhiyun * 41*4882a593Smuzhiyun * Returns: 42*4882a593Smuzhiyun * 0 on VM-Exit, 1 on VM-Fail 43*4882a593Smuzhiyun */ 44*4882a593SmuzhiyunSYM_FUNC_START(__vmx_vcpu_run) 45*4882a593Smuzhiyun push %_ASM_BP 46*4882a593Smuzhiyun mov %_ASM_SP, %_ASM_BP 47*4882a593Smuzhiyun#ifdef CONFIG_X86_64 48*4882a593Smuzhiyun push %r15 49*4882a593Smuzhiyun push %r14 50*4882a593Smuzhiyun push %r13 51*4882a593Smuzhiyun push %r12 52*4882a593Smuzhiyun#else 53*4882a593Smuzhiyun push %edi 54*4882a593Smuzhiyun push %esi 55*4882a593Smuzhiyun#endif 56*4882a593Smuzhiyun push %_ASM_BX 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun /* Save @vmx for SPEC_CTRL handling */ 59*4882a593Smuzhiyun push %_ASM_ARG1 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun /* Save @flags for SPEC_CTRL handling */ 62*4882a593Smuzhiyun push %_ASM_ARG3 63*4882a593Smuzhiyun 64*4882a593Smuzhiyun /* 65*4882a593Smuzhiyun * Save @regs, _ASM_ARG2 may be modified by vmx_update_host_rsp() and 66*4882a593Smuzhiyun * @regs is needed after VM-Exit to save the guest's register values. 67*4882a593Smuzhiyun */ 68*4882a593Smuzhiyun push %_ASM_ARG2 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun /* Copy @flags to BL, _ASM_ARG3 is volatile. */ 71*4882a593Smuzhiyun mov %_ASM_ARG3B, %bl 72*4882a593Smuzhiyun 73*4882a593Smuzhiyun lea (%_ASM_SP), %_ASM_ARG2 74*4882a593Smuzhiyun call vmx_update_host_rsp 75*4882a593Smuzhiyun 76*4882a593Smuzhiyun /* Load @regs to RAX. */ 77*4882a593Smuzhiyun mov (%_ASM_SP), %_ASM_AX 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun /* Check if vmlaunch or vmresume is needed */ 80*4882a593Smuzhiyun testb $VMX_RUN_VMRESUME, %bl 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun /* Load guest registers. Don't clobber flags. */ 83*4882a593Smuzhiyun mov VCPU_RCX(%_ASM_AX), %_ASM_CX 84*4882a593Smuzhiyun mov VCPU_RDX(%_ASM_AX), %_ASM_DX 85*4882a593Smuzhiyun mov VCPU_RBX(%_ASM_AX), %_ASM_BX 86*4882a593Smuzhiyun mov VCPU_RBP(%_ASM_AX), %_ASM_BP 87*4882a593Smuzhiyun mov VCPU_RSI(%_ASM_AX), %_ASM_SI 88*4882a593Smuzhiyun mov VCPU_RDI(%_ASM_AX), %_ASM_DI 89*4882a593Smuzhiyun#ifdef CONFIG_X86_64 90*4882a593Smuzhiyun mov VCPU_R8 (%_ASM_AX), %r8 91*4882a593Smuzhiyun mov VCPU_R9 (%_ASM_AX), %r9 92*4882a593Smuzhiyun mov VCPU_R10(%_ASM_AX), %r10 93*4882a593Smuzhiyun mov VCPU_R11(%_ASM_AX), %r11 94*4882a593Smuzhiyun mov VCPU_R12(%_ASM_AX), %r12 95*4882a593Smuzhiyun mov VCPU_R13(%_ASM_AX), %r13 96*4882a593Smuzhiyun mov VCPU_R14(%_ASM_AX), %r14 97*4882a593Smuzhiyun mov VCPU_R15(%_ASM_AX), %r15 98*4882a593Smuzhiyun#endif 99*4882a593Smuzhiyun /* Load guest RAX. This kills the @regs pointer! */ 100*4882a593Smuzhiyun mov VCPU_RAX(%_ASM_AX), %_ASM_AX 101*4882a593Smuzhiyun 102*4882a593Smuzhiyun /* Check EFLAGS.ZF from 'testb' above */ 103*4882a593Smuzhiyun jz .Lvmlaunch 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun /* 106*4882a593Smuzhiyun * After a successful VMRESUME/VMLAUNCH, control flow "magically" 107*4882a593Smuzhiyun * resumes below at 'vmx_vmexit' due to the VMCS HOST_RIP setting. 108*4882a593Smuzhiyun * So this isn't a typical function and objtool needs to be told to 109*4882a593Smuzhiyun * save the unwind state here and restore it below. 110*4882a593Smuzhiyun */ 111*4882a593Smuzhiyun UNWIND_HINT_SAVE 112*4882a593Smuzhiyun 113*4882a593Smuzhiyun/* 114*4882a593Smuzhiyun * If VMRESUME/VMLAUNCH and corresponding vmexit succeed, execution resumes at 115*4882a593Smuzhiyun * the 'vmx_vmexit' label below. 116*4882a593Smuzhiyun */ 117*4882a593Smuzhiyun.Lvmresume: 118*4882a593Smuzhiyun vmresume 119*4882a593Smuzhiyun jmp .Lvmfail 120*4882a593Smuzhiyun 121*4882a593Smuzhiyun.Lvmlaunch: 122*4882a593Smuzhiyun vmlaunch 123*4882a593Smuzhiyun jmp .Lvmfail 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun _ASM_EXTABLE(.Lvmresume, .Lfixup) 126*4882a593Smuzhiyun _ASM_EXTABLE(.Lvmlaunch, .Lfixup) 127*4882a593Smuzhiyun 128*4882a593SmuzhiyunSYM_INNER_LABEL(vmx_vmexit, SYM_L_GLOBAL) 129*4882a593Smuzhiyun 130*4882a593Smuzhiyun /* Restore unwind state from before the VMRESUME/VMLAUNCH. */ 131*4882a593Smuzhiyun UNWIND_HINT_RESTORE 132*4882a593Smuzhiyun 133*4882a593Smuzhiyun /* Temporarily save guest's RAX. */ 134*4882a593Smuzhiyun push %_ASM_AX 135*4882a593Smuzhiyun 136*4882a593Smuzhiyun /* Reload @regs to RAX. */ 137*4882a593Smuzhiyun mov WORD_SIZE(%_ASM_SP), %_ASM_AX 138*4882a593Smuzhiyun 139*4882a593Smuzhiyun /* Save all guest registers, including RAX from the stack */ 140*4882a593Smuzhiyun pop VCPU_RAX(%_ASM_AX) 141*4882a593Smuzhiyun mov %_ASM_CX, VCPU_RCX(%_ASM_AX) 142*4882a593Smuzhiyun mov %_ASM_DX, VCPU_RDX(%_ASM_AX) 143*4882a593Smuzhiyun mov %_ASM_BX, VCPU_RBX(%_ASM_AX) 144*4882a593Smuzhiyun mov %_ASM_BP, VCPU_RBP(%_ASM_AX) 145*4882a593Smuzhiyun mov %_ASM_SI, VCPU_RSI(%_ASM_AX) 146*4882a593Smuzhiyun mov %_ASM_DI, VCPU_RDI(%_ASM_AX) 147*4882a593Smuzhiyun#ifdef CONFIG_X86_64 148*4882a593Smuzhiyun mov %r8, VCPU_R8 (%_ASM_AX) 149*4882a593Smuzhiyun mov %r9, VCPU_R9 (%_ASM_AX) 150*4882a593Smuzhiyun mov %r10, VCPU_R10(%_ASM_AX) 151*4882a593Smuzhiyun mov %r11, VCPU_R11(%_ASM_AX) 152*4882a593Smuzhiyun mov %r12, VCPU_R12(%_ASM_AX) 153*4882a593Smuzhiyun mov %r13, VCPU_R13(%_ASM_AX) 154*4882a593Smuzhiyun mov %r14, VCPU_R14(%_ASM_AX) 155*4882a593Smuzhiyun mov %r15, VCPU_R15(%_ASM_AX) 156*4882a593Smuzhiyun#endif 157*4882a593Smuzhiyun 158*4882a593Smuzhiyun /* Clear return value to indicate VM-Exit (as opposed to VM-Fail). */ 159*4882a593Smuzhiyun xor %ebx, %ebx 160*4882a593Smuzhiyun 161*4882a593Smuzhiyun.Lclear_regs: 162*4882a593Smuzhiyun /* 163*4882a593Smuzhiyun * Clear all general purpose registers except RSP and RBX to prevent 164*4882a593Smuzhiyun * speculative use of the guest's values, even those that are reloaded 165*4882a593Smuzhiyun * via the stack. In theory, an L1 cache miss when restoring registers 166*4882a593Smuzhiyun * could lead to speculative execution with the guest's values. 167*4882a593Smuzhiyun * Zeroing XORs are dirt cheap, i.e. the extra paranoia is essentially 168*4882a593Smuzhiyun * free. RSP and RAX are exempt as RSP is restored by hardware during 169*4882a593Smuzhiyun * VM-Exit and RBX is explicitly loaded with 0 or 1 to hold the return 170*4882a593Smuzhiyun * value. 171*4882a593Smuzhiyun */ 172*4882a593Smuzhiyun xor %eax, %eax 173*4882a593Smuzhiyun xor %ecx, %ecx 174*4882a593Smuzhiyun xor %edx, %edx 175*4882a593Smuzhiyun xor %ebp, %ebp 176*4882a593Smuzhiyun xor %esi, %esi 177*4882a593Smuzhiyun xor %edi, %edi 178*4882a593Smuzhiyun#ifdef CONFIG_X86_64 179*4882a593Smuzhiyun xor %r8d, %r8d 180*4882a593Smuzhiyun xor %r9d, %r9d 181*4882a593Smuzhiyun xor %r10d, %r10d 182*4882a593Smuzhiyun xor %r11d, %r11d 183*4882a593Smuzhiyun xor %r12d, %r12d 184*4882a593Smuzhiyun xor %r13d, %r13d 185*4882a593Smuzhiyun xor %r14d, %r14d 186*4882a593Smuzhiyun xor %r15d, %r15d 187*4882a593Smuzhiyun#endif 188*4882a593Smuzhiyun 189*4882a593Smuzhiyun /* "POP" @regs. */ 190*4882a593Smuzhiyun add $WORD_SIZE, %_ASM_SP 191*4882a593Smuzhiyun 192*4882a593Smuzhiyun /* 193*4882a593Smuzhiyun * IMPORTANT: RSB filling and SPEC_CTRL handling must be done before 194*4882a593Smuzhiyun * the first unbalanced RET after vmexit! 195*4882a593Smuzhiyun * 196*4882a593Smuzhiyun * For retpoline or IBRS, RSB filling is needed to prevent poisoned RSB 197*4882a593Smuzhiyun * entries and (in some cases) RSB underflow. 198*4882a593Smuzhiyun * 199*4882a593Smuzhiyun * eIBRS has its own protection against poisoned RSB, so it doesn't 200*4882a593Smuzhiyun * need the RSB filling sequence. But it does need to be enabled, and a 201*4882a593Smuzhiyun * single call to retire, before the first unbalanced RET. 202*4882a593Smuzhiyun */ 203*4882a593Smuzhiyun 204*4882a593Smuzhiyun FILL_RETURN_BUFFER %_ASM_CX, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_VMEXIT,\ 205*4882a593Smuzhiyun X86_FEATURE_RSB_VMEXIT_LITE 206*4882a593Smuzhiyun 207*4882a593Smuzhiyun 208*4882a593Smuzhiyun pop %_ASM_ARG2 /* @flags */ 209*4882a593Smuzhiyun pop %_ASM_ARG1 /* @vmx */ 210*4882a593Smuzhiyun 211*4882a593Smuzhiyun call vmx_spec_ctrl_restore_host 212*4882a593Smuzhiyun 213*4882a593Smuzhiyun /* Put return value in AX */ 214*4882a593Smuzhiyun mov %_ASM_BX, %_ASM_AX 215*4882a593Smuzhiyun 216*4882a593Smuzhiyun pop %_ASM_BX 217*4882a593Smuzhiyun#ifdef CONFIG_X86_64 218*4882a593Smuzhiyun pop %r12 219*4882a593Smuzhiyun pop %r13 220*4882a593Smuzhiyun pop %r14 221*4882a593Smuzhiyun pop %r15 222*4882a593Smuzhiyun#else 223*4882a593Smuzhiyun pop %esi 224*4882a593Smuzhiyun pop %edi 225*4882a593Smuzhiyun#endif 226*4882a593Smuzhiyun pop %_ASM_BP 227*4882a593Smuzhiyun RET 228*4882a593Smuzhiyun 229*4882a593Smuzhiyun.Lfixup: 230*4882a593Smuzhiyun cmpb $0, kvm_rebooting 231*4882a593Smuzhiyun jne .Lvmfail 232*4882a593Smuzhiyun ud2 233*4882a593Smuzhiyun.Lvmfail: 234*4882a593Smuzhiyun /* VM-Fail: set return value to 1 */ 235*4882a593Smuzhiyun mov $1, %_ASM_BX 236*4882a593Smuzhiyun jmp .Lclear_regs 237*4882a593Smuzhiyun 238*4882a593SmuzhiyunSYM_FUNC_END(__vmx_vcpu_run) 239*4882a593Smuzhiyun 240*4882a593Smuzhiyun 241*4882a593Smuzhiyun.section .text, "ax" 242*4882a593Smuzhiyun 243*4882a593Smuzhiyun/** 244*4882a593Smuzhiyun * vmread_error_trampoline - Trampoline from inline asm to vmread_error() 245*4882a593Smuzhiyun * @field: VMCS field encoding that failed 246*4882a593Smuzhiyun * @fault: %true if the VMREAD faulted, %false if it failed 247*4882a593Smuzhiyun 248*4882a593Smuzhiyun * Save and restore volatile registers across a call to vmread_error(). Note, 249*4882a593Smuzhiyun * all parameters are passed on the stack. 250*4882a593Smuzhiyun */ 251*4882a593SmuzhiyunSYM_FUNC_START(vmread_error_trampoline) 252*4882a593Smuzhiyun push %_ASM_BP 253*4882a593Smuzhiyun mov %_ASM_SP, %_ASM_BP 254*4882a593Smuzhiyun 255*4882a593Smuzhiyun push %_ASM_AX 256*4882a593Smuzhiyun push %_ASM_CX 257*4882a593Smuzhiyun push %_ASM_DX 258*4882a593Smuzhiyun#ifdef CONFIG_X86_64 259*4882a593Smuzhiyun push %rdi 260*4882a593Smuzhiyun push %rsi 261*4882a593Smuzhiyun push %r8 262*4882a593Smuzhiyun push %r9 263*4882a593Smuzhiyun push %r10 264*4882a593Smuzhiyun push %r11 265*4882a593Smuzhiyun#endif 266*4882a593Smuzhiyun#ifdef CONFIG_X86_64 267*4882a593Smuzhiyun /* Load @field and @fault to arg1 and arg2 respectively. */ 268*4882a593Smuzhiyun mov 3*WORD_SIZE(%rbp), %_ASM_ARG2 269*4882a593Smuzhiyun mov 2*WORD_SIZE(%rbp), %_ASM_ARG1 270*4882a593Smuzhiyun#else 271*4882a593Smuzhiyun /* Parameters are passed on the stack for 32-bit (see asmlinkage). */ 272*4882a593Smuzhiyun push 3*WORD_SIZE(%ebp) 273*4882a593Smuzhiyun push 2*WORD_SIZE(%ebp) 274*4882a593Smuzhiyun#endif 275*4882a593Smuzhiyun 276*4882a593Smuzhiyun call vmread_error 277*4882a593Smuzhiyun 278*4882a593Smuzhiyun#ifndef CONFIG_X86_64 279*4882a593Smuzhiyun add $8, %esp 280*4882a593Smuzhiyun#endif 281*4882a593Smuzhiyun 282*4882a593Smuzhiyun /* Zero out @fault, which will be popped into the result register. */ 283*4882a593Smuzhiyun _ASM_MOV $0, 3*WORD_SIZE(%_ASM_BP) 284*4882a593Smuzhiyun 285*4882a593Smuzhiyun#ifdef CONFIG_X86_64 286*4882a593Smuzhiyun pop %r11 287*4882a593Smuzhiyun pop %r10 288*4882a593Smuzhiyun pop %r9 289*4882a593Smuzhiyun pop %r8 290*4882a593Smuzhiyun pop %rsi 291*4882a593Smuzhiyun pop %rdi 292*4882a593Smuzhiyun#endif 293*4882a593Smuzhiyun pop %_ASM_DX 294*4882a593Smuzhiyun pop %_ASM_CX 295*4882a593Smuzhiyun pop %_ASM_AX 296*4882a593Smuzhiyun pop %_ASM_BP 297*4882a593Smuzhiyun 298*4882a593Smuzhiyun RET 299*4882a593SmuzhiyunSYM_FUNC_END(vmread_error_trampoline) 300*4882a593Smuzhiyun 301*4882a593SmuzhiyunSYM_FUNC_START(vmx_do_interrupt_nmi_irqoff) 302*4882a593Smuzhiyun /* 303*4882a593Smuzhiyun * Unconditionally create a stack frame, getting the correct RSP on the 304*4882a593Smuzhiyun * stack (for x86-64) would take two instructions anyways, and RBP can 305*4882a593Smuzhiyun * be used to restore RSP to make objtool happy (see below). 306*4882a593Smuzhiyun */ 307*4882a593Smuzhiyun push %_ASM_BP 308*4882a593Smuzhiyun mov %_ASM_SP, %_ASM_BP 309*4882a593Smuzhiyun 310*4882a593Smuzhiyun#ifdef CONFIG_X86_64 311*4882a593Smuzhiyun /* 312*4882a593Smuzhiyun * Align RSP to a 16-byte boundary (to emulate CPU behavior) before 313*4882a593Smuzhiyun * creating the synthetic interrupt stack frame for the IRQ/NMI. 314*4882a593Smuzhiyun */ 315*4882a593Smuzhiyun and $-16, %rsp 316*4882a593Smuzhiyun push $__KERNEL_DS 317*4882a593Smuzhiyun push %rbp 318*4882a593Smuzhiyun#endif 319*4882a593Smuzhiyun pushf 320*4882a593Smuzhiyun push $__KERNEL_CS 321*4882a593Smuzhiyun CALL_NOSPEC _ASM_ARG1 322*4882a593Smuzhiyun 323*4882a593Smuzhiyun /* 324*4882a593Smuzhiyun * "Restore" RSP from RBP, even though IRET has already unwound RSP to 325*4882a593Smuzhiyun * the correct value. objtool doesn't know the callee will IRET and, 326*4882a593Smuzhiyun * without the explicit restore, thinks the stack is getting walloped. 327*4882a593Smuzhiyun * Using an unwind hint is problematic due to x86-64's dynamic alignment. 328*4882a593Smuzhiyun */ 329*4882a593Smuzhiyun mov %_ASM_BP, %_ASM_SP 330*4882a593Smuzhiyun pop %_ASM_BP 331*4882a593Smuzhiyun RET 332*4882a593SmuzhiyunSYM_FUNC_END(vmx_do_interrupt_nmi_irqoff) 333