xref: /openbmc/linux/arch/x86/kernel/paravirt.c (revision 5c83511b)
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>
22186f4360SPaul Gortmaker #include <linux/init.h>
23186f4360SPaul Gortmaker #include <linux/export.h>
24b1df07bdSGlauber de Oliveira Costa #include <linux/efi.h>
25b1df07bdSGlauber de Oliveira Costa #include <linux/bcd.h>
26b1df07bdSGlauber de Oliveira Costa #include <linux/highmem.h>
27376e2424SMasami Hiramatsu #include <linux/kprobes.h>
28b1df07bdSGlauber de Oliveira Costa 
29b1df07bdSGlauber de Oliveira Costa #include <asm/bug.h>
30b1df07bdSGlauber de Oliveira Costa #include <asm/paravirt.h>
3150af5eadSPaul Gortmaker #include <asm/debugreg.h>
32b1df07bdSGlauber de Oliveira Costa #include <asm/desc.h>
33b1df07bdSGlauber de Oliveira Costa #include <asm/setup.h>
34a312b37bSEduardo Habkost #include <asm/pgtable.h>
35b1df07bdSGlauber de Oliveira Costa #include <asm/time.h>
36eba0045fSJeremy Fitzhardinge #include <asm/pgalloc.h>
37b1df07bdSGlauber de Oliveira Costa #include <asm/irq.h>
38b1df07bdSGlauber de Oliveira Costa #include <asm/delay.h>
39b1df07bdSGlauber de Oliveira Costa #include <asm/fixmap.h>
40b1df07bdSGlauber de Oliveira Costa #include <asm/apic.h>
41b1df07bdSGlauber de Oliveira Costa #include <asm/tlbflush.h>
42b1df07bdSGlauber de Oliveira Costa #include <asm/timer.h>
43f05e798aSDavid Howells #include <asm/special_insns.h>
4448a8b97cSPeter Zijlstra #include <asm/tlb.h>
45b1df07bdSGlauber de Oliveira Costa 
46fc57a7c6SAndy Lutomirski /*
47fc57a7c6SAndy Lutomirski  * nop stub, which must not clobber anything *including the stack* to
48fc57a7c6SAndy Lutomirski  * avoid confusing the entry prologues.
49fc57a7c6SAndy Lutomirski  */
50fc57a7c6SAndy Lutomirski extern void _paravirt_nop(void);
51fc57a7c6SAndy Lutomirski asm (".pushsection .entry.text, \"ax\"\n"
52fc57a7c6SAndy Lutomirski      ".global _paravirt_nop\n"
53fc57a7c6SAndy Lutomirski      "_paravirt_nop:\n\t"
54fc57a7c6SAndy Lutomirski      "ret\n\t"
55fc57a7c6SAndy Lutomirski      ".size _paravirt_nop, . - _paravirt_nop\n\t"
56fc57a7c6SAndy Lutomirski      ".type _paravirt_nop, @function\n\t"
57fc57a7c6SAndy Lutomirski      ".popsection");
58b1df07bdSGlauber de Oliveira Costa 
5941edafdbSJeremy Fitzhardinge /* identity function, which can be inlined */
6015301a57SSteven Rostedt u32 notrace _paravirt_ident_32(u32 x)
6141edafdbSJeremy Fitzhardinge {
6241edafdbSJeremy Fitzhardinge 	return x;
6341edafdbSJeremy Fitzhardinge }
6441edafdbSJeremy Fitzhardinge 
6515301a57SSteven Rostedt u64 notrace _paravirt_ident_64(u64 x)
6641edafdbSJeremy Fitzhardinge {
6741edafdbSJeremy Fitzhardinge 	return x;
6841edafdbSJeremy Fitzhardinge }
6941edafdbSJeremy Fitzhardinge 
706f30c1acSThomas Gleixner void __init default_banner(void)
71b1df07bdSGlauber de Oliveira Costa {
72b1df07bdSGlauber de Oliveira Costa 	printk(KERN_INFO "Booting paravirtualized kernel on %s\n",
73b1df07bdSGlauber de Oliveira Costa 	       pv_info.name);
74b1df07bdSGlauber de Oliveira Costa }
75b1df07bdSGlauber de Oliveira Costa 
76b1df07bdSGlauber de Oliveira Costa /* Undefined instruction for dealing with missing ops pointers. */
77b1df07bdSGlauber de Oliveira Costa static const unsigned char ud2a[] = { 0x0f, 0x0b };
78b1df07bdSGlauber de Oliveira Costa 
79b1df07bdSGlauber de Oliveira Costa struct branch {
80b1df07bdSGlauber de Oliveira Costa 	unsigned char opcode;
81b1df07bdSGlauber de Oliveira Costa 	u32 delta;
82b1df07bdSGlauber de Oliveira Costa } __attribute__((packed));
83b1df07bdSGlauber de Oliveira Costa 
84abc745f8SJuergen Gross static unsigned paravirt_patch_call(void *insnbuf, const void *target,
85abc745f8SJuergen Gross 				    unsigned long addr, unsigned len)
86b1df07bdSGlauber de Oliveira Costa {
87b1df07bdSGlauber de Oliveira Costa 	struct branch *b = insnbuf;
88b1df07bdSGlauber de Oliveira Costa 	unsigned long delta = (unsigned long)target - (addr+5);
89b1df07bdSGlauber de Oliveira Costa 
905800dc5cSPeter Zijlstra 	if (len < 5) {
915800dc5cSPeter Zijlstra #ifdef CONFIG_RETPOLINE
925800dc5cSPeter Zijlstra 		WARN_ONCE("Failing to patch indirect CALL in %ps\n", (void *)addr);
935800dc5cSPeter Zijlstra #endif
94b1df07bdSGlauber de Oliveira Costa 		return len;	/* call too long for patch site */
955800dc5cSPeter Zijlstra 	}
96b1df07bdSGlauber de Oliveira Costa 
97b1df07bdSGlauber de Oliveira Costa 	b->opcode = 0xe8; /* call */
98b1df07bdSGlauber de Oliveira Costa 	b->delta = delta;
99b1df07bdSGlauber de Oliveira Costa 	BUILD_BUG_ON(sizeof(*b) != 5);
100b1df07bdSGlauber de Oliveira Costa 
101b1df07bdSGlauber de Oliveira Costa 	return 5;
102b1df07bdSGlauber de Oliveira Costa }
103b1df07bdSGlauber de Oliveira Costa 
1047e437202SJuergen Gross static unsigned paravirt_patch_jmp(void *insnbuf, const void *target,
105b1df07bdSGlauber de Oliveira Costa 				   unsigned long addr, unsigned len)
106b1df07bdSGlauber de Oliveira Costa {
107b1df07bdSGlauber de Oliveira Costa 	struct branch *b = insnbuf;
108b1df07bdSGlauber de Oliveira Costa 	unsigned long delta = (unsigned long)target - (addr+5);
109b1df07bdSGlauber de Oliveira Costa 
1105800dc5cSPeter Zijlstra 	if (len < 5) {
1115800dc5cSPeter Zijlstra #ifdef CONFIG_RETPOLINE
1125800dc5cSPeter Zijlstra 		WARN_ONCE("Failing to patch indirect JMP in %ps\n", (void *)addr);
1135800dc5cSPeter Zijlstra #endif
114b1df07bdSGlauber de Oliveira Costa 		return len;	/* call too long for patch site */
1155800dc5cSPeter Zijlstra 	}
116b1df07bdSGlauber de Oliveira Costa 
117b1df07bdSGlauber de Oliveira Costa 	b->opcode = 0xe9;	/* jmp */
118b1df07bdSGlauber de Oliveira Costa 	b->delta = delta;
119b1df07bdSGlauber de Oliveira Costa 
120b1df07bdSGlauber de Oliveira Costa 	return 5;
121b1df07bdSGlauber de Oliveira Costa }
122b1df07bdSGlauber de Oliveira Costa 
1239043442bSJuergen Gross DEFINE_STATIC_KEY_TRUE(virt_spin_lock_key);
1249043442bSJuergen Gross 
1259043442bSJuergen Gross void __init native_pv_lock_init(void)
1269043442bSJuergen Gross {
1279043442bSJuergen Gross 	if (!static_cpu_has(X86_FEATURE_HYPERVISOR))
1289043442bSJuergen Gross 		static_branch_disable(&virt_spin_lock_key);
1299043442bSJuergen Gross }
1309043442bSJuergen Gross 
1315c83511bSJuergen Gross unsigned paravirt_patch_default(u8 type, void *insnbuf,
1325c83511bSJuergen Gross 				unsigned long addr, unsigned len)
1335c83511bSJuergen Gross {
1349043442bSJuergen Gross 	/*
1359043442bSJuergen Gross 	 * Neat trick to map patch type back to the call within the
1369043442bSJuergen Gross 	 * corresponding structure.
1379043442bSJuergen Gross 	 */
1385c83511bSJuergen Gross 	void *opfunc = *((void **)&pv_ops + type);
139b1df07bdSGlauber de Oliveira Costa 	unsigned ret;
140b1df07bdSGlauber de Oliveira Costa 
141b1df07bdSGlauber de Oliveira Costa 	if (opfunc == NULL)
142b1df07bdSGlauber de Oliveira Costa 		/* If there's no function, patch it with a ud2a (BUG) */
143b1df07bdSGlauber de Oliveira Costa 		ret = paravirt_patch_insns(insnbuf, len, ud2a, ud2a+sizeof(ud2a));
14441edafdbSJeremy Fitzhardinge 	else if (opfunc == _paravirt_nop)
14579f1d836SBorislav Petkov 		ret = 0;
14641edafdbSJeremy Fitzhardinge 
14741edafdbSJeremy Fitzhardinge 	/* identity functions just return their single argument */
14841edafdbSJeremy Fitzhardinge 	else if (opfunc == _paravirt_ident_32)
14941edafdbSJeremy Fitzhardinge 		ret = paravirt_patch_ident_32(insnbuf, len);
15041edafdbSJeremy Fitzhardinge 	else if (opfunc == _paravirt_ident_64)
15141edafdbSJeremy Fitzhardinge 		ret = paravirt_patch_ident_64(insnbuf, len);
15241edafdbSJeremy Fitzhardinge 
1535c83511bSJuergen Gross 	else if (type == PARAVIRT_PATCH(cpu.iret) ||
1545c83511bSJuergen Gross 		 type == PARAVIRT_PATCH(cpu.usergs_sysret64))
155b1df07bdSGlauber de Oliveira Costa 		/* If operation requires a jmp, then jmp */
156b1df07bdSGlauber de Oliveira Costa 		ret = paravirt_patch_jmp(insnbuf, opfunc, addr, len);
157b1df07bdSGlauber de Oliveira Costa 	else
158abc745f8SJuergen Gross 		/* Otherwise call the function. */
159abc745f8SJuergen Gross 		ret = paravirt_patch_call(insnbuf, opfunc, addr, len);
160b1df07bdSGlauber de Oliveira Costa 
161b1df07bdSGlauber de Oliveira Costa 	return ret;
162b1df07bdSGlauber de Oliveira Costa }
163b1df07bdSGlauber de Oliveira Costa 
164b1df07bdSGlauber de Oliveira Costa unsigned paravirt_patch_insns(void *insnbuf, unsigned len,
165b1df07bdSGlauber de Oliveira Costa 			      const char *start, const char *end)
166b1df07bdSGlauber de Oliveira Costa {
167b1df07bdSGlauber de Oliveira Costa 	unsigned insn_len = end - start;
168b1df07bdSGlauber de Oliveira Costa 
169b1df07bdSGlauber de Oliveira Costa 	if (insn_len > len || start == NULL)
170b1df07bdSGlauber de Oliveira Costa 		insn_len = len;
171b1df07bdSGlauber de Oliveira Costa 	else
172b1df07bdSGlauber de Oliveira Costa 		memcpy(insnbuf, start, insn_len);
173b1df07bdSGlauber de Oliveira Costa 
174b1df07bdSGlauber de Oliveira Costa 	return insn_len;
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 
1911299ef1dSAndy Lutomirski static void native_flush_tlb_one_user(unsigned long addr)
192b1df07bdSGlauber de Oliveira Costa {
1931299ef1dSAndy Lutomirski 	__native_flush_tlb_one_user(addr);
194b1df07bdSGlauber de Oliveira Costa }
195b1df07bdSGlauber de Oliveira Costa 
196c5905afbSIngo Molnar struct static_key paravirt_steal_enabled;
197c5905afbSIngo Molnar struct static_key paravirt_steal_rq_enabled;
1983c404b57SGlauber Costa 
1993c404b57SGlauber Costa static u64 native_steal_clock(int cpu)
2003c404b57SGlauber Costa {
2013c404b57SGlauber Costa 	return 0;
2023c404b57SGlauber Costa }
2033c404b57SGlauber Costa 
204b1df07bdSGlauber de Oliveira Costa /* These are in entry.S */
205b1df07bdSGlauber de Oliveira Costa extern void native_iret(void);
2062be29982SJeremy Fitzhardinge extern void native_usergs_sysret64(void);
207b1df07bdSGlauber de Oliveira Costa 
208b1df07bdSGlauber de Oliveira Costa static struct resource reserve_ioports = {
209b1df07bdSGlauber de Oliveira Costa 	.start = 0,
210b1df07bdSGlauber de Oliveira Costa 	.end = IO_SPACE_LIMIT,
211b1df07bdSGlauber de Oliveira Costa 	.name = "paravirt-ioport",
212b1df07bdSGlauber de Oliveira Costa 	.flags = IORESOURCE_IO | IORESOURCE_BUSY,
213b1df07bdSGlauber de Oliveira Costa };
214b1df07bdSGlauber de Oliveira Costa 
215b1df07bdSGlauber de Oliveira Costa /*
216b1df07bdSGlauber de Oliveira Costa  * Reserve the whole legacy IO space to prevent any legacy drivers
217b1df07bdSGlauber de Oliveira Costa  * from wasting time probing for their hardware.  This is a fairly
218b1df07bdSGlauber de Oliveira Costa  * brute-force approach to disabling all non-virtual drivers.
219b1df07bdSGlauber de Oliveira Costa  *
220b1df07bdSGlauber de Oliveira Costa  * Note that this must be called very early to have any effect.
221b1df07bdSGlauber de Oliveira Costa  */
222b1df07bdSGlauber de Oliveira Costa int paravirt_disable_iospace(void)
223b1df07bdSGlauber de Oliveira Costa {
224f7743fe6SJeremy Fitzhardinge 	return request_resource(&ioport_resource, &reserve_ioports);
225b1df07bdSGlauber de Oliveira Costa }
226b1df07bdSGlauber de Oliveira Costa 
227b1df07bdSGlauber de Oliveira Costa static DEFINE_PER_CPU(enum paravirt_lazy_mode, paravirt_lazy_mode) = PARAVIRT_LAZY_NONE;
228b1df07bdSGlauber de Oliveira Costa 
229b1df07bdSGlauber de Oliveira Costa static inline void enter_lazy(enum paravirt_lazy_mode mode)
230b1df07bdSGlauber de Oliveira Costa {
231c6ae41e7SAlex Shi 	BUG_ON(this_cpu_read(paravirt_lazy_mode) != PARAVIRT_LAZY_NONE);
232b1df07bdSGlauber de Oliveira Costa 
233c6ae41e7SAlex Shi 	this_cpu_write(paravirt_lazy_mode, mode);
234b1df07bdSGlauber de Oliveira Costa }
235b1df07bdSGlauber de Oliveira Costa 
236b407fc57SJeremy Fitzhardinge static void leave_lazy(enum paravirt_lazy_mode mode)
237b1df07bdSGlauber de Oliveira Costa {
238c6ae41e7SAlex Shi 	BUG_ON(this_cpu_read(paravirt_lazy_mode) != mode);
239b1df07bdSGlauber de Oliveira Costa 
240c6ae41e7SAlex Shi 	this_cpu_write(paravirt_lazy_mode, PARAVIRT_LAZY_NONE);
241b1df07bdSGlauber de Oliveira Costa }
242b1df07bdSGlauber de Oliveira Costa 
243b1df07bdSGlauber de Oliveira Costa void paravirt_enter_lazy_mmu(void)
244b1df07bdSGlauber de Oliveira Costa {
245b1df07bdSGlauber de Oliveira Costa 	enter_lazy(PARAVIRT_LAZY_MMU);
246b1df07bdSGlauber de Oliveira Costa }
247b1df07bdSGlauber de Oliveira Costa 
248b1df07bdSGlauber de Oliveira Costa void paravirt_leave_lazy_mmu(void)
249b1df07bdSGlauber de Oliveira Costa {
250b407fc57SJeremy Fitzhardinge 	leave_lazy(PARAVIRT_LAZY_MMU);
251b1df07bdSGlauber de Oliveira Costa }
252b1df07bdSGlauber de Oliveira Costa 
253511ba86eSBoris Ostrovsky void paravirt_flush_lazy_mmu(void)
254511ba86eSBoris Ostrovsky {
255511ba86eSBoris Ostrovsky 	preempt_disable();
256511ba86eSBoris Ostrovsky 
257511ba86eSBoris Ostrovsky 	if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
258511ba86eSBoris Ostrovsky 		arch_leave_lazy_mmu_mode();
259511ba86eSBoris Ostrovsky 		arch_enter_lazy_mmu_mode();
260511ba86eSBoris Ostrovsky 	}
261511ba86eSBoris Ostrovsky 
262511ba86eSBoris Ostrovsky 	preempt_enable();
263511ba86eSBoris Ostrovsky }
264511ba86eSBoris Ostrovsky 
265224101edSJeremy Fitzhardinge void paravirt_start_context_switch(struct task_struct *prev)
266b1df07bdSGlauber de Oliveira Costa {
2672829b449SJeremy Fitzhardinge 	BUG_ON(preemptible());
2682829b449SJeremy Fitzhardinge 
269c6ae41e7SAlex Shi 	if (this_cpu_read(paravirt_lazy_mode) == PARAVIRT_LAZY_MMU) {
270b407fc57SJeremy Fitzhardinge 		arch_leave_lazy_mmu_mode();
271224101edSJeremy Fitzhardinge 		set_ti_thread_flag(task_thread_info(prev), TIF_LAZY_MMU_UPDATES);
272b407fc57SJeremy Fitzhardinge 	}
273b1df07bdSGlauber de Oliveira Costa 	enter_lazy(PARAVIRT_LAZY_CPU);
274b1df07bdSGlauber de Oliveira Costa }
275b1df07bdSGlauber de Oliveira Costa 
276224101edSJeremy Fitzhardinge void paravirt_end_context_switch(struct task_struct *next)
277b1df07bdSGlauber de Oliveira Costa {
2782829b449SJeremy Fitzhardinge 	BUG_ON(preemptible());
2792829b449SJeremy Fitzhardinge 
280b407fc57SJeremy Fitzhardinge 	leave_lazy(PARAVIRT_LAZY_CPU);
281b407fc57SJeremy Fitzhardinge 
282224101edSJeremy Fitzhardinge 	if (test_and_clear_ti_thread_flag(task_thread_info(next), TIF_LAZY_MMU_UPDATES))
283b407fc57SJeremy Fitzhardinge 		arch_enter_lazy_mmu_mode();
284b1df07bdSGlauber de Oliveira Costa }
285b1df07bdSGlauber de Oliveira Costa 
286b1df07bdSGlauber de Oliveira Costa enum paravirt_lazy_mode paravirt_get_lazy_mode(void)
287b1df07bdSGlauber de Oliveira Costa {
288b8bcfe99SJeremy Fitzhardinge 	if (in_interrupt())
289b8bcfe99SJeremy Fitzhardinge 		return PARAVIRT_LAZY_NONE;
290b8bcfe99SJeremy Fitzhardinge 
291c6ae41e7SAlex Shi 	return this_cpu_read(paravirt_lazy_mode);
292b1df07bdSGlauber de Oliveira Costa }
293b1df07bdSGlauber de Oliveira Costa 
294b1df07bdSGlauber de Oliveira Costa struct pv_info pv_info = {
295b1df07bdSGlauber de Oliveira Costa 	.name = "bare hardware",
296b1df07bdSGlauber de Oliveira Costa 	.kernel_rpl = 0,
297b1df07bdSGlauber de Oliveira Costa 	.shared_kernel_pmd = 1,	/* Only used when CONFIG_X86_PAE is set */
298318f5a2aSAndy Lutomirski 
299318f5a2aSAndy Lutomirski #ifdef CONFIG_X86_64
300318f5a2aSAndy Lutomirski 	.extra_user_64bit_cs = __USER_CS,
301318f5a2aSAndy Lutomirski #endif
302b1df07bdSGlauber de Oliveira Costa };
303b1df07bdSGlauber de Oliveira Costa 
30441edafdbSJeremy Fitzhardinge #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE)
30541edafdbSJeremy Fitzhardinge /* 32-bit pagetable entries */
306da5de7c2SJeremy Fitzhardinge #define PTE_IDENT	__PV_IS_CALLEE_SAVE(_paravirt_ident_32)
30741edafdbSJeremy Fitzhardinge #else
30841edafdbSJeremy Fitzhardinge /* 64-bit pagetable entries */
309da5de7c2SJeremy Fitzhardinge #define PTE_IDENT	__PV_IS_CALLEE_SAVE(_paravirt_ident_64)
31041edafdbSJeremy Fitzhardinge #endif
31141edafdbSJeremy Fitzhardinge 
3125c83511bSJuergen Gross struct paravirt_patch_template pv_ops = {
3135c83511bSJuergen Gross 	/* Init ops. */
3145c83511bSJuergen Gross 	.init.patch		= native_patch,
315b1df07bdSGlauber de Oliveira Costa 
3165c83511bSJuergen Gross 	/* Time ops. */
3175c83511bSJuergen Gross 	.time.sched_clock	= native_sched_clock,
3185c83511bSJuergen Gross 	.time.steal_clock	= native_steal_clock,
319b1df07bdSGlauber de Oliveira Costa 
3205c83511bSJuergen Gross 	/* Cpu ops. */
3215c83511bSJuergen Gross 	.cpu.cpuid		= native_cpuid,
3225c83511bSJuergen Gross 	.cpu.get_debugreg	= native_get_debugreg,
3235c83511bSJuergen Gross 	.cpu.set_debugreg	= native_set_debugreg,
3245c83511bSJuergen Gross 	.cpu.read_cr0		= native_read_cr0,
3255c83511bSJuergen Gross 	.cpu.write_cr0		= native_write_cr0,
3265c83511bSJuergen Gross 	.cpu.write_cr4		= native_write_cr4,
3275c83511bSJuergen Gross #ifdef CONFIG_X86_64
3285c83511bSJuergen Gross 	.cpu.read_cr8		= native_read_cr8,
3295c83511bSJuergen Gross 	.cpu.write_cr8		= native_write_cr8,
3305c83511bSJuergen Gross #endif
3315c83511bSJuergen Gross 	.cpu.wbinvd		= native_wbinvd,
3325c83511bSJuergen Gross 	.cpu.read_msr		= native_read_msr,
3335c83511bSJuergen Gross 	.cpu.write_msr		= native_write_msr,
3345c83511bSJuergen Gross 	.cpu.read_msr_safe	= native_read_msr_safe,
3355c83511bSJuergen Gross 	.cpu.write_msr_safe	= native_write_msr_safe,
3365c83511bSJuergen Gross 	.cpu.read_pmc		= native_read_pmc,
3375c83511bSJuergen Gross 	.cpu.load_tr_desc	= native_load_tr_desc,
3385c83511bSJuergen Gross 	.cpu.set_ldt		= native_set_ldt,
3395c83511bSJuergen Gross 	.cpu.load_gdt		= native_load_gdt,
3405c83511bSJuergen Gross 	.cpu.load_idt		= native_load_idt,
3415c83511bSJuergen Gross 	.cpu.store_tr		= native_store_tr,
3425c83511bSJuergen Gross 	.cpu.load_tls		= native_load_tls,
3435c83511bSJuergen Gross #ifdef CONFIG_X86_64
3445c83511bSJuergen Gross 	.cpu.load_gs_index	= native_load_gs_index,
3455c83511bSJuergen Gross #endif
3465c83511bSJuergen Gross 	.cpu.write_ldt_entry	= native_write_ldt_entry,
3475c83511bSJuergen Gross 	.cpu.write_gdt_entry	= native_write_gdt_entry,
3485c83511bSJuergen Gross 	.cpu.write_idt_entry	= native_write_idt_entry,
349b1df07bdSGlauber de Oliveira Costa 
3505c83511bSJuergen Gross 	.cpu.alloc_ldt		= paravirt_nop,
3515c83511bSJuergen Gross 	.cpu.free_ldt		= paravirt_nop,
352eba0045fSJeremy Fitzhardinge 
3535c83511bSJuergen Gross 	.cpu.load_sp0		= native_load_sp0,
354b1df07bdSGlauber de Oliveira Costa 
3555c83511bSJuergen Gross #ifdef CONFIG_X86_64
3565c83511bSJuergen Gross 	.cpu.usergs_sysret64	= native_usergs_sysret64,
3575c83511bSJuergen Gross #endif
3585c83511bSJuergen Gross 	.cpu.iret		= native_iret,
3595c83511bSJuergen Gross 	.cpu.swapgs		= native_swapgs,
360b1df07bdSGlauber de Oliveira Costa 
3615c83511bSJuergen Gross 	.cpu.set_iopl_mask	= native_set_iopl_mask,
3625c83511bSJuergen Gross 	.cpu.io_delay		= native_io_delay,
3635c83511bSJuergen Gross 
3645c83511bSJuergen Gross 	.cpu.start_context_switch	= paravirt_nop,
3655c83511bSJuergen Gross 	.cpu.end_context_switch		= paravirt_nop,
3665c83511bSJuergen Gross 
3675c83511bSJuergen Gross 	/* Irq ops. */
3685c83511bSJuergen Gross 	.irq.save_fl		= __PV_IS_CALLEE_SAVE(native_save_fl),
3695c83511bSJuergen Gross 	.irq.restore_fl		= __PV_IS_CALLEE_SAVE(native_restore_fl),
3705c83511bSJuergen Gross 	.irq.irq_disable	= __PV_IS_CALLEE_SAVE(native_irq_disable),
3715c83511bSJuergen Gross 	.irq.irq_enable		= __PV_IS_CALLEE_SAVE(native_irq_enable),
3725c83511bSJuergen Gross 	.irq.safe_halt		= native_safe_halt,
3735c83511bSJuergen Gross 	.irq.halt		= native_halt,
3745c83511bSJuergen Gross 
3755c83511bSJuergen Gross 	/* Mmu ops. */
3765c83511bSJuergen Gross 	.mmu.read_cr2		= native_read_cr2,
3775c83511bSJuergen Gross 	.mmu.write_cr2		= native_write_cr2,
3785c83511bSJuergen Gross 	.mmu.read_cr3		= __native_read_cr3,
3795c83511bSJuergen Gross 	.mmu.write_cr3		= native_write_cr3,
3805c83511bSJuergen Gross 
3815c83511bSJuergen Gross 	.mmu.flush_tlb_user	= native_flush_tlb,
3825c83511bSJuergen Gross 	.mmu.flush_tlb_kernel	= native_flush_tlb_global,
3835c83511bSJuergen Gross 	.mmu.flush_tlb_one_user	= native_flush_tlb_one_user,
3845c83511bSJuergen Gross 	.mmu.flush_tlb_others	= native_flush_tlb_others,
3855c83511bSJuergen Gross 	.mmu.tlb_remove_table	=
3865c83511bSJuergen Gross 			(void (*)(struct mmu_gather *, void *))tlb_remove_page,
3875c83511bSJuergen Gross 
3885c83511bSJuergen Gross 	.mmu.pgd_alloc		= __paravirt_pgd_alloc,
3895c83511bSJuergen Gross 	.mmu.pgd_free		= paravirt_nop,
3905c83511bSJuergen Gross 
3915c83511bSJuergen Gross 	.mmu.alloc_pte		= paravirt_nop,
3925c83511bSJuergen Gross 	.mmu.alloc_pmd		= paravirt_nop,
3935c83511bSJuergen Gross 	.mmu.alloc_pud		= paravirt_nop,
3945c83511bSJuergen Gross 	.mmu.alloc_p4d		= paravirt_nop,
3955c83511bSJuergen Gross 	.mmu.release_pte	= paravirt_nop,
3965c83511bSJuergen Gross 	.mmu.release_pmd	= paravirt_nop,
3975c83511bSJuergen Gross 	.mmu.release_pud	= paravirt_nop,
3985c83511bSJuergen Gross 	.mmu.release_p4d	= paravirt_nop,
3995c83511bSJuergen Gross 
4005c83511bSJuergen Gross 	.mmu.set_pte		= native_set_pte,
4015c83511bSJuergen Gross 	.mmu.set_pte_at		= native_set_pte_at,
4025c83511bSJuergen Gross 	.mmu.set_pmd		= native_set_pmd,
4035c83511bSJuergen Gross 
4045c83511bSJuergen Gross 	.mmu.ptep_modify_prot_start	= __ptep_modify_prot_start,
4055c83511bSJuergen Gross 	.mmu.ptep_modify_prot_commit	= __ptep_modify_prot_commit,
40608b882c6SJeremy Fitzhardinge 
40798233368SKirill A. Shutemov #if CONFIG_PGTABLE_LEVELS >= 3
408b1df07bdSGlauber de Oliveira Costa #ifdef CONFIG_X86_PAE
4095c83511bSJuergen Gross 	.mmu.set_pte_atomic	= native_set_pte_atomic,
4105c83511bSJuergen Gross 	.mmu.pte_clear		= native_pte_clear,
4115c83511bSJuergen Gross 	.mmu.pmd_clear		= native_pmd_clear,
412f95f2f7bSEduardo Habkost #endif
4135c83511bSJuergen Gross 	.mmu.set_pud		= native_set_pud,
414da5de7c2SJeremy Fitzhardinge 
4155c83511bSJuergen Gross 	.mmu.pmd_val		= PTE_IDENT,
4165c83511bSJuergen Gross 	.mmu.make_pmd		= PTE_IDENT,
417f95f2f7bSEduardo Habkost 
418f2a6a705SKirill A. Shutemov #if CONFIG_PGTABLE_LEVELS >= 4
4195c83511bSJuergen Gross 	.mmu.pud_val		= PTE_IDENT,
4205c83511bSJuergen Gross 	.mmu.make_pud		= PTE_IDENT,
421da5de7c2SJeremy Fitzhardinge 
4225c83511bSJuergen Gross 	.mmu.set_p4d		= native_set_p4d,
423f2a6a705SKirill A. Shutemov 
424f2a6a705SKirill A. Shutemov #if CONFIG_PGTABLE_LEVELS >= 5
4255c83511bSJuergen Gross 	.mmu.p4d_val		= PTE_IDENT,
4265c83511bSJuergen Gross 	.mmu.make_p4d		= PTE_IDENT,
427335437fbSKirill A. Shutemov 
4285c83511bSJuergen Gross 	.mmu.set_pgd		= native_set_pgd,
429335437fbSKirill A. Shutemov #endif /* CONFIG_PGTABLE_LEVELS >= 5 */
430f2a6a705SKirill A. Shutemov #endif /* CONFIG_PGTABLE_LEVELS >= 4 */
43198233368SKirill A. Shutemov #endif /* CONFIG_PGTABLE_LEVELS >= 3 */
432b1df07bdSGlauber de Oliveira Costa 
4335c83511bSJuergen Gross 	.mmu.pte_val		= PTE_IDENT,
4345c83511bSJuergen Gross 	.mmu.pgd_val		= PTE_IDENT,
435b1df07bdSGlauber de Oliveira Costa 
4365c83511bSJuergen Gross 	.mmu.make_pte		= PTE_IDENT,
4375c83511bSJuergen Gross 	.mmu.make_pgd		= PTE_IDENT,
438b1df07bdSGlauber de Oliveira Costa 
4395c83511bSJuergen Gross 	.mmu.dup_mmap		= paravirt_nop,
4405c83511bSJuergen Gross 	.mmu.exit_mmap		= paravirt_nop,
4415c83511bSJuergen Gross 	.mmu.activate_mm	= paravirt_nop,
442b1df07bdSGlauber de Oliveira Costa 
4435c83511bSJuergen Gross 	.mmu.lazy_mode = {
444b1df07bdSGlauber de Oliveira Costa 		.enter		= paravirt_nop,
445b1df07bdSGlauber de Oliveira Costa 		.leave		= paravirt_nop,
446511ba86eSBoris Ostrovsky 		.flush		= paravirt_nop,
447b1df07bdSGlauber de Oliveira Costa 	},
448aeaaa59cSJeremy Fitzhardinge 
4495c83511bSJuergen Gross 	.mmu.set_fixmap		= native_set_fixmap,
4505c83511bSJuergen Gross 
4515c83511bSJuergen Gross #if defined(CONFIG_PARAVIRT_SPINLOCKS)
4525c83511bSJuergen Gross 	/* Lock ops. */
4535c83511bSJuergen Gross #ifdef CONFIG_SMP
4545c83511bSJuergen Gross 	.lock.queued_spin_lock_slowpath	= native_queued_spin_lock_slowpath,
4555c83511bSJuergen Gross 	.lock.queued_spin_unlock	=
4565c83511bSJuergen Gross 				PV_CALLEE_SAVE(__native_queued_spin_unlock),
4575c83511bSJuergen Gross 	.lock.wait			= paravirt_nop,
4585c83511bSJuergen Gross 	.lock.kick			= paravirt_nop,
4595c83511bSJuergen Gross 	.lock.vcpu_is_preempted		=
4605c83511bSJuergen Gross 				PV_CALLEE_SAVE(__native_vcpu_is_preempted),
4615c83511bSJuergen Gross #endif /* SMP */
4625c83511bSJuergen Gross #endif
463b1df07bdSGlauber de Oliveira Costa };
464b1df07bdSGlauber de Oliveira Costa 
4655c83511bSJuergen Gross /* At this point, native_get/set_debugreg has real function entries */
4665c83511bSJuergen Gross NOKPROBE_SYMBOL(native_get_debugreg);
4675c83511bSJuergen Gross NOKPROBE_SYMBOL(native_set_debugreg);
4685c83511bSJuergen Gross NOKPROBE_SYMBOL(native_load_idt);
4695c83511bSJuergen Gross 
4705c83511bSJuergen Gross EXPORT_SYMBOL_GPL(pv_ops);
471b1df07bdSGlauber de Oliveira Costa EXPORT_SYMBOL_GPL(pv_info);
472