#ifndef _ASM_X86_PARAVIRT_TYPES_H
#define _ASM_X86_PARAVIRT_TYPES_H
#ifdef CONFIG_PARAVIRT
#ifndef __ASSEMBLER__
#include <linux/types.h>
#include <asm/paravirt-base.h>
#include <asm/desc_defs.h>
#include <asm/pgtable_types.h>
#include <asm/nospec-branch.h>
struct thread_struct;
struct mm_struct;
struct task_struct;
struct cpumask;
struct flush_tlb_info;
struct vm_area_struct;
#ifdef CONFIG_PARAVIRT_XXL
struct pv_lazy_ops {
void (*enter)(void);
void (*leave)(void);
void (*flush)(void);
} __no_randomize_layout;
#endif
struct pv_cpu_ops {
void (*io_delay)(void);
#ifdef CONFIG_PARAVIRT_XXL
unsigned long (*get_debugreg)(int regno);
void (*set_debugreg)(int regno, unsigned long value);
unsigned long (*read_cr0)(void);
void (*write_cr0)(unsigned long);
void (*write_cr4)(unsigned long);
void (*load_tr_desc)(void);
void (*load_gdt)(const struct desc_ptr *);
void (*load_idt)(const struct desc_ptr *);
void (*set_ldt)(const void *desc, unsigned entries);
unsigned long (*store_tr)(void);
void (*load_tls)(struct thread_struct *t, unsigned int cpu);
void (*load_gs_index)(unsigned int idx);
void (*write_ldt_entry)(struct desc_struct *ldt, int entrynum,
const void *desc);
void (*write_gdt_entry)(struct desc_struct *,
int entrynum, const void *desc, int size);
void (*write_idt_entry)(gate_desc *,
int entrynum, const gate_desc *gate);
void (*alloc_ldt)(struct desc_struct *ldt, unsigned entries);
void (*free_ldt)(struct desc_struct *ldt, unsigned entries);
void (*load_sp0)(unsigned long sp0);
#ifdef CONFIG_X86_IOPL_IOPERM
void (*invalidate_io_bitmap)(void);
void (*update_io_bitmap)(void);
#endif
void (*cpuid)(unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx);
u64 (*read_msr)(u32 msr);
void (*write_msr)(u32 msr, u64 val);
int (*read_msr_safe)(u32 msr, u64 *val);
int (*write_msr_safe)(u32 msr, u64 val);
u64 (*read_pmc)(int counter);
void (*start_context_switch)(struct task_struct *prev);
void (*end_context_switch)(struct task_struct *next);
#endif
} __no_randomize_layout;
struct pv_irq_ops {
#ifdef CONFIG_PARAVIRT_XXL
struct paravirt_callee_save save_fl;
struct paravirt_callee_save irq_disable;
struct paravirt_callee_save irq_enable;
#endif
void (*safe_halt)(void);
void (*halt)(void);
} __no_randomize_layout;
struct pv_mmu_ops {
void (*flush_tlb_user)(void);
void (*flush_tlb_kernel)(void);
void (*flush_tlb_one_user)(unsigned long addr);
void (*flush_tlb_multi)(const struct cpumask *cpus,
const struct flush_tlb_info *info);
void (*exit_mmap)(struct mm_struct *mm);
void (*notify_page_enc_status_changed)(unsigned long pfn, int npages, bool enc);
#ifdef CONFIG_PARAVIRT_XXL
struct paravirt_callee_save read_cr2;
void (*write_cr2)(unsigned long);
unsigned long (*read_cr3)(void);
void (*write_cr3)(unsigned long);
void (*enter_mmap)(struct mm_struct *mm);
int (*pgd_alloc)(struct mm_struct *mm);
void (*pgd_free)(struct mm_struct *mm, pgd_t *pgd);
void (*alloc_pte)(struct mm_struct *mm, unsigned long pfn);
void (*alloc_pmd)(struct mm_struct *mm, unsigned long pfn);
void (*alloc_pud)(struct mm_struct *mm, unsigned long pfn);
void (*alloc_p4d)(struct mm_struct *mm, unsigned long pfn);
void (*release_pte)(unsigned long pfn);
void (*release_pmd)(unsigned long pfn);
void (*release_pud)(unsigned long pfn);
void (*release_p4d)(unsigned long pfn);
void (*set_pte)(pte_t *ptep, pte_t pteval);
void (*set_pmd)(pmd_t *pmdp, pmd_t pmdval);
pte_t (*ptep_modify_prot_start)(struct vm_area_struct *vma, unsigned long addr,
pte_t *ptep);
void (*ptep_modify_prot_commit)(struct vm_area_struct *vma, unsigned long addr,
pte_t *ptep, pte_t pte);
struct paravirt_callee_save pte_val;
struct paravirt_callee_save make_pte;
struct paravirt_callee_save pgd_val;
struct paravirt_callee_save make_pgd;
void (*set_pud)(pud_t *pudp, pud_t pudval);
struct paravirt_callee_save pmd_val;
struct paravirt_callee_save make_pmd;
struct paravirt_callee_save pud_val;
struct paravirt_callee_save make_pud;
void (*set_p4d)(p4d_t *p4dp, p4d_t p4dval);
struct paravirt_callee_save p4d_val;
struct paravirt_callee_save make_p4d;
void (*set_pgd)(pgd_t *pgdp, pgd_t pgdval);
struct pv_lazy_ops lazy_mode;
void (*set_fixmap)(unsigned idx,
phys_addr_t phys, pgprot_t flags);
#endif
} __no_randomize_layout;
struct paravirt_patch_template {
struct pv_cpu_ops cpu;
struct pv_irq_ops irq;
struct pv_mmu_ops mmu;
} __no_randomize_layout;
extern struct paravirt_patch_template pv_ops;
#define paravirt_ptr(array, op) [paravirt_opptr] "m" (array.op)
#define PARAVIRT_CALL \
ANNOTATE_RETPOLINE_SAFE "\n\t" \
"call *%[paravirt_opptr]"
#ifdef CONFIG_X86_32
#define PVOP_CALL_ARGS \
unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx;
#define PVOP_CALL_ARG1(x) "a" ((unsigned long)(x))
#define PVOP_CALL_ARG2(x) "d" ((unsigned long)(x))
#define PVOP_CALL_ARG3(x) "c" ((unsigned long)(x))
#define PVOP_VCALL_CLOBBERS "=a" (__eax), "=d" (__edx), \
"=c" (__ecx)
#define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS
#define PVOP_VCALLEE_CLOBBERS "=a" (__eax), "=d" (__edx)
#define PVOP_CALLEE_CLOBBERS PVOP_VCALLEE_CLOBBERS
#define EXTRA_CLOBBERS
#define VEXTRA_CLOBBERS
#else
#define PVOP_CALL_ARGS \
unsigned long __edi = __edi, __esi = __esi, \
__edx = __edx, __ecx = __ecx, __eax = __eax;
#define PVOP_CALL_ARG1(x) "D" ((unsigned long)(x))
#define PVOP_CALL_ARG2(x) "S" ((unsigned long)(x))
#define PVOP_CALL_ARG3(x) "d" ((unsigned long)(x))
#define PVOP_CALL_ARG4(x) "c" ((unsigned long)(x))
#define PVOP_VCALL_CLOBBERS "=D" (__edi), \
"=S" (__esi), "=d" (__edx), \
"=c" (__ecx)
#define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS, "=a" (__eax)
#ifdef CONFIG_ZERO_CALL_USED_REGS
#define PVOP_VCALLEE_CLOBBERS "=a" (__eax), PVOP_VCALL_CLOBBERS
#else
#define PVOP_VCALLEE_CLOBBERS "=a" (__eax)
#endif
#define PVOP_CALLEE_CLOBBERS PVOP_VCALLEE_CLOBBERS
#define EXTRA_CLOBBERS , "r8", "r9", "r10", "r11"
#define VEXTRA_CLOBBERS , "rax", "r8", "r9", "r10", "r11"
#endif
#define PVOP_RETVAL(rettype) \
({ unsigned long __mask = ~0UL; \
BUILD_BUG_ON(sizeof(rettype) > sizeof(unsigned long)); \
switch (sizeof(rettype)) { \
case 1: __mask = 0xffUL; break; \
case 2: __mask = 0xffffUL; break; \
case 4: __mask = 0xffffffffUL; break; \
default: break; \
} \
__mask & __eax; \
})
#define ____PVOP_CALL(ret, array, op, call_clbr, extra_clbr, ...) \
({ \
PVOP_CALL_ARGS; \
asm volatile(ALTERNATIVE(PARAVIRT_CALL, ALT_CALL_INSTR, \
ALT_CALL_ALWAYS) \
: call_clbr, ASM_CALL_CONSTRAINT \
: paravirt_ptr(array, op), \
##__VA_ARGS__ \
: "memory", "cc" extra_clbr); \
ret; \
})
#define ____PVOP_ALT_CALL(ret, array, op, alt, cond, call_clbr, \
extra_clbr, ...) \
({ \
PVOP_CALL_ARGS; \
asm volatile(ALTERNATIVE_2(PARAVIRT_CALL, \
ALT_CALL_INSTR, ALT_CALL_ALWAYS, \
alt, cond) \
: call_clbr, ASM_CALL_CONSTRAINT \
: paravirt_ptr(array, op), \
##__VA_ARGS__ \
: "memory", "cc" extra_clbr); \
ret; \
})
#define __PVOP_CALL(rettype, array, op, ...) \
____PVOP_CALL(PVOP_RETVAL(rettype), array, op, \
PVOP_CALL_CLOBBERS, EXTRA_CLOBBERS, ##__VA_ARGS__)
#define __PVOP_ALT_CALL(rettype, array, op, alt, cond, ...) \
____PVOP_ALT_CALL(PVOP_RETVAL(rettype), array, op, alt, cond, \
PVOP_CALL_CLOBBERS, EXTRA_CLOBBERS, \
##__VA_ARGS__)
#define __PVOP_CALLEESAVE(rettype, array, op, ...) \
____PVOP_CALL(PVOP_RETVAL(rettype), array, op.func, \
PVOP_CALLEE_CLOBBERS, , ##__VA_ARGS__)
#define __PVOP_ALT_CALLEESAVE(rettype, array, op, alt, cond, ...) \
____PVOP_ALT_CALL(PVOP_RETVAL(rettype), array, op.func, alt, cond, \
PVOP_CALLEE_CLOBBERS, , ##__VA_ARGS__)
#define __PVOP_VCALL(array, op, ...) \
(void)____PVOP_CALL(, array, op, PVOP_VCALL_CLOBBERS, \
VEXTRA_CLOBBERS, ##__VA_ARGS__)
#define __PVOP_ALT_VCALL(array, op, alt, cond, ...) \
(void)____PVOP_ALT_CALL(, array, op, alt, cond, \
PVOP_VCALL_CLOBBERS, VEXTRA_CLOBBERS, \
##__VA_ARGS__)
#define __PVOP_VCALLEESAVE(array, op, ...) \
(void)____PVOP_CALL(, array, op.func, \
PVOP_VCALLEE_CLOBBERS, , ##__VA_ARGS__)
#define __PVOP_ALT_VCALLEESAVE(array, op, alt, cond, ...) \
(void)____PVOP_ALT_CALL(, array, op.func, alt, cond, \
PVOP_VCALLEE_CLOBBERS, , ##__VA_ARGS__)
#define PVOP_CALL0(rettype, array, op) \
__PVOP_CALL(rettype, array, op)
#define PVOP_VCALL0(array, op) \
__PVOP_VCALL(array, op)
#define PVOP_ALT_CALL0(rettype, array, op, alt, cond) \
__PVOP_ALT_CALL(rettype, array, op, alt, cond)
#define PVOP_ALT_VCALL0(array, op, alt, cond) \
__PVOP_ALT_VCALL(array, op, alt, cond)
#define PVOP_CALLEE0(rettype, array, op) \
__PVOP_CALLEESAVE(rettype, array, op)
#define PVOP_VCALLEE0(array, op) \
__PVOP_VCALLEESAVE(array, op)
#define PVOP_ALT_CALLEE0(rettype, array, op, alt, cond) \
__PVOP_ALT_CALLEESAVE(rettype, array, op, alt, cond)
#define PVOP_ALT_VCALLEE0(array, op, alt, cond) \
__PVOP_ALT_VCALLEESAVE(array, op, alt, cond)
#define PVOP_CALL1(rettype, array, op, arg1) \
__PVOP_CALL(rettype, array, op, PVOP_CALL_ARG1(arg1))
#define PVOP_VCALL1(array, op, arg1) \
__PVOP_VCALL(array, op, PVOP_CALL_ARG1(arg1))
#define PVOP_ALT_VCALL1(array, op, arg1, alt, cond) \
__PVOP_ALT_VCALL(array, op, alt, cond, PVOP_CALL_ARG1(arg1))
#define PVOP_CALLEE1(rettype, array, op, arg1) \
__PVOP_CALLEESAVE(rettype, array, op, PVOP_CALL_ARG1(arg1))
#define PVOP_VCALLEE1(array, op, arg1) \
__PVOP_VCALLEESAVE(array, op, PVOP_CALL_ARG1(arg1))
#define PVOP_ALT_CALLEE1(rettype, array, op, arg1, alt, cond) \
__PVOP_ALT_CALLEESAVE(rettype, array, op, alt, cond, PVOP_CALL_ARG1(arg1))
#define PVOP_ALT_VCALLEE1(array, op, arg1, alt, cond) \
__PVOP_ALT_VCALLEESAVE(array, op, alt, cond, PVOP_CALL_ARG1(arg1))
#define PVOP_CALL2(rettype, array, op, arg1, arg2) \
__PVOP_CALL(rettype, array, op, PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2))
#define PVOP_VCALL2(array, op, arg1, arg2) \
__PVOP_VCALL(array, op, PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2))
#define PVOP_CALL3(rettype, array, op, arg1, arg2, arg3) \
__PVOP_CALL(rettype, array, op, PVOP_CALL_ARG1(arg1), \
PVOP_CALL_ARG2(arg2), PVOP_CALL_ARG3(arg3))
#define PVOP_VCALL3(array, op, arg1, arg2, arg3) \
__PVOP_VCALL(array, op, PVOP_CALL_ARG1(arg1), \
PVOP_CALL_ARG2(arg2), PVOP_CALL_ARG3(arg3))
#define PVOP_CALL4(rettype, array, op, arg1, arg2, arg3, arg4) \
__PVOP_CALL(rettype, array, op, \
PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2), \
PVOP_CALL_ARG3(arg3), PVOP_CALL_ARG4(arg4))
#define PVOP_VCALL4(array, op, arg1, arg2, arg3, arg4) \
__PVOP_VCALL(array, op, PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2), \
PVOP_CALL_ARG3(arg3), PVOP_CALL_ARG4(arg4))
#endif
#define ALT_NOT_XEN ALT_NOT(X86_FEATURE_XENPV)
#ifdef CONFIG_X86_32
#define PV_SAVE_ALL_CALLER_REGS "pushl %ecx;"
#define PV_RESTORE_ALL_CALLER_REGS "popl %ecx;"
#else
#define PV_SAVE_ALL_CALLER_REGS \
"push %rcx;" \
"push %rdx;" \
"push %rsi;" \
"push %rdi;" \
"push %r8;" \
"push %r9;" \
"push %r10;" \
"push %r11;"
#define PV_RESTORE_ALL_CALLER_REGS \
"pop %r11;" \
"pop %r10;" \
"pop %r9;" \
"pop %r8;" \
"pop %rdi;" \
"pop %rsi;" \
"pop %rdx;" \
"pop %rcx;"
#endif
#define PV_THUNK_NAME(func) "__raw_callee_save_" #func
#define __PV_CALLEE_SAVE_REGS_THUNK(func, section) \
extern typeof(func) __raw_callee_save_##func; \
\
asm(".pushsection " section ", \"ax\";" \
".globl " PV_THUNK_NAME(func) ";" \
".type " PV_THUNK_NAME(func) ", @function;" \
ASM_FUNC_ALIGN \
PV_THUNK_NAME(func) ":" \
ASM_ENDBR \
FRAME_BEGIN \
PV_SAVE_ALL_CALLER_REGS \
"call " #func ";" \
PV_RESTORE_ALL_CALLER_REGS \
FRAME_END \
ASM_RET \
".size " PV_THUNK_NAME(func) ", .-" PV_THUNK_NAME(func) ";" \
".popsection")
#define PV_CALLEE_SAVE_REGS_THUNK(func) \
__PV_CALLEE_SAVE_REGS_THUNK(func, ".text")
#define PV_CALLEE_SAVE(func) \
((struct paravirt_callee_save) { __raw_callee_save_##func })
#define __PV_IS_CALLEE_SAVE(func) \
((struct paravirt_callee_save) { func })
#endif
#endif