aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-02-22 14:38:22 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-22 14:38:22 -0500
commite30aee9e10bb5168579e047f05c3d13d09e23356 (patch)
tree12371bdcd52d2427cad838201997479e31b6a9c9 /arch
parent8ff546b801e5cca0337c0f0a7234795d0a6309a1 (diff)
parent6cf18e6927c0b224f972e3042fb85770d63cb9f8 (diff)
Merge tag 'char-misc-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver updates from Greg KH: "Here is the big char/misc driver patchset for 4.11-rc1. Lots of different driver subsystems updated here: rework for the hyperv subsystem to handle new platforms better, mei and w1 and extcon driver updates, as well as a number of other "minor" driver updates. All of these have been in linux-next for a while with no reported issues" * tag 'char-misc-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (169 commits) goldfish: Sanitize the broken interrupt handler x86/platform/goldfish: Prevent unconditional loading vmbus: replace modulus operation with subtraction vmbus: constify parameters where possible vmbus: expose hv_begin/end_read vmbus: remove conditional locking of vmbus_write vmbus: add direct isr callback mode vmbus: change to per channel tasklet vmbus: put related per-cpu variable together vmbus: callback is in softirq not workqueue binder: Add support for file-descriptor arrays binder: Add support for scatter-gather binder: Add extra size to allocator binder: Refactor binder_transact() binder: Support multiple /dev instances binder: Deal with contexts in debugfs binder: Support multiple context managers binder: Split flat_binder_object auxdisplay: ht16k33: remove private workqueue auxdisplay: ht16k33: rework input device initialization ...
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-davinci/da850.c10
-rw-r--r--arch/arm/mach-davinci/da8xx-dt.c12
-rw-r--r--arch/x86/Kbuild3
-rw-r--r--arch/x86/hyperv/Makefile1
-rw-r--r--arch/x86/hyperv/hv_init.c277
-rw-r--r--arch/x86/include/asm/mshyperv.h151
-rw-r--r--arch/x86/include/uapi/asm/hyperv.h8
-rw-r--r--arch/x86/kernel/cpu/mshyperv.c50
-rw-r--r--arch/x86/platform/goldfish/goldfish.c14
9 files changed, 492 insertions, 34 deletions
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 1d873d15b545..9780829f8a05 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -557,15 +557,7 @@ static struct clk_lookup da850_clks[] = {
557 CLK("da830-mmc.0", NULL, &mmcsd0_clk), 557 CLK("da830-mmc.0", NULL, &mmcsd0_clk),
558 CLK("da830-mmc.1", NULL, &mmcsd1_clk), 558 CLK("da830-mmc.1", NULL, &mmcsd1_clk),
559 CLK("ti-aemif", NULL, &aemif_clk), 559 CLK("ti-aemif", NULL, &aemif_clk),
560 /* 560 CLK("davinci-nand.0", "aemif", &aemif_nand_clk),
561 * The only user of this clock is davinci_nand and it get's it through
562 * con_id. The nand node itself is created from within the aemif
563 * driver to guarantee that it's probed after the aemif timing
564 * parameters are configured. of_dev_auxdata is not accessible from
565 * the aemif driver and can't be passed to of_platform_populate(). For
566 * that reason we're leaving the dev_id here as NULL.
567 */
568 CLK(NULL, "aemif", &aemif_nand_clk),
569 CLK("ohci-da8xx", "usb11", &usb11_clk), 561 CLK("ohci-da8xx", "usb11", &usb11_clk),
570 CLK("musb-da8xx", "usb20", &usb20_clk), 562 CLK("musb-da8xx", "usb20", &usb20_clk),
571 CLK("spi_davinci.0", NULL, &spi0_clk), 563 CLK("spi_davinci.0", NULL, &spi0_clk),
diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c
index 9ee44da6eb7b..06205fe4c120 100644
--- a/arch/arm/mach-davinci/da8xx-dt.c
+++ b/arch/arm/mach-davinci/da8xx-dt.c
@@ -11,6 +11,7 @@
11#include <linux/of_irq.h> 11#include <linux/of_irq.h>
12#include <linux/of_platform.h> 12#include <linux/of_platform.h>
13#include <linux/irqdomain.h> 13#include <linux/irqdomain.h>
14#include <linux/platform_data/ti-aemif.h>
14 15
15#include <asm/mach/arch.h> 16#include <asm/mach/arch.h>
16 17
@@ -18,6 +19,15 @@
18#include "cp_intc.h" 19#include "cp_intc.h"
19#include <mach/da8xx.h> 20#include <mach/da8xx.h>
20 21
22static struct of_dev_auxdata da850_aemif_auxdata_lookup[] = {
23 OF_DEV_AUXDATA("ti,davinci-nand", 0x62000000, "davinci-nand.0", NULL),
24 {}
25};
26
27static struct aemif_platform_data aemif_data = {
28 .dev_lookup = da850_aemif_auxdata_lookup,
29};
30
21static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = { 31static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
22 OF_DEV_AUXDATA("ti,davinci-i2c", 0x01c22000, "i2c_davinci.1", NULL), 32 OF_DEV_AUXDATA("ti,davinci-i2c", 0x01c22000, "i2c_davinci.1", NULL),
23 OF_DEV_AUXDATA("ti,davinci-i2c", 0x01e28000, "i2c_davinci.2", NULL), 33 OF_DEV_AUXDATA("ti,davinci-i2c", 0x01e28000, "i2c_davinci.2", NULL),
@@ -37,7 +47,7 @@ static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
37 OF_DEV_AUXDATA("ti,davinci-dm6467-emac", 0x01e20000, "davinci_emac.1", 47 OF_DEV_AUXDATA("ti,davinci-dm6467-emac", 0x01e20000, "davinci_emac.1",
38 NULL), 48 NULL),
39 OF_DEV_AUXDATA("ti,da830-mcasp-audio", 0x01d00000, "davinci-mcasp.0", NULL), 49 OF_DEV_AUXDATA("ti,da830-mcasp-audio", 0x01d00000, "davinci-mcasp.0", NULL),
40 OF_DEV_AUXDATA("ti,da850-aemif", 0x68000000, "ti-aemif", NULL), 50 OF_DEV_AUXDATA("ti,da850-aemif", 0x68000000, "ti-aemif", &aemif_data),
41 OF_DEV_AUXDATA("ti,da850-tilcdc", 0x01e13000, "da8xx_lcdc.0", NULL), 51 OF_DEV_AUXDATA("ti,da850-tilcdc", 0x01e13000, "da8xx_lcdc.0", NULL),
42 OF_DEV_AUXDATA("ti,da830-ohci", 0x01e25000, "ohci-da8xx", NULL), 52 OF_DEV_AUXDATA("ti,da830-ohci", 0x01e25000, "ohci-da8xx", NULL),
43 OF_DEV_AUXDATA("ti,da830-musb", 0x01e00000, "musb-da8xx", NULL), 53 OF_DEV_AUXDATA("ti,da830-musb", 0x01e00000, "musb-da8xx", NULL),
diff --git a/arch/x86/Kbuild b/arch/x86/Kbuild
index eb3abf8ac44e..586b786b3edf 100644
--- a/arch/x86/Kbuild
+++ b/arch/x86/Kbuild
@@ -7,6 +7,9 @@ obj-$(CONFIG_KVM) += kvm/
7# Xen paravirtualization support 7# Xen paravirtualization support
8obj-$(CONFIG_XEN) += xen/ 8obj-$(CONFIG_XEN) += xen/
9 9
10# Hyper-V paravirtualization support
11obj-$(CONFIG_HYPERVISOR_GUEST) += hyperv/
12
10# lguest paravirtualization support 13# lguest paravirtualization support
11obj-$(CONFIG_LGUEST_GUEST) += lguest/ 14obj-$(CONFIG_LGUEST_GUEST) += lguest/
12 15
diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile
new file mode 100644
index 000000000000..171ae09864d7
--- /dev/null
+++ b/arch/x86/hyperv/Makefile
@@ -0,0 +1 @@
obj-y := hv_init.o
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
new file mode 100644
index 000000000000..db64baf0e500
--- /dev/null
+++ b/arch/x86/hyperv/hv_init.c
@@ -0,0 +1,277 @@
1/*
2 * X86 specific Hyper-V initialization code.
3 *
4 * Copyright (C) 2016, Microsoft, Inc.
5 *
6 * Author : K. Y. Srinivasan <kys@microsoft.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published
10 * by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
15 * NON INFRINGEMENT. See the GNU General Public License for more
16 * details.
17 *
18 */
19
20#include <linux/types.h>
21#include <asm/hypervisor.h>
22#include <asm/hyperv.h>
23#include <asm/mshyperv.h>
24#include <linux/version.h>
25#include <linux/vmalloc.h>
26#include <linux/mm.h>
27#include <linux/clockchips.h>
28
29
30#ifdef CONFIG_X86_64
31
32static struct ms_hyperv_tsc_page *tsc_pg;
33
34static u64 read_hv_clock_tsc(struct clocksource *arg)
35{
36 u64 current_tick;
37
38 if (tsc_pg->tsc_sequence != 0) {
39 /*
40 * Use the tsc page to compute the value.
41 */
42
43 while (1) {
44 u64 tmp;
45 u32 sequence = tsc_pg->tsc_sequence;
46 u64 cur_tsc;
47 u64 scale = tsc_pg->tsc_scale;
48 s64 offset = tsc_pg->tsc_offset;
49
50 rdtscll(cur_tsc);
51 /* current_tick = ((cur_tsc *scale) >> 64) + offset */
52 asm("mulq %3"
53 : "=d" (current_tick), "=a" (tmp)
54 : "a" (cur_tsc), "r" (scale));
55
56 current_tick += offset;
57 if (tsc_pg->tsc_sequence == sequence)
58 return current_tick;
59
60 if (tsc_pg->tsc_sequence != 0)
61 continue;
62 /*
63 * Fallback using MSR method.
64 */
65 break;
66 }
67 }
68 rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
69 return current_tick;
70}
71
72static struct clocksource hyperv_cs_tsc = {
73 .name = "hyperv_clocksource_tsc_page",
74 .rating = 400,
75 .read = read_hv_clock_tsc,
76 .mask = CLOCKSOURCE_MASK(64),
77 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
78};
79#endif
80
81static u64 read_hv_clock_msr(struct clocksource *arg)
82{
83 u64 current_tick;
84 /*
85 * Read the partition counter to get the current tick count. This count
86 * is set to 0 when the partition is created and is incremented in
87 * 100 nanosecond units.
88 */
89 rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
90 return current_tick;
91}
92
93static struct clocksource hyperv_cs_msr = {
94 .name = "hyperv_clocksource_msr",
95 .rating = 400,
96 .read = read_hv_clock_msr,
97 .mask = CLOCKSOURCE_MASK(64),
98 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
99};
100
101static void *hypercall_pg;
102struct clocksource *hyperv_cs;
103EXPORT_SYMBOL_GPL(hyperv_cs);
104
105/*
106 * This function is to be invoked early in the boot sequence after the
107 * hypervisor has been detected.
108 *
109 * 1. Setup the hypercall page.
110 * 2. Register Hyper-V specific clocksource.
111 */
112void hyperv_init(void)
113{
114 u64 guest_id;
115 union hv_x64_msr_hypercall_contents hypercall_msr;
116
117 if (x86_hyper != &x86_hyper_ms_hyperv)
118 return;
119
120 /*
121 * Setup the hypercall page and enable hypercalls.
122 * 1. Register the guest ID
123 * 2. Enable the hypercall and register the hypercall page
124 */
125 guest_id = generate_guest_id(0, LINUX_VERSION_CODE, 0);
126 wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id);
127
128 hypercall_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX);
129 if (hypercall_pg == NULL) {
130 wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
131 return;
132 }
133
134 rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
135 hypercall_msr.enable = 1;
136 hypercall_msr.guest_physical_address = vmalloc_to_pfn(hypercall_pg);
137 wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
138
139 /*
140 * Register Hyper-V specific clocksource.
141 */
142#ifdef CONFIG_X86_64
143 if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) {
144 union hv_x64_msr_hypercall_contents tsc_msr;
145
146 tsc_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL);
147 if (!tsc_pg)
148 goto register_msr_cs;
149
150 hyperv_cs = &hyperv_cs_tsc;
151
152 rdmsrl(HV_X64_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
153
154 tsc_msr.enable = 1;
155 tsc_msr.guest_physical_address = vmalloc_to_pfn(tsc_pg);
156
157 wrmsrl(HV_X64_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
158 clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100);
159 return;
160 }
161#endif
162 /*
163 * For 32 bit guests just use the MSR based mechanism for reading
164 * the partition counter.
165 */
166
167register_msr_cs:
168 hyperv_cs = &hyperv_cs_msr;
169 if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
170 clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100);
171}
172
173/*
174 * This routine is called before kexec/kdump, it does the required cleanup.
175 */
176void hyperv_cleanup(void)
177{
178 union hv_x64_msr_hypercall_contents hypercall_msr;
179
180 /* Reset our OS id */
181 wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
182
183 /* Reset the hypercall page */
184 hypercall_msr.as_uint64 = 0;
185 wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
186
187 /* Reset the TSC page */
188 hypercall_msr.as_uint64 = 0;
189 wrmsrl(HV_X64_MSR_REFERENCE_TSC, hypercall_msr.as_uint64);
190}
191EXPORT_SYMBOL_GPL(hyperv_cleanup);
192
193/*
194 * hv_do_hypercall- Invoke the specified hypercall
195 */
196u64 hv_do_hypercall(u64 control, void *input, void *output)
197{
198 u64 input_address = (input) ? virt_to_phys(input) : 0;
199 u64 output_address = (output) ? virt_to_phys(output) : 0;
200#ifdef CONFIG_X86_64
201 u64 hv_status = 0;
202
203 if (!hypercall_pg)
204 return (u64)ULLONG_MAX;
205
206 __asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8");
207 __asm__ __volatile__("call *%3" : "=a" (hv_status) :
208 "c" (control), "d" (input_address),
209 "m" (hypercall_pg));
210
211 return hv_status;
212
213#else
214
215 u32 control_hi = control >> 32;
216 u32 control_lo = control & 0xFFFFFFFF;
217 u32 hv_status_hi = 1;
218 u32 hv_status_lo = 1;
219 u32 input_address_hi = input_address >> 32;
220 u32 input_address_lo = input_address & 0xFFFFFFFF;
221 u32 output_address_hi = output_address >> 32;
222 u32 output_address_lo = output_address & 0xFFFFFFFF;
223
224 if (!hypercall_pg)
225 return (u64)ULLONG_MAX;
226
227 __asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi),
228 "=a"(hv_status_lo) : "d" (control_hi),
229 "a" (control_lo), "b" (input_address_hi),
230 "c" (input_address_lo), "D"(output_address_hi),
231 "S"(output_address_lo), "m" (hypercall_pg));
232
233 return hv_status_lo | ((u64)hv_status_hi << 32);
234#endif /* !x86_64 */
235}
236EXPORT_SYMBOL_GPL(hv_do_hypercall);
237
238void hyperv_report_panic(struct pt_regs *regs)
239{
240 static bool panic_reported;
241
242 /*
243 * We prefer to report panic on 'die' chain as we have proper
244 * registers to report, but if we miss it (e.g. on BUG()) we need
245 * to report it on 'panic'.
246 */
247 if (panic_reported)
248 return;
249 panic_reported = true;
250
251 wrmsrl(HV_X64_MSR_CRASH_P0, regs->ip);
252 wrmsrl(HV_X64_MSR_CRASH_P1, regs->ax);
253 wrmsrl(HV_X64_MSR_CRASH_P2, regs->bx);
254 wrmsrl(HV_X64_MSR_CRASH_P3, regs->cx);
255 wrmsrl(HV_X64_MSR_CRASH_P4, regs->dx);
256
257 /*
258 * Let Hyper-V know there is crash data available
259 */
260 wrmsrl(HV_X64_MSR_CRASH_CTL, HV_CRASH_CTL_CRASH_NOTIFY);
261}
262EXPORT_SYMBOL_GPL(hyperv_report_panic);
263
264bool hv_is_hypercall_page_setup(void)
265{
266 union hv_x64_msr_hypercall_contents hypercall_msr;
267
268 /* Check if the hypercall page is setup */
269 hypercall_msr.as_uint64 = 0;
270 rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
271
272 if (!hypercall_msr.enable)
273 return false;
274
275 return true;
276}
277EXPORT_SYMBOL_GPL(hv_is_hypercall_page_setup);
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index aaf59b7da98a..7c9c895432a9 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -3,8 +3,28 @@
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5#include <linux/interrupt.h> 5#include <linux/interrupt.h>
6#include <linux/clocksource.h>
6#include <asm/hyperv.h> 7#include <asm/hyperv.h>
7 8
9/*
10 * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
11 * is set by CPUID(HVCPUID_VERSION_FEATURES).
12 */
13enum hv_cpuid_function {
14 HVCPUID_VERSION_FEATURES = 0x00000001,
15 HVCPUID_VENDOR_MAXFUNCTION = 0x40000000,
16 HVCPUID_INTERFACE = 0x40000001,
17
18 /*
19 * The remaining functions depend on the value of
20 * HVCPUID_INTERFACE
21 */
22 HVCPUID_VERSION = 0x40000002,
23 HVCPUID_FEATURES = 0x40000003,
24 HVCPUID_ENLIGHTENMENT_INFO = 0x40000004,
25 HVCPUID_IMPLEMENTATION_LIMITS = 0x40000005,
26};
27
8struct ms_hyperv_info { 28struct ms_hyperv_info {
9 u32 features; 29 u32 features;
10 u32 misc_features; 30 u32 misc_features;
@@ -13,6 +33,128 @@ struct ms_hyperv_info {
13 33
14extern struct ms_hyperv_info ms_hyperv; 34extern struct ms_hyperv_info ms_hyperv;
15 35
36/*
37 * Declare the MSR used to setup pages used to communicate with the hypervisor.
38 */
39union hv_x64_msr_hypercall_contents {
40 u64 as_uint64;
41 struct {
42 u64 enable:1;
43 u64 reserved:11;
44 u64 guest_physical_address:52;
45 };
46};
47
48/*
49 * TSC page layout.
50 */
51
52struct ms_hyperv_tsc_page {
53 volatile u32 tsc_sequence;
54 u32 reserved1;
55 volatile u64 tsc_scale;
56 volatile s64 tsc_offset;
57 u64 reserved2[509];
58};
59
60/*
61 * The guest OS needs to register the guest ID with the hypervisor.
62 * The guest ID is a 64 bit entity and the structure of this ID is
63 * specified in the Hyper-V specification:
64 *
65 * msdn.microsoft.com/en-us/library/windows/hardware/ff542653%28v=vs.85%29.aspx
66 *
67 * While the current guideline does not specify how Linux guest ID(s)
68 * need to be generated, our plan is to publish the guidelines for
69 * Linux and other guest operating systems that currently are hosted
70 * on Hyper-V. The implementation here conforms to this yet
71 * unpublished guidelines.
72 *
73 *
74 * Bit(s)
75 * 63 - Indicates if the OS is Open Source or not; 1 is Open Source
76 * 62:56 - Os Type; Linux is 0x100
77 * 55:48 - Distro specific identification
78 * 47:16 - Linux kernel version number
79 * 15:0 - Distro specific identification
80 *
81 *
82 */
83
84#define HV_LINUX_VENDOR_ID 0x8100
85
86/*
87 * Generate the guest ID based on the guideline described above.
88 */
89
90static inline __u64 generate_guest_id(__u64 d_info1, __u64 kernel_version,
91 __u64 d_info2)
92{
93 __u64 guest_id = 0;
94
95 guest_id = (((__u64)HV_LINUX_VENDOR_ID) << 48);
96 guest_id |= (d_info1 << 48);
97 guest_id |= (kernel_version << 16);
98 guest_id |= d_info2;
99
100 return guest_id;
101}
102
103
104/* Free the message slot and signal end-of-message if required */
105static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type)
106{
107 /*
108 * On crash we're reading some other CPU's message page and we need
109 * to be careful: this other CPU may already had cleared the header
110 * and the host may already had delivered some other message there.
111 * In case we blindly write msg->header.message_type we're going
112 * to lose it. We can still lose a message of the same type but
113 * we count on the fact that there can only be one
114 * CHANNELMSG_UNLOAD_RESPONSE and we don't care about other messages
115 * on crash.
116 */
117 if (cmpxchg(&msg->header.message_type, old_msg_type,
118 HVMSG_NONE) != old_msg_type)
119 return;
120
121 /*
122 * Make sure the write to MessageType (ie set to
123 * HVMSG_NONE) happens before we read the
124 * MessagePending and EOMing. Otherwise, the EOMing
125 * will not deliver any more messages since there is
126 * no empty slot
127 */
128 mb();
129
130 if (msg->header.message_flags.msg_pending) {
131 /*
132 * This will cause message queue rescan to
133 * possibly deliver another msg from the
134 * hypervisor
135 */
136 wrmsrl(HV_X64_MSR_EOM, 0);
137 }
138}
139
140#define hv_get_current_tick(tick) rdmsrl(HV_X64_MSR_TIME_REF_COUNT, tick)
141#define hv_init_timer(timer, tick) wrmsrl(timer, tick)
142#define hv_init_timer_config(config, val) wrmsrl(config, val)
143
144#define hv_get_simp(val) rdmsrl(HV_X64_MSR_SIMP, val)
145#define hv_set_simp(val) wrmsrl(HV_X64_MSR_SIMP, val)
146
147#define hv_get_siefp(val) rdmsrl(HV_X64_MSR_SIEFP, val)
148#define hv_set_siefp(val) wrmsrl(HV_X64_MSR_SIEFP, val)
149
150#define hv_get_synic_state(val) rdmsrl(HV_X64_MSR_SCONTROL, val)
151#define hv_set_synic_state(val) wrmsrl(HV_X64_MSR_SCONTROL, val)
152
153#define hv_get_vp_index(index) rdmsrl(HV_X64_MSR_VP_INDEX, index)
154
155#define hv_get_synint_state(int_num, val) rdmsrl(int_num, val)
156#define hv_set_synint_state(int_num, val) wrmsrl(int_num, val)
157
16void hyperv_callback_vector(void); 158void hyperv_callback_vector(void);
17#ifdef CONFIG_TRACING 159#ifdef CONFIG_TRACING
18#define trace_hyperv_callback_vector hyperv_callback_vector 160#define trace_hyperv_callback_vector hyperv_callback_vector
@@ -25,4 +167,13 @@ void hv_setup_kexec_handler(void (*handler)(void));
25void hv_remove_kexec_handler(void); 167void hv_remove_kexec_handler(void);
26void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs)); 168void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
27void hv_remove_crash_handler(void); 169void hv_remove_crash_handler(void);
170
171#if IS_ENABLED(CONFIG_HYPERV)
172extern struct clocksource *hyperv_cs;
173
174void hyperv_init(void);
175void hyperv_report_panic(struct pt_regs *regs);
176bool hv_is_hypercall_page_setup(void);
177void hyperv_cleanup(void);
178#endif
28#endif 179#endif
diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h
index 9b1a91834ac8..3a20ccf787b8 100644
--- a/arch/x86/include/uapi/asm/hyperv.h
+++ b/arch/x86/include/uapi/asm/hyperv.h
@@ -73,6 +73,9 @@
73 */ 73 */
74#define HV_X64_MSR_STAT_PAGES_AVAILABLE (1 << 8) 74#define HV_X64_MSR_STAT_PAGES_AVAILABLE (1 << 8)
75 75
76/* Crash MSR available */
77#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE (1 << 10)
78
76/* 79/*
77 * Feature identification: EBX indicates which flags were specified at 80 * Feature identification: EBX indicates which flags were specified at
78 * partition creation. The format is the same as the partition creation 81 * partition creation. The format is the same as the partition creation
@@ -144,6 +147,11 @@
144 */ 147 */
145#define HV_X64_RELAXED_TIMING_RECOMMENDED (1 << 5) 148#define HV_X64_RELAXED_TIMING_RECOMMENDED (1 << 5)
146 149
150/*
151 * Crash notification flag.
152 */
153#define HV_CRASH_CTL_CRASH_NOTIFY (1ULL << 63)
154
147/* MSR used to identify the guest OS. */ 155/* MSR used to identify the guest OS. */
148#define HV_X64_MSR_GUEST_OS_ID 0x40000000 156#define HV_X64_MSR_GUEST_OS_ID 0x40000000
149 157
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index 65e20c97e04b..b5375b9497b3 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -133,26 +133,6 @@ static uint32_t __init ms_hyperv_platform(void)
133 return 0; 133 return 0;
134} 134}
135 135
136static u64 read_hv_clock(struct clocksource *arg)
137{
138 u64 current_tick;
139 /*
140 * Read the partition counter to get the current tick count. This count
141 * is set to 0 when the partition is created and is incremented in
142 * 100 nanosecond units.
143 */
144 rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
145 return current_tick;
146}
147
148static struct clocksource hyperv_cs = {
149 .name = "hyperv_clocksource",
150 .rating = 400, /* use this when running on Hyperv*/
151 .read = read_hv_clock,
152 .mask = CLOCKSOURCE_MASK(64),
153 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
154};
155
156static unsigned char hv_get_nmi_reason(void) 136static unsigned char hv_get_nmi_reason(void)
157{ 137{
158 return 0; 138 return 0;
@@ -180,6 +160,11 @@ static int hv_nmi_unknown(unsigned int val, struct pt_regs *regs)
180 160
181static void __init ms_hyperv_init_platform(void) 161static void __init ms_hyperv_init_platform(void)
182{ 162{
163 int hv_host_info_eax;
164 int hv_host_info_ebx;
165 int hv_host_info_ecx;
166 int hv_host_info_edx;
167
183 /* 168 /*
184 * Extract the features and hints 169 * Extract the features and hints
185 */ 170 */
@@ -190,6 +175,21 @@ static void __init ms_hyperv_init_platform(void)
190 pr_info("HyperV: features 0x%x, hints 0x%x\n", 175 pr_info("HyperV: features 0x%x, hints 0x%x\n",
191 ms_hyperv.features, ms_hyperv.hints); 176 ms_hyperv.features, ms_hyperv.hints);
192 177
178 /*
179 * Extract host information.
180 */
181 if (cpuid_eax(HVCPUID_VENDOR_MAXFUNCTION) >= HVCPUID_VERSION) {
182 hv_host_info_eax = cpuid_eax(HVCPUID_VERSION);
183 hv_host_info_ebx = cpuid_ebx(HVCPUID_VERSION);
184 hv_host_info_ecx = cpuid_ecx(HVCPUID_VERSION);
185 hv_host_info_edx = cpuid_edx(HVCPUID_VERSION);
186
187 pr_info("Hyper-V Host Build:%d-%d.%d-%d-%d.%d\n",
188 hv_host_info_eax, hv_host_info_ebx >> 16,
189 hv_host_info_ebx & 0xFFFF, hv_host_info_ecx,
190 hv_host_info_edx >> 24, hv_host_info_edx & 0xFFFFFF);
191 }
192
193#ifdef CONFIG_X86_LOCAL_APIC 193#ifdef CONFIG_X86_LOCAL_APIC
194 if (ms_hyperv.features & HV_X64_MSR_APIC_FREQUENCY_AVAILABLE) { 194 if (ms_hyperv.features & HV_X64_MSR_APIC_FREQUENCY_AVAILABLE) {
195 /* 195 /*
@@ -208,9 +208,6 @@ static void __init ms_hyperv_init_platform(void)
208 "hv_nmi_unknown"); 208 "hv_nmi_unknown");
209#endif 209#endif
210 210
211 if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
212 clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100);
213
214#ifdef CONFIG_X86_IO_APIC 211#ifdef CONFIG_X86_IO_APIC
215 no_timer_check = 1; 212 no_timer_check = 1;
216#endif 213#endif
@@ -227,6 +224,13 @@ static void __init ms_hyperv_init_platform(void)
227 */ 224 */
228 if (efi_enabled(EFI_BOOT)) 225 if (efi_enabled(EFI_BOOT))
229 x86_platform.get_nmi_reason = hv_get_nmi_reason; 226 x86_platform.get_nmi_reason = hv_get_nmi_reason;
227
228#if IS_ENABLED(CONFIG_HYPERV)
229 /*
230 * Setup the hook to get control post apic initialization.
231 */
232 x86_platform.apic_post_init = hyperv_init;
233#endif
230} 234}
231 235
232const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { 236const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
diff --git a/arch/x86/platform/goldfish/goldfish.c b/arch/x86/platform/goldfish/goldfish.c
index 1693107a518e..0d17c0aafeb1 100644
--- a/arch/x86/platform/goldfish/goldfish.c
+++ b/arch/x86/platform/goldfish/goldfish.c
@@ -42,10 +42,22 @@ static struct resource goldfish_pdev_bus_resources[] = {
42 } 42 }
43}; 43};
44 44
45static bool goldfish_enable __initdata;
46
47static int __init goldfish_setup(char *str)
48{
49 goldfish_enable = true;
50 return 0;
51}
52__setup("goldfish", goldfish_setup);
53
45static int __init goldfish_init(void) 54static int __init goldfish_init(void)
46{ 55{
56 if (!goldfish_enable)
57 return -ENODEV;
58
47 platform_device_register_simple("goldfish_pdev_bus", -1, 59 platform_device_register_simple("goldfish_pdev_bus", -1,
48 goldfish_pdev_bus_resources, 2); 60 goldfish_pdev_bus_resources, 2);
49 return 0; 61 return 0;
50} 62}
51device_initcall(goldfish_init); 63device_initcall(goldfish_init);