mirror of
https://github.com/armbian/build.git
synced 2025-08-15 23:56:57 +02:00
240 lines
7.2 KiB
Diff
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 111111111111..222222222222 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 111111111111..222222222222 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..111111111111
|
|
--- /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 111111111111..222222222222 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
|
|
|