LKML Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH v7 00/10] Enable Linux guests on Hyper-V on ARM64
@ 2020-08-24 16:46 Michael Kelley
  2020-08-24 16:46 ` [PATCH v7 01/10] arm/arm64: smccc-1.1: Add vendor specific owner definition Michael Kelley
                   ` (9 more replies)
  0 siblings, 10 replies; 25+ messages in thread
From: Michael Kelley @ 2020-08-24 16:46 UTC (permalink / raw)
  To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
	linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
	linux-arch, wei.liu, vkuznets, kys
  Cc: mikelley, sunilmut, boqun.feng

This series enables Linux guests running on Hyper-V on ARM64
hardware. New ARM64-specific code in arch/arm64/hyperv initializes
Hyper-V, including its interrupts and hypercall mechanism.
Existing architecture independent drivers for Hyper-V's VMbus and
synthetic devices just work when built for ARM64. Hyper-V code is
built and included in the image and modules only if CONFIG_HYPERV
is enabled.

The ten patches are organized as follows:
1) Add #define for vendor specific owner definition to linux/arm-smccc.h

2) Add include files that define the Hyper-V interface as
   described in the Hyper-V Top Level Functional Spec (TLFS), plus
   additional definitions specific to Linux running on Hyper-V.

3) thru 7) Add core Hyper-V support on ARM64, including hypercalls,
   interrupt handlers, kexec & panic handlers, and core hypervisor
   initialization.

8) Update the existing VMbus driver to generalize interrupt
   management across x86/x64 and ARM64.

9) Export screen_info so it may be used by the Hyper-V frame buffer
   driver built as a module. It is already exported for x86,
   powerpc, and alpha architectures.

10) Make CONFIG_HYPERV selectable on ARM64 in addition to x86/x64.

Some areas of Linux guests on Hyper-V on ARM64 are a work-
in-progress:

* Hyper-V on ARM64 currently runs with a 4 Kbyte page size, but
  allows guests with 16K/64K page size. However, the Linux drivers
  for Hyper-V synthetic devices assume the guest page size is 4K.
  This patch set lays the groundwork for larger guest page sizes,
  but additional patches are coming to update these drivers.

* The Hyper-V vPCI driver at drivers/pci/host/pci-hyperv.c has
  x86/x64-specific code and is not being built for ARM64. Fixing
  this driver to enable vPCI devices on ARM64 will be done later.

In a few cases, terminology from the x86/x64 world has been carried
over into the ARM64 code ("MSR", "TSC").  Hyper-V still uses the
x86/x64 terminology and has not replaced it with something more
generic, so the code uses the Hyper-V terminology.  This will be
fixed when Hyper-V updates the usage in the TLFS.

This patch set is based on the linux-next-20200817 tree (5.9-rc1).

Changes in v7:
* Separately upstreamed split of hyperv-tlfs.h into arch dependent
  and independent sections. In this patch set, update the ARM64
  hyperv-tlfs.h to include architecture independent definitions.
  This approach eliminates a lot of lines of otherwise duplicated
  code on the ARM64 side.
* Break ARM64 mshyperv.h into smaller pieces. Have an initial
  baseline, and add code along with patches for a particular
  functional area. [Marc Zyngier]
* In mshyperv.h, use static inline functions instead of #defines
  where possible. [Arnd Bergmann]
* Use VMbus INTID obtained from ACPI DSDT instead of hardcoding.
  The STIMER INTID is still hardcoded because it is needed
  before Linux has initialized the ACPI subsystem, so it can't
  be obtained from the DSDT.  Wedging it into the GTDT seems
  dubious, so was not done. [Marc Zyngier]
* Update Hyper-V page size allocation functions to use
  alloc_page() if PAGE_SIZE == HV_HYP_PAGE_SIZE [Arnd
  Bergmann]
* Various other minor changes based on feedback and to rebase
  to latest linux-next [Marc Zyngier and Arnd Bergmann]

Changes in v6:
* Use SMCCC hypercall interface instead of direct invocation
  of HVC instruction and the Hyper-V hypercall interface
  [Marc Zyngier]
* Reimplemented functions to alloc/free Hyper-V size pages
  using kmalloc/kfree since kmalloc now guarantees alignment of
  power of 2 size allocations [Marc Zyngier]
* Export screen_info in arm64 architecture so it can be used
  by the Hyper-V buffer driver built as a module
* Renamed source file arch/arm64/hyperv/hv_init.c to hv_core.c
  to better reflect its content
* Fixed the bit position of certain feature flags presented by
  Hyper-V to the guest.  The bit positions on ARM64 don't match
  the position on x86 like originally thought.
* Minor fixups to rebase to 5.6-rc5 linux-next

Changes in v5:
* Minor fixups to rebase to 5.4-rc1 linux-next

Changes in v4:
* Moved clock-related code into an architecture independent
  Hyper-V clocksource driver that is already upstream. Clock
  related code is removed from this patch set except for the
  ARM64 specific interrupt handler. [Marc Zyngier]
* Separately upstreamed the split of mshyperv.h into arch independent
  and arch dependent portions. The arch independent portion has been
  removed from this patch set.
* Divided patch #2 of the series into multiple smaller patches
  [Marc Zyngier]
* Changed a dozen or so smaller things based on feedback
  [Marc Zyngier, Will Deacon]
* Added functions to alloc/free Hyper-V size pages for use by
  drivers for Hyper-V synthetic devices when updated to not assume
  guest page size and Hyper-v page size are the same

Changes in v3:
* Added initialization of hv_vp_index array like was recently
  added on x86 branch [KY Srinivasan]
* Changed Hyper-V ARM64 register symbols to be all uppercase 
  instead of mixed case [KY Srinivasan]
* Separated mshyperv.h into two files, one architecture
  independent and one architecture dependent. After this code
  is upstream, will make changes to the x86 code to use the
  architecture independent file and remove duplication. And
  once we have a multi-architecture Hyper-V TLFS, will do a
  separate patch to split hyperv-tlfs.h in the same way.
  [KY Srinivasan]
* Minor tweaks to rebase to latest linux-next code

Changes in v2:
* Removed patch to implement slow_virt_to_phys() on ARM64.
  Use of slow_virt_to_phys() in arch independent Hyper-V
  drivers has been eliminated by commit 6ba34171bcbd
  ("Drivers: hv: vmbus: Remove use of slow_virt_to_phys()")
* Minor tweaks to rebase to latest linux-next code

---

Michael Kelley (10):
  arm/arm64: smccc-1.1: Add vendor specific owner definition
  arm64: hyperv: Add core Hyper-V include files
  arm64: hyperv: Add hypercall and register access functions
  arm64: hyperv: Add memory alloc/free functions for Hyper-V size pages
  arm64: hyperv: Add interrupt handlers for VMbus and stimer
  arm64: hyperv: Add kexec and panic handlers
  arm64: hyperv: Initialize hypervisor on boot
  Drivers: hv: vmbus: Add hooks for per-CPU IRQ
  arm64: efi: Export screen_info
  Drivers: hv: Enable Hyper-V code to be built on ARM64

 MAINTAINERS                          |   3 +
 arch/arm64/Kbuild                    |   1 +
 arch/arm64/hyperv/Makefile           |   2 +
 arch/arm64/hyperv/hv_core.c          | 437 +++++++++++++++++++++++++++++++++++
 arch/arm64/hyperv/mshyperv.c         | 159 +++++++++++++
 arch/arm64/include/asm/hyperv-tlfs.h |  94 ++++++++
 arch/arm64/include/asm/mshyperv.h    | 165 +++++++++++++
 arch/arm64/kernel/efi.c              |   1 +
 arch/x86/include/asm/mshyperv.h      |   4 +
 drivers/hv/Kconfig                   |   3 +-
 drivers/hv/hv.c                      |   3 +
 include/asm-generic/mshyperv.h       |   5 +
 include/linux/arm-smccc.h            |   1 +
 13 files changed, 877 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/hyperv/Makefile
 create mode 100644 arch/arm64/hyperv/hv_core.c
 create mode 100644 arch/arm64/hyperv/mshyperv.c
 create mode 100644 arch/arm64/include/asm/hyperv-tlfs.h
 create mode 100644 arch/arm64/include/asm/mshyperv.h

-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v7 01/10] arm/arm64: smccc-1.1: Add vendor specific owner definition
  2020-08-24 16:46 [PATCH v7 00/10] Enable Linux guests on Hyper-V on ARM64 Michael Kelley
@ 2020-08-24 16:46 ` Michael Kelley
  2020-08-24 16:46 ` [PATCH v7 02/10] arm64: hyperv: Add core Hyper-V include files Michael Kelley
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 25+ messages in thread
From: Michael Kelley @ 2020-08-24 16:46 UTC (permalink / raw)
  To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
	linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
	linux-arch, wei.liu, vkuznets, kys
  Cc: mikelley, sunilmut, boqun.feng

In the SMCCC v1.1 spec, the Owning Entity Number in the Function
Identifier may have a value of 6 for a vendor specific hypervisor
service call. Add this #define.

Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
 include/linux/arm-smccc.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index 15c706f..ee286f5 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -49,6 +49,7 @@
 #define ARM_SMCCC_OWNER_OEM		3
 #define ARM_SMCCC_OWNER_STANDARD	4
 #define ARM_SMCCC_OWNER_STANDARD_HYP	5
+#define ARM_SMCCC_OWNER_VENDOR_HYP	6
 #define ARM_SMCCC_OWNER_TRUSTED_APP	48
 #define ARM_SMCCC_OWNER_TRUSTED_APP_END	49
 #define ARM_SMCCC_OWNER_TRUSTED_OS	50
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v7 02/10] arm64: hyperv: Add core Hyper-V include files
  2020-08-24 16:46 [PATCH v7 00/10] Enable Linux guests on Hyper-V on ARM64 Michael Kelley
  2020-08-24 16:46 ` [PATCH v7 01/10] arm/arm64: smccc-1.1: Add vendor specific owner definition Michael Kelley
@ 2020-08-24 16:46 ` Michael Kelley
  2020-08-24 18:38   ` Arnd Bergmann
  2020-08-24 16:46 ` [PATCH v7 03/10] arm64: hyperv: Add hypercall and register access functions Michael Kelley
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 25+ messages in thread
From: Michael Kelley @ 2020-08-24 16:46 UTC (permalink / raw)
  To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
	linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
	linux-arch, wei.liu, vkuznets, kys
  Cc: mikelley, sunilmut, boqun.feng

hyperv-tlfs.h defines Hyper-V interfaces from the Hyper-V Top Level
Functional Spec (TLFS), and #includes the architecture-independent
part of hyperv-tlfs.h in include/asm-generic.  The published TLFS
is distinctly oriented to x86/x64, so the ARM64-specific
hyperv-tlfs.h includes information for ARM64 that is not yet formally
published. The TLFS is available here:

  docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs

mshyperv.h defines Linux-specific structures and routines for
interacting with Hyper-V on ARM64, and #includes the architecture-
independent part of mshyperv.h in include/asm-generic.

Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
 MAINTAINERS                          |  2 +
 arch/arm64/include/asm/hyperv-tlfs.h | 94 ++++++++++++++++++++++++++++++++++++
 arch/arm64/include/asm/mshyperv.h    | 76 +++++++++++++++++++++++++++++
 3 files changed, 172 insertions(+)
 create mode 100644 arch/arm64/include/asm/hyperv-tlfs.h
 create mode 100644 arch/arm64/include/asm/mshyperv.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 4179dfa..803bade 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8054,6 +8054,8 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux.git
 F:	Documentation/ABI/stable/sysfs-bus-vmbus
 F:	Documentation/ABI/testing/debugfs-hyperv
 F:	Documentation/networking/device_drivers/ethernet/microsoft/netvsc.rst
+F:	arch/arm64/include/asm/hyperv-tlfs.h
+F:	arch/arm64/include/asm/mshyperv.h
 F:	arch/x86/hyperv
 F:	arch/x86/include/asm/hyperv-tlfs.h
 F:	arch/x86/include/asm/mshyperv.h
