Skip to content

Commit f7434a1

Browse files
kelleymhkelsey-steele
authored andcommitted
arm64: hyperv: Enable Hyper-V synthetic clocks/timers
This patch adds support for Hyper-V synthetic clocks and timers on ARM64. Upstream code assumes changes to Hyper-V that were made in Fall 2021 that fully virtualize the ARM64 architectural counter and timer so that the driver in drivers/clocksource/arm_arch_timer.c can be used. But older versions of Hyper-V don't have this support and must use the Hyper-V synthetic clocks and timers. As such, this patch is out-of-tree code. This patch does two related things. First it splits the general Hyper-V initialization code to create hyperv_early_init() that runs much earlier during kernel boot. This early init function is needed so that core Hyper-V functionality is ready before the synthetic clocks and timers are initialized. Second, it adds Hyper-V clock and timer initialization via TIMER_ACPI_DECLARE() and hyperv_timer_init() in the Hyper-V clocksource driver in drivers/clocksource/hyperv_timer.c. Signed-off-by: Michael Kelley <mikelley@microsoft.com> [tyhicks: Forward port around a minor text conflict caused by commit 245b993 ("clocksource: hyper-v: unexport __init-annotated hv_init_clocksource()") Signed-off-by: Tyler Hicks <tyhicks@linux.microsoft.com> [kms: Forward port to 6.6] Signed-off-by: Kelsey Steele <kelseysteele@microsoft.com>
1 parent ffc2532 commit f7434a1

5 files changed

Lines changed: 47 additions & 6 deletions

File tree

arch/arm64/hyperv/mshyperv.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,22 @@
1919

2020
static bool hyperv_initialized;
2121

22-
static int __init hyperv_init(void)
22+
void __init hyperv_early_init(void)
2323
{
2424
struct hv_get_vp_registers_output result;
2525
u32 a, b, c, d;
2626
u64 guest_id;
27-
int ret;
2827

2928
/*
3029
* Allow for a kernel built with CONFIG_HYPERV to be running in
3130
* a non-Hyper-V environment, including on DT instead of ACPI.
3231
* In such cases, do nothing and return success.
3332
*/
3433
if (acpi_disabled)
35-
return 0;
34+
return;
3635

3736
if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8))
38-
return 0;
37+
return;
3938

4039
/* Setup the guest ID */
4140
guest_id = hv_generate_guest_id(LINUX_VERSION_CODE);
@@ -63,6 +62,13 @@ static int __init hyperv_init(void)
6362
pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n",
6463
b >> 16, b & 0xFFFF, a, d & 0xFFFFFF, c, d >> 24);
6564

65+
hyperv_initialized = true;
66+
}
67+
68+
static int __init hyperv_init(void)
69+
{
70+
int ret;
71+
6672
ret = hv_common_init();
6773
if (ret)
6874
return ret;
@@ -74,7 +80,6 @@ static int __init hyperv_init(void)
7480
return ret;
7581
}
7682

77-
hyperv_initialized = true;
7883
return 0;
7984
}
8085

arch/arm64/include/asm/mshyperv.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@
2121
#include <linux/types.h>
2222
#include <linux/arm-smccc.h>
2323
#include <asm/hyperv-tlfs.h>
24+
#include <clocksource/arm_arch_timer.h>
25+
26+
#if IS_ENABLED(CONFIG_HYPERV)
27+
void __init hyperv_early_init(void);
28+
#else
29+
static inline void hyperv_early_init(void) {};
30+
#endif
2431

2532
/*
2633
* Declare calls to get and set Hyper-V VP register values on ARM64, which
@@ -41,6 +48,17 @@ static inline u64 hv_get_register(unsigned int reg)
4148
return hv_get_vpreg(reg);
4249
}
4350

51+
/* Define the interrupt ID used by STIMER0 Direct Mode interrupts. This
52+
* value can't come from ACPI tables because it is needed before the
53+
* Linux ACPI subsystem is initialized.
54+
*/
55+
#define HYPERV_STIMER0_VECTOR 31
56+
57+
static inline u64 hv_get_raw_timer(void)
58+
{
59+
return arch_timer_read_counter();
60+
}
61+
4462
/* SMCCC hypercall parameters */
4563
#define HV_SMCCC_FUNC_NUMBER 1
4664
#define HV_FUNC_ID ARM_SMCCC_CALL_VAL( \

arch/arm64/kernel/setup.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#include <asm/traps.h>
5353
#include <asm/efi.h>
5454
#include <asm/xen/hypervisor.h>
55+
#include <asm/mshyperv.h>
5556
#include <asm/mmu_context.h>
5657

5758
static int num_standard_resources;
@@ -354,6 +355,9 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p)
354355
if (acpi_disabled)
355356
unflatten_device_tree();
356357

358+
/* Do after acpi_boot_table_init() so local FADT is available */
359+
hyperv_early_init();
360+
357361
bootmem_init();
358362

359363
kasan_init();

drivers/clocksource/hyperv_timer.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,3 +612,17 @@ void __init hv_remap_tsc_clocksource(void)
612612
if (!tsc_page)
613613
pr_err("Failed to remap Hyper-V TSC page.\n");
614614
}
615+
616+
/* Initialize everything on ARM64 */
617+
static int __init hyperv_timer_init(struct acpi_table_header *table)
618+
{
619+
if (!hv_is_hyperv_initialized())
620+
return -EINVAL;
621+
622+
hv_init_clocksource();
623+
if (hv_stimer_alloc(true))
624+
return -EINVAL;
625+
626+
return 0;
627+
}
628+
TIMER_ACPI_DECLARE(hyperv, ACPI_SIG_GTDT, hyperv_timer_init);

drivers/hv/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ config HYPERV_VTL_MODE
3838
If unsure, say N
3939

4040
config HYPERV_TIMER
41-
def_bool HYPERV && X86
41+
def_bool HYPERV
4242

4343
config HYPERV_UTILS
4444
tristate "Microsoft Hyper-V Utilities driver"

0 commit comments

Comments
 (0)