changing definition of paravirt_ops.iret

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I'm implementing a more efficient version of the Xen iret paravirt_op,
so that it can use the real iret instruction where possible.  I really
need to get access to per-cpu variables, so I can set the event mask
state in the vcpu_info structure, but unfortunately at the point where
INTERRUPT_RETURN is used in entry.S, the usermode %fs has already been
restored.

How would you feel if we changed paravirt_ops.iret to make it also
responsible for restoring %fs? 

In other words, change RESTORE_REGS to skip %fs, and then native_iret
would look like:

1:	popl %fs
	iret

with the normal exception stuff.  Fortunately, %fs is already the first
thing to be saved and last to be restored, so there's no major
rearrangements.

Ideally I'd also like a register to play with, but that would require
rearranging pt_regs, which is a bit tricky.

Also, INTERRUPT_RETURN already has a bug, in which it needs to deal with
its own iret exceptions.

    J

diff -r e13ec2ed67aa arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S	Mon May 21 16:56:20 2007 +0100
+++ b/arch/i386/kernel/entry.S	Mon May 21 17:21:37 2007 +0100
@@ -59,6 +59,9 @@
  *   INTERRUPT_RETURN (aka. "iret")
  *   GET_CR0_INTO_EAX (aka. "movl %cr0, %eax")
  *   ENABLE_INTERRUPTS_SYSEXIT (aka "sti; sysexit").
+ *
+ * INTERRUPT_RETURN is responsible for restoring the usermode %fs
+ * from the stack.
  *
  * For DISABLE_INTERRUPTS/ENABLE_INTERRUPTS (aka "cli"/"sti"), you must
  * specify what registers can be overwritten (CLBR_NONE, CLBR_EAX/EDX/ECX/ANY).
@@ -166,21 +169,15 @@ 2:	popl %es;	\
 2:	popl %es;	\
 	CFI_ADJUST_CFA_OFFSET -4;\
 	/*CFI_RESTORE es;*/\
-3:	popl %fs;	\
-	CFI_ADJUST_CFA_OFFSET -4;\
-	/*CFI_RESTORE fs;*/\
 .pushsection .fixup,"ax";	\
 4:	movl $0,(%esp);	\
 	jmp 1b;		\
 5:	movl $0,(%esp);	\
 	jmp 2b;		\
-6:	movl $0,(%esp);	\
-	jmp 3b;		\
 .section __ex_table,"a";\
 	.align 4;	\
 	.long 1b,4b;	\
 	.long 2b,5b;	\
-	.long 3b,6b;	\
 .popsection
 
 #define RING0_INT_FRAME \
@@ -406,19 +403,14 @@ restore_nocheck_notrace:
 	RESTORE_REGS
 	addl $4, %esp			# skip orig_eax/error_code
 	CFI_ADJUST_CFA_OFFSET -4
-1:	INTERRUPT_RETURN
-.section .fixup,"ax"
+	INTERRUPT_RETURN
+
 iret_exc:
 	TRACE_IRQS_ON
 	ENABLE_INTERRUPTS(CLBR_NONE)
 	pushl $0			# no error code
 	pushl $do_iret_error
 	jmp error_code
-.previous
-.section __ex_table,"a"
-	.align 4
-	.long 1b,iret_exc
-.previous
 
 	CFI_RESTORE_STATE
 ldt_ss:
@@ -863,21 +855,22 @@ nmi_espfix_stack:
 	RESTORE_REGS
 	lss 12+4(%esp), %esp		# back to espfix stack
 	CFI_ADJUST_CFA_OFFSET -24
-1:	INTERRUPT_RETURN
-	CFI_ENDPROC
+	INTERRUPT_RETURN
+	CFI_ENDPROC
+KPROBE_END(nmi)
+
+#ifdef CONFIG_PARAVIRT
+ENTRY(native_iret)
+1:	popl %fs
+2:	iret
+.pushsection .fixup,"ax"
+3:	movl $0,(%esp)
+	jmp 1b
 .section __ex_table,"a"
 	.align 4
-	.long 1b,iret_exc
-.previous
-KPROBE_END(nmi)
-
-#ifdef CONFIG_PARAVIRT
-ENTRY(native_iret)
-1:	iret
-.section __ex_table,"a"
-	.align 4
-	.long 1b,iret_exc
-.previous
+	.long 1b,3b
+	.long 2b,iret_exc
+.popsection
 END(native_iret)
 
 ENTRY(native_irq_enable_sysexit)
diff -r e13ec2ed67aa arch/i386/xen/enlighten.c
--- a/arch/i386/xen/enlighten.c	Mon May 21 16:56:20 2007 +0100
+++ b/arch/i386/xen/enlighten.c	Mon May 21 17:21:37 2007 +0100
@@ -851,7 +851,6 @@ static unsigned xen_patch(u8 type, u16 c
 		SITE(irq_disable);
 		SITE(save_fl);
 		SITE(restore_fl);
-		SITE(iret);
 #undef SITE
 
 	patch_site:
@@ -935,7 +934,7 @@ static const struct paravirt_ops xen_par
 	.read_tsc = native_read_tsc,
 	.read_pmc = native_read_pmc,
 
-	.iret = (void *)&hypercall_page[__HYPERVISOR_iret],
+	.iret = xen_iret,
 	.irq_enable_sysexit = NULL,  /* never called */
 
 	.load_tr_desc = paravirt_nop,
diff -r e13ec2ed67aa include/asm-i386/irqflags.h
--- a/include/asm-i386/irqflags.h	Mon May 21 16:56:20 2007 +0100
+++ b/include/asm-i386/irqflags.h	Mon May 21 17:21:37 2007 +0100
@@ -106,7 +106,18 @@ static inline unsigned long __raw_local_
 #define DISABLE_INTERRUPTS(clobbers)	cli
 #define ENABLE_INTERRUPTS(clobbers)	sti
 #define ENABLE_INTERRUPTS_SYSEXIT	sti; sysexit
-#define INTERRUPT_RETURN		iret
+#define INTERRUPT_RETURN				\
+1:	popl %fs;					\
+2:	iret;						\
+.pushsection .fixup,"ax";				\
+3:	movl $0,(%esp);					\
+	jmp 1b;						\
+.section __ex_table,"a";				\
+	.align 4;					\
+	.long 1b,3b;					\
+	.long 2b,iret_exc;				\
+.popsection
+
 #define GET_CR0_INTO_EAX		movl %cr0, %eax
 #endif /* __ASSEMBLY__ */
 #endif /* CONFIG_PARAVIRT */

_______________________________________________
Virtualization mailing list
Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linux-foundation.org/mailman/listinfo/virtualization

[Index of Archives]     [KVM Development]     [Libvirt Development]     [Libvirt Users]     [CentOS Virtualization]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux