mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH -rt] update kmap_atomic on !HIGHMEM
@ 2006-12-27 19:35 Daniel Walker
  2006-12-27 20:54 ` Ingo Molnar
  2006-12-27 21:25 ` Ingo Molnar
  0 siblings, 2 replies; 10+ messages in thread
From: Daniel Walker @ 2006-12-27 19:35 UTC (permalink / raw)
  To: mingo; +Cc: linux-kernel

I got some scheduling while atomic on x86-64 , and since x86-64 doesn't seem
to have HIGHMEM there's no workaround for kmap_atomic() .

This patch adds the same as i386 HIGHMEM for !HIGHMEM.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 include/linux/highmem.h |   14 +++++++++++++-
 1 files changed, 13 insertions(+), 1 deletion(-)

Index: linux-2.6.19/include/linux/highmem.h
===================================================================
--- linux-2.6.19.orig/include/linux/highmem.h
+++ linux-2.6.19/include/linux/highmem.h
@@ -42,13 +42,25 @@ static inline void *kmap(struct page *pa
 
 #define kunmap(page) do { (void) (page); } while (0)
 
+#ifdef CONFIG_PREEMPT_RT
+/*
+ * kmap and kmunmap are above, and they don't really do anything
+ * interesting.
+ */
+# define kmap_atomic(page, idx)		kmap(page)
+# define kmap_atomic_pfn(pfn, idx)	kmap(pfn_to_page(pfn))
+# define kunmap_atomic(kvaddr, idx)	kunmap(kvaddr)
+#else
 #define kmap_atomic(page, idx) \
 	({ pagefault_disable(); page_address(page); })
 #define kunmap_atomic(addr, idx)	do { pagefault_enable(); } while (0)
 #define kmap_atomic_pfn(pfn, idx)	kmap_atomic(pfn_to_page(pfn), (idx))
-#define kmap_atomic_to_page(ptr)	virt_to_page(ptr)
 #endif
 
+#define kmap_atomic_to_page(ptr)	virt_to_page(ptr)
+
+#endif /* ARCH_HAS_KMAP */
+
 #endif /* CONFIG_HIGHMEM */
 
 /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */
--

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH -rt] update kmap_atomic on !HIGHMEM
  2006-12-27 19:35 [PATCH -rt] update kmap_atomic on !HIGHMEM Daniel Walker
@ 2006-12-27 20:54 ` Ingo Molnar
  2006-12-27 21:04   ` Daniel Walker
  2006-12-27 21:25 ` Ingo Molnar
  1 sibling, 1 reply; 10+ messages in thread
From: Ingo Molnar @ 2006-12-27 20:54 UTC (permalink / raw)
  To: Daniel Walker; +Cc: linux-kernel


* Daniel Walker <dwalker@mvista.com> wrote:

> I got some scheduling while atomic on x86-64 , [...]

please post those messages too.

	Ingo

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH -rt] update kmap_atomic on !HIGHMEM
  2006-12-27 20:54 ` Ingo Molnar