diff --git a/arch/arm64/include/asm/hyperv-tlfs.h b/arch/arm64/include/asm/hyperv-tlfs.h
new file mode 100644
index 0000000..09f5228
--- /dev/null
+++ b/arch/arm64/include/asm/hyperv-tlfs.h
@@ -0,0 +1,94 @@
+/* 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) 2019, 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_VPINDEX		0x00090003
+#define HV_REGISTER_TIME_REFCOUNT	0x00090004
+#define HV_REGISTER_REFERENCE_TSC	0x00090017
+
+#define HV_REGISTER_SINT0		0x000A0000
+#define HV_REGISTER_SCONTROL		0x000A0010
+#define HV_REGISTER_SIFP		0x000A0012
+#define HV_REGISTER_SIPP		0x000A0013
+#define HV_REGISTER_EOM			0x000A0014
+
+#define HV_REGISTER_STIMER0_CONFIG	0x000B0000
+#define HV_REGISTER_STIMER0_COUNT	0x000B0001
+
+/*
+ * Define hypervisor message types. These must be
+ * included in the architecture specific hyperv-tlfs.h
+ * because there are processor specific values on the
+ * x86 side.
+ */
+enum hv_message_type {
+	HVMSG_NONE			= 0x00000000,
+
+	/* Memory access messages. */
+	HVMSG_UNMAPPED_GPA		= 0x80000000,
+	HVMSG_GPA_INTERCEPT		= 0x80000001,
+
+	/* Timer notification messages. */
+	HVMSG_TIMER_EXPIRED		= 0x80000010,
+
+	/* Error messages. */
+	HVMSG_INVALID_VP_REGISTER_VALUE	= 0x80000020,
+	HVMSG_UNRECOVERABLE_EXCEPTION	= 0x80000021,
+	HVMSG_UNSUPPORTED_FEATURE	= 0x80000022,
+
+	/* Trace buffer complete messages. */
+	HVMSG_EVENTLOG_BUFFERCOMPLETE	= 0x80000040,
+};
+
+#include <asm-generic/hyperv-tlfs.h>
+
+#endif
diff --git a/arch/arm64/include/asm/mshyperv.h b/arch/arm64/include/asm/mshyperv.h
new file mode 100644
index 0000000..6b1f26c
--- /dev/null
+++ b/arch/arm64/include/asm/mshyperv.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * Linux-specific definitions for managing interactions with Microsoft's
+ * Hyper-V hypervisor. The definitions in this file are specific to
+ * the ARM64 architecture.  See include/asm-generic/mshyperv.h for
+ * definitions are that architecture independent.
+ *
+ * Definitions that are specified in the Hyper-V Top Level Functional
+ * Spec (TLFS) should not go in this file, but should instead go in
+ * hyperv-tlfs.h.
+ *
+ * Copyright (C) 2019, Microsoft, Inc.
+ *
+ * Author : Michael Kelley <mikelley@microsoft.com>
+ */
+
+#ifndef _ASM_MSHYPERV_H
+#define _ASM_MSHYPERV_H
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/clocksource.h>
+#include <linux/irq.h>
+#include <linux/irqdesc.h>
+#include <linux/arm-smccc.h>
+#include <asm/hyperv-tlfs.h>
+
+/* Access various Hyper-V synthetic registers */
+static inline void hv_set_simp(u64 val)
+{
+	hv_set_vpreg(HV_REGISTER_SIPP, val);
+}
+
+#define hv_get_simp(val) (val = hv_get_vpreg(HV_REGISTER_SIPP))
+
+static inline void hv_set_siefp(u64 val)
+{
+	hv_set_vpreg(HV_REGISTER_SIFP, val);
+}
+
+#define hv_get_siefp(val) (val = hv_get_vpreg(HV_REGISTER_SIFP))
+
+static inline void hv_set_synic_state(u64 val)
+{
+	hv_set_vpreg(HV_REGISTER_SCONTROL, val);
+}
+
+#define hv_get_synic_state(val) (val = hv_get_vpreg(HV_REGISTER_SCONTROL))
+
+static inline bool hv_recommend_using_aeoi(void)
+{
+	return false;
+}
+
+static inline void hv_signal_eom(void)
+{
+	hv_set_vpreg(HV_REGISTER_EOM, 0);
+}
+
+/*
+ * Hyper-V SINT registers are numbered sequentially, so we can just
+ * add the SINT number to the register number of SINT0
+ */
+
+static inline void hv_set_synint_state(u32 sint_num, u64 val)
+{
+	hv_set_vpreg(HV_REGISTER_SINT0 + sint_num, val);
+}
+
+#define hv_get_synint_state(sint_num, val) \
+		(val = hv_get_vpreg(HV_REGISTER_SINT0 + sint_num))
+
+#include <asm-generic/mshyperv.h>
+
+#endif
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v7 03/10] arm64: hyperv: Add hypercall and register access functions
  2020-08-24 16:46 [PATCH v7 00/10] Enable Linux guests on Hyper-V on ARM64 Michael Kelley
  2020-08-24 16:46 ` [PATCH v7 01/10] arm/arm64: smccc-1.1: Add vendor specific owner definition Michael Kelley
  2020-08-24 16:46 ` [PATCH v7 02/10] arm64: hyperv: Add core Hyper-V include files Michael Kelley
@ 2020-08-24 16:46 ` Michael Kelley
  2020-08-24 16:46 ` [PATCH v7 04/10] arm64: hyperv: Add memory alloc/free functions for Hyper-V size pages Michael Kelley
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 25+ messages in thread
From: Michael Kelley @ 2020-08-24 16:46 UTC (permalink / raw)
  To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
	linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
	linux-arch, wei.liu, vkuznets, kys
  Cc: mikelley, sunilmut, boqun.feng

Add ARM64-specific code to make Hyper-V hypercalls and to
access virtual processor synthetic registers via hypercalls.
Hypercalls follow the SMC Calling Convention spec v1.1.

This code is architecture dependent and is mostly driven by
architecture independent code in the VMbus driver and the
Hyper-V timer clocksource driver.

This code is built only when CONFIG_HYPERV is enabled.

Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
 MAINTAINERS                       |   1 +
 arch/arm64/Kbuild                 |   1 +
 arch/arm64/hyperv/Makefile        |   2 +
 arch/arm64/hyperv/hv_core.c       | 170 ++++++++++++++++++++++++++++++++++++++
 arch/arm64/include/asm/mshyperv.h |  17 ++++
 5 files changed, 191 insertions(+)
 create mode 100644 arch/arm64/hyperv/Makefile
 create mode 100644 arch/arm64/hyperv/hv_core.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 803bade..f67d208 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8054,6 +8054,7 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux.git
 F:	Documentation/ABI/stable/sysfs-bus-vmbus
 F:	Documentation/ABI/testing/debugfs-hyperv
 F:	Documentation/networking/device_drivers/ethernet/microsoft/netvsc.rst
+F:	arch/arm64/hyperv
 F:	arch/arm64/include/asm/hyperv-tlfs.h
 F:	arch/arm64/include/asm/mshyperv.h
 F:	arch/x86/hyperv
diff --git a/arch/arm64/Kbuild b/arch/arm64/Kbuild
index d646582..7a37608 100644
--- a/arch/arm64/Kbuild
+++ b/arch/arm64/Kbuild
@@ -3,4 +3,5 @@ obj-y			+= kernel/ mm/
 obj-$(CONFIG_NET)	+= net/
 obj-$(CONFIG_KVM)	+= kvm/
 obj-$(CONFIG_XEN)	+= xen/
+obj-$(subst m,y,$(CONFIG_HYPERV))	+= hyperv/
 obj-$(CONFIG_CRYPTO)	+= crypto/
