armbian_build/patch/kernel/archive/wsl2-arm64-6.1/1666-Hyper-V-ARM64-Always-use-the-Hyper-V-hypercall-interface.patch
Ricardo Pardini 204d2e79b9 WSL2 "boards" wsl2-x86/wsl2-arm64 with current (6.1.y) and edge (6.6.y) kernels with Microsoft patches
> tl,dr: add 4 small-ish UEFI-like kernels, with Microsoft patches & fixes, for use with Microsoft WSL2 on x86/arm64 and 6.1.y/6.6.y

- the boards are UEFI derivatives, using a common `microsoft` vendor include to modify
  - `KERNELPATCHDIR`/`LINUXFAMILY` (for now, we don't want those patches in regular UEFI builds / .debs)
  - disable `EXTRAWIFI` (kernel is for a VM, will never have wifi so doesn't need any drivers)
  - `LINUXCONFIG`, so we can use Microsoft's own monolithic kernel, required for WSL2 (their initrd is a mistery)
- really, what we're mostly interested right now are the kernels (in the future we might have an "Armbian" WSL2 app in the Microsoft Store)
  - `current` `6.1.y`:
    - rebased from https://github.com/microsoft/WSL2-Linux-Kernel/tree/linux-msft-wsl-6.1.y onto real 6.1.y
    - using Microsoft's `.config` exactly (monolithic, there are no `=m`'s)
  - `edge` `6.6.y`:
    - also from https://github.com/microsoft/WSL2-Linux-Kernel/tree/linux-msft-wsl-6.1.y but rebased onto 6.6.y
    - using updated Microsoft's `.config` (monolithic, there are no `=m`'s)
    - dropped 2 of 6.1.y's patches that were actually upstreamed in the meantime:
      - `mm-page_reporting-Add-checks-for-page_reporting_order-param` - mainlined in https://lore.kernel.org/all/1664517699-1085-2-git-send-email-shradhagupta@linux.microsoft.com/
      - `hv_balloon-Add-support-for-configurable-order-free-page-reporting` - mainlined in https://lore.kernel.org/all/1664517699-1085-3-git-send-email-shradhagupta@linux.microsoft.com/
    - drop the `arm64: hyperv: Enable Hyper-V synthetic clocks/timers` patch, since it causes asm breakage on 6.6.y
      - a shame, but I tried and can't fix it myself - @kelleymh ?
    - add my own patch to fix:
      - `1709-drivers-hv-dxgkrnl-restore-uuid_le_cmp-removed-from-upstream-in-f5b3c341a.patch` due to https://lore.kernel.org/all/20230202145412.87569-1-andriy.shevchenko@linux.intel.com/ landing in 6.6
      - `1710-drivers-hv-dxgkrnl-adapt-dxg_remove_vmbus-to-96ec29396-s-reality-void-return.patch` to adapt to
        https://lore.kernel.org/all/TYCP286MB2323A93C55526E4DF239D3ACCAFA9@TYCP286MB2323.JPNP286.PROD.OUTLOOK.COM/
2023-11-27 11:14:01 +01:00

