Patchwork ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15

login
register
mail settings
Submitter Uwe Kleine-König
Date Jan. 16, 2012, 4:49 p.m.
Message ID <1326732555-17915-1-git-send-email-u.kleine-koenig@pengutronix.de>
Download mbox | patch
Permalink /patch/136315/
State New
Headers show

Comments

Uwe Kleine-König - Jan. 16, 2012, 4:49 p.m.
cr_alignment is defined in arch/arm/kernel/entry-armv.S. When a build
doesn't include this file but arch/arm/kernel/head-common.S the latter
intruduces an invalid reference to cr_alignment.

So handle cr_alignment not being available in head-common.S and for
completeness only define and use cr_alignment (and cr_no_alignment) when
CONFIG_CPU_CP15 is enabled.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
Hello,

currently arch/arm/kernel/entry-armv.S is used unconditionally, but the
Cortex-M3 port in my tree doesn't need it. So this patch fixex a build
error only in my tree and it's not urgent to include it.

Best regards
Uwe

 arch/arm/include/asm/system.h |    2 ++
 arch/arm/kernel/entry-armv.S  |    4 ++++
 arch/arm/kernel/head-common.S |    9 +++++++--
 arch/arm/kernel/setup.c       |    8 ++++++--
 arch/arm/mm/alignment.c       |    6 ++++++
 arch/arm/mm/mmu.c             |    8 +++++++-
 6 files changed, 32 insertions(+), 5 deletions(-)
Russell King - ARM Linux - Jan. 16, 2012, 4:54 p.m.
On Mon, Jan 16, 2012 at 05:49:15PM +0100, Uwe Kleine-König wrote:
> cr_alignment is defined in arch/arm/kernel/entry-armv.S. When a build
> doesn't include this file but arch/arm/kernel/head-common.S the latter
> intruduces an invalid reference to cr_alignment.
> 
> So handle cr_alignment not being available in head-common.S and for
> completeness only define and use cr_alignment (and cr_no_alignment) when
> CONFIG_CPU_CP15 is enabled.
> 
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> ---
> Hello,
> 
> currently arch/arm/kernel/entry-armv.S is used unconditionally, but the
> Cortex-M3 port in my tree doesn't need it. So this patch fixex a build
> error only in my tree and it's not urgent to include it.

We'll wait then until we can see what you're replacing that file with.
Ryan Mallon - Jan. 18, 2012, 9:39 p.m.
On 17/01/12 03:49, Uwe Kleine-König wrote:

> cr_alignment is defined in arch/arm/kernel/entry-armv.S. When a build
> doesn't include this file but arch/arm/kernel/head-common.S the latter
> intruduces an invalid reference to cr_alignment.
> 
> So handle cr_alignment not being available in head-common.S and for
> completeness only define and use cr_alignment (and cr_no_alignment) when
> CONFIG_CPU_CP15 is enabled.
> 
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>


Hi Uwe,

We have something similar to this patch for our para-virtualised Linux
kernel (www.ok-labs.com). I agree with Russell that we need a user of
this code in the kernel before making this change, and our own patches
are in no danger of hitting mainline any time soon, but I would like to
see this patch go in.

One minor comment below.

Thanks,
~Ryan

> ---
> Hello,
> 
> currently arch/arm/kernel/entry-armv.S is used unconditionally, but the
> Cortex-M3 port in my tree doesn't need it. So this patch fixex a build
> error only in my tree and it's not urgent to include it.
> 
> Best regards
> Uwe
> 
>  arch/arm/include/asm/system.h |    2 ++
>  arch/arm/kernel/entry-armv.S  |    4 ++++
>  arch/arm/kernel/head-common.S |    9 +++++++--
>  arch/arm/kernel/setup.c       |    8 ++++++--
>  arch/arm/mm/alignment.c       |    6 ++++++
>  arch/arm/mm/mmu.c             |    8 +++++++-
>  6 files changed, 32 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
> index 984014b..54c9921 100644
> --- a/arch/arm/include/asm/system.h
> +++ b/arch/arm/include/asm/system.h
> @@ -177,6 +177,7 @@ extern unsigned int user_debug;
>  #define set_mb(var, value)	do { var = value; smp_mb(); } while (0)
>  #define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");


There is another reference in this file to cr_alignment:

#if __LINUX_ARM_ARCH__ >= 4
#define vectors_high()  (cr_alignment & CR_V)
#else
#define vectors_high()  (0)
#endif

