* [PATCH v2 1/6] MIPS: Sync after cacheflush on BMIPS processors
@ 2011-01-14 1:52 Kevin Cernekee
2011-01-14 1:52 ` Kevin Cernekee
` (5 more replies)
0 siblings, 6 replies; 12+ messages in thread
From: Kevin Cernekee @ 2011-01-14 1:52 UTC (permalink / raw)
To: Ralf Baechle; +Cc: macro, skuribay, raiko, linux-mips, linux-kernel
On BMIPS processors, cache writeback operations may complete before the
data has actually been written out to memory. Subsequent uncached reads
(or I/O operations) may see stale data unless a sync instruction is
executed after the writeback loop.
Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
---
arch/mips/include/asm/hazards.h | 21 +++++++++++++++++++++
arch/mips/mm/c-r4k.c | 5 +++++
2 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/arch/mips/include/asm/hazards.h b/arch/mips/include/asm/hazards.h
index 4e33216..655da05 100644
--- a/arch/mips/include/asm/hazards.h
+++ b/arch/mips/include/asm/hazards.h
@@ -270,4 +270,25 @@ ASMMACRO(disable_fpu_hazard,
)
#endif
+/*
+ * Some processors will "pipeline" cache writeback operations, and need an
+ * extra sync instruction to ensure that they are actually flushed out to
+ * memory. Performing an uncached read (or an I/O operation) without the
+ * flush may cause stale data to be fetched.
+ */
+
+#if defined(CONFIG_CPU_BMIPS3300) || defined(CONFIG_CPU_BMIPS4350) || \
+ defined(CONFIG_CPU_BMIPS4380) || defined(CONFIG_CPU_BMIPS5000)
+
+#define cacheflush_hazard() \
+do { \
+ __sync(); \
+} while (0)
+
+#else
+
+#define cacheflush_hazard() do { } while (0)
+
+#endif
+
#endif /* _ASM_HAZARDS_H */
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index b4923a7..6c113cd 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -33,6 +33,7 @@
#include <asm/mmu_context.h>
#include <asm/war.h>
#include <asm/cacheflush.h> /* for run_uncached() */
+#include <asm/hazards.h>
/*
@@ -604,6 +605,7 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
r4k_blast_scache();
else
blast_scache_range(addr, addr + size);
+ cacheflush_hazard();
return;
}
@@ -620,6 +622,7 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
}
bc_wback_inv(addr, size);
+ cacheflush_hazard();
}
static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
@@ -647,6 +650,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
(addr + size - 1) & almask);
blast_inv_scache_range(addr, addr + size);
}
+ cacheflush_hazard();
return;
}
@@ -663,6 +667,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
}
bc_inv(addr, size);
+ cacheflush_hazard();
}
#endif /* CONFIG_DMA_NONCOHERENT */
--
1.7.0.4
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v2 1/6] MIPS: Sync after cacheflush on BMIPS processors 2011-01-14 1:52 [PATCH v2 1/6] MIPS: Sync after cacheflush on BMIPS processors Kevin Cernekee @ 2011-01-14 1:52 ` Kevin Cernekee 2011-01-14 1:52 ` [PATCH v2 2/6] MIPS: pfn_valid() is broken on low memory HIGHMEM systems Kevin Cernekee ` (4 subsequent siblings) 5 siblings, 0 replies; 12+ messages in thread From: Kevin Cernekee @ 2011-01-14 1:52 UTC (permalink / raw) To: Ralf Baechle; +Cc: macro, skuribay, raiko, linux-mips, linux-kernel On BMIPS processors, cache writeback operations may complete before the data has actually been written out to memory. Subsequent uncached reads (or I/O operations) may see stale data unless a sync instruction is executed after the writeback loop. Signed-off-by: Kevin Cernekee <cernekee@gmail.com> --- arch/mips/include/asm/hazards.h | 21 +++++++++++++++++++++ arch/mips/mm/c-r4k.c | 5 +++++ 2 files changed, 26 insertions(+), 0 deletions(-) diff --git a/arch/mips/include/asm/hazards.h b/arch/mips/include/asm/hazards.h index 4e33216..655da05 100644 --- a/arch/mips/include/asm/hazards.h +++ b/arch/mips/include/asm/hazards.h @@ -270,4 +270,25 @@ ASMMACRO(disable_fpu_hazard, ) #endif +/* + * Some processors will "pipeline" cache writeback operations, and need an + * extra sync instruction to ensure that they are actually flushed out to + * memory. Performing an uncached read (or an I/O operation) without the + * flush may cause stale data to be fetched. + */ + +#if defined(CONFIG_CPU_BMIPS3300) || defined(CONFIG_CPU_BMIPS4350) || \ + defined(CONFIG_CPU_BMIPS4380) || defined(CONFIG_CPU_BMIPS5000) + +#define cacheflush_hazard() \ +do { \ + __sync(); \ +} while (0) + +#else + +#define cacheflush_hazard() do { } while (0) + +#endif + #endif /* _ASM_HAZARDS_H */ diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index b4923a7..6c113cd 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -33,6 +33,7 @@ #include <asm/mmu_context.h> #include <asm/war.h> #include <asm/cacheflush.h> /* for run_uncached() */ +#include <asm/hazards.h> /* @@ -604,6 +605,7 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size) r4k_blast_scache(); else blast_scache_range(addr, addr + size); + cacheflush_hazard(); return; } @@ -620,6 +622,7 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size) } bc_wback_inv(addr, size); + cacheflush_hazard(); } static void r4k_dma_cache_inv(unsigned long addr, unsigned long size) @@ -647,6 +650,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size) (addr + size - 1) & almask); blast_inv_scache_range(addr, addr + size); } + cacheflush_hazard(); return; } @@ -663,6 +667,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size) } bc_inv(addr, size); + cacheflush_hazard(); } #endif /* CONFIG_DMA_NONCOHERENT */ -- 1.7.0.4 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v2 2/6] MIPS: pfn_valid() is broken on low memory HIGHMEM systems 2011-01-14 1:52 [PATCH v2 1/6] MIPS: Sync after cacheflush on BMIPS processors Kevin Cernekee 2011-01-14 1:52 ` Kevin Cernekee @ 2011-01-14 1:52 ` Kevin Cernekee 2011-01-14 1:52 ` Kevin Cernekee 2011-01-14 1:52 ` [PATCH v2 RESEND 3/6] MIPS: Move FIXADDR_TOP into spaces.h Kevin Cernekee ` (3 subsequent siblings) 5 siblings, 1 reply; 12+ messages in thread From: Kevin Cernekee @ 2011-01-14 1:52 UTC (permalink / raw) To: Ralf Baechle; +Cc: ddaney, linux-mips, linux-kernel pfn_valid() compares the PFN to max_mapnr: __pfn >= min_low_pfn && __pfn < max_mapnr; On HIGHMEM kernels, highend_pfn is used to set the value of max_mapnr. Unfortunately, highend_pfn is left at zero if the system does not actually have enough RAM to reach into the HIGHMEM range. This causes pfn_valid() to always return false, and when debug checks are enabled the kernel will fail catastrophically: Memory: 22432k/32768k available (2249k kernel code, 10336k reserved, 653k data, 1352k init, 0k highmem) NR_IRQS:128 kfree_debugcheck: out of range ptr 81c02900h. Kernel bug detected[#1]: Cpu 0 $ 0 : 00000000 10008400 00000034 00000000 $ 4 : 8003e160 802a0000 8003e160 00000000 $ 8 : 00000000 0000003e 00000747 00000747 ... On such a configuration, max_low_pfn should be used to set max_mapnr. Signed-off-by: Kevin Cernekee <cernekee@gmail.com> --- arch/mips/mm/init.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 2efcbd2..45447cd 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -370,7 +370,7 @@ void __init mem_init(void) #ifdef CONFIG_DISCONTIGMEM #error "CONFIG_HIGHMEM and CONFIG_DISCONTIGMEM dont work together yet" #endif - max_mapnr = highend_pfn; + max_mapnr = highend_pfn ? highend_pfn : max_low_pfn; #else max_mapnr = max_low_pfn; #endif -- 1.7.0.4 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v2 2/6] MIPS: pfn_valid() is broken on low memory HIGHMEM systems 2011-01-14 1:52 ` [PATCH v2 2/6] MIPS: pfn_valid() is broken on low memory HIGHMEM systems Kevin Cernekee @ 2011-01-14 1:52 ` Kevin Cernekee 0 siblings, 0 replies; 12+ messages in thread From: Kevin Cernekee @ 2011-01-14 1:52 UTC (permalink / raw) To: Ralf Baechle; +Cc: ddaney, linux-mips, linux-kernel pfn_valid() compares the PFN to max_mapnr: __pfn >= min_low_pfn && __pfn < max_mapnr; On HIGHMEM kernels, highend_pfn is used to set the value of max_mapnr. Unfortunately, highend_pfn is left at zero if the system does not actually have enough RAM to reach into the HIGHMEM range. This causes pfn_valid() to always return false, and when debug checks are enabled the kernel will fail catastrophically: Memory: 22432k/32768k available (2249k kernel code, 10336k reserved, 653k data, 1352k init, 0k highmem) NR_IRQS:128 kfree_debugcheck: out of range ptr 81c02900h. Kernel bug detected[#1]: Cpu 0 $ 0 : 00000000 10008400 00000034 00000000 $ 4 : 8003e160 802a0000 8003e160 00000000 $ 8 : 00000000 0000003e 00000747 00000747 ... On such a configuration, max_low_pfn should be used to set max_mapnr. Signed-off-by: Kevin Cernekee <cernekee@gmail.com> --- arch/mips/mm/init.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 2efcbd2..45447cd 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -370,7 +370,7 @@ void __init mem_init(void) #ifdef CONFIG_DISCONTIGMEM #error "CONFIG_HIGHMEM and CONFIG_DISCONTIGMEM dont work together yet" #endif - max_mapnr = highend_pfn; + max_mapnr = highend_pfn ? highend_pfn : max_low_pfn; #else max_mapnr = max_low_pfn; #endif -- 1.7.0.4 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v2 RESEND 3/6] MIPS: Move FIXADDR_TOP into spaces.h 2011-01-14 1:52 [PATCH v2 1/6] MIPS: Sync after cacheflush on BMIPS processors Kevin Cernekee 2011-01-14 1:52 ` Kevin Cernekee 2011-01-14 1:52 ` [PATCH v2 2/6] MIPS: pfn_valid() is broken on low memory HIGHMEM systems Kevin Cernekee @ 2011-01-14 1:52 ` Kevin Cernekee 2011-01-14 1:52 ` Kevin Cernekee 2011-01-14 1:52 ` [PATCH v4 RESEND 4/6] MIPS: HIGHMEM DMA on noncoherent MIPS32 processors Kevin Cernekee ` (2 subsequent siblings) 5 siblings, 1 reply; 12+ messages in thread From: Kevin Cernekee @ 2011-01-14 1:52 UTC (permalink / raw) To: Ralf Baechle; +Cc: anemo, linux-mips, linux-kernel Memory maps and addressing quirks are normally defined in <spaces.h>. There are already three targets that need to override FIXADDR_TOP, and others exist. This will be a cleaner approach than adding lots of ifdefs in fixmap.h . Signed-off-by: Kevin Cernekee <cernekee@gmail.com> --- arch/mips/include/asm/fixmap.h | 10 +--------- arch/mips/include/asm/mach-bcm63xx/spaces.h | 17 +++++++++++++++++ arch/mips/include/asm/mach-generic/spaces.h | 4 ++++ arch/mips/include/asm/mach-tx39xx/spaces.h | 17 +++++++++++++++++ arch/mips/include/asm/mach-tx49xx/spaces.h | 17 +++++++++++++++++ 5 files changed, 56 insertions(+), 9 deletions(-) create mode 100644 arch/mips/include/asm/mach-bcm63xx/spaces.h create mode 100644 arch/mips/include/asm/mach-tx39xx/spaces.h create mode 100644 arch/mips/include/asm/mach-tx49xx/spaces.h diff --git a/arch/mips/include/asm/fixmap.h b/arch/mips/include/asm/fixmap.h index 0b89b83..98bcc98 100644 --- a/arch/mips/include/asm/fixmap.h +++ b/arch/mips/include/asm/fixmap.h @@ -14,6 +14,7 @@ #define _ASM_FIXMAP_H #include <asm/page.h> +#include <spaces.h> #ifdef CONFIG_HIGHMEM #include <linux/threads.h> #include <asm/kmap_types.h> @@ -67,15 +68,6 @@ enum fixed_addresses { * the start of the fixmap, and leave one page empty * at the top of mem.. */ -#ifdef CONFIG_BCM63XX -#define FIXADDR_TOP ((unsigned long)(long)(int)0xff000000) -#else -#if defined(CONFIG_CPU_TX39XX) || defined(CONFIG_CPU_TX49XX) -#define FIXADDR_TOP ((unsigned long)(long)(int)(0xff000000 - 0x20000)) -#else -#define FIXADDR_TOP ((unsigned long)(long)(int)0xfffe0000) -#endif -#endif #define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) #define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) diff --git a/arch/mips/include/asm/mach-bcm63xx/spaces.h b/arch/mips/include/asm/mach-bcm63xx/spaces.h new file mode 100644 index 0000000..61e750f --- /dev/null +++ b/arch/mips/include/asm/mach-bcm63xx/spaces.h @@ -0,0 +1,17 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle + * Copyright (C) 2000, 2002 Maciej W. Rozycki + * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_BCM63XX_SPACES_H +#define _ASM_BCM63XX_SPACES_H + +#define FIXADDR_TOP ((unsigned long)(long)(int)0xff000000) + +#include <asm/mach-generic/spaces.h> + +#endif /* __ASM_BCM63XX_SPACES_H */ diff --git a/arch/mips/include/asm/mach-generic/spaces.h b/arch/mips/include/asm/mach-generic/spaces.h index c9fa4b1..d7a9efd 100644 --- a/arch/mips/include/asm/mach-generic/spaces.h +++ b/arch/mips/include/asm/mach-generic/spaces.h @@ -82,4 +82,8 @@ #define PAGE_OFFSET (CAC_BASE + PHYS_OFFSET) #endif +#ifndef FIXADDR_TOP +#define FIXADDR_TOP ((unsigned long)(long)(int)0xfffe0000) +#endif + #endif /* __ASM_MACH_GENERIC_SPACES_H */ diff --git a/arch/mips/include/asm/mach-tx39xx/spaces.h b/arch/mips/include/asm/mach-tx39xx/spaces.h new file mode 100644 index 0000000..151fe7a --- /dev/null +++ b/arch/mips/include/asm/mach-tx39xx/spaces.h @@ -0,0 +1,17 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle + * Copyright (C) 2000, 2002 Maciej W. Rozycki + * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_TX39XX_SPACES_H +#define _ASM_TX39XX_SPACES_H + +#define FIXADDR_TOP ((unsigned long)(long)(int)0xfefe0000) + +#include <asm/mach-generic/spaces.h> + +#endif /* __ASM_TX39XX_SPACES_H */ diff --git a/arch/mips/include/asm/mach-tx49xx/spaces.h b/arch/mips/include/asm/mach-tx49xx/spaces.h new file mode 100644 index 0000000..0cb10a6 --- /dev/null +++ b/arch/mips/include/asm/mach-tx49xx/spaces.h @@ -0,0 +1,17 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle + * Copyright (C) 2000, 2002 Maciej W. Rozycki + * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_TX49XX_SPACES_H +#define _ASM_TX49XX_SPACES_H + +#define FIXADDR_TOP ((unsigned long)(long)(int)0xfefe0000) + +#include <asm/mach-generic/spaces.h> + +#endif /* __ASM_TX49XX_SPACES_H */ -- 1.7.0.4 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v2 RESEND 3/6] MIPS: Move FIXADDR_TOP into spaces.h 2011-01-14 1:52 ` [PATCH v2 RESEND 3/6] MIPS: Move FIXADDR_TOP into spaces.h Kevin Cernekee @ 2011-01-14 1:52 ` Kevin Cernekee 0 siblings, 0 replies; 12+ messages in thread From: Kevin Cernekee @ 2011-01-14 1:52 UTC (permalink / raw) To: Ralf Baechle; +Cc: anemo, linux-mips, linux-kernel Memory maps and addressing quirks are normally defined in <spaces.h>. There are already three targets that need to override FIXADDR_TOP, and others exist. This will be a cleaner approach than adding lots of ifdefs in fixmap.h . Signed-off-by: Kevin Cernekee <cernekee@gmail.com> --- arch/mips/include/asm/fixmap.h | 10 +--------- arch/mips/include/asm/mach-bcm63xx/spaces.h | 17 +++++++++++++++++ arch/mips/include/asm/mach-generic/spaces.h | 4 ++++ arch/mips/include/asm/mach-tx39xx/spaces.h | 17 +++++++++++++++++ arch/mips/include/asm/mach-tx49xx/spaces.h | 17 +++++++++++++++++ 5 files changed, 56 insertions(+), 9 deletions(-) create mode 100644 arch/mips/include/asm/mach-bcm63xx/spaces.h create mode 100644 arch/mips/include/asm/mach-tx39xx/spaces.h create mode 100644 arch/mips/include/asm/mach-tx49xx/spaces.h diff --git a/arch/mips/include/asm/fixmap.h b/arch/mips/include/asm/fixmap.h index 0b89b83..98bcc98 100644 --- a/arch/mips/include/asm/fixmap.h +++ b/arch/mips/include/asm/fixmap.h @@ -14,6 +14,7 @@ #define _ASM_FIXMAP_H #include <asm/page.h> +#include <spaces.h> #ifdef CONFIG_HIGHMEM #include <linux/threads.h> #include <asm/kmap_types.h> @@ -67,15 +68,6 @@ enum fixed_addresses { * the start of the fixmap, and leave one page empty * at the top of mem.. */ -#ifdef CONFIG_BCM63XX -#define FIXADDR_TOP ((unsigned long)(long)(int)0xff000000) -#else -#if defined(CONFIG_CPU_TX39XX) || defined(CONFIG_CPU_TX49XX) -#define FIXADDR_TOP ((unsigned long)(long)(int)(0xff000000 - 0x20000)) -#else -#define FIXADDR_TOP ((unsigned long)(long)(int)0xfffe0000) -#endif -#endif #define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) #define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) diff --git a/arch/mips/include/asm/mach-bcm63xx/spaces.h b/arch/mips/include/asm/mach-bcm63xx/spaces.h new file mode 100644 index 0000000..61e750f --- /dev/null +++ b/arch/mips/include/asm/mach-bcm63xx/spaces.h @@ -0,0 +1,17 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle + * Copyright (C) 2000, 2002 Maciej W. Rozycki + * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_BCM63XX_SPACES_H +#define _ASM_BCM63XX_SPACES_H + +#define FIXADDR_TOP ((unsigned long)(long)(int)0xff000000) + +#include <asm/mach-generic/spaces.h> + +#endif /* __ASM_BCM63XX_SPACES_H */ diff --git a/arch/mips/include/asm/mach-generic/spaces.h b/arch/mips/include/asm/mach-generic/spaces.h index c9fa4b1..d7a9efd 100644 --- a/arch/mips/include/asm/mach-generic/spaces.h +++ b/arch/mips/include/asm/mach-generic/spaces.h @@ -82,4 +82,8 @@ #define PAGE_OFFSET (CAC_BASE + PHYS_OFFSET) #endif +#ifndef FIXADDR_TOP +#define FIXADDR_TOP ((unsigned long)(long)(int)0xfffe0000) +#endif + #endif /* __ASM_MACH_GENERIC_SPACES_H */ diff --git a/arch/mips/include/asm/mach-tx39xx/spaces.h b/arch/mips/include/asm/mach-tx39xx/spaces.h new file mode 100644 index 0000000..151fe7a --- /dev/null +++ b/arch/mips/include/asm/mach-tx39xx/spaces.h @@ -0,0 +1,17 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle + * Copyright (C) 2000, 2002 Maciej W. Rozycki + * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_TX39XX_SPACES_H +#define _ASM_TX39XX_SPACES_H + +#define FIXADDR_TOP ((unsigned long)(long)(int)0xfefe0000) + +#include <asm/mach-generic/spaces.h> + +#endif /* __ASM_TX39XX_SPACES_H */ diff --git a/arch/mips/include/asm/mach-tx49xx/spaces.h b/arch/mips/include/asm/mach-tx49xx/spaces.h new file mode 100644 index 0000000..0cb10a6 --- /dev/null +++ b/arch/mips/include/asm/mach-tx49xx/spaces.h @@ -0,0 +1,17 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle + * Copyright (C) 2000, 2002 Maciej W. Rozycki + * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc. + */ +#ifndef _ASM_TX49XX_SPACES_H +#define _ASM_TX49XX_SPACES_H + +#define FIXADDR_TOP ((unsigned long)(long)(int)0xfefe0000) + +#include <asm/mach-generic/spaces.h> + +#endif /* __ASM_TX49XX_SPACES_H */ -- 1.7.0.4 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v4 RESEND 4/6] MIPS: HIGHMEM DMA on noncoherent MIPS32 processors 2011-01-14 1:52 [PATCH v2 1/6] MIPS: Sync after cacheflush on BMIPS processors Kevin Cernekee ` (2 preceding siblings ...) 2011-01-14 1:52 ` [PATCH v2 RESEND 3/6] MIPS: Move FIXADDR_TOP into spaces.h Kevin Cernekee @ 2011-01-14 1:52 ` Kevin Cernekee 2011-01-14 1:52 ` Kevin Cernekee 2011-01-14 1:52 ` [PATCH RESEND 5/6] MIPS: Install handlers for BMIPS software IRQs Kevin Cernekee 2011-01-14 1:52 ` [PATCH RESEND 6/6] MIPS: Limit fixrange_init() to the FIXMAP region Kevin Cernekee 5 siblings, 1 reply; 12+ messages in thread From: Kevin Cernekee @ 2011-01-14 1:52 UTC (permalink / raw) To: Ralf Baechle Cc: dediao, ddaney, dvomlehn, sshtylyov, linux-mips, linux-kernel The MIPS DMA coherency functions do not work properly (i.e. kernel oops) when HIGHMEM pages are passed in as arguments. Use kmap_atomic() to temporarily map high pages for cache maintenance operations. Tested on a 2.6.37-rc7 1GB HIGHMEM SMP no-alias system. Signed-off-by: Dezhong Diao <dediao@cisco.com> Signed-off-by: Kevin Cernekee <cernekee@gmail.com> --- arch/mips/mm/dma-default.c | 114 ++++++++++++++++++++++++++------------------ 1 files changed, 68 insertions(+), 46 deletions(-) diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 21ea14e..4608491 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -15,18 +15,18 @@ #include <linux/scatterlist.h> #include <linux/string.h> #include <linux/gfp.h> +#include <linux/highmem.h> #include <asm/cache.h> #include <asm/io.h> #include <dma-coherence.h> -static inline unsigned long dma_addr_to_virt(struct device *dev, +static inline struct page *dma_addr_to_page(struct device *dev, dma_addr_t dma_addr) { - unsigned long addr = plat_dma_addr_to_phys(dev, dma_addr); - - return (unsigned long)phys_to_virt(addr); + return pfn_to_page( + plat_dma_addr_to_phys(dev, dma_addr) >> PAGE_SHIFT); } /* @@ -148,20 +148,20 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr, free_pages(addr, get_order(size)); } -static inline void __dma_sync(unsigned long addr, size_t size, +static inline void __dma_sync_virtual(void *addr, size_t size, enum dma_data_direction direction) { switch (direction) { case DMA_TO_DEVICE: - dma_cache_wback(addr, size); + dma_cache_wback((unsigned long)addr, size); break; case DMA_FROM_DEVICE: - dma_cache_inv(addr, size); + dma_cache_inv((unsigned long)addr, size); break; case DMA_BIDIRECTIONAL: - dma_cache_wback_inv(addr, size); + dma_cache_wback_inv((unsigned long)addr, size); break; default: @@ -169,12 +169,49 @@ static inline void __dma_sync(unsigned long addr, size_t size, } } +/* + * A single sg entry may refer to multiple physically contiguous + * pages. But we still need to process highmem pages individually. + * If highmem is not configured then the bulk of this loop gets + * optimized out. + */ +static inline void __dma_sync(struct page *page, + unsigned long offset, size_t size, enum dma_data_direction direction) +{ + size_t left = size; + + do { + size_t len = left; + + if (PageHighMem(page)) { + void *addr; + + if (offset + len > PAGE_SIZE) { + if (offset >= PAGE_SIZE) { + page += offset >> PAGE_SHIFT; + offset &= ~PAGE_MASK; + } + len = PAGE_SIZE - offset; + } + + addr = kmap_atomic(page); + __dma_sync_virtual(addr + offset, len, direction); + kunmap_atomic(addr); + } else + __dma_sync_virtual(page_address(page) + offset, + size, direction); + offset = 0; + page++; + left -= len; + } while (left); +} + static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction direction, struct dma_attrs *attrs) { if (cpu_is_noncoherent_r10000(dev)) - __dma_sync(dma_addr_to_virt(dev, dma_addr), size, - direction); + __dma_sync(dma_addr_to_page(dev, dma_addr), + dma_addr & ~PAGE_MASK, size, direction); plat_unmap_dma_mem(dev, dma_addr, size, direction); } @@ -185,13 +222,11 @@ static int mips_dma_map_sg(struct device *dev, struct scatterlist *sg, int i; for (i = 0; i < nents; i++, sg++) { - unsigned long addr; - - addr = (unsigned long) sg_virt(sg); - if (!plat_device_is_coherent(dev) && addr) - __dma_sync(addr, sg->length, direction); - sg->dma_address = plat_map_dma_mem(dev, - (void *)addr, sg->length); + if (!plat_device_is_coherent(dev)) + __dma_sync(sg_page(sg), sg->offset, sg->length, + direction); + sg->dma_address = plat_map_dma_mem_page(dev, sg_page(sg)) + + sg->offset; } return nents; @@ -201,30 +236,23 @@ static dma_addr_t mips_dma_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction direction, struct dma_attrs *attrs) { - unsigned long addr; - - addr = (unsigned long) page_address(page) + offset; - if (!plat_device_is_coherent(dev)) - __dma_sync(addr, size, direction); + __dma_sync(page, offset, size, direction); - return plat_map_dma_mem(dev, (void *)addr, size); + return plat_map_dma_mem_page(dev, page) + offset; } static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, enum dma_data_direction direction, struct dma_attrs *attrs) { - unsigned long addr; int i; for (i = 0; i < nhwentries; i++, sg++) { if (!plat_device_is_coherent(dev) && - direction != DMA_TO_DEVICE) { - addr = (unsigned long) sg_virt(sg); - if (addr) - __dma_sync(addr, sg->length, direction); - } + direction != DMA_TO_DEVICE) + __dma_sync(sg_page(sg), sg->offset, sg->length, + direction); plat_unmap_dma_mem(dev, sg->dma_address, sg->length, direction); } } @@ -232,24 +260,18 @@ static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg, static void mips_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) { - if (cpu_is_noncoherent_r10000(dev)) { - unsigned long addr; - - addr = dma_addr_to_virt(dev, dma_handle); - __dma_sync(addr, size, direction); - } + if (cpu_is_noncoherent_r10000(dev)) + __dma_sync(dma_addr_to_page(dev, dma_handle), + dma_handle & ~PAGE_MASK, size, direction); } static void mips_dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) { plat_extra_sync_for_device(dev); - if (!plat_device_is_coherent(dev)) { - unsigned long addr; - - addr = dma_addr_to_virt(dev, dma_handle); - __dma_sync(addr, size, direction); - } + if (!plat_device_is_coherent(dev)) + __dma_sync(dma_addr_to_page(dev, dma_handle), + dma_handle & ~PAGE_MASK, size, direction); } static void mips_dma_sync_sg_for_cpu(struct device *dev, @@ -260,8 +282,8 @@ static void mips_dma_sync_sg_for_cpu(struct device *dev, /* Make sure that gcc doesn't leave the empty loop body. */ for (i = 0; i < nelems; i++, sg++) { if (cpu_is_noncoherent_r10000(dev)) - __dma_sync((unsigned long)page_address(sg_page(sg)), - sg->length, direction); + __dma_sync(sg_page(sg), sg->offset, sg->length, + direction); } } @@ -273,8 +295,8 @@ static void mips_dma_sync_sg_for_device(struct device *dev, /* Make sure that gcc doesn't leave the empty loop body. */ for (i = 0; i < nelems; i++, sg++) { if (!plat_device_is_coherent(dev)) - __dma_sync((unsigned long)page_address(sg_page(sg)), - sg->length, direction); + __dma_sync(sg_page(sg), sg->offset, sg->length, + direction); } } @@ -295,7 +317,7 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size, plat_extra_sync_for_device(dev); if (!plat_device_is_coherent(dev)) - __dma_sync((unsigned long)vaddr, size, direction); + __dma_sync_virtual(vaddr, size, direction); } EXPORT_SYMBOL(dma_cache_sync); -- 1.7.0.4 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v4 RESEND 4/6] MIPS: HIGHMEM DMA on noncoherent MIPS32 processors 2011-01-14 1:52 ` [PATCH v4 RESEND 4/6] MIPS: HIGHMEM DMA on noncoherent MIPS32 processors Kevin Cernekee @ 2011-01-14 1:52 ` Kevin Cernekee 0 siblings, 0 replies; 12+ messages in thread From: Kevin Cernekee @ 2011-01-14 1:52 UTC (permalink / raw) To: Ralf Baechle Cc: dediao, ddaney, dvomlehn, sshtylyov, linux-mips, linux-kernel The MIPS DMA coherency functions do not work properly (i.e. kernel oops) when HIGHMEM pages are passed in as arguments. Use kmap_atomic() to temporarily map high pages for cache maintenance operations. Tested on a 2.6.37-rc7 1GB HIGHMEM SMP no-alias system. Signed-off-by: Dezhong Diao <dediao@cisco.com> Signed-off-by: Kevin Cernekee <cernekee@gmail.com> --- arch/mips/mm/dma-default.c | 114 ++++++++++++++++++++++++++------------------ 1 files changed, 68 insertions(+), 46 deletions(-) diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 21ea14e..4608491 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -15,18 +15,18 @@ #include <linux/scatterlist.h> #include <linux/string.h> #include <linux/gfp.h> +#include <linux/highmem.h> #include <asm/cache.h> #include <asm/io.h> #include <dma-coherence.h> -static inline unsigned long dma_addr_to_virt(struct device *dev, +static inline struct page *dma_addr_to_page(struct device *dev, dma_addr_t dma_addr) { - unsigned long addr = plat_dma_addr_to_phys(dev, dma_addr); - - return (unsigned long)phys_to_virt(addr); + return pfn_to_page( + plat_dma_addr_to_phys(dev, dma_addr) >> PAGE_SHIFT); } /* @@ -148,20 +148,20 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr, free_pages(addr, get_order(size)); } -static inline void __dma_sync(unsigned long addr, size_t size, +static inline void __dma_sync_virtual(void *addr, size_t size, enum dma_data_direction direction) { switch (direction) { case DMA_TO_DEVICE: - dma_cache_wback(addr, size); + dma_cache_wback((unsigned long)addr, size); break; case DMA_FROM_DEVICE: - dma_cache_inv(addr, size); + dma_cache_inv((unsigned long)addr, size); break; case DMA_BIDIRECTIONAL: - dma_cache_wback_inv(addr, size); + dma_cache_wback_inv((unsigned long)addr, size); break; default: @@ -169,12 +169,49 @@ static inline void __dma_sync(unsigned long addr, size_t size, } } +/* + * A single sg entry may refer to multiple physically contiguous + * pages. But we still need to process highmem pages individually. + * If highmem is not configured then the bulk of this loop gets + * optimized out. + */ +static inline void __dma_sync(struct page *page, + unsigned long offset, size_t size, enum dma_data_direction direction) +{ + size_t left = size; + + do { + size_t len = left; + + if (PageHighMem(page)) { + void *addr; + + if (offset + len > PAGE_SIZE) { + if (offset >= PAGE_SIZE) { + page += offset >> PAGE_SHIFT; + offset &= ~PAGE_MASK; + } + len = PAGE_SIZE - offset; + } + + addr = kmap_atomic(page); + __dma_sync_virtual(addr + offset, len, direction); + kunmap_atomic(addr); + } else + __dma_sync_virtual(page_address(page) + offset, + size, direction); + offset = 0; + page++; + left -= len; + } while (left); +} + static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction direction, struct dma_attrs *attrs) { if (cpu_is_noncoherent_r10000(dev)) - __dma_sync(dma_addr_to_virt(dev, dma_addr), size, - direction); + __dma_sync(dma_addr_to_page(dev, dma_addr), + dma_addr & ~PAGE_MASK, size, direction); plat_unmap_dma_mem(dev, dma_addr, size, direction); } @@ -185,13 +222,11 @@ static int mips_dma_map_sg(struct device *dev, struct scatterlist *sg, int i; for (i = 0; i < nents; i++, sg++) { - unsigned long addr; - - addr = (unsigned long) sg_virt(sg); - if (!plat_device_is_coherent(dev) && addr) - __dma_sync(addr, sg->length, direction); - sg->dma_address = plat_map_dma_mem(dev, - (void *)addr, sg->length); + if (!plat_device_is_coherent(dev)) + __dma_sync(sg_page(sg), sg->offset, sg->length, + direction); + sg->dma_address = plat_map_dma_mem_page(dev, sg_page(sg)) + + sg->offset; } return nents; @@ -201,30 +236,23 @@ static dma_addr_t mips_dma_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction direction, struct dma_attrs *attrs) { - unsigned long addr; - - addr = (unsigned long) page_address(page) + offset; - if (!plat_device_is_coherent(dev)) - __dma_sync(addr, size, direction); + __dma_sync(page, offset, size, direction); - return plat_map_dma_mem(dev, (void *)addr, size); + return plat_map_dma_mem_page(dev, page) + offset; } static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, enum dma_data_direction direction, struct dma_attrs *attrs) { - unsigned long addr; int i; for (i = 0; i < nhwentries; i++, sg++) { if (!plat_device_is_coherent(dev) && - direction != DMA_TO_DEVICE) { - addr = (unsigned long) sg_virt(sg); - if (addr) - __dma_sync(addr, sg->length, direction); - } + direction != DMA_TO_DEVICE) + __dma_sync(sg_page(sg), sg->offset, sg->length, + direction); plat_unmap_dma_mem(dev, sg->dma_address, sg->length, direction); } } @@ -232,24 +260,18 @@ static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg, static void mips_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) { - if (cpu_is_noncoherent_r10000(dev)) { - unsigned long addr; - - addr = dma_addr_to_virt(dev, dma_handle); - __dma_sync(addr, size, direction); - } + if (cpu_is_noncoherent_r10000(dev)) + __dma_sync(dma_addr_to_page(dev, dma_handle), + dma_handle & ~PAGE_MASK, size, direction); } static void mips_dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) { plat_extra_sync_for_device(dev); - if (!plat_device_is_coherent(dev)) { - unsigned long addr; - - addr = dma_addr_to_virt(dev, dma_handle); - __dma_sync(addr, size, direction); - } + if (!plat_device_is_coherent(dev)) + __dma_sync(dma_addr_to_page(dev, dma_handle), + dma_handle & ~PAGE_MASK, size, direction); } static void mips_dma_sync_sg_for_cpu(struct device *dev, @@ -260,8 +282,8 @@ static void mips_dma_sync_sg_for_cpu(struct device *dev, /* Make sure that gcc doesn't leave the empty loop body. */ for (i = 0; i < nelems; i++, sg++) { if (cpu_is_noncoherent_r10000(dev)) - __dma_sync((unsigned long)page_address(sg_page(sg)), - sg->length, direction); + __dma_sync(sg_page(sg), sg->offset, sg->length, + direction); } } @@ -273,8 +295,8 @@ static void mips_dma_sync_sg_for_device(struct device *dev, /* Make sure that gcc doesn't leave the empty loop body. */ for (i = 0; i < nelems; i++, sg++) { if (!plat_device_is_coherent(dev)) - __dma_sync((unsigned long)page_address(sg_page(sg)), - sg->length, direction); + __dma_sync(sg_page(sg), sg->offset, sg->length, + direction); } } @@ -295,7 +317,7 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size, plat_extra_sync_for_device(dev); if (!plat_device_is_coherent(dev)) - __dma_sync((unsigned long)vaddr, size, direction); + __dma_sync_virtual(vaddr, size, direction); } EXPORT_SYMBOL(dma_cache_sync); -- 1.7.0.4 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH RESEND 5/6] MIPS: Install handlers for BMIPS software IRQs 2011-01-14 1:52 [PATCH v2 1/6] MIPS: Sync after cacheflush on BMIPS processors Kevin Cernekee ` (3 preceding siblings ...) 2011-01-14 1:52 ` [PATCH v4 RESEND 4/6] MIPS: HIGHMEM DMA on noncoherent MIPS32 processors Kevin Cernekee @ 2011-01-14 1:52 ` Kevin Cernekee 2011-01-14 1:52 ` Kevin Cernekee 2011-01-14 1:52 ` [PATCH RESEND 6/6] MIPS: Limit fixrange_init() to the FIXMAP region Kevin Cernekee 5 siblings, 1 reply; 12+ messages in thread From: Kevin Cernekee @ 2011-01-14 1:52 UTC (permalink / raw) To: Ralf Baechle; +Cc: linux-mips, linux-kernel BMIPS4350/4380/5000 CMT/SMT all use SW INT0/INT1 for inter-thread signaling. Signed-off-by: Kevin Cernekee <cernekee@gmail.com> --- arch/mips/kernel/irq_cpu.c | 14 ++++++-------- 1 files changed, 6 insertions(+), 8 deletions(-) diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c index 0262abe..70d4736 100644 --- a/arch/mips/kernel/irq_cpu.c +++ b/arch/mips/kernel/irq_cpu.c @@ -107,14 +107,12 @@ void __init mips_cpu_irq_init(void) clear_c0_status(ST0_IM); clear_c0_cause(CAUSEF_IP); - /* - * Only MT is using the software interrupts currently, so we just - * leave them uninitialized for other processors. - */ - if (cpu_has_mipsmt) - for (i = irq_base; i < irq_base + 2; i++) - set_irq_chip_and_handler(i, &mips_mt_cpu_irq_controller, - handle_percpu_irq); + /* Software interrupts are used for MT/CMT IPI */ + for (i = irq_base; i < irq_base + 2; i++) + set_irq_chip_and_handler(i, cpu_has_mipsmt ? + &mips_mt_cpu_irq_controller : + &mips_cpu_irq_controller, + handle_percpu_irq); for (i = irq_base + 2; i < irq_base + 8; i++) set_irq_chip_and_handler(i, &mips_cpu_irq_controller, -- 1.7.0.4 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH RESEND 5/6] MIPS: Install handlers for BMIPS software IRQs 2011-01-14 1:52 ` [PATCH RESEND 5/6] MIPS: Install handlers for BMIPS software IRQs Kevin Cernekee @ 2011-01-14 1:52 ` Kevin Cernekee 0 siblings, 0 replies; 12+ messages in thread From: Kevin Cernekee @ 2011-01-14 1:52 UTC (permalink / raw) To: Ralf Baechle; +Cc: linux-mips, linux-kernel BMIPS4350/4380/5000 CMT/SMT all use SW INT0/INT1 for inter-thread signaling. Signed-off-by: Kevin Cernekee <cernekee@gmail.com> --- arch/mips/kernel/irq_cpu.c | 14 ++++++-------- 1 files changed, 6 insertions(+), 8 deletions(-) diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c index 0262abe..70d4736 100644 --- a/arch/mips/kernel/irq_cpu.c +++ b/arch/mips/kernel/irq_cpu.c @@ -107,14 +107,12 @@ void __init mips_cpu_irq_init(void) clear_c0_status(ST0_IM); clear_c0_cause(CAUSEF_IP); - /* - * Only MT is using the software interrupts currently, so we just - * leave them uninitialized for other processors. - */ - if (cpu_has_mipsmt) - for (i = irq_base; i < irq_base + 2; i++) - set_irq_chip_and_handler(i, &mips_mt_cpu_irq_controller, - handle_percpu_irq); + /* Software interrupts are used for MT/CMT IPI */ + for (i = irq_base; i < irq_base + 2; i++) + set_irq_chip_and_handler(i, cpu_has_mipsmt ? + &mips_mt_cpu_irq_controller : + &mips_cpu_irq_controller, + handle_percpu_irq); for (i = irq_base + 2; i < irq_base + 8; i++) set_irq_chip_and_handler(i, &mips_cpu_irq_controller, -- 1.7.0.4 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH RESEND 6/6] MIPS: Limit fixrange_init() to the FIXMAP region 2011-01-14 1:52 [PATCH v2 1/6] MIPS: Sync after cacheflush on BMIPS processors Kevin Cernekee ` (4 preceding siblings ...) 2011-01-14 1:52 ` [PATCH RESEND 5/6] MIPS: Install handlers for BMIPS software IRQs Kevin Cernekee @ 2011-01-14 1:52 ` Kevin Cernekee 2011-01-14 1:52 ` Kevin Cernekee 5 siblings, 1 reply; 12+ messages in thread From: Kevin Cernekee @ 2011-01-14 1:52 UTC (permalink / raw) To: Ralf Baechle; +Cc: linux-mips, linux-kernel fixrange_init() allocates page tables for all addresses higher than FIXADDR_TOP. On processors that override the default FIXADDR_TOP address of 0xfffe_0000, this can consume up to 4 pages (1 page per 4MB) for pgd's that are never used. Signed-off-by: Kevin Cernekee <cernekee@gmail.com> --- arch/mips/mm/init.c | 6 +++--- arch/mips/mm/pgtable-32.c | 2 +- arch/mips/mm/pgtable-64.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 45447cd..14a89bd 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -279,11 +279,11 @@ void __init fixrange_init(unsigned long start, unsigned long end, k = __pmd_offset(vaddr); pgd = pgd_base + i; - for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) { + for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) { pud = (pud_t *)pgd; - for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) { + for ( ; (j < PTRS_PER_PUD) && (vaddr < end); pud++, j++) { pmd = (pmd_t *)pud; - for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) { + for (; (k < PTRS_PER_PMD) && (vaddr < end); pmd++, k++) { if (pmd_none(*pmd)) { pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); set_pmd(pmd, __pmd((unsigned long)pte)); diff --git a/arch/mips/mm/pgtable-32.c b/arch/mips/mm/pgtable-32.c index 575e401..adc6911 100644 --- a/arch/mips/mm/pgtable-32.c +++ b/arch/mips/mm/pgtable-32.c @@ -52,7 +52,7 @@ void __init pagetable_init(void) * Fixed mappings: */ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; - fixrange_init(vaddr, 0, pgd_base); + fixrange_init(vaddr, vaddr + FIXADDR_SIZE, pgd_base); #ifdef CONFIG_HIGHMEM /* diff --git a/arch/mips/mm/pgtable-64.c b/arch/mips/mm/pgtable-64.c index 78eaa4f..cda4e30 100644 --- a/arch/mips/mm/pgtable-64.c +++ b/arch/mips/mm/pgtable-64.c @@ -76,5 +76,5 @@ void __init pagetable_init(void) * Fixed mappings: */ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; - fixrange_init(vaddr, 0, pgd_base); + fixrange_init(vaddr, vaddr + FIXADDR_SIZE, pgd_base); } -- 1.7.0.4 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH RESEND 6/6] MIPS: Limit fixrange_init() to the FIXMAP region 2011-01-14 1:52 ` [PATCH RESEND 6/6] MIPS: Limit fixrange_init() to the FIXMAP region Kevin Cernekee @ 2011-01-14 1:52 ` Kevin Cernekee 0 siblings, 0 replies; 12+ messages in thread From: Kevin Cernekee @ 2011-01-14 1:52 UTC (permalink / raw) To: Ralf Baechle; +Cc: linux-mips, linux-kernel fixrange_init() allocates page tables for all addresses higher than FIXADDR_TOP. On processors that override the default FIXADDR_TOP address of 0xfffe_0000, this can consume up to 4 pages (1 page per 4MB) for pgd's that are never used. Signed-off-by: Kevin Cernekee <cernekee@gmail.com> --- arch/mips/mm/init.c | 6 +++--- arch/mips/mm/pgtable-32.c | 2 +- arch/mips/mm/pgtable-64.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 45447cd..14a89bd 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -279,11 +279,11 @@ void __init fixrange_init(unsigned long start, unsigned long end, k = __pmd_offset(vaddr); pgd = pgd_base + i; - for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) { + for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) { pud = (pud_t *)pgd; - for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) { + for ( ; (j < PTRS_PER_PUD) && (vaddr < end); pud++, j++) { pmd = (pmd_t *)pud; - for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) { + for (; (k < PTRS_PER_PMD) && (vaddr < end); pmd++, k++) { if (pmd_none(*pmd)) { pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); set_pmd(pmd, __pmd((unsigned long)pte)); diff --git a/arch/mips/mm/pgtable-32.c b/arch/mips/mm/pgtable-32.c index 575e401..adc6911 100644 --- a/arch/mips/mm/pgtable-32.c +++ b/arch/mips/mm/pgtable-32.c @@ -52,7 +52,7 @@ void __init pagetable_init(void) * Fixed mappings: */ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; - fixrange_init(vaddr, 0, pgd_base); + fixrange_init(vaddr, vaddr + FIXADDR_SIZE, pgd_base); #ifdef CONFIG_HIGHMEM /* diff --git a/arch/mips/mm/pgtable-64.c b/arch/mips/mm/pgtable-64.c index 78eaa4f..cda4e30 100644 --- a/arch/mips/mm/pgtable-64.c +++ b/arch/mips/mm/pgtable-64.c @@ -76,5 +76,5 @@ void __init pagetable_init(void) * Fixed mappings: */ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; - fixrange_init(vaddr, 0, pgd_base); + fixrange_init(vaddr, vaddr + FIXADDR_SIZE, pgd_base); } -- 1.7.0.4 ^ permalink raw reply related [flat|nested] 12+ messages in thread
end of thread, other threads:[~2011-01-14 1:59 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-01-14 1:52 [PATCH v2 1/6] MIPS: Sync after cacheflush on BMIPS processors Kevin Cernekee 2011-01-14 1:52 ` Kevin Cernekee 2011-01-14 1:52 ` [PATCH v2 2/6] MIPS: pfn_valid() is broken on low memory HIGHMEM systems Kevin Cernekee 2011-01-14 1:52 ` Kevin Cernekee 2011-01-14 1:52 ` [PATCH v2 RESEND 3/6] MIPS: Move FIXADDR_TOP into spaces.h Kevin Cernekee 2011-01-14 1:52 ` Kevin Cernekee 2011-01-14 1:52 ` [PATCH v4 RESEND 4/6] MIPS: HIGHMEM DMA on noncoherent MIPS32 processors Kevin Cernekee 2011-01-14 1:52 ` Kevin Cernekee 2011-01-14 1:52 ` [PATCH RESEND 5/6] MIPS: Install handlers for BMIPS software IRQs Kevin Cernekee 2011-01-14 1:52 ` Kevin Cernekee 2011-01-14 1:52 ` [PATCH RESEND 6/6] MIPS: Limit fixrange_init() to the FIXMAP region Kevin Cernekee 2011-01-14 1:52 ` Kevin Cernekee
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox