Skip to contentSkip to conversation

Cortex-M3 support

RFC PATCH New Uwe Kleine-König 7 participants 40 messages Jan 22, 2012 – Mar 13, 2012

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover Cortex-M3 support

Hello,

this series is mostly a port of patches done by Catalin Marinas for 2.6.33. It's based on 3.3-rc1. There are still a few rough edges and I'm sure I'm not aware of all of them as this deep architecture stuff is mostly news for me. Some things are noted in the respective patches, I'm sure you can find more.

My target machine is the EFM32 Giant Gecko by Energy Micro and my complete tree can be found at

git://git.pengutronix.de/git/ukl/linux.git efm32

(with a gitweb being available at

	http://git.pengutronix.de/?p=ukl/linux.git;a=shortlog;h=efm32

).

I look forward to your comments.

Best regards
Uwe

Signature · 2 lines
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
#1 lore raw

RFC PATCH 1/11 ARM: only show modules in the memory layout for MODULES=y

This line is irritating and wrong when modules are not supported, so don't show it then.

---
 arch/arm/mm/init.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
arch/arm/mm/init.c +4 -0
index 6ec1226..42d906f 100644
@@ -659,7 +659,9 @@ void __init mem_init(void)
 #ifdef CONFIG_HIGHMEM
 			"    pkmap   : 0x%08lx - 0x%08lx   (%4ld MB)\n"
 #endif
+#ifdef CONFIG_MODULES
 			"    modules : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+#endif
 			"      .text : 0x%p" " - 0x%p" "   (%4d kB)\n"
 			"      .init : 0x%p" " - 0x%p" "   (%4d kB)\n"
 			"      .data : 0x%p" " - 0x%p" "   (%4d kB)\n"
@@ -678,7 +680,9 @@ void __init mem_init(void)
 			MLM(PKMAP_BASE, (PKMAP_BASE) + (LAST_PKMAP) *
 				(PAGE_SIZE)),
 #endif
+#ifdef CONFIG_MODULES
 			MLM(MODULES_VADDR, MODULES_END),
+#endif
 
 			MLK_ROUNDUP(_text, _etext),
 			MLK_ROUNDUP(__init_begin, __init_end),
Signature · 1 line
1.7.8.3
#3 lore raw

RFC PATCH 2/11 ARM: add device tree blobs to .gitignore

In reply to Uwe Kleine-König

*.dtb files are a build result and so should be ignored.

Forwarded: id:1323808612-14976-1-git-send-email-u.kleine-koenig at pengutronix.de

---
 arch/arm/boot/.gitignore |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
arch/arm/boot/.gitignore +1 -0
index ce1c5ff..3c79f85 100644
@@ -3,3 +3,4 @@ zImage
 xipImage
 bootpImage
 uImage
+*.dtb
Signature · 1 line
1.7.8.3
#4 lore raw

RFC PATCH 3/11 ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15

In reply to Uwe Kleine-König
---
 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(-)
arch/arm/include/asm/system.h +2 -0
index e4c96cc..de46477 100644
@@ -185,6 +185,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 */
 
@@ -224,6 +225,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,
arch/arm/kernel/entry-armv.S +4 -0
index 3a456c6..15bfeff 100644
@@ -314,8 +314,10 @@ __pabt_svc:
 ENDPROC(__pabt_svc)
 
 	.align	5
+#ifdef CONFIG_CPU_CP15
 .LCcralign:
 	.word	cr_alignment
+#endif
 #ifdef MULTI_DABORT
 .LCprocfns:
 	.word	processor
@@ -1146,12 +1148,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
arch/arm/kernel/head-common.S +7 -2
index 854bd22..2f560c5 100644
@@ -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
 
arch/arm/kernel/setup.c +6 -2
index 129fbd5..3849737 100644
@@ -459,9 +459,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);
arch/arm/mm/alignment.c +6 -0
index caf14dc..119d178 100644
@@ -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(FAULT_CODE_ALIGNMENT, do_alignment, SIGBUS, BUS_ADRALN,
 			"alignment exception");
arch/arm/mm/mmu.c +7 -1
index 94c5a0c..f6dbe1a 100644
@@ -109,8 +109,10 @@ static int __init early_cachepolicy(char *p)
 
 		if (memcmp(p, cache_policies[i].policy, len) == 0) {
 			cachepolicy = i;
+#ifdef CONFIG_CPU_CP15
 			cr_alignment &= ~cache_policies[i].cr_mask;
 			cr_no_alignment &= ~cache_policies[i].cr_mask;
+#endif
 			break;
 		}
 	}
@@ -128,7 +130,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);
@@ -163,6 +167,7 @@ static int __init early_ecc(char *p)
 early_param("ecc", early_ecc);
 #endif
 
+#ifdef CONFIG_CPU_CP15
 static int __init noalign_setup(char *__unused)
 {
 	cr_alignment &= ~CR_A;
@@ -171,8 +176,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;
Signature · 1 line
1.7.8.3
#5 lore raw

RFC PATCH 3/11 ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15

Quoted 126 lines · Uwe Kleine-K?nig
---
 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(-)
arch/arm/include/asm/system.h +2 -0
index e4c96cc..de46477 100644
@@ -185,6 +185,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 */
 
@@ -224,6 +225,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,
arch/arm/kernel/entry-armv.S +4 -0
index 3a456c6..15bfeff 100644
@@ -314,8 +314,10 @@ __pabt_svc:
 ENDPROC(__pabt_svc)
 
 	.align	5
+#ifdef CONFIG_CPU_CP15
 .LCcralign:
 	.word	cr_alignment
+#endif
 #ifdef MULTI_DABORT
 .LCprocfns:
 	.word	processor
@@ -1146,12 +1148,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
arch/arm/kernel/head-common.S +7 -2
index 854bd22..2f560c5 100644
@@ -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
 
arch/arm/kernel/setup.c +6 -2
index 129fbd5..3849737 100644
@@ -459,9 +459,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);
arch/arm/mm/alignment.c +4 -0
index caf14dc..119d178 100644
@@ -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;

arch/arm/mm/alignment.c static int __init alignment_init(void) · line 975

Quoted 10 lines
arch/arm/mm/alignment.c +2 -0
 #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

why if CPU_CP15 is not supported cpu_is_v6_unaligned return 0

arch/arm/mm/mmu.c static int __init early_cachepolicy(char *p) · line 112

Quoted 12 lines
arch/arm/mm/alignment.c +0 -0
 	hook_fault_code(FAULT_CODE_ALIGNMENT, do_alignment, SIGBUS, BUS_ADRALN,
 			"alignment exception");
arch/arm/mm/mmu.c +1 -0
index 94c5a0c..f6dbe1a 100644
@@ -109,8 +109,10 @@ static int __init early_cachepolicy(char *p)
 
 		if (memcmp(p, cache_policies[i].policy, len) == 0) {
 			cachepolicy = i;
+#ifdef CONFIG_CPU_CP15

can you use if (IS_ENABLED(x)) instead

Best Regards,
J.

#6 lore raw

RFC PATCH 3/11 ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15

Hi Jean-Christophe,

Quoted 21 lines · Jean-Christophe PLAGNIOL-VILLARD
Quoted 20 lines · Uwe Kleine-K?nig
arch/arm/mm/alignment.c +4 -0
index caf14dc..119d178 100644
@@ -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
 
Quoted 9 lines

arch/arm/mm/alignment.c static int __init alignment_init(void) · line 975

Quoted 8 lines
arch/arm/mm/alignment.c +2 -0
+#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

why if CPU_CP15 is not supported cpu_is_v6_unaligned return 0

on v7M I could probably check the CCR register's UNALIGN_TRP flag which has the semantic matching the CP15 U-flag. I don't know how a v7m machine should be handled here. The only affected (and relevant) code is in safe_usermode():

	/*
	 * ARMv6 and later CPUs can perform unaligned accesses for
	 * most single load and store instructions up to word size.
	 * LDM, STM, LDRD and STRD still need to be handled.
	 *
	 * Ignoring the alignment fault is not an option on these
	 * CPUs since we spin re-faulting the instruction without
	 * making any progress.
	 */
	if (cpu_is_v6_unaligned() && !(new_usermode & (UM_FIXUP | UM_SIGNAL))) {
		new_usermode |= UM_FIXUP;

		if (warn)
			printk(KERN_WARNING "alignment: ignoring faults is unsafe on this CPU.	Defaulting to fixup mode.\n");
	}

	return new_usermode;

Does this apply for v7m, too? If so, cpu_is_v6_unaligned needs fixing. Catalin? Russell?

Quoted 8 lines
Quoted 8 lines
arch/arm/mm/alignment.c +0 -0
 	hook_fault_code(FAULT_CODE_ALIGNMENT, do_alignment, SIGBUS, BUS_ADRALN,
 			"alignment exception");
arch/arm/mm/mmu.c +0 -0
index 94c5a0c..f6dbe1a 100644
@@ -109,8 +109,10 @@ static int __init early_cachepolicy(char *p)
 
Quoted 4 lines

arch/arm/mm/mmu.c static int __init early_cachepolicy(char *p) · line 112

Quoted 3 lines
arch/arm/mm/mmu.c +1 -0
 		if (memcmp(p, cache_policies[i].policy, len) == 0) {
 			cachepolicy = i;
+#ifdef CONFIG_CPU_CP15

can you use if (IS_ENABLED(x)) instead

IS_ENABLED is defined as:

	#define IS_ENABLED(option) (__enabled_ ## option || __enabled_ ## option ## _MODULE)

CPU_CP15 isn't tristate, so I don't see the benefit.

Best regards
Uwe

Signature · 2 lines
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
#7 lore raw

RFC PATCH 4/11 ARM: Add a printk loglevel modifier

In reply to Uwe Kleine-König

This is a needed followup for

ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15

otherwise no newline is printed for !CONFIG_CPU_CP15

---
Should this be folded into the

ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15

patch? Or should it come before it?

---
 arch/arm/kernel/setup.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
arch/arm/kernel/setup.c +1 -1
index 3849737..f7c0d55 100644
@@ -326,7 +326,7 @@ static void __init cacheid_init(void)
 		cacheid = CACHEID_VIVT;
 	}
 
-	printk("CPU: %s data cache, %s instruction cache\n",
+	printk(KERN_INFO "CPU: %s data cache, %s instruction cache\n",
 		cache_is_vivt() ? "VIVT" :
 		cache_is_vipt_aliasing() ? "VIPT aliasing" :
 		cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown",
Signature · 1 line
1.7.8.3
#8 lore raw

RFC PATCH 4/11 ARM: Add a printk loglevel modifier

Quoted 22 lines · Uwe Kleine-K?nig

This is a needed followup for

ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15

otherwise no newline is printed for !CONFIG_CPU_CP15

---
Should this be folded into the

ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15

patch? Or should it come before it?

---
 arch/arm/kernel/setup.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
arch/arm/kernel/setup.c +0 -0
index 3849737..f7c0d55 100644

arch/arm/kernel/setup.c static void __init cacheid_init(void) · line 332

Quoted 8 lines
arch/arm/kernel/setup.c +1 -1
@@ -326,7 +326,7 @@ static void __init cacheid_init(void)
 		cacheid = CACHEID_VIVT;
 	}
 
-	printk("CPU: %s data cache, %s instruction cache\n",
+	printk(KERN_INFO "CPU: %s data cache, %s instruction cache\n",
 		cache_is_vivt() ? "VIVT" :
 		cache_is_vipt_aliasing() ? "VIPT aliasing" :
 		cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown",

pr_info?

Best Regrds,
J.

#9 lore raw

RFC PATCH 5/11 ARM: provide XIP_VIRT_ADDR for no-MMU builds

In reply to Uwe Kleine-König

XIP_VIRT_ADDR is needed for XIP builds and currently only defined for builds with CONFIG_MMU.

Also provide it for no-MMU builds to make it possible to build an XIP kernel for MMU-less machines. As these lack an MMU it has to be an identity mapping.

Forwarded: id:1323467451-12128-1-git-send-email-u.kleine-koenig at pengutronix.de

---
 arch/arm/include/asm/memory.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
arch/arm/include/asm/memory.h +2 -0
index a8997d7..fcb5757 100644
@@ -116,6 +116,8 @@
 #define MODULES_END		(END_MEM)
 #define MODULES_VADDR		(PHYS_OFFSET)
 
+#define XIP_VIRT_ADDR(physaddr)  (physaddr)
+
 #endif /* !CONFIG_MMU */
 
 /*
Signature · 1 line
1.7.8.3
#10 lore raw

RFC PATCH 6/11 Cortex-M3: Add base support for Cortex-M3

In reply to Uwe Kleine-König

From: Catalin Marinas <[email protected]>

This patch adds the base support for the Cortex-M3 processor (ARMv7-M architecture). It consists of the corresponding arch/arm/mm/ files and various #ifdef's around the kernel. Exception handling is implemented by a subsequent patch.

[ukleinek: squash in some changes originating from commit

b5717ba (Cortex-M3: Add support for the Microcontroller Prototyping System)

from the v2.6.33-arm1 patch stack, port to post 3.2, drop zImage support, and a few cosmetic changes]

---
Russell already pointed out that setmode being empty looks wrong because it should handle the irq flag. According to Catalin there are hardly calling sides where this matters. I admit I didn't look at this, yet.

 arch/arm/include/asm/assembler.h  |   13 +++-
 arch/arm/include/asm/cputype.h    |    3 +
 arch/arm/include/asm/glue-cache.h |   24 +++++
 arch/arm/include/asm/glue-df.h    |    8 ++
 arch/arm/include/asm/glue-proc.h  |    9 ++
 arch/arm/include/asm/irqflags.h   |   51 ++++++++++-
 arch/arm/include/asm/processor.h  |    8 ++
 arch/arm/include/asm/ptrace.h     |   43 +++++++++-
 arch/arm/include/asm/system.h     |    3 +
 arch/arm/kernel/asm-offsets.c     |    3 +
 arch/arm/kernel/head-common.S     |    4 +-
 arch/arm/kernel/head-nommu.S      |    9 ++-
 arch/arm/kernel/setup.c           |   13 +++-
 arch/arm/kernel/traps.c           |    2 +
 arch/arm/mm/nommu.c               |    2 +
 arch/arm/mm/proc-v7m.S            |  178 +++++++++++++++++++++++++++++++++++++
 16 files changed, 363 insertions(+), 10 deletions(-)
 create mode 100644 arch/arm/mm/proc-v7m.S
arch/arm/include/asm/assembler.h +12 -1
index b6e65de..f2083c3 100644
@@ -133,7 +133,11 @@
  * assumes FIQs are enabled, and that the processor is in SVC mode.
  */
 	.macro	save_and_disable_irqs, oldcpsr
+#ifdef CONFIG_CPU_V7M
+	mrs	\oldcpsr, primask
+#else
 	mrs	\oldcpsr, cpsr
+#endif
 	disable_irq
 	.endm
 
@@ -142,7 +146,11 @@
  * guarantee that this will preserve the flags.
  */
 	.macro	restore_irqs_notrace, oldcpsr
+#ifdef CONFIG_CPU_V7M
+	msr	primask, \oldcpsr
+#else
 	msr	cpsr_c, \oldcpsr
+#endif
 	.endm
 
 	.macro restore_irqs, oldcpsr
@@ -221,7 +229,10 @@
 #endif
 	.endm
 
-#ifdef CONFIG_THUMB2_KERNEL
+#if defined(CONFIG_CPU_V7M)
+	.macro	setmode, mode, reg
+	.endm
+#elif defined(CONFIG_THUMB2_KERNEL)
 	.macro	setmode, mode, reg
 	mov	\reg, #\mode
 	msr	cpsr_c, \reg
arch/arm/include/asm/cputype.h +3 -0
index cb47d28..5bd8cb6 100644
@@ -46,6 +46,9 @@ extern unsigned int processor_id;
 		    : "cc");						\
 		__val;							\
 	})
+#elif defined(CONFIG_CPU_V7M)
+#define read_cpuid(reg) (*(unsigned int *)0xe000ed00)
+#define read_cpuid_ext(reg) 0
 #else
 #define read_cpuid(reg) (processor_id)
 #define read_cpuid_ext(reg) 0
arch/arm/include/asm/glue-cache.h +24 -0
index 7e30874..6a5fd0b 100644
@@ -125,10 +125,34 @@
 //# endif
 #endif
 
+#if defined(CONFIG_CPU_V7M)
+# ifdef _CACHE
+#  error "Multi-cache not supported on ARMv7-M"
+# else
+#  define _CACHE nop
+# endif
+#endif
+
 #if !defined(_CACHE) && !defined(MULTI_CACHE)
 #error Unknown cache maintenance model
 #endif
 
+#ifndef __ASSEMBLER__
+static inline void nop_flush_icache_all(void) { }
+static inline void nop_flush_kern_cache_all(void) { }
+static inline void nop_flush_user_cache_all(void) { }
+static inline void nop_flush_user_cache_range(unsigned long a, unsigned long b, unsigned int c) { }
+
+static inline void nop_coherent_kern_range(unsigned long a, unsigned long b) { }
+static inline void nop_coherent_user_range(unsigned long a, unsigned long b) { }
+static inline void nop_flush_kern_dcache_area(void *a, size_t s) { }
+
+static inline void nop_dma_flush_range(const void *a, const void *b) { }
+
+static inline void nop_dma_map_area(const void *s, size_t l, int f) { }
+static inline void nop_dma_unmap_area(const void *s, size_t l, int f) { }
+#endif
+
 #ifndef MULTI_CACHE
 #define __cpuc_flush_icache_all		__glue(_CACHE,_flush_icache_all)
 #define __cpuc_flush_kern_all		__glue(_CACHE,_flush_kern_cache_all)
arch/arm/include/asm/glue-df.h +8 -0
index 354d571..26be71c 100644
@@ -103,6 +103,14 @@
 # endif
 #endif
 
+#ifdef CONFIG_CPU_ABRT_NOMMU
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER nommu_early_abort
+# endif
+#endif
+
 #ifndef CPU_DABORT_HANDLER
 #error Unknown data abort handler type
 #endif
arch/arm/include/asm/glue-proc.h +9 -0
index e2be7f1..8f9991b 100644
@@ -248,6 +248,15 @@
 # endif
 #endif
 
+#ifdef CONFIG_CPU_V7M
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_v7m
+# endif
+#endif
+
 #ifndef MULTI_CPU
 #define cpu_proc_init			__glue(CPU_NAME,_proc_init)
 #define cpu_proc_fin			__glue(CPU_NAME,_proc_fin)
arch/arm/include/asm/irqflags.h +49 -2

72 lines not on this page · raw message

arch/arm/include/asm/processor.h +8 -0
index ce280b8..aa4c8a2 100644
@@ -49,7 +49,15 @@ struct thread_struct {
 #ifdef CONFIG_MMU
 #define nommu_start_thread(regs) do { } while (0)
 #else
+#ifndef CONFIG_CPU_V7M
 #define nommu_start_thread(regs) regs->ARM_r10 = current->mm->start_data
+#else
+#define nommu_start_thread(regs) do {					\
+	regs->ARM_r10 = current->mm->start_data;			\
+	regs->ARM_sp -= 32;		/* exception return state */	\
+	regs->ARM_EXC_lr = 0xfffffffdL;	/* exception lr */		\
+} while (0)
+#endif
 #endif
 
 #define start_thread(regs,pc,sp)					\
arch/arm/include/asm/ptrace.h +42 -1

86 lines not on this page · raw message

arch/arm/include/asm/system.h +3 -0
index de46477..16117ed 100644
@@ -13,6 +13,7 @@
 #define CPU_ARCH_ARMv5TEJ	7
 #define CPU_ARCH_ARMv6		8
 #define CPU_ARCH_ARMv7		9
+#define CPU_ARCH_ARMv7M		10
 
 /*
  * CR1 bits (CP#15 CR1)
@@ -232,7 +233,9 @@ static inline void set_copro_access(unsigned int val)
  * so enable interrupts over the context switch to avoid high
  * latency.
  */
+#ifndef CONFIG_CPU_V7M
 #define __ARCH_WANT_INTERRUPTS_ON_CTXSW
+#endif
 
 /*
  * switch_to(prev, next) should switch from task `prev' to `next'
arch/arm/kernel/asm-offsets.c +3 -0
index 1429d89..e861849 100644
@@ -91,6 +91,9 @@ int main(void)
   DEFINE(S_PC,			offsetof(struct pt_regs, ARM_pc));
   DEFINE(S_PSR,			offsetof(struct pt_regs, ARM_cpsr));
   DEFINE(S_OLD_R0,		offsetof(struct pt_regs, ARM_ORIG_r0));
+#ifdef CONFIG_CPU_V7M
+  DEFINE(S_EXC_LR,		offsetof(struct pt_regs, ARM_EXC_lr));
+#endif
   DEFINE(S_FRAME_SIZE,		sizeof(struct pt_regs));
   BLANK();
 #ifdef CONFIG_CACHE_L2X0
arch/arm/kernel/head-common.S +2 -2
index 2f560c5..2852c37 100644
@@ -100,7 +100,7 @@ __mmap_switched:
 	str	r2, [r6]			@ Save atags pointer
 	cmp	r7, #0
 	bicne	r4, r0, #CR_A			@ Clear 'A' bit
-	stmneia	r7, {r0, r4}			@ Save control register values
+	stmiane	r7, {r0, r4}			@ Save control register values
 	b	start_kernel
 ENDPROC(__mmap_switched)
 
@@ -117,7 +117,7 @@ __mmap_switched_data:
 #ifdef CONFIG_CPU_CP15
 	.long	cr_alignment			@ r7
 #else
-	.long	0
+	.long	0				@ r7
 #endif
 	.long	init_thread_union + THREAD_START_SP @ sp
 	.size	__mmap_switched_data, . - __mmap_switched_data
arch/arm/kernel/head-nommu.S +6 -3
index d46f259..dba31af 100644
@@ -44,10 +44,13 @@ ENTRY(stext)
 
 	setmode	PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
 						@ and irqs disabled
-#ifndef CONFIG_CPU_CP15
-	ldr	r9, =CONFIG_PROCESSOR_ID
-#else
+#if defined(CONFIG_CPU_CP15)
 	mrc	p15, 0, r9, c0, c0		@ get processor id
+#elif defined(CONFIG_CPU_V7M)
+	ldr	r9, =0xe000ed00			@ CPUID register address
+	ldr	r9, [r9]
+#else
+	ldr	r9, =CONFIG_PROCESSOR_ID
 #endif
 	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
 	movs	r10, r5				@ invalid processor (r5=0)?
arch/arm/kernel/setup.c +12 -1
index f7c0d55..da7b17d 100644
@@ -133,7 +133,9 @@ struct stack {
 	u32 und[3];
 } ____cacheline_aligned;
 
+#ifndef CONFIG_CPU_V7M
 static struct stack stacks[NR_CPUS];
+#endif
 
 char elf_platform[ELF_PLATFORM_SIZE];
 EXPORT_SYMBOL(elf_platform);
@@ -213,7 +215,7 @@ static const char *proc_arch[] = {
 	"5TEJ",
 	"6TEJ",
 	"7",
-	"?(11)",
+	"7M",
 	"?(12)",
 	"?(13)",
 	"?(14)",
@@ -222,6 +224,12 @@ static const char *proc_arch[] = {
 	"?(17)",
 };
 
+#ifdef CONFIG_CPU_V7M
+static int __get_cpu_architecture(void)
+{
+	return CPU_ARCH_ARMv7M;
+}
+#else
 static int __get_cpu_architecture(void)
 {
 	int cpu_arch;
@@ -254,6 +262,7 @@ static int __get_cpu_architecture(void)
 
 	return cpu_arch;
 }
+#endif
 
 int __pure cpu_architecture(void)
 {
@@ -381,6 +390,7 @@ static void __init feat_v6_fixup(void)
  */
 void cpu_init(void)
 {
+#ifndef CONFIG_CPU_V7M
 	unsigned int cpu = smp_processor_id();
 	struct stack *stk = &stacks[cpu];
 
@@ -425,6 +435,7 @@ void cpu_init(void)
 	      "I" (offsetof(struct stack, und[0])),
 	      PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
 	    : "r14");
+#endif
 }
 
 static void __init setup_processor(void)
arch/arm/kernel/traps.c +2 -0
index 99a5727..8956d08 100644
@@ -783,6 +783,7 @@ static void __init kuser_get_tls_init(unsigned long vectors)
 
 void __init early_trap_init(void)
 {
+#ifndef CONFIG_CPU_V7M
 #if defined(CONFIG_CPU_USE_DOMAINS)
 	unsigned long vectors = CONFIG_VECTORS_BASE;
 #else
@@ -818,4 +819,5 @@ void __init early_trap_init(void)
 
 	flush_icache_range(vectors, vectors + PAGE_SIZE);
 	modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
+#endif
 }
arch/arm/mm/nommu.c +2 -0
index 4fc6794..fdd49ac 100644
@@ -19,12 +19,14 @@
 
 void __init arm_mm_memblock_reserve(void)
 {
+#ifndef CONFIG_CPU_V7M
 	/*
 	 * Register the exception vector page.
 	 * some architectures which the DRAM is the exception vector to trap,
 	 * alloc_page breaks with error, although it is not NULL, but "0."
 	 */
 	memblock_reserve(CONFIG_VECTORS_BASE, PAGE_SIZE);
+#endif
 }
 
 void __init sanity_check_meminfo(void)
arch/arm/mm/proc-v7m.S new file +178 -0

178 lines not on this page · raw message

Signature · 1 line
1.7.8.3
#11 lore raw

RFC PATCH 6/11 Cortex-M3: Add base support for Cortex-M3

2012/1/22 Uwe Kleine-K?nig <[email protected]>:

Quoted 11 lines
arch/arm/kernel/head-common.S +0 -0
@@ -100,7 +100,7 @@ __mmap_switched:

? ? ? ?str ? ? r2, [r6] ? ? ? ? ? ? ? ? ? ? ? ?@ Save atags pointer ? ? ? ?cmp ? ? r7, #0
? ? ? ?bicne ? r4, r0, #CR_A ? ? ? ? ? ? ? ? ? @ Clear 'A' bit
- ? ? ? stmneia r7, {r0, r4} ? ? ? ? ? ? ? ? ? ?@ Save control register values
+ ? ? ? stmiane r7, {r0, r4} ? ? ? ? ? ? ? ? ? ?@ Save control register values ? ? ? ?b ? ? ? start_kernel
?ENDPROC(__mmap_switched)

This fixes one of previous patches, doesn't it?

Best Regards,
Micha? Miros?aw

#12 lore raw

RFC PATCH 6/11 Cortex-M3: Add base support for Cortex-M3

Hello Micha?,

Quoted 14 lines · Micha? Miros?aw

2012/1/22 Uwe Kleine-K?nig <[email protected]>:

Quoted 11 lines
arch/arm/kernel/head-common.S +0 -0
@@ -100,7 +100,7 @@ __mmap_switched:

? ? ? ?str ? ? r2, [r6] ? ? ? ? ? ? ? ? ? ? ? ?@ Save atags pointer ? ? ? ?cmp ? ? r7, #0
? ? ? ?bicne ? r4, r0, #CR_A ? ? ? ? ? ? ? ? ? @ Clear 'A' bit
- ? ? ? stmneia r7, {r0, r4} ? ? ? ? ? ? ? ? ? ?@ Save control register values
+ ? ? ? stmiane r7, {r0, r4} ? ? ? ? ? ? ? ? ? ?@ Save control register values ? ? ? ?b ? ? ? start_kernel
?ENDPROC(__mmap_switched)

This fixes one of previous patches, doesn't it?

