Skip to content
paravirt.h 31.2 KiB
Newer Older
void _paravirt_nop(void);
#define paravirt_nop	((void *)_paravirt_nop)

/* These all sit in the .parainstructions section to tell us what to patch. */
	u8 *instr; 		/* original instructions */
	u8 instrtype;		/* type of this instruction */
	u8 len;			/* length of original instruction */
	u16 clobbers;		/* what registers you may clobber */
};

extern struct paravirt_patch_site __parainstructions[],
	__parainstructions_end[];

static inline unsigned long __raw_local_save_flags(void)
{
	unsigned long f;

	asm volatile(paravirt_alt("pushl %%ecx; pushl %%edx;"
				  PARAVIRT_CALL
				  "popl %%edx; popl %%ecx")
		     : "=a"(f)
		     : paravirt_type(pv_irq_ops.save_fl),
	return f;
}

static inline void raw_local_irq_restore(unsigned long f)
{
	asm volatile(paravirt_alt("pushl %%ecx; pushl %%edx;"
				  PARAVIRT_CALL
				  "popl %%edx; popl %%ecx")
		     : "=a"(f)
		     : "0"(f),
		       paravirt_type(pv_irq_ops.restore_fl),
}

static inline void raw_local_irq_disable(void)
{
	asm volatile(paravirt_alt("pushl %%ecx; pushl %%edx;"
				  PARAVIRT_CALL
				  "popl %%edx; popl %%ecx")
		     :
		     : paravirt_type(pv_irq_ops.irq_disable),
}

static inline void raw_local_irq_enable(void)
{
	asm volatile(paravirt_alt("pushl %%ecx; pushl %%edx;"
				  PARAVIRT_CALL
				  "popl %%edx; popl %%ecx")
		     :
		     : paravirt_type(pv_irq_ops.irq_enable),
}

static inline unsigned long __raw_local_irq_save(void)
{
	unsigned long f;

#define CLI_STRING							\
	_paravirt_alt("pushl %%ecx; pushl %%edx;"			\
		      "call *%[paravirt_cli_opptr];"			\
		      "popl %%edx; popl %%ecx",				\
		      "%c[paravirt_cli_type]", "%c[paravirt_clobber]")

#define STI_STRING							\
	_paravirt_alt("pushl %%ecx; pushl %%edx;"			\
		      "call *%[paravirt_sti_opptr];"			\
		      "popl %%edx; popl %%ecx",				\
		      "%c[paravirt_sti_type]", "%c[paravirt_clobber]")
	[paravirt_cli_type] "i" (PARAVIRT_PATCH(pv_irq_ops.irq_disable)),		\
	[paravirt_cli_opptr] "m" (pv_irq_ops.irq_disable),		\
	[paravirt_sti_type] "i" (PARAVIRT_PATCH(pv_irq_ops.irq_enable)),		\
	[paravirt_sti_opptr] "m" (pv_irq_ops.irq_enable),		\
/* Make sure as little as possible of this mess escapes. */
#undef __PVOP_CALL
#undef __PVOP_VCALL
#undef PVOP_VCALL0
#undef PVOP_CALL0
#undef PVOP_VCALL1
#undef PVOP_CALL1
#undef PVOP_VCALL2
#undef PVOP_CALL2
#undef PVOP_VCALL3
#undef PVOP_CALL3
#undef PVOP_VCALL4
#undef PVOP_CALL4
#define PARA_PATCH(struct, off)	((PARAVIRT_PATCH_##struct + (off)) / 4)
771:;						\
	ops;					\
772:;						\
	.pushsection .parainstructions,"a";	\
	 .long 771b;				\
	 .byte ptype;				\
	 .byte 772b-771b;			\
	 .short clobbers;			\
	.popsection

#define INTERRUPT_RETURN						\
	PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_iret), CLBR_NONE,	\
		  jmp *%cs:pv_cpu_ops+PV_CPU_iret)
	PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_disable), clobbers, \
		  call *%cs:pv_irq_ops+PV_IRQ_irq_disable;		\
	PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_enable), clobbers,	\
		  call *%cs:pv_irq_ops+PV_IRQ_irq_enable;		\
#define ENABLE_INTERRUPTS_SYSCALL_RET					\
	PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_irq_enable_syscall_ret),\
		  CLBR_NONE,						\
		  jmp *%cs:pv_cpu_ops+PV_CPU_irq_enable_syscall_ret)
	call *pv_cpu_ops+PV_CPU_read_cr0;	\
#endif /* __ASSEMBLY__ */
#endif /* CONFIG_PARAVIRT */
#endif	/* __ASM_PARAVIRT_H */