* 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.