Commit 7b664cc3 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'x86_tdx_for_6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 tdx update from Dave Hansen:
 "The original tdx hypercall assembly code took two flags in %RSI to
  tweak its behavior at runtime. PeterZ recently axed one flag in commit
  e80a48ba ("x86/tdx: Remove TDX_HCALL_ISSUE_STI").

  Kill the other flag too and tweak the 'output' mode with an assembly
  macro instead. This results in elimination of one push/pop pair and
  overall easier to read assembly.

   - Do conditional __tdx_hypercall() 'output' processing via an
     assembly macro argument rather than a runtime register"

* tag 'x86_tdx_for_6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/tdx: Drop flags from __tdx_hypercall()
parents e54debe6 7a3a4018
...@@ -26,7 +26,7 @@ static inline unsigned int tdx_io_in(int size, u16 port) ...@@ -26,7 +26,7 @@ static inline unsigned int tdx_io_in(int size, u16 port)
.r14 = port, .r14 = port,
}; };
if (__tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT)) if (__tdx_hypercall_ret(&args))
return UINT_MAX; return UINT_MAX;
return args.r11; return args.r11;
...@@ -43,7 +43,7 @@ static inline void tdx_io_out(int size, u16 port, u32 value) ...@@ -43,7 +43,7 @@ static inline void tdx_io_out(int size, u16 port, u32 value)
.r15 = value, .r15 = value,
}; };
__tdx_hypercall(&args, 0); __tdx_hypercall(&args);
} }
static inline u8 tdx_inb(u16 port) static inline u8 tdx_inb(u16 port)
......
...@@ -85,12 +85,12 @@ SYM_FUNC_START(__tdx_module_call) ...@@ -85,12 +85,12 @@ SYM_FUNC_START(__tdx_module_call)
SYM_FUNC_END(__tdx_module_call) SYM_FUNC_END(__tdx_module_call)
/* /*
* __tdx_hypercall() - Make hypercalls to a TDX VMM using TDVMCALL leaf * TDX_HYPERCALL - Make hypercalls to a TDX VMM using TDVMCALL leaf of TDCALL
* of TDCALL instruction * instruction
* *
* Transforms values in function call argument struct tdx_hypercall_args @args * Transforms values in function call argument struct tdx_hypercall_args @args
* into the TDCALL register ABI. After TDCALL operation, VMM output is saved * into the TDCALL register ABI. After TDCALL operation, VMM output is saved
* back in @args. * back in @args, if \ret is 1.
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
* TD VMCALL ABI: * TD VMCALL ABI:
...@@ -105,26 +105,18 @@ SYM_FUNC_END(__tdx_module_call) ...@@ -105,26 +105,18 @@ SYM_FUNC_END(__tdx_module_call)
* specification. Non zero value indicates vendor * specification. Non zero value indicates vendor
* specific ABI. * specific ABI.
* R11 - VMCALL sub function number * R11 - VMCALL sub function number
* RBX, RBP, RDI, RSI - Used to pass VMCALL sub function specific arguments. * RBX, RDX, RDI, RSI - Used to pass VMCALL sub function specific arguments.
* R8-R9, R12-R15 - Same as above. * R8-R9, R12-R15 - Same as above.
* *
* Output Registers: * Output Registers:
* *
* RAX - TDCALL instruction status (Not related to hypercall * RAX - TDCALL instruction status (Not related to hypercall
* output). * output).
* R10 - Hypercall output error code. * RBX, RDX, RDI, RSI - Hypercall sub function specific output values.
* R11-R15 - Hypercall sub function specific output values. * R8-R15 - Same as above.
* *
*-------------------------------------------------------------------------
*
* __tdx_hypercall() function ABI:
*
* @args (RDI) - struct tdx_hypercall_args for input and output
* @flags (RSI) - TDX_HCALL_* flags
*
* On successful completion, return the hypercall error code.
*/ */
SYM_FUNC_START(__tdx_hypercall) .macro TDX_HYPERCALL ret:req
FRAME_BEGIN FRAME_BEGIN
/* Save callee-saved GPRs as mandated by the x86_64 ABI */ /* Save callee-saved GPRs as mandated by the x86_64 ABI */
...@@ -134,9 +126,8 @@ SYM_FUNC_START(__tdx_hypercall) ...@@ -134,9 +126,8 @@ SYM_FUNC_START(__tdx_hypercall)
push %r12 push %r12
push %rbx push %rbx
/* Free RDI and RSI to be used as TDVMCALL arguments */ /* Free RDI to be used as TDVMCALL arguments */
movq %rdi, %rax movq %rdi, %rax
push %rsi
/* Copy hypercall registers from arg struct: */ /* Copy hypercall registers from arg struct: */
movq TDX_HYPERCALL_r8(%rax), %r8 movq TDX_HYPERCALL_r8(%rax), %r8
...@@ -171,14 +162,11 @@ SYM_FUNC_START(__tdx_hypercall) ...@@ -171,14 +162,11 @@ SYM_FUNC_START(__tdx_hypercall)
* and are handled by callers. * and are handled by callers.
*/ */
testq %rax, %rax testq %rax, %rax
jne .Lpanic jne .Lpanic\@
pop %rax pop %rax
/* Copy hypercall result registers to arg struct if needed */ .if \ret
testq $TDX_HCALL_HAS_OUTPUT, (%rsp)
jz .Lout
movq %r8, TDX_HYPERCALL_r8(%rax) movq %r8, TDX_HYPERCALL_r8(%rax)
movq %r9, TDX_HYPERCALL_r9(%rax) movq %r9, TDX_HYPERCALL_r9(%rax)
movq %r10, TDX_HYPERCALL_r10(%rax) movq %r10, TDX_HYPERCALL_r10(%rax)
...@@ -191,7 +179,8 @@ SYM_FUNC_START(__tdx_hypercall) ...@@ -191,7 +179,8 @@ SYM_FUNC_START(__tdx_hypercall)
movq %rsi, TDX_HYPERCALL_rsi(%rax) movq %rsi, TDX_HYPERCALL_rsi(%rax)
movq %rbx, TDX_HYPERCALL_rbx(%rax) movq %rbx, TDX_HYPERCALL_rbx(%rax)
movq %rdx, TDX_HYPERCALL_rdx(%rax) movq %rdx, TDX_HYPERCALL_rdx(%rax)
.Lout: .endif
/* TDVMCALL leaf return code is in R10 */ /* TDVMCALL leaf return code is in R10 */
movq %r10, %rax movq %r10, %rax
...@@ -208,9 +197,6 @@ SYM_FUNC_START(__tdx_hypercall) ...@@ -208,9 +197,6 @@ SYM_FUNC_START(__tdx_hypercall)
xor %rdi, %rdi xor %rdi, %rdi
xor %rdx, %rdx xor %rdx, %rdx
/* Remove TDX_HCALL_* flags from the stack */
pop %rsi
/* Restore callee-saved GPRs as mandated by the x86_64 ABI */ /* Restore callee-saved GPRs as mandated by the x86_64 ABI */
pop %rbx pop %rbx
pop %r12 pop %r12
...@@ -221,9 +207,33 @@ SYM_FUNC_START(__tdx_hypercall) ...@@ -221,9 +207,33 @@ SYM_FUNC_START(__tdx_hypercall)
FRAME_END FRAME_END
RET RET
.Lpanic: .Lpanic\@:
call __tdx_hypercall_failed call __tdx_hypercall_failed
/* __tdx_hypercall_failed never returns */ /* __tdx_hypercall_failed never returns */
REACHABLE REACHABLE
jmp .Lpanic jmp .Lpanic\@
.endm
/*
*
* __tdx_hypercall() function ABI:
*
* @args (RDI) - struct tdx_hypercall_args for input
*
* On successful completion, return the hypercall error code.
*/
SYM_FUNC_START(__tdx_hypercall)
TDX_HYPERCALL ret=0
SYM_FUNC_END(__tdx_hypercall) SYM_FUNC_END(__tdx_hypercall)
/*
*
* __tdx_hypercall_ret() function ABI:
*
* @args (RDI) - struct tdx_hypercall_args for input and output
*
* On successful completion, return the hypercall error code.
*/
SYM_FUNC_START(__tdx_hypercall_ret)
TDX_HYPERCALL ret=1
SYM_FUNC_END(__tdx_hypercall_ret)
...@@ -66,7 +66,7 @@ static inline u64 _tdx_hypercall(u64 fn, u64 r12, u64 r13, u64 r14, u64 r15) ...@@ -66,7 +66,7 @@ static inline u64 _tdx_hypercall(u64 fn, u64 r12, u64 r13, u64 r14, u64 r15)
.r15 = r15, .r15 = r15,
}; };
return __tdx_hypercall(&args, 0); return __tdx_hypercall(&args);
} }
/* Called from __tdx_hypercall() for unrecoverable failure */ /* Called from __tdx_hypercall() for unrecoverable failure */
...@@ -99,7 +99,7 @@ long tdx_kvm_hypercall(unsigned int nr, unsigned long p1, unsigned long p2, ...@@ -99,7 +99,7 @@ long tdx_kvm_hypercall(unsigned int nr, unsigned long p1, unsigned long p2,
.r14 = p4, .r14 = p4,
}; };
return __tdx_hypercall(&args, 0); return __tdx_hypercall(&args);
} }
EXPORT_SYMBOL_GPL(tdx_kvm_hypercall); EXPORT_SYMBOL_GPL(tdx_kvm_hypercall);
#endif #endif
...@@ -179,7 +179,7 @@ static void __noreturn tdx_panic(const char *msg) ...@@ -179,7 +179,7 @@ static void __noreturn tdx_panic(const char *msg)
* happens to return. * happens to return.
*/ */
while (1) while (1)
__tdx_hypercall(&args, 0); __tdx_hypercall(&args);
} }
static void tdx_parse_tdinfo(u64 *cc_mask) static void tdx_parse_tdinfo(u64 *cc_mask)
...@@ -289,7 +289,7 @@ static u64 __cpuidle __halt(const bool irq_disabled) ...@@ -289,7 +289,7 @@ static u64 __cpuidle __halt(const bool irq_disabled)
* can keep the vCPU in virtual HLT, even if an IRQ is * can keep the vCPU in virtual HLT, even if an IRQ is
* pending, without hanging/breaking the guest. * pending, without hanging/breaking the guest.
*/ */
return __tdx_hypercall(&args, 0); return __tdx_hypercall(&args);
} }
static int handle_halt(struct ve_info *ve) static int handle_halt(struct ve_info *ve)
...@@ -326,7 +326,7 @@ static int read_msr(struct pt_regs *regs, struct ve_info *ve) ...@@ -326,7 +326,7 @@ static int read_msr(struct pt_regs *regs, struct ve_info *ve)
* can be found in TDX Guest-Host-Communication Interface * can be found in TDX Guest-Host-Communication Interface
* (GHCI), section titled "TDG.VP.VMCALL<Instruction.RDMSR>". * (GHCI), section titled "TDG.VP.VMCALL<Instruction.RDMSR>".
*/ */
if (__tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT)) if (__tdx_hypercall_ret(&args))
return -EIO; return -EIO;
regs->ax = lower_32_bits(args.r11); regs->ax = lower_32_bits(args.r11);
...@@ -348,7 +348,7 @@ static int write_msr(struct pt_regs *regs, struct ve_info *ve) ...@@ -348,7 +348,7 @@ static int write_msr(struct pt_regs *regs, struct ve_info *ve)
* can be found in TDX Guest-Host-Communication Interface * can be found in TDX Guest-Host-Communication Interface
* (GHCI) section titled "TDG.VP.VMCALL<Instruction.WRMSR>". * (GHCI) section titled "TDG.VP.VMCALL<Instruction.WRMSR>".
*/ */
if (__tdx_hypercall(&args, 0)) if (__tdx_hypercall(&args))
return -EIO; return -EIO;
return ve_instr_len(ve); return ve_instr_len(ve);
...@@ -380,7 +380,7 @@ static int handle_cpuid(struct pt_regs *regs, struct ve_info *ve) ...@@ -380,7 +380,7 @@ static int handle_cpuid(struct pt_regs *regs, struct ve_info *ve)
* ABI can be found in TDX Guest-Host-Communication Interface * ABI can be found in TDX Guest-Host-Communication Interface
* (GHCI), section titled "VP.VMCALL<Instruction.CPUID>". * (GHCI), section titled "VP.VMCALL<Instruction.CPUID>".
*/ */
if (__tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT)) if (__tdx_hypercall_ret(&args))
return -EIO; return -EIO;
/* /*
...@@ -407,7 +407,7 @@ static bool mmio_read(int size, unsigned long addr, unsigned long *val) ...@@ -407,7 +407,7 @@ static bool mmio_read(int size, unsigned long addr, unsigned long *val)
.r15 = *val, .r15 = *val,
}; };
if (__tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT)) if (__tdx_hypercall_ret(&args))
return false; return false;
*val = args.r11; *val = args.r11;
return true; return true;
...@@ -541,7 +541,7 @@ static bool handle_in(struct pt_regs *regs, int size, int port) ...@@ -541,7 +541,7 @@ static bool handle_in(struct pt_regs *regs, int size, int port)
* in TDX Guest-Host-Communication Interface (GHCI) section titled * in TDX Guest-Host-Communication Interface (GHCI) section titled
* "TDG.VP.VMCALL<Instruction.IO>". * "TDG.VP.VMCALL<Instruction.IO>".
*/ */
success = !__tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT); success = !__tdx_hypercall_ret(&args);
/* Update part of the register affected by the emulated instruction */ /* Update part of the register affected by the emulated instruction */
regs->ax &= ~mask; regs->ax &= ~mask;
......
...@@ -7,8 +7,6 @@ ...@@ -7,8 +7,6 @@
#define TDX_HYPERCALL_STANDARD 0 #define TDX_HYPERCALL_STANDARD 0
#define TDX_HCALL_HAS_OUTPUT BIT(0)
#define TDX_CPUID_LEAF_ID 0x21 #define TDX_CPUID_LEAF_ID 0x21
#define TDX_IDENT "IntelTDX " #define TDX_IDENT "IntelTDX "
...@@ -36,7 +34,8 @@ struct tdx_hypercall_args { ...@@ -36,7 +34,8 @@ struct tdx_hypercall_args {
}; };
/* Used to request services from the VMM */ /* Used to request services from the VMM */
u64 __tdx_hypercall(struct tdx_hypercall_args *args, unsigned long flags); u64 __tdx_hypercall(struct tdx_hypercall_args *args);
u64 __tdx_hypercall_ret(struct tdx_hypercall_args *args);
/* Called from __tdx_hypercall() for unrecoverable failure */ /* Called from __tdx_hypercall() for unrecoverable failure */
void __tdx_hypercall_failed(void); void __tdx_hypercall_failed(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment