18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*  Paravirtualization interfaces
38c2ecf20Sopenharmony_ci    Copyright (C) 2006 Rusty Russell IBM Corporation
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci    2007 - x86_64 support added by Glauber de Oliveira Costa, Red Hat Inc
78c2ecf20Sopenharmony_ci*/
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/errno.h>
108c2ecf20Sopenharmony_ci#include <linux/init.h>
118c2ecf20Sopenharmony_ci#include <linux/export.h>
128c2ecf20Sopenharmony_ci#include <linux/efi.h>
138c2ecf20Sopenharmony_ci#include <linux/bcd.h>
148c2ecf20Sopenharmony_ci#include <linux/highmem.h>
158c2ecf20Sopenharmony_ci#include <linux/kprobes.h>
168c2ecf20Sopenharmony_ci#include <linux/pgtable.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include <asm/bug.h>
198c2ecf20Sopenharmony_ci#include <asm/paravirt.h>
208c2ecf20Sopenharmony_ci#include <asm/debugreg.h>
218c2ecf20Sopenharmony_ci#include <asm/desc.h>
228c2ecf20Sopenharmony_ci#include <asm/setup.h>
238c2ecf20Sopenharmony_ci#include <asm/time.h>
248c2ecf20Sopenharmony_ci#include <asm/pgalloc.h>
258c2ecf20Sopenharmony_ci#include <asm/irq.h>
268c2ecf20Sopenharmony_ci#include <asm/delay.h>
278c2ecf20Sopenharmony_ci#include <asm/fixmap.h>
288c2ecf20Sopenharmony_ci#include <asm/apic.h>
298c2ecf20Sopenharmony_ci#include <asm/tlbflush.h>
308c2ecf20Sopenharmony_ci#include <asm/timer.h>
318c2ecf20Sopenharmony_ci#include <asm/special_insns.h>
328c2ecf20Sopenharmony_ci#include <asm/tlb.h>
338c2ecf20Sopenharmony_ci#include <asm/io_bitmap.h>
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci/*
368c2ecf20Sopenharmony_ci * nop stub, which must not clobber anything *including the stack* to
378c2ecf20Sopenharmony_ci * avoid confusing the entry prologues.
388c2ecf20Sopenharmony_ci */
398c2ecf20Sopenharmony_ciextern void _paravirt_nop(void);
408c2ecf20Sopenharmony_ciasm (".pushsection .entry.text, \"ax\"\n"
418c2ecf20Sopenharmony_ci     ".global _paravirt_nop\n"
428c2ecf20Sopenharmony_ci     "_paravirt_nop:\n\t"
438c2ecf20Sopenharmony_ci     ASM_RET
448c2ecf20Sopenharmony_ci     ".size _paravirt_nop, . - _paravirt_nop\n\t"
458c2ecf20Sopenharmony_ci     ".type _paravirt_nop, @function\n\t"
468c2ecf20Sopenharmony_ci     ".popsection");
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_civoid __init default_banner(void)
498c2ecf20Sopenharmony_ci{
508c2ecf20Sopenharmony_ci	printk(KERN_INFO "Booting paravirtualized kernel on %s\n",
518c2ecf20Sopenharmony_ci	       pv_info.name);
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci/* Undefined instruction for dealing with missing ops pointers. */
558c2ecf20Sopenharmony_cistatic const unsigned char ud2a[] = { 0x0f, 0x0b };
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_cistruct branch {
588c2ecf20Sopenharmony_ci	unsigned char opcode;
598c2ecf20Sopenharmony_ci	u32 delta;
608c2ecf20Sopenharmony_ci} __attribute__((packed));
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistatic unsigned paravirt_patch_call(void *insn_buff, const void *target,
638c2ecf20Sopenharmony_ci				    unsigned long addr, unsigned len)
648c2ecf20Sopenharmony_ci{
658c2ecf20Sopenharmony_ci	const int call_len = 5;
668c2ecf20Sopenharmony_ci	struct branch *b = insn_buff;
678c2ecf20Sopenharmony_ci	unsigned long delta = (unsigned long)target - (addr+call_len);
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	if (len < call_len) {
708c2ecf20Sopenharmony_ci		pr_warn("paravirt: Failed to patch indirect CALL at %ps\n", (void *)addr);
718c2ecf20Sopenharmony_ci		/* Kernel might not be viable if patching fails, bail out: */
728c2ecf20Sopenharmony_ci		BUG_ON(1);
738c2ecf20Sopenharmony_ci	}
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	b->opcode = 0xe8; /* call */
768c2ecf20Sopenharmony_ci	b->delta = delta;
778c2ecf20Sopenharmony_ci	BUILD_BUG_ON(sizeof(*b) != call_len);
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	return call_len;
808c2ecf20Sopenharmony_ci}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci#ifdef CONFIG_PARAVIRT_XXL
838c2ecf20Sopenharmony_ci/* identity function, which can be inlined */
848c2ecf20Sopenharmony_ciu64 notrace _paravirt_ident_64(u64 x)
858c2ecf20Sopenharmony_ci{
868c2ecf20Sopenharmony_ci	return x;
878c2ecf20Sopenharmony_ci}
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_cistatic unsigned paravirt_patch_jmp(void *insn_buff, const void *target,
908c2ecf20Sopenharmony_ci				   unsigned long addr, unsigned len)
918c2ecf20Sopenharmony_ci{
928c2ecf20Sopenharmony_ci	struct branch *b = insn_buff;
938c2ecf20Sopenharmony_ci	unsigned long delta = (unsigned long)target - (addr+5);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	if (len < 5) {
968c2ecf20Sopenharmony_ci#ifdef CONFIG_RETPOLINE
978c2ecf20Sopenharmony_ci		WARN_ONCE(1, "Failing to patch indirect JMP in %ps\n", (void *)addr);
988c2ecf20Sopenharmony_ci#endif
998c2ecf20Sopenharmony_ci		return len;	/* call too long for patch site */
1008c2ecf20Sopenharmony_ci	}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	b->opcode = 0xe9;	/* jmp */
1038c2ecf20Sopenharmony_ci	b->delta = delta;
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	return 5;
1068c2ecf20Sopenharmony_ci}
1078c2ecf20Sopenharmony_ci#endif
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ciDEFINE_STATIC_KEY_TRUE(virt_spin_lock_key);
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_civoid __init native_pv_lock_init(void)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	if (!boot_cpu_has(X86_FEATURE_HYPERVISOR))
1148c2ecf20Sopenharmony_ci		static_branch_disable(&virt_spin_lock_key);
1158c2ecf20Sopenharmony_ci}
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ciunsigned paravirt_patch_default(u8 type, void *insn_buff,
1188c2ecf20Sopenharmony_ci				unsigned long addr, unsigned len)
1198c2ecf20Sopenharmony_ci{
1208c2ecf20Sopenharmony_ci	/*
1218c2ecf20Sopenharmony_ci	 * Neat trick to map patch type back to the call within the
1228c2ecf20Sopenharmony_ci	 * corresponding structure.
1238c2ecf20Sopenharmony_ci	 */
1248c2ecf20Sopenharmony_ci	void *opfunc = *((void **)&pv_ops + type);
1258c2ecf20Sopenharmony_ci	unsigned ret;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	if (opfunc == NULL)
1288c2ecf20Sopenharmony_ci		/* If there's no function, patch it with a ud2a (BUG) */
1298c2ecf20Sopenharmony_ci		ret = paravirt_patch_insns(insn_buff, len, ud2a, ud2a+sizeof(ud2a));
1308c2ecf20Sopenharmony_ci	else if (opfunc == _paravirt_nop)
1318c2ecf20Sopenharmony_ci		ret = 0;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci#ifdef CONFIG_PARAVIRT_XXL
1348c2ecf20Sopenharmony_ci	/* identity functions just return their single argument */
1358c2ecf20Sopenharmony_ci	else if (opfunc == _paravirt_ident_64)
1368c2ecf20Sopenharmony_ci		ret = paravirt_patch_ident_64(insn_buff, len);
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	else if (type == PARAVIRT_PATCH(cpu.iret) ||
1398c2ecf20Sopenharmony_ci		 type == PARAVIRT_PATCH(cpu.usergs_sysret64))
1408c2ecf20Sopenharmony_ci		/* If operation requires a jmp, then jmp */
1418c2ecf20Sopenharmony_ci		ret = paravirt_patch_jmp(insn_buff, opfunc, addr, len);
1428c2ecf20Sopenharmony_ci#endif
1438c2ecf20Sopenharmony_ci	else
1448c2ecf20Sopenharmony_ci		/* Otherwise call the function. */
1458c2ecf20Sopenharmony_ci		ret = paravirt_patch_call(insn_buff, opfunc, addr, len);
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	return ret;
1488c2ecf20Sopenharmony_ci}
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ciunsigned paravirt_patch_insns(void *insn_buff, unsigned len,
1518c2ecf20Sopenharmony_ci			      const char *start, const char *end)
1528c2ecf20Sopenharmony_ci{
1538c2ecf20Sopenharmony_ci	unsigned insn_len = end - start;
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	/* Alternative instruction is too large for the patch site and we cannot continue: */
1568c2ecf20Sopenharmony_ci	BUG_ON(insn_len > len || start == NULL);
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	memcpy(insn_buff, start, insn_len);
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	return insn_len;
1618c2ecf20Sopenharmony_ci}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_cistruct static_key paravirt_steal_enabled;
1648c2ecf20Sopenharmony_cistruct static_key paravirt_steal_rq_enabled;
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_cistatic u64 native_steal_clock(int cpu)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	return 0;
1698c2ecf20Sopenharmony_ci}
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci/* These are in entry.S */
1728c2ecf20Sopenharmony_ciextern void native_iret(void);
1738c2ecf20Sopenharmony_ciextern void native_usergs_sysret64(void);
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_cistatic struct resource reserve_ioports = {
1768c2ecf20Sopenharmony_ci	.start = 0,
1778c2ecf20Sopenharmony_ci	.end = IO_SPACE_LIMIT,
1788c2ecf20Sopenharmony_ci	.name = "paravirt-ioport",
1798c2ecf20Sopenharmony_ci	.flags = IORESOURCE_IO | IORESOURCE_BUSY,
1808c2ecf20Sopenharmony_ci};
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci/*
1838c2ecf20Sopenharmony_ci * Reserve the whole legacy IO space to prevent any legacy drivers
1848c2ecf20Sopenharmony_ci * from wasting time probing for their hardware.  This is a fairly
1858c2ecf20Sopenharmony_ci * brute-force approach to disabling all non-virtual drivers.
1868c2ecf20Sopenharmony_ci *
1878c2ecf20Sopenharmony_ci * Note that this must be called very early to have any effect.
1888c2ecf20Sopenharmony_ci */
1898c2ecf20Sopenharmony_ciint paravirt_disable_iospace(void)
1908c2ecf20Sopenharmony_ci{
1918c2ecf20Sopenharmony_ci	return request_resource(&ioport_resource, &reserve_ioports);
1928c2ecf20Sopenharmony_ci}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_cistatic DEFINE_PER_CPU(enum paravirt_lazy_mode, paravirt_lazy_mode) = PARAVIRT_LAZY_NONE;
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_cistatic inline void enter_lazy(enum paravirt_lazy_mode mode)
1978c2ecf20Sopenharmony_ci{
1988c2ecf20Sopenharmony_ci	BUG_ON(this_cpu_read(paravirt_lazy_mode) != PARAVIRT_LAZY_NONE);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	this_cpu_write(paravirt_lazy_mode, mode);
2018c2ecf20Sopenharmony_ci}
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_cistatic void leave_lazy(enum paravirt_lazy_mode mode)
2048c2ecf20Sopenharmony_ci{
2058c2ecf20Sopenharmony_ci	BUG_ON(this_cpu_read(paravirt_lazy_mode) != mode);
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	this_cpu_write(paravirt_lazy_mode, PARAVIRT_LAZY_NONE);
2088c2ecf20Sopenharmony_ci}
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_civoid paravirt_enter_lazy_mmu(void)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	enter_lazy(PARAVIRT_LAZY_MMU);
2138c2ecf20Sopenharmony_ci}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_civoid paravirt_leave_lazy_mmu(void)
2168c2ecf20Sopenharmony_ci{
2178c2ecf20Sopenharmony_ci	leave_lazy(PARAVIRT_LAZY_MMU);
2188c2ecf20Sopenharmony_ci}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_civoid paravirt_flush_lazy_mmu(void)
2218c2ecf20Sopenharmony_ci{
2228c2ecf20Sopenharmony_ci	preempt_disable();
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
2258c2ecf20Sopenharmony_ci		arch_leave_lazy_mmu_mode();
2268c2ecf20Sopenharmony_ci		arch_enter_lazy_mmu_mode();
2278c2ecf20Sopenharmony_ci	}
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	preempt_enable();
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci#ifdef CONFIG_PARAVIRT_XXL
2338c2ecf20Sopenharmony_civoid paravirt_start_context_switch(struct task_struct *prev)
2348c2ecf20Sopenharmony_ci{
2358c2ecf20Sopenharmony_ci	BUG_ON(preemptible());
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	if (this_cpu_read(paravirt_lazy_mode) == PARAVIRT_LAZY_MMU) {
2388c2ecf20Sopenharmony_ci		arch_leave_lazy_mmu_mode();
2398c2ecf20Sopenharmony_ci		set_ti_thread_flag(task_thread_info(prev), TIF_LAZY_MMU_UPDATES);
2408c2ecf20Sopenharmony_ci	}
2418c2ecf20Sopenharmony_ci	enter_lazy(PARAVIRT_LAZY_CPU);
2428c2ecf20Sopenharmony_ci}
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_civoid paravirt_end_context_switch(struct task_struct *next)
2458c2ecf20Sopenharmony_ci{
2468c2ecf20Sopenharmony_ci	BUG_ON(preemptible());
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	leave_lazy(PARAVIRT_LAZY_CPU);
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	if (test_and_clear_ti_thread_flag(task_thread_info(next), TIF_LAZY_MMU_UPDATES))
2518c2ecf20Sopenharmony_ci		arch_enter_lazy_mmu_mode();
2528c2ecf20Sopenharmony_ci}
2538c2ecf20Sopenharmony_ci#endif
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_cienum paravirt_lazy_mode paravirt_get_lazy_mode(void)
2568c2ecf20Sopenharmony_ci{
2578c2ecf20Sopenharmony_ci	if (in_interrupt())
2588c2ecf20Sopenharmony_ci		return PARAVIRT_LAZY_NONE;
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	return this_cpu_read(paravirt_lazy_mode);
2618c2ecf20Sopenharmony_ci}
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_cistruct pv_info pv_info = {
2648c2ecf20Sopenharmony_ci	.name = "bare hardware",
2658c2ecf20Sopenharmony_ci#ifdef CONFIG_PARAVIRT_XXL
2668c2ecf20Sopenharmony_ci	.extra_user_64bit_cs = __USER_CS,
2678c2ecf20Sopenharmony_ci#endif
2688c2ecf20Sopenharmony_ci};
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci/* 64-bit pagetable entries */
2718c2ecf20Sopenharmony_ci#define PTE_IDENT	__PV_IS_CALLEE_SAVE(_paravirt_ident_64)
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_cistruct paravirt_patch_template pv_ops = {
2748c2ecf20Sopenharmony_ci	/* Init ops. */
2758c2ecf20Sopenharmony_ci	.init.patch		= native_patch,
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	/* Time ops. */
2788c2ecf20Sopenharmony_ci	.time.sched_clock	= native_sched_clock,
2798c2ecf20Sopenharmony_ci	.time.steal_clock	= native_steal_clock,
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	/* Cpu ops. */
2828c2ecf20Sopenharmony_ci	.cpu.io_delay		= native_io_delay,
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci#ifdef CONFIG_PARAVIRT_XXL
2858c2ecf20Sopenharmony_ci	.cpu.cpuid		= native_cpuid,
2868c2ecf20Sopenharmony_ci	.cpu.get_debugreg	= native_get_debugreg,
2878c2ecf20Sopenharmony_ci	.cpu.set_debugreg	= native_set_debugreg,
2888c2ecf20Sopenharmony_ci	.cpu.read_cr0		= native_read_cr0,
2898c2ecf20Sopenharmony_ci	.cpu.write_cr0		= native_write_cr0,
2908c2ecf20Sopenharmony_ci	.cpu.write_cr4		= native_write_cr4,
2918c2ecf20Sopenharmony_ci	.cpu.wbinvd		= native_wbinvd,
2928c2ecf20Sopenharmony_ci	.cpu.read_msr		= native_read_msr,
2938c2ecf20Sopenharmony_ci	.cpu.write_msr		= native_write_msr,
2948c2ecf20Sopenharmony_ci	.cpu.read_msr_safe	= native_read_msr_safe,
2958c2ecf20Sopenharmony_ci	.cpu.write_msr_safe	= native_write_msr_safe,
2968c2ecf20Sopenharmony_ci	.cpu.read_pmc		= native_read_pmc,
2978c2ecf20Sopenharmony_ci	.cpu.load_tr_desc	= native_load_tr_desc,
2988c2ecf20Sopenharmony_ci	.cpu.set_ldt		= native_set_ldt,
2998c2ecf20Sopenharmony_ci	.cpu.load_gdt		= native_load_gdt,
3008c2ecf20Sopenharmony_ci	.cpu.load_idt		= native_load_idt,
3018c2ecf20Sopenharmony_ci	.cpu.store_tr		= native_store_tr,
3028c2ecf20Sopenharmony_ci	.cpu.load_tls		= native_load_tls,
3038c2ecf20Sopenharmony_ci	.cpu.load_gs_index	= native_load_gs_index,
3048c2ecf20Sopenharmony_ci	.cpu.write_ldt_entry	= native_write_ldt_entry,
3058c2ecf20Sopenharmony_ci	.cpu.write_gdt_entry	= native_write_gdt_entry,
3068c2ecf20Sopenharmony_ci	.cpu.write_idt_entry	= native_write_idt_entry,
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	.cpu.alloc_ldt		= paravirt_nop,
3098c2ecf20Sopenharmony_ci	.cpu.free_ldt		= paravirt_nop,
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	.cpu.load_sp0		= native_load_sp0,
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	.cpu.usergs_sysret64	= native_usergs_sysret64,
3148c2ecf20Sopenharmony_ci	.cpu.iret		= native_iret,
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_IOPL_IOPERM
3178c2ecf20Sopenharmony_ci	.cpu.invalidate_io_bitmap	= native_tss_invalidate_io_bitmap,
3188c2ecf20Sopenharmony_ci	.cpu.update_io_bitmap		= native_tss_update_io_bitmap,
3198c2ecf20Sopenharmony_ci#endif
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	.cpu.start_context_switch	= paravirt_nop,
3228c2ecf20Sopenharmony_ci	.cpu.end_context_switch		= paravirt_nop,
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	/* Irq ops. */
3258c2ecf20Sopenharmony_ci	.irq.save_fl		= __PV_IS_CALLEE_SAVE(native_save_fl),
3268c2ecf20Sopenharmony_ci	.irq.restore_fl		= __PV_IS_CALLEE_SAVE(native_restore_fl),
3278c2ecf20Sopenharmony_ci	.irq.irq_disable	= __PV_IS_CALLEE_SAVE(native_irq_disable),
3288c2ecf20Sopenharmony_ci	.irq.irq_enable		= __PV_IS_CALLEE_SAVE(native_irq_enable),
3298c2ecf20Sopenharmony_ci	.irq.safe_halt		= native_safe_halt,
3308c2ecf20Sopenharmony_ci	.irq.halt		= native_halt,
3318c2ecf20Sopenharmony_ci#endif /* CONFIG_PARAVIRT_XXL */
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	/* Mmu ops. */
3348c2ecf20Sopenharmony_ci	.mmu.flush_tlb_user	= native_flush_tlb_local,
3358c2ecf20Sopenharmony_ci	.mmu.flush_tlb_kernel	= native_flush_tlb_global,
3368c2ecf20Sopenharmony_ci	.mmu.flush_tlb_one_user	= native_flush_tlb_one_user,
3378c2ecf20Sopenharmony_ci	.mmu.flush_tlb_others	= native_flush_tlb_others,
3388c2ecf20Sopenharmony_ci	.mmu.tlb_remove_table	=
3398c2ecf20Sopenharmony_ci			(void (*)(struct mmu_gather *, void *))tlb_remove_page,
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	.mmu.exit_mmap		= paravirt_nop,
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci#ifdef CONFIG_PARAVIRT_XXL
3448c2ecf20Sopenharmony_ci	.mmu.read_cr2		= __PV_IS_CALLEE_SAVE(native_read_cr2),
3458c2ecf20Sopenharmony_ci	.mmu.write_cr2		= native_write_cr2,
3468c2ecf20Sopenharmony_ci	.mmu.read_cr3		= __native_read_cr3,
3478c2ecf20Sopenharmony_ci	.mmu.write_cr3		= native_write_cr3,
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	.mmu.pgd_alloc		= __paravirt_pgd_alloc,
3508c2ecf20Sopenharmony_ci	.mmu.pgd_free		= paravirt_nop,
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	.mmu.alloc_pte		= paravirt_nop,
3538c2ecf20Sopenharmony_ci	.mmu.alloc_pmd		= paravirt_nop,
3548c2ecf20Sopenharmony_ci	.mmu.alloc_pud		= paravirt_nop,
3558c2ecf20Sopenharmony_ci	.mmu.alloc_p4d		= paravirt_nop,
3568c2ecf20Sopenharmony_ci	.mmu.release_pte	= paravirt_nop,
3578c2ecf20Sopenharmony_ci	.mmu.release_pmd	= paravirt_nop,
3588c2ecf20Sopenharmony_ci	.mmu.release_pud	= paravirt_nop,
3598c2ecf20Sopenharmony_ci	.mmu.release_p4d	= paravirt_nop,
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	.mmu.set_pte		= native_set_pte,
3628c2ecf20Sopenharmony_ci	.mmu.set_pmd		= native_set_pmd,
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	.mmu.ptep_modify_prot_start	= __ptep_modify_prot_start,
3658c2ecf20Sopenharmony_ci	.mmu.ptep_modify_prot_commit	= __ptep_modify_prot_commit,
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	.mmu.set_pud		= native_set_pud,
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	.mmu.pmd_val		= PTE_IDENT,
3708c2ecf20Sopenharmony_ci	.mmu.make_pmd		= PTE_IDENT,
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	.mmu.pud_val		= PTE_IDENT,
3738c2ecf20Sopenharmony_ci	.mmu.make_pud		= PTE_IDENT,
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci	.mmu.set_p4d		= native_set_p4d,
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci#if CONFIG_PGTABLE_LEVELS >= 5
3788c2ecf20Sopenharmony_ci	.mmu.p4d_val		= PTE_IDENT,
3798c2ecf20Sopenharmony_ci	.mmu.make_p4d		= PTE_IDENT,
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	.mmu.set_pgd		= native_set_pgd,
3828c2ecf20Sopenharmony_ci#endif /* CONFIG_PGTABLE_LEVELS >= 5 */
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	.mmu.pte_val		= PTE_IDENT,
3858c2ecf20Sopenharmony_ci	.mmu.pgd_val		= PTE_IDENT,
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	.mmu.make_pte		= PTE_IDENT,
3888c2ecf20Sopenharmony_ci	.mmu.make_pgd		= PTE_IDENT,
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	.mmu.dup_mmap		= paravirt_nop,
3918c2ecf20Sopenharmony_ci	.mmu.activate_mm	= paravirt_nop,
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	.mmu.lazy_mode = {
3948c2ecf20Sopenharmony_ci		.enter		= paravirt_nop,
3958c2ecf20Sopenharmony_ci		.leave		= paravirt_nop,
3968c2ecf20Sopenharmony_ci		.flush		= paravirt_nop,
3978c2ecf20Sopenharmony_ci	},
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	.mmu.set_fixmap		= native_set_fixmap,
4008c2ecf20Sopenharmony_ci#endif /* CONFIG_PARAVIRT_XXL */
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci#if defined(CONFIG_PARAVIRT_SPINLOCKS)
4038c2ecf20Sopenharmony_ci	/* Lock ops. */
4048c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP
4058c2ecf20Sopenharmony_ci	.lock.queued_spin_lock_slowpath	= native_queued_spin_lock_slowpath,
4068c2ecf20Sopenharmony_ci	.lock.queued_spin_unlock	=
4078c2ecf20Sopenharmony_ci				PV_CALLEE_SAVE(__native_queued_spin_unlock),
4088c2ecf20Sopenharmony_ci	.lock.wait			= paravirt_nop,
4098c2ecf20Sopenharmony_ci	.lock.kick			= paravirt_nop,
4108c2ecf20Sopenharmony_ci	.lock.vcpu_is_preempted		=
4118c2ecf20Sopenharmony_ci				PV_CALLEE_SAVE(__native_vcpu_is_preempted),
4128c2ecf20Sopenharmony_ci#endif /* SMP */
4138c2ecf20Sopenharmony_ci#endif
4148c2ecf20Sopenharmony_ci};
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci#ifdef CONFIG_PARAVIRT_XXL
4178c2ecf20Sopenharmony_ci/* At this point, native_get/set_debugreg has real function entries */
4188c2ecf20Sopenharmony_ciNOKPROBE_SYMBOL(native_get_debugreg);
4198c2ecf20Sopenharmony_ciNOKPROBE_SYMBOL(native_set_debugreg);
4208c2ecf20Sopenharmony_ciNOKPROBE_SYMBOL(native_load_idt);
4218c2ecf20Sopenharmony_ci#endif
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ciEXPORT_SYMBOL(pv_ops);
4248c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pv_info);
425