⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 paravirt.h

📁 linux 内核源代码
💻 H
📖 第 1 页 / 共 3 页
字号:
#ifndef __ASM_PARAVIRT_H#define __ASM_PARAVIRT_H/* Various instructions on x86 need to be replaced for * para-virtualization: those hooks are defined here. */#ifdef CONFIG_PARAVIRT#include <asm/page.h>/* 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#ifndef __ASSEMBLY__#include <linux/types.h>#include <linux/cpumask.h>#include <asm/kmap_types.h>struct page;struct thread_struct;struct Xgt_desc_struct;struct tss_struct;struct mm_struct;struct desc_struct;/* general info */struct pv_info {	unsigned int kernel_rpl;	int shared_kernel_pmd;	int paravirt_enabled;	const char *name;};struct pv_init_ops {	/*	 * 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 *insnbuf,			  unsigned long addr, unsigned len);	/* Basic arch-specific setup */	void (*arch_setup)(void);	char *(*memory_setup)(void);	void (*post_allocator_init)(void);	/* Print a banner to identify the environment */	void (*banner)(void);};struct pv_lazy_ops {	/* Set deferred update mode, used for batching operations. */	void (*enter)(void);	void (*leave)(void);};struct pv_time_ops {	void (*time_init)(void);	/* Set and set time of day */	unsigned long (*get_wallclock)(void);	int (*set_wallclock)(unsigned long);	unsigned long long (*sched_clock)(void);	unsigned long (*get_cpu_khz)(void);};struct pv_cpu_ops {	/* hooks for various privileged instructions */	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_cr4_safe)(void);	unsigned long (*read_cr4)(void);	void (*write_cr4)(unsigned long);	/* Segment descriptor handling */	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 (*wbinvd)(void);	void (*io_delay)(void);	/* cpuid emulation, mostly so that caps bits can be disabled */	void (*cpuid)(unsigned int *eax, unsigned int *ebx,		      unsigned int *ecx, unsigned int *edx);	/* MSR, PMC and TSR operations.	   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);	/* These two are jmp to, not actually called. */	void (*irq_enable_sysexit)(void);	void (*iret)(void);	struct pv_lazy_ops lazy_mode;};struct pv_irq_ops {	void (*init_IRQ)(void);	/*	 * Get/set interrupt state.  save_fl and restore_fl are only	 * expected to use X86_EFLAGS_IF; all other bits	 * returned from save_fl are undefined, and may be ignored by	 * restore_fl.	 */	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);};struct pv_apic_ops {#ifdef CONFIG_X86_LOCAL_APIC	/*	 * Direct APIC operations, principally for VMI.  Ideally	 * these shouldn't be in this interface.	 */	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 (*startup_ipi_hook)(int phys_apicid,				 unsigned long start_eip,				 unsigned long start_esp);#endif};struct pv_mmu_ops {	/*	 * Called before/after init_mm pagetable setup. setup_start	 * may reset %cr3, and may pre-install parts of the pagetable;	 * pagetable setup is expected to preserve any existing	 * mapping.	 */	void (*pagetable_setup_start)(pgd_t *pgd_base);	void (*pagetable_setup_done)(pgd_t *pgd_base);	unsigned long (*read_cr2)(void);	void (*write_cr2)(unsigned long);	unsigned long (*read_cr3)(void);	void (*write_cr3)(unsigned long);	/*	 * Hooks for intercepting the creation/use/destruction of an	 * mm_struct.	 */	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);	/* TLB operations */	void (*flush_tlb_user)(void);	void (*flush_tlb_kernel)(void);	void (*flush_tlb_single)(unsigned long addr);	void (*flush_tlb_others)(const cpumask_t *cpus, struct mm_struct *mm,				 unsigned long va);	/* Hooks for allocating/releasing pagetable pages */	void (*alloc_pt)(struct mm_struct *mm, 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);	/* Pagetable manipulation functions */	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);#ifdef CONFIG_X86_PAE	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);#endif#ifdef CONFIG_HIGHPTE	void *(*kmap_atomic_pte)(struct page *page, enum km_type type);#endif	struct pv_lazy_ops lazy_mode;};/* This contains all the paravirt structures: we get a convenient * number for each function using the offset which we use to indicate * what to patch. */struct paravirt_patch_template{	struct pv_init_ops pv_init_ops;	struct pv_time_ops pv_time_ops;	struct pv_cpu_ops pv_cpu_ops;	struct pv_irq_ops pv_irq_ops;	struct pv_apic_ops pv_apic_ops;	struct pv_mmu_ops pv_mmu_ops;};extern struct pv_info pv_info;extern struct pv_init_ops pv_init_ops;extern struct pv_time_ops pv_time_ops;extern struct pv_cpu_ops pv_cpu_ops;extern struct pv_irq_ops pv_irq_ops;extern struct pv_apic_ops pv_apic_ops;extern struct pv_mmu_ops pv_mmu_ops;#define PARAVIRT_PATCH(x)					\	(offsetof(struct paravirt_patch_template, x) / sizeof(void *))#define paravirt_type(op)				\	[paravirt_typenum] "i" (PARAVIRT_PATCH(op)),	\	[paravirt_opptr] "m" (op)#define paravirt_clobber(clobber)		\	[paravirt_clobber] "i" (clobber)/* * Generate some code, and mark it as patchable by the * apply_paravirt() alternate instruction patcher. */#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"/* Generate patchable code, with the default asm parameters. */#define paravirt_alt(insn_string)					\	_paravirt_alt(insn_string, "%c[paravirt_typenum]", "%c[paravirt_clobber]")unsigned paravirt_patch_nop(void);unsigned paravirt_patch_ignore(unsigned len);unsigned paravirt_patch_call(void *insnbuf,			     const void *target, u16 tgt_clobbers,			     unsigned long addr, u16 site_clobbers,			     unsigned len);unsigned paravirt_patch_jmp(void *insnbuf, const void *target,			    unsigned long addr, unsigned len);unsigned paravirt_patch_default(u8 type, u16 clobbers, void *insnbuf,				unsigned long addr, unsigned len);unsigned paravirt_patch_insns(void *insnbuf, unsigned len,			      const char *start, const char *end);int paravirt_disable_iospace(void);/* * This generates an indirect call based on the operation type number. * The type number, computed in PARAVIRT_PATCH, is derived from the * offset into the paravirt_patch_template structure, and can therefore be * freely converted back into a structure offset. */#define PARAVIRT_CALL	"call *%[paravirt_opptr];"/* * These macros are intended to wrap calls through one of the paravirt * ops structs, so that they can be later identified and patched at * runtime. * * Normally, a call to a pv_op function is a simple indirect call: * (paravirt_ops.operations)(args...). * * Unfortunately, this is a relatively slow operation for modern CPUs, * because it cannot necessarily determine what the destination * address is.  In this case, the address is a runtime constant, so at * the very least we can patch the call to e a simple direct call, or * ideally, patch an inline implementation into the callsite.  (Direct * calls are essentially free, because the call and return addresses * are completely predictable.) * * These macros rely on the standard gcc "regparm(3)" calling * convention, in which the first three arguments are placed in %eax, * %edx, %ecx (in that order), and the remaining arguments are placed * on the stack.  All caller-save registers (eax,edx,ecx) are expected * to be modified (either clobbered or used for return values). * * The call instruction itself is marked by placing its start address * and size into the .parainstructions section, so that * apply_paravirt() in arch/i386/kernel/alternative.c can do the * appropriate patching under the control of the backend pv_init_ops * implementation. * * Unfortunately there's no way to get gcc to generate the args setup * for the call, and then allow the call itself to be generated by an * inline asm.  Because of this, we must do the complete arg setup and * return value handling from within these macros.  This is fairly * cumbersome. * * There are 5 sets of PVOP_* macros for dealing with 0-4 arguments. * It could be extended to more arguments, but there would be little * to be gained from that.  For each number of arguments, there are * the two VCALL and CALL variants for void and non-void functions. * * When there is a return value, the invoker of the macro must specify * the return type.  The macro then uses sizeof() on that type to * determine whether its a 32 or 64 bit value, and places the return * in the right register(s) (just %eax for 32-bit, and %edx:%eax for * 64-bit). * * 64-bit arguments are passed as a pair of adjacent 32-bit arguments * in low,high order. * * Small structures are passed and returned in registers.  The macro * calling convention can't directly deal with this, so the wrapper * functions must do this. * * These PVOP_* macros are only defined within this header.  This * means that all uses must be wrapped in inline functions.  This also * makes sure the incoming and outgoing types are always correct. */#define __PVOP_CALL(rettype, op, pre, post, ...)			\	({								\		rettype __ret;						\		unsigned long __eax, __edx, __ecx;			\		if (sizeof(rettype) > sizeof(unsigned long)) {		\			asm volatile(pre				\				     paravirt_alt(PARAVIRT_CALL)	\				     post				\				     : "=a" (__eax), "=d" (__edx),	\				       "=c" (__ecx)			\				     : paravirt_type(op),		\				       paravirt_clobber(CLBR_ANY),	\				       ##__VA_ARGS__			\				     : "memory", "cc");			\

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -