Patchwork ARM: Remove the domain switching on ARMv6k/v7 CPUs - update

login
register
mail settings
Submitter Sebastien Jan
Date July 6, 2010, 9:09 a.m.
Message ID <1278407354-13003-1-git-send-email-s-jan@ti.com>
Download mbox | patch
Permalink /patch/57990/
State Accepted
Headers show

Comments

Sebastien Jan - July 6, 2010, 9:09 a.m.
From: Catalin Marinas <catalin.marinas@arm.com>

This is an update of the patch from Catalin Marinas:
Remove the domain switching on ARMv6k/v7 CPUs

The first proposal of this patch was already integrated.
This patch upgrades it to the v4 revision from Catalin:
http://www.spinics.net/lists/arm-kernel/msg91260.html

This patch fixes some 'segmentation faults' seen with Maverick FS
on OMAP4.

Signed-off-by: Sebastien Jan <s-jan@ti.com>

---
This patch replaces the previous patch sent for reviews with title:
Fix spurious segmentation faults
---
 arch/arm/include/asm/assembler.h |   12 ++++++------
 arch/arm/include/asm/traps.h     |    2 ++
 arch/arm/kernel/fiq.c            |    5 +++++
 arch/arm/kernel/traps.c          |   14 ++++++++++----
 arch/arm/mm/Kconfig              |    3 +--
 arch/arm/mm/mmu.c                |    6 +++---
 arch/arm/mm/proc-macros.S        |    9 ++++++++-
 arch/arm/mm/proc-v7.S            |    3 +++
 8 files changed, 38 insertions(+), 16 deletions(-)
