1#include <asm/paravirt.h> 2#include <asm/asm-offsets.h> 3#include <linux/stringify.h> 4 5DEF_NATIVE(pv_irq_ops, irq_disable, "cli"); 6DEF_NATIVE(pv_irq_ops, irq_enable, "sti"); 7DEF_NATIVE(pv_irq_ops, restore_fl, "pushq %rdi; popfq"); 8DEF_NATIVE(pv_irq_ops, save_fl, "pushfq; popq %rax"); 9DEF_NATIVE(pv_mmu_ops, read_cr2, "movq %cr2, %rax"); 10DEF_NATIVE(pv_mmu_ops, read_cr3, "movq %cr3, %rax"); 11DEF_NATIVE(pv_mmu_ops, write_cr3, "movq %rdi, %cr3"); 12DEF_NATIVE(pv_mmu_ops, flush_tlb_single, "invlpg (%rdi)"); 13DEF_NATIVE(pv_cpu_ops, clts, "clts"); 14DEF_NATIVE(pv_cpu_ops, wbinvd, "wbinvd"); 15 16DEF_NATIVE(pv_cpu_ops, irq_enable_sysexit, "swapgs; sti; sysexit"); 17DEF_NATIVE(pv_cpu_ops, usergs_sysret64, "swapgs; sysretq"); 18DEF_NATIVE(pv_cpu_ops, usergs_sysret32, "swapgs; sysretl"); 19DEF_NATIVE(pv_cpu_ops, swapgs, "swapgs"); 20 21DEF_NATIVE(, mov32, "mov %edi, %eax"); 22DEF_NATIVE(, mov64, "mov %rdi, %rax"); 23 24unsigned paravirt_patch_ident_32(void *insnbuf, unsigned len) 25{ 26 return paravirt_patch_insns(insnbuf, len, 27 start__mov32, end__mov32); 28} 29 30unsigned paravirt_patch_ident_64(void *insnbuf, unsigned len) 31{ 32 return paravirt_patch_insns(insnbuf, len, 33 start__mov64, end__mov64); 34} 35 36unsigned native_patch(u8 type, u16 clobbers, void *ibuf, 37 unsigned long addr, unsigned len) 38{ 39 const unsigned char *start, *end; 40 unsigned ret; 41 42#define PATCH_SITE(ops, x) \ 43 case PARAVIRT_PATCH(ops.x): \ 44 start = start_##ops##_##x; \ 45 end = end_##ops##_##x; \ 46 goto patch_site 47 switch(type) { 48 PATCH_SITE(pv_irq_ops, restore_fl); 49 PATCH_SITE(pv_irq_ops, save_fl); 50 PATCH_SITE(pv_irq_ops, irq_enable); 51 PATCH_SITE(pv_irq_ops, irq_disable); 52 PATCH_SITE(pv_cpu_ops, irq_enable_sysexit); 53 PATCH_SITE(pv_cpu_ops, usergs_sysret32); 54 PATCH_SITE(pv_cpu_ops, usergs_sysret64); 55 PATCH_SITE(pv_cpu_ops, swapgs); 56 PATCH_SITE(pv_mmu_ops, read_cr2); 57 PATCH_SITE(pv_mmu_ops, read_cr3); 58 PATCH_SITE(pv_mmu_ops, write_cr3); 59 PATCH_SITE(pv_cpu_ops, clts); 60 PATCH_SITE(pv_mmu_ops, flush_tlb_single); 61 PATCH_SITE(pv_cpu_ops, wbinvd); 62 63 patch_site: 64 ret = paravirt_patch_insns(ibuf, len, start, end); 65 break; 66 67 default: 68 ret = paravirt_patch_default(type, clobbers, ibuf, addr, len); 69 break; 70 } 71#undef PATCH_SITE 72 return ret; 73} 74