xref: /openbmc/linux/arch/x86/kernel/paravirt.c (revision 41edafdb)
1b1df07bdSGlauber de Oliveira Costa /*  Paravirtualization interfaces
2b1df07bdSGlauber de Oliveira Costa     Copyright (C) 2006 Rusty Russell IBM Corporation
3b1df07bdSGlauber de Oliveira Costa 
4b1df07bdSGlauber de Oliveira Costa     This program is free software; you can redistribute it and/or modify
5b1df07bdSGlauber de Oliveira Costa     it under the terms of the GNU General Public License as published by
6b1df07bdSGlauber de Oliveira Costa     the Free Software Foundation; either version 2 of the License, or
7b1df07bdSGlauber de Oliveira Costa     (at your option) any later version.
8b1df07bdSGlauber de Oliveira Costa 
9b1df07bdSGlauber de Oliveira Costa     This program is distributed in the hope that it will be useful,
10b1df07bdSGlauber de Oliveira Costa     but WITHOUT ANY WARRANTY; without even the implied warranty of
11b1df07bdSGlauber de Oliveira Costa     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12b1df07bdSGlauber de Oliveira Costa     GNU General Public License for more details.
13b1df07bdSGlauber de Oliveira Costa 
14b1df07bdSGlauber de Oliveira Costa     You should have received a copy of the GNU General Public License
15b1df07bdSGlauber de Oliveira Costa     along with this program; if not, write to the Free Software
16b1df07bdSGlauber de Oliveira Costa     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17b1df07bdSGlauber de Oliveira Costa 
18b1df07bdSGlauber de Oliveira Costa     2007 - x86_64 support added by Glauber de Oliveira Costa, Red Hat Inc
19b1df07bdSGlauber de Oliveira Costa */
20b1df07bdSGlauber de Oliveira Costa 
21b1df07bdSGlauber de Oliveira Costa #include <linux/errno.h>
22b1df07bdSGlauber de Oliveira Costa #include <linux/module.h>
23b1df07bdSGlauber de Oliveira Costa #include <linux/efi.h>
24b1df07bdSGlauber de Oliveira Costa #include <linux/bcd.h>
25b1df07bdSGlauber de Oliveira Costa #include <linux/highmem.h>
26b1df07bdSGlauber de Oliveira Costa 
27b1df07bdSGlauber de Oliveira Costa #include <asm/bug.h>
28b1df07bdSGlauber de Oliveira Costa #include <asm/paravirt.h>
29b1df07bdSGlauber de Oliveira Costa #include <asm/desc.h>
30b1df07bdSGlauber de Oliveira Costa #include <asm/setup.h>
31b1df07bdSGlauber de Oliveira Costa #include <asm/arch_hooks.h>
32a312b37bSEduardo Habkost #include <asm/pgtable.h>
33b1df07bdSGlauber de Oliveira Costa #include <asm/time.h>
34eba0045fSJeremy Fitzhardinge #include <asm/pgalloc.h>
35b1df07bdSGlauber de Oliveira Costa #include <asm/irq.h>
36b1df07bdSGlauber de Oliveira Costa #include <asm/delay.h>
37b1df07bdSGlauber de Oliveira Costa #include <asm/fixmap.h>
38b1df07bdSGlauber de Oliveira Costa #include <asm/apic.h>
39b1df07bdSGlauber de Oliveira Costa #include <asm/tlbflush.h>
40b1df07bdSGlauber de Oliveira Costa #include <asm/timer.h>
41b1df07bdSGlauber de Oliveira Costa 
42b1df07bdSGlauber de Oliveira Costa /* nop stub */
43b1df07bdSGlauber de Oliveira Costa void _paravirt_nop(void)
44b1df07bdSGlauber de Oliveira Costa {
45b1df07bdSGlauber de Oliveira Costa }
46b1df07bdSGlauber de Oliveira Costa 
4741edafdbSJeremy Fitzhardinge /* identity function, which can be inlined */
4841edafdbSJeremy Fitzhardinge u32 _paravirt_ident_32(u32 x)
4941edafdbSJeremy Fitzhardinge {
5041edafdbSJeremy Fitzhardinge 	return x;
5141edafdbSJeremy Fitzhardinge }
5241edafdbSJeremy Fitzhardinge 
5341edafdbSJeremy Fitzhardinge u64 _paravirt_ident_64(u64 x)
5441edafdbSJeremy Fitzhardinge {
5541edafdbSJeremy Fitzhardinge 	return x;
5641edafdbSJeremy Fitzhardinge }
5741edafdbSJeremy Fitzhardinge 
58b1df07bdSGlauber de Oliveira Costa static void __init default_banner(void)
59b1df07bdSGlauber de Oliveira Costa {
60b1df07bdSGlauber de Oliveira Costa 	printk(KERN_INFO "Booting paravirtualized kernel on %s\n",
61b1df07bdSGlauber de Oliveira Costa 	       pv_info.name);
62b1df07bdSGlauber de Oliveira Costa }
63b1df07bdSGlauber de Oliveira Costa 
64b1df07bdSGlauber de Oliveira Costa char *memory_setup(void)
65b1df07bdSGlauber de Oliveira Costa {
66b1df07bdSGlauber de Oliveira Costa 	return pv_init_ops.memory_setup();
67b1df07bdSGlauber de Oliveira Costa }
68b1df07bdSGlauber de Oliveira Costa 
69b1df07bdSGlauber de Oliveira Costa /* Simple instruction patching code. */
70b1df07bdSGlauber de Oliveira Costa #define DEF_NATIVE(ops, name, code)					\
71b1df07bdSGlauber de Oliveira Costa 	extern const char start_##ops##_##name[], end_##ops##_##name[];	\
72b1df07bdSGlauber de Oliveira Costa 	asm("start_" #ops "_" #name ": " code "; end_" #ops "_" #name ":")
73b1df07bdSGlauber de Oliveira Costa 
74b1df07bdSGlauber de Oliveira Costa /* Undefined instruction for dealing with missing ops pointers. */
75b1df07bdSGlauber de Oliveira Costa static const unsigned char ud2a[] = { 0x0f, 0x0b };
76b1df07bdSGlauber de Oliveira Costa 
77b1df07bdSGlauber de Oliveira Costa unsigned paravirt_patch_nop(void)
78b1df07bdSGlauber de Oliveira Costa {
79b1df07bdSGlauber de Oliveira Costa 	return 0;
80b1df07bdSGlauber de Oliveira Costa }
81b1df07bdSGlauber de Oliveira Costa 
82b1df07bdSGlauber de Oliveira Costa unsigned paravirt_patch_ignore(unsigned len)
83b1df07bdSGlauber de Oliveira Costa {
84b1df07bdSGlauber de Oliveira Costa 	return len;
85b1df07bdSGlauber de Oliveira Costa }
86b1df07bdSGlauber de Oliveira Costa 
87b1df07bdSGlauber de Oliveira Costa struct branch {
88b1df07bdSGlauber de Oliveira Costa 	unsigned char opcode;
89b1df07bdSGlauber de Oliveira Costa 	u32 delta;
90b1df07bdSGlauber de Oliveira Costa } __attribute__((packed));
91b1df07bdSGlauber de Oliveira Costa 
92b1df07bdSGlauber de Oliveira Costa unsigned paravirt_patch_call(void *insnbuf,
93b1df07bdSGlauber de Oliveira Costa 			     const void *target, u16 tgt_clobbers,
94b1df07bdSGlauber de Oliveira Costa 			     unsigned long addr, u16 site_clobbers,
95b1df07bdSGlauber de Oliveira Costa 			     unsigned len)
96b1df07bdSGlauber de Oliveira Costa {
97b1df07bdSGlauber de Oliveira Costa 	struct branch *b = insnbuf;
98b1df07bdSGlauber de Oliveira Costa 	unsigned long delta = (unsigned long)target - (addr+5);
99b1df07bdSGlauber de Oliveira Costa 
100b1df07bdSGlauber de Oliveira Costa 	if (tgt_clobbers & ~site_clobbers)
101b1df07bdSGlauber de Oliveira Costa 		return len;	/* target would clobber too much for this site */
102b1df07bdSGlauber de Oliveira Costa 	if (len < 5)
103b1df07bdSGlauber de Oliveira Costa 		return len;	/* call too long for patch site */
104b1df07bdSGlauber de Oliveira Costa 
105b1df07bdSGlauber de Oliveira Costa 	b->opcode = 0xe8; /* call */
106b1df07bdSGlauber de Oliveira Costa 	b->delta = delta;
107b1df07bdSGlauber de Oliveira Costa 	BUILD_BUG_ON(sizeof(*b) != 5);
108b1df07bdSGlauber de Oliveira Costa 
109b1df07bdSGlauber de Oliveira Costa 	return 5;
110b1df07bdSGlauber de Oliveira Costa }
111b1df07bdSGlauber de Oliveira Costa 
112b1df07bdSGlauber de Oliveira Costa unsigned paravirt_patch_jmp(void *insnbuf, const void *target,
113b1df07bdSGlauber de Oliveira Costa 			    unsigned long addr, unsigned len)
114b1df07bdSGlauber de Oliveira Costa {
115b1df07bdSGlauber de Oliveira Costa 	struct branch *b = insnbuf;
116b1df07bdSGlauber de Oliveira Costa 	unsigned long delta = (unsigned long)target - (addr+5);
117b1df07bdSGlauber de Oliveira Costa 
118b1df07bdSGlauber de Oliveira Costa 	if (len < 5)
119b1df07bdSGlauber de Oliveira Costa 		return len;	/* call too long for patch site */
120b1df07bdSGlauber de Oliveira Costa 
121b1df07bdSGlauber de Oliveira Costa 	b->opcode = 0xe9;	/* jmp */
122b1df07bdSGlauber de Oliveira Costa 	b->delta = delta;
123b1df07bdSGlauber de Oliveira Costa 
124b1df07bdSGlauber de Oliveira Costa 	return 5;
125b1df07bdSGlauber de Oliveira Costa }
126b1df07bdSGlauber de Oliveira Costa 
127b1df07bdSGlauber de Oliveira Costa /* Neat trick to map patch type back to the call within the
128b1df07bdSGlauber de Oliveira Costa  * corresponding structure. */
129b1df07bdSGlauber de Oliveira Costa static void *get_call_destination(u8 type)
130b1df07bdSGlauber de Oliveira Costa {
131b1df07bdSGlauber de Oliveira Costa 	struct paravirt_patch_template tmpl = {
132b1df07bdSGlauber de Oliveira Costa 		.pv_init_ops = pv_init_ops,
133b1df07bdSGlauber de Oliveira Costa 		.pv_time_ops = pv_time_ops,
134b1df07bdSGlauber de Oliveira Costa 		.pv_cpu_ops = pv_cpu_ops,
135b1df07bdSGlauber de Oliveira Costa 		.pv_irq_ops = pv_irq_ops,
136b1df07bdSGlauber de Oliveira Costa 		.pv_apic_ops = pv_apic_ops,
137b1df07bdSGlauber de Oliveira Costa 		.pv_mmu_ops = pv_mmu_ops,
13874d4affdSJeremy Fitzhardinge 		.pv_lock_ops = pv_lock_ops,
139b1df07bdSGlauber de Oliveira Costa 	};
140b1df07bdSGlauber de Oliveira Costa 	return *((void **)&tmpl + type);
141b1df07bdSGlauber de Oliveira Costa }
142b1df07bdSGlauber de Oliveira Costa 
143b1df07bdSGlauber de Oliveira Costa unsigned paravirt_patch_default(u8 type, u16 clobbers, void *insnbuf,
144b1df07bdSGlauber de Oliveira Costa 				unsigned long addr, unsigned len)
145b1df07bdSGlauber de Oliveira Costa {
146b1df07bdSGlauber de Oliveira Costa 	void *opfunc = get_call_destination(type);
147b1df07bdSGlauber de Oliveira Costa 	unsigned ret;
148b1df07bdSGlauber de Oliveira Costa 
149b1df07bdSGlauber de Oliveira Costa 	if (opfunc == NULL)
150b1df07bdSGlauber de Oliveira Costa 		/* If there's no function, patch it with a ud2a (BUG) */
151b1df07bdSGlauber de Oliveira Costa 		ret = paravirt_patch_insns(insnbuf, len, ud2a, ud2a+sizeof(ud2a));
15241edafdbSJeremy Fitzhardinge 	else if (opfunc == _paravirt_nop)
153b1df07bdSGlauber de Oliveira Costa 		/* If the operation is a nop, then nop the callsite */
154b1df07bdSGlauber de Oliveira Costa 		ret = paravirt_patch_nop();
15541edafdbSJeremy Fitzhardinge 
15641edafdbSJeremy Fitzhardinge 	/* identity functions just return their single argument */
15741edafdbSJeremy Fitzhardinge 	else if (opfunc == _paravirt_ident_32)
15841edafdbSJeremy Fitzhardinge 		ret = paravirt_patch_ident_32(insnbuf, len);
15941edafdbSJeremy Fitzhardinge 	else if (opfunc == _paravirt_ident_64)
16041edafdbSJeremy Fitzhardinge 		ret = paravirt_patch_ident_64(insnbuf, len);
16141edafdbSJeremy Fitzhardinge 
162b1df07bdSGlauber de Oliveira Costa 	else if (type == PARAVIRT_PATCH(pv_cpu_ops.iret) ||
163d75cd22fSJeremy Fitzhardinge 		 type == PARAVIRT_PATCH(pv_cpu_ops.irq_enable_sysexit) ||
1642be29982SJeremy Fitzhardinge 		 type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret32) ||
1652be29982SJeremy Fitzhardinge 		 type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret64))
166b1df07bdSGlauber de Oliveira Costa 		/* If operation requires a jmp, then jmp */
167b1df07bdSGlauber de Oliveira Costa 		ret = paravirt_patch_jmp(insnbuf, opfunc, addr, len);
168b1df07bdSGlauber de Oliveira Costa 	else
169b1df07bdSGlauber de Oliveira Costa 		/* Otherwise call the function; assume target could
170b1df07bdSGlauber de Oliveira Costa 		   clobber any caller-save reg */
171b1df07bdSGlauber de Oliveira Costa 		ret = paravirt_patch_call(insnbuf, opfunc, CLBR_ANY,
172b1df07bdSGlauber de Oliveira Costa 					  addr, clobbers, len);
173b1df07bdSGlauber de Oliveira Costa 
174b1df07bdSGlauber de Oliveira Costa 	return ret;
175b1df07bdSGlauber de Oliveira Costa }
176b1df07bdSGlauber de Oliveira Costa 
177b1df07bdSGlauber de Oliveira Costa unsigned paravirt_patch_insns(void *insnbuf, unsigned len,
178b1df07bdSGlauber de Oliveira Costa 			      const char *start, const char *end)
179b1df07bdSGlauber de Oliveira Costa {
180b1df07bdSGlauber de Oliveira Costa 	unsigned insn_len = end - start;
181b1df07bdSGlauber de Oliveira Costa 
182b1df07bdSGlauber de Oliveira Costa 	if (insn_len > len || start == NULL)
183b1df07bdSGlauber de Oliveira Costa 		insn_len = len;
184b1df07bdSGlauber de Oliveira Costa 	else
185b1df07bdSGlauber de Oliveira Costa 		memcpy(insnbuf, start, insn_len);
186b1df07bdSGlauber de Oliveira Costa 
187b1df07bdSGlauber de Oliveira Costa 	return insn_len;
188b1df07bdSGlauber de Oliveira Costa }
189b1df07bdSGlauber de Oliveira Costa 
190b1df07bdSGlauber de Oliveira Costa void init_IRQ(void)
191b1df07bdSGlauber de Oliveira Costa {
192b1df07bdSGlauber de Oliveira Costa 	pv_irq_ops.init_IRQ();
193b1df07bdSGlauber de Oliveira Costa }
194b1df07bdSGlauber de Oliveira Costa 
195b1df07bdSGlauber de Oliveira Costa static void native_flush_tlb(void)
196b1df07bdSGlauber de Oliveira Costa {
197b1df07bdSGlauber de Oliveira Costa 	__native_flush_tlb();
198b1df07bdSGlauber de Oliveira Costa }
199b1df07bdSGlauber de Oliveira Costa 
200b1df07bdSGlauber de Oliveira Costa /*
201b1df07bdSGlauber de Oliveira Costa  * Global pages have to be flushed a bit differently. Not a real
202b1df07bdSGlauber de Oliveira Costa  * performance problem because this does not happen often.
203b1df07bdSGlauber de Oliveira Costa  */
204b1df07bdSGlauber de Oliveira Costa static void native_flush_tlb_global(void)
205b1df07bdSGlauber de Oliveira Costa {
206b1df07bdSGlauber de Oliveira Costa 	__native_flush_tlb_global();
207b1df07bdSGlauber de Oliveira Costa }
208b1df07bdSGlauber de Oliveira Costa 
209b1df07bdSGlauber de Oliveira Costa static void native_flush_tlb_single(unsigned long addr)
210b1df07bdSGlauber de Oliveira Costa {
211b1df07bdSGlauber de Oliveira Costa 	__native_flush_tlb_single(addr);
212b1df07bdSGlauber de Oliveira Costa }
213b1df07bdSGlauber de Oliveira Costa 
214b1df07bdSGlauber de Oliveira Costa /* These are in entry.S */
215b1df07bdSGlauber de Oliveira Costa extern void native_iret(void);
216d75cd22fSJeremy Fitzhardinge extern void native_irq_enable_sysexit(void);
2172be29982SJeremy Fitzhardinge extern void native_usergs_sysret32(void);
2182be29982SJeremy Fitzhardinge extern void native_usergs_sysret64(void);
219b1df07bdSGlauber de Oliveira Costa 
220b1df07bdSGlauber de Oliveira Costa static int __init print_banner(void)
221b1df07bdSGlauber de Oliveira Costa {
222b1df07bdSGlauber de Oliveira Costa 	pv_init_ops.banner();
223b1df07bdSGlauber de Oliveira Costa 	return 0;
224b1df07bdSGlauber de Oliveira Costa }
225b1df07bdSGlauber de Oliveira Costa core_initcall(print_banner);
226b1df07bdSGlauber de Oliveira Costa 
227b1df07bdSGlauber de Oliveira Costa static struct resource reserve_ioports = {
228b1df07bdSGlauber de Oliveira Costa 	.start = 0,
229b1df07bdSGlauber de Oliveira Costa 	.end = IO_SPACE_LIMIT,
230b1df07bdSGlauber de Oliveira Costa 	.name = "paravirt-ioport",
231b1df07bdSGlauber de Oliveira Costa 	.flags = IORESOURCE_IO | IORESOURCE_BUSY,
232b1df07bdSGlauber de Oliveira Costa };
233b1df07bdSGlauber de Oliveira Costa 
234b1df07bdSGlauber de Oliveira Costa /*
235b1df07bdSGlauber de Oliveira Costa  * Reserve the whole legacy IO space to prevent any legacy drivers
236b1df07bdSGlauber de Oliveira Costa  * from wasting time probing for their hardware.  This is a fairly
237b1df07bdSGlauber de Oliveira Costa  * brute-force approach to disabling all non-virtual drivers.
238b1df07bdSGlauber de Oliveira Costa  *
239b1df07bdSGlauber de Oliveira Costa  * Note that this must be called very early to have any effect.
240b1df07bdSGlauber de Oliveira Costa  */
241b1df07bdSGlauber de Oliveira Costa int paravirt_disable_iospace(void)
242b1df07bdSGlauber de Oliveira Costa {
243f7743fe6SJeremy Fitzhardinge 	return request_resource(&ioport_resource, &reserve_ioports);
244b1df07bdSGlauber de Oliveira Costa }
245b1df07bdSGlauber de Oliveira Costa 
246b1df07bdSGlauber de Oliveira Costa static DEFINE_PER_CPU(enum paravirt_lazy_mode, paravirt_lazy_mode) = PARAVIRT_LAZY_NONE;
247b1df07bdSGlauber de Oliveira Costa 
248b1df07bdSGlauber de Oliveira Costa static inline void enter_lazy(enum paravirt_lazy_mode mode)
249b1df07bdSGlauber de Oliveira Costa {
250bfd074e0SGlauber de Oliveira Costa 	BUG_ON(__get_cpu_var(paravirt_lazy_mode) != PARAVIRT_LAZY_NONE);
251b1df07bdSGlauber de Oliveira Costa 	BUG_ON(preemptible());
252b1df07bdSGlauber de Oliveira Costa 
253bfd074e0SGlauber de Oliveira Costa 	__get_cpu_var(paravirt_lazy_mode) = mode;
254b1df07bdSGlauber de Oliveira Costa }
255b1df07bdSGlauber de Oliveira Costa 
256b1df07bdSGlauber de Oliveira Costa void paravirt_leave_lazy(enum paravirt_lazy_mode mode)
257b1df07bdSGlauber de Oliveira Costa {
258bfd074e0SGlauber de Oliveira Costa 	BUG_ON(__get_cpu_var(paravirt_lazy_mode) != mode);
259b1df07bdSGlauber de Oliveira Costa 	BUG_ON(preemptible());
260b1df07bdSGlauber de Oliveira Costa 
261bfd074e0SGlauber de Oliveira Costa 	__get_cpu_var(paravirt_lazy_mode) = PARAVIRT_LAZY_NONE;
262b1df07bdSGlauber de Oliveira Costa }
263b1df07bdSGlauber de Oliveira Costa 
264b1df07bdSGlauber de Oliveira Costa void paravirt_enter_lazy_mmu(void)
265b1df07bdSGlauber de Oliveira Costa {
266b1df07bdSGlauber de Oliveira Costa 	enter_lazy(PARAVIRT_LAZY_MMU);
267b1df07bdSGlauber de Oliveira Costa }
268b1df07bdSGlauber de Oliveira Costa 
269b1df07bdSGlauber de Oliveira Costa void paravirt_leave_lazy_mmu(void)
270b1df07bdSGlauber de Oliveira Costa {
271b1df07bdSGlauber de Oliveira Costa 	paravirt_leave_lazy(PARAVIRT_LAZY_MMU);
272b1df07bdSGlauber de Oliveira Costa }
273b1df07bdSGlauber de Oliveira Costa 
274b1df07bdSGlauber de Oliveira Costa void paravirt_enter_lazy_cpu(void)
275b1df07bdSGlauber de Oliveira Costa {
276b1df07bdSGlauber de Oliveira Costa 	enter_lazy(PARAVIRT_LAZY_CPU);
277b1df07bdSGlauber de Oliveira Costa }
278b1df07bdSGlauber de Oliveira Costa 
279b1df07bdSGlauber de Oliveira Costa void paravirt_leave_lazy_cpu(void)
280b1df07bdSGlauber de Oliveira Costa {
281b1df07bdSGlauber de Oliveira Costa 	paravirt_leave_lazy(PARAVIRT_LAZY_CPU);
282b1df07bdSGlauber de Oliveira Costa }
283b1df07bdSGlauber de Oliveira Costa 
284b1df07bdSGlauber de Oliveira Costa enum paravirt_lazy_mode paravirt_get_lazy_mode(void)
285b1df07bdSGlauber de Oliveira Costa {
286bfd074e0SGlauber de Oliveira Costa 	return __get_cpu_var(paravirt_lazy_mode);
287b1df07bdSGlauber de Oliveira Costa }
288b1df07bdSGlauber de Oliveira Costa 
289b1df07bdSGlauber de Oliveira Costa struct pv_info pv_info = {
290b1df07bdSGlauber de Oliveira Costa 	.name = "bare hardware",
291b1df07bdSGlauber de Oliveira Costa 	.paravirt_enabled = 0,
292b1df07bdSGlauber de Oliveira Costa 	.kernel_rpl = 0,
293b1df07bdSGlauber de Oliveira Costa 	.shared_kernel_pmd = 1,	/* Only used when CONFIG_X86_PAE is set */
294b1df07bdSGlauber de Oliveira Costa };
295b1df07bdSGlauber de Oliveira Costa 
296b1df07bdSGlauber de Oliveira Costa struct pv_init_ops pv_init_ops = {
297b1df07bdSGlauber de Oliveira Costa 	.patch = native_patch,
298b1df07bdSGlauber de Oliveira Costa 	.banner = default_banner,
299b1df07bdSGlauber de Oliveira Costa 	.arch_setup = paravirt_nop,
300b1df07bdSGlauber de Oliveira Costa 	.memory_setup = machine_specific_memory_setup,
301b1df07bdSGlauber de Oliveira Costa };
302b1df07bdSGlauber de Oliveira Costa 
303b1df07bdSGlauber de Oliveira Costa struct pv_time_ops pv_time_ops = {
304b1df07bdSGlauber de Oliveira Costa 	.time_init = hpet_time_init,
305b1df07bdSGlauber de Oliveira Costa 	.get_wallclock = native_get_wallclock,
306b1df07bdSGlauber de Oliveira Costa 	.set_wallclock = native_set_wallclock,
307b1df07bdSGlauber de Oliveira Costa 	.sched_clock = native_sched_clock,
308e93ef949SAlok Kataria 	.get_tsc_khz = native_calibrate_tsc,
309b1df07bdSGlauber de Oliveira Costa };
310b1df07bdSGlauber de Oliveira Costa 
311b1df07bdSGlauber de Oliveira Costa struct pv_irq_ops pv_irq_ops = {
312b1df07bdSGlauber de Oliveira Costa 	.init_IRQ = native_init_IRQ,
313b1df07bdSGlauber de Oliveira Costa 	.save_fl = native_save_fl,
314b1df07bdSGlauber de Oliveira Costa 	.restore_fl = native_restore_fl,
315b1df07bdSGlauber de Oliveira Costa 	.irq_disable = native_irq_disable,
316b1df07bdSGlauber de Oliveira Costa 	.irq_enable = native_irq_enable,
317b1df07bdSGlauber de Oliveira Costa 	.safe_halt = native_safe_halt,
318b1df07bdSGlauber de Oliveira Costa 	.halt = native_halt,
319fab58420SJeremy Fitzhardinge #ifdef CONFIG_X86_64
320fab58420SJeremy Fitzhardinge 	.adjust_exception_frame = paravirt_nop,
321fab58420SJeremy Fitzhardinge #endif
322b1df07bdSGlauber de Oliveira Costa };
323b1df07bdSGlauber de Oliveira Costa 
324b1df07bdSGlauber de Oliveira Costa struct pv_cpu_ops pv_cpu_ops = {
325b1df07bdSGlauber de Oliveira Costa 	.cpuid = native_cpuid,
326b1df07bdSGlauber de Oliveira Costa 	.get_debugreg = native_get_debugreg,
327b1df07bdSGlauber de Oliveira Costa 	.set_debugreg = native_set_debugreg,
328b1df07bdSGlauber de Oliveira Costa 	.clts = native_clts,
329b1df07bdSGlauber de Oliveira Costa 	.read_cr0 = native_read_cr0,
330b1df07bdSGlauber de Oliveira Costa 	.write_cr0 = native_write_cr0,
331b1df07bdSGlauber de Oliveira Costa 	.read_cr4 = native_read_cr4,
332b1df07bdSGlauber de Oliveira Costa 	.read_cr4_safe = native_read_cr4_safe,
333b1df07bdSGlauber de Oliveira Costa 	.write_cr4 = native_write_cr4,
33488b4755fSGlauber de Oliveira Costa #ifdef CONFIG_X86_64
33588b4755fSGlauber de Oliveira Costa 	.read_cr8 = native_read_cr8,
33688b4755fSGlauber de Oliveira Costa 	.write_cr8 = native_write_cr8,
33788b4755fSGlauber de Oliveira Costa #endif
338b1df07bdSGlauber de Oliveira Costa 	.wbinvd = native_wbinvd,
339b1df07bdSGlauber de Oliveira Costa 	.read_msr = native_read_msr_safe,
340b05f78f5SYinghai Lu 	.read_msr_amd = native_read_msr_amd_safe,
341b1df07bdSGlauber de Oliveira Costa 	.write_msr = native_write_msr_safe,
342b1df07bdSGlauber de Oliveira Costa 	.read_tsc = native_read_tsc,
343b1df07bdSGlauber de Oliveira Costa 	.read_pmc = native_read_pmc,
344e5aaac44SGlauber de Oliveira Costa 	.read_tscp = native_read_tscp,
345b1df07bdSGlauber de Oliveira Costa 	.load_tr_desc = native_load_tr_desc,
346b1df07bdSGlauber de Oliveira Costa 	.set_ldt = native_set_ldt,
347b1df07bdSGlauber de Oliveira Costa 	.load_gdt = native_load_gdt,
348b1df07bdSGlauber de Oliveira Costa 	.load_idt = native_load_idt,
349b1df07bdSGlauber de Oliveira Costa 	.store_gdt = native_store_gdt,
350b1df07bdSGlauber de Oliveira Costa 	.store_idt = native_store_idt,
351b1df07bdSGlauber de Oliveira Costa 	.store_tr = native_store_tr,
352b1df07bdSGlauber de Oliveira Costa 	.load_tls = native_load_tls,
3539f9d489aSJeremy Fitzhardinge #ifdef CONFIG_X86_64
3549f9d489aSJeremy Fitzhardinge 	.load_gs_index = native_load_gs_index,
3559f9d489aSJeremy Fitzhardinge #endif
356b1df07bdSGlauber de Oliveira Costa 	.write_ldt_entry = native_write_ldt_entry,
357b1df07bdSGlauber de Oliveira Costa 	.write_gdt_entry = native_write_gdt_entry,
358b1df07bdSGlauber de Oliveira Costa 	.write_idt_entry = native_write_idt_entry,
35938ffbe66SJeremy Fitzhardinge 
36038ffbe66SJeremy Fitzhardinge 	.alloc_ldt = paravirt_nop,
36138ffbe66SJeremy Fitzhardinge 	.free_ldt = paravirt_nop,
36238ffbe66SJeremy Fitzhardinge 
363b1df07bdSGlauber de Oliveira Costa 	.load_sp0 = native_load_sp0,
364b1df07bdSGlauber de Oliveira Costa 
365102d0a4bSJeremy Fitzhardinge #if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION)
366d75cd22fSJeremy Fitzhardinge 	.irq_enable_sysexit = native_irq_enable_sysexit,
367102d0a4bSJeremy Fitzhardinge #endif
3682be29982SJeremy Fitzhardinge #ifdef CONFIG_X86_64
369102d0a4bSJeremy Fitzhardinge #ifdef CONFIG_IA32_EMULATION
3702be29982SJeremy Fitzhardinge 	.usergs_sysret32 = native_usergs_sysret32,
371102d0a4bSJeremy Fitzhardinge #endif
3722be29982SJeremy Fitzhardinge 	.usergs_sysret64 = native_usergs_sysret64,
373d75cd22fSJeremy Fitzhardinge #endif
374b1df07bdSGlauber de Oliveira Costa 	.iret = native_iret,
375e801f864SGlauber de Oliveira Costa 	.swapgs = native_swapgs,
376b1df07bdSGlauber de Oliveira Costa 
377b1df07bdSGlauber de Oliveira Costa 	.set_iopl_mask = native_set_iopl_mask,
378b1df07bdSGlauber de Oliveira Costa 	.io_delay = native_io_delay,
379b1df07bdSGlauber de Oliveira Costa 
380b1df07bdSGlauber de Oliveira Costa 	.lazy_mode = {
381b1df07bdSGlauber de Oliveira Costa 		.enter = paravirt_nop,
382b1df07bdSGlauber de Oliveira Costa 		.leave = paravirt_nop,
383b1df07bdSGlauber de Oliveira Costa 	},
384b1df07bdSGlauber de Oliveira Costa };
385b1df07bdSGlauber de Oliveira Costa 
386b1df07bdSGlauber de Oliveira Costa struct pv_apic_ops pv_apic_ops = {
387b1df07bdSGlauber de Oliveira Costa #ifdef CONFIG_X86_LOCAL_APIC
388b1df07bdSGlauber de Oliveira Costa 	.setup_boot_clock = setup_boot_APIC_clock,
389b1df07bdSGlauber de Oliveira Costa 	.setup_secondary_clock = setup_secondary_APIC_clock,
390b1df07bdSGlauber de Oliveira Costa 	.startup_ipi_hook = paravirt_nop,
391b1df07bdSGlauber de Oliveira Costa #endif
392b1df07bdSGlauber de Oliveira Costa };
393b1df07bdSGlauber de Oliveira Costa 
39441edafdbSJeremy Fitzhardinge typedef pte_t make_pte_t(pteval_t);
39541edafdbSJeremy Fitzhardinge typedef pmd_t make_pmd_t(pmdval_t);
39641edafdbSJeremy Fitzhardinge typedef pud_t make_pud_t(pudval_t);
39741edafdbSJeremy Fitzhardinge typedef pgd_t make_pgd_t(pgdval_t);
39841edafdbSJeremy Fitzhardinge 
39941edafdbSJeremy Fitzhardinge typedef pteval_t pte_val_t(pte_t);
40041edafdbSJeremy Fitzhardinge typedef pmdval_t pmd_val_t(pmd_t);
40141edafdbSJeremy Fitzhardinge typedef pudval_t pud_val_t(pud_t);
40241edafdbSJeremy Fitzhardinge typedef pgdval_t pgd_val_t(pgd_t);
40341edafdbSJeremy Fitzhardinge 
40441edafdbSJeremy Fitzhardinge 
40541edafdbSJeremy Fitzhardinge #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE)
40641edafdbSJeremy Fitzhardinge /* 32-bit pagetable entries */
40741edafdbSJeremy Fitzhardinge #define paravirt_native_make_pte	(make_pte_t *)_paravirt_ident_32
40841edafdbSJeremy Fitzhardinge #define paravirt_native_pte_val		(pte_val_t *)_paravirt_ident_32
40941edafdbSJeremy Fitzhardinge 
41041edafdbSJeremy Fitzhardinge #define paravirt_native_make_pmd	(make_pmd_t *)_paravirt_ident_32
41141edafdbSJeremy Fitzhardinge #define paravirt_native_pmd_val		(pmd_val_t *)_paravirt_ident_32
41241edafdbSJeremy Fitzhardinge 
41341edafdbSJeremy Fitzhardinge #define paravirt_native_make_pud	(make_pud_t *)_paravirt_ident_32
41441edafdbSJeremy Fitzhardinge #define paravirt_native_pud_val		(pud_val_t *)_paravirt_ident_32
41541edafdbSJeremy Fitzhardinge 
41641edafdbSJeremy Fitzhardinge #define paravirt_native_make_pgd	(make_pgd_t *)_paravirt_ident_32
41741edafdbSJeremy Fitzhardinge #define paravirt_native_pgd_val		(pgd_val_t *)_paravirt_ident_32
41841edafdbSJeremy Fitzhardinge #else
41941edafdbSJeremy Fitzhardinge /* 64-bit pagetable entries */
42041edafdbSJeremy Fitzhardinge #define paravirt_native_make_pte	(make_pte_t *)_paravirt_ident_64
42141edafdbSJeremy Fitzhardinge #define paravirt_native_pte_val		(pte_val_t *)_paravirt_ident_64
42241edafdbSJeremy Fitzhardinge 
42341edafdbSJeremy Fitzhardinge #define paravirt_native_make_pmd	(make_pmd_t *)_paravirt_ident_64
42441edafdbSJeremy Fitzhardinge #define paravirt_native_pmd_val		(pmd_val_t *)_paravirt_ident_64
42541edafdbSJeremy Fitzhardinge 
42641edafdbSJeremy Fitzhardinge #define paravirt_native_make_pud	(make_pud_t *)_paravirt_ident_64
42741edafdbSJeremy Fitzhardinge #define paravirt_native_pud_val		(pud_val_t *)_paravirt_ident_64
42841edafdbSJeremy Fitzhardinge 
42941edafdbSJeremy Fitzhardinge #define paravirt_native_make_pgd	(make_pgd_t *)_paravirt_ident_64
43041edafdbSJeremy Fitzhardinge #define paravirt_native_pgd_val		(pgd_val_t *)_paravirt_ident_64
43141edafdbSJeremy Fitzhardinge #endif
43241edafdbSJeremy Fitzhardinge 
433b1df07bdSGlauber de Oliveira Costa struct pv_mmu_ops pv_mmu_ops = {
434d8dd8eecSEduardo Habkost #ifndef CONFIG_X86_64
435b1df07bdSGlauber de Oliveira Costa 	.pagetable_setup_start = native_pagetable_setup_start,
436b1df07bdSGlauber de Oliveira Costa 	.pagetable_setup_done = native_pagetable_setup_done,
437a312b37bSEduardo Habkost #else
438a312b37bSEduardo Habkost 	.pagetable_setup_start = paravirt_nop,
439a312b37bSEduardo Habkost 	.pagetable_setup_done = paravirt_nop,
440d8dd8eecSEduardo Habkost #endif
441b1df07bdSGlauber de Oliveira Costa 
442b1df07bdSGlauber de Oliveira Costa 	.read_cr2 = native_read_cr2,
443b1df07bdSGlauber de Oliveira Costa 	.write_cr2 = native_write_cr2,
444b1df07bdSGlauber de Oliveira Costa 	.read_cr3 = native_read_cr3,
445b1df07bdSGlauber de Oliveira Costa 	.write_cr3 = native_write_cr3,
446b1df07bdSGlauber de Oliveira Costa 
447b1df07bdSGlauber de Oliveira Costa 	.flush_tlb_user = native_flush_tlb,
448b1df07bdSGlauber de Oliveira Costa 	.flush_tlb_kernel = native_flush_tlb_global,
449b1df07bdSGlauber de Oliveira Costa 	.flush_tlb_single = native_flush_tlb_single,
450b1df07bdSGlauber de Oliveira Costa 	.flush_tlb_others = native_flush_tlb_others,
451b1df07bdSGlauber de Oliveira Costa 
452eba0045fSJeremy Fitzhardinge 	.pgd_alloc = __paravirt_pgd_alloc,
453eba0045fSJeremy Fitzhardinge 	.pgd_free = paravirt_nop,
454eba0045fSJeremy Fitzhardinge 
4556944a9c8SJeremy Fitzhardinge 	.alloc_pte = paravirt_nop,
4566944a9c8SJeremy Fitzhardinge 	.alloc_pmd = paravirt_nop,
4576944a9c8SJeremy Fitzhardinge 	.alloc_pmd_clone = paravirt_nop,
4582761fa09SJeremy Fitzhardinge 	.alloc_pud = paravirt_nop,
4596944a9c8SJeremy Fitzhardinge 	.release_pte = paravirt_nop,
4606944a9c8SJeremy Fitzhardinge 	.release_pmd = paravirt_nop,
4612761fa09SJeremy Fitzhardinge 	.release_pud = paravirt_nop,
462b1df07bdSGlauber de Oliveira Costa 
463b1df07bdSGlauber de Oliveira Costa 	.set_pte = native_set_pte,
464b1df07bdSGlauber de Oliveira Costa 	.set_pte_at = native_set_pte_at,
465b1df07bdSGlauber de Oliveira Costa 	.set_pmd = native_set_pmd,
466b1df07bdSGlauber de Oliveira Costa 	.pte_update = paravirt_nop,
467b1df07bdSGlauber de Oliveira Costa 	.pte_update_defer = paravirt_nop,
468b1df07bdSGlauber de Oliveira Costa 
46908b882c6SJeremy Fitzhardinge 	.ptep_modify_prot_start = __ptep_modify_prot_start,
47008b882c6SJeremy Fitzhardinge 	.ptep_modify_prot_commit = __ptep_modify_prot_commit,
47108b882c6SJeremy Fitzhardinge 
472b1df07bdSGlauber de Oliveira Costa #ifdef CONFIG_HIGHPTE
473b1df07bdSGlauber de Oliveira Costa 	.kmap_atomic_pte = kmap_atomic,
474b1df07bdSGlauber de Oliveira Costa #endif
475b1df07bdSGlauber de Oliveira Costa 
476f95f2f7bSEduardo Habkost #if PAGETABLE_LEVELS >= 3
477b1df07bdSGlauber de Oliveira Costa #ifdef CONFIG_X86_PAE
478b1df07bdSGlauber de Oliveira Costa 	.set_pte_atomic = native_set_pte_atomic,
479b1df07bdSGlauber de Oliveira Costa 	.set_pte_present = native_set_pte_present,
480b1df07bdSGlauber de Oliveira Costa 	.pte_clear = native_pte_clear,
481b1df07bdSGlauber de Oliveira Costa 	.pmd_clear = native_pmd_clear,
482f95f2f7bSEduardo Habkost #endif
483f95f2f7bSEduardo Habkost 	.set_pud = native_set_pud,
48441edafdbSJeremy Fitzhardinge 	.pmd_val = paravirt_native_pmd_val,
48541edafdbSJeremy Fitzhardinge 	.make_pmd = paravirt_native_make_pmd,
486f95f2f7bSEduardo Habkost 
487f95f2f7bSEduardo Habkost #if PAGETABLE_LEVELS == 4
48841edafdbSJeremy Fitzhardinge 	.pud_val = paravirt_native_pud_val,
48941edafdbSJeremy Fitzhardinge 	.make_pud = paravirt_native_make_pud,
490f95f2f7bSEduardo Habkost 	.set_pgd = native_set_pgd,
491b1df07bdSGlauber de Oliveira Costa #endif
492f95f2f7bSEduardo Habkost #endif /* PAGETABLE_LEVELS >= 3 */
493b1df07bdSGlauber de Oliveira Costa 
49441edafdbSJeremy Fitzhardinge 	.pte_val = paravirt_native_pte_val,
49541edafdbSJeremy Fitzhardinge 	.pgd_val = paravirt_native_pgd_val,
496b1df07bdSGlauber de Oliveira Costa 
49741edafdbSJeremy Fitzhardinge 	.make_pte = paravirt_native_make_pte,
49841edafdbSJeremy Fitzhardinge 	.make_pgd = paravirt_native_make_pgd,
499b1df07bdSGlauber de Oliveira Costa 
500b1df07bdSGlauber de Oliveira Costa 	.dup_mmap = paravirt_nop,
501b1df07bdSGlauber de Oliveira Costa 	.exit_mmap = paravirt_nop,
502b1df07bdSGlauber de Oliveira Costa 	.activate_mm = paravirt_nop,
503b1df07bdSGlauber de Oliveira Costa 
504b1df07bdSGlauber de Oliveira Costa 	.lazy_mode = {
505b1df07bdSGlauber de Oliveira Costa 		.enter = paravirt_nop,
506b1df07bdSGlauber de Oliveira Costa 		.leave = paravirt_nop,
507b1df07bdSGlauber de Oliveira Costa 	},
508aeaaa59cSJeremy Fitzhardinge 
509aeaaa59cSJeremy Fitzhardinge 	.set_fixmap = native_set_fixmap,
510b1df07bdSGlauber de Oliveira Costa };
511b1df07bdSGlauber de Oliveira Costa 
512b1df07bdSGlauber de Oliveira Costa EXPORT_SYMBOL_GPL(pv_time_ops);
513b1df07bdSGlauber de Oliveira Costa EXPORT_SYMBOL    (pv_cpu_ops);
514b1df07bdSGlauber de Oliveira Costa EXPORT_SYMBOL    (pv_mmu_ops);
515b1df07bdSGlauber de Oliveira Costa EXPORT_SYMBOL_GPL(pv_apic_ops);
516b1df07bdSGlauber de Oliveira Costa EXPORT_SYMBOL_GPL(pv_info);
517b1df07bdSGlauber de Oliveira Costa EXPORT_SYMBOL    (pv_irq_ops);
518