forked from alk3p/WSA-Linux-Kernel
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
- Loading branch information
Showing
22 changed files
with
1,058 additions
and
320 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# SPDX-License-Identifier: GPL-2.0 | ||
obj-y := hv_core.o mshyperv.o hv_hvc.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
|
||
/* | ||
* Low level utility routines for interacting with Hyper-V. | ||
* | ||
* Copyright (C) 2021, Microsoft, Inc. | ||
* | ||
* Author : Michael Kelley <mikelley@microsoft.com> | ||
*/ | ||
|
||
#include <linux/types.h> | ||
#include <linux/export.h> | ||
#include <linux/mm.h> | ||
#include <linux/hyperv.h> | ||
#include <linux/arm-smccc.h> | ||
#include <linux/module.h> | ||
#include <asm-generic/bug.h> | ||
#include <asm/hyperv-tlfs.h> | ||
#include <asm/mshyperv.h> | ||
|
||
/* | ||
* hv_do_hypercall- Invoke the specified hypercall | ||
*/ | ||
u64 hv_do_hypercall(u64 control, void *input, void *output) | ||
{ | ||
u64 input_address; | ||
u64 output_address; | ||
|
||
input_address = input ? virt_to_phys(input) : 0; | ||
output_address = output ? virt_to_phys(output) : 0; | ||
|
||
return hv_do_hvc(control, input_address, output_address); | ||
} | ||
EXPORT_SYMBOL_GPL(hv_do_hypercall); | ||
|
||
/* | ||
* hv_do_fast_hypercall8 -- Invoke the specified 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) | ||
{ | ||
u64 control; | ||
|
||
control = (u64)code | HV_HYPERCALL_FAST_BIT; | ||
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) | ||
{ | ||
union hv_hypercall_status status; | ||
|
||
status.as_uint64 = hv_do_hvc( | ||
HVCALL_SET_VP_REGISTERS | HV_HYPERCALL_FAST_BIT | | ||
HV_HYPERCALL_REP_COMP_1, | ||
HV_PARTITION_ID_SELF, | ||
HV_VP_INDEX_SELF, | ||
msr, | ||
0, | ||
value, | ||
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(status.status != HV_STATUS_SUCCESS); | ||
} | ||
EXPORT_SYMBOL_GPL(hv_set_vpreg); | ||
|
||
/* | ||
* Get the value of a single VP register. One version | ||
* returns just 64 bits and another returns the full 128 bits. | ||
* The two versions are separate to avoid complicating the | ||
* calling sequence for the more frequently used 64 bit version. | ||
*/ | ||
|
||
void hv_get_vpreg_128(u32 msr, struct hv_get_vp_registers_output *result) | ||
{ | ||
u64 status; | ||
|
||
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((status & HV_HYPERCALL_RESULT_MASK) != HV_STATUS_SUCCESS); | ||
} | ||
EXPORT_SYMBOL_GPL(hv_get_vpreg_128); | ||
|
||
u64 hv_get_vpreg(u32 msr) | ||
{ | ||
struct hv_get_vp_registers_output output; | ||
|
||
hv_get_vpreg_128(msr, &output); | ||
|
||
return output.as64.low; | ||
} | ||
EXPORT_SYMBOL_GPL(hv_get_vpreg); | ||
|
||
/* | ||
* hyperv_report_panic - report a panic to Hyper-V. This function uses | ||
* the older version of the Hyper-V interface that admittedly doesn't | ||
* pass enough information to be useful beyond just recording the | ||
* occurrence of a panic. The parallel hv_kmsg_dump() uses the | ||
* new interface that allows reporting 4 Kbytes of data, which is much | ||
* more useful. Hyper-V on ARM64 always supports the newer interface, but | ||
* we retain support for the older version because the sysadmin is allowed | ||
* to disable the newer version via sysctl in case of information security | ||
* concerns about the more verbose version. | ||
*/ | ||
void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die) | ||
{ | ||
static bool panic_reported; | ||
u64 guest_id; | ||
|
||
/* Don't report a panic to Hyper-V if we're not going to panic */ | ||
if (in_die && !panic_on_oops) | ||
return; | ||
|
||
/* | ||
* We prefer to report panic on 'die' chain as we have proper | ||
* registers to report, but if we miss it (e.g. on BUG()) we need | ||
* to report it on 'panic'. | ||
* | ||
* Calling code in the 'die' and 'panic' paths ensures that only | ||
* one CPU is running this code, so no atomicity is needed. | ||
*/ | ||
if (panic_reported) | ||
return; | ||
panic_reported = true; | ||
|
||
guest_id = hv_get_vpreg(HV_REGISTER_GUEST_OSID); | ||
|
||
/* | ||
* Hyper-V provides the ability to store only 5 values. | ||
* Pick the passed in error value, the guest_id, and the PC. | ||
* The first two general registers are added arbitrarily. | ||
*/ | ||
hv_set_vpreg(HV_REGISTER_CRASH_P0, err); | ||
hv_set_vpreg(HV_REGISTER_CRASH_P1, guest_id); | ||
hv_set_vpreg(HV_REGISTER_CRASH_P2, regs->pc); | ||
hv_set_vpreg(HV_REGISTER_CRASH_P3, regs->regs[0]); | ||
hv_set_vpreg(HV_REGISTER_CRASH_P4, regs->regs[1]); | ||
|
||
/* | ||
* Let Hyper-V know there is crash data available | ||
*/ | ||
hv_set_vpreg(HV_REGISTER_CRASH_CTL, HV_CRASH_CTL_CRASH_NOTIFY); | ||
} | ||
EXPORT_SYMBOL_GPL(hyperv_report_panic); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
Oops, something went wrong.