diff --git a/arch/arm64/hyperv/Makefile b/arch/arm64/hyperv/Makefile
new file mode 100644
index 0000000..1697d30
--- /dev/null
+++ b/arch/arm64/hyperv/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-y		:= hv_core.o
diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c
new file mode 100644
index 0000000..9b35011
--- /dev/null
+++ b/arch/arm64/hyperv/hv_core.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Initialization of the interface with Microsoft's Hyper-V hypervisor,
+ * and various low level utility routines for interacting with Hyper-V.
+ *
+ * Copyright (C) 2019, Microsoft, Inc.
+ *
+ * Author : Michael Kelley <mikelley@microsoft.com>
+ */
+
+
+#include <linux/types.h>
+#include <linux/log2.h>
+#include <linux/version.h>
+#include <linux/export.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/hyperv.h>
+#include <linux/arm-smccc.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;
+	struct arm_smccc_res res;
+
+	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)
+{
+	u64 control;
+	struct arm_smccc_res res;
+
+	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((res.a0 & HV_HYPERCALL_RESULT_MASK) != 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.
+ */
+
+static void __hv_get_vpreg_128(u32 msr, struct hv_get_vp_registers_output *res)
+{
+	struct hv_get_vp_registers_input	*input;
+	u64					status;
+
+	/*
+	 * Allocate a power of 2 size so alignment to that size is
+	 * guaranteed, since the hypercall input area must not cross
+	 * a page boundary.
+	 */
+
+	input = kzalloc(roundup_pow_of_two(sizeof(input->header) +
+				sizeof(input->element[0])), GFP_ATOMIC);
+
+	input->header.partitionid = HV_PARTITION_ID_SELF;
+	input->header.vpindex = HV_VP_INDEX_SELF;
+	input->header.inputvtl = 0;
+	input->element[0].name0 = msr;
+	input->element[0].name1 = 0;
+
+
+	status = hv_do_hypercall(
+		HVCALL_GET_VP_REGISTERS | HV_HYPERCALL_REP_COMP_1,
+		input, 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((status & HV_HYPERCALL_RESULT_MASK) != HV_STATUS_SUCCESS);
+
+	kfree(input);
+}
+
+u64 hv_get_vpreg(u32 msr)
+{
+	struct hv_get_vp_registers_output	*output;
+	u64					result;
+
+	/*
+	 * Allocate a power of 2 size so alignment to that size is
+	 * guaranteed, since the hypercall output area must not cross
+	 * a page boundary.
+	 */
+	output = kmalloc(roundup_pow_of_two(sizeof(*output)), GFP_ATOMIC);
+
+	__hv_get_vpreg_128(msr, output);
+
+	result = output->as64.low;
+	kfree(output);
+	return result;
+}
+EXPORT_SYMBOL_GPL(hv_get_vpreg);
+
+void hv_get_vpreg_128(u32 msr, struct hv_get_vp_registers_output *res)
+{
+	struct hv_get_vp_registers_output	*output;
+
+	/*
+	 * Allocate a power of 2 size so alignment to that size is
+	 * guaranteed, since the hypercall output area must not cross
+	 * a page boundary.
+	 */
+	output = kmalloc(roundup_pow_of_two(sizeof(*output)), GFP_ATOMIC);
+
+	__hv_get_vpreg_128(msr, output);
+
+	res->as64.low = output->as64.low;
+	res->as64.high = output->as64.high;
+	kfree(output);
+}
+EXPORT_SYMBOL_GPL(hv_get_vpreg_128);
diff --git a/arch/arm64/include/asm/mshyperv.h b/arch/arm64/include/asm/mshyperv.h
index 6b1f26c..b17d4a1 100644
--- a/arch/arm64/include/asm/mshyperv.h
+++ b/arch/arm64/include/asm/mshyperv.h
@@ -26,6 +26,14 @@
 #include <linux/arm-smccc.h>
 #include <asm/hyperv-tlfs.h>
 
+/*
+ * Declare calls to get and set Hyper-V VP register values on ARM64, which
+ * requires a hypercall.
+ */
+extern void hv_set_vpreg(u32 reg, u64 value);
+extern u64 hv_get_vpreg(u32 reg);
+extern void hv_get_vpreg_128(u32 reg, struct hv_get_vp_registers_output *result);
+
 /* Access various Hyper-V synthetic registers */
 static inline void hv_set_simp(u64 val)
 {
@@ -71,6 +79,15 @@ static inline void hv_set_synint_state(u32 sint_num, u64 val)
 #define hv_get_synint_state(sint_num, val) \
 		(val = hv_get_vpreg(HV_REGISTER_SINT0 + sint_num))
 
+
+/* SMCCC hypercall parameters */
+#define HV_SMCCC_FUNC_NUMBER	1
+#define HV_FUNC_ID	ARM_SMCCC_CALL_VAL(			\
+				ARM_SMCCC_STD_CALL,		\
+				ARM_SMCCC_SMC_64,		\
+				ARM_SMCCC_OWNER_VENDOR_HYP,	\
+				HV_SMCCC_FUNC_NUMBER)
+
 #include <asm-generic/mshyperv.h>
 
 #endif
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v7 04/10] arm64: hyperv: Add memory alloc/free functions for Hyper-V size pages
  2020-08-24 16:46 [PATCH v7 00/10] Enable Linux guests on Hyper-V on ARM64 Michael Kelley
                   ` (2 preceding siblings ...)
  2020-08-24 16:46 ` [PATCH v7 03/10] arm64: hyperv: Add hypercall and register access functions Michael Kelley
@ 2020-08-24 16:46 ` Michael Kelley
  2020-08-24 16:46 ` [PATCH v7 05/10] arm64: hyperv: Add interrupt handlers for VMbus and stimer Michael Kelley
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 25+ messages in thread
From: Michael Kelley @ 2020-08-24 16:46 UTC (permalink / raw)
  To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
	linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
	linux-arch, wei.liu, vkuznets, kys
  Cc: mikelley, sunilmut, boqun.feng

Add ARM64-specific code to allocate memory with HV_HYP_PAGE_SIZE
size and alignment. These are for use when pages need to be shared
with Hyper-V. Separate functions are needed as the page size used
by Hyper-V may not be the same as the guest page size.

This code is built only when CONFIG_HYPERV is enabled.

Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
 arch/arm64/hyperv/hv_core.c    | 43 ++++++++++++++++++++++++++++++++++++++++++
 include/asm-generic/mshyperv.h |  5 +++++
 2 files changed, 48 insertions(+)

diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c
index 9b35011..14e41b7 100644
--- a/arch/arm64/hyperv/hv_core.c
+++ b/arch/arm64/hyperv/hv_core.c
@@ -24,6 +24,49 @@
 
 
 /*
+ * Functions for allocating and freeing memory with size and
+ * alignment HV_HYP_PAGE_SIZE. These functions are needed because
+ * the guest page size may not be the same as the Hyper-V page
+ * size. We depend upon kmalloc() aligning power-of-two size
+ * allocations to the allocation size boundary, so that the
+ * allocated memory appears to Hyper-V as a page of the size
+ * it expects.
+ *
+ * These functions are used by arm64 specific code as well as
+ * arch independent Hyper-V drivers.
+ */
+
+void *hv_alloc_hyperv_page(void)
+{
+	BUILD_BUG_ON(PAGE_SIZE <  HV_HYP_PAGE_SIZE);
+
+	if (PAGE_SIZE == HV_HYP_PAGE_SIZE)
+		return (void *)__get_free_page(GFP_KERNEL);
+	else
+		return kmalloc(HV_HYP_PAGE_SIZE, GFP_KERNEL);
+}
+EXPORT_SYMBOL_GPL(hv_alloc_hyperv_page);
+
+void *hv_alloc_hyperv_zeroed_page(void)
+{
+	if (PAGE_SIZE == HV_HYP_PAGE_SIZE)
+		return (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+	else
+		return kzalloc(HV_HYP_PAGE_SIZE, GFP_KERNEL);
+}
+EXPORT_SYMBOL_GPL(hv_alloc_hyperv_zeroed_page);
+
+void hv_free_hyperv_page(unsigned long addr)
+{
+	if (PAGE_SIZE == HV_HYP_PAGE_SIZE)
+		free_page(addr);
+	else
+		kfree((void *)addr);
+}
+EXPORT_SYMBOL_GPL(hv_free_hyperv_page);
+
+
+/*
  * hv_do_hypercall- Invoke the specified hypercall
  */
 u64 hv_do_hypercall(u64 control, void *input, void *output)
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index c577996..d345a59 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -101,6 +101,11 @@ static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type)
 
 extern int vmbus_interrupt;
 
+void *hv_alloc_hyperv_page(void);
+void *hv_alloc_hyperv_zeroed_page(void);
+void hv_free_hyperv_page(unsigned long addr);
+
+
 #if IS_ENABLED(CONFIG_HYPERV)
 /*
  * Hypervisor's notion of virtual processor ID is different from
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v7 05/10] arm64: hyperv: Add interrupt handlers for VMbus and stimer
  2020-08-24 16:46 [PATCH v7 00/10] Enable Linux guests on Hyper-V on ARM64 Michael Kelley
                   ` (3 preceding siblings ...)
  2020-08-24 16:46 ` [PATCH v7 04/10] arm64: hyperv: Add memory alloc/free functions for Hyper-V size pages Michael Kelley
@ 2020-08-24 16:46 ` Michael Kelley
  2020-08-24 18:54   ` Arnd Bergmann
  2020-08-24 16:46 ` [PATCH v7 06/10] arm64: hyperv: Add kexec and panic handlers Michael Kelley
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 25+ messages in thread
From: Michael Kelley @ 2020-08-24 16:46 UTC (permalink / raw)
  To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
	linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
	linux-arch, wei.liu, vkuznets, kys
  Cc: mikelley, sunilmut, boqun.feng

Add ARM64-specific code to set up and handle the interrupts
generated by Hyper-V for VMbus messages and for stimer expiration.

This code is architecture dependent and is mostly driven by
architecture independent code in the VMbus driver and the
Hyper-V timer clocksource driver.

This code is built only when CONFIG_HYPERV is enabled.

Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
 arch/arm64/hyperv/Makefile        |   2 +-
 arch/arm64/hyperv/mshyperv.c      | 133 ++++++++++++++++++++++++++++++++++++++
 arch/arm64/include/asm/mshyperv.h |  70 ++++++++++++++++++++
 3 files changed, 204 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/hyperv/mshyperv.c

diff --git a/arch/arm64/hyperv/Makefile b/arch/arm64/hyperv/Makefile
index 1697d30..87c31c0 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
+obj-y		:= hv_core.o mshyperv.o
diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
new file mode 100644
index 0000000..be2cd2f
--- /dev/null
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Core routines for interacting with Microsoft's Hyper-V hypervisor,
+ * including setting up VMbus and STIMER interrupts, and handling
+ * crashes and kexecs. These interactions are through a set of
+ * static "handler" variables set by the architecture independent
+ * VMbus and STIMER drivers.
+ *
+ * Copyright (C) 2019, Microsoft, Inc.
+ *
+ * Author : Michael Kelley <mikelley@microsoft.com>
+ */
+
+#include <linux/types.h>
+#include <linux/export.h>
+#include <linux/interrupt.h>
+#include <linux/kexec.h>
+#include <linux/acpi.h>
+#include <linux/ptrace.h>
+#include <asm/hyperv-tlfs.h>
+#include <asm/mshyperv.h>
+
+static void (*vmbus_handler)(void);
+static void (*hv_stimer0_handler)(void);
+
+static int vmbus_irq;
+static long __percpu *vmbus_evt;
+static long __percpu *stimer0_evt;
+
+irqreturn_t hyperv_vector_handler(int irq, void *dev_id)
+{
+	vmbus_handler();
+	return IRQ_HANDLED;
+}
+
+/* Must be done just once */
+int hv_setup_vmbus_irq(int irq, void (*handler)(void))
+{
+	int result;
+
+	vmbus_handler = handler;
+
+	vmbus_evt = alloc_percpu(long);
+	result = request_percpu_irq(irq, hyperv_vector_handler,
+			"Hyper-V VMbus", vmbus_evt);
+	if (result) {
+		pr_err("Can't request Hyper-V VMBus IRQ %d. Error %d",
+			irq, result);
+		free_percpu(vmbus_evt);
+		return result;
+	}
+
+	vmbus_irq = irq;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(hv_setup_vmbus_irq);
+
+/* Must be done just once */
+void hv_remove_vmbus_irq(void)
+{
+	if (vmbus_irq) {
+		free_percpu_irq(vmbus_irq, vmbus_evt);
+		free_percpu(vmbus_evt);
+	}
+}
+EXPORT_SYMBOL_GPL(hv_remove_vmbus_irq);
+
+/* Must be done by each CPU */
+void hv_enable_vmbus_irq(void)
+{
+	enable_percpu_irq(vmbus_irq, 0);
+}
+EXPORT_SYMBOL_GPL(hv_enable_vmbus_irq);
+
+/* Must be done by each CPU */
+void hv_disable_vmbus_irq(void)
+{
+	disable_percpu_irq(vmbus_irq);
+}
+EXPORT_SYMBOL_GPL(hv_disable_vmbus_irq);
+
+/* Routines to do per-architecture handling of STIMER0 when in Direct Mode */
+
+static irqreturn_t hv_stimer0_vector_handler(int irq, void *dev_id)
+{
+	if (hv_stimer0_handler)
+		hv_stimer0_handler();
+	return IRQ_HANDLED;
+}
+
+int hv_setup_stimer0_irq(int *irq, int *vector, void (*handler)(void))
+{
+	int localirq;
+	int result;
+
+	localirq = acpi_register_gsi(NULL, HV_STIMER0_INTID,
+			ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH);
+	if (localirq <= 0) {
+		pr_err("Can't register Hyper-V stimer0 GSI. Error %d",
+			localirq);
+		*irq = 0;
+		return -1;
+	}
+	stimer0_evt = alloc_percpu(long);
+	result = request_percpu_irq(localirq, hv_stimer0_vector_handler,
+					 "Hyper-V stimer0", stimer0_evt);
+	if (result) {
+		pr_err("Can't request Hyper-V stimer0 IRQ %d. Error %d",
+			localirq, result);
+		free_percpu(stimer0_evt);
+		acpi_unregister_gsi(localirq);
+		*irq = 0;
+		return result;
+	}
+
+	hv_stimer0_handler = handler;
+	*vector = HV_STIMER0_INTID;
+	*irq = localirq;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(hv_setup_stimer0_irq);
+
+void hv_remove_stimer0_irq(int irq)
+{
+	hv_stimer0_handler = NULL;
+	if (irq) {
+		free_percpu_irq(irq, stimer0_evt);
+		free_percpu(stimer0_evt);
+		acpi_unregister_gsi(irq);
+	}
+}
+EXPORT_SYMBOL_GPL(hv_remove_stimer0_irq);
diff --git a/arch/arm64/include/asm/mshyperv.h b/arch/arm64/include/asm/mshyperv.h
index b17d4a1..2ea64e54 100644
--- a/arch/arm64/include/asm/mshyperv.h
+++ b/arch/arm64/include/asm/mshyperv.h
@@ -23,6 +23,7 @@
 #include <linux/clocksource.h>
 #include <linux/irq.h>
 #include <linux/irqdesc.h>
+#include <linux/sched_clock.h>
 #include <linux/arm-smccc.h>
 #include <asm/hyperv-tlfs.h>
 
@@ -80,6 +81,75 @@ static inline void hv_set_synint_state(u32 sint_num, u64 val)
 		(val = hv_get_vpreg(HV_REGISTER_SINT0 + sint_num))
 
 
+/*
+ * Define the INTID used by STIMER0 Direct Mode interrupts.  This
+ * value can't come from ACPI tables because it is needed before
+ * the Linux ACPI subsystem is initialized.
+ */
+#define	HV_STIMER0_INTID	31
+
+/*
+ * Use the Hyper-V provided stimer0 as the timer that is made
+ * available to the architecture independent Hyper-V drivers.
+ */
+static inline void hv_init_timer(u32 timer, u64 tick)
+{
+	hv_set_vpreg(HV_REGISTER_STIMER0_COUNT + (2*timer), tick);
+}
+
+static inline void hv_init_timer_config(u32 timer, u64 val)
+{
+	hv_set_vpreg(HV_REGISTER_STIMER0_CONFIG + (2*timer), val);
+}
+
+#define hv_get_time_ref_count(val) \
+		(val = hv_get_vpreg(HV_REGISTER_TIME_REFCOUNT))
+#define hv_get_reference_tsc(val) \
+		(val = hv_get_vpreg(HV_REGISTER_REFERENCE_TSC))
+
+static inline void hv_set_reference_tsc(u64 val)
+{
+	hv_set_vpreg(HV_REGISTER_REFERENCE_TSC, val);
+}
+
+#define hv_set_clocksource_vdso(val) \
+		((val).vdso_clock_mode = VDSO_CLOCKMODE_NONE)
+
+static inline void hv_enable_vdso_clocksource(void) {}
+
+static inline void hv_enable_stimer0_percpu_irq(int irq)
+{
+	enable_percpu_irq(irq, 0);
+}
+
+static inline void hv_disable_stimer0_percpu_irq(int irq)
+{
+	disable_percpu_irq(irq);
+}
+
+static inline u64 hv_get_raw_timer(void)
+{
+	return arch_timer_read_counter();
+}
+
+static inline void hv_setup_sched_clock(void *sched_clock)
+{
+	/*
+	 * The Hyper-V sched clock read function returns nanoseconds,
+	 * not the normal 100ns units of the Hyper-V synthetic clock,
+	 * so specify 1 GHz here as the rate.
+	 */
+	sched_clock_register(sched_clock, 64, NSEC_PER_SEC);
+}
+
+extern int vmbus_interrupt;
+
+static inline int hv_get_vector(void)
+{
+	return vmbus_interrupt;
+}
+
+
 /* SMCCC hypercall parameters */
 #define HV_SMCCC_FUNC_NUMBER	1
 #define HV_FUNC_ID	ARM_SMCCC_CALL_VAL(			\
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v7 06/10] arm64: hyperv: Add kexec and panic handlers
  2020-08-24 16:46 [PATCH v7 00/10] Enable Linux guests on Hyper-V on ARM64 Michael Kelley
                   ` (4 preceding siblings ...)
  2020-08-24 16:46 ` [PATCH v7 05/10] arm64: hyperv: Add interrupt handlers for VMbus and stimer Michael Kelley
@ 2020-08-24 16:46 ` Michael Kelley
  2020-08-24 16:46 ` [PATCH v7 07/10] arm64: hyperv: Initialize hypervisor on boot Michael Kelley
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 25+ messages in thread
From: Michael Kelley @ 2020-08-24 16:46 UTC (permalink / raw)
  To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
	linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
	linux-arch, wei.liu, vkuznets, kys
  Cc: mikelley, sunilmut, boqun.feng

Add functions to set up and remove kexec and panic
handlers, and to inform Hyper-V about a guest panic.
These functions are called from architecture independent
code in the VMbus driver.

This code is built only when CONFIG_HYPERV is enabled.

Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
 arch/arm64/hyperv/hv_core.c       | 80 +++++++++++++++++++++++++++++++++++++++
 arch/arm64/hyperv/mshyperv.c      | 26 +++++++++++++
 arch/arm64/include/asm/mshyperv.h |  2 +
 3 files changed, 108 insertions(+)

diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c
index 14e41b7..966d815 100644
--- a/arch/arm64/hyperv/hv_core.c
+++ b/arch/arm64/hyperv/hv_core.c
@@ -211,3 +211,83 @@ void hv_get_vpreg_128(u32 msr, struct hv_get_vp_registers_output *res)
 	kfree(output);
 }
 EXPORT_SYMBOL_GPL(hv_get_vpreg_128);
+
+
+/*
+ * 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 hyperv_report_panic_msg() 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);
+
+/*
+ * hyperv_report_panic_msg - report panic message to Hyper-V
+ * @pa: physical address of the panic page containing the message
+ * @size: size of the message in the page
+ */
+void hyperv_report_panic_msg(phys_addr_t pa, size_t size)
+{
+	/*
+	 * P3 to contain the physical address of the panic page & P4 to
+	 * contain the size of the panic data in that page. Rest of the
+	 * registers are no-op when the NOTIFY_MSG flag is set.
+	 */
+	hv_set_vpreg(HV_REGISTER_CRASH_P0, 0);
+	hv_set_vpreg(HV_REGISTER_CRASH_P1, 0);
+	hv_set_vpreg(HV_REGISTER_CRASH_P2, 0);
+	hv_set_vpreg(HV_REGISTER_CRASH_P3, pa);
+	hv_set_vpreg(HV_REGISTER_CRASH_P4, size);
+
+	/*
+	 * Let Hyper-V know there is crash data available along with
+	 * the panic message.
+	 */
+	hv_set_vpreg(HV_REGISTER_CRASH_CTL,
+	       (HV_CRASH_CTL_CRASH_NOTIFY | HV_CRASH_CTL_CRASH_NOTIFY_MSG));
+}
+EXPORT_SYMBOL_GPL(hyperv_report_panic_msg);
diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
index be2cd2f..5bd39cb 100644
--- a/arch/arm64/hyperv/mshyperv.c
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -23,6 +23,8 @@
 
 static void (*vmbus_handler)(void);
 static void (*hv_stimer0_handler)(void);
+static void (*hv_kexec_handler)(void);
+static void (*hv_crash_handler)(struct pt_regs *regs);
 
 static int vmbus_irq;
 static long __percpu *vmbus_evt;
@@ -131,3 +133,27 @@ void hv_remove_stimer0_irq(int irq)
 	}
 }
 EXPORT_SYMBOL_GPL(hv_remove_stimer0_irq);