In our para-virtualised kernel we hardcode the value of vectors_high()
to 1, however this is might not be the correct thing to do universally
if !CONFIG_CPU_CP15 && __LINUX_ARM_ARCH__ >= 4.

>  
> +#ifdef CONFIG_CPU_CP15
>  extern unsigned long cr_no_alignment;	/* defined in entry-armv.S */
>  extern unsigned long cr_alignment;	/* defined in entry-armv.S */
>  
> @@ -216,6 +217,7 @@ static inline void set_copro_access(unsigned int val)
>  	  : : "r" (val) : "cc");
>  	isb();
>  }
> +#endif
>  
>  /*
>   * switch_mm() may do a full cache flush over the context switch,
> diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
> index b145f16..7782e7d 100644
> --- a/arch/arm/kernel/entry-armv.S
> +++ b/arch/arm/kernel/entry-armv.S
> @@ -315,8 +315,10 @@ __pabt_svc:
>  ENDPROC(__pabt_svc)
>  
>  	.align	5
> +#ifdef CONFIG_CPU_CP15
>  .LCcralign:
>  	.word	cr_alignment
> +#endif
>  #ifdef MULTI_DABORT
>  .LCprocfns:
>  	.word	processor
> @@ -1147,12 +1149,14 @@ __vectors_end:
>  
>  	.data
>  
> +#ifdef CONFIG_CPU_CP15
>  	.globl	cr_alignment
>  	.globl	cr_no_alignment
>  cr_alignment:
>  	.space	4
>  cr_no_alignment:
>  	.space	4
> +#endif
>  
>  #ifdef CONFIG_MULTI_IRQ_HANDLER
>  	.globl	handle_arch_irq
> diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
> index 854bd22..2f560c5 100644
> --- a/arch/arm/kernel/head-common.S
> +++ b/arch/arm/kernel/head-common.S
> @@ -98,8 +98,9 @@ __mmap_switched:
>  	str	r9, [r4]			@ Save processor ID
>  	str	r1, [r5]			@ Save machine type
>  	str	r2, [r6]			@ Save atags pointer
> -	bic	r4, r0, #CR_A			@ Clear 'A' bit
> -	stmia	r7, {r0, r4}			@ Save control register values
> +	cmp	r7, #0
> +	bicne	r4, r0, #CR_A			@ Clear 'A' bit
> +	stmneia	r7, {r0, r4}			@ Save control register values
>  	b	start_kernel
>  ENDPROC(__mmap_switched)
>  
> @@ -113,7 +114,11 @@ __mmap_switched_data:
>  	.long	processor_id			@ r4
>  	.long	__machine_arch_type		@ r5
>  	.long	__atags_pointer			@ r6
> +#ifdef CONFIG_CPU_CP15
>  	.long	cr_alignment			@ r7
> +#else
> +	.long	0
> +#endif
>  	.long	init_thread_union + THREAD_START_SP @ sp
>  	.size	__mmap_switched_data, . - __mmap_switched_data
>  
> diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
> index 8fc2c8f..d37a02fa 100644
> --- a/arch/arm/kernel/setup.c
> +++ b/arch/arm/kernel/setup.c
> @@ -457,9 +457,13 @@ static void __init setup_processor(void)
>  	cpu_cache = *list->cache;
>  #endif
>  
> -	printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
> +	printk("CPU: %s [%08x] revision %d (ARMv%s)",
>  	       cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
> -	       proc_arch[cpu_architecture()], cr_alignment);
> +	       proc_arch[cpu_architecture()]);
> +
> +#ifdef CONFIG_CPU_CP15
> +	printk(KERN_CONT ", cr=%08lx\n", cr_alignment);
> +#endif
>  
>  	snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c",
>  		 list->arch_name, ENDIANNESS);
> diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
> index c335c76..56da01c 100644
> --- a/arch/arm/mm/alignment.c
> +++ b/arch/arm/mm/alignment.c
> @@ -89,7 +89,11 @@ core_param(alignment, ai_usermode, int, 0600);
>  /* Return true if and only if the ARMv6 unaligned access model is in use. */
>  static bool cpu_is_v6_unaligned(void)
>  {
> +#ifdef CONFIG_CPU_CP15
>  	return cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U);
> +#else
> +	return 0;
> +#endif
>  }
>  
>  static int safe_usermode(int new_usermode, bool warn)
> @@ -961,12 +965,14 @@ static int __init alignment_init(void)
>  		return -ENOMEM;
>  #endif
>  
> +#ifdef CONFIG_CPU_CP15
>  	if (cpu_is_v6_unaligned()) {
>  		cr_alignment &= ~CR_A;
>  		cr_no_alignment &= ~CR_A;
>  		set_cr(cr_alignment);
>  		ai_usermode = safe_usermode(ai_usermode, false);
>  	}
> +#endif
>  
>  	hook_fault_code(1, do_alignment, SIGBUS, BUS_ADRALN,
>  			"alignment exception");
> diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
> index 8b8446a..d5a170a 100644
> --- a/arch/arm/mm/mmu.c
> +++ b/arch/arm/mm/mmu.c
> @@ -106,8 +106,10 @@ static int __init early_cachepolicy(char *p)
>  	for (i = 0; i < ARRAY_SIZE(cache_policies); i++) {
>  		if (strcmp(p, cache_policies[i].policy) == 0) {
>  			cachepolicy = i;
> +#ifdef CONFIG_CPU_CP15
>  			cr_alignment &= ~cache_policies[i].cr_mask;
>  			cr_no_alignment &= ~cache_policies[i].cr_mask;
> +#endif
>  			break;
>  		}
>  	}
> @@ -125,7 +127,9 @@ static int __init early_cachepolicy(char *p)
>  		cachepolicy = CPOLICY_WRITEBACK;
>  	}
>  	flush_cache_all();
> +#ifdef CONFIG_CPU_CP15
>  	set_cr(cr_alignment);
> +#endif
>  	return 0;
>  }
>  early_param("cachepolicy", early_cachepolicy);
> @@ -158,6 +162,7 @@ static int __init early_ecc(char *p)
>  }
>  early_param("ecc", early_ecc);
>  
> +#ifdef CONFIG_CPU_CP15
>  static int __init noalign_setup(char *__unused)
>  {
>  	cr_alignment &= ~CR_A;
> @@ -166,8 +171,9 @@ static int __init noalign_setup(char *__unused)
>  	return 1;
>  }
>  __setup("noalign", noalign_setup);
> +#endif
>  
> -#ifndef CONFIG_SMP
> +#if !defined(CONFIG_SMP) && defined(CONFIG_CPU_CP15)
>  void adjust_cr(unsigned long mask, unsigned long set)
>  {
>  	unsigned long flags;
Uwe Kleine-König - Jan. 19, 2012, 8:13 a.m.
Hello Ryan,

On Thu, Jan 19, 2012 at 08:39:08AM +1100, Ryan Mallon wrote:
> On 17/01/12 03:49, Uwe Kleine-König wrote:
> There is another reference in this file to cr_alignment:
> 
> #if __LINUX_ARM_ARCH__ >= 4
> #define vectors_high()  (cr_alignment & CR_V)
> #else
> #define vectors_high()  (0)
> #endif
> 
> In our para-virtualised kernel we hardcode the value of vectors_high()
> to 1, however this is might not be the correct thing to do universally
> if !CONFIG_CPU_CP15 && __LINUX_ARM_ARCH__ >= 4.
On Cortex-M3 the concept of high vectors doesn't exist. There is just a
register that gets the address of the vector (that looks quite different
on M3) and is located in the data section. Hm.

Best regards and thanks for the heads up,
Uwe

Patch

diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index 984014b..54c9921 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -177,6 +177,7 @@  extern unsigned int user_debug;
 #define set_mb(var, value)	do { var = value; smp_mb(); } while (0)
 #define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
 
+#ifdef CONFIG_CPU_CP15
 extern unsigned long cr_no_alignment;	/* defined in entry-armv.S */
 extern unsigned long cr_alignment;	/* defined in entry-armv.S */
 
@@ -216,6 +217,7 @@  static inline void set_copro_access(unsigned int val)
 	  : : "r" (val) : "cc");
 	isb();
 }