Thanks for noticing, and no, stmiane is an undefined instruction, but only the non-thumb build barfs on that. It seems my conflict resolution failed somehow :-(. I fixed it now.

Thanks
Uwe

Signature · 2 lines
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
#13 lore raw

RFC PATCH 7/11 Cortex-M3: Add support for exception handling

In reply to Uwe Kleine-König

From: Catalin Marinas <[email protected]>

This patch implements the exception handling for the ARMv7-M architecture (pretty different from the A or R profiles).

[ukleinek: small adaptions, e.g. use show_regs instead of __show_regs in invalid_entry]

---
 arch/arm/kernel/entry-common.S |   18 +++++-
 arch/arm/kernel/entry-header.S |   94 ++++++++++++++++++++++++++++-
 arch/arm/kernel/entry-v7m.S    |  131 ++++++++++++++++++++++++++++++++++++++++
 arch/arm/kernel/process.c      |    8 +++
 4 files changed, 249 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/kernel/entry-v7m.S
arch/arm/kernel/entry-common.S +17 -1
index 520889c..95d3d4a 100644
@@ -43,7 +43,13 @@ ret_fast_syscall:
  * Ok, we need to do extra processing, enter the slow path.
  */
 fast_work_pending:
+#ifdef CONFIG_CPU_V7M
+	@ S_R0 not at the beginning of struct pt_regs
+	add	sp, #S_OFF
+	str	r0, [sp, #S_R0]			@ returned r0
+#else
 	str	r0, [sp, #S_R0+S_OFF]!		@ returned r0
+#endif
 work_pending:
 	tst	r1, #_TIF_NEED_RESCHED
 	bne	work_resched
@@ -342,6 +348,9 @@ ENDPROC(ftrace_stub)
 
 	.align	5
 ENTRY(vector_swi)
+#ifdef CONFIG_CPU_V7M
+	v7m_exception_entry
+#else
 	sub	sp, sp, #S_FRAME_SIZE
 	stmia	sp, {r0 - r12}			@ Calling r0 - r12
  ARM(	add	r8, sp, #S_PC		)
@@ -351,6 +360,7 @@ ENTRY(vector_swi)
 	mrs	r8, spsr			@ called from non-FIQ mode, so ok.
 	str	lr, [sp, #S_PC]			@ Save calling PC
 	str	r8, [sp, #S_PSR]		@ Save CPSR
+#endif
 	str	r0, [sp, #S_OLD_R0]		@ Save OLD_R0
 	zero_fp
 
@@ -470,14 +480,20 @@ __sys_trace:
 
 	adr	lr, BSYM(__sys_trace_return)	@ return address
 	mov	scno, r0			@ syscall number (possibly new)
-	add	r1, sp, #S_R0 + S_OFF		@ pointer to regs
+	add	r1, sp, #S_OFF			@ pointer to regs
 	cmp	scno, #NR_syscalls		@ check upper syscall limit
 	ldmccia	r1, {r0 - r3}			@ have to reload r0 - r3
 	ldrcc	pc, [tbl, scno, lsl #2]		@ call sys_* routine
 	b	2b
 
 __sys_trace_return:
+#ifdef CONFIG_CPU_V7M
+	@ S_R0 not at the beginning of struct pt_regs
+	add	sp, #S_OFF
+	str	r0, [sp, #S_R0]			@ save returned r0
+#else
 	str	r0, [sp, #S_R0 + S_OFF]!	@ save returned r0
+#endif
 	mov	r2, scno
 	mov	r1, sp
 	mov	r0, #1				@ trace exit [IP = 1]
arch/arm/kernel/entry-header.S +93 -1

118 lines not on this page · raw message

arch/arm/kernel/entry-v7m.S new file +131 -0

131 lines not on this page · raw message

arch/arm/kernel/process.c +8 -0
index 971d65c..ee604dd 100644
@@ -452,7 +452,11 @@ asm(	".pushsection .text\n"
 #ifdef CONFIG_TRACE_IRQFLAGS
 "	bl	trace_hardirqs_on\n"
 #endif
+#ifdef CONFIG_CPU_V7M
+"	msr	primask, r7\n"
+#else
 "	msr	cpsr_c, r7\n"
+#endif
 "	mov	r0, r4\n"
 "	mov	lr, r6\n"
 "	mov	pc, r5\n"
@@ -491,6 +495,10 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 	regs.ARM_r7 = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE;
 	regs.ARM_pc = (unsigned long)kernel_thread_helper;
 	regs.ARM_cpsr = regs.ARM_r7 | PSR_I_BIT;
+#ifdef CONFIG_CPU_V7M
+	/* Return to Handler mode */
+	regs.ARM_EXC_lr = 0xfffffff1L;
+#endif
 
 	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
 }
Signature · 1 line
1.7.8.3
#14 lore raw

RFC PATCH 8/11 Cortex-M3: Add NVIC support

In reply to Uwe Kleine-König

From: Catalin Marinas <[email protected]>

This patch implements the NVIC (interrupt controller) support for Cortex-M3.

[ukleinek: use a raw spinlock]

---
Actually it should be able to share much code with/use arch/arm/common/gic.c, but I didn't manage to get it up.

My problem is that I need hardware irq 13 but in gic.c hw_irq is set to at least 16. I guess I didn't understood something correctly and would be glad to get a tip who to fix that.

---
 arch/arm/common/Kconfig              |    3 +
 arch/arm/common/Makefile             |    1 +
 arch/arm/common/nvic.c               |   98 ++++++++++++++++++++++++++++++++++
 arch/arm/include/asm/hardware/nvic.h |   34 ++++++++++++
 4 files changed, 136 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/common/nvic.c
 create mode 100644 arch/arm/include/asm/hardware/nvic.h
arch/arm/common/Kconfig +3 -0
index 81a933e..74adbe7 100644
@@ -21,6 +21,9 @@ config ARM_VIC_NR
 	  The maximum number of VICs available in the system, for
 	  power management.
 
+config ARM_NVIC
+	bool
+
 config ICST
 	bool
 
arch/arm/common/Makefile +1 -0
index 6ea9b6f..102f5a2 100644
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_ARM_GIC)		+= gic.o
 obj-$(CONFIG_ARM_VIC)		+= vic.o
+obj-$(CONFIG_ARM_NVIC)		+= nvic.o
 obj-$(CONFIG_ICST)		+= icst.o
 obj-$(CONFIG_PL330)		+= pl330.o
 obj-$(CONFIG_SA1111)		+= sa1111.o
arch/arm/common/nvic.c new file +98 -0

98 lines not on this page · raw message

arch/arm/include/asm/hardware/nvic.h new file +34 -0
new file mode 100644
index 0000000..b7f8026
@@ -0,0 +1,34 @@
+/*
+ *  linux/include/asm-arm/hardware/nvic.h
+ *
+ *  Copyright (C) 2008 ARM Limited, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_ARM_HARDWARE_NVIC_H
+#define __ASM_ARM_HARDWARE_NVIC_H
+
+#include <linux/compiler.h>
+
+#define V7M_SCS				0xe000e000
+#define NVIC_INTR_CTRL			(V7M_SCS + 0x004)
+#define NVIC_SYSTICK_CTRL		(V7M_SCS + 0x010)
+#define NVIC_SYSTICK_RELOAD		(V7M_SCS + 0x014)
+#define NVIC_SYSTICK_CURRENT		(V7M_SCS + 0x018)
+#define NVIC_SYSTICK_CALIBRATION	(V7M_SCS + 0x01c)
+#define NVIC_SET_ENABLE			(V7M_SCS + 0x100)
+#define NVIC_CLEAR_ENABLE		(V7M_SCS + 0x180)
+#define NVIC_SET_PENDING		(V7M_SCS + 0x200)
+#define NVIC_CLEAR_PENDING		(V7M_SCS + 0x280)
+#define NVIC_ACTIVE_BIT			(V7M_SCS + 0x300)
+#define NVIC_PRIORITY			(V7M_SCS + 0x400)
+#define NVIC_INTR_CTRL_STATE		(V7M_SCS + 0xd04)
+#define NVIC_SOFTWARE_INTR		(V7M_SCS + 0xf00)
+
+#ifndef __ASSEMBLY__
+void nvic_init(void);
+#endif
+
+#endif
Signature · 1 line
1.7.8.3
#15 lore raw

RFC PATCH 8/11 Cortex-M3: Add NVIC support

Hello,

Quoted 8 lines · Uwe Kleine-K?nig

From: Catalin Marinas <[email protected]>

This patch implements the NVIC (interrupt controller) support for Cortex-M3.

[ukleinek: use a raw spinlock]
Quoted 7 lines

---
Actually it should be able to share much code with/use arch/arm/common/gic.c, but I didn't manage to get it up.

My problem is that I need hardware irq 13 but in gic.c hw_irq is set to at least 16. I guess I didn't understood something correctly and would be glad to get a tip who to fix that.

s/who/how/ of course.

I added a few people to Cc that recently touched arch/arm/common/gic.c.

Can anybody help?

Best regards
Uwe

Signature · 2 lines
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
#16 lore raw

RFC PATCH 9/11 Cortex-M3: Allow the building of Cortex-M3 kernel port

In reply to Uwe Kleine-König

From: Catalin Marinas <[email protected]>

This patch modifies the required Kconfig and Makefile files to allow the building of kernel for Cortex-M3.

[ukleinek: don't make CPU_V7M user visible]

---
 arch/arm/Kconfig         |    2 +-
 arch/arm/Kconfig-nommu   |    2 +-
 arch/arm/Makefile        |    1 +
 arch/arm/kernel/Makefile |    8 +++++++-
 arch/arm/mm/Kconfig      |   24 +++++++++++++++++++++++-
 arch/arm/mm/Makefile     |    1 +
 6 files changed, 34 insertions(+), 4 deletions(-)
arch/arm/Kconfig +1 -1
index 24626b0..ca9b48c 100644
@@ -1599,7 +1599,7 @@ config HZ
 
 config THUMB2_KERNEL
 	bool "Compile the kernel in Thumb-2 mode (EXPERIMENTAL)"
-	depends on CPU_V7 && !CPU_V6 && !CPU_V6K && EXPERIMENTAL
+	depends on (CPU_V7 || CPU_V7M) && !CPU_V6 && !CPU_V6K && EXPERIMENTAL
 	select AEABI
 	select ARM_ASM_UNIFIED
 	select ARM_UNWIND
arch/arm/Kconfig-nommu +1 -1
index 2cef8e1..c859495 100644
@@ -28,7 +28,7 @@ config FLASH_SIZE
 config PROCESSOR_ID
 	hex 'Hard wire the processor ID'
 	default 0x00007700
-	depends on !CPU_CP15
+	depends on !(CPU_CP15 || CPU_V7M)
 	help
 	  If processor has no CP15 register, this processor ID is
 	  used instead of the auto-probing which utilizes the register.
arch/arm/Makefile +1 -0
index 40319d9..e36b8b0 100644
@@ -57,6 +57,7 @@ comma = ,
 # Note that GCC does not numerically define an architecture version
 # macro, but instead defines a whole series of macros which makes
 # testing for a specific architecture or later rather impossible.
+arch-$(CONFIG_CPU_32v7M)	:=-D__LINUX_ARM_ARCH__=7 -march=armv7-m -Wa,-march=armv7-m
 arch-$(CONFIG_CPU_32v7)		:=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7-a,-march=armv5t -Wa$(comma)-march=armv7-a)
 arch-$(CONFIG_CPU_32v6)		:=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6)
 # Only override the compiler option if ARMv6. The ARMv6K extensions are
arch/arm/kernel/Makefile +7 -1
index 43b740d..32e96e6 100644
@@ -13,10 +13,16 @@ CFLAGS_REMOVE_return_address.o = -pg
 
 # Object file lists.
 
-obj-y		:= elf.o entry-armv.o entry-common.o irq.o opcodes.o \
+obj-y		:= elf.o entry-common.o irq.o opcodes.o \
 		   process.o ptrace.o return_address.o setup.o signal.o \
 		   sys_arm.o stacktrace.o time.o traps.o
 
+ifeq ($(CONFIG_CPU_V7M),y)
+obj-y		+= entry-v7m.o
+else
+obj-y		+= entry-armv.o
+endif
+
 obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += compat.o
 
 obj-$(CONFIG_LEDS)		+= leds.o
arch/arm/mm/Kconfig +23 -1
index 4cefb57..0b57034 100644
@@ -429,6 +429,18 @@ config CPU_V7
 	select CPU_COPY_V6 if MMU
 	select CPU_TLB_V7 if MMU
 
+# ARMv7
+config CPU_V7M
+	bool
+	select THUMB2_KERNEL
+	select ARM_THUMB
+	select CPU_32v7M
+	select CPU_32v6K
+	select CPU_ABRT_NOMMU
+	select CPU_PABRT_LEGACY
+	select CPU_CACHE_V7M
+	select CPU_CACHE_VIPT
+
 # Figure out what processor architecture version we should be using.
 # This defines the compiler instruction set which depends on the machine type.
 config CPU_32v3
@@ -466,6 +478,9 @@ config CPU_32v6K
 config CPU_32v7
 	bool
 
+config CPU_32v7M
+	bool
+
 # The abort model
 config CPU_ABRT_NOMMU
 	bool
@@ -519,6 +534,9 @@ config CPU_CACHE_V6
 config CPU_CACHE_V7
 	bool
 
+config CPU_CACHE_V7M
+	bool
+
 config CPU_CACHE_VIVT
 	bool
 
@@ -648,7 +666,11 @@ config ARCH_DMA_ADDR_T_64BIT
 
 config ARM_THUMB
 	bool "Support Thumb user binaries"
-	depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_V6 || CPU_V6K || CPU_V7 || CPU_FEROCEON
+	depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || \
+		CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || \
+		CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || \
+		CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_V6 || CPU_V6K || CPU_V7 || \
+		CPU_FEROCEON || CPU_V7M
 	default y
 	help
 	  Say Y if you want to include kernel support for running user space
arch/arm/mm/Makefile +1 -0
index bca7e61..3f94178 100644
@@ -92,6 +92,7 @@ obj-$(CONFIG_CPU_FEROCEON)	+= proc-feroceon.o
 obj-$(CONFIG_CPU_V6)		+= proc-v6.o
 obj-$(CONFIG_CPU_V6K)		+= proc-v6.o
 obj-$(CONFIG_CPU_V7)		+= proc-v7.o
+obj-$(CONFIG_CPU_V7M)		+= proc-v7m.o
 
 AFLAGS_proc-v6.o	:=-Wa,-march=armv6
 AFLAGS_proc-v7.o	:=-Wa,-march=armv7-a
Signature · 1 line
1.7.8.3
#17 lore raw

RFC PATCH 9/11 Cortex-M3: Allow the building of Cortex-M3 kernel port

2012/1/22 Uwe Kleine-K?nig <[email protected]>:
[...]

Quoted 11 lines
arch/arm/kernel/Makefile +0 -0
@@ -13,10 +13,16 @@ CFLAGS_REMOVE_return_address.o = -pg
 

?# Object file lists.

arch/arm/kernel/Makefile +1 -1
-obj-y ? ? ? ? ?:= elf.o entry-armv.o entry-common.o irq.o opcodes.o \
+obj-y ? ? ? ? ?:= elf.o entry-common.o irq.o opcodes.o \

? ? ? ? ? ? ? ? ? process.o ptrace.o return_address.o setup.o signal.o \
? ? ? ? ? ? ? ? ? sys_arm.o stacktrace.o time.o traps.o

arch/arm/kernel/Makefile CFLAGS_REMOVE_return_address.o = -pg · line 25

Quoted 6 lines
arch/arm/kernel/Makefile +6 -0
+ifeq ($(CONFIG_CPU_V7M),y)
+obj-y ? ? ? ? ?+= entry-v7m.o
+else
+obj-y ? ? ? ? ?+= entry-armv.o
+endif
+

Maybe something shorter, like this? '-)

obj-$(CONFIG_CPU_V7M) += entry-v7m.o
obj-$(if $(CONFIG_CPU_V7M),,y) += entry-armv.o

Best Regards,
Micha? Miros?aw

#18 lore raw

RFC PATCH 9/11 Cortex-M3: Allow the building of Cortex-M3 kernel port

Quoted 22 lines · Micha? Miros?aw

2012/1/22 Uwe Kleine-K?nig <[email protected]>:
[...]

Quoted 11 lines
arch/arm/kernel/Makefile +0 -0
@@ -13,10 +13,16 @@ CFLAGS_REMOVE_return_address.o = -pg
 

?# Object file lists.

arch/arm/kernel/Makefile +1 -1
-obj-y ? ? ? ? ?:= elf.o entry-armv.o entry-common.o irq.o opcodes.o \
+obj-y ? ? ? ? ?:= elf.o entry-common.o irq.o opcodes.o \

? ? ? ? ? ? ? ? ? process.o ptrace.o return_address.o setup.o signal.o \
? ? ? ? ? ? ? ? ? sys_arm.o stacktrace.o time.o traps.o

arch/arm/kernel/Makefile CFLAGS_REMOVE_return_address.o = -pg · line 25

Quoted 6 lines
arch/arm/kernel/Makefile +6 -0
+ifeq ($(CONFIG_CPU_V7M),y)
+obj-y ? ? ? ? ?+= entry-v7m.o
+else
+obj-y ? ? ? ? ?+= entry-armv.o
+endif
+

Maybe something shorter, like this? '-)

Quoted 2 lines

obj-$(CONFIG_CPU_V7M) += entry-v7m.o
obj-$(if $(CONFIG_CPU_V7M),,y) += entry-armv.o

It's shorter, but for readability I prefer my version.

Best regards
Uwe

Signature · 2 lines
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
#19 lore raw

RFC PATCH 10/11 Cortex-M3: Add VFP support

In reply to Uwe Kleine-König

From: Catalin Marinas <[email protected]>

This patch adds support for the ARMv7-M VFP extension. It uses the lazy state preservation mechanism available in hardware for the S0-S15 registers. The S16-S32 registers are saved at a context switch if the thread being scheduled out ever used the VFP. Similarly, the S16-S31 registers are restored if the thread being scheduled in ever used the VFP.

---
 arch/arm/Kconfig               |    7 +++
 arch/arm/include/asm/fpstate.h |    3 +
 arch/arm/kernel/Makefile       |    2 +
 arch/arm/kernel/asm-offsets.c  |    3 +
 arch/arm/kernel/entry-header.S |   14 ++++++
 arch/arm/kernel/vfp-m.c        |  102 ++++++++++++++++++++++++++++++++++++++++
 6 files changed, 131 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/kernel/vfp-m.c
arch/arm/Kconfig +7 -0
index ca9b48c..c5caeee 100644
@@ -2227,6 +2227,13 @@ config NEON
 	  Say Y to include support code for NEON, the ARMv7 Advanced SIMD
 	  Extension.
 
+config VFPM
+	bool "ARMv7-M VFP Extension support"
+	depends on CPU_V7M
+	help
+	  Say Y to include support for the ARMv7-M VFP Extension
+	  (single-precision floating point hardware).
+
 endmenu
 
 menu "Userspace binary formats"
arch/arm/include/asm/fpstate.h +3 -0
index 3ad4c10..e18c3d9 100644
@@ -43,6 +43,9 @@ struct vfp_hard_struct {
 #ifdef CONFIG_SMP
 	__u32 cpu;
 #endif
+#ifdef CONFIG_VFPM
+	__u32 clean;
+#endif
 };
 
 union vfp_state {
arch/arm/kernel/Makefile +2 -0
index 32e96e6..66d6c92 100644
@@ -81,6 +81,8 @@ obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
 AFLAGS_iwmmxt.o			:= -Wa,-mcpu=iwmmxt
 obj-$(CONFIG_ARM_CPU_TOPOLOGY)  += topology.o
 
+obj-$(CONFIG_VFPM)		+= vfp-m.o
+
 ifneq ($(CONFIG_ARCH_EBSA110),y)
   obj-y		+= io.o
 endif
arch/arm/kernel/asm-offsets.c +3 -0
index e861849..10ec416 100644
@@ -60,6 +60,9 @@ int main(void)
   DEFINE(TI_TP_VALUE,		offsetof(struct thread_info, tp_value));
   DEFINE(TI_FPSTATE,		offsetof(struct thread_info, fpstate));
   DEFINE(TI_VFPSTATE,		offsetof(struct thread_info, vfpstate));
+#ifdef CONFIG_VFPM
+  DEFINE(TI_VFPSTATE_CLEAN,	offsetof(struct thread_info, vfpstate.hard.clean));
+#endif
 #ifdef CONFIG_SMP
   DEFINE(VFP_CPU,		offsetof(union vfp_state, hard.cpu));
 #endif
arch/arm/kernel/entry-header.S +14 -0
index 8050d9b..cb38aff 100644
@@ -72,7 +72,15 @@
  */
 	.macro	v7m_exception_entry
 	cpsid	i
+#ifdef CONFIG_VFPM
+	get_thread_info r0
+	and	r1, lr, #1 << 4		@ VFP clean state
+	str	r1, [r0, #TI_VFPSTATE_CLEAN]
+#endif
 	cmp	lr, #0xfffffffd		@ check the return stack
+#ifdef CONFIG_VFPM
+	cmpne	lr, #0xffffffed
+#endif
 	beq	1f			@ exception on process stack
 	add	r12, sp, #32		@ MSP before exception
 	stmdb	sp!, {r4-r12, lr}	@ push unsaved registers
@@ -90,6 +98,9 @@
 	.macro	v7m_exception_fast_exit
 	ldmia	sp!, {r4-r12, lr}	@ restore previously saved state
 	cmp	lr, #0xfffffffd		@ check the return stack
+#ifdef CONFIG_VFPM
+	cmpne	lr, #0xffffffed
+#endif
 	addeq	sp, #32			@ returning to PSP, just restore MSP
 	cpsie	i
 	bx	lr
@@ -99,6 +110,9 @@
 	cpsid	i
 	ldr	lr, [sp, #S_EXC_LR]	@ read exception LR
 	cmp	lr, #0xfffffffd		@ check the return stack
+#ifdef CONFIG_VFPM
+	cmpne	lr, #0xffffffed
+#endif
 	beq	1f			@ returning to PSP
 	@ Prepare the MSP stack
 	ldmia	sp, {r4-r11}		@ restore previously saved state
arch/arm/kernel/vfp-m.c new file +102 -0

102 lines not on this page · raw message

Signature · 1 line
1.7.8.3
#20 lore raw

RFC PATCH 11/11 HACK! ARM: no, we don't enter in ARM

In reply to Uwe Kleine-König

... as a Cortex-M3 can only do Thumb-2 ...

---
This probably needs a new Kconfig symbol as THUMB2_KERNEL doesn't have the right meaning. Something like "CPU_THUMB_ONLY"?

---
 arch/arm/kernel/head-nommu.S |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)
arch/arm/kernel/head-nommu.S +4 -3
index dba31af..bb94ce4 100644
@@ -32,13 +32,14 @@
  * numbers for r1.
  *
  */
-	.arm
+
+	@.arm
 
 	__HEAD
 ENTRY(stext)
 
- THUMB(	adr	r9, BSYM(1f)	)	@ Kernel is always entered in ARM.
- THUMB(	bx	r9		)	@ If this is a Thumb-2 kernel,
+ @THUMB(	adr	r9, BSYM(1f)	)	@ Kernel is always entered in ARM.
+ @THUMB(	bx	r9		)	@ If this is a Thumb-2 kernel,
  THUMB(	.thumb			)	@ switch to Thumb now.
  THUMB(1:			)
 
Signature · 1 line
1.7.8.3
#21 lore raw

cover Cortex-M3 support

In reply to Uwe Kleine-König
Quoted 11 lines · Uwe Kleine-K?nig

this series is mostly a port of patches done by Catalin Marinas for 2.6.33. It's based on 3.3-rc1. There are still a few rough edges and I'm sure I'm not aware of all of them as this deep architecture stuff is mostly news for me. Some things are noted in the respective patches, I'm sure you can find more.

My target machine is the EFM32 Giant Gecko by Energy Micro and my complete tree can be found at

git://git.pengutronix.de/git/ukl/linux.git efm32

Quoted 7 lines

(with a gitweb being available at

	http://git.pengutronix.de/?p=ukl/linux.git;a=shortlog;h=efm32

).

I look forward to your comments.

I didn't get much comments apart from a few trivial ones. I'd like to plan how to go forward here.

Catalin, Russell, I guess it's just lack of time on your side that you didn't comment?

There are a few things to fix and follow up (e.g. platform support, ftrace, adapt unwinding to the v7m model), but I first want to see the base patches in before I invest the time to address these.

Best regards
Uwe

Signature · 2 lines
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
#22 lore raw

cover Cortex-M3 support

Quoted 22 lines · Uwe Kleine-K?nig
Quoted 11 lines · Uwe Kleine-K?nig

this series is mostly a port of patches done by Catalin Marinas for 2.6.33. It's based on 3.3-rc1. There are still a few rough edges and I'm sure I'm not aware of all of them as this deep architecture stuff is mostly news for me. Some things are noted in the respective patches, I'm sure you can find more.

My target machine is the EFM32 Giant Gecko by Energy Micro and my complete tree can be found at

git://git.pengutronix.de/git/ukl/linux.git efm32

Quoted 7 lines

(with a gitweb being available at

	http://git.pengutronix.de/?p=ukl/linux.git;a=shortlog;h=efm32

).

I look forward to your comments.

I didn't get much comments apart from a few trivial ones. I'd like to plan how to go forward here.

Quoted 6 lines

Catalin, Russell, I guess it's just lack of time on your side that you didn't comment?

There are a few things to fix and follow up (e.g. platform support, ftrace, adapt unwinding to the v7m model), but I first want to see the base patches in before I invest the time to address these.

I improved a few things, most notably I fixed a stack overflow. Other than that the following changes are included, too:

- update to 3.3-rc3
- only check bit 3 of lr to determine which mode the machine was in when the current exception triggered
- several updates to the efm32 platform (that should IMHO only go in when the M3 support is available in mainline)

I'd be really happy to get some feedback on Catalin's and my patches and will repost the patches I think are mature enough to go in for a start.

The updated and complete stack is available from the URLs above.

Best regards
Uwe

Signature · 2 lines
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
#23 lore raw

PATCH 1/5 ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15

---
 arch/arm/include/asm/system.h |    2 ++
 arch/arm/kernel/entry-armv.S  |    4 ++++
 arch/arm/kernel/head-common.S |   10 ++++++++--
 arch/arm/kernel/setup.c       |    8 ++++++--
 arch/arm/mm/alignment.c       |    6 ++++++
 arch/arm/mm/mmu.c             |    8 +++++++-
 6 files changed, 33 insertions(+), 5 deletions(-)
arch/arm/include/asm/system.h +2 -0
index e4c96cc..de46477 100644
@@ -185,6 +185,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 */
 
@@ -224,6 +225,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,
arch/arm/kernel/entry-armv.S +4 -0
index be16a48..a6f2ef5 100644
@@ -314,8 +314,10 @@ __pabt_svc:
 ENDPROC(__pabt_svc)
 
 	.align	5
+#ifdef CONFIG_CPU_CP15
 .LCcralign:
 	.word	cr_alignment
+#endif
 #ifdef MULTI_DABORT
 .LCprocfns:
 	.word	processor
@@ -1146,12 +1148,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
arch/arm/kernel/head-common.S +8 -2
index 854bd22..5ca01bb 100644
@@ -98,8 +98,10 @@ __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
+	itt	ne
+	bicne	r4, r0, #CR_A			@ Clear 'A' bit
+	stmneia	r7, {r0, r4}			@ Save control register values
 	b	start_kernel
 ENDPROC(__mmap_switched)
 
@@ -113,7 +115,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
 
arch/arm/kernel/setup.c +6 -2
index a255c39..50d3df8 100644
@@ -472,9 +472,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);
arch/arm/mm/alignment.c +6 -0
index caf14dc..119d178 100644
@@ -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(FAULT_CODE_ALIGNMENT, do_alignment, SIGBUS, BUS_ADRALN,
 			"alignment exception");
arch/arm/mm/mmu.c +7 -1
index 94c5a0c..f6dbe1a 100644
@@ -109,8 +109,10 @@ static int __init early_cachepolicy(char *p)
 
 		if (memcmp(p, cache_policies[i].policy, len) == 0) {
 			cachepolicy = i;
+#ifdef CONFIG_CPU_CP15
 			cr_alignment &= ~cache_policies[i].cr_mask;
 			cr_no_alignment &= ~cache_policies[i].cr_mask;
+#endif
 			break;
 		}
 	}
@@ -128,7 +130,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);
@@ -163,6 +167,7 @@ static int __init early_ecc(char *p)
 early_param("ecc", early_ecc);
 #endif
 
+#ifdef CONFIG_CPU_CP15
 static int __init noalign_setup(char *__unused)
 {
 	cr_alignment &= ~CR_A;
@@ -171,8 +176,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;
Signature · 1 line
1.7.9
#24 lore raw

PATCH 2/5 ARM: Add a printk loglevel modifier

This is a needed followup for

ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15

otherwise no newline is printed for !CONFIG_CPU_CP15

---
Should this be folded into the

ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15

patch? Or should it come before it?

---
 arch/arm/kernel/setup.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
arch/arm/kernel/setup.c +1 -1
index 50d3df8..23893b1 100644
@@ -325,7 +325,7 @@ static void __init cacheid_init(void)
 		cacheid = CACHEID_VIVT;
 	}
 
-	printk("CPU: %s data cache, %s instruction cache\n",
+	printk(KERN_INFO "CPU: %s data cache, %s instruction cache\n",
 		cache_is_vivt() ? "VIVT" :
 		cache_is_vipt_aliasing() ? "VIPT aliasing" :
 		cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown",
Signature · 1 line
1.7.9
#25 lore raw

PATCH 3/5 ARM: force branch instructions to use long distance encoding

In reply to Uwe Kleine-König

This fixes a linker error when the kernel image gets bigger than approx. 1 MiB.

This is done analogous to the change to head.S in commit

a75e524 (ARM: 6504/1: Thumb-2: Fix long-distance conditional branches in head.S for Thumb-2.)

---
 arch/arm/kernel/head-nommu.S |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
arch/arm/kernel/head-nommu.S +1 -0
index d46f259..1aca35d 100644
@@ -51,6 +51,7 @@ ENTRY(stext)
 #endif
 	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
 	movs	r10, r5				@ invalid processor (r5=0)?
+	it	eq
 	beq	__error_p				@ yes, error 'p'
 
 	adr	lr, BSYM(__after_proc_init)	@ return (PIC) address
Signature · 1 line
1.7.9
#26 lore raw

PATCH 4/5 ARM: Cortex-M3: Add base support for Cortex-M3

In reply to Uwe Kleine-König

From: Catalin Marinas <[email protected]>

This patch adds the base support for the Cortex-M3 processor (ARMv7-M architecture). It consists of the corresponding arch/arm/mm/ files and various #ifdef's around the kernel. Exception handling is implemented by a subsequent patch.

[ukleinek: squash in some changes originating from commit

b5717ba (Cortex-M3: Add support for the Microcontroller Prototyping System)

from the v2.6.33-arm1 patch stack, port to post 3.2, drop zImage support, and a few cosmetic changes]

---
 arch/arm/include/asm/assembler.h  |   13 +++-
 arch/arm/include/asm/cputype.h    |    3 +
 arch/arm/include/asm/glue-cache.h |   24 +++++
 arch/arm/include/asm/glue-df.h    |    8 ++
 arch/arm/include/asm/glue-proc.h  |    9 ++
 arch/arm/include/asm/irqflags.h   |   51 ++++++++++-
 arch/arm/include/asm/processor.h  |    8 ++
 arch/arm/include/asm/ptrace.h     |   43 +++++++++-
 arch/arm/include/asm/system.h     |    3 +
 arch/arm/kernel/asm-offsets.c     |    3 +
 arch/arm/kernel/head-common.S     |    2 +-
 arch/arm/kernel/head-nommu.S      |    9 ++-
 arch/arm/kernel/setup.c           |   13 +++-
 arch/arm/kernel/traps.c           |    2 +
 arch/arm/mm/nommu.c               |    2 +
 arch/arm/mm/proc-v7m.S            |  178 +++++++++++++++++++++++++++++++++++++
 16 files changed, 362 insertions(+), 9 deletions(-)
 create mode 100644 arch/arm/mm/proc-v7m.S
arch/arm/include/asm/assembler.h +12 -1
index 62f8095..1bafa39 100644
@@ -133,7 +133,11 @@
  * assumes FIQs are enabled, and that the processor is in SVC mode.
  */
 	.macro	save_and_disable_irqs, oldcpsr
+#ifdef CONFIG_CPU_V7M
+	mrs	\oldcpsr, primask
+#else
 	mrs	\oldcpsr, cpsr
+#endif
 	disable_irq
 	.endm
 
@@ -142,7 +146,11 @@
  * guarantee that this will preserve the flags.
  */
 	.macro	restore_irqs_notrace, oldcpsr
+#ifdef CONFIG_CPU_V7M
+	msr	primask, \oldcpsr
+#else
 	msr	cpsr_c, \oldcpsr
+#endif
 	.endm
 
 	.macro restore_irqs, oldcpsr
@@ -221,7 +229,10 @@
 #endif
 	.endm
 
-#ifdef CONFIG_THUMB2_KERNEL
+#if defined(CONFIG_CPU_V7M)
+	.macro	setmode, mode, reg
+	.endm
+#elif defined(CONFIG_THUMB2_KERNEL)
 	.macro	setmode, mode, reg
 	mov	\reg, #\mode
 	msr	cpsr_c, \reg
arch/arm/include/asm/cputype.h +3 -0
index cb47d28..5bd8cb6 100644
@@ -46,6 +46,9 @@ extern unsigned int processor_id;
 		    : "cc");						\
 		__val;							\
 	})
+#elif defined(CONFIG_CPU_V7M)
+#define read_cpuid(reg) (*(unsigned int *)0xe000ed00)
+#define read_cpuid_ext(reg) 0
 #else
 #define read_cpuid(reg) (processor_id)
 #define read_cpuid_ext(reg) 0
arch/arm/include/asm/glue-cache.h +24 -0
index 7e30874..6a5fd0b 100644
@@ -125,10 +125,34 @@
 //# endif
 #endif
 
+#if defined(CONFIG_CPU_V7M)
+# ifdef _CACHE
+#  error "Multi-cache not supported on ARMv7-M"
+# else
+#  define _CACHE nop
+# endif
+#endif
+
 #if !defined(_CACHE) && !defined(MULTI_CACHE)
 #error Unknown cache maintenance model
 #endif
 
+#ifndef __ASSEMBLER__
+static inline void nop_flush_icache_all(void) { }
+static inline void nop_flush_kern_cache_all(void) { }
+static inline void nop_flush_user_cache_all(void) { }
+static inline void nop_flush_user_cache_range(unsigned long a, unsigned long b, unsigned int c) { }
+
+static inline void nop_coherent_kern_range(unsigned long a, unsigned long b) { }
+static inline void nop_coherent_user_range(unsigned long a, unsigned long b) { }
+static inline void nop_flush_kern_dcache_area(void *a, size_t s) { }
+
+static inline void nop_dma_flush_range(const void *a, const void *b) { }
+
+static inline void nop_dma_map_area(const void *s, size_t l, int f) { }
+static inline void nop_dma_unmap_area(const void *s, size_t l, int f) { }
+#endif
+
 #ifndef MULTI_CACHE
 #define __cpuc_flush_icache_all		__glue(_CACHE,_flush_icache_all)
 #define __cpuc_flush_kern_all		__glue(_CACHE,_flush_kern_cache_all)
arch/arm/include/asm/glue-df.h +8 -0
index 354d571..26be71c 100644
@@ -103,6 +103,14 @@
 # endif
 #endif
 
+#ifdef CONFIG_CPU_ABRT_NOMMU
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER nommu_early_abort
+# endif
+#endif
+
 #ifndef CPU_DABORT_HANDLER
 #error Unknown data abort handler type
 #endif
arch/arm/include/asm/glue-proc.h +9 -0
index e2be7f1..8f9991b 100644
@@ -248,6 +248,15 @@
 # endif
 #endif
 
+#ifdef CONFIG_CPU_V7M
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_v7m
+# endif
+#endif
+
 #ifndef MULTI_CPU
 #define cpu_proc_init			__glue(CPU_NAME,_proc_init)
 #define cpu_proc_fin			__glue(CPU_NAME,_proc_fin)
arch/arm/include/asm/irqflags.h +49 -2

72 lines not on this page · raw message

arch/arm/include/asm/processor.h +8 -0
index ce280b8..aa4c8a2 100644
@@ -49,7 +49,15 @@ struct thread_struct {
 #ifdef CONFIG_MMU
 #define nommu_start_thread(regs) do { } while (0)
 #else
+#ifndef CONFIG_CPU_V7M
 #define nommu_start_thread(regs) regs->ARM_r10 = current->mm->start_data
+#else
+#define nommu_start_thread(regs) do {					\
+	regs->ARM_r10 = current->mm->start_data;			\
+	regs->ARM_sp -= 32;		/* exception return state */	\
+	regs->ARM_EXC_lr = 0xfffffffdL;	/* exception lr */		\
+} while (0)
+#endif
 #endif
 
 #define start_thread(regs,pc,sp)					\
arch/arm/include/asm/ptrace.h +42 -1

86 lines not on this page · raw message

arch/arm/include/asm/system.h +3 -0
index de46477..16117ed 100644
@@ -13,6 +13,7 @@
 #define CPU_ARCH_ARMv5TEJ	7
 #define CPU_ARCH_ARMv6		8
 #define CPU_ARCH_ARMv7		9
+#define CPU_ARCH_ARMv7M		10
 
 /*
  * CR1 bits (CP#15 CR1)
@@ -232,7 +233,9 @@ static inline void set_copro_access(unsigned int val)
  * so enable interrupts over the context switch to avoid high
  * latency.
  */
+#ifndef CONFIG_CPU_V7M
 #define __ARCH_WANT_INTERRUPTS_ON_CTXSW
+#endif
 
 /*
  * switch_to(prev, next) should switch from task `prev' to `next'
arch/arm/kernel/asm-offsets.c +3 -0
index 1429d89..e861849 100644
@@ -91,6 +91,9 @@ int main(void)
   DEFINE(S_PC,			offsetof(struct pt_regs, ARM_pc));
   DEFINE(S_PSR,			offsetof(struct pt_regs, ARM_cpsr));
   DEFINE(S_OLD_R0,		offsetof(struct pt_regs, ARM_ORIG_r0));
+#ifdef CONFIG_CPU_V7M
+  DEFINE(S_EXC_LR,		offsetof(struct pt_regs, ARM_EXC_lr));
+#endif
   DEFINE(S_FRAME_SIZE,		sizeof(struct pt_regs));
   BLANK();
 #ifdef CONFIG_CACHE_L2X0
arch/arm/kernel/head-common.S +1 -1
index 5ca01bb..efeb2d0 100644
@@ -118,7 +118,7 @@ __mmap_switched_data:
 #ifdef CONFIG_CPU_CP15
 	.long	cr_alignment			@ r7
 #else
-	.long	0
+	.long	0				@ r7
 #endif
 	.long	init_thread_union + THREAD_START_SP @ sp
 	.size	__mmap_switched_data, . - __mmap_switched_data
arch/arm/kernel/head-nommu.S +6 -3
index 1aca35d..61ba029 100644
@@ -44,10 +44,13 @@ ENTRY(stext)
 
 	setmode	PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
 						@ and irqs disabled
-#ifndef CONFIG_CPU_CP15
-	ldr	r9, =CONFIG_PROCESSOR_ID
-#else
+#if defined(CONFIG_CPU_CP15)
 	mrc	p15, 0, r9, c0, c0		@ get processor id
+#elif defined(CONFIG_CPU_V7M)
+	ldr	r9, =0xe000ed00			@ CPUID register address
+	ldr	r9, [r9]
+#else
+	ldr	r9, =CONFIG_PROCESSOR_ID
 #endif
 	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
 	movs	r10, r5				@ invalid processor (r5=0)?
arch/arm/kernel/setup.c +12 -1
index 23893b1..d0fc5b8 100644
@@ -132,7 +132,9 @@ struct stack {
 	u32 und[3];
 } ____cacheline_aligned;
 
+#ifndef CONFIG_CPU_V7M
 static struct stack stacks[NR_CPUS];
+#endif
 
 char elf_platform[ELF_PLATFORM_SIZE];
 EXPORT_SYMBOL(elf_platform);
@@ -212,7 +214,7 @@ static const char *proc_arch[] = {
 	"5TEJ",
 	"6TEJ",
 	"7",
-	"?(11)",
+	"7M",
 	"?(12)",
 	"?(13)",
 	"?(14)",
@@ -221,6 +223,12 @@ static const char *proc_arch[] = {
 	"?(17)",
 };
 
+#ifdef CONFIG_CPU_V7M
+static int __get_cpu_architecture(void)
+{
+	return CPU_ARCH_ARMv7M;
+}
+#else
 static int __get_cpu_architecture(void)
 {
 	int cpu_arch;
@@ -253,6 +261,7 @@ static int __get_cpu_architecture(void)
 
 	return cpu_arch;
 }
+#endif
 
 int __pure cpu_architecture(void)
 {
@@ -380,6 +389,7 @@ static void __init feat_v6_fixup(void)
  */
 void cpu_init(void)
 {
+#ifndef CONFIG_CPU_V7M
 	unsigned int cpu = smp_processor_id();
 	struct stack *stk = &stacks[cpu];
 
@@ -424,6 +434,7 @@ void cpu_init(void)
 	      "I" (offsetof(struct stack, und[0])),
 	      PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
 	    : "r14");
+#endif
 }
 
 int __cpu_logical_map[NR_CPUS];
arch/arm/kernel/traps.c +2 -0
index 99a5727..8956d08 100644
@@ -783,6 +783,7 @@ static void __init kuser_get_tls_init(unsigned long vectors)
 
 void __init early_trap_init(void)
 {
+#ifndef CONFIG_CPU_V7M
 #if defined(CONFIG_CPU_USE_DOMAINS)
 	unsigned long vectors = CONFIG_VECTORS_BASE;
 #else
@@ -818,4 +819,5 @@ void __init early_trap_init(void)
 
 	flush_icache_range(vectors, vectors + PAGE_SIZE);
 	modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
+#endif
 }
arch/arm/mm/nommu.c +2 -0
index 4fc6794..fdd49ac 100644
@@ -19,12 +19,14 @@
 
 void __init arm_mm_memblock_reserve(void)
 {
+#ifndef CONFIG_CPU_V7M
 	/*
 	 * Register the exception vector page.
 	 * some architectures which the DRAM is the exception vector to trap,
 	 * alloc_page breaks with error, although it is not NULL, but "0."
 	 */
 	memblock_reserve(CONFIG_VECTORS_BASE, PAGE_SIZE);
+#endif
 }
 
 void __init sanity_check_meminfo(void)
arch/arm/mm/proc-v7m.S new file +178 -0

178 lines not on this page · raw message

Signature · 1 line
1.7.9
#27 lore raw

PATCH 5/5 ARM: Cortex-M3: Add support for exception handling

In reply to Uwe Kleine-König

From: Catalin Marinas <[email protected]>

This patch implements the exception handling for the ARMv7-M architecture (pretty different from the A or R profiles).

[ukleinek: small adaptions, e.g. use show_regs instead of __show_regs in invalid_entry, fix stack corruption in v7m_exception_fast_exit, check for bit 3 in exception lr only instead of explicit values]

---
 arch/arm/kernel/entry-common.S |   18 +++++-
 arch/arm/kernel/entry-header.S |   94 ++++++++++++++++++++++++++++-
 arch/arm/kernel/entry-v7m.S    |  131 ++++++++++++++++++++++++++++++++++++++++
 arch/arm/kernel/process.c      |    8 +++
 4 files changed, 249 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/kernel/entry-v7m.S
arch/arm/kernel/entry-common.S +17 -1
index 9fd0ba9..4a12bc3 100644
@@ -43,7 +43,13 @@ ret_fast_syscall:
  * Ok, we need to do extra processing, enter the slow path.
  */
 fast_work_pending:
+#ifdef CONFIG_CPU_V7M
+	@ S_R0 not at the beginning of struct pt_regs
+	add	sp, #S_OFF
+	str	r0, [sp, #S_R0]			@ returned r0
+#else
 	str	r0, [sp, #S_R0+S_OFF]!		@ returned r0
+#endif
 work_pending:
 	tst	r1, #_TIF_NEED_RESCHED
 	bne	work_resched
@@ -345,6 +351,9 @@ ENDPROC(ftrace_stub)
 
 	.align	5
 ENTRY(vector_swi)
+#ifdef CONFIG_CPU_V7M
+	v7m_exception_entry
+#else
 	sub	sp, sp, #S_FRAME_SIZE
 	stmia	sp, {r0 - r12}			@ Calling r0 - r12
  ARM(	add	r8, sp, #S_PC		)
@@ -354,6 +363,7 @@ ENTRY(vector_swi)
 	mrs	r8, spsr			@ called from non-FIQ mode, so ok.
 	str	lr, [sp, #S_PC]			@ Save calling PC
 	str	r8, [sp, #S_PSR]		@ Save CPSR
+#endif
 	str	r0, [sp, #S_OLD_R0]		@ Save OLD_R0
 	zero_fp
 
@@ -473,14 +483,20 @@ __sys_trace:
 
 	adr	lr, BSYM(__sys_trace_return)	@ return address
 	mov	scno, r0			@ syscall number (possibly new)
-	add	r1, sp, #S_R0 + S_OFF		@ pointer to regs
+	add	r1, sp, #S_OFF			@ pointer to regs
 	cmp	scno, #NR_syscalls		@ check upper syscall limit
 	ldmccia	r1, {r0 - r3}			@ have to reload r0 - r3
 	ldrcc	pc, [tbl, scno, lsl #2]		@ call sys_* routine
 	b	2b
 
 __sys_trace_return:
+#ifdef CONFIG_CPU_V7M
+	@ S_R0 not at the beginning of struct pt_regs
+	add	sp, #S_OFF
+	str	r0, [sp, #S_R0]			@ save returned r0
+#else
 	str	r0, [sp, #S_R0 + S_OFF]!	@ save returned r0
+#endif
 	mov	r2, scno
 	mov	r1, sp
 	mov	r0, #1				@ trace exit [IP = 1]
arch/arm/kernel/entry-header.S +93 -1

118 lines not on this page · raw message

arch/arm/kernel/entry-v7m.S new file +131 -0

131 lines not on this page · raw message

arch/arm/kernel/process.c +8 -0
index 971d65c..ee604dd 100644
@@ -452,7 +452,11 @@ asm(	".pushsection .text\n"
 #ifdef CONFIG_TRACE_IRQFLAGS
 "	bl	trace_hardirqs_on\n"
 #endif
+#ifdef CONFIG_CPU_V7M
+"	msr	primask, r7\n"
+#else
 "	msr	cpsr_c, r7\n"
+#endif
 "	mov	r0, r4\n"
 "	mov	lr, r6\n"
 "	mov	pc, r5\n"
@@ -491,6 +495,10 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 	regs.ARM_r7 = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE;
 	regs.ARM_pc = (unsigned long)kernel_thread_helper;
 	regs.ARM_cpsr = regs.ARM_r7 | PSR_I_BIT;
+#ifdef CONFIG_CPU_V7M
+	/* Return to Handler mode */
+	regs.ARM_EXC_lr = 0xfffffff1L;
+#endif
 
 	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
 }
Signature · 1 line
1.7.9
#28 lore raw

PATCH 5/5 ARM: Cortex-M3: Add support for exception handling

Quoted 4 lines · Uwe Kleine-K?nig
arch/arm/kernel/entry-header.S +4 -0
+	.macro	v7m_exception_entry
+	cpsid	i
+	tst	lr, #0x8		@ check the return stack
+	bne	1f			@ exception on process stack

arch/arm/kernel/entry-header.S line 86

Quoted 10 lines
arch/arm/kernel/entry-header.S +10 -0
+	add	r12, sp, #32		@ MSP before exception
+	stmdb	sp!, {r4-r12, lr}	@ push unsaved registers
+	b	2f
+1:
+	mrs	r12, psp		@ get the process stack
+	sub	sp, #S_FRAME_SIZE
+	stmia	sp, {r4-r12, lr}	@ push unsaved registers
+	ldmia	r12, {r0-r3, r6, r8-r10} @ load automatically saved registers
+	add	r12, sp, #S_R0
+	stmia	r12, {r0-r3, r6, r8-r10} @ fill in the rest of struct pt_regs

I guess this means that pt_regs no longer contains r0..pc, cpsr, old_r0 on this Cortex-M ?

If so, that's a problem - tools like gdb, strace, and other user programs which make use of siginfo stuff all expect ARM to have a certain ptrace layout. This is major ABI breakage.

#29 lore raw

PATCH 5/5 ARM: Cortex-M3: Add support for exception handling

Hello Catalin,

Quoted 10 lines · Russell King - ARM Linux
Quoted 9 lines · Uwe Kleine-K?nig
arch/arm/kernel/entry-header.S +9 -0
+	.macro	v7m_exception_entry
+	cpsid	i
+	tst	lr, #0x8		@ check the return stack
+	bne	1f			@ exception on process stack
+	add	r12, sp, #32		@ MSP before exception
+	stmdb	sp!, {r4-r12, lr}	@ push unsaved registers
+	b	2f
+1:
+	mrs	r12, psp		@ get the process stack
Quoted 8 lines

arch/arm/kernel/entry-header.S line 86

Quoted 5 lines
arch/arm/kernel/entry-header.S +5 -0
+	sub	sp, #S_FRAME_SIZE
+	stmia	sp, {r4-r12, lr}	@ push unsaved registers
+	ldmia	r12, {r0-r3, r6, r8-r10} @ load automatically saved registers
+	add	r12, sp, #S_R0
+	stmia	r12, {r0-r3, r6, r8-r10} @ fill in the rest of struct pt_regs

I guess this means that pt_regs no longer contains r0..pc, cpsr, old_r0 on this Cortex-M ?

I stared at the code now for some time and I wonder if it wouldn't be the most nice solution to just do something like this on exception entry:

	cpsid	i
	sub	sp, #S_FRAME_SIZE
	stmia	sp, {r0-r12}
	put_the_right_sp_to_sp[13]
	put_lr_returnaddr_and_xPSR_from_right_stack_to_sp[14-16]

For returning you could just do:

add sp, #S_FRAME_SIZE
cpsie i
bx lr

after fixing r0 on the right stack in case you need to return something.

The machine takes care to restore {r0-r3,r12,lr} and the remaining registers should be untouched as everything we called between entry and exit is AAPCS conformant.

This way we would even need one value less in pt_regs (namely orig_r0).

Does this make sense? (Note it's just before bedtime here, so it might not.)

Anyhow, I will try to implement that if I still think it could work after sleeping.

Quoted 3 lines

If so, that's a problem - tools like gdb, strace, and other user programs which make use of siginfo stuff all expect ARM to have a certain ptrace layout. This is major ABI breakage.

Best regards
Uwe

Signature · 2 lines
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
#30 lore raw

PATCH 5/5 ARM: Cortex-M3: Add support for exception handling

Hi Uwe,

2012/2/24 Uwe Kleine-K?nig <[email protected]>:

Quoted 17 lines · Russell King - ARM Linux
Quoted 16 lines · Uwe Kleine-K?nig
Quoted 14 lines

+ ? .macro ?v7m_exception_entry
+ ? cpsid ? i
+ ? tst ? ? lr, #0x8 ? ? ? ? ? ? ? ?@ check the return stack
+ ? bne ? ? 1f ? ? ? ? ? ? ? ? ? ? ?@ exception on process stack
+ ? add ? ? r12, sp, #32 ? ? ? ? ? ?@ MSP before exception
+ ? stmdb ? sp!, {r4-r12, lr} ? ? ? @ push unsaved registers
+ ? b ? ? ? 2f
+1:
+ ? mrs ? ? r12, psp ? ? ? ? ? ? ? ?@ get the process stack
+ ? sub ? ? sp, #S_FRAME_SIZE
+ ? stmia ? sp, {r4-r12, lr} ? ? ? ?@ push unsaved registers
+ ? ldmia ? r12, {r0-r3, r6, r8-r10} @ load automatically saved registers
+ ? add ? ? r12, sp, #S_R0
+ ? stmia ? r12, {r0-r3, r6, r8-r10} @ fill in the rest of struct pt_regs

Quoted 2 lines
Quoted 2 lines

I guess this means that pt_regs no longer contains r0..pc, cpsr, old_r0 on this Cortex-M ?

Just to reply to Russell - yes, this part needs changing (could be the pt_regs saving or just the signal and trace code that copies them to user so that we preserve the ABI).

Quoted 10 lines

I stared at the code now for some time and I wonder if it wouldn't be the most nice solution to just do something like this on exception entry:

? ? ? ?cpsid ? i
? ? ? ?sub ? ? sp, #S_FRAME_SIZE
? ? ? ?stmia ? sp, {r0-r12}
? ? ? ?put_the_right_sp_to_sp[13]
? ? ? ?put_lr_returnaddr_and_xPSR_from_right_stack_to_sp[14-16]

Quoted 5 lines

For returning you could just do:

? ? ? ?add ? ? sp, #S_FRAME_SIZE
? ? ? ?cpsie ? i
? ? ? ?bx ? ? ?lr

For this kind of returning, do we actually change between Process and Handler stack?

But we still need to set the pt_regs to the user stack. The kernel would touch all of them if a signal is to be delivered (actually restoring them when returning from the signal handler).

Quoted 5 lines

after fixing r0 on the right stack in case you need to return something.

The machine takes care to restore {r0-r3,r12,lr} and the remaining registers should be untouched as everything we called between entry and exit is AAPCS conformant.

As I said, we have sys_sigreturn which modifies those registers.

Quoted 2 lines

Anyhow, I will try to implement that if I still think it could work after sleeping.

It's late here as well :). We'll see next week.

Signature · 1 line
Catalin
#31 lore raw

PATCH 5/5 ARM: Cortex-M3: Add support for exception handling

Quoted 3 lines · Catalin Marinas

Just to reply to Russell - yes, this part needs changing (could be the pt_regs saving or just the signal and trace code that copies them to user so that we preserve the ABI).

It's more than just that. What about the various exception handling code which needs to look up registers by numerical index? That encompasses kprobes, alignment fixup, swp emulation, fp exception fixup, and so forth.

#32 lore raw

PATCH 5/5 ARM: Cortex-M3: Add support for exception handling

Quoted 9 lines · Russell King - ARM Linux
Quoted 3 lines · Catalin Marinas

Just to reply to Russell - yes, this part needs changing (could be the pt_regs saving or just the signal and trace code that copies them to user so that we preserve the ABI).

It's more than just that. What about the various exception handling code which needs to look up registers by numerical index? That encompasses kprobes, alignment fixup, swp emulation, fp exception fixup, and so forth.

Some of these don't apply to the M profile, like swp emulation (Thumb-2 only core). Anyway, it's not difficult to get the pt_regs structure back to the standard layout.

Catalin

#33 lore raw

PATCH 5/5 ARM: Cortex-M3: Add support for exception handling

In reply to Catalin Marinas
Quoted 37 lines · Catalin Marinas

Hi Uwe,

2012/2/24 Uwe Kleine-K?nig <[email protected]>:

Quoted 17 lines · Russell King - ARM Linux
Quoted 16 lines · Uwe Kleine-K?nig
Quoted 14 lines

+ ? .macro ?v7m_exception_entry
+ ? cpsid ? i
+ ? tst ? ? lr, #0x8 ? ? ? ? ? ? ? ?@ check the return stack
+ ? bne ? ? 1f ? ? ? ? ? ? ? ? ? ? ?@ exception on process stack
+ ? add ? ? r12, sp, #32 ? ? ? ? ? ?@ MSP before exception
+ ? stmdb ? sp!, {r4-r12, lr} ? ? ? @ push unsaved registers
+ ? b ? ? ? 2f
+1:
+ ? mrs ? ? r12, psp ? ? ? ? ? ? ? ?@ get the process stack
+ ? sub ? ? sp, #S_FRAME_SIZE
+ ? stmia ? sp, {r4-r12, lr} ? ? ? ?@ push unsaved registers
+ ? ldmia ? r12, {r0-r3, r6, r8-r10} @ load automatically saved registers
+ ? add ? ? r12, sp, #S_R0
+ ? stmia ? r12, {r0-r3, r6, r8-r10} @ fill in the rest of struct pt_regs

Quoted 2 lines
Quoted 2 lines

I guess this means that pt_regs no longer contains r0..pc, cpsr, old_r0 on this Cortex-M ?

Just to reply to Russell - yes, this part needs changing (could be the pt_regs saving or just the signal and trace code that copies them to user so that we preserve the ABI).

Quoted 10 lines

I stared at the code now for some time and I wonder if it wouldn't be the most nice solution to just do something like this on exception entry:

? ? ? ?cpsid ? i
? ? ? ?sub ? ? sp, #S_FRAME_SIZE
? ? ? ?stmia ? sp, {r0-r12}
? ? ? ?put_the_right_sp_to_sp[13]
? ? ? ?put_lr_returnaddr_and_xPSR_from_right_stack_to_sp[14-16]

Quoted 8 lines
Quoted 5 lines

For returning you could just do:

? ? ? ?add ? ? sp, #S_FRAME_SIZE
? ? ? ?cpsie ? i
? ? ? ?bx ? ? ?lr

For this kind of returning, do we actually change between Process and Handler stack?

According to ARMARM-v7-M when pc is written to 0xfXXXXXXX (with X denoting don't care) also the stack is restored.

Quoted 3 lines

But we still need to set the pt_regs to the user stack. The kernel would touch all of them if a signal is to be delivered (actually restoring them when returning from the signal handler).

Ah, I thought only r0 might be changed. I will bear that in mind.

Thanks for your insights
Uwe

Signature · 2 lines
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
#34 lore raw

PATCH v2 4/5 Cortex-M3: Add base support for Cortex-M3

In reply to Catalin Marinas

From: Catalin Marinas <[email protected]>

This patch adds the base support for the Cortex-M3 processor (ARMv7-M architecture). It consists of the corresponding arch/arm/mm/ files and various #ifdef's around the kernel. Exception handling is implemented by a subsequent patch.

[ukleinek: squash in some changes originating from commit

b5717ba (Cortex-M3: Add support for the Microcontroller Prototyping System)

from the v2.6.33-arm1 patch stack, port to post 3.2, drop zImage support, and a few cosmetic changes, rework to preserve layout of pt_regs]

---
 arch/arm/include/asm/assembler.h  |   13 +++-
 arch/arm/include/asm/cputype.h    |    3 +
 arch/arm/include/asm/glue-cache.h |   24 +++++
 arch/arm/include/asm/glue-df.h    |    8 ++
 arch/arm/include/asm/glue-proc.h  |    9 ++
 arch/arm/include/asm/irqflags.h   |   51 +++++++++++-
 arch/arm/include/asm/processor.h  |    8 ++
 arch/arm/include/asm/ptrace.h     |   21 ++++-
 arch/arm/include/asm/system.h     |    3 +
 arch/arm/kernel/asm-offsets.c     |    4 +
 arch/arm/kernel/head-common.S     |    2 +-
 arch/arm/kernel/head-nommu.S      |    9 ++-
 arch/arm/kernel/ptrace.c          |    4 +
 arch/arm/kernel/setup.c           |   13 +++-
 arch/arm/kernel/signal.c          |    5 +
 arch/arm/kernel/traps.c           |    2 +
 arch/arm/mm/nommu.c               |    2 +
 arch/arm/mm/proc-v7m.S            |  168 +++++++++++++++++++++++++++++++++++++
 18 files changed, 339 insertions(+), 10 deletions(-)
 create mode 100644 arch/arm/mm/proc-v7m.S
arch/arm/include/asm/assembler.h +12 -1
index 62f8095..1bafa39 100644
@@ -133,7 +133,11 @@
  * assumes FIQs are enabled, and that the processor is in SVC mode.
  */
 	.macro	save_and_disable_irqs, oldcpsr
+#ifdef CONFIG_CPU_V7M
+	mrs	\oldcpsr, primask
+#else
 	mrs	\oldcpsr, cpsr
+#endif
 	disable_irq
 	.endm
 
@@ -142,7 +146,11 @@
  * guarantee that this will preserve the flags.
  */
 	.macro	restore_irqs_notrace, oldcpsr
+#ifdef CONFIG_CPU_V7M
+	msr	primask, \oldcpsr
+#else
 	msr	cpsr_c, \oldcpsr
+#endif
 	.endm
 
 	.macro restore_irqs, oldcpsr
@@ -221,7 +229,10 @@
 #endif
 	.endm
 
-#ifdef CONFIG_THUMB2_KERNEL
+#if defined(CONFIG_CPU_V7M)
+	.macro	setmode, mode, reg
+	.endm
+#elif defined(CONFIG_THUMB2_KERNEL)
 	.macro	setmode, mode, reg
 	mov	\reg, #\mode
 	msr	cpsr_c, \reg
arch/arm/include/asm/cputype.h +3 -0
index cb47d28..5bd8cb6 100644
@@ -46,6 +46,9 @@ extern unsigned int processor_id;
 		    : "cc");						\
 		__val;							\
 	})
+#elif defined(CONFIG_CPU_V7M)
+#define read_cpuid(reg) (*(unsigned int *)0xe000ed00)
+#define read_cpuid_ext(reg) 0
 #else
 #define read_cpuid(reg) (processor_id)
 #define read_cpuid_ext(reg) 0
arch/arm/include/asm/glue-cache.h +24 -0
index 7e30874..6a5fd0b 100644
@@ -125,10 +125,34 @@
 //# endif
 #endif
 
+#if defined(CONFIG_CPU_V7M)
+# ifdef _CACHE
+#  error "Multi-cache not supported on ARMv7-M"
+# else
+#  define _CACHE nop
+# endif
+#endif
+
 #if !defined(_CACHE) && !defined(MULTI_CACHE)
 #error Unknown cache maintenance model
 #endif
 
+#ifndef __ASSEMBLER__
+static inline void nop_flush_icache_all(void) { }
+static inline void nop_flush_kern_cache_all(void) { }
+static inline void nop_flush_user_cache_all(void) { }
+static inline void nop_flush_user_cache_range(unsigned long a, unsigned long b, unsigned int c) { }
+
+static inline void nop_coherent_kern_range(unsigned long a, unsigned long b) { }
+static inline void nop_coherent_user_range(unsigned long a, unsigned long b) { }
+static inline void nop_flush_kern_dcache_area(void *a, size_t s) { }
+
+static inline void nop_dma_flush_range(const void *a, const void *b) { }
+
+static inline void nop_dma_map_area(const void *s, size_t l, int f) { }
+static inline void nop_dma_unmap_area(const void *s, size_t l, int f) { }
+#endif
+
 #ifndef MULTI_CACHE
 #define __cpuc_flush_icache_all		__glue(_CACHE,_flush_icache_all)
 #define __cpuc_flush_kern_all		__glue(_CACHE,_flush_kern_cache_all)
arch/arm/include/asm/glue-df.h +8 -0
index 354d571..26be71c 100644
@@ -103,6 +103,14 @@
 # endif
 #endif
 
+#ifdef CONFIG_CPU_ABRT_NOMMU
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER nommu_early_abort
+# endif
+#endif
+
 #ifndef CPU_DABORT_HANDLER
 #error Unknown data abort handler type
 #endif
arch/arm/include/asm/glue-proc.h +9 -0
index e2be7f1..8f9991b 100644
@@ -248,6 +248,15 @@
 # endif
 #endif
 
+#ifdef CONFIG_CPU_V7M
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_v7m
+# endif
+#endif
+
 #ifndef MULTI_CPU
 #define cpu_proc_init			__glue(CPU_NAME,_proc_init)
 #define cpu_proc_fin			__glue(CPU_NAME,_proc_fin)
arch/arm/include/asm/irqflags.h +49 -2

72 lines not on this page · raw message

arch/arm/include/asm/processor.h +8 -0
index ce280b8..18ec6b6 100644
@@ -49,7 +49,15 @@ struct thread_struct {
 #ifdef CONFIG_MMU
 #define nommu_start_thread(regs) do { } while (0)
 #else
+#ifndef CONFIG_CPU_V7M
 #define nommu_start_thread(regs) regs->ARM_r10 = current->mm->start_data
+#else
+#define nommu_start_thread(regs) do {					\
+	regs->ARM_r10 = current->mm->start_data;			\
+	regs->ARM_sp -= 32;		/* exception return state */	\
+	regs->ARM_EXCRET = 0xfffffffdL;					\
+} while (0)
+#endif
 #endif
 
 #define start_thread(regs,pc,sp)					\
arch/arm/include/asm/ptrace.h +19 -2
index 451808b..154d442 100644
@@ -39,16 +39,25 @@
 #define FIQ26_MODE	0x00000001
 #define IRQ26_MODE	0x00000002
 #define SVC26_MODE	0x00000003
+#ifndef CONFIG_CPU_V7M
 #define USR_MODE	0x00000010
+#define SVC_MODE	0x00000013
+#else
+#define USR_MODE	0x00000000
+#define SVC_MODE	0x00000000
+#endif
 #define FIQ_MODE	0x00000011
 #define IRQ_MODE	0x00000012
-#define SVC_MODE	0x00000013
 #define ABT_MODE	0x00000017
 #define UND_MODE	0x0000001b
 #define SYSTEM_MODE	0x0000001f
 #define MODE32_BIT	0x00000010
 #define MODE_MASK	0x0000001f
+#ifndef CONFIG_CPU_V7M
 #define PSR_T_BIT	0x00000020
+#else
+#define PSR_T_BIT	0x01000000
+#endif
 #define PSR_F_BIT	0x00000040
 #define PSR_I_BIT	0x00000080
 #define PSR_A_BIT	0x00000100
@@ -127,7 +136,11 @@ struct pt_regs {
 #define ARM_r2		uregs[2]
 #define ARM_r1		uregs[1]
 #define ARM_r0		uregs[0]
+#if defined CONFIG_CPU_V7M
+#define ARM_EXCRET	uregs[17]
+#else
 #define ARM_ORIG_r0	uregs[17]
+#endif
 
 /*
  * The size of the user-visible VFP state as seen by PTRACE_GET/SETVFPREGS
@@ -165,6 +178,7 @@ struct pt_regs {
  */
 static inline int valid_user_regs(struct pt_regs *regs)
 {
+#ifndef CONFIG_CPU_V7M
 	unsigned long mode = regs->ARM_cpsr & MODE_MASK;
 
 	/*
@@ -187,6 +201,9 @@ static inline int valid_user_regs(struct pt_regs *regs)
 		regs->ARM_cpsr |= USR_MODE;
 
 	return 0;
+#else /* ifndef CONFIG_CPU_V7M */
+	return 1;
+#endif
 }
 
 static inline long regs_return_value(struct pt_regs *regs)
@@ -218,7 +235,7 @@ extern unsigned long profile_pc(struct pt_regs *regs);
  */
 #include <linux/stddef.h>
 #include <linux/types.h>
-#define MAX_REG_OFFSET (offsetof(struct pt_regs, ARM_ORIG_r0))
+#define MAX_REG_OFFSET (offsetof(struct pt_regs, ARM_cpsr) + 4)
 
 extern int regs_query_register_offset(const char *name);
 extern const char *regs_query_register_name(unsigned int offset);
arch/arm/include/asm/system.h +3 -0
index de46477..16117ed 100644
@@ -13,6 +13,7 @@
 #define CPU_ARCH_ARMv5TEJ	7
 #define CPU_ARCH_ARMv6		8
 #define CPU_ARCH_ARMv7		9
+#define CPU_ARCH_ARMv7M		10
 
 /*
  * CR1 bits (CP#15 CR1)
@@ -232,7 +233,9 @@ static inline void set_copro_access(unsigned int val)
  * so enable interrupts over the context switch to avoid high
  * latency.
  */
+#ifndef CONFIG_CPU_V7M
 #define __ARCH_WANT_INTERRUPTS_ON_CTXSW
+#endif
 
 /*
  * switch_to(prev, next) should switch from task `prev' to `next'
arch/arm/kernel/asm-offsets.c +4 -0
index 1429d89..da2ce93 100644
@@ -90,7 +90,11 @@ int main(void)
   DEFINE(S_LR,			offsetof(struct pt_regs, ARM_lr));
   DEFINE(S_PC,			offsetof(struct pt_regs, ARM_pc));
   DEFINE(S_PSR,			offsetof(struct pt_regs, ARM_cpsr));
+#ifdef CONFIG_CPU_V7M
+  DEFINE(S_EXCRET,		offsetof(struct pt_regs, ARM_EXCRET));
+#else
   DEFINE(S_OLD_R0,		offsetof(struct pt_regs, ARM_ORIG_r0));
+#endif
   DEFINE(S_FRAME_SIZE,		sizeof(struct pt_regs));
   BLANK();
 #ifdef CONFIG_CACHE_L2X0
arch/arm/kernel/head-common.S +1 -1
index 5ca01bb..efeb2d0 100644
@@ -118,7 +118,7 @@ __mmap_switched_data:
 #ifdef CONFIG_CPU_CP15
 	.long	cr_alignment			@ r7
 #else
-	.long	0
+	.long	0				@ r7
 #endif
 	.long	init_thread_union + THREAD_START_SP @ sp
 	.size	__mmap_switched_data, . - __mmap_switched_data
arch/arm/kernel/head-nommu.S +6 -3
index 1aca35d..61ba029 100644
@@ -44,10 +44,13 @@ ENTRY(stext)
 
 	setmode	PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
 						@ and irqs disabled
-#ifndef CONFIG_CPU_CP15
-	ldr	r9, =CONFIG_PROCESSOR_ID
-#else
+#if defined(CONFIG_CPU_CP15)
 	mrc	p15, 0, r9, c0, c0		@ get processor id
+#elif defined(CONFIG_CPU_V7M)
+	ldr	r9, =0xe000ed00			@ CPUID register address
+	ldr	r9, [r9]
+#else
+	ldr	r9, =CONFIG_PROCESSOR_ID
 #endif
 	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
 	movs	r10, r5				@ invalid processor (r5=0)?
arch/arm/kernel/ptrace.c +4 -0
index e33870f..9ba31f8 100644
@@ -81,7 +81,11 @@ static const struct pt_regs_offset regoffset_table[] = {
 	REG_OFFSET_NAME(lr),
 	REG_OFFSET_NAME(pc),
 	REG_OFFSET_NAME(cpsr),
+#ifdef CONFIG_CPU_V7M
+	REG_OFFSET_NAME(EXCRET),
+#else
 	REG_OFFSET_NAME(ORIG_r0),
+#endif
 	REG_OFFSET_END,
 };
 
arch/arm/kernel/setup.c +12 -1
index 23893b1..d0fc5b8 100644
@@ -132,7 +132,9 @@ struct stack {
 	u32 und[3];
 } ____cacheline_aligned;
 
+#ifndef CONFIG_CPU_V7M
 static struct stack stacks[NR_CPUS];
+#endif
 
 char elf_platform[ELF_PLATFORM_SIZE];
 EXPORT_SYMBOL(elf_platform);
@@ -212,7 +214,7 @@ static const char *proc_arch[] = {
 	"5TEJ",
 	"6TEJ",
 	"7",
-	"?(11)",
+	"7M",
 	"?(12)",
 	"?(13)",
 	"?(14)",
@@ -221,6 +223,12 @@ static const char *proc_arch[] = {
 	"?(17)",
 };
 
+#ifdef CONFIG_CPU_V7M
+static int __get_cpu_architecture(void)
+{
+	return CPU_ARCH_ARMv7M;
+}
+#else
 static int __get_cpu_architecture(void)
 {
 	int cpu_arch;
@@ -253,6 +261,7 @@ static int __get_cpu_architecture(void)
 
 	return cpu_arch;
 }
+#endif
 
 int __pure cpu_architecture(void)
 {
@@ -380,6 +389,7 @@ static void __init feat_v6_fixup(void)
  */
 void cpu_init(void)
 {
+#ifndef CONFIG_CPU_V7M
 	unsigned int cpu = smp_processor_id();
 	struct stack *stk = &stacks[cpu];
 
@@ -424,6 +434,7 @@ void cpu_init(void)
 	      "I" (offsetof(struct stack, und[0])),
 	      PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
 	    : "r14");
+#endif
 }
 
 int __cpu_logical_map[NR_CPUS];
arch/arm/kernel/signal.c +5 -0
index 9e617bd..8407c17 100644
@@ -688,7 +688,12 @@ static void do_signal(struct pt_regs *regs, int syscall)
 		case -ERESTARTNOHAND:
 		case -ERESTARTSYS:
 		case -ERESTARTNOINTR:
+#ifdef CONFIG_CPU_V7M
+			pr_info("%s: cannot restart yet!\n", __func__);
+			while(1);
+#else
 			regs->ARM_r0 = regs->ARM_ORIG_r0;
+#endif
 			regs->ARM_pc = restart_addr;
 			break;
 		case -ERESTART_RESTARTBLOCK:
arch/arm/kernel/traps.c +2 -0
index 99a5727..8956d08 100644
@@ -783,6 +783,7 @@ static void __init kuser_get_tls_init(unsigned long vectors)
 
 void __init early_trap_init(void)
 {
+#ifndef CONFIG_CPU_V7M
 #if defined(CONFIG_CPU_USE_DOMAINS)
 	unsigned long vectors = CONFIG_VECTORS_BASE;
 #else
@@ -818,4 +819,5 @@ void __init early_trap_init(void)
 
 	flush_icache_range(vectors, vectors + PAGE_SIZE);
 	modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
+#endif
 }
arch/arm/mm/nommu.c +2 -0
index 4fc6794..fdd49ac 100644
@@ -19,12 +19,14 @@
 
 void __init arm_mm_memblock_reserve(void)
 {
+#ifndef CONFIG_CPU_V7M
 	/*
 	 * Register the exception vector page.
 	 * some architectures which the DRAM is the exception vector to trap,
 	 * alloc_page breaks with error, although it is not NULL, but "0."
 	 */
 	memblock_reserve(CONFIG_VECTORS_BASE, PAGE_SIZE);
+#endif
 }
 
 void __init sanity_check_meminfo(void)
arch/arm/mm/proc-v7m.S new file +168 -0

168 lines not on this page · raw message

Signature · 1 line
1.7.9.1
#35 lore raw

PATCH v2 5/5 Cortex-M3: Add support for exception handling

This patch implements the exception handling for the ARMv7-M architecture (pretty different from the A or R profiles).

Initially this based on a patch by Catalin Marinas but was completely reworked to use a pt_regs layout similar to the A profile.

Note this is broken in at least two ways:
- r0 isn't saved for signal restarting (should be easy)
- crashes early after reaching userspace.

---
Hello,

To save r0, I'd readd OLD_R0 at the end of pt_regs (plus one buffer word to get even alignment). Or would that already be unacceptable because it's an ABI change, too?

Anyhow, this is (once more :-) a great opportunity for you to blame me in public by pointing out why my machine crashes with this patch. But to be honest this time I wouldn't mind because hopefully after describing your findings I'd be able to fix the problem.

Best regards
Uwe

 arch/arm/kernel/entry-common.S |    9 ++-
 arch/arm/kernel/entry-header.S |  149 +++++++++++++++++++++++++++++++++++++++-
 arch/arm/kernel/entry-v7m.S    |  135 ++++++++++++++++++++++++++++++++++++
 arch/arm/kernel/process.c      |    8 ++
 4 files changed, 299 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/kernel/entry-v7m.S
arch/arm/kernel/entry-common.S +8 -1
index 9fd0ba9..953e517 100644
@@ -345,6 +345,9 @@ ENDPROC(ftrace_stub)
 
 	.align	5
 ENTRY(vector_swi)
+#ifdef CONFIG_CPU_V7M
+	v7m_exception_entry
+#else
 	sub	sp, sp, #S_FRAME_SIZE
 	stmia	sp, {r0 - r12}			@ Calling r0 - r12
  ARM(	add	r8, sp, #S_PC		)
@@ -354,7 +357,11 @@ ENTRY(vector_swi)
 	mrs	r8, spsr			@ called from non-FIQ mode, so ok.
 	str	lr, [sp, #S_PC]			@ Save calling PC
 	str	r8, [sp, #S_PSR]		@ Save CPSR
+#endif
+#if XXX
+	/* XXX: fixme: we need to preserve r0 somewhere for signal stuff */
 	str	r0, [sp, #S_OLD_R0]		@ Save OLD_R0
+#endif
 	zero_fp
 
 	/*
@@ -473,7 +480,7 @@ __sys_trace:
 
 	adr	lr, BSYM(__sys_trace_return)	@ return address
 	mov	scno, r0			@ syscall number (possibly new)
-	add	r1, sp, #S_R0 + S_OFF		@ pointer to regs
+	add	r1, sp, #S_OFF			@ pointer to regs
 	cmp	scno, #NR_syscalls		@ check upper syscall limit
 	ldmccia	r1, {r0 - r3}			@ have to reload r0 - r3
 	ldrcc	pc, [tbl, scno, lsl #2]		@ call sys_* routine
arch/arm/kernel/entry-header.S +148 -1

173 lines not on this page · raw message

arch/arm/kernel/entry-v7m.S new file +135 -0

135 lines not on this page · raw message

arch/arm/kernel/process.c +8 -0
index 971d65c..bdccb8f 100644
@@ -452,7 +452,11 @@ asm(	".pushsection .text\n"
 #ifdef CONFIG_TRACE_IRQFLAGS
 "	bl	trace_hardirqs_on\n"
 #endif
+#ifdef CONFIG_CPU_V7M
+"	msr	primask, r7\n"
+#else
 "	msr	cpsr_c, r7\n"
+#endif
 "	mov	r0, r4\n"
 "	mov	lr, r6\n"
 "	mov	pc, r5\n"
@@ -491,6 +495,10 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 	regs.ARM_r7 = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE;
 	regs.ARM_pc = (unsigned long)kernel_thread_helper;
 	regs.ARM_cpsr = regs.ARM_r7 | PSR_I_BIT;
+#ifdef CONFIG_CPU_V7M
+	/* Return to Handler mode */
+	regs.ARM_EXCRET = 0xfffffff1L;
+#endif
 
 	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
 }
Signature · 1 line
1.7.9.1
#36 lore raw

PATCH v2 5/5 Cortex-M3: Add support for exception handling

Quoted 3 lines · Uwe Kleine-K?nig

To save r0, I'd readd OLD_R0 at the end of pt_regs (plus one buffer word to get even alignment). Or would that already be unacceptable because it's an ABI change, too?

If we preserve the first part of the pt_regs structure, we could add the exception return at the end (with two additional 32-bit words to preserve the 64-bit alignment).

arch/arm/kernel/entry-common.S __sys_trace: · line 483

Quoted 8 lines
arch/arm/kernel/entry-common.S +1 -1
@@ -473,7 +480,7 @@ __sys_trace:
 
 	adr	lr, BSYM(__sys_trace_return)	@ return address
 	mov	scno, r0			@ syscall number (possibly new)
-	add	r1, sp, #S_R0 + S_OFF		@ pointer to regs
+	add	r1, sp, #S_OFF			@ pointer to regs

This change is no longer needed since S_R0 is no 0.

arch/arm/kernel/entry-header.S line 29

Quoted 8 lines
arch/arm/kernel/entry-header.S +1 -1
@@ -26,7 +26,7 @@
  * The SWI code relies on the fact that R0 is at the bottom of the stack
  * (due to slow/fast restore user regs).
  */
-#if S_R0 != 0
+#if S_R0 != 0 && !defined(CONFIG_CPU_V7M)

Same here.

Quoted 24 lines
arch/arm/kernel/entry-header.S +24 -0
+#ifdef CONFIG_CPU_V7M
+/*
+ * ARMv7-M exception entry/exit macros.
+ *
+ * xPSR, ReturnAddress(), LR (R14), R12, R3, R2, R1, and R0 are
+ * automatically saved on the current stack (32 words) before
+ * switching to the exception stack (SP_main).
+ *
+ * If exception is taken while in user mode, SP_main is
+ * empty. Otherwise, SP_main is aligned to 64 bit automatically
+ * (CCR.STKALIGN set).
+ *
+ * Linux assumes that the interrupts are disabled when entering an
+ * exception handler and it may BUG if this is not the case. Interrupts
+ * are disabled during entry and reenabled in the exit macro.
+ *
+ * v7m_exception_fast_exit is used when returning from interrupts.
+ *
+ * v7m_exception_slow_exit is used when returning from SVC or PendSV.
+ * When returning to kernel mode, we don't return from exception.
+ */
+	.macro	v7m_exception_entry
+	cpsid	i
+	sub	sp, #S_FRAME_SIZE

arch/arm/kernel/entry-header.S line 80

Quoted 10 lines
arch/arm/kernel/entry-header.S +10 -0
+	stmia	sp, {r0-r12}
+
+	@ set r0 to the location of the registers saved by the core during
+	@ exception entry. Depending on the mode the cpu was in when the
+	@ exception happend that is either on the main or the process stack.
+	@ Bit 2 of EXC_RETURN stored in the lr register specifies which stack
+	@ was used.
+	tst	lr, #0x4
+	mrsne	r0, psp
+	addeq	r0, sp, #S_FRAME_SIZE

Could we use some other registers here like r8-r12 so that we keep r0-r7 for syscall handling later and avoid another ldmia?

Quoted 4 lines
arch/arm/kernel/entry-header.S +4 -0
+	add	r0, r0, #20		@ skip over r0-r3, r12
+	ldmia	r0!, {r1-r3}		@ load saved lr, return address and xPSR
+
+	@ calculate the orignal stack pointer value.

arch/arm/kernel/entry-header.S line 95

Quoted 10 lines
arch/arm/kernel/entry-header.S +10 -0
+	@ r0 currently points to the memory location just above the auto saved
+	@ xPSR. If the FP extension is implemented and bit 4 of EXC_RETURN is 0
+	@ then space was allocated for FP state. That is space for 18 32-bit
+	@ values. (If FP extension is unimplemented, bit 4 is 1.)
+	@ Additionally the cpu might automatically 8-byte align the stack. Bit 9
+	@ of the saved xPSR specifies if stack aligning took place. In this case
+	@ another 32-bit value is included in the stack.
+
+	tst	lr, #0x10
+	addeq	r0, r0, #576

I think you can ignore VFP for now. We could change it to do lazy save/restore and avoid the automatic state saving. If it does this while in kernel, it takes a bit of extra stack space.

arch/arm/kernel/entry-header.S line 101

Quoted 2 lines
arch/arm/kernel/entry-header.S +2 -0
+	@ save original sp, lr, return address, xPSR and EXC_RETURN
+	add	r12, sp, #52

Just use S_ARM_SP or whatever asm offsets, it's easier to read.

arch/arm/kernel/entry-header.S line 105

Quoted 4 lines
arch/arm/kernel/entry-header.S +4 -0
+	stmia	r12, {r0-r3, lr}
+
+	@ restore registers for system calls
+	ldmia	sp, {r0-r12}

We could avoid reloading r0-r7 (that's what we actually need for syscalls) if we don't corrupt them.

arch/arm/kernel/entry-header.S line 110

Quoted 5 lines
arch/arm/kernel/entry-header.S +5 -0
+	.endm
+
+	.macro	v7m_exception_fast_exit
+	@ read r12, sp, lr, return address, xPSR and EXC_RETURN
+	add	r12, sp, #48

S_ARM_R12?

Quoted 11 lines
arch/arm/kernel/entry-header.S +11 -0
+	ldmia	r12, {r1-r5, lr}
+
+	tst     r5, #0x100
+	subne   r2, r2, #4
+
+	tst	lr, #0x10
+	subeq	r2, r2, #576
+
+	stmdb	r2!, {r1, r3-r5}		@ write saved r12, lr, return address and xPSR
+
+	ldmia	sp, {r1, r3-r5}			@ read saved r0-r3

arch/arm/kernel/entry-header.S line 131

Quoted 10 lines
arch/arm/kernel/entry-header.S +10 -0
+	stmdb	r2!, {r1, r3-r5}		@ write r0-r3 to basic exception frame
+
+	tst	lr, #0x4
+	msrne	psp, r2
+
+	ldmia	sp, {r0-r12}
+	add	sp, #S_FRAME_SIZE
+	cpsie	i
+	bx	lr
+	.endm

In the context v7m_exception_fast_exit is used (return from interrupts), the previously saved r0-r4,r12 etc. are still on the return stack and restored from there. There is no need for the ldmia/stmdb to re-create the interrupted process stack. Here we only need to make sure that we restore the registers that were not automatically saved and also move the kernel SP back to the original location (add S_FRAME_SIZE).

We handle rescheduling and work pending by raising PendSV, so we get another interrupt which would be returned via the slow_exit macro.

Quoted 30 lines
arch/arm/kernel/entry-header.S +30 -0
+	.macro	v7m_exception_slow_exit ret_r0
+	cpsid	i
+	ldr	lr, [sp, #S_EXCRET]		@ read exception LR
+	tst     lr, #0x8
+	bne	1f				@ go to thread mode using exception return
+
+	/*
+	 * return to kernel thread
+	 * sp is already set up (and might be unset in pt_regs), so only
+	 * restore r0-r12 and pc
+	 */
+	ldmia	sp, {r0-r12}
+	ldr	lr, [sp, #S_PC]
+	add	sp, sp, #S_FRAME_SIZE
+	cpsie	i
+	bx	lr
+	/*
+	 * return to userspace
+	 */
+1:
+	@ read original r12, sp, lr, pc, xPSR
+	add	r12, sp, #48
+	ldmia	r12, {r1-r5}
+
+	/* stack aligning */
+	tst	r5, #0x100
+	subne	r2, r2, #4
+
+	/* skip over stack space for fp extension */
+	tst	lr, #0x10

arch/arm/kernel/entry-header.S line 173

Quoted 10 lines
arch/arm/kernel/entry-header.S +10 -0
+	subeq	r2, r2, #576
+
+	/* write basic exception frame */
+	stmdb	r2!, {r1, r3-r5}		@ saved r12, lr, return address and xPSR
+	ldmia	sp, {r1, r3-r5}			@ read saved r0-r3
+	.if	\ret_r0
+	stmdb	r2!, {r0, r3-r5}		@ restore r0-r3
+	.else
+	stmdb	r2!, {r1, r3-r5}		@ restore r0-r3
+	.endif

This looks fine.

arch/arm/kernel/entry-header.S line 177

Quoted 3 lines
arch/arm/kernel/entry-header.S +3 -0
+	msr	psp, r2
+
+	ldmia	sp, {r0-r12}			@ restore original r4-r11

Isn't this reading too much (optimisation)?

Quoted 5 lines
arch/arm/kernel/entry-header.S +5 -0
+	add	sp, #S_FRAME_SIZE		@ restore the original MSP
+	cpsie	i
+	bx	lr
+	.endm
+#endif	/* CONFIG_CPU_V7M */

...

Quoted 15 lines
arch/arm/kernel/process.c +4 -0
@@ -452,7 +452,11 @@ asm(	".pushsection .text\n"
 #ifdef CONFIG_TRACE_IRQFLAGS
 "	bl	trace_hardirqs_on\n"
 #endif
+#ifdef CONFIG_CPU_V7M
+"	msr	primask, r7\n"
+#else
 "	msr	cpsr_c, r7\n"
+#endif
 "	mov	r0, r4\n"
 "	mov	lr, r6\n"
 "	mov	pc, r5\n"

arch/arm/kernel/process.c pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) · line 501

Quoted 7 lines
arch/arm/kernel/process.c +4 -0
@@ -491,6 +495,10 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 	regs.ARM_r7 = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE;
 	regs.ARM_pc = (unsigned long)kernel_thread_helper;
 	regs.ARM_cpsr = regs.ARM_r7 | PSR_I_BIT;
+#ifdef CONFIG_CPU_V7M
+	/* Return to Handler mode */
+	regs.ARM_EXCRET = 0xfffffff1L;
+#endif

BTW, do we need to set this here? We don't return to a kernel thread via exception return.

I currently cannot see any obvious bugs in the code. Since you said it doesn't work, what are the symptoms?

Signature · 1 line
Catalin
#37 lore raw

PATCH v2 5/5 Cortex-M3: Add support for exception handling

Hello Catalin,

Quoted 8 lines · Catalin Marinas
Quoted 3 lines · Uwe Kleine-K?nig

To save r0, I'd readd OLD_R0 at the end of pt_regs (plus one buffer word to get even alignment). Or would that already be unacceptable because it's an ABI change, too?

If we preserve the first part of the pt_regs structure, we could add the exception return at the end (with two additional 32-bit words to preserve the 64-bit alignment).

I will do that.

Quoted 10 lines

arch/arm/kernel/entry-common.S __sys_trace: · line 483

Quoted 8 lines
arch/arm/kernel/entry-common.S +1 -1
@@ -473,7 +480,7 @@ __sys_trace:
 
 	adr	lr, BSYM(__sys_trace_return)	@ return address
 	mov	scno, r0			@ syscall number (possibly new)
-	add	r1, sp, #S_R0 + S_OFF		@ pointer to regs
+	add	r1, sp, #S_OFF			@ pointer to regs

This change is no longer needed since S_R0 is no 0.

hmm, I thought I had removed them. Seems I didn't.

Quoted 10 lines

arch/arm/kernel/entry-header.S line 29

Quoted 8 lines
arch/arm/kernel/entry-header.S +1 -1
@@ -26,7 +26,7 @@
  * The SWI code relies on the fact that R0 is at the bottom of the stack
  * (due to slow/fast restore user regs).
  */
-#if S_R0 != 0
+#if S_R0 != 0 && !defined(CONFIG_CPU_V7M)

Same here.

Same here ;-)

Quoted 30 lines
Quoted 30 lines
arch/arm/kernel/entry-header.S +29 -0
+#ifdef CONFIG_CPU_V7M
+/*
+ * ARMv7-M exception entry/exit macros.
+ *
+ * xPSR, ReturnAddress(), LR (R14), R12, R3, R2, R1, and R0 are
+ * automatically saved on the current stack (32 words) before
+ * switching to the exception stack (SP_main).
+ *
+ * If exception is taken while in user mode, SP_main is
+ * empty. Otherwise, SP_main is aligned to 64 bit automatically
+ * (CCR.STKALIGN set).
+ *
+ * Linux assumes that the interrupts are disabled when entering an
+ * exception handler and it may BUG if this is not the case. Interrupts
+ * are disabled during entry and reenabled in the exit macro.
+ *
+ * v7m_exception_fast_exit is used when returning from interrupts.
+ *
+ * v7m_exception_slow_exit is used when returning from SVC or PendSV.
+ * When returning to kernel mode, we don't return from exception.
+ */
+	.macro	v7m_exception_entry
+	cpsid	i
+	sub	sp, #S_FRAME_SIZE
+	stmia	sp, {r0-r12}
+
+	@ set r0 to the location of the registers saved by the core during
+	@ exception entry. Depending on the mode the cpu was in when the
+	@ exception happend that is either on the main or the process stack.
Quoted 8 lines

arch/arm/kernel/entry-header.S line 80

Quoted 5 lines
arch/arm/kernel/entry-header.S +5 -0
+	@ Bit 2 of EXC_RETURN stored in the lr register specifies which stack
+	@ was used.
+	tst	lr, #0x4
+	mrsne	r0, psp
+	addeq	r0, sp, #S_FRAME_SIZE

Could we use some other registers here like r8-r12 so that we keep r0-r7 for syscall handling later and avoid another ldmia?

One upside of using r0 is that

	addeq	r0, sp, #S_FRAME_SIZE

can be encoded in 16 bits while this is not possible and 32 bits are needed. And I wonder if it's allowed to corrupt r8-r12?

Quoted 10 lines
Quoted 10 lines
arch/arm/kernel/entry-header.S +10 -0
+	add	r0, r0, #20		@ skip over r0-r3, r12
+	ldmia	r0!, {r1-r3}		@ load saved lr, return address and xPSR
+
+	@ calculate the orignal stack pointer value.
+	@ r0 currently points to the memory location just above the auto saved
+	@ xPSR. If the FP extension is implemented and bit 4 of EXC_RETURN is 0
+	@ then space was allocated for FP state. That is space for 18 32-bit
+	@ values. (If FP extension is unimplemented, bit 4 is 1.)
+	@ Additionally the cpu might automatically 8-byte align the stack. Bit 9
+	@ of the saved xPSR specifies if stack aligning took place. In this case
Quoted 8 lines

arch/arm/kernel/entry-header.S line 95

Quoted 4 lines
arch/arm/kernel/entry-header.S +4 -0
+	@ another 32-bit value is included in the stack.
+
+	tst	lr, #0x10
+	addeq	r0, r0, #576

I think you can ignore VFP for now. We could change it to do lazy save/restore and avoid the automatic state saving. If it does this while in kernel, it takes a bit of extra stack space.

If I understood correctly this will never trigger for kernel tasks, won't it?

Quoted 4 lines

arch/arm/kernel/entry-header.S line 101

Quoted 2 lines
arch/arm/kernel/entry-header.S +2 -0
+	@ save original sp, lr, return address, xPSR and EXC_RETURN
+	add	r12, sp, #52

Just use S_ARM_SP or whatever asm offsets, it's easier to read.

OK, right.

Quoted 7 lines

arch/arm/kernel/entry-header.S line 105

Quoted 4 lines
arch/arm/kernel/entry-header.S +4 -0
+	stmia	r12, {r0-r3, lr}
+
+	@ restore registers for system calls
+	ldmia	sp, {r0-r12}

We could avoid reloading r0-r7 (that's what we actually need for syscalls) if we don't corrupt them.

See question above. And I noticed that because of tail-chaining we need to load the register values from the exception frame at least once anyhow. I will try to optimise here.

Quoted 37 lines

arch/arm/kernel/entry-header.S line 110

Quoted 5 lines
arch/arm/kernel/entry-header.S +5 -0
+	.endm
+
+	.macro	v7m_exception_fast_exit
+	@ read r12, sp, lr, return address, xPSR and EXC_RETURN
+	add	r12, sp, #48

S_ARM_R12?

Quoted 11 lines
arch/arm/kernel/entry-header.S +11 -0
+	ldmia	r12, {r1-r5, lr}
+
+	tst     r5, #0x100
+	subne   r2, r2, #4
+
+	tst	lr, #0x10
+	subeq	r2, r2, #576
+
+	stmdb	r2!, {r1, r3-r5}		@ write saved r12, lr, return address and xPSR
+
+	ldmia	sp, {r1, r3-r5}			@ read saved r0-r3

arch/arm/kernel/entry-header.S line 131

Quoted 10 lines
arch/arm/kernel/entry-header.S +10 -0
+	stmdb	r2!, {r1, r3-r5}		@ write r0-r3 to basic exception frame
+
+	tst	lr, #0x4
+	msrne	psp, r2
+
+	ldmia	sp, {r0-r12}
+	add	sp, #S_FRAME_SIZE
+	cpsie	i
+	bx	lr
+	.endm

In the context v7m_exception_fast_exit is used (return from interrupts), the previously saved r0-r4,r12 etc. are still on the return stack and restored from there. There is no need for the ldmia/stmdb to re-create the interrupted process stack. Here we only need to make sure that we restore the registers that were not automatically saved and also move the kernel SP back to the original location (add S_FRAME_SIZE).

Quoted 2 lines

We handle rescheduling and work pending by raising PendSV, so we get another interrupt which would be returned via the slow_exit macro.

I was not sure if a task could be preempted during an exception. So I choosed to play save.

Quoted 43 lines
Quoted 30 lines
arch/arm/kernel/entry-header.S +30 -0
+	.macro	v7m_exception_slow_exit ret_r0
+	cpsid	i
+	ldr	lr, [sp, #S_EXCRET]		@ read exception LR
+	tst     lr, #0x8
+	bne	1f				@ go to thread mode using exception return
+
+	/*
+	 * return to kernel thread
+	 * sp is already set up (and might be unset in pt_regs), so only
+	 * restore r0-r12 and pc
+	 */
+	ldmia	sp, {r0-r12}
+	ldr	lr, [sp, #S_PC]
+	add	sp, sp, #S_FRAME_SIZE
+	cpsie	i
+	bx	lr
+	/*
+	 * return to userspace
+	 */
+1:
+	@ read original r12, sp, lr, pc, xPSR
+	add	r12, sp, #48
+	ldmia	r12, {r1-r5}
+
+	/* stack aligning */
+	tst	r5, #0x100
+	subne	r2, r2, #4
+
+	/* skip over stack space for fp extension */
+	tst	lr, #0x10

arch/arm/kernel/entry-header.S line 173

Quoted 10 lines
arch/arm/kernel/entry-header.S +10 -0
+	subeq	r2, r2, #576
+
+	/* write basic exception frame */
+	stmdb	r2!, {r1, r3-r5}		@ saved r12, lr, return address and xPSR
+	ldmia	sp, {r1, r3-r5}			@ read saved r0-r3
+	.if	\ret_r0
+	stmdb	r2!, {r0, r3-r5}		@ restore r0-r3
+	.else
+	stmdb	r2!, {r1, r3-r5}		@ restore r0-r3
+	.endif

This looks fine.

Quoted 5 lines

arch/arm/kernel/entry-header.S line 177

Quoted 3 lines
arch/arm/kernel/entry-header.S +3 -0
+	msr	psp, r2
+
+	ldmia	sp, {r0-r12}			@ restore original r4-r11

Isn't this reading too much (optimisation)?

yeah, I think r12 isn't needed. For r0-r3 I'm not sure which is better:

	ldmia	sp, {r0-r11}
	add	sp, #S_FRAME_SIZE

vs.

	add	sp, #S_R4
	ldmia	sp, {r4-r11}
	add	sp, #S_FRAME_SIZE - S_R4

It's not described in the V7-M reverence. Do you know a document where I can look that up?

Quoted 23 lines
Quoted 5 lines
arch/arm/kernel/entry-header.S +5 -0
+	add	sp, #S_FRAME_SIZE		@ restore the original MSP
+	cpsie	i
+	bx	lr
+	.endm
+#endif	/* CONFIG_CPU_V7M */

...

Quoted 17 lines
arch/arm/kernel/process.c +4 -0
@@ -452,7 +452,11 @@ asm(	".pushsection .text\n"
 #ifdef CONFIG_TRACE_IRQFLAGS
 "	bl	trace_hardirqs_on\n"
 #endif
+#ifdef CONFIG_CPU_V7M
+"	msr	primask, r7\n"
+#else
 "	msr	cpsr_c, r7\n"
+#endif
 "	mov	r0, r4\n"
 "	mov	lr, r6\n"
 "	mov	pc, r5\n"
@@ -491,6 +495,10 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 	regs.ARM_r7 = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE;
 	regs.ARM_pc = (unsigned long)kernel_thread_helper;
Quoted 8 lines

arch/arm/kernel/process.c pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) · line 501

Quoted 5 lines
arch/arm/kernel/process.c +4 -0
 	regs.ARM_cpsr = regs.ARM_r7 | PSR_I_BIT;
+#ifdef CONFIG_CPU_V7M
+	/* Return to Handler mode */
+	regs.ARM_EXCRET = 0xfffffff1L;
+#endif

BTW, do we need to set this here? We don't return to a kernel thread via exception return.

But we need it to decide in slow_return if we should use exception return or not. So yes, I think it's needed.

Quoted 2 lines

I currently cannot see any obvious bugs in the code. Since you said it doesn't work, what are the symptoms?

I found two problems. One is I wasn't aware that r0-r3,r12 doesn't necessarily need to match the values on exception entry (because of tail-chaining) and in start_thread decreasing sp is wrong.

I will reimplement the three macros now with the new lessons learned.

Best regards and thanks for your input (here and on irc) Uwe

Signature · 2 lines
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
#38 lore raw

PATCH v2 4/5 Cortex-M3: Add base support for Cortex-M3

In reply to Uwe Kleine-König

Hi Uwe,

Quoted 14 lines · Uwe Kleine-K?nig
arch/arm/include/asm/processor.h +7 -0
@@ -49,7 +49,15 @@ struct thread_struct {
 #ifdef CONFIG_MMU
 #define nommu_start_thread(regs) do { } while (0)
 #else
+#ifndef CONFIG_CPU_V7M
 #define nommu_start_thread(regs) regs->ARM_r10 = current->mm->start_data
+#else
+#define nommu_start_thread(regs) do {                                  \
+       regs->ARM_r10 = current->mm->start_data;                        \
+       regs->ARM_sp -= 32;             /* exception return state */    \
+       regs->ARM_EXCRET = 0xfffffffdL;                                 \
+} while (0)

...

arch/arm/include/asm/ptrace.h struct pt_regs { · line 143

Quoted 12 lines
arch/arm/include/asm/ptrace.h +4 -0
@@ -39,16 +39,25 @@
@@ -127,7 +136,11 @@ struct pt_regs {
 #define ARM_r2         uregs[2]
 #define ARM_r1         uregs[1]
 #define ARM_r0         uregs[0]
+#if defined CONFIG_CPU_V7M
+#define ARM_EXCRET     uregs[17]
+#else
 #define ARM_ORIG_r0    uregs[17]
+#endif

Could we save the exception return somewhere in thread_info and preserve ORIG_r0?

Alternatively, with some care, we could extend the kernel pt_regs definition with two more registers and use one of them for exception return. The user variant would remain the same as it's used by ptrace.

Signature · 1 line
Catalin
#39 lore raw

PATCH 1/5 ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15

In reply to Uwe Kleine-König
Quoted 9 lines · Uwe Kleine-K?nig
---
 arch/arm/include/asm/system.h |    2 ++
 arch/arm/kernel/entry-armv.S  |    4 ++++
 arch/arm/kernel/head-common.S |   10 ++++++++--
 arch/arm/kernel/setup.c       |    8 ++++++--
 arch/arm/mm/alignment.c       |    6 ++++++
 arch/arm/mm/mmu.c             |    8 +++++++-
 6 files changed, 33 insertions(+), 5 deletions(-)

Hi Uwe,

Couple of points below,

Thanks,
~Ryan

Quoted 55 lines
arch/arm/include/asm/system.h +2 -0
index e4c96cc..de46477 100644
@@ -185,6 +185,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 */
 
@@ -224,6 +225,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,
arch/arm/kernel/entry-armv.S +4 -0
index be16a48..a6f2ef5 100644
@@ -314,8 +314,10 @@ __pabt_svc:
 ENDPROC(__pabt_svc)
 
 	.align	5
+#ifdef CONFIG_CPU_CP15
 .LCcralign:
 	.word	cr_alignment
+#endif
 #ifdef MULTI_DABORT
 .LCprocfns:
 	.word	processor
@@ -1146,12 +1148,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
arch/arm/kernel/head-common.S +0 -0
index 854bd22..5ca01bb 100644

arch/arm/kernel/head-common.S __mmap_switched: · line 104

Quoted 9 lines
arch/arm/kernel/head-common.S +4 -2
@@ -98,8 +98,10 @@ __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
+	itt	ne
+	bicne	r4, r0, #CR_A			@ Clear 'A' bit
+	stmneia	r7, {r0, r4}			@ Save control register values

Can the cr_alignment variable ever have a value of zero if CONFIG_CPU_15 is enabled? If so you fail to do the stmnia which is possibly not correct? Why do the registers not need to be stored if cr_alignment is zero? I think this at least deserves a comment explaining.

Also, couldn't it just be done like this:

#ifndef CONFIG_CPU_CP15
	bic	r4, r0, #CR_A
	stimia	r7, {r0, r4}

#endif

Since r7 will always be zero in the !CP15 case?

Quoted 21 lines
arch/arm/kernel/head-common.S +4 -0
 	b	start_kernel
 ENDPROC(__mmap_switched)
 
@@ -113,7 +115,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
 
arch/arm/kernel/setup.c +0 -0
index a255c39..50d3df8 100644
@@ -472,9 +472,13 @@ static void __init setup_processor(void)
 	cpu_cache = *list->cache;

arch/arm/kernel/setup.c static void __init setup_processor(void) · line 480

Quoted 10 lines
arch/arm/kernel/setup.c +5 -2
 #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);
#else
	printk(KERN_CONT "\n");

?

Quoted 82 lines
arch/arm/kernel/setup.c +1 -0
+#endif
 
 
 	snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c",
arch/arm/kernel/setup.c +0 -0
 		 list->arch_name, ENDIANNESS);
arch/arm/mm/alignment.c +4 -0
index caf14dc..119d178 100644
@@ -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)

arch/arm/mm/alignment.c +2 -0
@@ -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(FAULT_CODE_ALIGNMENT, do_alignment, SIGBUS, BUS_ADRALN,
 			"alignment exception");
arch/arm/mm/mmu.c +7 -1
index 94c5a0c..f6dbe1a 100644
@@ -109,8 +109,10 @@ static int __init early_cachepolicy(char *p)
 
 		if (memcmp(p, cache_policies[i].policy, len) == 0) {
 			cachepolicy = i;
+#ifdef CONFIG_CPU_CP15
 			cr_alignment &= ~cache_policies[i].cr_mask;
 			cr_no_alignment &= ~cache_policies[i].cr_mask;
+#endif
 			break;
 		}
 	}
@@ -128,7 +130,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);
@@ -163,6 +167,7 @@ static int __init early_ecc(char *p)
 early_param("ecc", early_ecc);
 #endif
 
+#ifdef CONFIG_CPU_CP15
 static int __init noalign_setup(char *__unused)
 {
 	cr_alignment &= ~CR_A;
@@ -171,8 +176,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;