+
+void hv_setup_kexec_handler(void (*handler)(void))
+{
+	hv_kexec_handler = handler;
+}
+EXPORT_SYMBOL_GPL(hv_setup_kexec_handler);
+
+void hv_remove_kexec_handler(void)
+{
+	hv_kexec_handler = NULL;
+}
+EXPORT_SYMBOL_GPL(hv_remove_kexec_handler);
+
+void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs))
+{
+	hv_crash_handler = handler;
+}
+EXPORT_SYMBOL_GPL(hv_setup_crash_handler);
+
+void hv_remove_crash_handler(void)
+{
+	hv_crash_handler = NULL;
+}
+EXPORT_SYMBOL_GPL(hv_remove_crash_handler);
diff --git a/arch/arm64/include/asm/mshyperv.h b/arch/arm64/include/asm/mshyperv.h
index 2ea64e54..5df96a5 100644
--- a/arch/arm64/include/asm/mshyperv.h
+++ b/arch/arm64/include/asm/mshyperv.h
@@ -149,6 +149,8 @@ static inline int hv_get_vector(void)
 	return vmbus_interrupt;
 }
 
+#define hv_get_crash_ctl(val) \
+		(val = hv_get_vpreg(HV_REGISTER_CRASH_CTL))
 
 /* SMCCC hypercall parameters */
 #define HV_SMCCC_FUNC_NUMBER	1
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v7 07/10] arm64: hyperv: Initialize hypervisor on boot
  2020-08-24 16:46 [PATCH v7 00/10] Enable Linux guests on Hyper-V on ARM64 Michael Kelley
                   ` (5 preceding siblings ...)
  2020-08-24 16:46 ` [PATCH v7 06/10] arm64: hyperv: Add kexec and panic handlers Michael Kelley
@ 2020-08-24 16:46 ` Michael Kelley
  2020-08-24 18:33   ` Arnd Bergmann
  2020-08-24 16:46 ` [PATCH v7 08/10] Drivers: hv: vmbus: Add hooks for per-CPU IRQ Michael Kelley
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 25+ messages in thread
From: Michael Kelley @ 2020-08-24 16:46 UTC (permalink / raw)
  To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
	linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
	linux-arch, wei.liu, vkuznets, kys
  Cc: mikelley, sunilmut, boqun.feng

Add ARM64-specific code to initialize the Hyper-V
hypervisor when booting as a guest VM. Provide functions
and data structures indicating hypervisor status that
are needed by VMbus driver.

This code is built only when CONFIG_HYPERV is enabled.

Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
 arch/arm64/hyperv/hv_core.c | 144 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 144 insertions(+)

diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c
index 966d815..831a69c 100644
--- a/arch/arm64/hyperv/hv_core.c
+++ b/arch/arm64/hyperv/hv_core.c
@@ -18,10 +18,41 @@
 #include <linux/slab.h>
 #include <linux/hyperv.h>
 #include <linux/arm-smccc.h>
+#include <linux/vmalloc.h>
+#include <linux/acpi.h>
+#include <linux/module.h>
+#include <linux/cpuhotplug.h>
+#include <linux/psci.h>
 #include <asm-generic/bug.h>
 #include <asm/hyperv-tlfs.h>
 #include <asm/mshyperv.h>
+#include <asm/sysreg.h>
+#include <clocksource/hyperv_timer.h>
 
+static bool    hyperv_initialized;
+
+struct         ms_hyperv_info ms_hyperv __ro_after_init;
+EXPORT_SYMBOL_GPL(ms_hyperv);
+
+u32            *hv_vp_index;
+EXPORT_SYMBOL_GPL(hv_vp_index);
+
+u32            hv_max_vp_index;
+EXPORT_SYMBOL_GPL(hv_max_vp_index);
+
+static int hv_cpu_init(unsigned int cpu)
+{
+	u64 msr_vp_index;
+
+	msr_vp_index = hv_get_vpreg(HV_REGISTER_VPINDEX);
+
+	hv_vp_index[smp_processor_id()] = msr_vp_index;
+
+	if (msr_vp_index > hv_max_vp_index)
+		hv_max_vp_index = msr_vp_index;
+
+	return 0;
+}
 
 /*
  * Functions for allocating and freeing memory with size and
@@ -67,6 +98,107 @@ void hv_free_hyperv_page(unsigned long addr)
 
 
 /*
+ * This function is invoked via the ACPI clocksource probe mechanism. We
+ * don't actually use any values from the ACPI GTDT table, but we set up
+ * the Hyper-V synthetic clocksource and do other initialization for
+ * interacting with Hyper-V the first time.  Using early_initcall to invoke
+ * this function is too late because interrupts are already enabled at that
+ * point, and hv_init_clocksource() must run before interrupts are enabled.
+ *
+ * 1. Setup the guest ID.
+ * 2. Get features and hints info from Hyper-V
+ * 3. Setup per-cpu VP indices.
+ * 4. Initialize the Hyper-V clocksource.
+ */
+
+static int __init hyperv_init(struct acpi_table_header *table)
+{
+	struct hv_get_vp_registers_output result;
+	u32	a, b, c, d;
+	u64	guest_id;
+	int	i, cpuhp;
+
+	/*
+	 * If we're in a VM on Hyper-V, the ACPI hypervisor_id field will
+	 * have the string "MsHyperV".
+	 */
+	if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8))
+		return -EINVAL;
+
+	/* 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.misc_features = result.as32.c;
+
+	hv_get_vpreg_128(HV_REGISTER_ENLIGHTENMENTS, &result);
+	ms_hyperv.hints = result.as32.a;
+
+	pr_info("Hyper-V: Features 0x%x, hints 0x%x, misc 0x%x\n",
+		ms_hyperv.features, ms_hyperv.hints, ms_hyperv.misc_features);
+
+	/*
+	 * If Hyper-V has crash notifications, set crash_kexec_post_notifiers
+	 * so that we will report the panic to Hyper-V before running kdump.
+	 */
+	if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE)
+		crash_kexec_post_notifiers = true;
+
+	/* 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);
+
+	/* Allocate and initialize percpu VP index array */
+	hv_vp_index = kmalloc_array(num_possible_cpus(), sizeof(*hv_vp_index),
+				    GFP_KERNEL);
+	if (!hv_vp_index)
+		return -ENOMEM;
+
+	for (i = 0; i < num_possible_cpus(); i++)
+		hv_vp_index[i] = VP_INVAL;
+
+	cpuhp = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
+			"arm64/hyperv_init:online", hv_cpu_init, NULL);
+	if (cpuhp < 0)
+		goto free_vp_index;
+
+	hv_init_clocksource();
+	if (hv_stimer_alloc())
+		goto remove_cpuhp_state;
+
+	hyperv_initialized = true;
+	return 0;
+
+remove_cpuhp_state:
+	cpuhp_remove_state(cpuhp);
+free_vp_index:
+	kfree(hv_vp_index);
+	hv_vp_index = NULL;
+	return -EINVAL;
+}
+TIMER_ACPI_DECLARE(hyperv, ACPI_SIG_GTDT, hyperv_init);
+
+/*
+ * This routine is called before kexec/kdump, it does the required cleanup.
+ */
+void hyperv_cleanup(void)
+{
+	/* Reset our OS id */
+	hv_set_vpreg(HV_REGISTER_GUEST_OSID, 0);
+
+}
+EXPORT_SYMBOL_GPL(hyperv_cleanup);
+
+
+/*
  * hv_do_hypercall- Invoke the specified hypercall
  */
 u64 hv_do_hypercall(u64 control, void *input, void *output)
@@ -291,3 +423,15 @@ void hyperv_report_panic_msg(phys_addr_t pa, size_t size)
 	       (HV_CRASH_CTL_CRASH_NOTIFY | HV_CRASH_CTL_CRASH_NOTIFY_MSG));
 }
 EXPORT_SYMBOL_GPL(hyperv_report_panic_msg);
+
+bool hv_is_hyperv_initialized(void)
+{
+	return hyperv_initialized;
+}
+EXPORT_SYMBOL_GPL(hv_is_hyperv_initialized);
+
+bool hv_is_hibernation_supported(void)
+{
+	return false;
+}
+EXPORT_SYMBOL_GPL(hv_is_hibernation_supported);
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v7 08/10] Drivers: hv: vmbus: Add hooks for per-CPU IRQ
  2020-08-24 16:46 [PATCH v7 00/10] Enable Linux guests on Hyper-V on ARM64 Michael Kelley
                   ` (6 preceding siblings ...)
  2020-08-24 16:46 ` [PATCH v7 07/10] arm64: hyperv: Initialize hypervisor on boot Michael Kelley
@ 2020-08-24 16:46 ` Michael Kelley
  2020-08-24 16:46 ` [PATCH v7 09/10] arm64: efi: Export screen_info Michael Kelley
  2020-08-24 16:46 ` [PATCH v7 10/10] Drivers: hv: Enable Hyper-V code to be built on ARM64 Michael Kelley
  9 siblings, 0 replies; 25+ messages in thread
