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