Skip to content

Commit 6b48cb5

Browse files
kattisrinivasanKAGA-KOKO
authored andcommitted
X86/Hyper-V: Enlighten APIC access
Hyper-V supports MSR based APIC access; implement the enlightenment. Signed-off-by: K. Y. Srinivasan <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Michael Kelley <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Link: https://lkml.kernel.org/r/[email protected]
1 parent 73fcb1a commit 6b48cb5

File tree

4 files changed

+112
-3
lines changed

4 files changed

+112
-3
lines changed

arch/x86/hyperv/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
obj-y := hv_init.o mmu.o
1+
obj-y := hv_init.o mmu.o hv_apic.o

arch/x86/hyperv/hv_apic.c

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
/*
4+
* Hyper-V specific APIC code.
5+
*
6+
* Copyright (C) 2018, Microsoft, Inc.
7+
*
8+
* Author : K. Y. Srinivasan <[email protected]>
9+
*
10+
* This program is free software; you can redistribute it and/or modify it
11+
* under the terms of the GNU General Public License version 2 as published
12+
* by the Free Software Foundation.
13+
*
14+
* This program is distributed in the hope that it will be useful, but
15+
* WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
17+
* NON INFRINGEMENT. See the GNU General Public License for more
18+
* details.
19+
*
20+
*/
21+
22+
#include <linux/types.h>
23+
#include <linux/version.h>
24+
#include <linux/vmalloc.h>
25+
#include <linux/mm.h>
26+
#include <linux/clockchips.h>
27+
#include <linux/hyperv.h>
28+
#include <linux/slab.h>
29+
#include <linux/cpuhotplug.h>
30+
#include <asm/hypervisor.h>
31+
#include <asm/mshyperv.h>
32+
33+
#ifdef CONFIG_X86_64
34+
#if IS_ENABLED(CONFIG_HYPERV)
35+
36+
static u64 hv_apic_icr_read(void)
37+
{
38+
u64 reg_val;
39+
40+
rdmsrl(HV_X64_MSR_ICR, reg_val);
41+
return reg_val;
42+
}
43+
44+
static void hv_apic_icr_write(u32 low, u32 id)
45+
{
46+
u64 reg_val;
47+
48+
reg_val = SET_APIC_DEST_FIELD(id);
49+
reg_val = reg_val << 32;
50+
reg_val |= low;
51+
52+
wrmsrl(HV_X64_MSR_ICR, reg_val);
53+
}
54+
55+
static u32 hv_apic_read(u32 reg)
56+
{
57+
u32 reg_val, hi;
58+
59+
switch (reg) {
60+
case APIC_EOI:
61+
rdmsr(HV_X64_MSR_EOI, reg_val, hi);
62+
return reg_val;
63+
case APIC_TASKPRI:
64+
rdmsr(HV_X64_MSR_TPR, reg_val, hi);
65+
return reg_val;
66+
67+
default:
68+
return native_apic_mem_read(reg);
69+
}
70+
}
71+
72+
static void hv_apic_write(u32 reg, u32 val)
73+
{
74+
switch (reg) {
75+
case APIC_EOI:
76+
wrmsr(HV_X64_MSR_EOI, val, 0);
77+
break;
78+
case APIC_TASKPRI:
79+
wrmsr(HV_X64_MSR_TPR, val, 0);
80+
break;
81+
default:
82+
native_apic_mem_write(reg, val);
83+
}
84+
}
85+
86+
static void hv_apic_eoi_write(u32 reg, u32 val)
87+
{
88+
wrmsr(HV_X64_MSR_EOI, val, 0);
89+
}
90+
91+
void __init hv_apic_init(void)
92+
{
93+
if (ms_hyperv.hints & HV_X64_APIC_ACCESS_RECOMMENDED) {
94+
pr_info("Hyper-V: Using MSR based APIC access\n");
95+
apic_set_eoi_write(hv_apic_eoi_write);
96+
apic->read = hv_apic_read;
97+
apic->write = hv_apic_write;
98+
apic->icr_write = hv_apic_icr_write;
99+
apic->icr_read = hv_apic_icr_read;
100+
}
101+
}
102+
103+
#endif /* CONFIG_HYPERV */
104+
#endif /* CONFIG_X86_64 */

arch/x86/hyperv/hv_init.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,9 @@ static int hv_cpu_die(unsigned int cpu)
242242
*
243243
* 1. Setup the hypercall page.
244244
* 2. Register Hyper-V specific clocksource.
245+
* 3. Setup Hyper-V specific APIC entry points.
245246
*/
246-
void hyperv_init(void)
247+
void __init hyperv_init(void)
247248
{
248249
u64 guest_id, required_msrs;
249250
union hv_x64_msr_hypercall_contents hypercall_msr;
@@ -298,6 +299,8 @@ void hyperv_init(void)
298299

299300
hyper_alloc_mmu();
300301

302+
hv_apic_init();
303+
301304
/*
302305
* Register Hyper-V specific clocksource.
303306
*/

arch/x86/include/asm/mshyperv.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ static inline int hv_cpu_number_to_vp_number(int cpu_number)
258258
return hv_vp_index[cpu_number];
259259
}
260260

261-
void hyperv_init(void);
261+
void __init hyperv_init(void);
262262
void hyperv_setup_mmu_ops(void);
263263
void hyper_alloc_mmu(void);
264264
void hyperv_report_panic(struct pt_regs *regs, long err);
@@ -269,6 +269,7 @@ void hyperv_reenlightenment_intr(struct pt_regs *regs);
269269
void set_hv_tscchange_cb(void (*cb)(void));
270270
void clear_hv_tscchange_cb(void);
271271
void hyperv_stop_tsc_emulation(void);
272+
void hv_apic_init(void);
272273
#else /* CONFIG_HYPERV */
273274
static inline void hyperv_init(void) {}
274275
static inline bool hv_is_hyperv_initialized(void) { return false; }
@@ -277,6 +278,7 @@ static inline void hyperv_setup_mmu_ops(void) {}
277278
static inline void set_hv_tscchange_cb(void (*cb)(void)) {}
278279
static inline void clear_hv_tscchange_cb(void) {}
279280
static inline void hyperv_stop_tsc_emulation(void) {};
281+
static inline void hv_apic_init(void) {}
280282
static inline struct hv_vp_assist_page *hv_get_vp_assist_page(unsigned int cpu)
281283
{
282284
return NULL;

0 commit comments

Comments
 (0)