From: Michael Kelley @ 2020-08-24 16:46 UTC (permalink / raw)
  To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
	linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
	linux-arch, wei.liu, vkuznets, kys
  Cc: mikelley, sunilmut, boqun.feng

Add hooks to enable/disable a per-CPU IRQ for VMbus. These hooks
are in the architecture independent setup and shutdown paths for
Hyper-V, and are needed by Linux guests on Hyper-V on ARM64.  The
x86/x64 implementation is null because VMbus interrupts on x86/x64
don't use an IRQ.

Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
 arch/x86/include/asm/mshyperv.h | 4 ++++
 drivers/hv/hv.c                 | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index ffc2899..dd1365c 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -56,6 +56,10 @@ typedef int (*hyperv_fill_flush_list_func)(
 #define hv_get_raw_timer() rdtsc_ordered()
 #define hv_get_vector() HYPERVISOR_CALLBACK_VECTOR
 
+/* On x86/x64, there isn't a real IRQ to be enabled/disable */
+static inline void hv_enable_vmbus_irq(void) {}
+static inline void hv_disable_vmbus_irq(void) {}
+
 /*
  * Reference to pv_ops must be inline so objtool
  * detection of noinstr violations can work correctly.
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 2bd44fd..7499079 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -178,6 +178,7 @@ void hv_synic_enable_regs(unsigned int cpu)
 	hv_set_siefp(siefp.as_uint64);
 
 	/* Setup the shared SINT. */
+	hv_enable_vmbus_irq();
 	hv_get_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
 
 	shared_sint.vector = hv_get_vector();
@@ -235,6 +236,8 @@ void hv_synic_disable_regs(unsigned int cpu)
 	hv_get_synic_state(sctrl.as_uint64);
 	sctrl.enable = 0;
 	hv_set_synic_state(sctrl.as_uint64);
+
+	hv_disable_vmbus_irq();
 }
 
 int hv_synic_cleanup(unsigned int cpu)
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v7 09/10] arm64: efi: Export screen_info
  2020-08-24 16:46 [PATCH v7 00/10] Enable Linux guests on Hyper-V on ARM64 Michael Kelley
                   ` (7 preceding siblings ...)
  2020-08-24 16:46 ` [PATCH v7 08/10] Drivers: hv: vmbus: Add hooks for per-CPU IRQ Michael Kelley
@ 2020-08-24 16:46 ` Michael Kelley
  2020-08-24 17:21   ` Ard Biesheuvel
  2020-08-24 17:35   ` Greg KH
  2020-08-24 16:46 ` [PATCH v7 10/10] Drivers: hv: Enable Hyper-V code to be built on ARM64 Michael Kelley
  9 siblings, 2 replies; 25+ messages in thread
From: Michael Kelley @ 2020-08-24 16:46 UTC (permalink / raw)
  To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
	linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
	linux-arch, wei.liu, vkuznets, kys
  Cc: mikelley, sunilmut, boqun.feng

The Hyper-V frame buffer driver may be built as a module, and
it needs access to screen_info. So export screen_info.

Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
 arch/arm64/kernel/efi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index d0cf596..8ff557a 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -55,6 +55,7 @@ static __init pteval_t create_mapping_protection(efi_memory_desc_t *md)
 
 /* we will fill this structure from the stub, so don't put it in .bss */
 struct screen_info screen_info __section(.data);
+EXPORT_SYMBOL(screen_info);
 
 int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
 {
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v7 10/10] Drivers: hv: Enable Hyper-V code to be built on ARM64
  2020-08-24 16:46 [PATCH v7 00/10] Enable Linux guests on Hyper-V on ARM64 Michael Kelley
                   ` (8 preceding siblings ...)
  2020-08-24 16:46 ` [PATCH v7 09/10] arm64: efi: Export screen_info Michael Kelley
@ 2020-08-24 16:46 ` Michael Kelley
  2020-08-24 17:24   ` Ard Biesheuvel
  9 siblings, 1 reply; 25+ messages in thread
From: Michael Kelley @ 2020-08-24 16:46 UTC (permalink / raw)
  To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
	linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
	linux-arch, wei.liu, vkuznets, kys
  Cc: mikelley, sunilmut, boqun.feng

Update drivers/hv/Kconfig so CONFIG_HYPERV can be selected on
ARM64, causing the Hyper-V specific code to be built.

Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
 drivers/hv/Kconfig | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
index 79e5356..1113e49 100644
--- a/drivers/hv/Kconfig
+++ b/drivers/hv/Kconfig
@@ -4,7 +4,8 @@ menu "Microsoft Hyper-V guest support"
 
 config HYPERV
 	tristate "Microsoft Hyper-V client drivers"
-	depends on X86 && ACPI && X86_LOCAL_APIC && HYPERVISOR_GUEST
+	depends on ACPI && \
+			((X86 && X86_LOCAL_APIC && HYPERVISOR_GUEST) || ARM64)
 	select PARAVIRT
 	select X86_HV_CALLBACK_VECTOR
 	help
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v7 09/10] arm64: efi: Export screen_info
  2020-08-24 16:46 ` [PATCH v7 09/10] arm64: efi: Export screen_info Michael Kelley
@ 2020-08-24 17:21   ` Ard Biesheuvel
  2020-08-24 17:35   ` Greg KH
  1 sibling, 0 replies; 25+ messages in thread
From: Ard Biesheuvel @ 2020-08-24 17:21 UTC (permalink / raw)
  To: Michael Kelley
  Cc: Will Deacon, Arnd Bergmann, Catalin Marinas, Mark Rutland,
	Marc Zyngier, Linux ARM, Greg Kroah-Hartman,
	Linux Kernel Mailing List, linux-hyperv, linux-efi, linux-arch,
	wei.liu, vkuznets, KY Srinivasan, Sunil Muthuswamy, Boqun Feng

On Mon, 24 Aug 2020 at 18:48, Michael Kelley <mikelley@microsoft.com> wrote:
>
> The Hyper-V frame buffer driver may be built as a module, and
> it needs access to screen_info. So export screen_info.
>
> Signed-off-by: Michael Kelley <mikelley@microsoft.com>

Acked-by: Ard Biesheuvel <ardb@kernel.org>

> ---
>  arch/arm64/kernel/efi.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
> index d0cf596..8ff557a 100644
> --- a/arch/arm64/kernel/efi.c
> +++ b/arch/arm64/kernel/efi.c
> @@ -55,6 +55,7 @@ static __init pteval_t create_mapping_protection(efi_memory_desc_t *md)
>
>  /* we will fill this structure from the stub, so don't put it in .bss */
>  struct screen_info screen_info __section(.data);
> +EXPORT_SYMBOL(screen_info);
>
>  int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
>  {
> --
> 1.8.3.1
>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v7 10/10] Drivers: hv: Enable Hyper-V code to be built on ARM64
  2020-08-24 16:46 ` [PATCH v7 10/10] Drivers: hv: Enable Hyper-V code to be built on ARM64 Michael Kelley
@ 2020-08-24 17:24   ` Ard Biesheuvel
  2020-08-24 17:28     ` Michael Kelley
  2020-08-25  8:47     ` Ben Dooks
  0 siblings, 2 replies; 25+ messages in thread
From: Ard Biesheuvel @ 2020-08-24 17:24 UTC (permalink / raw)
  To: Michael Kelley
  Cc: Will Deacon, Arnd Bergmann, Catalin Marinas, Mark Rutland,
	Marc Zyngier, Linux ARM, Greg Kroah-Hartman,
	Linux Kernel Mailing List, linux-hyperv, linux-efi, linux-arch,
	wei.liu, vkuznets, KY Srinivasan, Sunil Muthuswamy, Boqun Feng

On Mon, 24 Aug 2020 at 18:48, Michael Kelley <mikelley@microsoft.com> wrote:
>
> Update drivers/hv/Kconfig so CONFIG_HYPERV can be selected on
> ARM64, causing the Hyper-V specific code to be built.
>
> Signed-off-by: Michael Kelley <mikelley@microsoft.com>
> ---
>  drivers/hv/Kconfig | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
> index 79e5356..1113e49 100644
> --- a/drivers/hv/Kconfig
> +++ b/drivers/hv/Kconfig
> @@ -4,7 +4,8 @@ menu "Microsoft Hyper-V guest support"
>
>  config HYPERV
>         tristate "Microsoft Hyper-V client drivers"
> -       depends on X86 && ACPI && X86_LOCAL_APIC && HYPERVISOR_GUEST
> +       depends on ACPI && \
> +                       ((X86 && X86_LOCAL_APIC && HYPERVISOR_GUEST) || ARM64)
>         select PARAVIRT
>         select X86_HV_CALLBACK_VECTOR
>         help

Given the comment in a previous patch

+/*
+ * 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.
+ */

shouldn't this depend on !CONFIG_CPU_BIG_ENDIAN ?

^ permalink raw reply	[flat|nested] 25+ messages in thread

* RE: [PATCH v7 10/10] Drivers: hv: Enable Hyper-V code to be built on ARM64
  2020-08-24 17:24   ` Ard Biesheuvel
@ 2020-08-24 17:28     ` Michael Kelley
  2020-08-25  8:47     ` Ben Dooks
  1 sibling, 0 replies; 25+ messages in thread
From: Michael Kelley @ 2020-08-24 17:28 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Will Deacon, Arnd Bergmann, Catalin Marinas, Mark.Rutland,
	Marc Zyngier, Linux ARM, Greg Kroah-Hartman,
	Linux Kernel Mailing List, linux-hyperv, linux-efi, linux-arch,
	wei.liu, vkuznets, KY Srinivasan, Sunil Muthuswamy, Boqun Feng

