Skip to content

Commit 33afc9d

Browse files
committed
Merge feature/hyperv-arm64/5.10 (afa4d09)
* msft/feature/hyperv-arm64/5.10: arm64: hyperv: Do not call hyperv_init if not on Hyper-V Hyper-V: ARM64: Always use the Hyper-V hypercall interface Drivers: hv: Enable Hyper-V code to be built on ARM64 arm64: efi: Export screen_info arm64: hyperv: Initialize hypervisor on boot arm64: hyperv: Add kexec and panic handlers arm64: hyperv: Add Hyper-V clocksource/clockevent support arm64: hyperv: Add Hyper-V hypercall and register access utilities smccc: Add HVC call variant with result registers other than 0 thru 3 clocksource/drivers/hyper-v: Move handling of STIMER0 interrupts clocksource/drivers/hyper-v: Set clocksource rating based on Hyper-V feature clocksource/drivers/hyper-v: Handle sched_clock differences inline clocksource/drivers/hyper-v: Handle vDSO differences inline Drivers: hv: vmbus: Move handling of VMbus interrupts Drivers: hv: vmbus: Handle auto EOI quirk inline Drivers: hv: vmbus: Move hyperv_report_panic_msg to arch neutral code Drivers: hv: Redo Hyper-V synthetic MSR get/set functions x86/hyper-v: Move hv_message_type to architecture neutral module Drivers: hv: vmbus: Move Hyper-V page allocator to arch neutral code
2 parents 809d96b + afa4d09 commit 33afc9d

File tree

22 files changed

+1058
-320
lines changed

22 files changed

+1058
-320
lines changed

MAINTAINERS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8153,6 +8153,9 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux.git
81538153
F: Documentation/ABI/stable/sysfs-bus-vmbus
81548154
F: Documentation/ABI/testing/debugfs-hyperv
81558155
F: Documentation/networking/device_drivers/ethernet/microsoft/netvsc.rst
8156+
F: arch/arm64/hyperv
8157+
F: arch/arm64/include/asm/hyperv-tlfs.h
8158+
F: arch/arm64/include/asm/mshyperv.h
81568159
F: arch/x86/hyperv
81578160
F: arch/x86/include/asm/hyperv-tlfs.h
81588161
F: arch/x86/include/asm/mshyperv.h

arch/arm64/Kbuild

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ obj-y += kernel/ mm/
33
obj-$(CONFIG_NET) += net/
44
obj-$(CONFIG_KVM) += kvm/
55
obj-$(CONFIG_XEN) += xen/
6+
obj-$(subst m,y,$(CONFIG_HYPERV)) += hyperv/
67
obj-$(CONFIG_CRYPTO) += crypto/

arch/arm64/hyperv/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
obj-y := hv_core.o mshyperv.o hv_hvc.o

arch/arm64/hyperv/hv_core.c

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
/*
4+
* Low level utility routines for interacting with Hyper-V.
5+
*
6+
* Copyright (C) 2021, Microsoft, Inc.
7+
*
8+
* Author : Michael Kelley <[email protected]>
9+
*/
10+
11+
#include <linux/types.h>
12+
#include <linux/export.h>
13+
#include <linux/mm.h>
14+
#include <linux/hyperv.h>
15+
#include <linux/arm-smccc.h>
16+
#include <linux/module.h>
17+
#include <asm-generic/bug.h>
18+
#include <asm/hyperv-tlfs.h>
19+
#include <asm/mshyperv.h>
20+
21+
/*
22+
* hv_do_hypercall- Invoke the specified hypercall
23+
*/
24+
u64 hv_do_hypercall(u64 control, void *input, void *output)
25+
{
26+
u64 input_address;
27+
u64 output_address;
28+
29+
input_address = input ? virt_to_phys(input) : 0;
30+
output_address = output ? virt_to_phys(output) : 0;
31+
32+
return hv_do_hvc(control, input_address, output_address);
33+
}
34+
EXPORT_SYMBOL_GPL(hv_do_hypercall);
35+
36+
/*
37+
* hv_do_fast_hypercall8 -- Invoke the specified hypercall
38+
* with arguments in registers instead of physical memory.
39+
* Avoids the overhead of virt_to_phys for simple hypercalls.
40+
*/
41+
u64 hv_do_fast_hypercall8(u16 code, u64 input)
42+
{
43+
u64 control;
44+
45+
control = (u64)code | HV_HYPERCALL_FAST_BIT;
46+
return hv_do_hvc(control, input);
47+
}
48+
EXPORT_SYMBOL_GPL(hv_do_fast_hypercall8);
49+
50+
union hv_hypercall_status {
51+
u64 as_uint64;
52+
struct {
53+
u16 status;
54+
u16 reserved;
55+
u16 reps_completed; /* Low 12 bits */
56+
u16 reserved2;
57+
};
58+
};
59+
60+
/*
61+
* Set a single VP register to a 64-bit value.
62+
*/
63+
void hv_set_vpreg(u32 msr, u64 value)
64+
{
65+
union hv_hypercall_status status;
66+
67+
status.as_uint64 = hv_do_hvc(
68+
HVCALL_SET_VP_REGISTERS | HV_HYPERCALL_FAST_BIT |
69+
HV_HYPERCALL_REP_COMP_1,
70+
HV_PARTITION_ID_SELF,
71+
HV_VP_INDEX_SELF,
72+
msr,
73+
0,
74+
value,
75+
0);
76+
77+
/*
78+
* Something is fundamentally broken in the hypervisor if
79+
* setting a VP register fails. There's really no way to
80+
* continue as a guest VM, so panic.
81+
*/
82+
BUG_ON(status.status != HV_STATUS_SUCCESS);
83+
}
84+
EXPORT_SYMBOL_GPL(hv_set_vpreg);
85+
86+
/*
87+
* Get the value of a single VP register. One version
88+
* returns just 64 bits and another returns the full 128 bits.
89+
* The two versions are separate to avoid complicating the
90+
* calling sequence for the more frequently used 64 bit version.
91+
*/
92+
93+
void hv_get_vpreg_128(u32 msr, struct hv_get_vp_registers_output *result)
94+
{
95+
u64 status;
96+
97+
status = hv_do_hvc_fast_get(
98+
HVCALL_GET_VP_REGISTERS | HV_HYPERCALL_FAST_BIT |
99+
HV_HYPERCALL_REP_COMP_1,
100+
HV_PARTITION_ID_SELF,
101+
HV_VP_INDEX_SELF,
102+
msr,
103+
result);
104+
105+
/*
106+
* Something is fundamentally broken in the hypervisor if
107+
* getting a VP register fails. There's really no way to
108+
* continue as a guest VM, so panic.
109+
*/
110+
BUG_ON((status & HV_HYPERCALL_RESULT_MASK) != HV_STATUS_SUCCESS);
111+
}
112+
EXPORT_SYMBOL_GPL(hv_get_vpreg_128);
113+
114+
u64 hv_get_vpreg(u32 msr)
115+
{
116+
struct hv_get_vp_registers_output output;
117+
118+
hv_get_vpreg_128(msr, &output);
119+
120+
return output.as64.low;
121+
}
122+
EXPORT_SYMBOL_GPL(hv_get_vpreg);
123+
124+
/*
125+
* hyperv_report_panic - report a panic to Hyper-V. This function uses
126+
* the older version of the Hyper-V interface that admittedly doesn't
127+
* pass enough information to be useful beyond just recording the
128+
* occurrence of a panic. The parallel hv_kmsg_dump() uses the
129+
* new interface that allows reporting 4 Kbytes of data, which is much
130+
* more useful. Hyper-V on ARM64 always supports the newer interface, but
131+
* we retain support for the older version because the sysadmin is allowed
132+
* to disable the newer version via sysctl in case of information security
133+
* concerns about the more verbose version.
134+
*/
135+
void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die)
136+
{
137+
static bool panic_reported;
138+
u64 guest_id;
139+
140+
/* Don't report a panic to Hyper-V if we're not going to panic */
141+
if (in_die && !panic_on_oops)
142+
return;
143+
144+
/*
145+
* We prefer to report panic on 'die' chain as we have proper
146+
* registers to report, but if we miss it (e.g. on BUG()) we need
147+
* to report it on 'panic'.
148+
*
149+
* Calling code in the 'die' and 'panic' paths ensures that only
150+
* one CPU is running this code, so no atomicity is needed.
151+
*/
152+
if (panic_reported)
153+
return;
154+
panic_reported = true;
155+
156+
guest_id = hv_get_vpreg(HV_REGISTER_GUEST_OSID);
157+
158+
/*
159+
* Hyper-V provides the ability to store only 5 values.
160+
* Pick the passed in error value, the guest_id, and the PC.
161+
* The first two general registers are added arbitrarily.
162+
*/
163+
hv_set_vpreg(HV_REGISTER_CRASH_P0, err);
164+
hv_set_vpreg(HV_REGISTER_CRASH_P1, guest_id);
165+
hv_set_vpreg(HV_REGISTER_CRASH_P2, regs->pc);
166+
hv_set_vpreg(HV_REGISTER_CRASH_P3, regs->regs[0]);
167+
hv_set_vpreg(HV_REGISTER_CRASH_P4, regs->regs[1]);
168+
169+
/*
170+
* Let Hyper-V know there is crash data available
171+
*/
172+
hv_set_vpreg(HV_REGISTER_CRASH_CTL, HV_CRASH_CTL_CRASH_NOTIFY);
173+
}
174+
EXPORT_SYMBOL_GPL(hyperv_report_panic);

arch/arm64/hyperv/hv_hvc.S

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
3+
/*
4+
* Microsoft Hyper-V hypervisor invocation routines
5+
*
6+
* Copyright (C) 2018, Microsoft, Inc.
7+
*
8+
* Author : Michael Kelley <[email protected]>
9+
*
10+
* This program is free software; you can redistribute it and/or modify it
11+
* under the terms of the GNU General Public License version 2 as published
12+
* by the Free Software Foundation.
13+
*
14+
* This program is distributed in the hope that it will be useful, but
15+
* WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
17+
* NON INFRINGEMENT. See the GNU General Public License for more
18+
* details.
19+
*/
20+
21+
#include <linux/linkage.h>
22+
#include <asm/assembler.h>
23+
24+
.text
25+
/*
26+
* Do the HVC instruction. For Hyper-V the argument is always 1.
27+
* x0 contains the hypercall control value, while additional registers
28+
* vary depending on the hypercall, and whether the hypercall arguments
29+
* are in memory or in registers (a "fast" hypercall per the Hyper-V
30+
* TLFS). When the arguments are in memory x1 is the guest physical
31+
* address of the input arguments, and x2 is the guest physical
32+
* address of the output arguments. When the arguments are in
33+
* registers, the register values depends on the hypercall. Note
34+
* that this version cannot return any values in registers.
35+
*/
36+
SYM_FUNC_START(hv_do_hvc)
37+
hvc #1
38+
ret
39+
SYM_FUNC_END(hv_do_hvc)
40+
41+
/*
42+
* This variant of HVC invocation is for hv_get_vpreg and
43+
* hv_get_vpreg_128. The input parameters are passed in registers
44+
* along with a pointer in x4 to where the output result should
45+
* be stored. The output is returned in x15 and x16. x19 is used as
46+
* scratch space to avoid buildng a stack frame, as Hyper-V does
47+
* not preserve registers x0-x17.
48+
*/
49+
SYM_FUNC_START(hv_do_hvc_fast_get)
50+
/*
51+
* Stash away x19 register so that it can be used as a scratch
52+
* register and pop it at the end.
53+
*/
54+
str x19, [sp, #-16]!
55+
mov x19, x4
56+
hvc #1
57+
str x15,[x19]
58+
str x16,[x19,#8]
59+
ldr x19, [sp], #16
60+
ret
61+
SYM_FUNC_END(hv_do_hvc_fast_get)

0 commit comments

Comments
 (0)