From: Peter Zijlstra <peterz@infradead.org>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>,
"hugh.dickins" <hugh.dickins@tiscali.co.uk>,
Ingo Molnar <mingo@elte.hu>, David Howells <dhowells@redhat.com>,
lkml <linux-kernel@vger.kernel.org>,
linux-arch <linux-arch@vger.kernel.org>
Subject: Re: [RFC][PATCH 0/4] stack based kmap_atomic -v2
Date: Fri, 09 Oct 2009 15:05:30 +0200 [thread overview]
Message-ID: <1255093530.8802.64.camel@laptop> (raw)
In-Reply-To: <20091008232226.768382977@chello.nl>
On Fri, 2009-10-09 at 01:22 +0200, Peter Zijlstra wrote:
>
> Maybe FRV can do a kind of kmap-stack switch on (soft)irq enter/exit
> in order to stay below 5 entries.
David, would something like the below work for you?
You'd need to disallow nested hardirqs, but I'm not sure FRV suffers
that particular issue?
---
Index: linux-2.6/include/linux/highmem.h
===================================================================
--- linux-2.6.orig/include/linux/highmem.h
+++ linux-2.6/include/linux/highmem.h
@@ -83,6 +83,30 @@ static inline void *kmap_atomic(struct p
#endif /* CONFIG_HIGHMEM */
+enum kmap_context {
+ KMAP_USER = 0,
+ KMAP_SOFTIRQ,
+ KMAP_IRQ,
+ KMAP_NMI,
+ KMAP_CONTEXT_NR,
+}
+
+#if !defined(CONFIG_HIGHMEM) || !defined(ARCH_HAS_KMAP_SWITCH)
+/*
+ * Routines the arch can use to save/restore kmap_atomic stacks.
+ *
+ * This can be useful when an arch has limited kmap_atomic slots
+ * and wants to deal with context nesting.
+ */
+static inline void kmap_atomic_save(enum kmap_context kctx)
+{
+}
+
+static inline void kmap_atomic_restore(enum kmap_context kctx)
+{
+}
+#endif
+
/* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */
#ifndef clear_user_highpage
static inline void clear_user_highpage(struct page *page, unsigned long vaddr)
Index: linux-2.6/kernel/softirq.c
===================================================================
--- linux-2.6.orig/kernel/softirq.c
+++ linux-2.6/kernel/softirq.c
@@ -283,6 +283,8 @@ void irq_enter(void)
tick_check_idle(cpu);
} else
__irq_enter();
+
+ kmap_atomic_save(KMAP_IRQ);
}
#ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
@@ -296,11 +298,15 @@ void irq_enter(void)
*/
void irq_exit(void)
{
+ kmap_atomic_restore(KMAP_IRQ);
account_system_vtime(current);
trace_hardirq_exit();
sub_preempt_count(IRQ_EXIT_OFFSET);
- if (!in_interrupt() && local_softirq_pending())
+ if (!in_interrupt() && local_softirq_pending()) {
+ kmap_atomic_save(KMAP_SOFTIRQ);
invoke_softirq();
+ kmap_atomic_restore(KMAP_SOFTIRQ);
+ }
#ifdef CONFIG_NO_HZ
/* Make sure that timer wheel updates are propagated */
Index: linux-2.6/arch/frv/include/asm/highmem.h
===================================================================
--- linux-2.6.orig/arch/frv/include/asm/highmem.h
+++ linux-2.6/arch/frv/include/asm/highmem.h
@@ -121,20 +121,13 @@ static inline void *kmap_atomic(struct p
type = kmap_atomic_idx_push();
paddr = page_to_phys(page);
- switch (type) {
- case 0: return __kmap_atomic_primary(0, paddr, 2);
- case 1: return __kmap_atomic_primary(1, paddr, 3);
- case 2: return __kmap_atomic_primary(2, paddr, 4);
- case 3: return __kmap_atomic_primary(3, paddr, 5);
+ switch (type + 4) {
case 4: return __kmap_atomic_primary(4, paddr, 6);
case 5: return __kmap_atomic_primary(5, paddr, 7);
case 6: return __kmap_atomic_primary(6, paddr, 8);
case 7: return __kmap_atomic_primary(7, paddr, 9);
case 8: return __kmap_atomic_primary(8, paddr, 10);
- case 9 ... 9 + NR_TLB_LINES - 1:
- return __kmap_atomic_secondary(type - 9, paddr);
-
default:
BUG();
return NULL;
@@ -156,27 +149,53 @@ do { \
static inline void kunmap_atomic(void *kvaddr)
{
int type = kmap_atomic_idx_pop();
- switch (type) {
- case 0: __kunmap_atomic_primary(0, 2); break;
- case 1: __kunmap_atomic_primary(1, 3); break;
- case 2: __kunmap_atomic_primary(2, 4); break;
- case 3: __kunmap_atomic_primary(3, 5); break;
+ switch (type+4) {
case 4: __kunmap_atomic_primary(4, 6); break;
case 5: __kunmap_atomic_primary(5, 7); break;
case 6: __kunmap_atomic_primary(6, 8); break;
case 7: __kunmap_atomic_primary(7, 9); break;
case 8: __kunmap_atomic_primary(8, 10); break;
- case 9 ... 9 + NR_TLB_LINES - 1:
- __kunmap_atomic_secondary(type - 9, kvaddr);
- break;
-
default:
BUG();
}
pagefault_enable();
}
+#define ARCH_HAS_KMAP_SWITCH
+
+struct kmap_atomic_context {
+ pte_t maps[KM_TYPE_NR];
+ int nr;
+};
+
+DECLARE_PER_CPU(struct kmap_atomic_context, kmap_ctxs[KMAP_CONTEXT_NR]);
+
+static inline void kmap_atomic_save(enum kmap_context kctx)
+{
+ struct kmap_atomic_context *kac = &__get_cpu_var(kmap_ctxs)[kctx];
+ int *idx = &__get_cpu_var(__kmap_atomic_idx);
+
+ kac->nr = *idx;
+
+ if (*idx) {
+ /* XXX save maps */ ;
+ *idx = 0;
+ }
+}
+
+static inline void kmap_atomic_restore(enum kmap_context kctx)
+{
+ struct kmap_atomic_context *kac = &__get_cpu_var(kmap_ctxs)[kctx];
+ int *idx = &__get_cpu_var(__kmap_atomic_idx);
+
+ *idx = kac->nr;
+ if (*idx) {
+ /* XXX restore maps */ ;
+ }
+}
+
+
#endif /* !__ASSEMBLY__ */
#endif /* __KERNEL__ */
Index: linux-2.6/arch/frv/include/asm/kmap_types.h
===================================================================
--- linux-2.6.orig/arch/frv/include/asm/kmap_types.h
+++ linux-2.6/arch/frv/include/asm/kmap_types.h
@@ -3,27 +3,8 @@
#define _ASM_KMAP_TYPES_H
enum km_type {
- /* arch specific kmaps - change the numbers attached to these at your peril */
- __KM_CACHE, /* cache flush page attachment point */
- __KM_PGD, /* current page directory */
- __KM_ITLB_PTD, /* current instruction TLB miss page table lookup */
- __KM_DTLB_PTD, /* current data TLB miss page table lookup */
-
/* general kmaps */
- KM_BOUNCE_READ,
- KM_SKB_SUNRPC_DATA,
- KM_SKB_DATA_SOFTIRQ,
- KM_USER0,
- KM_USER1,
- KM_BIO_SRC_IRQ,
- KM_BIO_DST_IRQ,
- KM_PTE0,
- KM_PTE1,
- KM_IRQ0,
- KM_IRQ1,
- KM_SOFTIRQ0,
- KM_SOFTIRQ1,
- KM_TYPE_NR
+ KM_TYPE_NR = 5
};
#endif
next prev parent reply other threads:[~2009-10-09 13:06 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-10-08 23:22 [RFC][PATCH 0/4] stack based kmap_atomic -v2 Peter Zijlstra
2009-10-08 23:22 ` Peter Zijlstra
2009-10-08 23:22 ` [RFC][PATCH 1/4] mm: strictly nested kmap_atomic Peter Zijlstra
2009-10-08 23:22 ` Peter Zijlstra
2009-10-08 23:22 ` [RFC][PATCH 2/4] mm: stack based kmap_atomic Peter Zijlstra
2009-10-08 23:22 ` Peter Zijlstra
2009-10-19 3:08 ` Raja R Harinath
2009-10-19 3:08 ` Raja R Harinath
2009-10-08 23:22 ` [RFC][PATCH 3/4] mm: remove KM_type argument Peter Zijlstra
2009-10-08 23:22 ` Peter Zijlstra
2009-10-08 23:22 ` [RFC][PATCH 4/4] mm: remove KM_type argument fallout Peter Zijlstra
2009-10-08 23:22 ` Peter Zijlstra
2009-10-09 13:05 ` Peter Zijlstra [this message]
2009-10-09 15:10 ` [RFC][PATCH 0/4] stack based kmap_atomic -v2 David Howells
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=1255093530.8802.64.camel@laptop \
--to=peterz@infradead.org \
--cc=akpm@linux-foundation.org \
--cc=dhowells@redhat.com \
--cc=hugh.dickins@tiscali.co.uk \
--cc=linux-arch@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=torvalds@linux-foundation.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.