@ 2006-12-27 21:04   ` Daniel Walker
  0 siblings, 0 replies; 10+ messages in thread
From: Daniel Walker @ 2006-12-27 21:04 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: linux-kernel

On Wed, 2006-12-27 at 21:54 +0100, Ingo Molnar wrote:
> * Daniel Walker <dwalker@mvista.com> wrote:
> 
> > I got some scheduling while atomic on x86-64 , [...]
> 
> please post those messages too.
> 
> 	Ingo

Ok .. This is from 2.6.20-rc2-rt0 tho .

BUG: scheduling while atomic: kswapd0/0x00000001/244, CPU#1

Call Trace:
[<ffffffff80268f80>] __sched_text_start+0xb0/0xb9f
[<ffffffff8028fa8c>] task_rq_lock+0x4c/0x90
[<ffffffff8028fdd3>] rt_mutex_setprio+0xb3/0xd0
[<ffffffff802bb2c4>] add_preempt_count+0x14/0xf0
[<ffffffff802b1353>] task_blocks_on_rt_mutex+0x163/0x1d0
[<ffffffff80269da5>] schedule+0xe5/0x110
[<ffffffff8026afa2>] rt_spin_lock_slowlock+0x102/0x1b0
[<ffffffff802c9b71>] swap_duplicate+0x51/0x100
[<ffffffff802c94b2>] move_to_swap_cache+0x32/0x70
[<ffffffff802cf4ba>] shmem_writepage+0xaa/0x1a0
[<ffffffff802c35e0>] shrink_inactive_list+0x430/0x950
[<ffffffff802134f4>] shrink_zone+0xe4/0x110
[<ffffffff8025e629>] kswapd+0x379/0x510
[<ffffffff802a8270>] autoremove_wake_function+0x0/0x30
[<ffffffff8025e2b0>] kswapd+0x0/0x510
[<ffffffff80234c89>] kthread+0xd9/0x120
[<ffffffff8022981c>] schedule_tail+0xdc/0x130
[<ffffffff802a80a0>] keventd_create_kthread+0x0/0x90
[<ffffffff80265ef8>] child_rip+0xa/0x12
[<ffffffff802a80a0>] keventd_create_kthread+0x0/0x90
[<ffffffff80234bb0>] kthread+0x0/0x120
[<ffffffff80265eee>] child_rip+0x0/0x12

---------------------------
| preempt count: 00000001 ]
| 1-level deep critical section nesting:
----------------------------------------
 .. [<ffffffff802cc111>] .... shmem_swp_entry+0x31/0x1a0
 .....[<00000000>] ..   ( <= 0x0)



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH -rt] update kmap_atomic on !HIGHMEM
  2006-12-27 19:35 [PATCH -rt] update kmap_atomic on !HIGHMEM Daniel Walker
  2006-12-27 20:54 ` Ingo Molnar
@ 2006-12-27 21:25 ` Ingo Molnar
  2006-12-27 21:31   ` Ingo Molnar
                     ` (3 more replies)
  1 sibling, 4 replies; 10+ messages in thread
From: Ingo Molnar @ 2006-12-27 21:25 UTC (permalink / raw)
  To: Daniel Walker; +Cc: linux-kernel


* Daniel Walker <dwalker@mvista.com> wrote:

> I got some scheduling while atomic on x86-64 , and since x86-64 
> doesn't seem to have HIGHMEM there's no workaround for kmap_atomic() .
> 
> This patch adds the same as i386 HIGHMEM for !HIGHMEM.

the problem is that this does not disable pagefaulting while 
kmap-atomic. Could you try the patch below, does it solve the assert?

	Ingo

------------------------->
Subject: [patch] clean up the page fault disabling logic
From: Ingo Molnar <mingo@elte.hu>

decouple the pagefault-disabled logic from the preempt count.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/arm/mm/fault.c     |    2 +-
 arch/i386/mm/fault.c    |    2 +-
 arch/mips/mm/fault.c    |    2 +-
 arch/powerpc/mm/fault.c |    2 +-
 arch/x86_64/mm/fault.c  |    2 +-
 include/linux/sched.h   |    1 +
 include/linux/uaccess.h |   33 +++------------------------------
 kernel/fork.c           |    1 +
 mm/memory.c             |   20 ++++++++++++++++++++
 9 files changed, 30 insertions(+), 35 deletions(-)

Index: linux/arch/arm/mm/fault.c
===================================================================
--- linux.orig/arch/arm/mm/fault.c
+++ linux/arch/arm/mm/fault.c
@@ -230,7 +230,7 @@ do_page_fault(unsigned long addr, unsign
 	 * If we're in an interrupt or have no user
 	 * context, we must not take the fault..
 	 */
-	if (in_atomic() || !mm)
+	if (in_atomic() || !mm || current->pagefault_disabled)
 		goto no_context;
 
 	/*
Index: linux/arch/i386/mm/fault.c
===================================================================
--- linux.orig/arch/i386/mm/fault.c
+++ linux/arch/i386/mm/fault.c
@@ -382,7 +382,7 @@ fastcall notrace void __kprobes do_page_
 	 * If we're in an interrupt, have no user context or are running in an
 	 * atomic region then we must not take the fault..
 	 */
-	if (in_atomic() || !mm)
+	if (in_atomic() || !mm || current->pagefault_disabled)
 		goto bad_area_nosemaphore;
 
 	/* When running in the kernel we expect faults to occur only to
Index: linux/arch/mips/mm/fault.c
===================================================================
--- linux.orig/arch/mips/mm/fault.c
+++ linux/arch/mips/mm/fault.c
@@ -69,7 +69,7 @@ asmlinkage void do_page_fault(struct pt_
 	 * If we're in an interrupt or have no user
 	 * context, we must not take the fault..
 	 */
-	if (in_atomic() || !mm)
+	if (in_atomic() || !mm || current->pagefault_disabled)
 		goto bad_area_nosemaphore;
 
 	down_read(&mm->mmap_sem);
Index: linux/arch/powerpc/mm/fault.c
===================================================================
--- linux.orig/arch/powerpc/mm/fault.c
+++ linux/arch/powerpc/mm/fault.c
@@ -196,7 +196,7 @@ int __kprobes notrace do_page_fault(stru
 	}
 #endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/
 
-	if (in_atomic() || mm == NULL) {
+	if (in_atomic() || mm == NULL || current->pagefault_disabled) {
 		if (!user_mode(regs))
 			return SIGSEGV;
 		/* in_atomic() in user mode is really bad,
Index: linux/arch/x86_64/mm/fault.c
===================================================================
--- linux.orig/arch/x86_64/mm/fault.c
+++ linux/arch/x86_64/mm/fault.c
@@ -405,7 +405,7 @@ asmlinkage void __kprobes do_page_fault(
 	 * If we're in an interrupt or have no user
 	 * context, we must not take the fault..
 	 */
-	if (unlikely(in_atomic() || !mm))
+	if (unlikely(in_atomic() || !mm || current->pagefault_disabled))
 		goto bad_area_nosemaphore;
 
  again:
Index: linux/include/linux/sched.h
===================================================================
--- linux.orig/include/linux/sched.h
+++ linux/include/linux/sched.h
@@ -1147,6 +1147,7 @@ struct task_struct {
 	/* mutex deadlock detection */
 	struct mutex_waiter *blocked_on;
 #endif
+	int pagefault_disabled;
 #ifdef CONFIG_TRACE_IRQFLAGS
 	unsigned int irq_events;
 	int hardirqs_enabled;
Index: linux/include/linux/uaccess.h
===================================================================
--- linux.orig/include/linux/uaccess.h
+++ linux/include/linux/uaccess.h
@@ -6,37 +6,10 @@
 
 /*
  * These routines enable/disable the pagefault handler in that
- * it will not take any locks and go straight to the fixup table.
- *
- * They have great resemblance to the preempt_disable/enable calls
- * and in fact they are identical; this is because currently there is
- * no other way to make the pagefault handlers do this. So we do
- * disable preemption but we don't necessarily care about that.
+ * it will not take any MM locks and go straight to the fixup table.
  */
-static inline void pagefault_disable(void)
-{
-	inc_preempt_count();
-	/*
-	 * make sure to have issued the store before a pagefault
-	 * can hit.
-	 */
-	barrier();
-}
-
-static inline void pagefault_enable(void)
-{
-	/*
-	 * make sure to issue those last loads/stores before enabling
-	 * the pagefault handler again.
-	 */
-	barrier();
-	dec_preempt_count();
-	/*
-	 * make sure we do..
-	 */
-	barrier();
-	preempt_check_resched();
-}
+extern void pagefault_disable(void);
+extern void pagefault_enable(void);
 
 #ifndef ARCH_HAS_NOCACHE_UACCESS
 
Index: linux/kernel/fork.c
===================================================================
--- linux.orig/kernel/fork.c
+++ linux/kernel/fork.c
@@ -1128,6 +1128,7 @@ static struct task_struct *copy_process(
 	p->hardirq_context = 0;
 	p->softirq_context = 0;
 #endif
+	p->pagefault_disabled = 0;
 #ifdef CONFIG_LOCKDEP
 	p->lockdep_depth = 0; /* no locks held yet */
 	p->curr_chain_key = 0;
Index: linux/mm/memory.c
===================================================================
--- linux.orig/mm/memory.c
+++ linux/mm/memory.c
@@ -2481,6 +2481,26 @@ unlock:
 	return VM_FAULT_MINOR;
 }
 
+void pagefault_disable(void)
+{
+	current->pagefault_disabled++;
+	/*
+	 * make sure to have issued the store before a pagefault
+	 * can hit.
+	 */
+	barrier();
+}
+
+void pagefault_enable(void)
+{
+	/*
+	 * make sure to issue those last loads/stores before enabling
+	 * the pagefault handler again.
+	 */
+	barrier();
+	current->pagefault_disabled--;
+}
+
 /*
  * By the time we get here, we already hold the mm semaphore
  */

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH -rt] update kmap_atomic on !HIGHMEM
  2006-12-27 21:25 ` Ingo Molnar
@ 2006-12-27 21:31   ` Ingo Molnar
  2006-12-27 21:37     ` Daniel Walker
  2006-12-27 21:36   ` Daniel Walker
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 10+ messages in thread
From: Ingo Molnar @ 2006-12-27 21:31 UTC (permalink / raw)
  To: Daniel Walker; +Cc: linux-kernel


plus on i386 the fix below is needed as well.

	Ingo

---
 include/asm-i386/highmem.h |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

Index: linux/include/asm-i386/highmem.h
===================================================================
--- linux.orig/include/asm-i386/highmem.h
+++ linux/include/asm-i386/highmem.h
@@ -81,9 +81,9 @@ struct page *__kmap_atomic_to_page(void 
  * on PREEMPT_RT kmap_atomic() is a wrapper that uses kmap():
  */
 #ifdef CONFIG_PREEMPT_RT
-#  define kmap_atomic(page, type)	kmap(page)
-#  define kmap_atomic_pfn(pfn, type)	kmap(pfn_to_page(pfn))
-#  define kunmap_atomic(kvaddr, type)	kunmap_virt(kvaddr)
+#  define kmap_atomic(page, type)	({ pagefault_disable(); kmap(page); })
+#  define kmap_atomic_pfn(pfn, type)	kmap_atomic(pfn_to_page(pfn), type)
+#  define kunmap_atomic(kvaddr, type)	do { pagefault_enable(); kunmap_virt(kvaddr); } while (0)
 #  define kmap_atomic_to_page(kvaddr)	kmap_to_page(kvaddr)
 #else
 # define kmap_atomic(page, type)	__kmap_atomic(page, type)

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH -rt] update kmap_atomic on !HIGHMEM
  2006-12-27 21:25 ` Ingo Molnar
  2006-12-27 21:31   ` Ingo Molnar
@ 2006-12-27 21:36   ` Daniel Walker
  2006-12-27 21:54   ` Daniel Walker
  2006-12-28  0:05   ` Daniel Walker
  3 siblings, 0 replies; 10+ messages in thread
From: Daniel Walker @ 2006-12-27 21:36 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: linux-kernel

On Wed, 2006-12-27 at 22:25 +0100, Ingo Molnar wrote:
> * Daniel Walker <dwalker@mvista.com> wrote:
> 
> > I got some scheduling while atomic on x86-64 , and since x86-64 
> > doesn't seem to have HIGHMEM there's no workaround for kmap_atomic() .
> > 
> > This patch adds the same as i386 HIGHMEM for !HIGHMEM.
> 
> the problem is that this does not disable pagefaulting while 
> kmap-atomic. Could you try the patch below, does it solve the assert?
> 

That goes for the other CONFIG_HIGHMEM changes also? I mean if we can't
do it here we shouldn't do it else where..

(note, I just used testscripts/ltpstress.sh from LTP to reproduce this.)

