static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf, unsigned long addr, unsigned len) { char *start, *end, *reloc; unsigned ret; start = end = reloc = NULL; #define SITE(op, x) \ case PARAVIRT_PATCH(op.x): \ if (have_vcpu_info_placement) { \ start = (char *)xen_##x##_direct; \ end = xen_##x##_direct_end; \ reloc = xen_##x##_direct_reloc; \ } \ goto patch_site switch (type) { SITE(pv_irq_ops, irq_enable); SITE(pv_irq_ops, irq_disable); SITE(pv_irq_ops, save_fl); SITE(pv_irq_ops, restore_fl); #undef SITE patch_site: if (start == NULL || (end-start) > len) goto default_patch; ret = paravirt_patch_insns(insnbuf, len, start, end); /* Note: because reloc is assigned from something that appears to be an array, gcc assumes it's non-null, but doesn't know its relationship with start and end. */ if (reloc > start && reloc < end) { int reloc_off = reloc - start; long *relocp = (long *)(insnbuf + reloc_off); long delta = start - (char *)addr; *relocp += delta; } break; default_patch: default: ret = paravirt_patch_default(type, clobbers, insnbuf, addr, len); break; } return ret; }
static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf, unsigned long addr, unsigned len) { char *start, *end, *reloc; unsigned ret; start = end = reloc = NULL; #define SITE(op, x) \ case PARAVIRT_PATCH(op.x): \ if (have_vcpu_info_placement) { \ start = (char *)xen_##x##_direct; \ end = xen_##x##_direct_end; \ reloc = xen_##x##_direct_reloc; \ } \ goto patch_site switch (type) { SITE(pv_irq_ops, irq_enable); SITE(pv_irq_ops, irq_disable); SITE(pv_irq_ops, save_fl); SITE(pv_irq_ops, restore_fl); #undef SITE patch_site: if (start == NULL || (end-start) > len) goto default_patch; ret = paravirt_patch_insns(insnbuf, len, start, end); if (reloc > start && reloc < end) { int reloc_off = reloc - start; long *relocp = (long *)(insnbuf + reloc_off); long delta = start - (char *)addr; *relocp += delta; } break; default_patch: default: ret = paravirt_patch_default(type, clobbers, insnbuf, addr, len); break; } return ret; }
static unsigned native_patch(u8 type, u16 clobbers, void *ibuf, unsigned long addr, unsigned len) { const unsigned char *start, *end; unsigned ret; switch(type) { #define SITE(x) case PARAVIRT_PATCH(x): start = start_##x; end = end_##x; goto patch_site SITE(irq_disable); SITE(irq_enable); SITE(restore_fl); SITE(save_fl); SITE(iret); SITE(irq_enable_sysexit); SITE(read_cr2); SITE(read_cr3); SITE(write_cr3); SITE(clts); SITE(read_tsc); #undef SITE patch_site: ret = paravirt_patch_insns(ibuf, len, start, end); break; case PARAVIRT_PATCH(make_pgd): case PARAVIRT_PATCH(make_pte): case PARAVIRT_PATCH(pgd_val): case PARAVIRT_PATCH(pte_val): #ifdef CONFIG_X86_PAE case PARAVIRT_PATCH(make_pmd): case PARAVIRT_PATCH(pmd_val): #endif /* These functions end up returning exactly what they're passed, in the same registers. */ ret = paravirt_patch_nop(); break; default: ret = paravirt_patch_default(type, clobbers, ibuf, addr, len); break; } return ret; }
static unsigned native_patch(u8 type, u16 clobbers, void *ibuf, unsigned long addr, unsigned len) { const unsigned char *start, *end; unsigned ret; switch(type) { #define SITE(ops, x) \ case PARAVIRT_PATCH(ops.x): \ start = start_##ops##_##x; \ end = end_##ops##_##x; \ goto patch_site SITE(pv_irq_ops, irq_disable); SITE(pv_irq_ops, irq_enable); SITE(pv_irq_ops, restore_fl); SITE(pv_irq_ops, save_fl); SITE(pv_cpu_ops, iret); SITE(pv_cpu_ops, irq_enable_sysexit); SITE(pv_mmu_ops, read_cr2); SITE(pv_mmu_ops, read_cr3); SITE(pv_mmu_ops, write_cr3); SITE(pv_cpu_ops, clts); SITE(pv_cpu_ops, read_tsc); #undef SITE patch_site: ret = paravirt_patch_insns(ibuf, len, start, end); break; default: ret = paravirt_patch_default(type, clobbers, ibuf, addr, len); break; } return ret; }