xref: /openbmc/linux/arch/x86/kernel/paravirt.c (revision f95f2f7b)
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>
32b1df07bdSGlauber de Oliveira Costa #include <asm/time.h>
33b1df07bdSGlauber de Oliveira Costa #include <asm/irq.h>
34b1df07bdSGlauber de Oliveira Costa #include <asm/delay.h>
35b1df07bdSGlauber de Oliveira Costa #include <asm/fixmap.h>
36b1df07bdSGlauber de Oliveira Costa #include <asm/apic.h>
37b1df07bdSGlauber de Oliveira Costa #include <asm/tlbflush.h>
38b1df07bdSGlauber de Oliveira Costa #include <asm/timer.h>
39b1df07bdSGlauber de Oliveira Costa 
40b1df07bdSGlauber de Oliveira Costa /* nop stub */
41b1df07bdSGlauber de Oliveira Costa void _paravirt_nop(void)
42b1df07bdSGlauber de Oliveira Costa {
43b1df07bdSGlauber de Oliveira Costa }
44b1df07bdSGlauber de Oliveira Costa 
45b1df07bdSGlauber de Oliveira Costa static void __init default_banner(void)
46b1df07bdSGlauber de Oliveira Costa {
47b1df07bdSGlauber de Oliveira Costa 	printk(KERN_INFO "Booting paravirtualized kernel on %s\n",
48b1df07bdSGlauber de Oliveira Costa 	       pv_info.name);
49b1df07bdSGlauber de Oliveira Costa }
50b1df07bdSGlauber de Oliveira Costa 
51b1df07bdSGlauber de Oliveira Costa char *memory_setup(void)
52b1df07bdSGlauber de Oliveira Costa {
53b1df07bdSGlauber de Oliveira Costa 	return pv_init_ops.memory_setup();
54b1df07bdSGlauber de Oliveira Costa }
55b1df07bdSGlauber de Oliveira Costa 
56b1df07bdSGlauber de Oliveira Costa /* Simple instruction patching code. */
57b1df07bdSGlauber de Oliveira Costa #define DEF_NATIVE(ops, name, code)					\
58b1df07bdSGlauber de Oliveira Costa 	extern const char start_##ops##_##name[], end_##ops##_##name[];	\
59b1df07bdSGlauber de Oliveira Costa 	asm("start_" #ops "_" #name ": " code "; end_" #ops "_" #name ":")
60b1df07bdSGlauber de Oliveira Costa 
61b1df07bdSGlauber de Oliveira Costa /* Undefined instruction for dealing with missing ops pointers. */
62b1df07bdSGlauber de Oliveira Costa static const unsigned char ud2a[] = { 0x0f, 0x0b };
63b1df07bdSGlauber de Oliveira Costa 
64b1df07bdSGlauber de Oliveira Costa unsigned paravirt_patch_nop(void)
65b1df07bdSGlauber de Oliveira Costa {
66b1df07bdSGlauber de Oliveira Costa 	return 0;
67b1df07bdSGlauber de Oliveira Costa }
68b1df07bdSGlauber de Oliveira Costa 
69b1df07bdSGlauber de Oliveira Costa unsigned paravirt_patch_ignore(unsigned len)
70b1df07bdSGlauber de Oliveira Costa {
71b1df07bdSGlauber de Oliveira Costa 	return len;
72b1df07bdSGlauber de Oliveira Costa }
73b1df07bdSGlauber de Oliveira Costa 
74b1df07bdSGlauber de Oliveira Costa struct branch {
75b1df07bdSGlauber de Oliveira Costa 	unsigned char opcode;
76b1df07bdSGlauber de Oliveira Costa 	u32 delta;
77b1df07bdSGlauber de Oliveira Costa } __attribute__((packed));
78b1df07bdSGlauber de Oliveira Costa 
79b1df07bdSGlauber de Oliveira Costa unsigned paravirt_patch_call(void *insnbuf,
80b1df07bdSGlauber de Oliveira Costa 			     const void *target, u16 tgt_clobbers,
81b1df07bdSGlauber de Oliveira Costa 			     unsigned long addr, u16 site_clobbers,
82b1df07bdSGlauber de Oliveira Costa 			     unsigned len)
83b1df07bdSGlauber de Oliveira Costa {
84b1df07bdSGlauber de Oliveira Costa 	struct branch *b = insnbuf;
85b1df07bdSGlauber de Oliveira Costa 	unsigned long delta = (unsigned long)target - (addr+5);
86b1df07bdSGlauber de Oliveira Costa 
87b1df07bdSGlauber de Oliveira Costa 	if (tgt_clobbers & ~site_clobbers)
88b1df07bdSGlauber de Oliveira Costa 		return len;	/* target would clobber too much for this site */
89b1df07bdSGlauber de Oliveira Costa 	if (len < 5)
90b1df07bdSGlauber de Oliveira Costa 		return len;	/* call too long for patch site */
91b1df07bdSGlauber de Oliveira Costa 
92b1df07bdSGlauber de Oliveira Costa 	b->opcode = 0xe8; /* call */
93b1df07bdSGlauber de Oliveira Costa 	b->delta = delta;
94b1df07bdSGlauber de Oliveira Costa 	BUILD_BUG_ON(sizeof(*b) != 5);
95b1df07bdSGlauber de Oliveira Costa 
96b1df07bdSGlauber de Oliveira Costa 	return 5;
97b1df07bdSGlauber de Oliveira Costa }
98b1df07bdSGlauber de Oliveira Costa 
99b1df07bdSGlauber de Oliveira Costa unsigned paravirt_patch_jmp(void *insnbuf, const void *target,
100b1df07bdSGlauber de Oliveira Costa 			    unsigned long addr, unsigned len)
101b1df07bdSGlauber de Oliveira Costa {
102b1df07bdSGlauber de Oliveira Costa 	struct branch *b = insnbuf;
103b1df07bdSGlauber de Oliveira Costa 	unsigned long delta = (unsigned long)target - (addr+5);
104b1df07bdSGlauber de Oliveira Costa 
105b1df07bdSGlauber de Oliveira Costa 	if (len < 5)
106b1df07bdSGlauber de Oliveira Costa 		return len;	/* call too long for patch site */
107b1df07bdSGlauber de Oliveira Costa 
108b1df07bdSGlauber de Oliveira Costa 	b->opcode = 0xe9;	/* jmp */
109b1df07bdSGlauber de Oliveira Costa 	b->delta = delta;
110b1df07bdSGlauber de Oliveira Costa 
111b1df07bdSGlauber de Oliveira Costa 	return 5;
112b1df07bdSGlauber de Oliveira Costa }
113b1df07bdSGlauber de Oliveira Costa 
114b1df07bdSGlauber de Oliveira Costa /* Neat trick to map patch type back to the call within the
115b1df07bdSGlauber de Oliveira Costa  * corresponding structure. */
116b1df07bdSGlauber de Oliveira Costa static void *get_call_destination(u8 type)
117b1df07bdSGlauber de Oliveira Costa {
118b1df07bdSGlauber de Oliveira Costa 	struct paravirt_patch_template tmpl = {
119b1df07bdSGlauber de Oliveira Costa 		.pv_init_ops = pv_init_ops,
120b1df07bdSGlauber de Oliveira Costa 		.pv_time_ops = pv_time_ops,
121b1df07bdSGlauber de Oliveira Costa 		.pv_cpu_ops = pv_cpu_ops,
122b1df07bdSGlauber de Oliveira Costa 		.pv_irq_ops = pv_irq_ops,
123b1df07bdSGlauber de Oliveira Costa 		.pv_apic_ops = pv_apic_ops,
124b1df07bdSGlauber de Oliveira Costa 		.pv_mmu_ops = pv_mmu_ops,
125b1df07bdSGlauber de Oliveira Costa 	};
126b1df07bdSGlauber de Oliveira Costa 	return *((void **)&tmpl + type);
127b1df07bdSGlauber de Oliveira Costa }
128b1df07bdSGlauber de Oliveira Costa 
129b1df07bdSGlauber de Oliveira Costa unsigned paravirt_patch_default(u8 type, u16 clobbers, void *insnbuf,
130b1df07bdSGlauber de Oliveira Costa 				unsigned long addr, unsigned len)
131b1df07bdSGlauber de Oliveira Costa {
132b1df07bdSGlauber de Oliveira Costa 	void *opfunc = get_call_destination(type);
133b1df07bdSGlauber de Oliveira Costa 	unsigned ret;
134b1df07bdSGlauber de Oliveira Costa 
135b1df07bdSGlauber de Oliveira Costa 	if (opfunc == NULL)
136b1df07bdSGlauber de Oliveira Costa 		/* If there's no function, patch it with a ud2a (BUG) */
137b1df07bdSGlauber de Oliveira Costa 		ret = paravirt_patch_insns(insnbuf, len, ud2a, ud2a+sizeof(ud2a));
138b1df07bdSGlauber de Oliveira Costa 	else if (opfunc == paravirt_nop)
139b1df07bdSGlauber de Oliveira Costa 		/* If the operation is a nop, then nop the callsite */
140b1df07bdSGlauber de Oliveira Costa 		ret = paravirt_patch_nop();
141b1df07bdSGlauber de Oliveira Costa 	else if (type == PARAVIRT_PATCH(pv_cpu_ops.iret) ||
142b1df07bdSGlauber de Oliveira Costa 		 type == PARAVIRT_PATCH(pv_cpu_ops.irq_enable_syscall_ret))
143b1df07bdSGlauber de Oliveira Costa 		/* If operation requires a jmp, then jmp */
144b1df07bdSGlauber de Oliveira Costa 		ret = paravirt_patch_jmp(insnbuf, opfunc, addr, len);
145b1df07bdSGlauber de Oliveira Costa 	else
146b1df07bdSGlauber de Oliveira Costa 		/* Otherwise call the function; assume target could
147b1df07bdSGlauber de Oliveira Costa 		   clobber any caller-save reg */
148b1df07bdSGlauber de Oliveira Costa 		ret = paravirt_patch_call(insnbuf, opfunc, CLBR_ANY,
149b1df07bdSGlauber de Oliveira Costa 					  addr, clobbers, len);
150b1df07bdSGlauber de Oliveira Costa 
151b1df07bdSGlauber de Oliveira Costa 	return ret;
152b1df07bdSGlauber de Oliveira Costa }
153b1df07bdSGlauber de Oliveira Costa 
154b1df07bdSGlauber de Oliveira Costa unsigned paravirt_patch_insns(void *insnbuf, unsigned len,
155b1df07bdSGlauber de Oliveira Costa 			      const char *start, const char *end)
156b1df07bdSGlauber de Oliveira Costa {
157b1df07bdSGlauber de Oliveira Costa 	unsigned insn_len = end - start;
158b1df07bdSGlauber de Oliveira Costa 
159b1df07bdSGlauber de Oliveira Costa 	if (insn_len > len || start == NULL)
160b1df07bdSGlauber de Oliveira Costa 		insn_len = len;
161b1df07bdSGlauber de Oliveira Costa 	else
162b1df07bdSGlauber de Oliveira Costa 		memcpy(insnbuf, start, insn_len);
163b1df07bdSGlauber de Oliveira Costa 
164b1df07bdSGlauber de Oliveira Costa 	return insn_len;
165b1df07bdSGlauber de Oliveira Costa }
166b1df07bdSGlauber de Oliveira Costa 
167b1df07bdSGlauber de Oliveira Costa void init_IRQ(void)
168b1df07bdSGlauber de Oliveira Costa {
169b1df07bdSGlauber de Oliveira Costa 	pv_irq_ops.init_IRQ();
170b1df07bdSGlauber de Oliveira Costa }
171b1df07bdSGlauber de Oliveira Costa 
172b1df07bdSGlauber de Oliveira Costa static void native_flush_tlb(void)
173b1df07bdSGlauber de Oliveira Costa {
174b1df07bdSGlauber de Oliveira Costa 	__native_flush_tlb();
175b1df07bdSGlauber de Oliveira Costa }
176b1df07bdSGlauber de Oliveira Costa 
177b1df07bdSGlauber de Oliveira Costa /*
178b1df07bdSGlauber de Oliveira Costa  * Global pages have to be flushed a bit differently. Not a real
179b1df07bdSGlauber de Oliveira Costa  * performance problem because this does not happen often.
180b1df07bdSGlauber de Oliveira Costa  */
181b1df07bdSGlauber de Oliveira Costa static void native_flush_tlb_global(void)
182b1df07bdSGlauber de Oliveira Costa {
183b1df07bdSGlauber de Oliveira Costa 	__native_flush_tlb_global();
184b1df07bdSGlauber de Oliveira Costa }
185b1df07bdSGlauber de Oliveira Costa 
186b1df07bdSGlauber de Oliveira Costa static void native_flush_tlb_single(unsigned long addr)
187b1df07bdSGlauber de Oliveira Costa {
188b1df07bdSGlauber de Oliveira Costa 	__native_flush_tlb_single(addr);
189b1df07bdSGlauber de Oliveira Costa }
190b1df07bdSGlauber de Oliveira Costa 
191b1df07bdSGlauber de Oliveira Costa /* These are in entry.S */
192b1df07bdSGlauber de Oliveira Costa extern void native_iret(void);
193b1df07bdSGlauber de Oliveira Costa extern void native_irq_enable_syscall_ret(void);
194b1df07bdSGlauber de Oliveira Costa 
195b1df07bdSGlauber de Oliveira Costa static int __init print_banner(void)
196b1df07bdSGlauber de Oliveira Costa {
197b1df07bdSGlauber de Oliveira Costa 	pv_init_ops.banner();
198b1df07bdSGlauber de Oliveira Costa 	return 0;
199b1df07bdSGlauber de Oliveira Costa }
200b1df07bdSGlauber de Oliveira Costa core_initcall(print_banner);
201b1df07bdSGlauber de Oliveira Costa 
202b1df07bdSGlauber de Oliveira Costa static struct resource reserve_ioports = {
203b1df07bdSGlauber de Oliveira Costa 	.start = 0,
204b1df07bdSGlauber de Oliveira Costa 	.end = IO_SPACE_LIMIT,
205b1df07bdSGlauber de Oliveira Costa 	.name = "paravirt-ioport",
206b1df07bdSGlauber de Oliveira Costa 	.flags = IORESOURCE_IO | IORESOURCE_BUSY,
207b1df07bdSGlauber de Oliveira Costa };
208b1df07bdSGlauber de Oliveira Costa 
209b1df07bdSGlauber de Oliveira Costa static struct resource reserve_iomem = {
210b1df07bdSGlauber de Oliveira Costa 	.start = 0,
211b1df07bdSGlauber de Oliveira Costa 	.end = -1,
212b1df07bdSGlauber de Oliveira Costa 	.name = "paravirt-iomem",
213b1df07bdSGlauber de Oliveira Costa 	.flags = IORESOURCE_MEM | 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 {
225b1df07bdSGlauber de Oliveira Costa 	int ret;
226b1df07bdSGlauber de Oliveira Costa 
227b1df07bdSGlauber de Oliveira Costa 	ret = request_resource(&ioport_resource, &reserve_ioports);
228b1df07bdSGlauber de Oliveira Costa 	if (ret == 0) {
229b1df07bdSGlauber de Oliveira Costa 		ret = request_resource(&iomem_resource, &reserve_iomem);
230b1df07bdSGlauber de Oliveira Costa 		if (ret)
231b1df07bdSGlauber de Oliveira Costa 			release_resource(&reserve_ioports);
232b1df07bdSGlauber de Oliveira Costa 	}
233b1df07bdSGlauber de Oliveira Costa 
234b1df07bdSGlauber de Oliveira Costa 	return ret;
235b1df07bdSGlauber de Oliveira Costa }
236b1df07bdSGlauber de Oliveira Costa 
237b1df07bdSGlauber de Oliveira Costa static DEFINE_PER_CPU(enum paravirt_lazy_mode, paravirt_lazy_mode) = PARAVIRT_LAZY_NONE;
238b1df07bdSGlauber de Oliveira Costa 
239b1df07bdSGlauber de Oliveira Costa static inline void enter_lazy(enum paravirt_lazy_mode mode)
240b1df07bdSGlauber de Oliveira Costa {
241bfd074e0SGlauber de Oliveira Costa 	BUG_ON(__get_cpu_var(paravirt_lazy_mode) != PARAVIRT_LAZY_NONE);
242b1df07bdSGlauber de Oliveira Costa 	BUG_ON(preemptible());
243b1df07bdSGlauber de Oliveira Costa 
244bfd074e0SGlauber de Oliveira Costa 	__get_cpu_var(paravirt_lazy_mode) = mode;
245b1df07bdSGlauber de Oliveira Costa }
246b1df07bdSGlauber de Oliveira Costa 
247b1df07bdSGlauber de Oliveira Costa void paravirt_leave_lazy(enum paravirt_lazy_mode mode)
248b1df07bdSGlauber de Oliveira Costa {
249bfd074e0SGlauber de Oliveira Costa 	BUG_ON(__get_cpu_var(paravirt_lazy_mode) != mode);
250b1df07bdSGlauber de Oliveira Costa 	BUG_ON(preemptible());
251b1df07bdSGlauber de Oliveira Costa 
252bfd074e0SGlauber de Oliveira Costa 	__get_cpu_var(paravirt_lazy_mode) = PARAVIRT_LAZY_NONE;
253b1df07bdSGlauber de Oliveira Costa }
254b1df07bdSGlauber de Oliveira Costa 
255b1df07bdSGlauber de Oliveira Costa void paravirt_enter_lazy_mmu(void)
256b1df07bdSGlauber de Oliveira Costa {
257b1df07bdSGlauber de Oliveira Costa 	enter_lazy(PARAVIRT_LAZY_MMU);
258b1df07bdSGlauber de Oliveira Costa }
259b1df07bdSGlauber de Oliveira Costa 
260b1df07bdSGlauber de Oliveira Costa void paravirt_leave_lazy_mmu(void)
261b1df07bdSGlauber de Oliveira Costa {
262b1df07bdSGlauber de Oliveira Costa 	paravirt_leave_lazy(PARAVIRT_LAZY_MMU);
263b1df07bdSGlauber de Oliveira Costa }
264b1df07bdSGlauber de Oliveira Costa 
265b1df07bdSGlauber de Oliveira Costa void paravirt_enter_lazy_cpu(void)
266b1df07bdSGlauber de Oliveira Costa {
267b1df07bdSGlauber de Oliveira Costa 	enter_lazy(PARAVIRT_LAZY_CPU);
268b1df07bdSGlauber de Oliveira Costa }
269b1df07bdSGlauber de Oliveira Costa 
270b1df07bdSGlauber de Oliveira Costa void paravirt_leave_lazy_cpu(void)
271b1df07bdSGlauber de Oliveira Costa {
272b1df07bdSGlauber de Oliveira Costa 	paravirt_leave_lazy(PARAVIRT_LAZY_CPU);
273b1df07bdSGlauber de Oliveira Costa }
274b1df07bdSGlauber de Oliveira Costa 
275b1df07bdSGlauber de Oliveira Costa enum paravirt_lazy_mode paravirt_get_lazy_mode(void)
276b1df07bdSGlauber de Oliveira Costa {
277bfd074e0SGlauber de Oliveira Costa 	return __get_cpu_var(paravirt_lazy_mode);
278b1df07bdSGlauber de Oliveira Costa }
279b1df07bdSGlauber de Oliveira Costa 
280b1df07bdSGlauber de Oliveira Costa struct pv_info pv_info = {
281b1df07bdSGlauber de Oliveira Costa 	.name = "bare hardware",
282b1df07bdSGlauber de Oliveira Costa 	.paravirt_enabled = 0,
283b1df07bdSGlauber de Oliveira Costa 	.kernel_rpl = 0,
284b1df07bdSGlauber de Oliveira Costa 	.shared_kernel_pmd = 1,	/* Only used when CONFIG_X86_PAE is set */
285b1df07bdSGlauber de Oliveira Costa };
286b1df07bdSGlauber de Oliveira Costa 
287b1df07bdSGlauber de Oliveira Costa struct pv_init_ops pv_init_ops = {
288b1df07bdSGlauber de Oliveira Costa 	.patch = native_patch,
289b1df07bdSGlauber de Oliveira Costa 	.banner = default_banner,
290b1df07bdSGlauber de Oliveira Costa 	.arch_setup = paravirt_nop,
291b1df07bdSGlauber de Oliveira Costa 	.memory_setup = machine_specific_memory_setup,
292b1df07bdSGlauber de Oliveira Costa };
293b1df07bdSGlauber de Oliveira Costa 
294b1df07bdSGlauber de Oliveira Costa struct pv_time_ops pv_time_ops = {
295b1df07bdSGlauber de Oliveira Costa 	.time_init = hpet_time_init,
296b1df07bdSGlauber de Oliveira Costa 	.get_wallclock = native_get_wallclock,
297b1df07bdSGlauber de Oliveira Costa 	.set_wallclock = native_set_wallclock,
298b1df07bdSGlauber de Oliveira Costa 	.sched_clock = native_sched_clock,
299b1df07bdSGlauber de Oliveira Costa 	.get_cpu_khz = native_calculate_cpu_khz,
300b1df07bdSGlauber de Oliveira Costa };
301b1df07bdSGlauber de Oliveira Costa 
302b1df07bdSGlauber de Oliveira Costa struct pv_irq_ops pv_irq_ops = {
303b1df07bdSGlauber de Oliveira Costa 	.init_IRQ = native_init_IRQ,
304b1df07bdSGlauber de Oliveira Costa 	.save_fl = native_save_fl,
305b1df07bdSGlauber de Oliveira Costa 	.restore_fl = native_restore_fl,
306b1df07bdSGlauber de Oliveira Costa 	.irq_disable = native_irq_disable,
307b1df07bdSGlauber de Oliveira Costa 	.irq_enable = native_irq_enable,
308b1df07bdSGlauber de Oliveira Costa 	.safe_halt = native_safe_halt,
309b1df07bdSGlauber de Oliveira Costa 	.halt = native_halt,
310b1df07bdSGlauber de Oliveira Costa };
311b1df07bdSGlauber de Oliveira Costa 
312b1df07bdSGlauber de Oliveira Costa struct pv_cpu_ops pv_cpu_ops = {
313b1df07bdSGlauber de Oliveira Costa 	.cpuid = native_cpuid,
314b1df07bdSGlauber de Oliveira Costa 	.get_debugreg = native_get_debugreg,
315b1df07bdSGlauber de Oliveira Costa 	.set_debugreg = native_set_debugreg,
316b1df07bdSGlauber de Oliveira Costa 	.clts = native_clts,
317b1df07bdSGlauber de Oliveira Costa 	.read_cr0 = native_read_cr0,
318b1df07bdSGlauber de Oliveira Costa 	.write_cr0 = native_write_cr0,
319b1df07bdSGlauber de Oliveira Costa 	.read_cr4 = native_read_cr4,
320b1df07bdSGlauber de Oliveira Costa 	.read_cr4_safe = native_read_cr4_safe,
321b1df07bdSGlauber de Oliveira Costa 	.write_cr4 = native_write_cr4,
32288b4755fSGlauber de Oliveira Costa #ifdef CONFIG_X86_64
32388b4755fSGlauber de Oliveira Costa 	.read_cr8 = native_read_cr8,
32488b4755fSGlauber de Oliveira Costa 	.write_cr8 = native_write_cr8,
32588b4755fSGlauber de Oliveira Costa #endif
326b1df07bdSGlauber de Oliveira Costa 	.wbinvd = native_wbinvd,
327b1df07bdSGlauber de Oliveira Costa 	.read_msr = native_read_msr_safe,
328b1df07bdSGlauber de Oliveira Costa 	.write_msr = native_write_msr_safe,
329b1df07bdSGlauber de Oliveira Costa 	.read_tsc = native_read_tsc,
330b1df07bdSGlauber de Oliveira Costa 	.read_pmc = native_read_pmc,
331e5aaac44SGlauber de Oliveira Costa 	.read_tscp = native_read_tscp,
332b1df07bdSGlauber de Oliveira Costa 	.load_tr_desc = native_load_tr_desc,
333b1df07bdSGlauber de Oliveira Costa 	.set_ldt = native_set_ldt,
334b1df07bdSGlauber de Oliveira Costa 	.load_gdt = native_load_gdt,
335b1df07bdSGlauber de Oliveira Costa 	.load_idt = native_load_idt,
336b1df07bdSGlauber de Oliveira Costa 	.store_gdt = native_store_gdt,
337b1df07bdSGlauber de Oliveira Costa 	.store_idt = native_store_idt,
338b1df07bdSGlauber de Oliveira Costa 	.store_tr = native_store_tr,
339b1df07bdSGlauber de Oliveira Costa 	.load_tls = native_load_tls,
340b1df07bdSGlauber de Oliveira Costa 	.write_ldt_entry = native_write_ldt_entry,
341b1df07bdSGlauber de Oliveira Costa 	.write_gdt_entry = native_write_gdt_entry,
342b1df07bdSGlauber de Oliveira Costa 	.write_idt_entry = native_write_idt_entry,
343b1df07bdSGlauber de Oliveira Costa 	.load_sp0 = native_load_sp0,
344b1df07bdSGlauber de Oliveira Costa 
345b1df07bdSGlauber de Oliveira Costa 	.irq_enable_syscall_ret = native_irq_enable_syscall_ret,
346b1df07bdSGlauber de Oliveira Costa 	.iret = native_iret,
347e801f864SGlauber de Oliveira Costa 	.swapgs = native_swapgs,
348b1df07bdSGlauber de Oliveira Costa 
349b1df07bdSGlauber de Oliveira Costa 	.set_iopl_mask = native_set_iopl_mask,
350b1df07bdSGlauber de Oliveira Costa 	.io_delay = native_io_delay,
351b1df07bdSGlauber de Oliveira Costa 
352b1df07bdSGlauber de Oliveira Costa 	.lazy_mode = {
353b1df07bdSGlauber de Oliveira Costa 		.enter = paravirt_nop,
354b1df07bdSGlauber de Oliveira Costa 		.leave = paravirt_nop,
355b1df07bdSGlauber de Oliveira Costa 	},
356b1df07bdSGlauber de Oliveira Costa };
357b1df07bdSGlauber de Oliveira Costa 
358b1df07bdSGlauber de Oliveira Costa struct pv_apic_ops pv_apic_ops = {
359b1df07bdSGlauber de Oliveira Costa #ifdef CONFIG_X86_LOCAL_APIC
360b1df07bdSGlauber de Oliveira Costa 	.apic_write = native_apic_write,
361b1df07bdSGlauber de Oliveira Costa 	.apic_write_atomic = native_apic_write_atomic,
362b1df07bdSGlauber de Oliveira Costa 	.apic_read = native_apic_read,
363b1df07bdSGlauber de Oliveira Costa 	.setup_boot_clock = setup_boot_APIC_clock,
364b1df07bdSGlauber de Oliveira Costa 	.setup_secondary_clock = setup_secondary_APIC_clock,
365b1df07bdSGlauber de Oliveira Costa 	.startup_ipi_hook = paravirt_nop,
366b1df07bdSGlauber de Oliveira Costa #endif
367b1df07bdSGlauber de Oliveira Costa };
368b1df07bdSGlauber de Oliveira Costa 
369b1df07bdSGlauber de Oliveira Costa struct pv_mmu_ops pv_mmu_ops = {
370d8dd8eecSEduardo Habkost #ifndef CONFIG_X86_64
371b1df07bdSGlauber de Oliveira Costa 	.pagetable_setup_start = native_pagetable_setup_start,
372b1df07bdSGlauber de Oliveira Costa 	.pagetable_setup_done = native_pagetable_setup_done,
373d8dd8eecSEduardo Habkost #endif
374b1df07bdSGlauber de Oliveira Costa 
375b1df07bdSGlauber de Oliveira Costa 	.read_cr2 = native_read_cr2,
376b1df07bdSGlauber de Oliveira Costa 	.write_cr2 = native_write_cr2,
377b1df07bdSGlauber de Oliveira Costa 	.read_cr3 = native_read_cr3,
378b1df07bdSGlauber de Oliveira Costa 	.write_cr3 = native_write_cr3,
379b1df07bdSGlauber de Oliveira Costa 
380b1df07bdSGlauber de Oliveira Costa 	.flush_tlb_user = native_flush_tlb,
381b1df07bdSGlauber de Oliveira Costa 	.flush_tlb_kernel = native_flush_tlb_global,
382b1df07bdSGlauber de Oliveira Costa 	.flush_tlb_single = native_flush_tlb_single,
383b1df07bdSGlauber de Oliveira Costa 	.flush_tlb_others = native_flush_tlb_others,
384b1df07bdSGlauber de Oliveira Costa 
385b1df07bdSGlauber de Oliveira Costa 	.alloc_pt = paravirt_nop,
386b1df07bdSGlauber de Oliveira Costa 	.alloc_pd = paravirt_nop,
387b1df07bdSGlauber de Oliveira Costa 	.alloc_pd_clone = paravirt_nop,
388b1df07bdSGlauber de Oliveira Costa 	.release_pt = paravirt_nop,
389b1df07bdSGlauber de Oliveira Costa 	.release_pd = paravirt_nop,
390b1df07bdSGlauber de Oliveira Costa 
391b1df07bdSGlauber de Oliveira Costa 	.set_pte = native_set_pte,
392b1df07bdSGlauber de Oliveira Costa 	.set_pte_at = native_set_pte_at,
393b1df07bdSGlauber de Oliveira Costa 	.set_pmd = native_set_pmd,
394b1df07bdSGlauber de Oliveira Costa 	.pte_update = paravirt_nop,
395b1df07bdSGlauber de Oliveira Costa 	.pte_update_defer = paravirt_nop,
396b1df07bdSGlauber de Oliveira Costa 
397b1df07bdSGlauber de Oliveira Costa #ifdef CONFIG_HIGHPTE
398b1df07bdSGlauber de Oliveira Costa 	.kmap_atomic_pte = kmap_atomic,
399b1df07bdSGlauber de Oliveira Costa #endif
400b1df07bdSGlauber de Oliveira Costa 
401f95f2f7bSEduardo Habkost #if PAGETABLE_LEVELS >= 3
402b1df07bdSGlauber de Oliveira Costa #ifdef CONFIG_X86_PAE
403b1df07bdSGlauber de Oliveira Costa 	.set_pte_atomic = native_set_pte_atomic,
404b1df07bdSGlauber de Oliveira Costa 	.set_pte_present = native_set_pte_present,
405b1df07bdSGlauber de Oliveira Costa 	.pte_clear = native_pte_clear,
406b1df07bdSGlauber de Oliveira Costa 	.pmd_clear = native_pmd_clear,
407f95f2f7bSEduardo Habkost #endif
408f95f2f7bSEduardo Habkost 	.set_pud = native_set_pud,
409b1df07bdSGlauber de Oliveira Costa 	.pmd_val = native_pmd_val,
410b1df07bdSGlauber de Oliveira Costa 	.make_pmd = native_make_pmd,
411f95f2f7bSEduardo Habkost 
412f95f2f7bSEduardo Habkost #if PAGETABLE_LEVELS == 4
413f95f2f7bSEduardo Habkost 	.pud_val = native_pud_val,
414f95f2f7bSEduardo Habkost 	.make_pud = native_make_pud,
415f95f2f7bSEduardo Habkost 	.set_pgd = native_set_pgd,
416b1df07bdSGlauber de Oliveira Costa #endif
417f95f2f7bSEduardo Habkost #endif /* PAGETABLE_LEVELS >= 3 */
418b1df07bdSGlauber de Oliveira Costa 
419b1df07bdSGlauber de Oliveira Costa 	.pte_val = native_pte_val,
420b1df07bdSGlauber de Oliveira Costa 	.pgd_val = native_pgd_val,
421b1df07bdSGlauber de Oliveira Costa 
422b1df07bdSGlauber de Oliveira Costa 	.make_pte = native_make_pte,
423b1df07bdSGlauber de Oliveira Costa 	.make_pgd = native_make_pgd,
424b1df07bdSGlauber de Oliveira Costa 
425b1df07bdSGlauber de Oliveira Costa 	.dup_mmap = paravirt_nop,
426b1df07bdSGlauber de Oliveira Costa 	.exit_mmap = paravirt_nop,
427b1df07bdSGlauber de Oliveira Costa 	.activate_mm = paravirt_nop,
428b1df07bdSGlauber de Oliveira Costa 
429b1df07bdSGlauber de Oliveira Costa 	.lazy_mode = {
430b1df07bdSGlauber de Oliveira Costa 		.enter = paravirt_nop,
431b1df07bdSGlauber de Oliveira Costa 		.leave = paravirt_nop,
432b1df07bdSGlauber de Oliveira Costa 	},
433b1df07bdSGlauber de Oliveira Costa };
434b1df07bdSGlauber de Oliveira Costa 
435b1df07bdSGlauber de Oliveira Costa EXPORT_SYMBOL_GPL(pv_time_ops);
436b1df07bdSGlauber de Oliveira Costa EXPORT_SYMBOL    (pv_cpu_ops);
437b1df07bdSGlauber de Oliveira Costa EXPORT_SYMBOL    (pv_mmu_ops);
438b1df07bdSGlauber de Oliveira Costa EXPORT_SYMBOL_GPL(pv_apic_ops);
439b1df07bdSGlauber de Oliveira Costa EXPORT_SYMBOL_GPL(pv_info);
440b1df07bdSGlauber de Oliveira Costa EXPORT_SYMBOL    (pv_irq_ops);
441