All of lore.kernel.org
 help / color / mirror / Atom feed
* needs caching for fixmap
@ 2008-02-15  4:06 Hideo Saito
  2008-02-26  6:49 ` Paul Mundt
  0 siblings, 1 reply; 2+ messages in thread
From: Hideo Saito @ 2008-02-15  4:06 UTC (permalink / raw)
  To: linux-sh

Hi Paul,

When I start up on linux-2.6.24 for SH7780, there are many assertion failed as follows although kernel doesn't hang up.
It seems that the failed address is fix-mapping pages and the entry on UTLB is replaced before using it at |copy_page_slow|.

[   17.667186] Unable to handle kernel paging request at virtual address dfff1400
[   17.718559] pc = 8804aba8
[   17.749845] *pde = 00000000
[   17.783201] Oops: 0000 [#1]
[   17.816551] Modules linked in:
[   17.853062] 
[   17.870799] Pid : 839, Comm:      default.hotplug
[   17.927145] PC is at copy_page_slow+0x10/0x4c
[   17.979295] PC  : 8804aba8 SP  : 8fafde60 SR  : 40008100 TEA : dfff1400    Not tainted
[   18.074226] R0  : 887353e0 R1  : 00000000 R2  : 0000000a R3  : 0000007b
[   18.153509] R4  : 00000028 R5  : 00000029 R6  : 0000003b R7  : 00000026
[   18.232795] R8  : dfff2000 R9  : 0fcbc53e R10 : 88735400 R11 : dfff1400
[   18.312076] R12 : 004b9108 R13 : 882c4140 R14 : 0fcbc55c
[   18.375712] MACH: 00000000 MACL: 00000000 GBR : 2976f658 PR  : 8804b794
[   18.454989] 
[   18.454996] Call trace: 
[   18.502980] [<88080f9e>] do_wp_page+0x28a/0x442
[   18.557227] [<88081fb8>] handle_mm_fault+0x538/0x5b0
[   18.616691] [<88061468>] __rcu_process_callbacks+0x144/0x206
[   18.684494] [<8804a7ee>] do_page_fault+0xa6/0x2c0
[   18.740829] [<8805637c>] __do_softirq+0x3c/0x98
[   18.795074] [<88056402>] do_softirq+0x2a/0x58
[   18.847234] [<880460e0>] ret_from_exception+0x0/0x8
[   18.905654] [<880460e0>] ret_from_exception+0x0/0x8
[   18.964075] [<8804e0bc>] schedule_tail+0x0/0x58
[   19.018319] [<8808efbc>] filp_close+0x30/0x68
[   19.070479] [<8808efce>] filp_close+0x42/0x68
[   19.122638] [<880460e0>] ret_from_exception+0x0/0x8
[   19.181058] [<880460e0>] ret_from_exception+0x0/0x8
[   19.239484] 

Following changes is available for this problem.

--- ./arch/sh/mm/pg-sh4.c.org	2008-01-25 07:58:37.000000000 +0900
+++ ./arch/sh/mm/pg-sh4.c	2008-02-06 17:19:58.000000000 +0900
@@ -11,27 +11,45 @@
 #include <linux/fs.h>
 #include <linux/highmem.h>
 #include <linux/module.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
 #define CACHE_ALIAS (current_cpu_data.dcache.alias_mask)
 
+pte_t fix_cmap_ptes[FIX_N_COLOURS];
+
+void put_fix_cmap_ptes(enum fixed_addresses idx, pte_t pte)
+{
+	fix_cmap_ptes[idx] = pte;
+}
+
+pte_t get_fix_cmap_ptes(unsigned long addr)
+{
+	int idx = __virt_to_fix(addr);
+	static pte_t null;
+
+	if (idx > 0 && idx <= FIX_N_COLOURS)
+		return fix_cmap_ptes[FIX_CMAP_END - idx];
+	return null;
+}
+
 static inline void *kmap_coherent(struct page *page, unsigned long addr)
 {
 	enum fixed_addresses idx;
 	unsigned long vaddr, flags;
 	pte_t pte;
 
 	inc_preempt_count();
 
 	idx = (addr & current_cpu_data.dcache.alias_mask) >> PAGE_SHIFT;
 	vaddr = __fix_to_virt(FIX_CMAP_END - idx);
 	pte = mk_pte(page, PAGE_KERNEL);
+	put_fix_cmap_ptes(idx, pte);
 
 	local_irq_save(flags);
 	flush_tlb_one(get_asid(), vaddr);
 	local_irq_restore(flags);
 
 	update_mmu_cache(NULL, vaddr, pte);
 
 	return (void *)vaddr;
--- ./arch/sh/mm/fault.c.org	2008-01-25 07:58:37.000000000 +0900
+++ ./arch/sh/mm/fault.c	2008-02-15 12:00:43.000000000 +0900
@@ -266,16 +266,25 @@ asmlinkage int __kprobes __do_page_fault
 
 	/*
 	 * We don't take page faults for P1, P2, and parts of P4, these
 	 * are always mapped, whether it be due to legacy behaviour in
 	 * 29-bit mode, or due to PMB configuration in 32-bit mode.
 	 */
 	if (address >= P3SEG && address < P3_ADDR_MAX) {
 		pgd = pgd_offset_k(address);
+		if (*(int *) pgd = 0) {
+			pte_t get_fix_cmap_ptes(unsigned long addr);
+
+			entry = get_fix_cmap_ptes(address);
+			if (!pte_none(entry)) {
+				update_mmu_cache(NULL, address, entry);
+				return 0;
+			}
+		}
 	} else {
 		if (unlikely(address >= TASK_SIZE || !current->mm))
 			return 1;
 
 		pgd = pgd_offset(current->mm, address);
 	}
 
 	pud = pud_offset(pgd, address);

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

* Re: needs caching for fixmap
  2008-02-15  4:06 needs caching for fixmap Hideo Saito
@ 2008-02-26  6:49 ` Paul Mundt
  0 siblings, 0 replies; 2+ messages in thread