From: Ard Biesheuvel <ardb@kernel.org> Sent: Monday, August 24, 2020 10:24 AM
> 
> On Mon, 24 Aug 2020 at 18:48, Michael Kelley <mikelley@microsoft.com> wrote:
> >
> > Update drivers/hv/Kconfig so CONFIG_HYPERV can be selected on
> > ARM64, causing the Hyper-V specific code to be built.
> >
> > Signed-off-by: Michael Kelley <mikelley@microsoft.com>
> > ---
> >  drivers/hv/Kconfig | 3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
> > index 79e5356..1113e49 100644
> > --- a/drivers/hv/Kconfig
> > +++ b/drivers/hv/Kconfig
> > @@ -4,7 +4,8 @@ menu "Microsoft Hyper-V guest support"
> >
> >  config HYPERV
> >         tristate "Microsoft Hyper-V client drivers"
> > -       depends on X86 && ACPI && X86_LOCAL_APIC && HYPERVISOR_GUEST
> > +       depends on ACPI && \
> > +                       ((X86 && X86_LOCAL_APIC && HYPERVISOR_GUEST) || ARM64)
> >         select PARAVIRT
> >         select X86_HV_CALLBACK_VECTOR
> >         help
> 
> Given the comment in a previous patch
> 
> +/*
> + * 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.
> + */
> 
> shouldn't this depend on !CONFIG_CPU_BIG_ENDIAN ?

Yes indeed.  I'll add it.

Michael

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v7 09/10] arm64: efi: Export screen_info
  2020-08-24 16:46 ` [PATCH v7 09/10] arm64: efi: Export screen_info Michael Kelley
  2020-08-24 17:21   ` Ard Biesheuvel
@ 2020-08-24 17:35   ` Greg KH
  2020-08-24 17:40     ` Michael Kelley
  1 sibling, 1 reply; 25+ messages in thread
From: Greg KH @ 2020-08-24 17:35 UTC (permalink / raw)
  To: Michael Kelley
  Cc: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
	linux-arm-kernel, linux-kernel, linux-hyperv, linux-efi,
	linux-arch, wei.liu, vkuznets, kys, sunilmut, boqun.feng

On Mon, Aug 24, 2020 at 09:46:22AM -0700, Michael Kelley wrote:
> The Hyper-V frame buffer driver may be built as a module, and
> it needs access to screen_info. So export screen_info.
> 
> Signed-off-by: Michael Kelley <mikelley@microsoft.com>
> ---
>  arch/arm64/kernel/efi.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
> index d0cf596..8ff557a 100644
> --- a/arch/arm64/kernel/efi.c
> +++ b/arch/arm64/kernel/efi.c
> @@ -55,6 +55,7 @@ static __init pteval_t create_mapping_protection(efi_memory_desc_t *md)
>  
>  /* we will fill this structure from the stub, so don't put it in .bss */
>  struct screen_info screen_info __section(.data);
> +EXPORT_SYMBOL(screen_info);

EXPORT_SYMBOL_GPL()?

I have to ask :)

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 25+ messages in thread

* RE: [PATCH v7 09/10] arm64: efi: Export screen_info
  2020-08-24 17:35   ` Greg KH
@ 2020-08-24 17:40     ` Michael Kelley
  2020-08-24 17:52       ` Greg KH
  0 siblings, 1 reply; 25+ messages in thread
From: Michael Kelley @ 2020-08-24 17:40 UTC (permalink / raw)
  To: Greg KH
  Cc: will, ardb, arnd, catalin.marinas, Mark.Rutland, maz,
	linux-arm-kernel, linux-kernel, linux-hyperv, linux-efi,
	linux-arch, wei.liu, vkuznets, KY Srinivasan, Sunil Muthuswamy,
	boqun.feng

From: Greg KH <gregkh@linuxfoundation.org> Sent: Monday, August 24, 2020 10:35 AM
> 
> On Mon, Aug 24, 2020 at 09:46:22AM -0700, Michael Kelley wrote:
> > The Hyper-V frame buffer driver may be built as a module, and
> > it needs access to screen_info. So export screen_info.
> >
> > Signed-off-by: Michael Kelley <mikelley@microsoft.com>
> > ---
> >  arch/arm64/kernel/efi.c | 1 +
> >  1 file changed, 1 insertion(+)
> >
> > diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
> > index d0cf596..8ff557a 100644
> > --- a/arch/arm64/kernel/efi.c
> > +++ b/arch/arm64/kernel/efi.c
> > @@ -55,6 +55,7 @@ static __init pteval_t
> create_mapping_protection(efi_memory_desc_t *md)
> >
> >  /* we will fill this structure from the stub, so don't put it in .bss */
> >  struct screen_info screen_info __section(.data);
> > +EXPORT_SYMBOL(screen_info);
> 
> EXPORT_SYMBOL_GPL()?
> 
> I have to ask :)

It's also just EXPORT_SYMBOL(screen_info) in the x86, PowerPC, and Alpha
architectures. I know that doesn't guarantee it's right, but I'll have to defer
to the appropriate subsystem maintainers for whether it really should be
EXPORT_SYMBOL_GPL.

Michael

> 
> thanks,
> 
> greg k-h

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v7 09/10] arm64: efi: Export screen_info
  2020-08-24 17:40     ` Michael Kelley
@ 2020-08-24 17:52       ` Greg KH
  0 siblings, 0 replies; 25+ messages in thread
From: Greg KH @ 2020-08-24 17:52 UTC (permalink / raw)
  To: Michael Kelley
  Cc: will, ardb, arnd, catalin.marinas, Mark.Rutland, maz,
	linux-arm-kernel, linux-kernel, linux-hyperv, linux-efi,
	linux-arch, wei.liu, vkuznets, KY Srinivasan, Sunil Muthuswamy,
	boqun.feng

On Mon, Aug 24, 2020 at 05:40:32PM +0000, Michael Kelley wrote:
> From: Greg KH <gregkh@linuxfoundation.org> Sent: Monday, August 24, 2020 10:35 AM
> > 
> > On Mon, Aug 24, 2020 at 09:46:22AM -0700, Michael Kelley wrote:
> > > The Hyper-V frame buffer driver may be built as a module, and
> > > it needs access to screen_info. So export screen_info.
> > >
> > > Signed-off-by: Michael Kelley <mikelley@microsoft.com>
> > > ---
> > >  arch/arm64/kernel/efi.c | 1 +
> > >  1 file changed, 1 insertion(+)
> > >
> > > diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
> > > index d0cf596..8ff557a 100644
> > > --- a/arch/arm64/kernel/efi.c
> > > +++ b/arch/arm64/kernel/efi.c
> > > @@ -55,6 +55,7 @@ static __init pteval_t
> > create_mapping_protection(efi_memory_desc_t *md)
> > >
> > >  /* we will fill this structure from the stub, so don't put it in .bss */
> > >  struct screen_info screen_info __section(.data);
> > > +EXPORT_SYMBOL(screen_info);
> > 
> > EXPORT_SYMBOL_GPL()?
> > 
> > I have to ask :)
> 
> It's also just EXPORT_SYMBOL(screen_info) in the x86, PowerPC, and Alpha
> architectures. I know that doesn't guarantee it's right, but I'll have to defer
> to the appropriate subsystem maintainers for whether it really should be
> EXPORT_SYMBOL_GPL.

Ok, fair enough, your original patch is fine.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v7 07/10] arm64: hyperv: Initialize hypervisor on boot
  2020-08-24 16:46 ` [PATCH v7 07/10] arm64: hyperv: Initialize hypervisor on boot Michael Kelley
@ 2020-08-24 18:33   ` Arnd Bergmann
  2020-08-25 21:20     ` Michael Kelley
  0 siblings, 1 reply; 25+ messages in thread
From: Arnd Bergmann @ 2020-08-24 18:33 UTC (permalink / raw)
  To: Michael Kelley
  Cc: Will Deacon, Ard Biesheuvel, Catalin Marinas, Mark Rutland,
	Marc Zyngier, Linux ARM, gregkh, linux-kernel, linux-hyperv,
	linux-efi, linux-arch, wei.liu, Vitaly Kuznetsov,
	K. Y. Srinivasan, Sunil Muthuswamy, Boqun Feng

On Mon, Aug 24, 2020 at 6:48 PM Michael Kelley <mikelley@microsoft.com> wrote:
>
>  /*
> + * This function is invoked via the ACPI clocksource probe mechanism. We
> + * don't actually use any values from the ACPI GTDT table, but we set up
> + * the Hyper-V synthetic clocksource and do other initialization for
> + * interacting with Hyper-V the first time.  Using early_initcall to invoke
> + * this function is too late because interrupts are already enabled at that
> + * point, and hv_init_clocksource() must run before interrupts are enabled.
> + *
> + * 1. Setup the guest ID.
> + * 2. Get features and hints info from Hyper-V
> + * 3. Setup per-cpu VP indices.
> + * 4. Initialize the Hyper-V clocksource.
> + */
> +
> +static int __init hyperv_init(struct acpi_table_header *table)
> +{
> +       struct hv_get_vp_registers_output result;
> +       u32     a, b, c, d;
> +       u64     guest_id;
> +       int     i, cpuhp;
> +
> +       /*
> +        * If we're in a VM on Hyper-V, the ACPI hypervisor_id field will
> +        * have the string "MsHyperV".
> +        */
> +       if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8))
> +               return -EINVAL;
> +
> +       /* 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.misc_features = result.as32.c;
> +
> +       hv_get_vpreg_128(HV_REGISTER_ENLIGHTENMENTS, &result);
> +       ms_hyperv.hints = result.as32.a;
> +
> +       pr_info("Hyper-V: Features 0x%x, hints 0x%x, misc 0x%x\n",
> +               ms_hyperv.features, ms_hyperv.hints, ms_hyperv.misc_features);
> +
> +       /*
> +        * If Hyper-V has crash notifications, set crash_kexec_post_notifiers
> +        * so that we will report the panic to Hyper-V before running kdump.
> +        */
> +       if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE)
> +               crash_kexec_post_notifiers = true;
> +
> +       /* 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);
> +
> +       /* Allocate and initialize percpu VP index array */
> +       hv_vp_index = kmalloc_array(num_possible_cpus(), sizeof(*hv_vp_index),
> +                                   GFP_KERNEL);
> +       if (!hv_vp_index)
> +               return -ENOMEM;
> +
> +       for (i = 0; i < num_possible_cpus(); i++)
> +               hv_vp_index[i] = VP_INVAL;
> +
> +       cpuhp = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
> +                       "arm64/hyperv_init:online", hv_cpu_init, NULL);
> +       if (cpuhp < 0)
> +               goto free_vp_index;
> +
> +       hv_init_clocksource();
> +       if (hv_stimer_alloc())
> +               goto remove_cpuhp_state;
> +
> +       hyperv_initialized = true;
> +       return 0;
> +
> +remove_cpuhp_state:
> +       cpuhp_remove_state(cpuhp);
> +free_vp_index:
> +       kfree(hv_vp_index);
> +       hv_vp_index = NULL;
> +       return -EINVAL;
> +}
> +TIMER_ACPI_DECLARE(hyperv, ACPI_SIG_GTDT, hyperv_init);

I think this has come up before, and I still don't consider it an acceptable
hack to hook platform initialization code into the timer code.

Please split out the timer into a standalone driver in drivers/clocksource
that can get reviewed by the clocksource maintainers.

      Arnd

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v7 02/10] arm64: hyperv: Add core Hyper-V include files
  2020-08-24 16:46 ` [PATCH v7 02/10] arm64: hyperv: Add core Hyper-V include files Michael Kelley
@ 2020-08-24 18:38   ` Arnd Bergmann
  0 siblings, 0 replies; 25+ messages in thread
From: Arnd Bergmann @ 2020-08-24 18:38 UTC (permalink / raw)
  To: Michael Kelley
  Cc: Will Deacon, Ard Biesheuvel, Catalin Marinas, Mark Rutland,
	Marc Zyngier, Linux ARM, gregkh, linux-kernel, linux-hyperv,
	linux-efi, linux-arch, wei.liu, Vitaly Kuznetsov,
	K. Y. Srinivasan, Sunil Muthuswamy, Boqun Feng