Daniel 


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH -rt] update kmap_atomic on !HIGHMEM
  2006-12-27 21:31   ` Ingo Molnar
@ 2006-12-27 21:37     ` Daniel Walker
  2006-12-27 21:41       ` Ingo Molnar
  0 siblings, 1 reply; 10+ messages in thread
From: Daniel Walker @ 2006-12-27 21:37 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: linux-kernel

On Wed, 2006-12-27 at 22:31 +0100, Ingo Molnar wrote:
> plus on i386 the fix below is needed as well.
> 

We do it on most other arches .. PowerPC , and I think ARM too.

Daniel


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH -rt] update kmap_atomic on !HIGHMEM
  2006-12-27 21:37     ` Daniel Walker
@ 2006-12-27 21:41       ` Ingo Molnar
  0 siblings, 0 replies; 10+ messages in thread
From: Ingo Molnar @ 2006-12-27 21:41 UTC (permalink / raw)
  To: Daniel Walker; +Cc: linux-kernel


* Daniel Walker <dwalker@mvista.com> wrote:

> On Wed, 2006-12-27 at 22:31 +0100, Ingo Molnar wrote:
> > plus on i386 the fix below is needed as well.
> > 
> 
> We do it on most other arches .. PowerPC , and I think ARM too.

I dont think they currently work with PREEMPT_RT and HIGHMEM enabled, 
but if/once they do they'll need a similar fix.

	Ingo

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH -rt] update kmap_atomic on !HIGHMEM
  2006-12-27 21:25 ` Ingo Molnar
  2006-12-27 21:31   ` Ingo Molnar
  2006-12-27 21:36   ` Daniel Walker
@ 2006-12-27 21:54   ` Daniel Walker
  2006-12-28  0:05   ` Daniel Walker
  3 siblings, 0 replies; 10+ messages in thread
From: Daniel Walker @ 2006-12-27 21:54 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: linux-kernel

On Wed, 2006-12-27 at 22:25 +0100, Ingo Molnar wrote:
> 
> +void pagefault_disable(void)
> +{
> +       current->pagefault_disabled++;
> +       /*
> +        * make sure to have issued the store before a pagefault
> +        * can hit.
> +        */
> +       barrier();
> +}
> +
> +void pagefault_enable(void)
> +{
> +       /*
> +        * make sure to issue those last loads/stores before enabling
> +        * the pagefault handler again.
> +        */
> +       barrier();
> +       current->pagefault_disabled--;
> +}
> +

I'll test it, but clearly I'm not going to get the same scheduling while
atomic using this change.. So may as well just put it in -rt and see if
something crashes ..

Daniel


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH -rt] update kmap_atomic on !HIGHMEM
  2006-12-27 21:25 ` Ingo Molnar
                     ` (2 preceding siblings ...)
  2006-12-27 21:54   ` Daniel Walker
@ 2006-12-28  0:05   ` Daniel Walker
  3 siblings, 0 replies; 10+ messages in thread
From: Daniel Walker @ 2006-12-28  0:05 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: linux-kernel

On Wed, 2006-12-27 at 22:25 +0100, Ingo Molnar wrote:
> * Daniel Walker <dwalker@mvista.com> wrote:
> 
> > I got some scheduling while atomic on x86-64 , and since x86-64 
> > doesn't seem to have HIGHMEM there's no workaround for kmap_atomic() .
> > 
> > This patch adds the same as i386 HIGHMEM for !HIGHMEM.
> 
> the problem is that this does not disable pagefaulting while 
> kmap-atomic. Could you try the patch below, does it solve the assert?
> 


It hasn't crashed after about an hour of stress.. One comment on the
patch tho , the pagefault_enable/pagefault_disable need module exports,
I saw the build complaining about them.

Daniel


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2006-12-28  0:06 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-12-27 19:35 [PATCH -rt] update kmap_atomic on !HIGHMEM Daniel Walker
2006-12-27 20:54 ` Ingo Molnar
2006-12-27 21:04   ` Daniel Walker
2006-12-27 21:25 ` Ingo Molnar
2006-12-27 21:31   ` Ingo Molnar
2006-12-27 21:37     ` Daniel Walker
2006-12-27 21:41       ` Ingo Molnar
2006-12-27 21:36   ` Daniel Walker
2006-12-27 21:54   ` Daniel Walker
2006-12-28  0:05   ` Daniel Walker

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®