Tim Gardner - July 6, 2010, 12:51 p.m.
On 07/06/2010 03:09 AM, Sebastien Jan wrote:
> From: Catalin Marinas<catalin.marinas@arm.com>
>
> This is an update of the patch from Catalin Marinas:
> Remove the domain switching on ARMv6k/v7 CPUs
>
> The first proposal of this patch was already integrated.
> This patch upgrades it to the v4 revision from Catalin:
> http://www.spinics.net/lists/arm-kernel/msg91260.html
>
> This patch fixes some 'segmentation faults' seen with Maverick FS
> on OMAP4.
>
> Signed-off-by: Sebastien Jan<s-jan@ti.com>
>
> ---
> This patch replaces the previous patch sent for reviews with title:
> Fix spurious segmentation faults
> ---
>   arch/arm/include/asm/assembler.h |   12 ++++++------
>   arch/arm/include/asm/traps.h     |    2 ++
>   arch/arm/kernel/fiq.c            |    5 +++++
>   arch/arm/kernel/traps.c          |   14 ++++++++++----
>   arch/arm/mm/Kconfig              |    3 +--
>   arch/arm/mm/mmu.c                |    6 +++---
>   arch/arm/mm/proc-macros.S        |    9 ++++++++-
>   arch/arm/mm/proc-v7.S            |    3 +++
>   8 files changed, 38 insertions(+), 16 deletions(-)
>
> diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
> index eb50c6a..66db132 100644
> --- a/arch/arm/include/asm/assembler.h
> +++ b/arch/arm/include/asm/assembler.h
> @@ -184,12 +184,12 @@
>    */
>   #ifdef CONFIG_THUMB2_KERNEL
>
> -	.macro	usraccoff, instr, reg, ptr, inc, off, cond, abort
> +	.macro	usraccoff, instr, reg, ptr, inc, off, cond, abort, t=T()
>   9999:
>   	.if	\inc == 1
> -	T(\instr\cond\()b) \reg, [\ptr, #\off]
> +	\instr\cond\()b\()\t\().w \reg, [\ptr, #\off]
>   	.elseif	\inc == 4
> -	T(\instr\cond\()) \reg, [\ptr, #\off]
> +	\instr\cond\()\t\().w \reg, [\ptr, #\off]
>   	.else
>   	.error	"Unsupported inc macro argument"
>   	.endif
> @@ -224,13 +224,13 @@
>
>   #else	/* !CONFIG_THUMB2_KERNEL */
>
> -	.macro	usracc, instr, reg, ptr, inc, cond, rept, abort
> +	.macro	usracc, instr, reg, ptr, inc, cond, rept, abort, t=T()
>   	.rept	\rept
>   9999:
>   	.if	\inc == 1
> -	T(\instr\cond\()b) \reg, [\ptr], #\inc
> +	\instr\cond\()b\()\t \reg, [\ptr], #\inc
>   	.elseif	\inc == 4
> -	T(\instr\cond\()) \reg, [\ptr], #\inc
> +	\instr\cond\()\t \reg, [\ptr], #\inc
>   	.else
>   	.error	"Unsupported inc macro argument"
>   	.endif
> diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h
> index 491960b..af5d5d1 100644
> --- a/arch/arm/include/asm/traps.h
> +++ b/arch/arm/include/asm/traps.h
> @@ -27,4 +27,6 @@ static inline int in_exception_text(unsigned long ptr)
>   extern void __init early_trap_init(void);
>   extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);
>
> +extern void *vectors_page;
> +
>   #endif
> diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
> index 6ff7919..d601ef2 100644
> --- a/arch/arm/kernel/fiq.c
> +++ b/arch/arm/kernel/fiq.c
> @@ -45,6 +45,7 @@
>   #include<asm/fiq.h>
>   #include<asm/irq.h>
>   #include<asm/system.h>
> +#include<asm/traps.h>
>
>   static unsigned long no_fiq_insn;
>
> @@ -77,7 +78,11 @@ int show_fiq_list(struct seq_file *p, void *v)
>
>   void set_fiq_handler(void *start, unsigned int length)
>   {
> +#if defined(CONFIG_CPU_USE_DOMAINS)
>   	memcpy((void *)0xffff001c, start, length);
> +#else
> +	memcpy(vectors_page + 0x1c, start, length);
> +#endif
>   	flush_icache_range(0xffff001c, 0xffff001c + length);
>   	if (!vectors_high())
>   		flush_icache_range(0x1c, 0x1c + length);
> diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
> index 0330a40..6394d43 100644
> --- a/arch/arm/kernel/traps.c
> +++ b/arch/arm/kernel/traps.c
> @@ -37,6 +37,8 @@
>
>   static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
>
> +void *vectors_page;
> +
>   #ifdef CONFIG_DEBUG_USER
>   unsigned int user_debug;
>
> @@ -762,7 +764,11 @@ void __init trap_init(void)
>
>   void __init early_trap_init(void)
>   {
> +#if defined(CONFIG_CPU_USE_DOMAINS)
>   	unsigned long vectors = CONFIG_VECTORS_BASE;
> +#else
> +	unsigned long vectors = (unsigned long)vectors_page;
> +#endif
>   	extern char __stubs_start[], __stubs_end[];
>   	extern char __vectors_start[], __vectors_end[];
>   	extern char __kuser_helper_start[], __kuser_helper_end[];
> @@ -791,10 +797,10 @@ void __init early_trap_init(void)
>   	 * Copy signal return handlers into the vector page, and
>   	 * set sigreturn to be a pointer to these.
>   	 */
> -	memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,
> -	       sizeof(sigreturn_codes));
> -	memcpy((void *)KERN_RESTART_CODE, syscall_restart_code,
> -	       sizeof(syscall_restart_code));
> +	memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE),
> +	       sigreturn_codes, sizeof(sigreturn_codes));
> +	memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE),
> +	       syscall_restart_code, sizeof(syscall_restart_code));
>
>   #ifndef CONFIG_CPU_USE_DOMAINS
>   	/* restore the vectors page permissions */
> diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
> index 3b07461..8f4dee8 100644
> --- a/arch/arm/mm/Kconfig
> +++ b/arch/arm/mm/Kconfig
> @@ -600,8 +600,7 @@ config CPU_CP15_MPU
>   config CPU_USE_DOMAINS
>   	bool
>   	depends on MMU
> -	default n if HAS_TLS_REG
> -	default y
> +	default y if !HAS_TLS_REG
>   	help
>   	  This option enables or disable the use of domain switching
>   	  via the set_fs() function.
> diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
> index 241c24a..4b0f4b0 100644
> --- a/arch/arm/mm/mmu.c
> +++ b/arch/arm/mm/mmu.c
> @@ -24,6 +24,7 @@
>   #include<asm/smp_plat.h>
>   #include<asm/tlb.h>
>   #include<asm/highmem.h>
> +#include<asm/traps.h>
>
>   #include<asm/mach/arch.h>
>   #include<asm/mach/map.h>
> @@ -933,12 +934,11 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
>   {
>   	struct map_desc map;
>   	unsigned long addr;
> -	void *vectors;
>
>   	/*
>   	 * Allocate the vector page early.
>   	 */
> -	vectors = alloc_bootmem_low_pages(PAGE_SIZE);
> +	vectors_page = alloc_bootmem_low_pages(PAGE_SIZE);
>
>   	for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
>   		pmd_clear(pmd_off_k(addr));
> @@ -978,7 +978,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
>   	 * location (0xffff0000).  If we aren't using high-vectors, also
>   	 * create a mapping at the low-vectors virtual address.
>   	 */
> -	map.pfn = __phys_to_pfn(virt_to_phys(vectors));
> +	map.pfn = __phys_to_pfn(virt_to_phys(vectors_page));
>   	map.virtual = 0xffff0000;
>   	map.length = PAGE_SIZE;
>   	map.type = MT_HIGH_VECTORS;
> diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S
> index 7d63bea..1ccf579 100644
> --- a/arch/arm/mm/proc-macros.S
> +++ b/arch/arm/mm/proc-macros.S
> @@ -99,7 +99,11 @@
>    *  110x   0   1   0	r/w	r/o
>    *  11x0   0   1   0	r/w	r/o
>    *  1111   0   1   1	r/w	r/w
> - */
> + *
> + * If !CONFIG_CPU_USE_DOMAINS, the following permissions are changed:
> + *  110x   1   1   1	r/o	r/o
> + *  11x0   1   1   1	r/o	r/o
> +  */
>   	.macro	armv6_mt_table pfx
>   \pfx\()_mt_table:
>   	.long	0x00						@ L_PTE_MT_UNCACHED
> @@ -138,8 +142,11 @@
>
>   	tst	r1, #L_PTE_USER
>   	orrne	r3, r3, #PTE_EXT_AP1
> +#ifdef CONFIG_CPU_USE_DOMAINS
> +	@ allow kernel read/write access to read-only user pages
>   	tstne	r3, #PTE_EXT_APX
>   	bicne	r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
> +#endif
>
>   	tst	r1, #L_PTE_EXEC
>   	orreq	r3, r3, #PTE_EXT_XN
> diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
> index df74916..c1c3fe0 100644
> --- a/arch/arm/mm/proc-v7.S
> +++ b/arch/arm/mm/proc-v7.S
> @@ -152,8 +152,11 @@ ENTRY(cpu_v7_set_pte_ext)
>
>   	tst	r1, #L_PTE_USER
>   	orrne	r3, r3, #PTE_EXT_AP1
> +#ifdef CONFIG_CPU_USE_DOMAINS
> +	@ allow kernel read/write access to read-only user pages
>   	tstne	r3, #PTE_EXT_APX
>   	bicne	r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
> +#endif
>
>   	tst	r1, #L_PTE_EXEC
>   	orreq	r3, r3, #PTE_EXT_XN

applied

Patch

diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index eb50c6a..66db132 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -184,12 +184,12 @@ 
  */
 #ifdef CONFIG_THUMB2_KERNEL
 
-	.macro	usraccoff, instr, reg, ptr, inc, off, cond, abort
+	.macro	usraccoff, instr, reg, ptr, inc, off, cond, abort, t=T()
 9999:
 	.if	\inc == 1
-	T(\instr\cond\()b) \reg, [\ptr, #\off]
+	\instr\cond\()b\()\t\().w \reg, [\ptr, #\off]
 	.elseif	\inc == 4
-	T(\instr\cond\()) \reg, [\ptr, #\off]
+	\instr\cond\()\t\().w \reg, [\ptr, #\off]
 	.else
 	.error	"Unsupported inc macro argument"
 	.endif
@@ -224,13 +224,13 @@ 
 
 #else	/* !CONFIG_THUMB2_KERNEL */
 
-	.macro	usracc, instr, reg, ptr, inc, cond, rept, abort
+	.macro	usracc, instr, reg, ptr, inc, cond, rept, abort, t=T()
 	.rept	\rept
 9999:
 	.if	\inc == 1
-	T(\instr\cond\()b) \reg, [\ptr], #\inc
+	\instr\cond\()b\()\t \reg, [\ptr], #\inc
 	.elseif	\inc == 4
-	T(\instr\cond\()) \reg, [\ptr], #\inc
+	\instr\cond\()\t \reg, [\ptr], #\inc
 	.else
 	.error	"Unsupported inc macro argument"
 	.endif
diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h
index 491960b..af5d5d1 100644
--- a/arch/arm/include/asm/traps.h
+++ b/arch/arm/include/asm/traps.h
@@ -27,4 +27,6 @@  static inline int in_exception_text(unsigned long ptr)
 extern void __init early_trap_init(void);
 extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);
 
+extern void *vectors_page;
+
 #endif
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
index 6ff7919..d601ef2 100644
--- a/arch/arm/kernel/fiq.c
+++ b/arch/arm/kernel/fiq.c
@@ -45,6 +45,7 @@ 
 #include <asm/fiq.h>
 #include <asm/irq.h>
 #include <asm/system.h>
+#include <asm/traps.h>
 
 static unsigned long no_fiq_insn;
 
@@ -77,7 +78,11 @@  int show_fiq_list(struct seq_file *p, void *v)
 
 void set_fiq_handler(void *start, unsigned int length)
 {
+#if defined(CONFIG_CPU_USE_DOMAINS)
 	memcpy((void *)0xffff001c, start, length);
+#else
+	memcpy(vectors_page + 0x1c, start, length);
+#endif
 	flush_icache_range(0xffff001c, 0xffff001c + length);
 	if (!vectors_high())
 		flush_icache_range(0x1c, 0x1c + length);
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 0330a40..6394d43 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -37,6 +37,8 @@ 
 
 static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
 
+void *vectors_page;
+
 #ifdef CONFIG_DEBUG_USER
 unsigned int user_debug;
 
@@ -762,7 +764,11 @@  void __init trap_init(void)
 
 void __init early_trap_init(void)
 {
+#if defined(CONFIG_CPU_USE_DOMAINS)
 	unsigned long vectors = CONFIG_VECTORS_BASE;
+#else
+	unsigned long vectors = (unsigned long)vectors_page;
+#endif
 	extern char __stubs_start[], __stubs_end[];
 	extern char __vectors_start[], __vectors_end[];
 	extern char __kuser_helper_start[], __kuser_helper_end[];
@@ -791,10 +797,10 @@  void __init early_trap_init(void)
 	 * Copy signal return handlers into the vector page, and
 	 * set sigreturn to be a pointer to these.
 	 */
-	memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,
-	       sizeof(sigreturn_codes));
-	memcpy((void *)KERN_RESTART_CODE, syscall_restart_code,
-	       sizeof(syscall_restart_code));
+	memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE),
+	       sigreturn_codes, sizeof(sigreturn_codes));
+	memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE),
+	       syscall_restart_code, sizeof(syscall_restart_code));
 
 #ifndef CONFIG_CPU_USE_DOMAINS
 	/* restore the vectors page permissions */
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 3b07461..8f4dee8 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -600,8 +600,7 @@  config CPU_CP15_MPU
 config CPU_USE_DOMAINS
 	bool
 	depends on MMU
-	default n if HAS_TLS_REG
-	default y
+	default y if !HAS_TLS_REG
 	help
 	  This option enables or disable the use of domain switching
 	  via the set_fs() function.
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 241c24a..4b0f4b0 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -24,6 +24,7 @@ 
 #include <asm/smp_plat.h>
 #include <asm/tlb.h>
 #include <asm/highmem.h>
+#include <asm/traps.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -933,12 +934,11 @@  static void __init devicemaps_init(struct machine_desc *mdesc)
 {
 	struct map_desc map;
 	unsigned long addr;
-	void *vectors;
 
 	/*
 	 * Allocate the vector page early.
 	 */
-	vectors = alloc_bootmem_low_pages(PAGE_SIZE);
+	vectors_page = alloc_bootmem_low_pages(PAGE_SIZE);
 
 	for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
 		pmd_clear(pmd_off_k(addr));
@@ -978,7 +978,7 @@  static void __init devicemaps_init(struct machine_desc *mdesc)
 	 * location (0xffff0000).  If we aren't using high-vectors, also
 	 * create a mapping at the low-vectors virtual address.
 	 */
-	map.pfn = __phys_to_pfn(virt_to_phys(vectors));
+	map.pfn = __phys_to_pfn(virt_to_phys(vectors_page));
 	map.virtual = 0xffff0000;
 	map.length = PAGE_SIZE;
 	map.type = MT_HIGH_VECTORS;
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S
index 7d63bea..1ccf579 100644
--- a/arch/arm/mm/proc-macros.S
+++ b/arch/arm/mm/proc-macros.S
@@ -99,7 +99,11 @@ 
  *  110x   0   1   0	r/w	r/o
  *  11x0   0   1   0	r/w	r/o
  *  1111   0   1   1	r/w	r/w
- */
+ *
+ * If !CONFIG_CPU_USE_DOMAINS, the following permissions are changed:
+ *  110x   1   1   1	r/o	r/o
+ *  11x0   1   1   1	r/o	r/o
+  */
 	.macro	armv6_mt_table pfx
 \pfx\()_mt_table:
 	.long	0x00						@ L_PTE_MT_UNCACHED
@@ -138,8 +142,11 @@ 
 
 	tst	r1, #L_PTE_USER
 	orrne	r3, r3, #PTE_EXT_AP1
+#ifdef CONFIG_CPU_USE_DOMAINS
+	@ allow kernel read/write access to read-only user pages
 	tstne	r3, #PTE_EXT_APX
 	bicne	r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
+#endif
 
 	tst	r1, #L_PTE_EXEC
 	orreq	r3, r3, #PTE_EXT_XN
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index df74916..c1c3fe0 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -152,8 +152,11 @@  ENTRY(cpu_v7_set_pte_ext)
 
 	tst	r1, #L_PTE_USER
 	orrne	r3, r3, #PTE_EXT_AP1
+#ifdef CONFIG_CPU_USE_DOMAINS
+	@ allow kernel read/write access to read-only user pages
 	tstne	r3, #PTE_EXT_APX
 	bicne	r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
+#endif
 
 	tst	r1, #L_PTE_EXEC
 	orreq	r3, r3, #PTE_EXT_XN