On Mon, Aug 24, 2020 at 6:47 PM Michael Kelley <mikelley@microsoft.com> wrote:
> +
> +#define hv_get_simp(val) (val = hv_get_vpreg(HV_REGISTER_SIPP))
> +
> +#define hv_get_siefp(val) (val = hv_get_vpreg(HV_REGISTER_SIFP))

Macros that modify their arguments are generally a bad idea. Since each one
of these only has a few callers, could you just redefine the x86 version to
use function-style calling conventions and turn them into inline functions?

      Arnd

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v7 05/10] arm64: hyperv: Add interrupt handlers for VMbus and stimer
  2020-08-24 16:46 ` [PATCH v7 05/10] arm64: hyperv: Add interrupt handlers for VMbus and stimer Michael Kelley
@ 2020-08-24 18:54   ` Arnd Bergmann
  2020-08-25 22:04     ` Michael Kelley
  0 siblings, 1 reply; 25+ messages in thread
From: Arnd Bergmann @ 2020-08-24 18:54 UTC (permalink / raw)
  To: Michael Kelley
  Cc: Will Deacon, Ard Biesheuvel, Catalin Marinas, Mark Rutland,
	Marc Zyngier, Linux ARM, gregkh, linux-kernel, linux-hyperv,
	linux-efi, linux-arch, wei.liu, Vitaly Kuznetsov,
	K. Y. Srinivasan, Sunil Muthuswamy, Boqun Feng

On Mon, Aug 24, 2020 at 6:46 PM Michael Kelley <mikelley@microsoft.com> wrote:
>
> Add ARM64-specific code to set up and handle the interrupts
> generated by Hyper-V for VMbus messages and for stimer expiration.
>
> This code is architecture dependent and is mostly driven by
> architecture independent code in the VMbus driver and the
> Hyper-V timer clocksource driver.
>
> This code is built only when CONFIG_HYPERV is enabled.
>
> Signed-off-by: Michael Kelley <mikelley@microsoft.com>
> ---
>  arch/arm64/hyperv/Makefile        |   2 +-
>  arch/arm64/hyperv/mshyperv.c      | 133 ++++++++++++++++++++++++++++++++++++++
>  arch/arm64/include/asm/mshyperv.h |  70 ++++++++++++++++++++

I still have the feeling that most of the code in arch/arm64/hyperv/ is
misplaced: the only callers are loadable modules in drivers/hv/, and the
code is not really part of the architecture but part of the platform.

For the arm64 architecture, we have a rule that platform specific
code belongs into device drivers rather than into the architecture
code as we used to do in the linux-2.6 days for arch/arm/.

I don't see hyperv being virtual rather than an SoC as a differentiator
either; it's still just one of many platforms. If you look at
arch/arm64/xen/, you can see that they have managed to get
to a much simpler implementation in comparison.

I'm not sure what the correct solution should be, but what I'd try to
do here is to move every function that just considers the platform
rather than the architecture somewhere into drivers/hv where it
can be linked into the same modules as the existing files when
building for arm64, while trying to keep architecture specific code
in the header file where it can be included from those modules.

      Arnd

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v7 10/10] Drivers: hv: Enable Hyper-V code to be built on ARM64
  2020-08-24 17:24   ` Ard Biesheuvel
  2020-08-24 17:28     ` Michael Kelley
@ 2020-08-25  8:47     ` Ben Dooks
  1 sibling, 0 replies; 25+ messages in thread
From: Ben Dooks @ 2020-08-25  8:47 UTC (permalink / raw)
  To: Ard Biesheuvel, Michael Kelley
  Cc: Will Deacon, Arnd Bergmann, Catalin Marinas, Mark Rutland,
	Marc Zyngier, Linux ARM, Greg Kroah-Hartman,
	Linux Kernel Mailing List, linux-hyperv, linux-efi, linux-arch,
	wei.liu, vkuznets, KY Srinivasan, Sunil Muthuswamy, Boqun Feng

On 24/08/2020 18:24, Ard Biesheuvel wrote:
> On Mon, 24 Aug 2020 at 18:48, Michael Kelley <mikelley@microsoft.com> wrote:
>>
>> Update drivers/hv/Kconfig so CONFIG_HYPERV can be selected on
>> ARM64, causing the Hyper-V specific code to be built.
>>
>> Signed-off-by: Michael Kelley <mikelley@microsoft.com>
>> ---
>>   drivers/hv/Kconfig | 3 ++-
>>   1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
>> index 79e5356..1113e49 100644
>> --- a/drivers/hv/Kconfig
>> +++ b/drivers/hv/Kconfig
>> @@ -4,7 +4,8 @@ menu "Microsoft Hyper-V guest support"
>>
>>   config HYPERV
>>          tristate "Microsoft Hyper-V client drivers"
>> -       depends on X86 && ACPI && X86_LOCAL_APIC && HYPERVISOR_GUEST
>> +       depends on ACPI && \
>> +                       ((X86 && X86_LOCAL_APIC && HYPERVISOR_GUEST) || ARM64)
>>          select PARAVIRT
>>          select X86_HV_CALLBACK_VECTOR
>>          help
> 
> Given the comment in a previous patch
> 
> +/*
> + * 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.
> + */
> 
> shouldn't this depend on !CONFIG_CPU_BIG_ENDIAN ?

or mark the data __le and have the appropriate accessor functions do
the swapping.


-- 
Ben Dooks				http://www.codethink.co.uk/
Senior Engineer				Codethink - Providing Genius

https://www.codethink.co.uk/privacy.html

^ permalink raw reply	[flat|nested] 25+ messages in thread

* RE: [PATCH v7 07/10] arm64: hyperv: Initialize hypervisor on boot
  2020-08-24 18:33   ` Arnd Bergmann
@ 2020-08-25 21:20     ` Michael Kelley
  2020-08-26  7:18       ` Arnd Bergmann
  0 siblings, 1 reply; 25+ messages in thread
From: Michael Kelley @ 2020-08-25 21:20 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Will Deacon, Ard Biesheuvel, Catalin Marinas, Mark.Rutland,
	Marc Zyngier, Linux ARM, gregkh, linux-kernel, linux-hyperv,
	linux-efi, linux-arch, wei.liu, vkuznets, KY Srinivasan,
	Sunil Muthuswamy, Boqun Feng

From: Arnd Bergmann <arnd@arndb.de> Sent: Monday, August 24, 2020 11:34 AM
> 
> On Mon, Aug 24, 2020 at 6:48 PM Michael Kelley <mikelley@microsoft.com> wrote:
> >
> >  /*
> > + * This function is invoked via the ACPI clocksource probe mechanism. We
> > + * don't actually use any values from the ACPI GTDT table, but we set up
> > + * the Hyper-V synthetic clocksource and do other initialization for
> > + * interacting with Hyper-V the first time.  Using early_initcall to invoke
> > + * this function is too late because interrupts are already enabled at that
> > + * point, and hv_init_clocksource() must run before interrupts are enabled.
> > + *
> > + * 1. Setup the guest ID.
> > + * 2. Get features and hints info from Hyper-V
> > + * 3. Setup per-cpu VP indices.
> > + * 4. Initialize the Hyper-V clocksource.
> > + */
> > +
> > +static int __init hyperv_init(struct acpi_table_header *table)
> > +{
> > +       struct hv_get_vp_registers_output result;
> > +       u32     a, b, c, d;
> > +       u64     guest_id;
> > +       int     i, cpuhp;
> > +
> > +       /*
> > +        * If we're in a VM on Hyper-V, the ACPI hypervisor_id field will
> > +        * have the string "MsHyperV".
> > +        */
> > +       if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8))
> > +               return -EINVAL;
> > +
> > +       /* 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.misc_features = result.as32.c;
> > +
> > +       hv_get_vpreg_128(HV_REGISTER_ENLIGHTENMENTS, &result);
> > +       ms_hyperv.hints = result.as32.a;
> > +
> > +       pr_info("Hyper-V: Features 0x%x, hints 0x%x, misc 0x%x\n",
> > +               ms_hyperv.features, ms_hyperv.hints, ms_hyperv.misc_features);
> > +
> > +       /*
> > +        * If Hyper-V has crash notifications, set crash_kexec_post_notifiers
> > +        * so that we will report the panic to Hyper-V before running kdump.
> > +        */
> > +       if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE)
> > +               crash_kexec_post_notifiers = true;
> > +
> > +       /* 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);
> > +
> > +       /* Allocate and initialize percpu VP index array */
> > +       hv_vp_index = kmalloc_array(num_possible_cpus(), sizeof(*hv_vp_index),
> > +                                   GFP_KERNEL);
> > +       if (!hv_vp_index)
> > +               return -ENOMEM;
> > +
> > +       for (i = 0; i < num_possible_cpus(); i++)
> > +               hv_vp_index[i] = VP_INVAL;
> > +
> > +       cpuhp = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
> > +                       "arm64/hyperv_init:online", hv_cpu_init, NULL);
> > +       if (cpuhp < 0)
> > +               goto free_vp_index;
> > +
> > +       hv_init_clocksource();
> > +       if (hv_stimer_alloc())
> > +               goto remove_cpuhp_state;
> > +
> > +       hyperv_initialized = true;
> > +       return 0;
> > +
> > +remove_cpuhp_state:
> > +       cpuhp_remove_state(cpuhp);
> > +free_vp_index:
> > +       kfree(hv_vp_index);
> > +       hv_vp_index = NULL;
> > +       return -EINVAL;
> > +}
> > +TIMER_ACPI_DECLARE(hyperv, ACPI_SIG_GTDT, hyperv_init);
> 
> I think this has come up before, and I still don't consider it an acceptable
> hack to hook platform initialization code into the timer code.
> 
> Please split out the timer into a standalone driver in drivers/clocksource
> that can get reviewed by the clocksource maintainers.

I see two related topics here.  First, the Hyper-V clocksource driver is
drivers/clocksource/hyperv_timer.c.  The code is architecture independent
and is used today on the x86 side and for ARM64 in this patch series.  A few
architecture specific calls are satisfied by code under arch/x86, and in this
patch series, under arch/arm64.  Is there some aspect of this driver that
needs reconsideration?  I just want to make sure to understand what you
are getting at.

Second is the question of where/how to do Hyper-V specific initialization.
I agree that hanging it off the timer initialization isn't a great approach.
Should I add a Hyper-V specific initialization call at the appropriate point
in the ARM64 init sequence?  The x86 side has some structure for handling
multiple hypervisors, and the Hyper-V initialization code naturally plugs into
that structure.  I'm certainly open to suggestions on the best way to handle
it for ARM64.

Michael

> 
>       Arnd

^ permalink raw reply	[flat|nested] 25+ messages in thread

* RE: [PATCH v7 05/10] arm64: hyperv: Add interrupt handlers for VMbus and stimer
  2020-08-24 18:54   ` Arnd Bergmann
@ 2020-08-25 22:04     ` Michael Kelley
  2020-08-26  7:14       ` Arnd Bergmann
  0 siblings, 1 reply; 25+ messages in thread
From: Michael Kelley @ 2020-08-25 22:04 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Will Deacon, Ard Biesheuvel, Catalin Marinas, Mark.Rutland,
	Marc Zyngier, Linux ARM, gregkh, linux-kernel, linux-hyperv,
	linux-efi, linux-arch, wei.liu, vkuznets, KY Srinivasan,
	Sunil Muthuswamy, Boqun Feng