From: Paul Mundt @ 2008-02-26  6:49 UTC (permalink / raw)
  To: linux-sh

On Fri, Feb 15, 2008 at 01:06:31PM +0900, Hideo Saito wrote:
> When I start up on linux-2.6.24 for SH7780, there are many assertion
> failed as follows although kernel doesn't hang up.  It seems that the
> failed address is fix-mapping pages and the entry on UTLB is replaced
> before using it at |copy_page_slow|.
> 
[snip]

> --- ./arch/sh/mm/fault.c.org	2008-01-25 07:58:37.000000000 +0900
> +++ ./arch/sh/mm/fault.c	2008-02-15 12:00:43.000000000 +0900
> @@ -266,16 +266,25 @@ asmlinkage int __kprobes __do_page_fault
>  
>  	/*
>  	 * We don't take page faults for P1, P2, and parts of P4, these
>  	 * are always mapped, whether it be due to legacy behaviour in
>  	 * 29-bit mode, or due to PMB configuration in 32-bit mode.
>  	 */
>  	if (address >= P3SEG && address < P3_ADDR_MAX) {
>  		pgd = pgd_offset_k(address);
> +		if (*(int *) pgd = 0) {
> +			pte_t get_fix_cmap_ptes(unsigned long addr);
> +
> +			entry = get_fix_cmap_ptes(address);
> +			if (!pte_none(entry)) {
> +				update_mmu_cache(NULL, address, entry);
> +				return 0;
> +			}
> +		}
>  	} else {
>  		if (unlikely(address >= TASK_SIZE || !current->mm))
>  			return 1;
>  
>  		pgd = pgd_offset(current->mm, address);
>  	}
>  
>  	pud = pud_offset(pgd, address);

We really don't want to shove this in the __do_page_fault() path. We also
do not need a cache for each of the possible colours, how does something
like this look?

---

 arch/sh/mm/init.c        |   12 +++++++++---
 arch/sh/mm/pg-sh4.c      |   17 +++++++++++++++++
 include/asm-sh/pgtable.h |    6 ++++++
 3 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index e2ed6dd..de54536 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -169,6 +169,7 @@ void __init page_table_range_init(unsigned long start, unsigned long end,
 void __init paging_init(void)
 {
 	unsigned long max_zone_pfns[MAX_NR_ZONES];
+	unsigned long vaddr;
 	int nid;
 
 	/* We don't need to map the kernel through the TLB, as
@@ -180,10 +181,15 @@ void __init paging_init(void)
 	 * check for a null value. */
 	set_TTB(swapper_pg_dir);
 
-	/* Populate the relevant portions of swapper_pg_dir so that
+	/*
+	 * Populate the relevant portions of swapper_pg_dir so that
 	 * we can use the fixmap entries without calling kmalloc.
-	 * pte's will be filled in by __set_fixmap(). */
-	page_table_range_init(FIXADDR_START, FIXADDR_TOP, swapper_pg_dir);
+	 * pte's will be filled in by __set_fixmap().
+	 */
+	vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
+	page_table_range_init(vaddr, 0, swapper_pg_dir);
+
+	kmap_coherent_init();
 
 	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
 
diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c
index 8c7a9ca..3ecec1d 100644
--- a/arch/sh/mm/pg-sh4.c
+++ b/arch/sh/mm/pg-sh4.c
@@ -7,6 +7,7 @@
  * Released under the terms of the GNU GPL v2.0.
  */
 #include <linux/mm.h>
+#include <linux/init.h>
 #include <linux/mutex.h>
 #include <linux/fs.h>
 #include <linux/highmem.h>
@@ -16,6 +17,20 @@
 
 #define CACHE_ALIAS (current_cpu_data.dcache.alias_mask)
 
+#define kmap_get_fixmap_pte(vaddr)					\
+	pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), (vaddr))
+
+static pte_t *kmap_coherent_pte;
+
+void __init kmap_coherent_init(void)
+{
+	unsigned long vaddr;
+
+	/* cache the first coherent kmap pte */
+	vaddr = __fix_to_virt(FIX_CMAP_BEGIN);
+	kmap_coherent_pte = kmap_get_fixmap_pte(vaddr);
+}
+
 static inline void *kmap_coherent(struct page *page, unsigned long addr)
 {
 	enum fixed_addresses idx;
@@ -34,6 +49,8 @@ static inline void *kmap_coherent(struct page *page, unsigned long addr)
 
 	update_mmu_cache(NULL, vaddr, pte);
 
+	set_pte(kmap_coherent_pte - (FIX_CMAP_END - idx), pte);
+
 	return (void *)vaddr;
 }
 
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
index a4a8f8b..081c1be 100644
--- a/include/asm-sh/pgtable.h
+++ b/include/asm-sh/pgtable.h
@@ -147,6 +147,12 @@ extern void paging_init(void);
 extern void page_table_range_init(unsigned long start, unsigned long end,
 				  pgd_t *pgd);
 
+#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_CPU_SH4) && defined(CONFIG_MMU)
+extern void kmap_coherent_init(void);
+#else
+#define kmap_coherent_init()	do { } while (0)
+#endif
+
 #include <asm-generic/pgtable.h>
 
 #endif /* __ASM_SH_PGTABLE_H */

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

end of thread, other threads:[~2008-02-26  6:49 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-02-15  4:06 needs caching for fixmap Hideo Saito
2008-02-26  6:49 ` Paul Mundt

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.