+#endif
 
 /*
  * switch_mm() may do a full cache flush over the context switch,
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index b145f16..7782e7d 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -315,8 +315,10 @@  __pabt_svc:
 ENDPROC(__pabt_svc)
 
 	.align	5
+#ifdef CONFIG_CPU_CP15
 .LCcralign:
 	.word	cr_alignment
+#endif
 #ifdef MULTI_DABORT
 .LCprocfns:
 	.word	processor
@@ -1147,12 +1149,14 @@  __vectors_end:
 
 	.data
 
+#ifdef CONFIG_CPU_CP15
 	.globl	cr_alignment
 	.globl	cr_no_alignment
 cr_alignment:
 	.space	4
 cr_no_alignment:
 	.space	4
+#endif
 
 #ifdef CONFIG_MULTI_IRQ_HANDLER
 	.globl	handle_arch_irq
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index 854bd22..2f560c5 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -98,8 +98,9 @@  __mmap_switched:
 	str	r9, [r4]			@ Save processor ID
 	str	r1, [r5]			@ Save machine type
 	str	r2, [r6]			@ Save atags pointer
-	bic	r4, r0, #CR_A			@ Clear 'A' bit
-	stmia	r7, {r0, r4}			@ Save control register values
+	cmp	r7, #0
+	bicne	r4, r0, #CR_A			@ Clear 'A' bit
+	stmneia	r7, {r0, r4}			@ Save control register values
 	b	start_kernel
 ENDPROC(__mmap_switched)
 
@@ -113,7 +114,11 @@  __mmap_switched_data:
 	.long	processor_id			@ r4
 	.long	__machine_arch_type		@ r5
 	.long	__atags_pointer			@ r6
+#ifdef CONFIG_CPU_CP15
 	.long	cr_alignment			@ r7
+#else
+	.long	0
+#endif
 	.long	init_thread_union + THREAD_START_SP @ sp
 	.size	__mmap_switched_data, . - __mmap_switched_data
 
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 8fc2c8f..d37a02fa 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -457,9 +457,13 @@  static void __init setup_processor(void)
 	cpu_cache = *list->cache;
 #endif
 
-	printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
+	printk("CPU: %s [%08x] revision %d (ARMv%s)",
 	       cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
-	       proc_arch[cpu_architecture()], cr_alignment);
+	       proc_arch[cpu_architecture()]);
+
+#ifdef CONFIG_CPU_CP15
+	printk(KERN_CONT ", cr=%08lx\n", cr_alignment);
+#endif
 
 	snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c",
 		 list->arch_name, ENDIANNESS);
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index c335c76..56da01c 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -89,7 +89,11 @@  core_param(alignment, ai_usermode, int, 0600);
 /* Return true if and only if the ARMv6 unaligned access model is in use. */
 static bool cpu_is_v6_unaligned(void)
 {
+#ifdef CONFIG_CPU_CP15
 	return cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U);
