From: Jan Kiszka <jan.kiszka@domain.hid>
To: Philippe Gerum <rpm@xenomai.org>
Cc: adeos-main <adeos-main@gna.org>
Subject: [Adeos-main] [PATCH 1/3] ipipe: x86-32: Drop IRQ flag virtualization from syscall/interrupt entry/exit
Date: Thu, 25 Nov 2010 17:46:59 +0100 [thread overview]
Message-ID: <4CEE9303.7050601@domain.hid> (raw)
In-Reply-To: <4CEE91CB.3060303@domain.hid>
The virtualization of the IRQ flag in entry_32.S turned out to be buggy
[1]. Instead of trying to fix it again, this patch removes the
virtualization, conceptually aligning x86-32 with x86-64. This
simplifies quite some code and should help keeping both in sync /wrt
this critical code paths.
[1] http://thread.gmane.org/gmane.linux.kernel.adeos.general/1706
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
Patch is moderately tested (both w/ and w/o IPIPE) and behaved properly
so far. Still, careful review would be welcome.
arch/x86/include/asm/irqflags.h | 42 ++++++++++--------
arch/x86/kernel/entry_32.S | 52 +++++++++--------------
arch/x86/kernel/ipipe.c | 88 +-------------------------------------
3 files changed, 47 insertions(+), 135 deletions(-)
diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h
index 59c8be8..5c18214 100644
--- a/arch/x86/include/asm/irqflags.h
+++ b/arch/x86/include/asm/irqflags.h
@@ -213,26 +213,15 @@ static inline unsigned long __raw_local_irq_save(void)
}
#else
+#define ENABLE_INTERRUPTS(x) sti
+#define DISABLE_INTERRUPTS(x) cli
+
#ifdef CONFIG_IPIPE
-#ifdef CONFIG_X86_32
-#define DISABLE_INTERRUPTS(clobbers) PER_CPU(ipipe_percpu_darray, %eax); btsl $0,(%eax); sti
-#define ENABLE_INTERRUPTS(clobbers) call __ipipe_unstall_root
-#else /* CONFIG_X86_64 */
-/* Not worth virtualizing in x86_64 mode. */
-#define DISABLE_INTERRUPTS(clobbers) cli
-#define ENABLE_INTERRUPTS(clobbers) sti
-#endif /* CONFIG_X86_64 */
#define ENABLE_INTERRUPTS_HW_COND sti
#define DISABLE_INTERRUPTS_HW_COND cli
-#define DISABLE_INTERRUPTS_HW(clobbers) cli
-#define ENABLE_INTERRUPTS_HW(clobbers) sti
#else /* !CONFIG_IPIPE */
-#define ENABLE_INTERRUPTS(x) sti
-#define DISABLE_INTERRUPTS(x) cli
#define ENABLE_INTERRUPTS_HW_COND
#define DISABLE_INTERRUPTS_HW_COND
-#define DISABLE_INTERRUPTS_HW(clobbers) DISABLE_INTERRUPTS(clobbers)
-#define ENABLE_INTERRUPTS_HW(clobbers) ENABLE_INTERRUPTS(clobbers)
#endif /* !CONFIG_IPIPE */
#ifdef CONFIG_X86_64
@@ -323,23 +312,38 @@ static inline int raw_irqs_disabled(void)
#endif
#ifdef CONFIG_TRACE_IRQFLAGS
-# if defined(CONFIG_IPIPE) && defined(CONFIG_X86_64)
-# define TRACE_IRQS_ON \
+# ifdef CONFIG_IPIPE
+# ifdef CONFIG_X86_64
+# define TRACE_IRQS_ON \
call trace_hardirqs_on_thunk; \
pushq %rax; \
PER_CPU(ipipe_percpu_darray, %rax); \
btrl $0,(%rax); \
popq %rax
-# define TRACE_IRQS_OFF \
+# define TRACE_IRQS_OFF \
pushq %rax; \
PER_CPU(ipipe_percpu_darray, %rax); \
btsl $0,(%rax); \
popq %rax; \
call trace_hardirqs_off_thunk
-# else /* !(CONFIG_IPIPE && CONFIG_X86_64) */
+# else /* CONFIG_X86_32 */
+# define TRACE_IRQS_ON \
+ call trace_hardirqs_on_thunk; \
+ pushl %eax; \
+ PER_CPU(ipipe_percpu_darray, %eax); \
+ btrl $0,(%eax); \
+ popl %eax
+# define TRACE_IRQS_OFF \
+ pushl %eax; \
+ PER_CPU(ipipe_percpu_darray, %eax); \
+ btsl $0,(%eax); \
+ popl %eax; \
+ call trace_hardirqs_off_thunk
+# endif /* CONFIG_X86_32 */
+# else /* !CONFIG_IPIPE */
# define TRACE_IRQS_ON call trace_hardirqs_on_thunk;
# define TRACE_IRQS_OFF call trace_hardirqs_off_thunk;
-# endif /* !(CONFIG_IPIPE && CONFIG_X86_64) */
+# endif /* !CONFIG_IPIPE */
#else
# define TRACE_IRQS_ON
# define TRACE_IRQS_OFF
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 4fc229b..cc382bc 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -82,25 +82,20 @@
#define nr_syscalls ((syscall_table_size)/4)
#ifdef CONFIG_IPIPE
-#define EMULATE_ROOT_IRET(bypass) \
- call __ipipe_unstall_iret_root ; \
- TRACE_IRQS_ON ; \
- bypass: \
- movl PT_EAX(%esp),%eax
-#define TEST_PREEMPTIBLE(regs) call __ipipe_kpreempt_root ; testl %eax,%eax
-#define CATCH_ROOT_SYSCALL(bypass1,bypass2) \
+#define CATCH_ROOT_SYSCALL(bypass_check,bypass_nocheck) \
movl %esp,%eax ; \
call __ipipe_syscall_root ; \
testl %eax,%eax ; \
- js bypass1 ; \
- jne bypass2 ; \
+ movl PT_EAX(%esp),%eax ; \
+ js bypass_check ; \
+ jne bypass_nocheck ; \
movl PT_ORIG_EAX(%esp),%eax
#define PUSH_XCODE(v) pushl $ ex_ ## v
#define PUSH_XVEC(v) pushl $ ex_ ## v
#define HANDLE_EXCEPTION(code) movl %code,%ecx ; \
call __ipipe_handle_exception ; \
testl %eax,%eax ; \
- jnz restore_ret
+ jnz restore_nocheck
#define DIVERT_EXCEPTION(code) movl $(__USER_DS), %ecx ; \
movl %ecx, %ds ; \
movl %ecx, %es ; \
@@ -108,7 +103,8 @@
movl $ex_ ## code,%edx ; \
call __ipipe_divert_exception ; \
testl %eax,%eax ; \
- jnz restore_ret
+ jnz restore_nocheck
+#define PREEMPT_SCHEDULE_IRQ call __ipipe_preempt_schedule_irq
#ifdef CONFIG_IPIPE_TRACE_IRQSOFF
# define IPIPE_TRACE_IRQ_ENTER \
@@ -125,17 +121,16 @@
#define IPIPE_TRACE_IRQ_EXIT
#endif /* CONFIG_IPIPE_TRACE_IRQSOFF */
#else /* !CONFIG_IPIPE */
-#define EMULATE_ROOT_IRET(bypass)
-#define TEST_PREEMPTIBLE(regs) testl $X86_EFLAGS_IF,PT_EFLAGS(regs)
-#define CATCH_ROOT_SYSCALL(bypass1,bypass2)
+#define CATCH_ROOT_SYSCALL(bypass_check,bypass_nocheck)
#define PUSH_XCODE(v) pushl $v
#define PUSH_XVEC(v) pushl v
#define HANDLE_EXCEPTION(code) call *%code
#define DIVERT_EXCEPTION(code)
+#define PREEMPT_SCHEDULE_IRQ call preempt_schedule_irq
#endif /* CONFIG_IPIPE */
#ifdef CONFIG_PREEMPT
-#define preempt_stop(clobbers) DISABLE_INTERRUPTS_HW(clobbers); TRACE_IRQS_OFF
+#define preempt_stop(clobbers) DISABLE_INTERRUPTS(clobbers); TRACE_IRQS_OFF
#else
#define preempt_stop(clobbers)
#define resume_kernel restore_all
@@ -429,15 +424,16 @@ END(ret_from_exception)
#ifdef CONFIG_PREEMPT
ENTRY(resume_kernel)
+ DISABLE_INTERRUPTS(CLBR_ANY)
cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ?
jnz restore_all
need_resched:
movl TI_flags(%ebp), %ecx # need_resched set ?
testb $_TIF_NEED_RESCHED, %cl
jz restore_all
- TEST_PREEMPTIBLE(%esp) # interrupts off (exception path) ?
+ testl $X86_EFLAGS_IF,PT_EFLAGS(%esp) # interrupts off (exception path) ?
jz restore_all
- call preempt_schedule_irq
+ PREEMPT_SCHEDULE_IRQ
jmp need_resched
END(resume_kernel)
#endif
@@ -487,7 +483,7 @@ sysenter_past_esp:
pushl %eax
CFI_ADJUST_CFA_OFFSET 4
SAVE_ALL
- ENABLE_INTERRUPTS_HW(CLBR_NONE)
+ ENABLE_INTERRUPTS(CLBR_NONE)
/*
* Load the potential sixth argument from user stack.
@@ -503,7 +499,7 @@ sysenter_past_esp:
.previous
GET_THREAD_INFO(%ebp)
- CATCH_ROOT_SYSCALL(sysenter_tail,sysenter_out)
+ CATCH_ROOT_SYSCALL(sysenter_tail,sysenter_exit)
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
jnz sysenter_audit
@@ -521,13 +517,10 @@ sysenter_tail:
jne sysexit_audit
sysenter_exit:
/* if something modifies registers it must also disable sysexit */
- EMULATE_ROOT_IRET(sysenter_out)
movl PT_EIP(%esp), %edx
movl PT_OLDESP(%esp), %ecx
xorl %ebp,%ebp
-#ifndef CONFIG_IPIPE
- TRACE_IRQS_ON
-#endif
+ TRACE_IRQS_ON
1: mov PT_FS(%esp), %fs
PTGS_TO_GS
ENABLE_INTERRUPTS_SYSEXIT
@@ -592,7 +585,7 @@ ENTRY(system_call)
CFI_ADJUST_CFA_OFFSET 4
SAVE_ALL
GET_THREAD_INFO(%ebp)
- CATCH_ROOT_SYSCALL(syscall_exit,restore_ret)
+ CATCH_ROOT_SYSCALL(syscall_exit,restore_nocheck)
# system call tracing in operation / emulation
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
jnz syscall_trace_entry
@@ -625,10 +618,6 @@ restore_all_notrace:
CFI_REMEMBER_STATE
je ldt_ss # returning to user-space with LDT SS
restore_nocheck:
-#ifdef CONFIG_IPIPE
- call __ipipe_unstall_iret_root
-#endif /* CONFIG_IPIPE */
-restore_ret:
RESTORE_REGS 4 # skip orig_eax/error_code
CFI_ADJUST_CFA_OFFSET -4
irq_return:
@@ -690,7 +679,7 @@ ldt_ss:
/* Disable interrupts, but do not irqtrace this section: we
* will soon execute iret and the tracer was already set to
* the irqstate after the iret */
- DISABLE_INTERRUPTS_HW(CLBR_EAX)
+ DISABLE_INTERRUPTS(CLBR_EAX)
lss (%esp), %esp /* switch to espfix segment */
CFI_ADJUST_CFA_OFFSET -8
jmp restore_nocheck
@@ -720,6 +709,7 @@ work_resched:
work_notifysig: # deal with pending signals and
# notify-resume requests
+ ENABLE_INTERRUPTS_HW_COND
#ifdef CONFIG_VM86
testl $X86_EFLAGS_VM, PT_EFLAGS(%esp)
movl %esp, %eax
@@ -931,7 +921,7 @@ common_interrupt:
IPIPE_TRACE_IRQ_EXIT
testl %eax,%eax
jnz ret_from_intr
- jmp restore_ret
+ jmp restore_nocheck
CFI_ENDPROC
.pushsection .kprobes.text, "ax"
@@ -947,7 +937,7 @@ ENTRY(name) \
IPIPE_TRACE_IRQ_EXIT; \
testl %eax,%eax; \
jnz ret_from_intr; \
- jmp restore_ret; \
+ jmp restore_nocheck; \
CFI_ENDPROC
#define BUILD_INTERRUPT(name, nr) BUILD_INTERRUPT3(name, nr, smp_##name)
diff --git a/arch/x86/kernel/ipipe.c b/arch/x86/kernel/ipipe.c
index 6720ba8..c943fca 100644
--- a/arch/x86/kernel/ipipe.c
+++ b/arch/x86/kernel/ipipe.c
@@ -393,72 +393,7 @@ static inline void __fixup_if(int s, struct pt_regs *regs)
regs->flags |= X86_EFLAGS_IF;
}
-#ifdef CONFIG_X86_32
-
-/*
- * Check the stall bit of the root domain to make sure the existing
- * preemption opportunity upon in-kernel resumption could be
- * exploited. In case a rescheduling could take place, the root stage
- * is stalled before the hw interrupts are re-enabled. This routine
- * must be called with hw interrupts off.
- */
-
-asmlinkage int __ipipe_kpreempt_root(struct pt_regs regs)
-{
- if (test_bit(IPIPE_STALL_FLAG, &ipipe_root_cpudom_var(status)))
- /* Root stage is stalled: rescheduling denied. */
- return 0;
-
- __ipipe_stall_root();
- trace_hardirqs_off();
- local_irq_enable_hw_notrace();
-
- return 1; /* Ok, may reschedule now. */
-}
-
-asmlinkage void __ipipe_unstall_iret_root(struct pt_regs regs)
-{
- struct ipipe_percpu_domain_data *p;
-
- /* Emulate IRET's handling of the interrupt flag. */
-
- local_irq_disable_hw();
-
- p = ipipe_root_cpudom_ptr();
-
- /*
- * Restore the software state as it used to be on kernel
- * entry. CAUTION: NMIs must *not* return through this
- * emulation.
- */
- if (raw_irqs_disabled_flags(regs.flags)) {
- if (!__test_and_set_bit(IPIPE_STALL_FLAG, &p->status))
- trace_hardirqs_off();
- if (!__ipipe_pipeline_head_p(ipipe_root_domain))
- regs.flags |= X86_EFLAGS_IF;
- } else {
- if (test_bit(IPIPE_STALL_FLAG, &p->status)) {
- trace_hardirqs_on();
- __clear_bit(IPIPE_STALL_FLAG, &p->status);
- }
- /*
- * We could have received and logged interrupts while
- * stalled in the syscall path: play the log now to
- * release any pending event. The SYNC_BIT prevents
- * infinite recursion in case of flooding.
- */
- if (unlikely(__ipipe_ipending_p(p)))
- __ipipe_sync_pipeline();
- }
-#ifdef CONFIG_IPIPE_TRACE_IRQSOFF
- ipipe_trace_end(0x8000000D);
-#endif /* CONFIG_IPIPE_TRACE_IRQSOFF */
-}
-
-#else /* !CONFIG_X86_32 */
-
#ifdef CONFIG_PREEMPT
-
asmlinkage void preempt_schedule_irq(void);
void __ipipe_preempt_schedule_irq(void)
@@ -492,11 +427,8 @@ void __ipipe_preempt_schedule_irq(void)
__local_irq_restore_nosync(flags);
}
-
#endif /* CONFIG_PREEMPT */
-#endif /* !CONFIG_X86_32 */
-
void __ipipe_halt_root(void)
{
struct ipipe_percpu_domain_data *p;
@@ -739,7 +671,6 @@ int __ipipe_divert_exception(struct pt_regs *regs, int vector)
int __ipipe_syscall_root(struct pt_regs *regs)
{
- struct ipipe_percpu_domain_data *p;
unsigned long flags;
int ret;
@@ -765,30 +696,17 @@ int __ipipe_syscall_root(struct pt_regs *regs)
__ipipe_dispatch_event(IPIPE_EVENT_RETURN, regs);
}
- if (!ipipe_root_domain_p) {
-#ifdef CONFIG_X86_32
- local_irq_restore_hw(flags);
-#endif
+ if (!ipipe_root_domain_p)
return 1;
- }
- p = ipipe_root_cpudom_ptr();
-#ifdef CONFIG_X86_32
- /*
- * Fix-up only required on 32-bit as only here the IRET return code
- * will evaluate the flags.
- */
- __fixup_if(test_bit(IPIPE_STALL_FLAG, &p->status), regs);
-#endif
/*
* If allowed, sync pending VIRQs before _TIF_NEED_RESCHED is
* tested.
*/
- if (__ipipe_ipending_p(p))
+ if (__ipipe_ipending_p(ipipe_root_cpudom_ptr()))
__ipipe_sync_pipeline();
-#ifdef CONFIG_X86_64
+
if (!ret)
-#endif
local_irq_restore_hw(flags);
return -ret;
--
1.7.1
next prev parent reply other threads:[~2010-11-25 16:46 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-11-25 16:41 [Adeos-main] [git pull] Updates for ipipe-2.6.35-x86 Jan Kiszka
2010-11-25 16:46 ` Jan Kiszka [this message]
2010-11-25 16:47 ` [Adeos-main] [PATCH 2/3] ipipe: x86: Push IF as set to stack of root IRQ handlers Jan Kiszka
2010-11-25 16:47 ` [Adeos-main] [PATCH 3/3] ipipe: x86: Fix up root state after __do_root_[vx]irq under CONFIG_TRACE_IRQFLAGS Jan Kiszka
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4CEE9303.7050601@domain.hid \
--to=jan.kiszka@domain.hid \
--cc=adeos-main@gna.org \
--cc=rpm@xenomai.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.