Skip to content
paravirt.h 28.2 KiB
Newer Older
#ifndef __ASM_PARAVIRT_H
#define __ASM_PARAVIRT_H
/* Various instructions on x86 need to be replaced for
 * para-virtualization: those hooks are defined here. */
/* Bitmask of what can be clobbered: usually at least eax. */
#define CLBR_NONE 0x0
#define CLBR_EAX 0x1
#define CLBR_ECX 0x2
#define CLBR_EDX 0x4
#define CLBR_ANY 0x7

struct thread_struct;
struct Xgt_desc_struct;
struct tss_struct;
struct desc_struct;
struct paravirt_ops
{
	unsigned int kernel_rpl;
 	int paravirt_enabled;
	const char *name;

	/*
	 * Patch may replace one of the defined code sequences with arbitrary
	 * code, subject to the same register constraints.  This generally
	 * means the code is not free to clobber any registers other than EAX.
	 * The patch function should return the number of bytes of code
	 * generated, as we nop pad the rest in generic code.
	 */
	unsigned (*patch)(u8 type, u16 clobber, void *firstinsn, unsigned len);

	void (*arch_setup)(void);
	char *(*memory_setup)(void);
	void (*init_IRQ)(void);

	void (*pagetable_setup_start)(pgd_t *pgd_base);
	void (*pagetable_setup_done)(pgd_t *pgd_base);

	void (*banner)(void);

	unsigned long (*get_wallclock)(void);
	int (*set_wallclock)(unsigned long);
	void (*time_init)(void);

	void (*cpuid)(unsigned int *eax, unsigned int *ebx,
		      unsigned int *ecx, unsigned int *edx);

	unsigned long (*get_debugreg)(int regno);
	void (*set_debugreg)(int regno, unsigned long value);
	void (*clts)(void);
	unsigned long (*read_cr0)(void);
	void (*write_cr0)(unsigned long);
	unsigned long (*read_cr2)(void);
	void (*write_cr2)(unsigned long);
	unsigned long (*read_cr3)(void);
	void (*write_cr3)(unsigned long);
	unsigned long (*read_cr4_safe)(void);
	unsigned long (*read_cr4)(void);
	void (*write_cr4)(unsigned long);
	unsigned long (*save_fl)(void);
	void (*restore_fl)(unsigned long);
	void (*irq_disable)(void);
	void (*irq_enable)(void);
	void (*safe_halt)(void);
	void (*halt)(void);
	void (*wbinvd)(void);

	/* err = 0/-EFAULT.  wrmsr returns 0/-EFAULT. */
	u64 (*read_msr)(unsigned int msr, int *err);
	int (*write_msr)(unsigned int msr, u64 val);

	u64 (*read_tsc)(void);
	u64 (*read_pmc)(void);
 	u64 (*get_scheduled_cycles)(void);
	unsigned long (*get_cpu_khz)(void);

	void (*load_tr_desc)(void);
	void (*load_gdt)(const struct Xgt_desc_struct *);
	void (*load_idt)(const struct Xgt_desc_struct *);
	void (*store_gdt)(struct Xgt_desc_struct *);
	void (*store_idt)(struct Xgt_desc_struct *);
	void (*set_ldt)(const void *desc, unsigned entries);
	unsigned long (*store_tr)(void);
	void (*load_tls)(struct thread_struct *t, unsigned int cpu);
	void (*write_ldt_entry)(struct desc_struct *,
				int entrynum, u32 low, u32 high);
	void (*write_gdt_entry)(struct desc_struct *,
				int entrynum, u32 low, u32 high);
	void (*write_idt_entry)(struct desc_struct *,
				int entrynum, u32 low, u32 high);
	void (*load_esp0)(struct tss_struct *tss, struct thread_struct *t);
	void (*set_iopl_mask)(unsigned mask);
	void (*io_delay)(void);
	void (*activate_mm)(struct mm_struct *prev,
			    struct mm_struct *next);
	void (*dup_mmap)(struct mm_struct *oldmm,
			 struct mm_struct *mm);
	void (*exit_mmap)(struct mm_struct *mm);

#ifdef CONFIG_X86_LOCAL_APIC
	void (*apic_write)(unsigned long reg, unsigned long v);
	void (*apic_write_atomic)(unsigned long reg, unsigned long v);
	unsigned long (*apic_read)(unsigned long reg);
	void (*setup_boot_clock)(void);
	void (*setup_secondary_clock)(void);
	void (*flush_tlb_user)(void);
	void (*flush_tlb_kernel)(void);
	void (*map_pt_hook)(int type, pte_t *va, u32 pfn);
	void (*alloc_pt)(u32 pfn);
	void (*alloc_pd)(u32 pfn);
	void (*alloc_pd_clone)(u32 pfn, u32 clonepfn, u32 start, u32 count);
	void (*release_pt)(u32 pfn);
	void (*release_pd)(u32 pfn);

	void (*set_pte)(pte_t *ptep, pte_t pteval);
	void (*set_pte_at)(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval);
	void (*set_pmd)(pmd_t *pmdp, pmd_t pmdval);
	void (*pte_update)(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
	void (*pte_update_defer)(struct mm_struct *mm, unsigned long addr, pte_t *ptep);

 	pte_t (*ptep_get_and_clear)(pte_t *ptep);

	void (*set_pte_atomic)(pte_t *ptep, pte_t pteval);
 	void (*set_pte_present)(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte);
	void (*set_pud)(pud_t *pudp, pud_t pudval);
 	void (*pte_clear)(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
	void (*pmd_clear)(pmd_t *pmdp);

	unsigned long long (*pte_val)(pte_t);
	unsigned long long (*pmd_val)(pmd_t);
	unsigned long long (*pgd_val)(pgd_t);

	pte_t (*make_pte)(unsigned long long pte);
	pmd_t (*make_pmd)(unsigned long long pmd);
	pgd_t (*make_pgd)(unsigned long long pgd);
#else
	unsigned long (*pte_val)(pte_t);
	unsigned long (*pgd_val)(pgd_t);

	pte_t (*make_pte)(unsigned long pte);
	pgd_t (*make_pgd)(unsigned long pgd);
	void (*set_lazy_mode)(int mode);
	/* These two are jmp to, not actually called. */
	void (*irq_enable_sysexit)(void);
	void (*iret)(void);
	void (*startup_ipi_hook)(int phys_apicid, unsigned long start_eip, unsigned long start_esp);
/* Mark a paravirt probe function. */
#define paravirt_probe(fn)						\
 static asmlinkage void (*__paravirtprobe_##fn)(void) __attribute_used__ \
		__attribute__((__section__(".paravirtprobe"))) = fn

extern struct paravirt_ops paravirt_ops;

#define PARAVIRT_PATCH(x)					\
	(offsetof(struct paravirt_ops, x) / sizeof(void *))

#define paravirt_type(type)					\
	[paravirt_typenum] "i" (PARAVIRT_PATCH(type))
#define paravirt_clobber(clobber)		\
	[paravirt_clobber] "i" (clobber)

#define PARAVIRT_CALL	"call *(paravirt_ops+%c[paravirt_typenum]*4);"

#define _paravirt_alt(insn_string, type, clobber)	\
	"771:\n\t" insn_string "\n" "772:\n"		\
	".pushsection .parainstructions,\"a\"\n"	\
	"  .long 771b\n"				\
	"  .byte " type "\n"				\
	"  .byte 772b-771b\n"				\
	"  .short " clobber "\n"			\
	".popsection\n"
Loading
Loading full blame...