+#else
+	return 0;
+#endif
 }
 
 static int safe_usermode(int new_usermode, bool warn)
@@ -961,12 +965,14 @@  static int __init alignment_init(void)
 		return -ENOMEM;
 #endif
 
+#ifdef CONFIG_CPU_CP15
 	if (cpu_is_v6_unaligned()) {
 		cr_alignment &= ~CR_A;
 		cr_no_alignment &= ~CR_A;
 		set_cr(cr_alignment);
 		ai_usermode = safe_usermode(ai_usermode, false);
 	}
+#endif
 
 	hook_fault_code(1, do_alignment, SIGBUS, BUS_ADRALN,
 			"alignment exception");
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 8b8446a..d5a170a 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -106,8 +106,10 @@  static int __init early_cachepolicy(char *p)
 	for (i = 0; i < ARRAY_SIZE(cache_policies); i++) {
 		if (strcmp(p, cache_policies[i].policy) == 0) {
 			cachepolicy = i;
+#ifdef CONFIG_CPU_CP15
 			cr_alignment &= ~cache_policies[i].cr_mask;
 			cr_no_alignment &= ~cache_policies[i].cr_mask;
+#endif
 			break;
 		}
 	}
@@ -125,7 +127,9 @@  static int __init early_cachepolicy(char *p)
 		cachepolicy = CPOLICY_WRITEBACK;
 	}
 	flush_cache_all();
+#ifdef CONFIG_CPU_CP15
 	set_cr(cr_alignment);
+#endif
 	return 0;
 }
 early_param("cachepolicy", early_cachepolicy);
@@ -158,6 +162,7 @@  static int __init early_ecc(char *p)
 }
 early_param("ecc", early_ecc);
 
+#ifdef CONFIG_CPU_CP15
 static int __init noalign_setup(char *__unused)
 {
 	cr_alignment &= ~CR_A;
@@ -166,8 +171,9 @@  static int __init noalign_setup(char *__unused)
 	return 1;
 }
 __setup("noalign", noalign_setup);
+#endif
 
-#ifndef CONFIG_SMP
+#if !defined(CONFIG_SMP) && defined(CONFIG_CPU_CP15)
 void adjust_cr(unsigned long mask, unsigned long set)
 {
 	unsigned long flags;