From: Arnd Bergmann <arnd@arndb.de> Sent: Monday, August 24, 2020 11:54 AM
> 
> On Mon, Aug 24, 2020 at 6:46 PM Michael Kelley <mikelley@microsoft.com> wrote:
> >
> > Add ARM64-specific code to set up and handle the interrupts
> > generated by Hyper-V for VMbus messages and for stimer expiration.
> >
> > This code is architecture dependent and is mostly driven by
> > architecture independent code in the VMbus driver and the
> > Hyper-V timer clocksource driver.
> >
> > This code is built only when CONFIG_HYPERV is enabled.
> >
> > Signed-off-by: Michael Kelley <mikelley@microsoft.com>
> > ---
> >  arch/arm64/hyperv/Makefile        |   2 +-
> >  arch/arm64/hyperv/mshyperv.c      | 133
> ++++++++++++++++++++++++++++++++++++++
> >  arch/arm64/include/asm/mshyperv.h |  70 ++++++++++++++++++++
> 
> I still have the feeling that most of the code in arch/arm64/hyperv/ is
> misplaced: the only callers are loadable modules in drivers/hv/, and the
> code is not really part of the architecture but part of the platform.
> 
> For the arm64 architecture, we have a rule that platform specific
> code belongs into device drivers rather than into the architecture
> code as we used to do in the linux-2.6 days for arch/arm/.
> 
> I don't see hyperv being virtual rather than an SoC as a differentiator
> either; it's still just one of many platforms. If you look at
> arch/arm64/xen/, you can see that they have managed to get
> to a much simpler implementation in comparison.
> 
> I'm not sure what the correct solution should be, but what I'd try to
> do here is to move every function that just considers the platform
> rather than the architecture somewhere into drivers/hv where it
> can be linked into the same modules as the existing files when
> building for arm64, while trying to keep architecture specific code
> in the header file where it can be included from those modules.

OK.  The concept of separating platform from architecture makes
sense to me.  The original separation of the Hyper-V code into
architecture independent portions and x86-specific portions could
use some tweaking now that we're dealing with n=2 architectures.  With
that tweaking, I can reduce the amount of Hyper-V code under arch/x86
and under arch/arm64.

On the flip side, the Hyper-V implementation on x86 and ARM64 has
differences that are semi-related to the architecture.  For example, on
x86 Hyper-V uses synthetic MSRs for a lot of guest-hypervisor setup, while
hypercalls are required on ARM64.  So I'm assuming those differences
will end up in code under arch/x86 and arch/arm64.  Arguably, I could
introduce a level of indirection (such as CONFIG_HYPERV_USE_MSRS vs.
CONFIG_HYPERV_USE_HYPERCALLS) to distinguish the two behaviors.
The selection would be tied to the architecture, and then code in
drivers/hv can #ifdef the two cases.  But I wonder if getting code out of
arch/x86 and arch/arm64 is worth that additional messiness.

Looking at the Xen code in drivers/xen, it looks like a lot of the Xen functionality
is implemented in hypercalls that can be consistent across architectures,
though I was a bit surprised to see a dozen or so instances of #ifdef CONFIG_X86.
Xen also #ifdefs on PV vs. PVHVM, which may handle some architecture
differences implicitly.  But I'm assuming that doing #ifdef <architecture>
in the Hyper-V code in order to reduce code under arch/x86 or arch/arm64
is not the right way to go.

Michael

> 
>       Arnd

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v7 05/10] arm64: hyperv: Add interrupt handlers for VMbus and stimer
  2020-08-25 22:04     ` Michael Kelley
@ 2020-08-26  7:14       ` Arnd Bergmann
  0 siblings, 0 replies; 25+ messages in thread
From: Arnd Bergmann @ 2020-08-26  7:14 UTC (permalink / raw)
  To: Michael Kelley
  Cc: Will Deacon, Ard Biesheuvel, Catalin Marinas, Mark.Rutland,
	Marc Zyngier, Linux ARM, gregkh, linux-kernel, linux-hyperv,
	linux-efi, linux-arch, wei.liu, vkuznets, KY Srinivasan,
	Sunil Muthuswamy, Boqun Feng

On Wed, Aug 26, 2020 at 12:04 AM Michael Kelley <mikelley@microsoft.com> wrote:
> From: Arnd Bergmann <arnd@arndb.de> Sent: Monday, August 24, 2020 11:54 AM

> >
> > I'm not sure what the correct solution should be, but what I'd try to
> > do here is to move every function that just considers the platform
> > rather than the architecture somewhere into drivers/hv where it
> > can be linked into the same modules as the existing files when
> > building for arm64, while trying to keep architecture specific code
> > in the header file where it can be included from those modules.
>
> OK.  The concept of separating platform from architecture makes
> sense to me.  The original separation of the Hyper-V code into
> architecture independent portions and x86-specific portions could
> use some tweaking now that we're dealing with n=2 architectures.  With
> that tweaking, I can reduce the amount of Hyper-V code under arch/x86
> and under arch/arm64.
>
> On the flip side, the Hyper-V implementation on x86 and ARM64 has
> differences that are semi-related to the architecture.  For example, on
> x86 Hyper-V uses synthetic MSRs for a lot of guest-hypervisor setup, while
> hypercalls are required on ARM64.  So I'm assuming those differences
> will end up in code under arch/x86 and arch/arm64.

Yes, that absolutely makes sense.

> Arguably, I could introduce a level of indirection (such as
> CONFIG_HYPERV_USE_MSRS vs.
> CONFIG_HYPERV_USE_HYPERCALLS) to distinguish the two behaviors.
> The selection would be tied to the architecture, and then code in
> drivers/hv can #ifdef the two cases.  But I wonder if getting code out of
> arch/x86 and arch/arm64 is worth that additional messiness.

No, I think that would take it a little too far, and conflicts with the
generic rule that code under drivers/* should be written to be portable
even if can only run on a particular target platform.

> Looking at the Xen code in drivers/xen, it looks like a lot of the Xen functionality
> is implemented in hypercalls that can be consistent across architectures,
> though I was a bit surprised to see a dozen or so instances of #ifdef CONFIG_X86.
> Xen also #ifdefs on PV vs. PVHVM, which may handle some architecture
> differences implicitly.  But I'm assuming that doing #ifdef <architecture>
> in the Hyper-V code in order to reduce code under arch/x86 or arch/arm64
> is not the right way to go.

In general that is true, adding a lot of #ifdefs makes code less readable and
harder to test. OTOH there are cases where a single #ifdef can be useful when
it avoids adding a larger amount of complexity elsewhere. Many subsystems
try to restrict the #ifdef checks to header files while keeping the
drivers/* code
free of them.

       Arnd

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v7 07/10] arm64: hyperv: Initialize hypervisor on boot
  2020-08-25 21:20     ` Michael Kelley
@ 2020-08-26  7:18       ` Arnd Bergmann
  0 siblings, 0 replies; 25+ messages in thread
From: Arnd Bergmann @ 2020-08-26  7:18 UTC (permalink / raw)
  To: Michael Kelley
  Cc: Will Deacon, Ard Biesheuvel, Catalin Marinas, Mark.Rutland,
	Marc Zyngier, Linux ARM, gregkh, linux-kernel, linux-hyperv,
	linux-efi, linux-arch, wei.liu, vkuznets, KY Srinivasan,
	Sunil Muthuswamy, Boqun Feng

On Tue, Aug 25, 2020 at 11:20 PM Michael Kelley <mikelley@microsoft.com> wrote:
> From: Arnd Bergmann <arnd@arndb.de> Sent: Monday, August 24, 2020 11:34 AM
> > On Mon, Aug 24, 2020 at 6:48 PM Michael Kelley <mikelley@microsoft.com> wrote:
> >
> > I think this has come up before, and I still don't consider it an acceptable
> > hack to hook platform initialization code into the timer code.
> >
> > Please split out the timer into a standalone driver in drivers/clocksource
> > that can get reviewed by the clocksource maintainers.
>
> I see two related topics here.

Agreed

>  First, the Hyper-V clocksource driver is
> drivers/clocksource/hyperv_timer.c.  The code is architecture independent
> and is used today on the x86 side and for ARM64 in this patch series.  A few
> architecture specific calls are satisfied by code under arch/x86, and in this
> patch series, under arch/arm64.  Is there some aspect of this driver that
> needs reconsideration?  I just want to make sure to understand what you
> are getting at.

For the clocksource driver, I would like to see the arm64 specific bits
(the code you add in arch/arm64 that are only relevant to this driver)
moved out of arch/arm64 and into drivers/clocksource, in whatever
form the clocksource maintainers prefer. I would suggest having a
separate file that can get linked along with the architecture-independent
part of that driver.

> Second is the question of where/how to do Hyper-V specific initialization.
> I agree that hanging it off the timer initialization isn't a great approach.
> Should I add a Hyper-V specific initialization call at the appropriate point
> in the ARM64 init sequence?  The x86 side has some structure for handling
> multiple hypervisors, and the Hyper-V initialization code naturally plugs into
> that structure.  I'm certainly open to suggestions on the best way to handle
> it for ARM64.

Yes, that is where I was getting at. Maybe the x86 abstraction for handling
multiple hypervisors can be lifted out of arch/x86/ into common code?

       Arnd

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, back to index

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-24 16:46 [PATCH v7 00/10] Enable Linux guests on Hyper-V on ARM64 Michael Kelley
2020-08-24 16:46 ` [PATCH v7 01/10] arm/arm64: smccc-1.1: Add vendor specific owner definition Michael Kelley
2020-08-24 16:46 ` [PATCH v7 02/10] arm64: hyperv: Add core Hyper-V include files Michael Kelley
2020-08-24 18:38   ` Arnd Bergmann
2020-08-24 16:46 ` [PATCH v7 03/10] arm64: hyperv: Add hypercall and register access functions Michael Kelley
2020-08-24 16:46 ` [PATCH v7 04/10] arm64: hyperv: Add memory alloc/free functions for Hyper-V size pages Michael Kelley
2020-08-24 16:46 ` [PATCH v7 05/10] arm64: hyperv: Add interrupt handlers for VMbus and stimer Michael Kelley
2020-08-24 18:54   ` Arnd Bergmann
2020-08-25 22:04     ` Michael Kelley
2020-08-26  7:14       ` Arnd Bergmann
2020-08-24 16:46 ` [PATCH v7 06/10] arm64: hyperv: Add kexec and panic handlers Michael Kelley
2020-08-24 16:46 ` [PATCH v7 07/10] arm64: hyperv: Initialize hypervisor on boot Michael Kelley
2020-08-24 18:33   ` Arnd Bergmann
2020-08-25 21:20     ` Michael Kelley
2020-08-26  7:18       ` Arnd Bergmann
2020-08-24 16:46 ` [PATCH v7 08/10] Drivers: hv: vmbus: Add hooks for per-CPU IRQ Michael Kelley
2020-08-24 16:46 ` [PATCH v7 09/10] arm64: efi: Export screen_info Michael Kelley
2020-08-24 17:21   ` Ard Biesheuvel
2020-08-24 17:35   ` Greg KH
2020-08-24 17:40     ` Michael Kelley
2020-08-24 17:52       ` Greg KH
2020-08-24 16:46 ` [PATCH v7 10/10] Drivers: hv: Enable Hyper-V code to be built on ARM64 Michael Kelley
2020-08-24 17:24   ` Ard Biesheuvel
2020-08-24 17:28     ` Michael Kelley
2020-08-25  8:47     ` Ben Dooks

LKML Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/lkml/0 lkml/git/0.git
	git clone --mirror https://lore.kernel.org/lkml/1 lkml/git/1.git
	git clone --mirror https://lore.kernel.org/lkml/2 lkml/git/2.git
	git clone --mirror https://lore.kernel.org/lkml/3 lkml/git/3.git
	git clone --mirror https://lore.kernel.org/lkml/4 lkml/git/4.git
	git clone --mirror https://lore.kernel.org/lkml/5 lkml/git/5.git
	git clone --mirror https://lore.kernel.org/lkml/6 lkml/git/6.git
	git clone --mirror https://lore.kernel.org/lkml/7 lkml/git/7.git
	git clone --mirror https://lore.kernel.org/lkml/8 lkml/git/8.git
	git clone --mirror https://lore.kernel.org/lkml/9 lkml/git/9.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 lkml lkml/ https://lore.kernel.org/lkml \
		linux-kernel@vger.kernel.org
	public-inbox-index lkml

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-kernel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git