-
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 tag 'hyperv-next-signed-20210831' of git://git.kernel.org/pub/s…
…cm/linux/kernel/git/hyperv/linux Pull hyperv updates from Wei Liu: - make Hyper-V code arch-agnostic (Michael Kelley) - fix sched_clock behaviour on Hyper-V (Ani Sinha) - fix a fault when Linux runs as the root partition on MSHV (Praveen Kumar) - fix VSS driver (Vitaly Kuznetsov) - cleanup (Sonia Sharma) * tag 'hyperv-next-signed-20210831' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: hv_utils: Set the maximum packet size for VSS driver to the length of the receive buffer 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 panic handler arm64: hyperv: Add Hyper-V hypercall and register access utilities x86/hyperv: fix root partition faults when writing to VP assist page MSR hv: hyperv.h: Remove unused inline functions drivers: hv: Decouple Hyper-V clock/timer code from VMbus drivers x86/hyperv: add comment describing TSC_INVARIANT_CONTROL MSR setting bit 0 Drivers: hv: Move Hyper-V misc functionality to arch-neutral code Drivers: hv: Add arch independent default functions for some Hyper-V handlers Drivers: hv: Make portions of Hyper-V init code be arch neutral x86/hyperv: fix for unwanted manipulation of sched_clock when TSC marked unstable asm-generic/hyperv: Add missing #include of nmi.h
- Loading branch information
Showing
20 changed files
with
724 additions
and
165 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 |
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,181 @@ | ||
// 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) | ||
{ | ||
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; | ||
} | ||
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) | ||
{ | ||
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; | ||
} | ||
EXPORT_SYMBOL_GPL(hv_do_fast_hypercall8); | ||
|
||
/* | ||
* Set a single VP register to a 64-bit value. | ||
*/ | ||
void hv_set_vpreg(u32 msr, u64 value) | ||
{ | ||
struct arm_smccc_res res; | ||
|
||
arm_smccc_1_1_hvc(HV_FUNC_ID, | ||
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, | ||
&res); | ||
|
||
/* | ||
* 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)); | ||
} | ||
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) | ||
{ | ||
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; | ||
|
||
/* | ||
* Use the SMCCC 1.2 interface because the results are in registers | ||
* beyond X0-X3. | ||
*/ | ||
arm_smccc_1_2_hvc(&args, &res); | ||
|
||
/* | ||
* 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; | ||
} | ||
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, the PC, | ||
* and the SP. | ||
*/ | ||
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->sp); | ||
hv_set_vpreg(HV_REGISTER_CRASH_P4, 0); | ||
|
||
/* | ||
* 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,87 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
|
||
/* | ||
* Core routines for interacting with Microsoft's Hyper-V hypervisor, | ||
* including hypervisor initialization. | ||
* | ||
* Copyright (C) 2021, Microsoft, Inc. | ||
* | ||
* Author : Michael Kelley <mikelley@microsoft.com> | ||
*/ | ||
|
||
#include <linux/types.h> | ||
#include <linux/acpi.h> | ||
#include <linux/export.h> | ||
#include <linux/errno.h> | ||
#include <linux/version.h> | ||
#include <linux/cpuhotplug.h> | ||
#include <asm/mshyperv.h> | ||
|
||
static bool hyperv_initialized; | ||
|
||
static int __init hyperv_init(void) | ||
{ | ||
struct hv_get_vp_registers_output result; | ||
u32 a, b, c, d; | ||
u64 guest_id; | ||
int ret; | ||
|
||
/* | ||
* Allow for a kernel built with CONFIG_HYPERV to be running in | ||
* a non-Hyper-V environment, including on DT instead of ACPI. | ||
* In such cases, do nothing and return success. | ||
*/ | ||
if (acpi_disabled) | ||
return 0; | ||
|
||
if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8)) | ||
return 0; | ||
|
||
/* Setup the guest ID */ | ||
guest_id = generate_guest_id(0, LINUX_VERSION_CODE, 0); | ||
hv_set_vpreg(HV_REGISTER_GUEST_OSID, guest_id); | ||
|
||
/* Get the features and hints from Hyper-V */ | ||
hv_get_vpreg_128(HV_REGISTER_FEATURES, &result); | ||
ms_hyperv.features = result.as32.a; | ||
ms_hyperv.priv_high = result.as32.b; | ||
ms_hyperv.misc_features = result.as32.c; | ||
|
||
hv_get_vpreg_128(HV_REGISTER_ENLIGHTENMENTS, &result); | ||
ms_hyperv.hints = result.as32.a; | ||
|
||
pr_info("Hyper-V: privilege flags low 0x%x, high 0x%x, hints 0x%x, misc 0x%x\n", | ||
ms_hyperv.features, ms_hyperv.priv_high, ms_hyperv.hints, | ||
ms_hyperv.misc_features); | ||
|
||
/* Get information about the Hyper-V host version */ | ||
hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION, &result); | ||
a = result.as32.a; | ||
b = result.as32.b; | ||
c = result.as32.c; | ||
d = result.as32.d; | ||
pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n", | ||
b >> 16, b & 0xFFFF, a, d & 0xFFFFFF, c, d >> 24); | ||
|
||
ret = hv_common_init(); | ||
if (ret) | ||
return ret; | ||
|
||
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "arm64/hyperv_init:online", | ||
hv_common_cpu_init, hv_common_cpu_die); | ||
if (ret < 0) { | ||
hv_common_free(); | ||
return ret; | ||
} | ||
|
||
hyperv_initialized = true; | ||
return 0; | ||
} | ||
|
||
early_initcall(hyperv_init); | ||
|
||
bool hv_is_hyperv_initialized(void) | ||
{ | ||
return hyperv_initialized; | ||
} | ||
EXPORT_SYMBOL_GPL(hv_is_hyperv_initialized); |
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,69 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
|
||
/* | ||
* This file contains definitions from the Hyper-V Hypervisor Top-Level | ||
* Functional Specification (TLFS): | ||
* https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs | ||
* | ||
* Copyright (C) 2021, Microsoft, Inc. | ||
* | ||
* Author : Michael Kelley <mikelley@microsoft.com> | ||
*/ | ||
|
||
#ifndef _ASM_HYPERV_TLFS_H | ||
#define _ASM_HYPERV_TLFS_H | ||
|
||
#include <linux/types.h> | ||
|
||
/* | ||
* All data structures defined in the TLFS that are shared between Hyper-V | ||
* and a guest VM use Little Endian byte ordering. This matches the default | ||
* byte ordering of Linux running on ARM64, so no special handling is required. | ||
*/ | ||
|
||
/* | ||
* These Hyper-V registers provide information equivalent to the CPUID | ||
* instruction on x86/x64. | ||
*/ | ||
#define HV_REGISTER_HYPERVISOR_VERSION 0x00000100 /*CPUID 0x40000002 */ | ||
#define HV_REGISTER_FEATURES 0x00000200 /*CPUID 0x40000003 */ | ||
#define HV_REGISTER_ENLIGHTENMENTS 0x00000201 /*CPUID 0x40000004 */ | ||
|
||
/* | ||
* Group C Features. See the asm-generic version of hyperv-tlfs.h | ||
* for a description of Feature Groups. | ||
*/ | ||
|
||
/* Crash MSRs available */ | ||
#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE BIT(8) | ||
|
||
/* STIMER direct mode is available */ | ||
#define HV_STIMER_DIRECT_MODE_AVAILABLE BIT(13) | ||
|
||
/* | ||
* Synthetic register definitions equivalent to MSRs on x86/x64 | ||
*/ | ||
#define HV_REGISTER_CRASH_P0 0x00000210 | ||
#define HV_REGISTER_CRASH_P1 0x00000211 | ||
#define HV_REGISTER_CRASH_P2 0x00000212 | ||
#define HV_REGISTER_CRASH_P3 0x00000213 | ||
#define HV_REGISTER_CRASH_P4 0x00000214 | ||
#define HV_REGISTER_CRASH_CTL 0x00000215 | ||
|
||
#define HV_REGISTER_GUEST_OSID 0x00090002 | ||
#define HV_REGISTER_VP_INDEX 0x00090003 | ||
#define HV_REGISTER_TIME_REF_COUNT 0x00090004 | ||
#define HV_REGISTER_REFERENCE_TSC 0x00090017 | ||
|
||
#define HV_REGISTER_SINT0 0x000A0000 | ||
#define HV_REGISTER_SCONTROL 0x000A0010 | ||
#define HV_REGISTER_SIEFP 0x000A0012 | ||
#define HV_REGISTER_SIMP 0x000A0013 | ||
#define HV_REGISTER_EOM 0x000A0014 | ||
|
||
#define HV_REGISTER_STIMER0_CONFIG 0x000B0000 | ||
#define HV_REGISTER_STIMER0_COUNT 0x000B0001 | ||
|
||
#include <asm-generic/hyperv-tlfs.h> | ||
|
||
#endif |
Oops, something went wrong.