153fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa#include <asm/paravirt.h>
253fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa#include <asm/asm-offsets.h>
38a650ce297c723ebe7da17ec2890f6971438aee1Glauber de Oliveira Costa#include <linux/stringify.h>
453fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa
553fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira CostaDEF_NATIVE(pv_irq_ops, irq_disable, "cli");
653fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira CostaDEF_NATIVE(pv_irq_ops, irq_enable, "sti");
753fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira CostaDEF_NATIVE(pv_irq_ops, restore_fl, "pushq %rdi; popfq");
853fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira CostaDEF_NATIVE(pv_irq_ops, save_fl, "pushfq; popq %rax");
953fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira CostaDEF_NATIVE(pv_cpu_ops, iret, "iretq");
1053fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira CostaDEF_NATIVE(pv_mmu_ops, read_cr2, "movq %cr2, %rax");
1153fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira CostaDEF_NATIVE(pv_mmu_ops, read_cr3, "movq %cr3, %rax");
1253fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira CostaDEF_NATIVE(pv_mmu_ops, write_cr3, "movq %rdi, %cr3");
1353fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira CostaDEF_NATIVE(pv_mmu_ops, flush_tlb_single, "invlpg (%rdi)");
1453fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira CostaDEF_NATIVE(pv_cpu_ops, clts, "clts");
1553fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira CostaDEF_NATIVE(pv_cpu_ops, wbinvd, "wbinvd");
1653fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa
172be29982a08009c731307f4a39053b70ac4700daJeremy FitzhardingeDEF_NATIVE(pv_cpu_ops, irq_enable_sysexit, "swapgs; sti; sysexit");
182be29982a08009c731307f4a39053b70ac4700daJeremy FitzhardingeDEF_NATIVE(pv_cpu_ops, usergs_sysret64, "swapgs; sysretq");
192be29982a08009c731307f4a39053b70ac4700daJeremy FitzhardingeDEF_NATIVE(pv_cpu_ops, usergs_sysret32, "swapgs; sysretl");
2053fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira CostaDEF_NATIVE(pv_cpu_ops, swapgs, "swapgs");
2153fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa
2241edafdb78feac1d1f8823846209975fde990633Jeremy FitzhardingeDEF_NATIVE(, mov32, "mov %edi, %eax");
2341edafdb78feac1d1f8823846209975fde990633Jeremy FitzhardingeDEF_NATIVE(, mov64, "mov %rdi, %rax");
2441edafdb78feac1d1f8823846209975fde990633Jeremy Fitzhardinge
2541edafdb78feac1d1f8823846209975fde990633Jeremy Fitzhardingeunsigned paravirt_patch_ident_32(void *insnbuf, unsigned len)
2641edafdb78feac1d1f8823846209975fde990633Jeremy Fitzhardinge{
2741edafdb78feac1d1f8823846209975fde990633Jeremy Fitzhardinge	return paravirt_patch_insns(insnbuf, len,
2841edafdb78feac1d1f8823846209975fde990633Jeremy Fitzhardinge				    start__mov32, end__mov32);
2941edafdb78feac1d1f8823846209975fde990633Jeremy Fitzhardinge}
3041edafdb78feac1d1f8823846209975fde990633Jeremy Fitzhardinge
3141edafdb78feac1d1f8823846209975fde990633Jeremy Fitzhardingeunsigned paravirt_patch_ident_64(void *insnbuf, unsigned len)
3241edafdb78feac1d1f8823846209975fde990633Jeremy Fitzhardinge{
3341edafdb78feac1d1f8823846209975fde990633Jeremy Fitzhardinge	return paravirt_patch_insns(insnbuf, len,
3441edafdb78feac1d1f8823846209975fde990633Jeremy Fitzhardinge				    start__mov64, end__mov64);
3541edafdb78feac1d1f8823846209975fde990633Jeremy Fitzhardinge}
3641edafdb78feac1d1f8823846209975fde990633Jeremy Fitzhardinge
3753fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costaunsigned native_patch(u8 type, u16 clobbers, void *ibuf,
3853fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa		      unsigned long addr, unsigned len)
3953fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa{
4053fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa	const unsigned char *start, *end;
4153fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa	unsigned ret;
4253fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa
4353fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa#define PATCH_SITE(ops, x)					\
4453fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa		case PARAVIRT_PATCH(ops.x):			\
4553fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa			start = start_##ops##_##x;		\
4653fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa			end = end_##ops##_##x;			\
4753fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa			goto patch_site
4853fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa	switch(type) {
4953fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa		PATCH_SITE(pv_irq_ops, restore_fl);
5053fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa		PATCH_SITE(pv_irq_ops, save_fl);
5153fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa		PATCH_SITE(pv_irq_ops, irq_enable);
5253fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa		PATCH_SITE(pv_irq_ops, irq_disable);
5353fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa		PATCH_SITE(pv_cpu_ops, iret);
542be29982a08009c731307f4a39053b70ac4700daJeremy Fitzhardinge		PATCH_SITE(pv_cpu_ops, irq_enable_sysexit);
552be29982a08009c731307f4a39053b70ac4700daJeremy Fitzhardinge		PATCH_SITE(pv_cpu_ops, usergs_sysret32);
562be29982a08009c731307f4a39053b70ac4700daJeremy Fitzhardinge		PATCH_SITE(pv_cpu_ops, usergs_sysret64);
5753fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa		PATCH_SITE(pv_cpu_ops, swapgs);
5853fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa		PATCH_SITE(pv_mmu_ops, read_cr2);
5953fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa		PATCH_SITE(pv_mmu_ops, read_cr3);
6053fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa		PATCH_SITE(pv_mmu_ops, write_cr3);
6153fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa		PATCH_SITE(pv_cpu_ops, clts);
6253fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa		PATCH_SITE(pv_mmu_ops, flush_tlb_single);
6353fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa		PATCH_SITE(pv_cpu_ops, wbinvd);
6453fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa
6553fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa	patch_site:
6653fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa		ret = paravirt_patch_insns(ibuf, len, start, end);
6753fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa		break;
6853fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa
6953fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa	default:
7053fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa		ret = paravirt_patch_default(type, clobbers, ibuf, addr, len);
7153fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa		break;
7253fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa	}
7353fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa#undef PATCH_SITE
7453fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa	return ret;
7553fd13cff04ce27ff3e8d3eb7e5ad4f56b580f2fGlauber de Oliveira Costa}
76