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