lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Mon, 21 Nov 2022 11:51:46 -0800
From:   Dexuan Cui <decui@...rosoft.com>
To:     ak@...ux.intel.com, arnd@...db.de, bp@...en8.de,
        brijesh.singh@....com, dan.j.williams@...el.com,
        dave.hansen@...ux.intel.com, haiyangz@...rosoft.com, hpa@...or.com,
        jane.chu@...cle.com, kirill.shutemov@...ux.intel.com,
        kys@...rosoft.com, linux-arch@...r.kernel.org,
        linux-hyperv@...r.kernel.org, luto@...nel.org, mingo@...hat.com,
        peterz@...radead.org, rostedt@...dmis.org,
        sathyanarayanan.kuppuswamy@...ux.intel.com, seanjc@...gle.com,
        tglx@...utronix.de, tony.luck@...el.com, wei.liu@...nel.org,
        x86@...nel.org
Cc:     linux-kernel@...r.kernel.org, Dexuan Cui <decui@...rosoft.com>
Subject: [PATCH 1/6] x86/tdx: Support hypercalls for TDX guests on Hyper-V

__tdx_hypercall() doesn't work for a TDX guest running on Hyper-V,
because Hyper-V uses a different calling convention, so add the
new function __tdx_ms_hv_hypercall().

Signed-off-by: Dexuan Cui <decui@...rosoft.com>
---
 arch/x86/coco/tdx/tdcall.S      | 87 +++++++++++++++++++++++++++++++++
 arch/x86/include/asm/mshyperv.h |  2 +
 2 files changed, 89 insertions(+)

diff --git a/arch/x86/coco/tdx/tdcall.S b/arch/x86/coco/tdx/tdcall.S
index f9eb1134f22d..468b71738485 100644
--- a/arch/x86/coco/tdx/tdcall.S
+++ b/arch/x86/coco/tdx/tdcall.S
@@ -13,6 +13,8 @@
 /*
  * Bitmasks of exposed registers (with VMM).
  */
+#define TDX_RDX		BIT(2)
+#define TDX_R8		BIT(8)
 #define TDX_R10		BIT(10)
 #define TDX_R11		BIT(11)
 #define TDX_R12		BIT(12)
@@ -203,3 +205,88 @@ SYM_FUNC_START(__tdx_hypercall)
 	REACHABLE
 	jmp .Lpanic
 SYM_FUNC_END(__tdx_hypercall)
+
+/*
+ * __tdx_ms_hv_hypercall() - Make hypercalls to Hype-V using TDVMCALL leaf
+ * of TDCALL instruction
+ *
+ * Transforms values in function call arguments "input control, output_addr,
+ * and input_addr" into the TDCALL register ABI. After TDCALL operation,
+ * Hyper-V has changed the memory pointed by output_addr, and R11 is the
+ * output control code. Note: before the TDCALL operation, the guest must
+ * share the memory pointed by input_addr and output_addr with Hyper-V.
+ *-------------------------------------------------------------------------
+ * TD VMCALL ABI on Hyper-V:
+ *-------------------------------------------------------------------------
+ *
+ * Input Registers:
+ *
+ * RAX                 - TDCALL instruction leaf number (0 - TDG.VP.VMCALL)
+ * RCX                 - BITMAP which controls which part of TD Guest GPR
+ *                         is passed as-is to the VMM and back.
+ * R10                 - Set to Hyper-V hypercall input control code.
+ *                         Note: legal Hyper-V hypercall input control codes
+ *                         are always non-zero, i.e. they don't conflict with
+ *                         TDX_HYPERCALL_STANDARD.
+ * R8                  - Output physical addr.
+ * RDX                 - Input physical addr.
+ *
+ * Output Registers:
+ *
+ * RAX                 - TDCALL instruction status (Not related to hypercall
+ *                         output).
+ * R11                 - Output control code.
+ *
+ *-------------------------------------------------------------------------
+ *
+ * __tdx_ms_hv_hypercall() function ABI:
+ *
+ * @arg   (RDI)        - Input control code, moved to R10
+ * @arg   (RSI)        - Output address, moved to R8
+ * @arg   (RDX)        - Input address. RDX is passed to Hyper-V as-is.
+ *
+ * On successful completion, return the hypercall output control code.
+ */
+SYM_FUNC_START(__tdx_ms_hv_hypercall)
+	FRAME_BEGIN
+
+	/* Set TDCALL leaf ID (TDVMCALL (0)) in RAX */
+	xor %eax, %eax
+
+	/* Do not leak the value of the output-only register to Hyper-V */
+	xor %r11, %r11
+
+	/* Load input control code */
+	mov %rdi, %r10
+
+	/* Load output addr. NB: input addr is already in RDX. */
+	mov %rsi, %r8
+
+	/* Expose these registers to Hyper-V as-is */
+	mov $(TDX_RDX | TDX_R8 | TDX_R10 |TDX_R11), %ecx
+
+	tdcall
+
+	/*
+	 * RAX==0 indicates a failure of the TDVMCALL mechanism itself and that
+	 * something has gone horribly wrong with the TDX module.
+	 *
+	 * The return status of the hypercall operation is in a separate
+	 * register (in R11). Hypercall errors are a part of normal operation
+	 * and are handled by callers.
+	 */
+	testq %rax, %rax
+	jne .Lpanic_ms_hv
+
+	/* Copy output control code as the function's return value */
+	movq %r11, %rax
+
+	FRAME_END
+
+	RET
+.Lpanic_ms_hv:
+	call __tdx_hypercall_failed
+	/* __tdx_hypercall_failed never returns */
+	REACHABLE
+	jmp .Lpanic_ms_hv
+SYM_FUNC_END(__tdx_ms_hv_hypercall)
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 61f0c206bff0..fc09b6739922 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -36,6 +36,8 @@ int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages);
 int hv_call_add_logical_proc(int node, u32 lp_index, u32 acpi_id);
 int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags);
 
+u64 __tdx_ms_hv_hypercall(u64 control, u64 output_addr, u64 input_addr);
+
 static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
 {
 	u64 input_address = input ? virt_to_phys(input) : 0;
-- 
2.25.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