Skip to content

Commit 0ad365f

Browse files
kelleymhRezaT4795
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 245b993d8f6c ("clocksource: hyper-v: unexport __init-annotated hv_init_clocksource()") Signed-off-by: Tyler Hicks <tyhicks@linux.microsoft.com>
1 parent f3b6c75 commit 0ad365f

File tree

5 files changed

+47
-6
lines changed

5 files changed

+47
-6
lines changed

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_outputresult;
2525
u32a, b, c, d;
2626
u64guest_id;
27-
intret;
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 = generate_guest_id(0, LINUX_VERSION_CODE, 0);
@@ -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_VECTOR31
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_NUMBER1
4664
#define HV_FUNC_IDARM_SMCCC_CALL_VAL( \

arch/arm64/kernel/setup.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include <asm/traps.h>
5151
#include <asm/efi.h>
5252
#include <asm/xen/hypervisor.h>
53+
#include <asm/mshyperv.h>
5354
#include <asm/mmu_context.h>
5455

5556
static int num_standard_resources;
@@ -347,6 +348,9 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p)
347348
if (acpi_disabled)
348349
unflatten_device_tree();
349350

351+
/* Do after acpi_boot_table_init() so local FADT is available */
352+
hyperv_early_init();
353+
350354
bootmem_init();
351355

352356
kasan_init();

drivers/clocksource/hyperv_timer.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,3 +565,17 @@ void __init hv_init_clocksource(void)
565565
hv_sched_clock_offset = hv_read_reference_counter();
566566
hv_setup_sched_clock(read_hv_sched_clock_msr);
567567
}
568+
569+
/* Initialize everything on ARM64 */
570+
static int __init hyperv_timer_init(struct acpi_table_header *table)
571+
{
572+
if (!hv_is_hyperv_initialized())
573+
return -EINVAL;
574+
575+
hv_init_clocksource();
576+
if (hv_stimer_alloc(true))
577+
return -EINVAL;
578+
579+
return 0;
580+
}
581+
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
@@ -13,7 +13,7 @@ config HYPERV
1313
system.
1414

1515
config HYPERV_TIMER
16-
def_bool HYPERV && X86
16+
def_bool HYPERV
1717

1818
config HYPERV_UTILS
1919
tristate "Microsoft Hyper-V Utilities driver"

0 commit comments

Comments
 (0)