240 lines
7.2 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sunil Muthuswamy <sunilmut@microsoft.com>
Date: Mon, 3 May 2021 14:17:52 -0700
Subject: Hyper-V: ARM64: Always use the Hyper-V hypercall interface
This patch forces the use of the Hyper-V hypercall interface,
instead of the architectural SMCCC interface on ARM64 because
not all versions of Windows support the SMCCC interface. All
versions of Windows will support the Hyper-V hypercall interface,
so this change should be both forward and backward compatible.
Signed-off-by: Sunil Muthuswamy <sunilmut@microsoft.com>
[tyhicks: Forward ported to v5.15]
Signed-off-by: Tyler Hicks <tyhicks@linux.microsoft.com>
[kms: Forward ported to v6.1]
Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
---
arch/arm64/hyperv/Makefile | 2 +-
arch/arm64/hyperv/hv_core.c | 57 ++++-----
arch/arm64/hyperv/hv_hvc.S | 61 ++++++++++
arch/arm64/include/asm/mshyperv.h | 4 +
4 files changed, 91 insertions(+), 33 deletions(-)
diff --git a/arch/arm64/hyperv/Makefile b/arch/arm64/hyperv/Makefile
index 87c31c001da9..4cbeaa36d189 100644
--- a/arch/arm64/hyperv/Makefile
+++ b/arch/arm64/hyperv/Makefile
@@ -1,2 +1,2 @@
# SPDX-License-Identifier: GPL-2.0
-obj-y := hv_core.o mshyperv.o
+obj-y := hv_core.o mshyperv.o hv_hvc.o
diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c
index b54c34793701..e7010b2a587c 100644
--- a/arch/arm64/hyperv/hv_core.c
+++ b/arch/arm64/hyperv/hv_core.c
@@ -23,16 +23,13 @@
*/
u64 hv_do_hypercall(u64 control, void *input, void *output)
{
- struct arm_smccc_res res;
u64 input_address;
u64 output_address;
input_address = input ? virt_to_phys(input) : 0;
output_address = output ? virt_to_phys(output) : 0;
- arm_smccc_1_1_hvc(HV_FUNC_ID, control,
- input_address, output_address, &res);
- return res.a0;
+ return hv_do_hvc(control, input_address, output_address);
}
EXPORT_SYMBOL_GPL(hv_do_hypercall);
@@ -41,27 +38,33 @@ EXPORT_SYMBOL_GPL(hv_do_hypercall);
* with arguments in registers instead of physical memory.
* Avoids the overhead of virt_to_phys for simple hypercalls.
*/
-
u64 hv_do_fast_hypercall8(u16 code, u64 input)
{
- struct arm_smccc_res res;
u64 control;
control = (u64)code | HV_HYPERCALL_FAST_BIT;
-
- arm_smccc_1_1_hvc(HV_FUNC_ID, control, input, &res);
- return res.a0;
+ return hv_do_hvc(control, input);
}
EXPORT_SYMBOL_GPL(hv_do_fast_hypercall8);
+union hv_hypercall_status {
+ u64 as_uint64;
+ struct {
+ u16 status;
+ u16 reserved;
+ u16 reps_completed; /* Low 12 bits */
+ u16 reserved2;
+ };
+};
+
/*
* Set a single VP register to a 64-bit value.
*/
void hv_set_vpreg(u32 msr, u64 value)
{
- struct arm_smccc_res res;
+ union hv_hypercall_status status;
- arm_smccc_1_1_hvc(HV_FUNC_ID,
+ status.as_uint64 = hv_do_hvc(
HVCALL_SET_VP_REGISTERS | HV_HYPERCALL_FAST_BIT |
HV_HYPERCALL_REP_COMP_1,
HV_PARTITION_ID_SELF,
@@ -69,15 +72,14 @@ void hv_set_vpreg(u32 msr, u64 value)
msr,
0,
value,
- 0,
- &res);
+ 0);
/*
* Something is fundamentally broken in the hypervisor if
* setting a VP register fails. There's really no way to
* continue as a guest VM, so panic.
*/
- BUG_ON(!hv_result_success(res.a0));
+ BUG_ON(status.status != HV_STATUS_SUCCESS);
}
EXPORT_SYMBOL_GPL(hv_set_vpreg);
@@ -90,31 +92,22 @@ EXPORT_SYMBOL_GPL(hv_set_vpreg);
void hv_get_vpreg_128(u32 msr, struct hv_get_vp_registers_output *result)
{
- struct arm_smccc_1_2_regs args;
- struct arm_smccc_1_2_regs res;
-
- args.a0 = HV_FUNC_ID;
- args.a1 = HVCALL_GET_VP_REGISTERS | HV_HYPERCALL_FAST_BIT |
- HV_HYPERCALL_REP_COMP_1;
- args.a2 = HV_PARTITION_ID_SELF;
- args.a3 = HV_VP_INDEX_SELF;
- args.a4 = msr;
+ u64 status;
- /*
- * Use the SMCCC 1.2 interface because the results are in registers
- * beyond X0-X3.
- */
- arm_smccc_1_2_hvc(&args, &res);
+ status = hv_do_hvc_fast_get(
+ HVCALL_GET_VP_REGISTERS | HV_HYPERCALL_FAST_BIT |
+ HV_HYPERCALL_REP_COMP_1,
+ HV_PARTITION_ID_SELF,
+ HV_VP_INDEX_SELF,
+ msr,
+ result);
/*
* Something is fundamentally broken in the hypervisor if
* getting a VP register fails. There's really no way to
* continue as a guest VM, so panic.
*/
- BUG_ON(!hv_result_success(res.a0));
-
- result->as64.low = res.a6;
- result->as64.high = res.a7;
+ BUG_ON((status & HV_HYPERCALL_RESULT_MASK) != HV_STATUS_SUCCESS);
}
EXPORT_SYMBOL_GPL(hv_get_vpreg_128);
diff --git a/arch/arm64/hyperv/hv_hvc.S b/arch/arm64/hyperv/hv_hvc.S
new file mode 100644
index 000000000000..c22d34ccd0aa
--- /dev/null
+++ b/arch/arm64/hyperv/hv_hvc.S
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * Microsoft Hyper-V hypervisor invocation routines
+ *
+ * Copyright (C) 2018, Microsoft, Inc.
+ *
+ * Author : Michael Kelley <mikelley@microsoft.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+ .text
+/*
+ * Do the HVC instruction. For Hyper-V the argument is always 1.
+ * x0 contains the hypercall control value, while additional registers
+ * vary depending on the hypercall, and whether the hypercall arguments
+ * are in memory or in registers (a "fast" hypercall per the Hyper-V
+ * TLFS). When the arguments are in memory x1 is the guest physical
+ * address of the input arguments, and x2 is the guest physical
+ * address of the output arguments. When the arguments are in
+ * registers, the register values depends on the hypercall. Note
+ * that this version cannot return any values in registers.
+ */
+SYM_FUNC_START(hv_do_hvc)
+ hvc #1
+ ret
+SYM_FUNC_END(hv_do_hvc)
+
+/*
+ * This variant of HVC invocation is for hv_get_vpreg and
+ * hv_get_vpreg_128. The input parameters are passed in registers
+ * along with a pointer in x4 to where the output result should
+ * be stored. The output is returned in x15 and x16. x19 is used as
+ * scratch space to avoid buildng a stack frame, as Hyper-V does
+ * not preserve registers x0-x17.
+ */
+SYM_FUNC_START(hv_do_hvc_fast_get)
+ /*
+ * Stash away x19 register so that it can be used as a scratch
+ * register and pop it at the end.
+ */
+ str x19, [sp, #-16]!
+ mov x19, x4
+ hvc #1
+ str x15,[x19]
+ str x16,[x19,#8]
+ ldr x19, [sp], #16
+ ret
+SYM_FUNC_END(hv_do_hvc_fast_get)
diff --git a/arch/arm64/include/asm/mshyperv.h b/arch/arm64/include/asm/mshyperv.h
index 20070a847304..f87a450e5b6b 100644
--- a/arch/arm64/include/asm/mshyperv.h
+++ b/arch/arm64/include/asm/mshyperv.h
@@ -22,6 +22,10 @@
#include <linux/arm-smccc.h>
#include <asm/hyperv-tlfs.h>
+extern u64 hv_do_hvc(u64 control, ...);
+extern u64 hv_do_hvc_fast_get(u64 control, u64 input1, u64 input2, u64 input3,
+ struct hv_get_vp_registers_output *output);
+
/*
* Declare calls to get and set Hyper-V VP register values on ARM64, which
* requires a hypercall.
--
Armbian