xref: /openbmc/linux/arch/x86/kernel/paravirt.c (revision b05f78f5)
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 
47b1df07bdSGlauber de Oliveira Costa static void __init default_banner(void)
48b1df07bdSGlauber de Oliveira Costa {
49b1df07bdSGlauber de Oliveira Costa 	printk(KERN_INFO "Booting paravirtualized kernel on %s\n",
50b1df07bdSGlauber de Oliveira Costa 	       pv_info.name);
51b1df07bdSGlauber de Oliveira Costa }
52b1df07bdSGlauber de Oliveira Costa 
53b1df07bdSGlauber de Oliveira Costa char *memory_setup(void)
54b1df07bdSGlauber de Oliveira Costa {
55b1df07bdSGlauber de Oliveira Costa 	return pv_init_ops.memory_setup();
56b1df07bdSGlauber de Oliveira Costa }
57b1df07bdSGlauber de Oliveira Costa 
58b1df07bdSGlauber de Oliveira Costa /* Simple instruction patching code. */
59b1df07bdSGlauber de Oliveira Costa #define DEF_NATIVE(ops, name, code)					\
60b1df07bdSGlauber de Oliveira Costa 	extern const char start_##ops##_##name[], end_##ops##_##name[];	\
61b1df07bdSGlauber de Oliveira Costa 	asm("start_" #ops "_" #name ": " code "; end_" #ops "_" #name ":")
62b1df07bdSGlauber de Oliveira Costa 
63b1df07bdSGlauber de Oliveira Costa /* Undefined instruction for dealing with missing ops pointers. */
64b1df07bdSGlauber de Oliveira Costa static const unsigned char ud2a[] = { 0x0f, 0x0b };
65b1df07bdSGlauber de Oliveira Costa 
66b1df07bdSGlauber de Oliveira Costa unsigned paravirt_patch_nop(void)
67b1df07bdSGlauber de Oliveira Costa {
68b1df07bdSGlauber de Oliveira Costa 	return 0;
69b1df07bdSGlauber de Oliveira Costa }
70b1df07bdSGlauber de Oliveira Costa 
71b1df07bdSGlauber de Oliveira Costa unsigned paravirt_patch_ignore(unsigned len)
72b1df07bdSGlauber de Oliveira Costa {
73b1df07bdSGlauber de Oliveira Costa 	return len;
74b1df07bdSGlauber de Oliveira Costa }
75b1df07bdSGlauber de Oliveira Costa 
76b1df07bdSGlauber de Oliveira Costa struct branch {
77b1df07bdSGlauber de Oliveira Costa 	unsigned char opcode;
78b1df07bdSGlauber de Oliveira Costa 	u32 delta;
79b1df07bdSGlauber de Oliveira Costa } __attribute__((packed));
80b1df07bdSGlauber de Oliveira Costa 
81b1df07bdSGlauber de Oliveira Costa unsigned paravirt_patch_call(void *insnbuf,
82b1df07bdSGlauber de Oliveira Costa 			     const void *target, u16 tgt_clobbers,
83b1df07bdSGlauber de Oliveira Costa 			     unsigned long addr, u16 site_clobbers,
84b1df07bdSGlauber de Oliveira Costa 			     unsigned len)
85b1df07bdSGlauber de Oliveira Costa {
86b1df07bdSGlauber de Oliveira Costa 	struct branch *b = insnbuf;
87b1df07bdSGlauber de Oliveira Costa 	unsigned long delta = (unsigned long)target - (addr+5);
88b1df07bdSGlauber de Oliveira Costa 
89b1df07bdSGlauber de Oliveira Costa 	if (tgt_clobbers & ~site_clobbers)
90b1df07bdSGlauber de Oliveira Costa 		return len;	/* target would clobber too much for this site */
91b1df07bdSGlauber de Oliveira Costa 	if (len < 5)
92b1df07bdSGlauber de Oliveira Costa 		return len;	/* call too long for patch site */
93b1df07bdSGlauber de Oliveira Costa 
94b1df07bdSGlauber de Oliveira Costa 	b->opcode = 0xe8; /* call */
95b1df07bdSGlauber de Oliveira Costa 	b->delta = delta;
96b1df07bdSGlauber de Oliveira Costa 	BUILD_BUG_ON(sizeof(*b) != 5);
97b1df07bdSGlauber de Oliveira Costa 
98b1df07bdSGlauber de Oliveira Costa 	return 5;
99b1df07bdSGlauber de Oliveira Costa }
100b1df07bdSGlauber de Oliveira Costa 
101b1df07bdSGlauber de Oliveira Costa unsigned paravirt_patch_jmp(void *insnbuf, const void *target,
102b1df07bdSGlauber de Oliveira Costa 			    unsigned long addr, unsigned len)
103b1df07bdSGlauber de Oliveira Costa {
104b1df07bdSGlauber de Oliveira Costa 	struct branch *b = insnbuf;
105b1df07bdSGlauber de Oliveira Costa 	unsigned long delta = (unsigned long)target - (addr+5);
106b1df07bdSGlauber de Oliveira Costa 
107b1df07bdSGlauber de Oliveira Costa 	if (len < 5)
108b1df07bdSGlauber de Oliveira Costa 		return len;	/* call too long for patch site */
109b1df07bdSGlauber de Oliveira Costa 
110b1df07bdSGlauber de Oliveira Costa 	b->opcode = 0xe9;	/* jmp */
111b1df07bdSGlauber de Oliveira Costa 	b->delta = delta;
112b1df07bdSGlauber de Oliveira Costa 
113b1df07bdSGlauber de Oliveira Costa 	return 5;
114b1df07bdSGlauber de Oliveira Costa }
115b1df07bdSGlauber de Oliveira Costa 
116b1df07bdSGlauber de Oliveira Costa /* Neat trick to map patch type back to the call within the
117b1df07bdSGlauber de Oliveira Costa  * corresponding structure. */
118b1df07bdSGlauber de Oliveira Costa static void *get_call_destination(u8 type)
119b1df07bdSGlauber de Oliveira Costa {
120b1df07bdSGlauber de Oliveira Costa 	struct paravirt_patch_template tmpl = {
121b1df07bdSGlauber de Oliveira Costa 		.pv_init_ops = pv_init_ops,
122b1df07bdSGlauber de Oliveira Costa 		.pv_time_ops = pv_time_ops,
123b1df07bdSGlauber de Oliveira Costa 		.pv_cpu_ops = pv_cpu_ops,
124b1df07bdSGlauber de Oliveira Costa 		.pv_irq_ops = pv_irq_ops,
125b1df07bdSGlauber de Oliveira Costa 		.pv_apic_ops = pv_apic_ops,
126b1df07bdSGlauber de Oliveira Costa 		.pv_mmu_ops = pv_mmu_ops,
12774d4affdSJeremy Fitzhardinge 		.pv_lock_ops = pv_lock_ops,
128b1df07bdSGlauber de Oliveira Costa 	};
129b1df07bdSGlauber de Oliveira Costa 	return *((void **)&tmpl + type);
130b1df07bdSGlauber de Oliveira Costa }
131b1df07bdSGlauber de Oliveira Costa 
132b1df07bdSGlauber de Oliveira Costa unsigned paravirt_patch_default(u8 type, u16 clobbers, void *insnbuf,
133b1df07bdSGlauber de Oliveira Costa 				unsigned long addr, unsigned len)
134b1df07bdSGlauber de Oliveira Costa {
135b1df07bdSGlauber de Oliveira Costa 	void *opfunc = get_call_destination(type);
136b1df07bdSGlauber de Oliveira Costa 	unsigned ret;
137b1df07bdSGlauber de Oliveira Costa 
138b1df07bdSGlauber de Oliveira Costa 	if (opfunc == NULL)
139b1df07bdSGlauber de Oliveira Costa 		/* If there's no function, patch it with a ud2a (BUG) */
140b1df07bdSGlauber de Oliveira Costa 		ret = paravirt_patch_insns(insnbuf, len, ud2a, ud2a+sizeof(ud2a));
141b1df07bdSGlauber de Oliveira Costa 	else if (opfunc == paravirt_nop)
142b1df07bdSGlauber de Oliveira Costa 		/* If the operation is a nop, then nop the callsite */
143b1df07bdSGlauber de Oliveira Costa 		ret = paravirt_patch_nop();
144b1df07bdSGlauber de Oliveira Costa 	else if (type == PARAVIRT_PATCH(pv_cpu_ops.iret) ||
145d75cd22fSJeremy Fitzhardinge 		 type == PARAVIRT_PATCH(pv_cpu_ops.irq_enable_sysexit) ||
1462be29982SJeremy Fitzhardinge 		 type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret32) ||
1472be29982SJeremy Fitzhardinge 		 type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret64))
148b1df07bdSGlauber de Oliveira Costa 		/* If operation requires a jmp, then jmp */
149b1df07bdSGlauber de Oliveira Costa 		ret = paravirt_patch_jmp(insnbuf, opfunc, addr, len);
150b1df07bdSGlauber de Oliveira Costa 	else
151b1df07bdSGlauber de Oliveira Costa 		/* Otherwise call the function; assume target could
152b1df07bdSGlauber de Oliveira Costa 		   clobber any caller-save reg */
153b1df07bdSGlauber de Oliveira Costa 		ret = paravirt_patch_call(insnbuf, opfunc, CLBR_ANY,
154b1df07bdSGlauber de Oliveira Costa 					  addr, clobbers, len);
155b1df07bdSGlauber de Oliveira Costa 
156b1df07bdSGlauber de Oliveira Costa 	return ret;
157b1df07bdSGlauber de Oliveira Costa }
158b1df07bdSGlauber de Oliveira Costa 
159b1df07bdSGlauber de Oliveira Costa unsigned paravirt_patch_insns(void *insnbuf, unsigned len,
160b1df07bdSGlauber de Oliveira Costa 			      const char *start, const char *end)
161b1df07bdSGlauber de Oliveira Costa {
162b1df07bdSGlauber de Oliveira Costa 	unsigned insn_len = end - start;
163b1df07bdSGlauber de Oliveira Costa 
164b1df07bdSGlauber de Oliveira Costa 	if (insn_len > len || start == NULL)
165b1df07bdSGlauber de Oliveira Costa 		insn_len = len;
166b1df07bdSGlauber de Oliveira Costa 	else
167b1df07bdSGlauber de Oliveira Costa 		memcpy(insnbuf, start, insn_len);
168b1df07bdSGlauber de Oliveira Costa 
169b1df07bdSGlauber de Oliveira Costa 	return insn_len;
170b1df07bdSGlauber de Oliveira Costa }
171b1df07bdSGlauber de Oliveira Costa 
172b1df07bdSGlauber de Oliveira Costa void init_IRQ(void)
173b1df07bdSGlauber de Oliveira Costa {
174b1df07bdSGlauber de Oliveira Costa 	pv_irq_ops.init_IRQ();
175b1df07bdSGlauber de Oliveira Costa }
176b1df07bdSGlauber de Oliveira Costa 
177b1df07bdSGlauber de Oliveira Costa static void native_flush_tlb(void)
178b1df07bdSGlauber de Oliveira Costa {
179b1df07bdSGlauber de Oliveira Costa 	__native_flush_tlb();
180b1df07bdSGlauber de Oliveira Costa }
181b1df07bdSGlauber de Oliveira Costa 
182b1df07bdSGlauber de Oliveira Costa /*
183b1df07bdSGlauber de Oliveira Costa  * Global pages have to be flushed a bit differently. Not a real
184b1df07bdSGlauber de Oliveira Costa  * performance problem because this does not happen often.
185b1df07bdSGlauber de Oliveira Costa  */
186b1df07bdSGlauber de Oliveira Costa static void native_flush_tlb_global(void)
187b1df07bdSGlauber de Oliveira Costa {
188b1df07bdSGlauber de Oliveira Costa 	__native_flush_tlb_global();
189b1df07bdSGlauber de Oliveira Costa }
190b1df07bdSGlauber de Oliveira Costa 
191b1df07bdSGlauber de Oliveira Costa static void native_flush_tlb_single(unsigned long addr)
192b1df07bdSGlauber de Oliveira Costa {
193b1df07bdSGlauber de Oliveira Costa 	__native_flush_tlb_single(addr);
194b1df07bdSGlauber de Oliveira Costa }
195b1df07bdSGlauber de Oliveira Costa 
196b1df07bdSGlauber de Oliveira Costa /* These are in entry.S */
197b1df07bdSGlauber de Oliveira Costa extern void native_iret(void);
198d75cd22fSJeremy Fitzhardinge extern void native_irq_enable_sysexit(void);
1992be29982SJeremy Fitzhardinge extern void native_usergs_sysret32(void);
2002be29982SJeremy Fitzhardinge extern void native_usergs_sysret64(void);
201b1df07bdSGlauber de Oliveira Costa 
202b1df07bdSGlauber de Oliveira Costa static int __init print_banner(void)
203b1df07bdSGlauber de Oliveira Costa {
204b1df07bdSGlauber de Oliveira Costa 	pv_init_ops.banner();
205b1df07bdSGlauber de Oliveira Costa 	return 0;
206b1df07bdSGlauber de Oliveira Costa }
207b1df07bdSGlauber de Oliveira Costa core_initcall(print_banner);
208b1df07bdSGlauber de Oliveira Costa 
209b1df07bdSGlauber de Oliveira Costa static struct resource reserve_ioports = {
210b1df07bdSGlauber de Oliveira Costa 	.start = 0,
211b1df07bdSGlauber de Oliveira Costa 	.end = IO_SPACE_LIMIT,
212b1df07bdSGlauber de Oliveira Costa 	.name = "paravirt-ioport",
213b1df07bdSGlauber de Oliveira Costa 	.flags = IORESOURCE_IO | IORESOURCE_BUSY,
214b1df07bdSGlauber de Oliveira Costa };
215b1df07bdSGlauber de Oliveira Costa 
216b1df07bdSGlauber de Oliveira Costa /*
217b1df07bdSGlauber de Oliveira Costa  * Reserve the whole legacy IO space to prevent any legacy drivers
218b1df07bdSGlauber de Oliveira Costa  * from wasting time probing for their hardware.  This is a fairly
219b1df07bdSGlauber de Oliveira Costa  * brute-force approach to disabling all non-virtual drivers.
220b1df07bdSGlauber de Oliveira Costa  *
221b1df07bdSGlauber de Oliveira Costa  * Note that this must be called very early to have any effect.
222b1df07bdSGlauber de Oliveira Costa  */
223b1df07bdSGlauber de Oliveira Costa int paravirt_disable_iospace(void)
224b1df07bdSGlauber de Oliveira Costa {
225f7743fe6SJeremy Fitzhardinge 	return request_resource(&ioport_resource, &reserve_ioports);
226b1df07bdSGlauber de Oliveira Costa }
227b1df07bdSGlauber de Oliveira Costa 
228b1df07bdSGlauber de Oliveira Costa static DEFINE_PER_CPU(enum paravirt_lazy_mode, paravirt_lazy_mode) = PARAVIRT_LAZY_NONE;
229b1df07bdSGlauber de Oliveira Costa 
230b1df07bdSGlauber de Oliveira Costa static inline void enter_lazy(enum paravirt_lazy_mode mode)
231b1df07bdSGlauber de Oliveira Costa {
232bfd074e0SGlauber de Oliveira Costa 	BUG_ON(__get_cpu_var(paravirt_lazy_mode) != PARAVIRT_LAZY_NONE);
233b1df07bdSGlauber de Oliveira Costa 	BUG_ON(preemptible());
234b1df07bdSGlauber de Oliveira Costa 
235bfd074e0SGlauber de Oliveira Costa 	__get_cpu_var(paravirt_lazy_mode) = mode;
236b1df07bdSGlauber de Oliveira Costa }
237b1df07bdSGlauber de Oliveira Costa 
238b1df07bdSGlauber de Oliveira Costa void paravirt_leave_lazy(enum paravirt_lazy_mode mode)
239b1df07bdSGlauber de Oliveira Costa {
240bfd074e0SGlauber de Oliveira Costa 	BUG_ON(__get_cpu_var(paravirt_lazy_mode) != mode);
241b1df07bdSGlauber de Oliveira Costa 	BUG_ON(preemptible());
242b1df07bdSGlauber de Oliveira Costa 
243bfd074e0SGlauber de Oliveira Costa 	__get_cpu_var(paravirt_lazy_mode) = PARAVIRT_LAZY_NONE;
244b1df07bdSGlauber de Oliveira Costa }
245b1df07bdSGlauber de Oliveira Costa 
246b1df07bdSGlauber de Oliveira Costa void paravirt_enter_lazy_mmu(void)
247b1df07bdSGlauber de Oliveira Costa {
248b1df07bdSGlauber de Oliveira Costa 	enter_lazy(PARAVIRT_LAZY_MMU);
249b1df07bdSGlauber de Oliveira Costa }
250b1df07bdSGlauber de Oliveira Costa 
251b1df07bdSGlauber de Oliveira Costa void paravirt_leave_lazy_mmu(void)
252b1df07bdSGlauber de Oliveira Costa {
253b1df07bdSGlauber de Oliveira Costa 	paravirt_leave_lazy(PARAVIRT_LAZY_MMU);
254b1df07bdSGlauber de Oliveira Costa }
255b1df07bdSGlauber de Oliveira Costa 
256b1df07bdSGlauber de Oliveira Costa void paravirt_enter_lazy_cpu(void)
257b1df07bdSGlauber de Oliveira Costa {
258b1df07bdSGlauber de Oliveira Costa 	enter_lazy(PARAVIRT_LAZY_CPU);
259b1df07bdSGlauber de Oliveira Costa }
260b1df07bdSGlauber de Oliveira Costa 
261b1df07bdSGlauber de Oliveira Costa void paravirt_leave_lazy_cpu(void)
262b1df07bdSGlauber de Oliveira Costa {
263b1df07bdSGlauber de Oliveira Costa 	paravirt_leave_lazy(PARAVIRT_LAZY_CPU);
264b1df07bdSGlauber de Oliveira Costa }
265b1df07bdSGlauber de Oliveira Costa 
266b1df07bdSGlauber de Oliveira Costa enum paravirt_lazy_mode paravirt_get_lazy_mode(void)
267b1df07bdSGlauber de Oliveira Costa {
268bfd074e0SGlauber de Oliveira Costa 	return __get_cpu_var(paravirt_lazy_mode);
269b1df07bdSGlauber de Oliveira Costa }
270b1df07bdSGlauber de Oliveira Costa 
2718efcbab6SJeremy Fitzhardinge void __init paravirt_use_bytelocks(void)
2728efcbab6SJeremy Fitzhardinge {
2734bb689eeSIngo Molnar #ifdef CONFIG_SMP
2748efcbab6SJeremy Fitzhardinge 	pv_lock_ops.spin_is_locked = __byte_spin_is_locked;
2758efcbab6SJeremy Fitzhardinge 	pv_lock_ops.spin_is_contended = __byte_spin_is_contended;
2768efcbab6SJeremy Fitzhardinge 	pv_lock_ops.spin_lock = __byte_spin_lock;
2778efcbab6SJeremy Fitzhardinge 	pv_lock_ops.spin_trylock = __byte_spin_trylock;
2788efcbab6SJeremy Fitzhardinge 	pv_lock_ops.spin_unlock = __byte_spin_unlock;
2794bb689eeSIngo Molnar #endif
2808efcbab6SJeremy Fitzhardinge }
2818efcbab6SJeremy Fitzhardinge 
282b1df07bdSGlauber de Oliveira Costa struct pv_info pv_info = {
283b1df07bdSGlauber de Oliveira Costa 	.name = "bare hardware",
284b1df07bdSGlauber de Oliveira Costa 	.paravirt_enabled = 0,
285b1df07bdSGlauber de Oliveira Costa 	.kernel_rpl = 0,
286b1df07bdSGlauber de Oliveira Costa 	.shared_kernel_pmd = 1,	/* Only used when CONFIG_X86_PAE is set */
287b1df07bdSGlauber de Oliveira Costa };
288b1df07bdSGlauber de Oliveira Costa 
289b1df07bdSGlauber de Oliveira Costa struct pv_init_ops pv_init_ops = {
290b1df07bdSGlauber de Oliveira Costa 	.patch = native_patch,
291b1df07bdSGlauber de Oliveira Costa 	.banner = default_banner,
292b1df07bdSGlauber de Oliveira Costa 	.arch_setup = paravirt_nop,
293b1df07bdSGlauber de Oliveira Costa 	.memory_setup = machine_specific_memory_setup,
294b1df07bdSGlauber de Oliveira Costa };
295b1df07bdSGlauber de Oliveira Costa 
296b1df07bdSGlauber de Oliveira Costa struct pv_time_ops pv_time_ops = {
297b1df07bdSGlauber de Oliveira Costa 	.time_init = hpet_time_init,
298b1df07bdSGlauber de Oliveira Costa 	.get_wallclock = native_get_wallclock,
299b1df07bdSGlauber de Oliveira Costa 	.set_wallclock = native_set_wallclock,
300b1df07bdSGlauber de Oliveira Costa 	.sched_clock = native_sched_clock,
301e93ef949SAlok Kataria 	.get_tsc_khz = native_calibrate_tsc,
302b1df07bdSGlauber de Oliveira Costa };
303b1df07bdSGlauber de Oliveira Costa 
304b1df07bdSGlauber de Oliveira Costa struct pv_irq_ops pv_irq_ops = {
305b1df07bdSGlauber de Oliveira Costa 	.init_IRQ = native_init_IRQ,
306b1df07bdSGlauber de Oliveira Costa 	.save_fl = native_save_fl,
307b1df07bdSGlauber de Oliveira Costa 	.restore_fl = native_restore_fl,
308b1df07bdSGlauber de Oliveira Costa 	.irq_disable = native_irq_disable,
309b1df07bdSGlauber de Oliveira Costa 	.irq_enable = native_irq_enable,
310b1df07bdSGlauber de Oliveira Costa 	.safe_halt = native_safe_halt,
311b1df07bdSGlauber de Oliveira Costa 	.halt = native_halt,
312fab58420SJeremy Fitzhardinge #ifdef CONFIG_X86_64
313fab58420SJeremy Fitzhardinge 	.adjust_exception_frame = paravirt_nop,
314fab58420SJeremy Fitzhardinge #endif
315b1df07bdSGlauber de Oliveira Costa };
316b1df07bdSGlauber de Oliveira Costa 
317b1df07bdSGlauber de Oliveira Costa struct pv_cpu_ops pv_cpu_ops = {
318b1df07bdSGlauber de Oliveira Costa 	.cpuid = native_cpuid,
319b1df07bdSGlauber de Oliveira Costa 	.get_debugreg = native_get_debugreg,
320b1df07bdSGlauber de Oliveira Costa 	.set_debugreg = native_set_debugreg,
321b1df07bdSGlauber de Oliveira Costa 	.clts = native_clts,
322b1df07bdSGlauber de Oliveira Costa 	.read_cr0 = native_read_cr0,
323b1df07bdSGlauber de Oliveira Costa 	.write_cr0 = native_write_cr0,
324b1df07bdSGlauber de Oliveira Costa 	.read_cr4 = native_read_cr4,
325b1df07bdSGlauber de Oliveira Costa 	.read_cr4_safe = native_read_cr4_safe,
326b1df07bdSGlauber de Oliveira Costa 	.write_cr4 = native_write_cr4,
32788b4755fSGlauber de Oliveira Costa #ifdef CONFIG_X86_64
32888b4755fSGlauber de Oliveira Costa 	.read_cr8 = native_read_cr8,
32988b4755fSGlauber de Oliveira Costa 	.write_cr8 = native_write_cr8,
33088b4755fSGlauber de Oliveira Costa #endif
331b1df07bdSGlauber de Oliveira Costa 	.wbinvd = native_wbinvd,
332b1df07bdSGlauber de Oliveira Costa 	.read_msr = native_read_msr_safe,
333b05f78f5SYinghai Lu 	.read_msr_amd = native_read_msr_amd_safe,
334b1df07bdSGlauber de Oliveira Costa 	.write_msr = native_write_msr_safe,
335b1df07bdSGlauber de Oliveira Costa 	.read_tsc = native_read_tsc,
336b1df07bdSGlauber de Oliveira Costa 	.read_pmc = native_read_pmc,
337e5aaac44SGlauber de Oliveira Costa 	.read_tscp = native_read_tscp,
338b1df07bdSGlauber de Oliveira Costa 	.load_tr_desc = native_load_tr_desc,
339b1df07bdSGlauber de Oliveira Costa 	.set_ldt = native_set_ldt,
340b1df07bdSGlauber de Oliveira Costa 	.load_gdt = native_load_gdt,
341b1df07bdSGlauber de Oliveira Costa 	.load_idt = native_load_idt,
342b1df07bdSGlauber de Oliveira Costa 	.store_gdt = native_store_gdt,
343b1df07bdSGlauber de Oliveira Costa 	.store_idt = native_store_idt,
344b1df07bdSGlauber de Oliveira Costa 	.store_tr = native_store_tr,
345b1df07bdSGlauber de Oliveira Costa 	.load_tls = native_load_tls,
3469f9d489aSJeremy Fitzhardinge #ifdef CONFIG_X86_64
3479f9d489aSJeremy Fitzhardinge 	.load_gs_index = native_load_gs_index,
3489f9d489aSJeremy Fitzhardinge #endif
349b1df07bdSGlauber de Oliveira Costa 	.write_ldt_entry = native_write_ldt_entry,
350b1df07bdSGlauber de Oliveira Costa 	.write_gdt_entry = native_write_gdt_entry,
351b1df07bdSGlauber de Oliveira Costa 	.write_idt_entry = native_write_idt_entry,
352b1df07bdSGlauber de Oliveira Costa 	.load_sp0 = native_load_sp0,
353b1df07bdSGlauber de Oliveira Costa 
354102d0a4bSJeremy Fitzhardinge #if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION)
355d75cd22fSJeremy Fitzhardinge 	.irq_enable_sysexit = native_irq_enable_sysexit,
356102d0a4bSJeremy Fitzhardinge #endif
3572be29982SJeremy Fitzhardinge #ifdef CONFIG_X86_64
358102d0a4bSJeremy Fitzhardinge #ifdef CONFIG_IA32_EMULATION
3592be29982SJeremy Fitzhardinge 	.usergs_sysret32 = native_usergs_sysret32,
360102d0a4bSJeremy Fitzhardinge #endif
3612be29982SJeremy Fitzhardinge 	.usergs_sysret64 = native_usergs_sysret64,
362d75cd22fSJeremy Fitzhardinge #endif
363b1df07bdSGlauber de Oliveira Costa 	.iret = native_iret,
364e801f864SGlauber de Oliveira Costa 	.swapgs = native_swapgs,
365b1df07bdSGlauber de Oliveira Costa 
366b1df07bdSGlauber de Oliveira Costa 	.set_iopl_mask = native_set_iopl_mask,
367b1df07bdSGlauber de Oliveira Costa 	.io_delay = native_io_delay,
368b1df07bdSGlauber de Oliveira Costa 
369b1df07bdSGlauber de Oliveira Costa 	.lazy_mode = {
370b1df07bdSGlauber de Oliveira Costa 		.enter = paravirt_nop,
371b1df07bdSGlauber de Oliveira Costa 		.leave = paravirt_nop,
372b1df07bdSGlauber de Oliveira Costa 	},
373b1df07bdSGlauber de Oliveira Costa };
374b1df07bdSGlauber de Oliveira Costa 
375b1df07bdSGlauber de Oliveira Costa struct pv_apic_ops pv_apic_ops = {
376b1df07bdSGlauber de Oliveira Costa #ifdef CONFIG_X86_LOCAL_APIC
377b1df07bdSGlauber de Oliveira Costa 	.apic_write = native_apic_write,
378b1df07bdSGlauber de Oliveira Costa 	.apic_read = native_apic_read,
379b1df07bdSGlauber de Oliveira Costa 	.setup_boot_clock = setup_boot_APIC_clock,
380b1df07bdSGlauber de Oliveira Costa 	.setup_secondary_clock = setup_secondary_APIC_clock,
381b1df07bdSGlauber de Oliveira Costa 	.startup_ipi_hook = paravirt_nop,
382b1df07bdSGlauber de Oliveira Costa #endif
383b1df07bdSGlauber de Oliveira Costa };
384b1df07bdSGlauber de Oliveira Costa 
385b1df07bdSGlauber de Oliveira Costa struct pv_mmu_ops pv_mmu_ops = {
386d8dd8eecSEduardo Habkost #ifndef CONFIG_X86_64
387b1df07bdSGlauber de Oliveira Costa 	.pagetable_setup_start = native_pagetable_setup_start,
388b1df07bdSGlauber de Oliveira Costa 	.pagetable_setup_done = native_pagetable_setup_done,
389a312b37bSEduardo Habkost #else
390a312b37bSEduardo Habkost 	.pagetable_setup_start = paravirt_nop,
391a312b37bSEduardo Habkost 	.pagetable_setup_done = paravirt_nop,
392d8dd8eecSEduardo Habkost #endif
393b1df07bdSGlauber de Oliveira Costa 
394b1df07bdSGlauber de Oliveira Costa 	.read_cr2 = native_read_cr2,
395b1df07bdSGlauber de Oliveira Costa 	.write_cr2 = native_write_cr2,
396b1df07bdSGlauber de Oliveira Costa 	.read_cr3 = native_read_cr3,
397b1df07bdSGlauber de Oliveira Costa 	.write_cr3 = native_write_cr3,
398b1df07bdSGlauber de Oliveira Costa 
399b1df07bdSGlauber de Oliveira Costa 	.flush_tlb_user = native_flush_tlb,
400b1df07bdSGlauber de Oliveira Costa 	.flush_tlb_kernel = native_flush_tlb_global,
401b1df07bdSGlauber de Oliveira Costa 	.flush_tlb_single = native_flush_tlb_single,
402b1df07bdSGlauber de Oliveira Costa 	.flush_tlb_others = native_flush_tlb_others,
403b1df07bdSGlauber de Oliveira Costa 
404eba0045fSJeremy Fitzhardinge 	.pgd_alloc = __paravirt_pgd_alloc,
405eba0045fSJeremy Fitzhardinge 	.pgd_free = paravirt_nop,
406eba0045fSJeremy Fitzhardinge 
4076944a9c8SJeremy Fitzhardinge 	.alloc_pte = paravirt_nop,
4086944a9c8SJeremy Fitzhardinge 	.alloc_pmd = paravirt_nop,
4096944a9c8SJeremy Fitzhardinge 	.alloc_pmd_clone = paravirt_nop,
4102761fa09SJeremy Fitzhardinge 	.alloc_pud = paravirt_nop,
4116944a9c8SJeremy Fitzhardinge 	.release_pte = paravirt_nop,
4126944a9c8SJeremy Fitzhardinge 	.release_pmd = paravirt_nop,
4132761fa09SJeremy Fitzhardinge 	.release_pud = paravirt_nop,
414b1df07bdSGlauber de Oliveira Costa 
415b1df07bdSGlauber de Oliveira Costa 	.set_pte = native_set_pte,
416b1df07bdSGlauber de Oliveira Costa 	.set_pte_at = native_set_pte_at,
417b1df07bdSGlauber de Oliveira Costa 	.set_pmd = native_set_pmd,
418b1df07bdSGlauber de Oliveira Costa 	.pte_update = paravirt_nop,
419b1df07bdSGlauber de Oliveira Costa 	.pte_update_defer = paravirt_nop,
420b1df07bdSGlauber de Oliveira Costa 
42108b882c6SJeremy Fitzhardinge 	.ptep_modify_prot_start = __ptep_modify_prot_start,
42208b882c6SJeremy Fitzhardinge 	.ptep_modify_prot_commit = __ptep_modify_prot_commit,
42308b882c6SJeremy Fitzhardinge 
424b1df07bdSGlauber de Oliveira Costa #ifdef CONFIG_HIGHPTE
425b1df07bdSGlauber de Oliveira Costa 	.kmap_atomic_pte = kmap_atomic,
426b1df07bdSGlauber de Oliveira Costa #endif
427b1df07bdSGlauber de Oliveira Costa 
428f95f2f7bSEduardo Habkost #if PAGETABLE_LEVELS >= 3
429b1df07bdSGlauber de Oliveira Costa #ifdef CONFIG_X86_PAE
430b1df07bdSGlauber de Oliveira Costa 	.set_pte_atomic = native_set_pte_atomic,
431b1df07bdSGlauber de Oliveira Costa 	.set_pte_present = native_set_pte_present,
432b1df07bdSGlauber de Oliveira Costa 	.pte_clear = native_pte_clear,
433b1df07bdSGlauber de Oliveira Costa 	.pmd_clear = native_pmd_clear,
434f95f2f7bSEduardo Habkost #endif
435f95f2f7bSEduardo Habkost 	.set_pud = native_set_pud,
436b1df07bdSGlauber de Oliveira Costa 	.pmd_val = native_pmd_val,
437b1df07bdSGlauber de Oliveira Costa 	.make_pmd = native_make_pmd,
438f95f2f7bSEduardo Habkost 
439f95f2f7bSEduardo Habkost #if PAGETABLE_LEVELS == 4
440f95f2f7bSEduardo Habkost 	.pud_val = native_pud_val,
441f95f2f7bSEduardo Habkost 	.make_pud = native_make_pud,
442f95f2f7bSEduardo Habkost 	.set_pgd = native_set_pgd,
443b1df07bdSGlauber de Oliveira Costa #endif
444f95f2f7bSEduardo Habkost #endif /* PAGETABLE_LEVELS >= 3 */
445b1df07bdSGlauber de Oliveira Costa 
446b1df07bdSGlauber de Oliveira Costa 	.pte_val = native_pte_val,
447c2e3277fSRusty Russell 	.pte_flags = native_pte_flags,
448b1df07bdSGlauber de Oliveira Costa 	.pgd_val = native_pgd_val,
449b1df07bdSGlauber de Oliveira Costa 
450b1df07bdSGlauber de Oliveira Costa 	.make_pte = native_make_pte,
451b1df07bdSGlauber de Oliveira Costa 	.make_pgd = native_make_pgd,
452b1df07bdSGlauber de Oliveira Costa 
453b1df07bdSGlauber de Oliveira Costa 	.dup_mmap = paravirt_nop,
454b1df07bdSGlauber de Oliveira Costa 	.exit_mmap = paravirt_nop,
455b1df07bdSGlauber de Oliveira Costa 	.activate_mm = paravirt_nop,
456b1df07bdSGlauber de Oliveira Costa 
457b1df07bdSGlauber de Oliveira Costa 	.lazy_mode = {
458b1df07bdSGlauber de Oliveira Costa 		.enter = paravirt_nop,
459b1df07bdSGlauber de Oliveira Costa 		.leave = paravirt_nop,
460b1df07bdSGlauber de Oliveira Costa 	},
461aeaaa59cSJeremy Fitzhardinge 
462aeaaa59cSJeremy Fitzhardinge 	.set_fixmap = native_set_fixmap,
463b1df07bdSGlauber de Oliveira Costa };
464b1df07bdSGlauber de Oliveira Costa 
46574d4affdSJeremy Fitzhardinge struct pv_lock_ops pv_lock_ops = {
4664bb689eeSIngo Molnar #ifdef CONFIG_SMP
46774d4affdSJeremy Fitzhardinge 	.spin_is_locked = __ticket_spin_is_locked,
46874d4affdSJeremy Fitzhardinge 	.spin_is_contended = __ticket_spin_is_contended,
46974d4affdSJeremy Fitzhardinge 
47074d4affdSJeremy Fitzhardinge 	.spin_lock = __ticket_spin_lock,
47174d4affdSJeremy Fitzhardinge 	.spin_trylock = __ticket_spin_trylock,
47274d4affdSJeremy Fitzhardinge 	.spin_unlock = __ticket_spin_unlock,
4734bb689eeSIngo Molnar #endif
47474d4affdSJeremy Fitzhardinge };
4759af98578SIngo Molnar EXPORT_SYMBOL_GPL(pv_lock_ops);
47674d4affdSJeremy Fitzhardinge 
477b1df07bdSGlauber de Oliveira Costa EXPORT_SYMBOL_GPL(pv_time_ops);
478b1df07bdSGlauber de Oliveira Costa EXPORT_SYMBOL    (pv_cpu_ops);
479b1df07bdSGlauber de Oliveira Costa EXPORT_SYMBOL    (pv_mmu_ops);
480b1df07bdSGlauber de Oliveira Costa EXPORT_SYMBOL_GPL(pv_apic_ops);
481b1df07bdSGlauber de Oliveira Costa EXPORT_SYMBOL_GPL(pv_info);
482b1df07bdSGlauber de Oliveira Costa EXPORT_SYMBOL    (pv_irq_ops);
483