All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 00/11] Cortex-M3 support
@ 2012-01-22 11:12 Uwe Kleine-König
  2012-01-22 11:13 ` [RFC PATCH 01/11] ARM: only show modules in the memory layout for MODULES=y Uwe Kleine-König
                   ` (11 more replies)
  0 siblings, 12 replies; 40+ messages in thread
From: Uwe Kleine-König @ 2012-01-22 11:12 UTC (permalink / raw)
  To: linux-arm-kernel

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

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [RFC PATCH 01/11] ARM: only show modules in the memory layout for MODULES=y
  2012-01-22 11:12 [RFC PATCH 00/11] Cortex-M3 support Uwe Kleine-König
@ 2012-01-22 11:13 ` Uwe Kleine-König
  2012-01-26  6:16   ` Linus Walleij
  2012-01-22 11:13 ` [RFC PATCH 02/11] ARM: add device tree blobs to .gitignore Uwe Kleine-König
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 40+ messages in thread
From: Uwe Kleine-König @ 2012-01-22 11:13 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
Acked-by: Nicolas Pitre <nico@linaro.org>
---
 arch/arm/mm/init.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 6ec1226..42d906f 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -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),
-- 
1.7.8.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC PATCH 02/11] ARM: add device tree blobs to .gitignore
  2012-01-22 11:12 [RFC PATCH 00/11] Cortex-M3 support Uwe Kleine-König
  2012-01-22 11:13 ` [RFC PATCH 01/11] ARM: only show modules in the memory layout for MODULES=y Uwe Kleine-König
@ 2012-01-22 11:13 ` Uwe Kleine-König
  2012-01-22 11:13 ` [RFC PATCH 03/11] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15 Uwe Kleine-König
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 40+ messages in thread
From: Uwe Kleine-König @ 2012-01-22 11:13 UTC (permalink / raw)
  To: linux-arm-kernel

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

Acked-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
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(-)

diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore
index ce1c5ff..3c79f85 100644
--- a/arch/arm/boot/.gitignore
+++ b/arch/arm/boot/.gitignore
@@ -3,3 +3,4 @@ zImage
 xipImage
 bootpImage
 uImage
+*.dtb
-- 
1.7.8.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC PATCH 03/11] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15
  2012-01-22 11:12 [RFC PATCH 00/11] Cortex-M3 support Uwe Kleine-König
  2012-01-22 11:13 ` [RFC PATCH 01/11] ARM: only show modules in the memory layout for MODULES=y Uwe Kleine-König
  2012-01-22 11:13 ` [RFC PATCH 02/11] ARM: add device tree blobs to .gitignore Uwe Kleine-König
@ 2012-01-22 11:13 ` Uwe Kleine-König
  2012-01-23  5:43   ` Jean-Christophe PLAGNIOL-VILLARD
  2012-01-22 11:13 ` [RFC PATCH 04/11] ARM: Add a printk loglevel modifier Uwe Kleine-König
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 40+ messages in thread
From: Uwe Kleine-König @ 2012-01-22 11:13 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
 arch/arm/include/asm/system.h |    2 ++
 arch/arm/kernel/entry-armv.S  |    4 ++++
 arch/arm/kernel/head-common.S |    9 +++++++--
 arch/arm/kernel/setup.c       |    8 ++++++--
 arch/arm/mm/alignment.c       |    6 ++++++
 arch/arm/mm/mmu.c             |    8 +++++++-
 6 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index e4c96cc..de46477 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -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,
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 3a456c6..15bfeff 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -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
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index 854bd22..2f560c5 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -98,8 +98,9 @@ __mmap_switched:
 	str	r9, [r4]			@ Save processor ID
 	str	r1, [r5]			@ Save machine type
 	str	r2, [r6]			@ Save atags pointer
-	bic	r4, r0, #CR_A			@ Clear 'A' bit
-	stmia	r7, {r0, r4}			@ Save control register values
+	cmp	r7, #0
+	bicne	r4, r0, #CR_A			@ Clear 'A' bit
+	stmneia	r7, {r0, r4}			@ Save control register values
 	b	start_kernel
 ENDPROC(__mmap_switched)
 
@@ -113,7 +114,11 @@ __mmap_switched_data:
 	.long	processor_id			@ r4
 	.long	__machine_arch_type		@ r5
 	.long	__atags_pointer			@ r6
+#ifdef CONFIG_CPU_CP15
 	.long	cr_alignment			@ r7
+#else
+	.long	0
+#endif
 	.long	init_thread_union + THREAD_START_SP @ sp
 	.size	__mmap_switched_data, . - __mmap_switched_data
 
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 129fbd5..3849737 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -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);
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index caf14dc..119d178 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -89,7 +89,11 @@ core_param(alignment, ai_usermode, int, 0600);
 /* Return true if and only if the ARMv6 unaligned access model is in use. */
 static bool cpu_is_v6_unaligned(void)
 {
+#ifdef CONFIG_CPU_CP15
 	return cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U);
+#else
+	return 0;
+#endif
 }
 
 static int safe_usermode(int new_usermode, bool warn)
@@ -961,12 +965,14 @@ static int __init alignment_init(void)
 		return -ENOMEM;
 #endif
 
+#ifdef CONFIG_CPU_CP15
 	if (cpu_is_v6_unaligned()) {
 		cr_alignment &= ~CR_A;
 		cr_no_alignment &= ~CR_A;
 		set_cr(cr_alignment);
 		ai_usermode = safe_usermode(ai_usermode, false);
 	}
+#endif
 
 	hook_fault_code(FAULT_CODE_ALIGNMENT, do_alignment, SIGBUS, BUS_ADRALN,
 			"alignment exception");
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 94c5a0c..f6dbe1a 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -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;
-- 
1.7.8.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC PATCH 04/11] ARM: Add a printk loglevel modifier
  2012-01-22 11:12 [RFC PATCH 00/11] Cortex-M3 support Uwe Kleine-König
                   ` (2 preceding siblings ...)
  2012-01-22 11:13 ` [RFC PATCH 03/11] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15 Uwe Kleine-König
@ 2012-01-22 11:13 ` Uwe Kleine-König
  2012-01-23  5:50   ` Jean-Christophe PLAGNIOL-VILLARD
  2012-01-22 11:13 ` [RFC PATCH 05/11] ARM: provide XIP_VIRT_ADDR for no-MMU builds Uwe Kleine-König
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 40+ messages in thread
From: Uwe Kleine-König @ 2012-01-22 11:13 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
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(-)

diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 3849737..f7c0d55 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -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",
-- 
1.7.8.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC PATCH 05/11] ARM: provide XIP_VIRT_ADDR for no-MMU builds
  2012-01-22 11:12 [RFC PATCH 00/11] Cortex-M3 support Uwe Kleine-König
                   ` (3 preceding siblings ...)
  2012-01-22 11:13 ` [RFC PATCH 04/11] ARM: Add a printk loglevel modifier Uwe Kleine-König
@ 2012-01-22 11:13 ` Uwe Kleine-König
  2012-01-22 11:13 ` [RFC PATCH 06/11] Cortex-M3: Add base support for Cortex-M3 Uwe Kleine-König
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 40+ messages in thread
From: Uwe Kleine-König @ 2012-01-22 11:13 UTC (permalink / raw)
  To: linux-arm-kernel

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
Acked-by: Nicolas Pitre <nico@linaro.org>
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
 arch/arm/include/asm/memory.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index a8997d7..fcb5757 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -116,6 +116,8 @@
 #define MODULES_END		(END_MEM)
 #define MODULES_VADDR		(PHYS_OFFSET)
 
+#define XIP_VIRT_ADDR(physaddr)  (physaddr)
+
 #endif /* !CONFIG_MMU */
 
 /*
-- 
1.7.8.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC PATCH 06/11] Cortex-M3: Add base support for Cortex-M3
  2012-01-22 11:12 [RFC PATCH 00/11] Cortex-M3 support Uwe Kleine-König
                   ` (4 preceding siblings ...)
  2012-01-22 11:13 ` [RFC PATCH 05/11] ARM: provide XIP_VIRT_ADDR for no-MMU builds Uwe Kleine-König
@ 2012-01-22 11:13 ` Uwe Kleine-König
  2012-01-22 19:45   ` Michał Mirosław
  2012-01-22 11:13 ` [RFC PATCH 07/11] Cortex-M3: Add support for exception handling Uwe Kleine-König
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 40+ messages in thread
From: Uwe Kleine-König @ 2012-01-22 11:13 UTC (permalink / raw)
  To: linux-arm-kernel

From: Catalin Marinas <catalin.marinas@arm.com>

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]

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
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

diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index b6e65de..f2083c3 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -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
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index cb47d28..5bd8cb6 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -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
diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h
index 7e30874..6a5fd0b 100644
--- a/arch/arm/include/asm/glue-cache.h
+++ b/arch/arm/include/asm/glue-cache.h
@@ -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)
diff --git a/arch/arm/include/asm/glue-df.h b/arch/arm/include/asm/glue-df.h
index 354d571..26be71c 100644
--- a/arch/arm/include/asm/glue-df.h
+++ b/arch/arm/include/asm/glue-df.h
@@ -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
diff --git a/arch/arm/include/asm/glue-proc.h b/arch/arm/include/asm/glue-proc.h
index e2be7f1..8f9991b 100644
--- a/arch/arm/include/asm/glue-proc.h
+++ b/arch/arm/include/asm/glue-proc.h
@@ -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)
diff --git a/arch/arm/include/asm/irqflags.h b/arch/arm/include/asm/irqflags.h
index 1e6cca5..ac4d548 100644
--- a/arch/arm/include/asm/irqflags.h
+++ b/arch/arm/include/asm/irqflags.h
@@ -10,6 +10,18 @@
  */
 #if __LINUX_ARM_ARCH__ >= 6
 
+#ifdef CONFIG_CPU_V7M
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags;
+
+	asm volatile(
+		"	mrs	%0, primask	@ arch_local_irq_save\n"
+		"	cpsid	i"
+		: "=r" (flags) : : "memory", "cc");
+	return flags;
+}
+#else
 static inline unsigned long arch_local_irq_save(void)
 {
 	unsigned long flags;
@@ -20,6 +32,7 @@ static inline unsigned long arch_local_irq_save(void)
 		: "=r" (flags) : : "memory", "cc");
 	return flags;
 }
+#endif
 
 static inline void arch_local_irq_enable(void)
 {
@@ -122,6 +135,38 @@ static inline void arch_local_irq_disable(void)
 
 #endif
 
+#ifdef CONFIG_CPU_V7M
+/*
+ * Save the current interrupt enable state.
+ */
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long flags;
+	asm volatile(
+		"	mrs	%0, primask	@ local_save_flags"
+		: "=r" (flags) : : "memory", "cc");
+	return flags;
+}
+
+/*
+ * restore saved IRQ & FIQ state
+ */
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	asm volatile(
+		"	msr	primask, %0	@ local_irq_restore"
+		:
+		: "r" (flags)
+		: "memory", "cc");
+}
+
+static inline int arch_irqs_disabled_flags(unsigned long flags)
+{
+	return flags & 1;
+}
+
+#else /* ifdef CONFIG_CPU_V7M */
+
 /*
  * Save the current interrupt enable state.
  */
@@ -151,5 +196,7 @@ static inline int arch_irqs_disabled_flags(unsigned long flags)
 	return flags & PSR_I_BIT;
 }
 
-#endif
-#endif
+#endif /* ifdef CONFIG_CPU_V7M / else */
+
+#endif /* ifdef __KERNEL__ */
+#endif /* ifndef __ASM_ARM_IRQFLAGS_H */
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index ce280b8..aa4c8a2 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -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)					\
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 451808b..1feb9a0 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -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
@@ -106,10 +115,37 @@ struct pt_regs {
 };
 #else /* __KERNEL__ */
 struct pt_regs {
+#ifdef CONFIG_CPU_V7M
+	unsigned long uregs[20];
+#else
 	unsigned long uregs[18];
+#endif
 };
 #endif /* __KERNEL__ */
 
+#ifdef CONFIG_CPU_V7M
+/* Automatically saved registers */
+#define ARM_cpsr	uregs[17]
+#define ARM_pc		uregs[16]
+#define ARM_lr		uregs[15]
+#define ARM_ip		uregs[14]
+#define ARM_r3		uregs[13]
+#define ARM_r2		uregs[12]
+#define ARM_r1		uregs[11]
+#define ARM_r0		uregs[10]
+/* saved by the exception entry code */
+#define ARM_EXC_lr	uregs[9]
+#define ARM_sp		uregs[8]
+#define ARM_fp		uregs[7]
+#define ARM_r10		uregs[6]
+#define ARM_r9		uregs[5]
+#define ARM_r8		uregs[4]
+#define ARM_r7		uregs[3]
+#define ARM_r6		uregs[2]
+#define ARM_r5		uregs[1]
+#define ARM_r4		uregs[0]
+#define ARM_ORIG_r0	uregs[18]
+#else
 #define ARM_cpsr	uregs[16]
 #define ARM_pc		uregs[15]
 #define ARM_lr		uregs[14]
@@ -128,6 +164,7 @@ struct pt_regs {
 #define ARM_r1		uregs[1]
 #define ARM_r0		uregs[0]
 #define ARM_ORIG_r0	uregs[17]
+#endif
 
 /*
  * The size of the user-visible VFP state as seen by PTRACE_GET/SETVFPREGS
@@ -165,6 +202,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 +225,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)
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index de46477..16117ed 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -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'
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 1429d89..e861849 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -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
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index 2f560c5..2852c37 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -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
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index d46f259..dba31af 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -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)?
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index f7c0d55..da7b17d 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -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)
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 99a5727..8956d08 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -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
 }
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
index 4fc6794..fdd49ac 100644
--- a/arch/arm/mm/nommu.c
+++ b/arch/arm/mm/nommu.c
@@ -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)
diff --git a/arch/arm/mm/proc-v7m.S b/arch/arm/mm/proc-v7m.S
new file mode 100644
index 0000000..a17653a
--- /dev/null
+++ b/arch/arm/mm/proc-v7m.S
@@ -0,0 +1,178 @@
+/*
+ *  linux/arch/arm/mm/proc-v7m.S
+ *
+ *  Copyright (C) 2008 ARM Ltd.
+ *  Copyright (C) 2001 Deep Blue Solutions Ltd.
+ *
+ * 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.
+ *
+ *  This is the "shell" of the ARMv7-M processor support.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+ENTRY(cpu_v7m_proc_init)
+	mov	pc, lr
+ENDPROC(cpu_v7m_proc_init)
+
+ENTRY(cpu_v7m_proc_fin)
+	mov	pc, lr
+ENDPROC(cpu_v7m_proc_fin)
+
+/*
+ *	cpu_v7m_reset(loc)
+ *
+ *	Perform a soft reset of the system.  Put the CPU into the
+ *	same state as it would be if it had been reset, and branch
+ *	to what would be the reset vector.
+ *
+ *	- loc   - location to jump to for soft reset
+ */
+	.align	5
+ENTRY(cpu_v7m_reset)
+	mov	pc, r0
+ENDPROC(cpu_v7m_reset)
+
+/*
+ *	cpu_v7m_do_idle()
+ *
+ *	Idle the processor (eg, wait for interrupt).
+ *
+ *	IRQs are already disabled.
+ */
+ENTRY(cpu_v7m_do_idle)
+	wfi
+	mov	pc, lr
+ENDPROC(cpu_v7m_do_idle)
+
+ENTRY(cpu_v7m_dcache_clean_area)
+	mov	pc, lr
+ENDPROC(cpu_v7m_dcache_clean_area)
+
+/*
+ *	cpu_v7m_switch_mm(pgd_phys, tsk)
+ *
+ *	Set the translation table base pointer to be pgd_phys
+ *
+ *	- pgd_phys - physical address of new TTB
+ *
+ *	It is assumed that:
+ *	- we are not using split page tables
+ */
+ENTRY(cpu_v7m_switch_mm)
+	mov	pc, lr
+ENDPROC(cpu_v7m_switch_mm)
+
+cpu_v7m_name:
+	.ascii	"ARMv7-M Processor"
+	.align
+
+	.section ".text.init", #alloc, #execinstr
+
+/*
+ *	__v7m_setup
+ *
+ *	Initialise TLB, Caches, and MMU state ready to switch the MMU
+ *	on.  Return in r0 the new CP15 C1 control register setting.
+ *
+ *	We automatically detect if we have a Harvard cache, and use the
+ *	Harvard cache control instructions insead of the unified cache
+ *	control instructions.
+ *
+ *	This should be able to cover all ARMv7-M cores.
+ *
+ *	It is assumed that:
+ *	- cache type register is implemented
+ */
+__v7m_setup:
+	@ Configure the vector table base address
+	ldr	r0, =0xe000ed08		@ vector table base address
+	ldr	r12, =vector_table
+	str	r12, [r0]
+
+	@ Lower the priority of the SVC and PendSV exceptions
+	ldr	r0, =0xe000ed1c
+	mov	r5, #0x80000000
+	str	r5, [r0]		@ set SVC priority
+	ldr	r0, =0xe000ed20
+	mov	r5, #0x00800000
+	str	r5, [r0]		@ set PendSV priority
+
+	@ SVC to run the kernel in this mode
+	adr	r0, BSYM(1f)
+	ldr	r5, [r12, #11 * 4]	@ read the SVC vector entry
+	str	r0, [r12, #11 * 4]	@ write the temporary SVC vector entry
+	mov	r6, lr			@ save LR
+	mov	r7, sp			@ save SP
+	ldr	sp, =__v7m_setup_stack_top
+	cpsie	i
+	svc	#0
+1:	cpsid	i
+	str	r5, [r12, #11 * 4]	@ restore the original SVC vector entry
+	mov	lr, r6			@ restore LR
+	mov	sp, r7			@ restore SP
+
+	@ Special-purpose control register
+	mov	r0, #1
+	msr	control, r0		@ Thread mode has unpriviledged access
+
+	@ Configure the System Control Register
+	ldr	r0, =0xe000ed14		@ system control register
+	ldr	r12, [r0]
+	orr	r12, #1 << 9		@ STKALIGN
+	str	r12, [r0]
+	mov	pc, lr
+ENDPROC(__v7m_setup)
+
+	.align	2
+	.type	v7m_processor_functions, #object
+ENTRY(v7m_processor_functions)
+	.word	nommu_early_abort
+	.word	cpu_v7m_proc_init
+	.word	cpu_v7m_proc_fin
+	.word	cpu_v7m_reset
+	.word	cpu_v7m_do_idle
+	.word	cpu_v7m_dcache_clean_area
+	.word	cpu_v7m_switch_mm
+	.word	0			@ cpu_v7m_set_pte_ext
+	.word	legacy_pabort
+	.size	v7m_processor_functions, . - v7m_processor_functions
+
+	.type	cpu_arch_name, #object
+cpu_arch_name:
+	.asciz	"armv7m"
+	.size	cpu_arch_name, . - cpu_arch_name
+
+	.type	cpu_elf_name, #object
+cpu_elf_name:
+	.asciz	"v7m"
+	.size	cpu_elf_name, . - cpu_elf_name
+	.align
+
+	.section ".proc.info.init", #alloc, #execinstr
+
+	/*
+	 * Match any ARMv7-M processor core.
+	 */
+	.type	__v7m_proc_info, #object
+__v7m_proc_info:
+	.long	0x000f0000		@ Required ID value
+	.long	0x000f0000		@ Mask for ID
+	.long   0			@ proc_info_list.__cpu_mm_mmu_flags
+	.long   0			@ proc_info_list.__cpu_io_mmu_flags
+	b	__v7m_setup		@ proc_info_list.__cpu_flush
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+	.long	cpu_v7m_name
+	.long	v7m_processor_functions	@ proc_info_list.proc
+	.long	0			@ proc_info_list.tlb
+	.long	0			@ proc_info_list.user
+	.long	0			@ proc_info_list.cache
+	.size	__v7m_proc_info, . - __v7m_proc_info
+
+__v7m_setup_stack:
+	.space	4 * 8				@ 8 registers
+__v7m_setup_stack_top:
-- 
1.7.8.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC PATCH 07/11] Cortex-M3: Add support for exception handling
  2012-01-22 11:12 [RFC PATCH 00/11] Cortex-M3 support Uwe Kleine-König
                   ` (5 preceding siblings ...)
  2012-01-22 11:13 ` [RFC PATCH 06/11] Cortex-M3: Add base support for Cortex-M3 Uwe Kleine-König
@ 2012-01-22 11:13 ` Uwe Kleine-König
  2012-01-22 11:13 ` [RFC PATCH 08/11] Cortex-M3: Add NVIC support Uwe Kleine-König
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 40+ messages in thread
From: Uwe Kleine-König @ 2012-01-22 11:13 UTC (permalink / raw)
  To: linux-arm-kernel

From: Catalin Marinas <catalin.marinas@arm.com>

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]

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
 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

diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 520889c..95d3d4a 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -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]
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 9a8531e..8050d9b 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -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)
 #error "Please fix"
 #endif
 
@@ -44,6 +44,89 @@
 #endif
 	.endm
 
+#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). The order of struct
+ * pt_regs members was changed to take advantage of the automatic
+ * state saving.
+ *
+ * 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.
+ *
+ * The v7m_exception_entry macro preserves the original r0-r5, r7 for
+ * the system call arguments.
+ *
+ * v7_exception_fast_exit is used when returning from interrupts.
+ *
+ * v7_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
+	cmp	lr, #0xfffffffd		@ check the return stack
+	beq	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
+2:
+	.endm
+
+	.macro	v7m_exception_fast_exit
+	ldmia	sp!, {r4-r12, lr}	@ restore previously saved state
+	cmp	lr, #0xfffffffd		@ check the return stack
+	addeq	sp, #32			@ returning to PSP, just restore MSP
+	cpsie	i
+	bx	lr
+	.endm
+
+	.macro	v7m_exception_slow_exit ret_r0
+	cpsid	i
+	ldr	lr, [sp, #S_EXC_LR]	@ read exception LR
+	cmp	lr, #0xfffffffd		@ check the return stack
+	beq	1f			@ returning to PSP
+	@ Prepare the MSP stack
+	ldmia	sp, {r4-r11}		@ restore previously saved state
+	ldr	lr, [sp, #S_PC]
+	add	sp, #S_R0
+	ldmia	sp, {r0-r3, r12}	@ restore the rest of registers
+	add	sp, #S_FRAME_SIZE-S_R0	@ restore the stack pointer
+	cpsie	i
+	bx	lr
+1:
+	@ Prepare the PSP stack
+	ldr	r12, [sp, #S_SP]	@ read original PSP
+	.if	\ret_r0
+	add	r11, sp, #S_R1
+	ldmia	r11, {r1-r7}		@ read state saved on MSP (r0 preserved)
+	.else
+	add	r11, sp, #S_R0
+	ldmia	r11, {r0-r7}		@ read state saved on MSP
+	.endif
+	msr	psp, r12		@ restore PSP
+	stmia	r12, {r0-r7}		@ restore saved state to PSP
+	ldmia	sp, {r4-r11}		@ restore previously saved state
+	add	sp, #S_FRAME_SIZE	@ restore the original MSP
+	cpsie	i
+	bx	lr
+	.endm
+#endif	/* CONFIG_CPU_V7M */
+
 	@
 	@ Store/load the USER SP and LR registers by switching to the SYS
 	@ mode. Useful in Thumb-2 mode where "stm/ldm rd, {sp, lr}^" is not
@@ -131,6 +214,14 @@
 	rfeia	sp!
 	.endm
 
+#ifdef CONFIG_CPU_V7M
+	.macro	restore_user_regs, fast = 0, offset = 0
+	.if	\offset
+	add	sp, #\offset
+	.endif
+	v7m_exception_slow_exit ret_r0 = \fast
+	.endm
+#else	/* !CONFIG_CPU_V7M */
 	.macro	restore_user_regs, fast = 0, offset = 0
 	clrex					@ clear the exclusive monitor
 	mov	r2, sp
@@ -147,6 +238,7 @@
 	add	sp, sp, #S_FRAME_SIZE - S_SP
 	movs	pc, lr				@ return & move spsr_svc into cpsr
 	.endm
+#endif	/* CONFIG_CPU_V7M */
 
 	.macro	get_thread_info, rd
 	mov	\rd, sp
diff --git a/arch/arm/kernel/entry-v7m.S b/arch/arm/kernel/entry-v7m.S
new file mode 100644
index 0000000..d216be5
--- /dev/null
+++ b/arch/arm/kernel/entry-v7m.S
@@ -0,0 +1,131 @@
+/*
+ * linux/arch/arm/kernel/entry-v7m.S
+ *
+ * Copyright (C) 2008 ARM Ltd.
+ *
+ * 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.
+ *
+ * Low-level vector interface routines for the ARMv7-M architecture
+ */
+#include <asm/memory.h>
+#include <asm/glue.h>
+#include <asm/thread_notify.h>
+
+#include <mach/entry-macro.S>
+
+#include "entry-header.S"
+
+#ifdef CONFIG_PREEMPT
+#error "CONFIG_PREEMPT not supported on the current ARMv7M implementation"
+#endif
+#ifdef CONFIG_TRACE_IRQFLAGS
+#error "CONFIG_TRACE_IRQFLAGS not supported on the current ARMv7M implementation"
+#endif
+
+__invalid_entry:
+	v7m_exception_entry
+	adr	r0, strerr
+	mrs	r1, ipsr
+	mov	r2, lr
+	bl	printk
+	mov	r0, sp
+	bl	show_regs
+1:	b	1b
+ENDPROC(__invalid_entry)
+
+strerr:	.asciz	"\nUnhandled exception: IPSR = %08lx LR = %08lx\n"
+
+	.align	2
+__irq_entry:
+	v7m_exception_entry
+
+	@
+	@ Invoke the IRQ handler
+	@
+	mrs	r0, ipsr
+	and	r0, #0xff
+	sub	r0, #16			@ IRQ number
+	mov	r1, sp
+	@ routine called with r0 = irq number, r1 = struct pt_regs *
+	bl	asm_do_IRQ
+
+	@
+	@ Check for any pending work if returning to user
+	@
+	ldr	lr, [sp, #S_EXC_LR]
+	cmp	lr, #0xfffffffd		@ check the return stack
+	bne	2f			@ returning to kernel
+	get_thread_info tsk
+	ldr	r1, [tsk, #TI_FLAGS]
+	tst	r1, #_TIF_WORK_MASK
+	beq	2f			@ no work pending
+	ldr	r1, =0xe000ed04		@ ICSR
+	mov	r0, #1 << 28		@ ICSR.PENDSVSET
+	str	r0, [r1]		@ raise PendSV
+
+2:
+	v7m_exception_fast_exit
+ENDPROC(__irq_entry)
+
+__pendsv_entry:
+	v7m_exception_entry
+
+	ldr	r1, =0xe000ed04		@ ICSR
+	mov	r0, #1 << 27		@ ICSR.PENDSVCLR
+	str	r0, [r1]		@ clear PendSV
+
+	@ execute the pending work, including reschedule
+	get_thread_info tsk
+	mov	why, #0
+	b	ret_to_user
+ENDPROC(__pendsv_entry)
+
+/*
+ * Register switch for ARMv7-M processors.
+ * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info
+ * previous and next are guaranteed not to be the same.
+ */
+ENTRY(__switch_to)
+	add	ip, r1, #TI_CPU_SAVE
+	stmia	ip!, {r4 - sl, fp}	@ Store most regs on stack
+	str	sp, [ip], #4
+	str	lr, [ip], #4
+	mov	r5, r0
+	add	r4, r2, #TI_CPU_SAVE
+	ldr	r0, =thread_notify_head
+	mov	r1, #THREAD_NOTIFY_SWITCH
+	bl	atomic_notifier_call_chain
+	mov	ip, r4
+	mov	r0, r5
+	ldmia	ip!, {r4 - sl, fp}	@ Load all regs saved previously
+	ldr	sp, [ip], #4
+	ldr	pc, [ip]
+ENDPROC(__switch_to)
+
+	.data
+	.align	8
+/*
+ * Vector table (64 words => 256 bytes natural alignment)
+ */
+ENTRY(vector_table)
+	.long	0			@ 0 - Reset stack pointer
+	.long	__invalid_entry		@ 1 - Reset
+	.long	__invalid_entry		@ 2 - NMI
+	.long	__invalid_entry		@ 3 - HardFault
+	.long	__invalid_entry		@ 4 - MemManage
+	.long	__invalid_entry		@ 5 - BusFault
+	.long	__invalid_entry		@ 6 - UsageFault
+	.long	__invalid_entry		@ 7 - Reserved
+	.long	__invalid_entry		@ 8 - Reserved
+	.long	__invalid_entry		@ 9 - Reserved
+	.long	__invalid_entry		@ 10 - Reserved
+	.long	vector_swi		@ 11 - SVCall
+	.long	__invalid_entry		@ 12 - Debug Monitor
+	.long	__invalid_entry		@ 13 - Reserved
+	.long	__pendsv_entry		@ 14 - PendSV
+	.long	__invalid_entry		@ 15 - SysTick
+	.rept	64 - 16
+	.long	__irq_entry		@ 16..64 - External Interrupts
+	.endr
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 971d65c..ee604dd 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -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);
 }
-- 
1.7.8.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC PATCH 08/11] Cortex-M3: Add NVIC support
  2012-01-22 11:12 [RFC PATCH 00/11] Cortex-M3 support Uwe Kleine-König
                   ` (6 preceding siblings ...)
  2012-01-22 11:13 ` [RFC PATCH 07/11] Cortex-M3: Add support for exception handling Uwe Kleine-König
@ 2012-01-22 11:13 ` Uwe Kleine-König
  2012-01-31 19:39   ` Uwe Kleine-König
  2012-01-22 11:13 ` [RFC PATCH 09/11] Cortex-M3: Allow the building of Cortex-M3 kernel port Uwe Kleine-König
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 40+ messages in thread
From: Uwe Kleine-König @ 2012-01-22 11:13 UTC (permalink / raw)
  To: linux-arm-kernel

From: Catalin Marinas <catalin.marinas@arm.com>

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

[ukleinek: use a raw spinlock]
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
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

diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index 81a933e..74adbe7 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -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
 
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 6ea9b6f..102f5a2 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -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
diff --git a/arch/arm/common/nvic.c b/arch/arm/common/nvic.c
new file mode 100644
index 0000000..a0d76f4
--- /dev/null
+++ b/arch/arm/common/nvic.c
@@ -0,0 +1,98 @@
+/*
+ *  linux/arch/arm/common/nvic.c
+ *
+ *  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.
+ *
+ * Support for the Nested Vectored Interrupt Controller found on the
+ * ARMv7-M CPUs (Cortex-M3)
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/mach/irq.h>
+#include <asm/hardware/nvic.h>
+
+static DEFINE_RAW_SPINLOCK(irq_controller_lock);
+
+/*
+ * Routines to acknowledge, disable and enable interrupts
+ *
+ * Linux assumes that when we're done with an interrupt we need to
+ * unmask it, in the same way we need to unmask an interrupt when
+ * we first enable it.
+ *
+ * The NVIC has a separate notion of "end of interrupt" to re-enable
+ * an interrupt after handling, in order to support hardware
+ * prioritisation.
+ *
+ * We can make the NVIC behave in the way that Linux expects by making
+ * our "acknowledge" routine disable the interrupt, then mark it as
+ * complete.
+ */
+static void nvic_ack_irq(struct irq_data *d)
+{
+	u32 mask = 1 << (d->irq % 32);
+
+	raw_spin_lock(&irq_controller_lock);
+	writel(mask, NVIC_CLEAR_ENABLE + d->irq / 32 * 4);
+	raw_spin_unlock(&irq_controller_lock);
+}
+
+static void nvic_mask_irq(struct irq_data *d)
+{
+	u32 mask = 1 << (d->irq % 32);
+
+	raw_spin_lock(&irq_controller_lock);
+	writel(mask, NVIC_CLEAR_ENABLE + d->irq / 32 * 4);
+	raw_spin_unlock(&irq_controller_lock);
+}
+
+static void nvic_unmask_irq(struct irq_data *d)
+{
+	u32 mask = 1 << (d->irq % 32);
+
+	raw_spin_lock(&irq_controller_lock);
+	writel(mask, NVIC_SET_ENABLE + d->irq / 32 * 4);
+	raw_spin_unlock(&irq_controller_lock);
+}
+
+static struct irq_chip nvic_chip = {
+	.name = "NVIC",
+	.irq_ack = nvic_ack_irq,
+	.irq_mask = nvic_mask_irq,
+	.irq_unmask = nvic_unmask_irq,
+};
+
+void __init nvic_init(void)
+{
+	unsigned int max_irq, i;
+
+	max_irq = ((readl(NVIC_INTR_CTRL) & 0x1f) + 1) * 32;
+
+	/*
+	 * Disable all interrupts
+	 */
+	for (i = 0; i < max_irq / 32; i++)
+		writel(~0, NVIC_CLEAR_ENABLE + i * 4);
+
+	/*
+	 * Set priority on all interrupts.
+	 */
+	for (i = 0; i < max_irq; i += 4)
+		writel(0, NVIC_PRIORITY + i);
+
+	/*
+	 * Setup the Linux IRQ subsystem.
+	 */
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_set_chip_and_handler(i, &nvic_chip, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+	}
+}
diff --git a/arch/arm/include/asm/hardware/nvic.h b/arch/arm/include/asm/hardware/nvic.h
new file mode 100644
index 0000000..b7f8026
--- /dev/null
+++ b/arch/arm/include/asm/hardware/nvic.h
@@ -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
-- 
1.7.8.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC PATCH 09/11] Cortex-M3: Allow the building of Cortex-M3 kernel port
  2012-01-22 11:12 [RFC PATCH 00/11] Cortex-M3 support Uwe Kleine-König
                   ` (7 preceding siblings ...)
  2012-01-22 11:13 ` [RFC PATCH 08/11] Cortex-M3: Add NVIC support Uwe Kleine-König
@ 2012-01-22 11:13 ` Uwe Kleine-König
  2012-01-22 20:05   ` Michał Mirosław
  2012-01-22 11:13 ` [RFC PATCH 10/11] Cortex-M3: Add VFP support Uwe Kleine-König
                   ` (2 subsequent siblings)
  11 siblings, 1 reply; 40+ messages in thread
From: Uwe Kleine-König @ 2012-01-22 11:13 UTC (permalink / raw)
  To: linux-arm-kernel

From: Catalin Marinas <catalin.marinas@arm.com>

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]

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
 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(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 24626b0..ca9b48c 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -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
diff --git a/arch/arm/Kconfig-nommu b/arch/arm/Kconfig-nommu
index 2cef8e1..c859495 100644
--- a/arch/arm/Kconfig-nommu
+++ b/arch/arm/Kconfig-nommu
@@ -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.
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 40319d9..e36b8b0 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -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
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 43b740d..32e96e6 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -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
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 4cefb57..0b57034 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -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
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index bca7e61..3f94178 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -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
-- 
1.7.8.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC PATCH 10/11] Cortex-M3: Add VFP support
  2012-01-22 11:12 [RFC PATCH 00/11] Cortex-M3 support Uwe Kleine-König
                   ` (8 preceding siblings ...)
  2012-01-22 11:13 ` [RFC PATCH 09/11] Cortex-M3: Allow the building of Cortex-M3 kernel port Uwe Kleine-König
@ 2012-01-22 11:13 ` Uwe Kleine-König
  2012-01-22 11:13 ` [RFC PATCH 11/11] HACK! ARM: no, we don't enter in ARM Uwe Kleine-König
  2012-02-07 20:18 ` [RFC PATCH 00/11] Cortex-M3 support Uwe Kleine-König
  11 siblings, 0 replies; 40+ messages in thread
From: Uwe Kleine-König @ 2012-01-22 11:13 UTC (permalink / raw)
  To: linux-arm-kernel

From: Catalin Marinas <catalin.marinas@arm.com>

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.

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
 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

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ca9b48c..c5caeee 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -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"
diff --git a/arch/arm/include/asm/fpstate.h b/arch/arm/include/asm/fpstate.h
index 3ad4c10..e18c3d9 100644
--- a/arch/arm/include/asm/fpstate.h
+++ b/arch/arm/include/asm/fpstate.h
@@ -43,6 +43,9 @@ struct vfp_hard_struct {
 #ifdef CONFIG_SMP
 	__u32 cpu;
 #endif
+#ifdef CONFIG_VFPM
+	__u32 clean;
+#endif
 };
 
 union vfp_state {
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 32e96e6..66d6c92 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -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
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index e861849..10ec416 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -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
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 8050d9b..cb38aff 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -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
diff --git a/arch/arm/kernel/vfp-m.c b/arch/arm/kernel/vfp-m.c
new file mode 100644
index 0000000..0528189
--- /dev/null
+++ b/arch/arm/kernel/vfp-m.c
@@ -0,0 +1,102 @@
+/*
+ * arch/arm/kernel/vfp-m.c
+ *
+ * Copyright (C) 2010 ARM Limited
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/thread_notify.h>
+
+static union vfp_state *last_vfp_context;
+
+static void save_vfp_context(union vfp_state *vfp)
+{
+	/* vstmia %0!, {d8-d15} */
+	asm("	stc	p11, cr8, [%0], #16*4\n" : : "r" (vfp) : "cc");
+}
+
+static void load_vfp_context(union vfp_state *vfp)
+{
+	/* vldmia %0!, {d8-d15} */
+	asm("	ldc	p11, cr8, [%0], #16*4\n" : : "r" (vfp) : "cc");
+}
+
+static int vfpm_notifier(struct notifier_block *self, unsigned long cmd,
+			 void *t)
+{
+	struct thread_info *thread = t;
+	union vfp_state *vfp = &thread->vfpstate;
+	union vfp_state *old_vfp = &current_thread_info()->vfpstate;
+	u32 *fpccr = (u32 *)0xe000ef34;
+
+	switch (cmd) {
+	case THREAD_NOTIFY_FLUSH:
+		memset(vfp, 0, sizeof(*vfp));
+		vfp->hard.clean = 1;
+		/* fall through */
+
+	case THREAD_NOTIFY_EXIT:
+		if (last_vfp_context == vfp) {
+			/* disable lazy state saving */
+			*fpccr &= ~1;
+			last_vfp_context = NULL;
+		}
+		break;
+
+	case THREAD_NOTIFY_SWITCH:
+		if (!old_vfp->hard.clean) {
+			save_vfp_context(last_vfp_context);
+			last_vfp_context = old_vfp;
+		}
+		if (!vfp->hard.clean && last_vfp_context != vfp) {
+			load_vfp_context(vfp);
+			last_vfp_context = vfp;
+		}
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block vfpm_notifier_block = {
+	.notifier_call	= vfpm_notifier,
+};
+
+static int __init vfpm_init(void)
+{
+	u32 *cpacr = (u32 *)0xe000ed88;
+	u32 *mvfr0 = (u32 *)0xe000ef40;
+	u32 *fpccr = (u32 *)0xe000ef34;
+
+	/* check for single-precision VFP operations */
+	if ((*mvfr0 & 0xf0) != 0x20)
+		return 0;
+
+	printk(KERN_INFO "ARMv7-M VFP Extension supported\n");
+
+	*cpacr |= 0xf << 20;		/* coprocessor access */
+	*fpccr |= 3 << 30;		/* automatic lazy state preservation */
+
+	elf_hwcap |= HWCAP_VFP;
+	thread_register_notifier(&vfpm_notifier_block);
+
+	return 0;
+}
+
+late_initcall(vfpm_init);
-- 
1.7.8.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC PATCH 11/11] HACK! ARM: no, we don't enter in ARM
  2012-01-22 11:12 [RFC PATCH 00/11] Cortex-M3 support Uwe Kleine-König
                   ` (9 preceding siblings ...)
  2012-01-22 11:13 ` [RFC PATCH 10/11] Cortex-M3: Add VFP support Uwe Kleine-König
@ 2012-01-22 11:13 ` Uwe Kleine-König
  2012-02-07 20:18 ` [RFC PATCH 00/11] Cortex-M3 support Uwe Kleine-König
  11 siblings, 0 replies; 40+ messages in thread
From: Uwe Kleine-König @ 2012-01-22 11:13 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
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(-)

diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index dba31af..bb94ce4 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -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:			)
 
-- 
1.7.8.3

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [RFC PATCH 06/11] Cortex-M3: Add base support for Cortex-M3
  2012-01-22 11:13 ` [RFC PATCH 06/11] Cortex-M3: Add base support for Cortex-M3 Uwe Kleine-König
@ 2012-01-22 19:45   ` Michał Mirosław
  2012-01-22 20:42     ` Uwe Kleine-König
  0 siblings, 1 reply; 40+ messages in thread
From: Michał Mirosław @ 2012-01-22 19:45 UTC (permalink / raw)
  To: linux-arm-kernel

2012/1/22 Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>:
> --- a/arch/arm/kernel/head-common.S
> +++ b/arch/arm/kernel/head-common.S
> @@ -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

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [RFC PATCH 09/11] Cortex-M3: Allow the building of Cortex-M3 kernel port
  2012-01-22 11:13 ` [RFC PATCH 09/11] Cortex-M3: Allow the building of Cortex-M3 kernel port Uwe Kleine-König
@ 2012-01-22 20:05   ` Michał Mirosław
  2012-02-07 19:43     ` Uwe Kleine-König
  0 siblings, 1 reply; 40+ messages in thread
From: Michał Mirosław @ 2012-01-22 20:05 UTC (permalink / raw)
  To: linux-arm-kernel

2012/1/22 Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>:
[...]
> --- a/arch/arm/kernel/Makefile
> +++ b/arch/arm/kernel/Makefile
> @@ -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
> +

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

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [RFC PATCH 06/11] Cortex-M3: Add base support for Cortex-M3
  2012-01-22 19:45   ` Michał Mirosław
@ 2012-01-22 20:42     ` Uwe Kleine-König
  0 siblings, 0 replies; 40+ messages in thread
From: Uwe Kleine-König @ 2012-01-22 20:42 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Micha?,

On Sun, Jan 22, 2012 at 08:45:24PM +0100, Micha? Miros?aw wrote:
> 2012/1/22 Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>:
> > --- a/arch/arm/kernel/head-common.S
> > +++ b/arch/arm/kernel/head-common.S
> > @@ -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

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [RFC PATCH 03/11] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15
  2012-01-22 11:13 ` [RFC PATCH 03/11] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15 Uwe Kleine-König
@ 2012-01-23  5:43   ` Jean-Christophe PLAGNIOL-VILLARD
  2012-01-23  8:14     ` Uwe Kleine-König
  0 siblings, 1 reply; 40+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-01-23  5:43 UTC (permalink / raw)
  To: linux-arm-kernel

On 12:13 Sun 22 Jan     , Uwe Kleine-K?nig wrote:
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
> ---
>  arch/arm/include/asm/system.h |    2 ++
>  arch/arm/kernel/entry-armv.S  |    4 ++++
>  arch/arm/kernel/head-common.S |    9 +++++++--
>  arch/arm/kernel/setup.c       |    8 ++++++--
>  arch/arm/mm/alignment.c       |    6 ++++++
>  arch/arm/mm/mmu.c             |    8 +++++++-
>  6 files changed, 32 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
> index e4c96cc..de46477 100644
> --- a/arch/arm/include/asm/system.h
> +++ b/arch/arm/include/asm/system.h
> @@ -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,
> diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
> index 3a456c6..15bfeff 100644
> --- a/arch/arm/kernel/entry-armv.S
> +++ b/arch/arm/kernel/entry-armv.S
> @@ -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
> diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
> index 854bd22..2f560c5 100644
> --- a/arch/arm/kernel/head-common.S
> +++ b/arch/arm/kernel/head-common.S
> @@ -98,8 +98,9 @@ __mmap_switched:
>  	str	r9, [r4]			@ Save processor ID
>  	str	r1, [r5]			@ Save machine type
>  	str	r2, [r6]			@ Save atags pointer
> -	bic	r4, r0, #CR_A			@ Clear 'A' bit
> -	stmia	r7, {r0, r4}			@ Save control register values
> +	cmp	r7, #0
> +	bicne	r4, r0, #CR_A			@ Clear 'A' bit
> +	stmneia	r7, {r0, r4}			@ Save control register values
>  	b	start_kernel
>  ENDPROC(__mmap_switched)
>  
> @@ -113,7 +114,11 @@ __mmap_switched_data:
>  	.long	processor_id			@ r4
>  	.long	__machine_arch_type		@ r5
>  	.long	__atags_pointer			@ r6
> +#ifdef CONFIG_CPU_CP15
>  	.long	cr_alignment			@ r7
> +#else
> +	.long	0
> +#endif
>  	.long	init_thread_union + THREAD_START_SP @ sp
>  	.size	__mmap_switched_data, . - __mmap_switched_data
>  
> diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
> index 129fbd5..3849737 100644
> --- a/arch/arm/kernel/setup.c
> +++ b/arch/arm/kernel/setup.c
> @@ -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);
> diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
> index caf14dc..119d178 100644
> --- a/arch/arm/mm/alignment.c
> +++ b/arch/arm/mm/alignment.c
> @@ -89,7 +89,11 @@ core_param(alignment, ai_usermode, int, 0600);
>  /* Return true if and only if the ARMv6 unaligned access model is in use. */
>  static bool cpu_is_v6_unaligned(void)
>  {
> +#ifdef CONFIG_CPU_CP15
>  	return cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U);
> +#else
> +	return 0;
> +#endif
>  }
>  
>  static int safe_usermode(int new_usermode, bool warn)
> @@ -961,12 +965,14 @@ static int __init alignment_init(void)
>  		return -ENOMEM;
>  #endif
>  
> +#ifdef CONFIG_CPU_CP15
>  	if (cpu_is_v6_unaligned()) {
>  		cr_alignment &= ~CR_A;
>  		cr_no_alignment &= ~CR_A;
>  		set_cr(cr_alignment);
>  		ai_usermode = safe_usermode(ai_usermode, false);
>  	}
> +#endif
why if CPU_CP15 is not supported cpu_is_v6_unaligned return 0
>  
>  	hook_fault_code(FAULT_CODE_ALIGNMENT, do_alignment, SIGBUS, BUS_ADRALN,
>  			"alignment exception");
> diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
> index 94c5a0c..f6dbe1a 100644
> --- a/arch/arm/mm/mmu.c
> +++ b/arch/arm/mm/mmu.c
> @@ -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.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [RFC PATCH 04/11] ARM: Add a printk loglevel modifier
  2012-01-22 11:13 ` [RFC PATCH 04/11] ARM: Add a printk loglevel modifier Uwe Kleine-König
@ 2012-01-23  5:50   ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 0 replies; 40+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-01-23  5:50 UTC (permalink / raw)
  To: linux-arm-kernel

On 12:13 Sun 22 Jan     , Uwe Kleine-K?nig wrote:
> 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
> 
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
> ---
> 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(-)
> 
> diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
> index 3849737..f7c0d55 100644
> --- a/arch/arm/kernel/setup.c
> +++ b/arch/arm/kernel/setup.c
> @@ -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.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [RFC PATCH 03/11] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15
  2012-01-23  5:43   ` Jean-Christophe PLAGNIOL-VILLARD
@ 2012-01-23  8:14     ` Uwe Kleine-König
  0 siblings, 0 replies; 40+ messages in thread
From: Uwe Kleine-König @ 2012-01-23  8:14 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jean-Christophe,

On Mon, Jan 23, 2012 at 06:43:46AM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 12:13 Sun 22 Jan     , Uwe Kleine-K?nig wrote:
> > diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
> > index caf14dc..119d178 100644
> > --- a/arch/arm/mm/alignment.c
> > +++ b/arch/arm/mm/alignment.c
> > @@ -89,7 +89,11 @@ core_param(alignment, ai_usermode, int, 0600);
> >  /* Return true if and only if the ARMv6 unaligned access model is in use. */
> >  static bool cpu_is_v6_unaligned(void)
> >  {
> > +#ifdef CONFIG_CPU_CP15
> >  	return cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U);
> > +#else
> > +	return 0;
> > +#endif
> >  }
> >  
> >  static int safe_usermode(int new_usermode, bool warn)
> > @@ -961,12 +965,14 @@ static int __init alignment_init(void)
> >  		return -ENOMEM;
> >  #endif
> >  
> > +#ifdef CONFIG_CPU_CP15
> >  	if (cpu_is_v6_unaligned()) {
> >  		cr_alignment &= ~CR_A;
> >  		cr_no_alignment &= ~CR_A;
> >  		set_cr(cr_alignment);
> >  		ai_usermode = safe_usermode(ai_usermode, false);
> >  	}
> > +#endif
> 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?

> >  	hook_fault_code(FAULT_CODE_ALIGNMENT, do_alignment, SIGBUS, BUS_ADRALN,
> >  			"alignment exception");
> > diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
> > index 94c5a0c..f6dbe1a 100644
> > --- a/arch/arm/mm/mmu.c
> > +++ b/arch/arm/mm/mmu.c
> > @@ -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
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

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [RFC PATCH 01/11] ARM: only show modules in the memory layout for MODULES=y
  2012-01-22 11:13 ` [RFC PATCH 01/11] ARM: only show modules in the memory layout for MODULES=y Uwe Kleine-König
@ 2012-01-26  6:16   ` Linus Walleij
  0 siblings, 0 replies; 40+ messages in thread
From: Linus Walleij @ 2012-01-26  6:16 UTC (permalink / raw)
  To: linux-arm-kernel

2012/1/22 Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>:

> This line is irritating and wrong when modules are not supported, so
> don't show it then.
>
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
> Acked-by: Nicolas Pitre <nico@linaro.org>

Pretty straight-forward....
Acked-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [RFC PATCH 08/11] Cortex-M3: Add NVIC support
  2012-01-22 11:13 ` [RFC PATCH 08/11] Cortex-M3: Add NVIC support Uwe Kleine-König
@ 2012-01-31 19:39   ` Uwe Kleine-König
  0 siblings, 0 replies; 40+ messages in thread
From: Uwe Kleine-König @ 2012-01-31 19:39 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

On Sun, Jan 22, 2012 at 12:13:34PM +0100, Uwe Kleine-K?nig wrote:
> From: Catalin Marinas <catalin.marinas@arm.com>
> 
> This patch implements the NVIC (interrupt controller) support for
> Cortex-M3.
> 
> [ukleinek: use a raw spinlock]
> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
> ---
> 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

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [RFC PATCH 09/11] Cortex-M3: Allow the building of Cortex-M3 kernel port
  2012-01-22 20:05   ` Michał Mirosław
@ 2012-02-07 19:43     ` Uwe Kleine-König
  0 siblings, 0 replies; 40+ messages in thread
From: Uwe Kleine-König @ 2012-02-07 19:43 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Jan 22, 2012 at 09:05:44PM +0100, Micha? Miros?aw wrote:
> 2012/1/22 Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>:
> [...]
> > --- a/arch/arm/kernel/Makefile
> > +++ b/arch/arm/kernel/Makefile
> > @@ -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
> > +
> 
> Maybe something shorter, like this? '-)
> 
> 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

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [RFC PATCH 00/11] Cortex-M3 support
  2012-01-22 11:12 [RFC PATCH 00/11] Cortex-M3 support Uwe Kleine-König
                   ` (10 preceding siblings ...)
  2012-01-22 11:13 ` [RFC PATCH 11/11] HACK! ARM: no, we don't enter in ARM Uwe Kleine-König
@ 2012-02-07 20:18 ` Uwe Kleine-König
  2012-02-16 20:01   ` Uwe Kleine-König
  11 siblings, 1 reply; 40+ messages in thread
From: Uwe Kleine-König @ 2012-02-07 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Jan 22, 2012 at 12:12:30PM +0100, Uwe Kleine-K?nig wrote:
> 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.
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

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [RFC PATCH 00/11] Cortex-M3 support
  2012-02-07 20:18 ` [RFC PATCH 00/11] Cortex-M3 support Uwe Kleine-König
@ 2012-02-16 20:01   ` Uwe Kleine-König
  2012-02-16 20:18     ` [PATCH 1/5] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15 Uwe Kleine-König
  0 siblings, 1 reply; 40+ messages in thread
From: Uwe Kleine-König @ 2012-02-16 20:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 07, 2012 at 09:18:10PM +0100, Uwe Kleine-K?nig wrote:
> On Sun, Jan 22, 2012 at 12:12:30PM +0100, Uwe Kleine-K?nig wrote:
> > 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.
> 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.
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

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH 1/5] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15
  2012-02-16 20:01   ` Uwe Kleine-König
@ 2012-02-16 20:18     ` Uwe Kleine-König
  2012-02-16 20:18       ` [PATCH 2/5] ARM: Add a printk loglevel modifier Uwe Kleine-König
                         ` (4 more replies)
  0 siblings, 5 replies; 40+ messages in thread
From: Uwe Kleine-König @ 2012-02-16 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
 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(-)

diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index e4c96cc..de46477 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -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,
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index be16a48..a6f2ef5 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -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
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index 854bd22..5ca01bb 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -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
 
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index a255c39..50d3df8 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -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);
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index caf14dc..119d178 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -89,7 +89,11 @@ core_param(alignment, ai_usermode, int, 0600);
 /* Return true if and only if the ARMv6 unaligned access model is in use. */
 static bool cpu_is_v6_unaligned(void)
 {
+#ifdef CONFIG_CPU_CP15
 	return cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U);
+#else
+	return 0;
+#endif
 }
 
 static int safe_usermode(int new_usermode, bool warn)
@@ -961,12 +965,14 @@ static int __init alignment_init(void)
 		return -ENOMEM;
 #endif
 
+#ifdef CONFIG_CPU_CP15
 	if (cpu_is_v6_unaligned()) {
 		cr_alignment &= ~CR_A;
 		cr_no_alignment &= ~CR_A;
 		set_cr(cr_alignment);
 		ai_usermode = safe_usermode(ai_usermode, false);
 	}
+#endif
 
 	hook_fault_code(FAULT_CODE_ALIGNMENT, do_alignment, SIGBUS, BUS_ADRALN,
 			"alignment exception");
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 94c5a0c..f6dbe1a 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -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;
-- 
1.7.9

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 2/5] ARM: Add a printk loglevel modifier
  2012-02-16 20:18     ` [PATCH 1/5] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15 Uwe Kleine-König
@ 2012-02-16 20:18       ` Uwe Kleine-König
  2012-02-16 20:18       ` [PATCH 3/5] ARM: force branch instructions to use long distance encoding Uwe Kleine-König
                         ` (3 subsequent siblings)
  4 siblings, 0 replies; 40+ messages in thread
From: Uwe Kleine-König @ 2012-02-16 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
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(-)

diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 50d3df8..23893b1 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -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",
-- 
1.7.9

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 3/5] ARM: force branch instructions to use long distance encoding
  2012-02-16 20:18     ` [PATCH 1/5] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15 Uwe Kleine-König
  2012-02-16 20:18       ` [PATCH 2/5] ARM: Add a printk loglevel modifier Uwe Kleine-König
@ 2012-02-16 20:18       ` Uwe Kleine-König
  2012-02-16 20:18       ` [PATCH 4/5] ARM: Cortex-M3: Add base support for Cortex-M3 Uwe Kleine-König
                         ` (2 subsequent siblings)
  4 siblings, 0 replies; 40+ messages in thread
From: Uwe Kleine-König @ 2012-02-16 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
 arch/arm/kernel/head-nommu.S |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index d46f259..1aca35d 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -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
-- 
1.7.9

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 4/5] ARM: Cortex-M3: Add base support for Cortex-M3
  2012-02-16 20:18     ` [PATCH 1/5] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15 Uwe Kleine-König
  2012-02-16 20:18       ` [PATCH 2/5] ARM: Add a printk loglevel modifier Uwe Kleine-König
  2012-02-16 20:18       ` [PATCH 3/5] ARM: force branch instructions to use long distance encoding Uwe Kleine-König
@ 2012-02-16 20:18       ` Uwe Kleine-König
  2012-02-16 20:18       ` [PATCH 5/5] ARM: Cortex-M3: Add support for exception handling Uwe Kleine-König
  2012-02-17  0:28       ` [PATCH 1/5] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15 Ryan Mallon
  4 siblings, 0 replies; 40+ messages in thread
From: Uwe Kleine-König @ 2012-02-16 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

From: Catalin Marinas <catalin.marinas@arm.com>

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]

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
 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

diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 62f8095..1bafa39 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -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
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index cb47d28..5bd8cb6 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -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
diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h
index 7e30874..6a5fd0b 100644
--- a/arch/arm/include/asm/glue-cache.h
+++ b/arch/arm/include/asm/glue-cache.h
@@ -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)
diff --git a/arch/arm/include/asm/glue-df.h b/arch/arm/include/asm/glue-df.h
index 354d571..26be71c 100644
--- a/arch/arm/include/asm/glue-df.h
+++ b/arch/arm/include/asm/glue-df.h
@@ -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
diff --git a/arch/arm/include/asm/glue-proc.h b/arch/arm/include/asm/glue-proc.h
index e2be7f1..8f9991b 100644
--- a/arch/arm/include/asm/glue-proc.h
+++ b/arch/arm/include/asm/glue-proc.h
@@ -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)
diff --git a/arch/arm/include/asm/irqflags.h b/arch/arm/include/asm/irqflags.h
index 1e6cca5..ac4d548 100644
--- a/arch/arm/include/asm/irqflags.h
+++ b/arch/arm/include/asm/irqflags.h
@@ -10,6 +10,18 @@
  */
 #if __LINUX_ARM_ARCH__ >= 6
 
+#ifdef CONFIG_CPU_V7M
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags;
+
+	asm volatile(
+		"	mrs	%0, primask	@ arch_local_irq_save\n"
+		"	cpsid	i"
+		: "=r" (flags) : : "memory", "cc");
+	return flags;
+}
+#else
 static inline unsigned long arch_local_irq_save(void)
 {
 	unsigned long flags;
@@ -20,6 +32,7 @@ static inline unsigned long arch_local_irq_save(void)
 		: "=r" (flags) : : "memory", "cc");
 	return flags;
 }
+#endif
 
 static inline void arch_local_irq_enable(void)
 {
@@ -122,6 +135,38 @@ static inline void arch_local_irq_disable(void)
 
 #endif
 
+#ifdef CONFIG_CPU_V7M
+/*
+ * Save the current interrupt enable state.
+ */
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long flags;
+	asm volatile(
+		"	mrs	%0, primask	@ local_save_flags"
+		: "=r" (flags) : : "memory", "cc");
+	return flags;
+}
+
+/*
+ * restore saved IRQ & FIQ state
+ */
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	asm volatile(
+		"	msr	primask, %0	@ local_irq_restore"
+		:
+		: "r" (flags)
+		: "memory", "cc");
+}
+
+static inline int arch_irqs_disabled_flags(unsigned long flags)
+{
+	return flags & 1;
+}
+
+#else /* ifdef CONFIG_CPU_V7M */
+
 /*
  * Save the current interrupt enable state.
  */
@@ -151,5 +196,7 @@ static inline int arch_irqs_disabled_flags(unsigned long flags)
 	return flags & PSR_I_BIT;
 }
 
-#endif
-#endif
+#endif /* ifdef CONFIG_CPU_V7M / else */
+
+#endif /* ifdef __KERNEL__ */
+#endif /* ifndef __ASM_ARM_IRQFLAGS_H */
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index ce280b8..aa4c8a2 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -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)					\
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 451808b..1feb9a0 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -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
@@ -106,10 +115,37 @@ struct pt_regs {
 };
 #else /* __KERNEL__ */
 struct pt_regs {
+#ifdef CONFIG_CPU_V7M
+	unsigned long uregs[20];
+#else
 	unsigned long uregs[18];
+#endif
 };
 #endif /* __KERNEL__ */
 
+#ifdef CONFIG_CPU_V7M
+/* Automatically saved registers */
+#define ARM_cpsr	uregs[17]
+#define ARM_pc		uregs[16]
+#define ARM_lr		uregs[15]
+#define ARM_ip		uregs[14]
+#define ARM_r3		uregs[13]
+#define ARM_r2		uregs[12]
+#define ARM_r1		uregs[11]
+#define ARM_r0		uregs[10]
+/* saved by the exception entry code */
+#define ARM_EXC_lr	uregs[9]
+#define ARM_sp		uregs[8]
+#define ARM_fp		uregs[7]
+#define ARM_r10		uregs[6]
+#define ARM_r9		uregs[5]
+#define ARM_r8		uregs[4]
+#define ARM_r7		uregs[3]
+#define ARM_r6		uregs[2]
+#define ARM_r5		uregs[1]
+#define ARM_r4		uregs[0]
+#define ARM_ORIG_r0	uregs[18]
+#else
 #define ARM_cpsr	uregs[16]
 #define ARM_pc		uregs[15]
 #define ARM_lr		uregs[14]
@@ -128,6 +164,7 @@ struct pt_regs {
 #define ARM_r1		uregs[1]
 #define ARM_r0		uregs[0]
 #define ARM_ORIG_r0	uregs[17]
+#endif
 
 /*
  * The size of the user-visible VFP state as seen by PTRACE_GET/SETVFPREGS
@@ -165,6 +202,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 +225,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)
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index de46477..16117ed 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -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'
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 1429d89..e861849 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -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
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index 5ca01bb..efeb2d0 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -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
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 1aca35d..61ba029 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -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)?
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 23893b1..d0fc5b8 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -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];
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 99a5727..8956d08 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -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
 }
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
index 4fc6794..fdd49ac 100644
--- a/arch/arm/mm/nommu.c
+++ b/arch/arm/mm/nommu.c
@@ -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)
diff --git a/arch/arm/mm/proc-v7m.S b/arch/arm/mm/proc-v7m.S
new file mode 100644
index 0000000..a17653a
--- /dev/null
+++ b/arch/arm/mm/proc-v7m.S
@@ -0,0 +1,178 @@
+/*
+ *  linux/arch/arm/mm/proc-v7m.S
+ *
+ *  Copyright (C) 2008 ARM Ltd.
+ *  Copyright (C) 2001 Deep Blue Solutions Ltd.
+ *
+ * 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.
+ *
+ *  This is the "shell" of the ARMv7-M processor support.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+ENTRY(cpu_v7m_proc_init)
+	mov	pc, lr
+ENDPROC(cpu_v7m_proc_init)
+
+ENTRY(cpu_v7m_proc_fin)
+	mov	pc, lr
+ENDPROC(cpu_v7m_proc_fin)
+
+/*
+ *	cpu_v7m_reset(loc)
+ *
+ *	Perform a soft reset of the system.  Put the CPU into the
+ *	same state as it would be if it had been reset, and branch
+ *	to what would be the reset vector.
+ *
+ *	- loc   - location to jump to for soft reset
+ */
+	.align	5
+ENTRY(cpu_v7m_reset)
+	mov	pc, r0
+ENDPROC(cpu_v7m_reset)
+
+/*
+ *	cpu_v7m_do_idle()
+ *
+ *	Idle the processor (eg, wait for interrupt).
+ *
+ *	IRQs are already disabled.
+ */
+ENTRY(cpu_v7m_do_idle)
+	wfi
+	mov	pc, lr
+ENDPROC(cpu_v7m_do_idle)
+
+ENTRY(cpu_v7m_dcache_clean_area)
+	mov	pc, lr
+ENDPROC(cpu_v7m_dcache_clean_area)
+
+/*
+ *	cpu_v7m_switch_mm(pgd_phys, tsk)
+ *
+ *	Set the translation table base pointer to be pgd_phys
+ *
+ *	- pgd_phys - physical address of new TTB
+ *
+ *	It is assumed that:
+ *	- we are not using split page tables
+ */
+ENTRY(cpu_v7m_switch_mm)
+	mov	pc, lr
+ENDPROC(cpu_v7m_switch_mm)
+
+cpu_v7m_name:
+	.ascii	"ARMv7-M Processor"
+	.align
+
+	.section ".text.init", #alloc, #execinstr
+
+/*
+ *	__v7m_setup
+ *
+ *	Initialise TLB, Caches, and MMU state ready to switch the MMU
+ *	on.  Return in r0 the new CP15 C1 control register setting.
+ *
+ *	We automatically detect if we have a Harvard cache, and use the
+ *	Harvard cache control instructions insead of the unified cache
+ *	control instructions.
+ *
+ *	This should be able to cover all ARMv7-M cores.
+ *
+ *	It is assumed that:
+ *	- cache type register is implemented
+ */
+__v7m_setup:
+	@ Configure the vector table base address
+	ldr	r0, =0xe000ed08		@ vector table base address
+	ldr	r12, =vector_table
+	str	r12, [r0]
+
+	@ Lower the priority of the SVC and PendSV exceptions
+	ldr	r0, =0xe000ed1c
+	mov	r5, #0x80000000
+	str	r5, [r0]		@ set SVC priority
+	ldr	r0, =0xe000ed20
+	mov	r5, #0x00800000
+	str	r5, [r0]		@ set PendSV priority
+
+	@ SVC to run the kernel in this mode
+	adr	r0, BSYM(1f)
+	ldr	r5, [r12, #11 * 4]	@ read the SVC vector entry
+	str	r0, [r12, #11 * 4]	@ write the temporary SVC vector entry
+	mov	r6, lr			@ save LR
+	mov	r7, sp			@ save SP
+	ldr	sp, =__v7m_setup_stack_top
+	cpsie	i
+	svc	#0
+1:	cpsid	i
+	str	r5, [r12, #11 * 4]	@ restore the original SVC vector entry
+	mov	lr, r6			@ restore LR
+	mov	sp, r7			@ restore SP
+
+	@ Special-purpose control register
+	mov	r0, #1
+	msr	control, r0		@ Thread mode has unpriviledged access
+
+	@ Configure the System Control Register
+	ldr	r0, =0xe000ed14		@ system control register
+	ldr	r12, [r0]
+	orr	r12, #1 << 9		@ STKALIGN
+	str	r12, [r0]
+	mov	pc, lr
+ENDPROC(__v7m_setup)
+
+	.align	2
+	.type	v7m_processor_functions, #object
+ENTRY(v7m_processor_functions)
+	.word	nommu_early_abort
+	.word	cpu_v7m_proc_init
+	.word	cpu_v7m_proc_fin
+	.word	cpu_v7m_reset
+	.word	cpu_v7m_do_idle
+	.word	cpu_v7m_dcache_clean_area
+	.word	cpu_v7m_switch_mm
+	.word	0			@ cpu_v7m_set_pte_ext
+	.word	legacy_pabort
+	.size	v7m_processor_functions, . - v7m_processor_functions
+
+	.type	cpu_arch_name, #object
+cpu_arch_name:
+	.asciz	"armv7m"
+	.size	cpu_arch_name, . - cpu_arch_name
+
+	.type	cpu_elf_name, #object
+cpu_elf_name:
+	.asciz	"v7m"
+	.size	cpu_elf_name, . - cpu_elf_name
+	.align
+
+	.section ".proc.info.init", #alloc, #execinstr
+
+	/*
+	 * Match any ARMv7-M processor core.
+	 */
+	.type	__v7m_proc_info, #object
+__v7m_proc_info:
+	.long	0x000f0000		@ Required ID value
+	.long	0x000f0000		@ Mask for ID
+	.long   0			@ proc_info_list.__cpu_mm_mmu_flags
+	.long   0			@ proc_info_list.__cpu_io_mmu_flags
+	b	__v7m_setup		@ proc_info_list.__cpu_flush
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+	.long	cpu_v7m_name
+	.long	v7m_processor_functions	@ proc_info_list.proc
+	.long	0			@ proc_info_list.tlb
+	.long	0			@ proc_info_list.user
+	.long	0			@ proc_info_list.cache
+	.size	__v7m_proc_info, . - __v7m_proc_info
+
+__v7m_setup_stack:
+	.space	4 * 8				@ 8 registers
+__v7m_setup_stack_top:
-- 
1.7.9

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 5/5] ARM: Cortex-M3: Add support for exception handling
  2012-02-16 20:18     ` [PATCH 1/5] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15 Uwe Kleine-König
                         ` (2 preceding siblings ...)
  2012-02-16 20:18       ` [PATCH 4/5] ARM: Cortex-M3: Add base support for Cortex-M3 Uwe Kleine-König
@ 2012-02-16 20:18       ` Uwe Kleine-König
  2012-02-16 22:20         ` Russell King - ARM Linux
  2012-02-17  0:28       ` [PATCH 1/5] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15 Ryan Mallon
  4 siblings, 1 reply; 40+ messages in thread
From: Uwe Kleine-König @ 2012-02-16 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

From: Catalin Marinas <catalin.marinas@arm.com>

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]

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
 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

diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 9fd0ba9..4a12bc3 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -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]
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 9a8531e..80055b4 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -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)
 #error "Please fix"
 #endif
 
@@ -44,6 +44,89 @@
 #endif
 	.endm
 
+#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). The order of struct
+ * pt_regs members was changed to take advantage of the automatic
+ * state saving.
+ *
+ * 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.
+ *
+ * The v7m_exception_entry macro preserves the original r0-r5, r7 for
+ * the system call arguments.
+ *
+ * v7_exception_fast_exit is used when returning from interrupts.
+ *
+ * v7_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
+	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
+2:
+	.endm
+
+	.macro	v7m_exception_fast_exit
+	ldmia	sp!, {r4-r12, lr}	@ restore previously saved state
+	tst     lr, #0x8		@ check the return stack
+	addne	sp, #S_FRAME_SIZE-S_R0	@ returning to PSP, just restore MSP
+	cpsie	i
+	bx	lr
+	.endm
+
+	.macro	v7m_exception_slow_exit ret_r0
+	cpsid	i
+	ldr	lr, [sp, #S_EXC_LR]	@ read exception LR
+	tst	lr, #0x8
+	bne	1f			@ returning to PSP
+	@ Prepare the MSP stack
+	ldmia	sp, {r4-r11}		@ restore previously saved state
+	ldr	lr, [sp, #S_PC]
+	add	sp, #S_R0
+	ldmia	sp, {r0-r3, r12}	@ restore the rest of registers
+	add	sp, #S_FRAME_SIZE-S_R0	@ restore the stack pointer
+	cpsie	i
+	bx	lr
+1:
+	@ Prepare the PSP stack
+	ldr	r12, [sp, #S_SP]	@ read original PSP
+	.if	\ret_r0
+	add	r11, sp, #S_R1
+	ldmia	r11, {r1-r7}		@ read state saved on MSP (r0 preserved)
+	.else
+	add	r11, sp, #S_R0
+	ldmia	r11, {r0-r7}		@ read state saved on MSP
+	.endif
+	msr	psp, r12		@ restore PSP
+	stmia	r12, {r0-r7}		@ restore saved state to PSP
+	ldmia	sp, {r4-r11}		@ restore previously saved state
+	add	sp, #S_FRAME_SIZE	@ restore the original MSP
+	cpsie	i
+	bx	lr
+	.endm
+#endif	/* CONFIG_CPU_V7M */
+
 	@
 	@ Store/load the USER SP and LR registers by switching to the SYS
 	@ mode. Useful in Thumb-2 mode where "stm/ldm rd, {sp, lr}^" is not
@@ -131,6 +214,14 @@
 	rfeia	sp!
 	.endm
 
+#ifdef CONFIG_CPU_V7M
+	.macro	restore_user_regs, fast = 0, offset = 0
+	.if	\offset
+	add	sp, #\offset
+	.endif
+	v7m_exception_slow_exit ret_r0 = \fast
+	.endm
+#else	/* !CONFIG_CPU_V7M */
 	.macro	restore_user_regs, fast = 0, offset = 0
 	clrex					@ clear the exclusive monitor
 	mov	r2, sp
@@ -147,6 +238,7 @@
 	add	sp, sp, #S_FRAME_SIZE - S_SP
 	movs	pc, lr				@ return & move spsr_svc into cpsr
 	.endm
+#endif	/* CONFIG_CPU_V7M */
 
 	.macro	get_thread_info, rd
 	mov	\rd, sp
diff --git a/arch/arm/kernel/entry-v7m.S b/arch/arm/kernel/entry-v7m.S
new file mode 100644
index 0000000..74a1b7e
--- /dev/null
+++ b/arch/arm/kernel/entry-v7m.S
@@ -0,0 +1,131 @@
+/*
+ * linux/arch/arm/kernel/entry-v7m.S
+ *
+ * Copyright (C) 2008 ARM Ltd.
+ *
+ * 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.
+ *
+ * Low-level vector interface routines for the ARMv7-M architecture
+ */
+#include <asm/memory.h>
+#include <asm/glue.h>
+#include <asm/thread_notify.h>
+
+#include <mach/entry-macro.S>
+
+#include "entry-header.S"
+
+#ifdef CONFIG_PREEMPT
+#error "CONFIG_PREEMPT not supported on the current ARMv7M implementation"
+#endif
+#ifdef CONFIG_TRACE_IRQFLAGS
+#error "CONFIG_TRACE_IRQFLAGS not supported on the current ARMv7M implementation"
+#endif
+
+__invalid_entry:
+	v7m_exception_entry
+	adr	r0, strerr
+	mrs	r1, ipsr
+	mov	r2, lr
+	bl	printk
+	mov	r0, sp
+	bl	show_regs
+1:	b	1b
+ENDPROC(__invalid_entry)
+
+strerr:	.asciz	"\nUnhandled exception: IPSR = %08lx LR = %08lx\n"
+
+	.align	2
+__irq_entry:
+	v7m_exception_entry
+
+	@
+	@ Invoke the IRQ handler
+	@
+	mrs	r0, ipsr
+	and	r0, #0xff
+	sub	r0, #16			@ IRQ number
+	mov	r1, sp
+	@ routine called with r0 = irq number, r1 = struct pt_regs *
+	bl	asm_do_IRQ
+
+	@
+	@ Check for any pending work if returning to user
+	@
+	ldr	lr, [sp, #S_EXC_LR]
+	tst	lr, #0x8		@ check the return stack
+	beq	2f			@ returning to kernel
+	get_thread_info tsk
+	ldr	r1, [tsk, #TI_FLAGS]
+	tst	r1, #_TIF_WORK_MASK
+	beq	2f			@ no work pending
+	ldr	r1, =0xe000ed04		@ ICSR
+	mov	r0, #1 << 28		@ ICSR.PENDSVSET
+	str	r0, [r1]		@ raise PendSV
+
+2:
+	v7m_exception_fast_exit
+ENDPROC(__irq_entry)
+
+__pendsv_entry:
+	v7m_exception_entry
+
+	ldr	r1, =0xe000ed04		@ ICSR
+	mov	r0, #1 << 27		@ ICSR.PENDSVCLR
+	str	r0, [r1]		@ clear PendSV
+
+	@ execute the pending work, including reschedule
+	get_thread_info tsk
+	mov	why, #0
+	b	ret_to_user
+ENDPROC(__pendsv_entry)
+
+/*
+ * Register switch for ARMv7-M processors.
+ * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info
+ * previous and next are guaranteed not to be the same.
+ */
+ENTRY(__switch_to)
+	add	ip, r1, #TI_CPU_SAVE
+	stmia	ip!, {r4 - sl, fp}	@ Store most regs on stack
+	str	sp, [ip], #4
+	str	lr, [ip], #4
+	mov	r5, r0
+	add	r4, r2, #TI_CPU_SAVE
+	ldr	r0, =thread_notify_head
+	mov	r1, #THREAD_NOTIFY_SWITCH
+	bl	atomic_notifier_call_chain
+	mov	ip, r4
+	mov	r0, r5
+	ldmia	ip!, {r4 - sl, fp}	@ Load all regs saved previously
+	ldr	sp, [ip], #4
+	ldr	pc, [ip]
+ENDPROC(__switch_to)
+
+	.data
+	.align	8
+/*
+ * Vector table (64 words => 256 bytes natural alignment)
+ */
+ENTRY(vector_table)
+	.long	0			@ 0 - Reset stack pointer
+	.long	__invalid_entry		@ 1 - Reset
+	.long	__invalid_entry		@ 2 - NMI
+	.long	__invalid_entry		@ 3 - HardFault
+	.long	__invalid_entry		@ 4 - MemManage
+	.long	__invalid_entry		@ 5 - BusFault
+	.long	__invalid_entry		@ 6 - UsageFault
+	.long	__invalid_entry		@ 7 - Reserved
+	.long	__invalid_entry		@ 8 - Reserved
+	.long	__invalid_entry		@ 9 - Reserved
+	.long	__invalid_entry		@ 10 - Reserved
+	.long	vector_swi		@ 11 - SVCall
+	.long	__invalid_entry		@ 12 - Debug Monitor
+	.long	__invalid_entry		@ 13 - Reserved
+	.long	__pendsv_entry		@ 14 - PendSV
+	.long	__invalid_entry		@ 15 - SysTick
+	.rept	64 - 16
+	.long	__irq_entry		@ 16..64 - External Interrupts
+	.endr
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 971d65c..ee604dd 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -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);
 }
-- 
1.7.9

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 5/5] ARM: Cortex-M3: Add support for exception handling
  2012-02-16 20:18       ` [PATCH 5/5] ARM: Cortex-M3: Add support for exception handling Uwe Kleine-König
@ 2012-02-16 22:20         ` Russell King - ARM Linux
  2012-02-24 22:01           ` Uwe Kleine-König
  0 siblings, 1 reply; 40+ messages in thread
From: Russell King - ARM Linux @ 2012-02-16 22:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 16, 2012 at 09:18:10PM +0100, Uwe Kleine-K?nig wrote:
> +	.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

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.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH 1/5] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15
  2012-02-16 20:18     ` [PATCH 1/5] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15 Uwe Kleine-König
                         ` (3 preceding siblings ...)
  2012-02-16 20:18       ` [PATCH 5/5] ARM: Cortex-M3: Add support for exception handling Uwe Kleine-König
@ 2012-02-17  0:28       ` Ryan Mallon
  4 siblings, 0 replies; 40+ messages in thread
From: Ryan Mallon @ 2012-02-17  0:28 UTC (permalink / raw)
  To: linux-arm-kernel

On 17/02/12 07:18, Uwe Kleine-K?nig wrote:

> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
> ---
>  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

> diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
> index e4c96cc..de46477 100644
> --- a/arch/arm/include/asm/system.h
> +++ b/arch/arm/include/asm/system.h
> @@ -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,
> diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
> index be16a48..a6f2ef5 100644
> --- a/arch/arm/kernel/entry-armv.S
> +++ b/arch/arm/kernel/entry-armv.S
> @@ -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
> diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
> index 854bd22..5ca01bb 100644
> --- a/arch/arm/kernel/head-common.S
> +++ b/arch/arm/kernel/head-common.S
> @@ -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?

>  	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
>  
> diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
> index a255c39..50d3df8 100644
> --- a/arch/arm/kernel/setup.c
> +++ b/arch/arm/kernel/setup.c
> @@ -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);


#else
	printk(KERN_CONT "\n");

?

> +#endif

>  
>  	snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c",
>  		 list->arch_name, ENDIANNESS);
> diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
> index caf14dc..119d178 100644
> --- a/arch/arm/mm/alignment.c
> +++ b/arch/arm/mm/alignment.c
> @@ -89,7 +89,11 @@ core_param(alignment, ai_usermode, int, 0600);
>  /* Return true if and only if the ARMv6 unaligned access model is in use. */
>  static bool cpu_is_v6_unaligned(void)
>  {
> +#ifdef CONFIG_CPU_CP15
>  	return cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U);
> +#else
> +	return 0;

> +#endif

>  }
>  
>  static int safe_usermode(int new_usermode, bool warn)
> @@ -961,12 +965,14 @@ static int __init alignment_init(void)
>  		return -ENOMEM;
>  #endif
>  
> +#ifdef CONFIG_CPU_CP15
>  	if (cpu_is_v6_unaligned()) {
>  		cr_alignment &= ~CR_A;
>  		cr_no_alignment &= ~CR_A;
>  		set_cr(cr_alignment);
>  		ai_usermode = safe_usermode(ai_usermode, false);
>  	}
> +#endif
>  
>  	hook_fault_code(FAULT_CODE_ALIGNMENT, do_alignment, SIGBUS, BUS_ADRALN,
>  			"alignment exception");
> diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
> index 94c5a0c..f6dbe1a 100644
> --- a/arch/arm/mm/mmu.c
> +++ b/arch/arm/mm/mmu.c
> @@ -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;

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH 5/5] ARM: Cortex-M3: Add support for exception handling
  2012-02-16 22:20         ` Russell King - ARM Linux
@ 2012-02-24 22:01           ` Uwe Kleine-König
  2012-02-24 22:12             ` Catalin Marinas
  0 siblings, 1 reply; 40+ messages in thread
From: Uwe Kleine-König @ 2012-02-24 22:01 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Catalin,

On Thu, Feb 16, 2012 at 10:20:02PM +0000, Russell King - ARM Linux wrote:
> On Thu, Feb 16, 2012 at 09:18:10PM +0100, Uwe Kleine-K?nig wrote:
> > +	.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
> 
> 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.

> 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

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH 5/5] ARM: Cortex-M3: Add support for exception handling
  2012-02-24 22:01           ` Uwe Kleine-König
@ 2012-02-24 22:12             ` Catalin Marinas
  2012-02-24 22:43               ` Russell King - ARM Linux
                                 ` (2 more replies)
  0 siblings, 3 replies; 40+ messages in thread
From: Catalin Marinas @ 2012-02-24 22:12 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Uwe,

2012/2/24 Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>:
> On Thu, Feb 16, 2012 at 10:20:02PM +0000, Russell King - ARM Linux wrote:
>> On Thu, Feb 16, 2012 at 09:18:10PM +0100, Uwe Kleine-K?nig wrote:
>> > + ? .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
>>
>> 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).

> 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

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

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

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

-- 
Catalin

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH 5/5] ARM: Cortex-M3: Add support for exception handling
  2012-02-24 22:12             ` Catalin Marinas
@ 2012-02-24 22:43               ` Russell King - ARM Linux
  2012-02-25  8:49                 ` Catalin Marinas
  2012-02-25 14:07               ` Uwe Kleine-König
  2012-03-05 17:04               ` [PATCH v2 4/5] Cortex-M3: Add base support for Cortex-M3 Uwe Kleine-König
  2 siblings, 1 reply; 40+ messages in thread
From: Russell King - ARM Linux @ 2012-02-24 22:43 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 24, 2012 at 10:12:06PM +0000, Catalin Marinas wrote:
> 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.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH 5/5] ARM: Cortex-M3: Add support for exception handling
  2012-02-24 22:43               ` Russell King - ARM Linux
@ 2012-02-25  8:49                 ` Catalin Marinas
  0 siblings, 0 replies; 40+ messages in thread
From: Catalin Marinas @ 2012-02-25  8:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 24, 2012 at 10:43:25PM +0000, Russell King - ARM Linux wrote:
> On Fri, Feb 24, 2012 at 10:12:06PM +0000, Catalin Marinas wrote:
> > 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

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH 5/5] ARM: Cortex-M3: Add support for exception handling
  2012-02-24 22:12             ` Catalin Marinas
  2012-02-24 22:43               ` Russell King - ARM Linux
@ 2012-02-25 14:07               ` Uwe Kleine-König
  2012-03-05 17:04               ` [PATCH v2 4/5] Cortex-M3: Add base support for Cortex-M3 Uwe Kleine-König
  2 siblings, 0 replies; 40+ messages in thread
From: Uwe Kleine-König @ 2012-02-25 14:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 24, 2012 at 10:12:06PM +0000, Catalin Marinas wrote:
> Hi Uwe,
> 
> 2012/2/24 Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>:
> > On Thu, Feb 16, 2012 at 10:20:02PM +0000, Russell King - ARM Linux wrote:
> >> On Thu, Feb 16, 2012 at 09:18:10PM +0100, Uwe Kleine-K?nig wrote:
> >> > + ? .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
> >>
> >> 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).
> 
> > 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
> 
> 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.

> 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

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH v2 4/5] Cortex-M3: Add base support for Cortex-M3
  2012-02-24 22:12             ` Catalin Marinas
  2012-02-24 22:43               ` Russell King - ARM Linux
  2012-02-25 14:07               ` Uwe Kleine-König
@ 2012-03-05 17:04               ` Uwe Kleine-König
  2012-03-05 17:04                 ` [PATCH v2 5/5] Cortex-M3: Add support for exception handling Uwe Kleine-König
  2012-03-08 10:52                 ` [PATCH v2 4/5] Cortex-M3: Add base support for Cortex-M3 Catalin Marinas
  2 siblings, 2 replies; 40+ messages in thread
From: Uwe Kleine-König @ 2012-03-05 17:04 UTC (permalink / raw)
  To: linux-arm-kernel

From: Catalin Marinas <catalin.marinas@arm.com>

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]

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
 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

diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 62f8095..1bafa39 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -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
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index cb47d28..5bd8cb6 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -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
diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h
index 7e30874..6a5fd0b 100644
--- a/arch/arm/include/asm/glue-cache.h
+++ b/arch/arm/include/asm/glue-cache.h
@@ -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)
diff --git a/arch/arm/include/asm/glue-df.h b/arch/arm/include/asm/glue-df.h
index 354d571..26be71c 100644
--- a/arch/arm/include/asm/glue-df.h
+++ b/arch/arm/include/asm/glue-df.h
@@ -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
diff --git a/arch/arm/include/asm/glue-proc.h b/arch/arm/include/asm/glue-proc.h
index e2be7f1..8f9991b 100644
--- a/arch/arm/include/asm/glue-proc.h
+++ b/arch/arm/include/asm/glue-proc.h
@@ -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)
diff --git a/arch/arm/include/asm/irqflags.h b/arch/arm/include/asm/irqflags.h
index 1e6cca5..ac4d548 100644
--- a/arch/arm/include/asm/irqflags.h
+++ b/arch/arm/include/asm/irqflags.h
@@ -10,6 +10,18 @@
  */
 #if __LINUX_ARM_ARCH__ >= 6
 
+#ifdef CONFIG_CPU_V7M
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags;
+
+	asm volatile(
+		"	mrs	%0, primask	@ arch_local_irq_save\n"
+		"	cpsid	i"
+		: "=r" (flags) : : "memory", "cc");
+	return flags;
+}
+#else
 static inline unsigned long arch_local_irq_save(void)
 {
 	unsigned long flags;
@@ -20,6 +32,7 @@ static inline unsigned long arch_local_irq_save(void)
 		: "=r" (flags) : : "memory", "cc");
 	return flags;
 }
+#endif
 
 static inline void arch_local_irq_enable(void)
 {
@@ -122,6 +135,38 @@ static inline void arch_local_irq_disable(void)
 
 #endif
 
+#ifdef CONFIG_CPU_V7M
+/*
+ * Save the current interrupt enable state.
+ */
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long flags;
+	asm volatile(
+		"	mrs	%0, primask	@ local_save_flags"
+		: "=r" (flags) : : "memory", "cc");
+	return flags;
+}
+
+/*
+ * restore saved IRQ & FIQ state
+ */
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	asm volatile(
+		"	msr	primask, %0	@ local_irq_restore"
+		:
+		: "r" (flags)
+		: "memory", "cc");
+}
+
+static inline int arch_irqs_disabled_flags(unsigned long flags)
+{
+	return flags & 1;
+}
+
+#else /* ifdef CONFIG_CPU_V7M */
+
 /*
  * Save the current interrupt enable state.
  */
@@ -151,5 +196,7 @@ static inline int arch_irqs_disabled_flags(unsigned long flags)
 	return flags & PSR_I_BIT;
 }
 
-#endif
-#endif
+#endif /* ifdef CONFIG_CPU_V7M / else */
+
+#endif /* ifdef __KERNEL__ */
+#endif /* ifndef __ASM_ARM_IRQFLAGS_H */
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index ce280b8..18ec6b6 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -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)					\
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 451808b..154d442 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -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);
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index de46477..16117ed 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -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'
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 1429d89..da2ce93 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -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
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index 5ca01bb..efeb2d0 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -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
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 1aca35d..61ba029 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -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)?
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index e33870f..9ba31f8 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -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,
 };
 
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 23893b1..d0fc5b8 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -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];
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 9e617bd..8407c17 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -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:
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 99a5727..8956d08 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -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
 }
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
index 4fc6794..fdd49ac 100644
--- a/arch/arm/mm/nommu.c
+++ b/arch/arm/mm/nommu.c
@@ -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)
diff --git a/arch/arm/mm/proc-v7m.S b/arch/arm/mm/proc-v7m.S
new file mode 100644
index 0000000..51404d9
--- /dev/null
+++ b/arch/arm/mm/proc-v7m.S
@@ -0,0 +1,168 @@
+/*
+ *  linux/arch/arm/mm/proc-v7m.S
+ *
+ *  Copyright (C) 2008 ARM Ltd.
+ *  Copyright (C) 2001 Deep Blue Solutions Ltd.
+ *
+ * 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.
+ *
+ *  This is the "shell" of the ARMv7-M processor support.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+ENTRY(cpu_v7m_proc_init)
+	mov	pc, lr
+ENDPROC(cpu_v7m_proc_init)
+
+ENTRY(cpu_v7m_proc_fin)
+	mov	pc, lr
+ENDPROC(cpu_v7m_proc_fin)
+
+/*
+ *	cpu_v7m_reset(loc)
+ *
+ *	Perform a soft reset of the system.  Put the CPU into the
+ *	same state as it would be if it had been reset, and branch
+ *	to what would be the reset vector.
+ *
+ *	- loc   - location to jump to for soft reset
+ */
+	.align	5
+ENTRY(cpu_v7m_reset)
+	mov	pc, r0
+ENDPROC(cpu_v7m_reset)
+
+/*
+ *	cpu_v7m_do_idle()
+ *
+ *	Idle the processor (eg, wait for interrupt).
+ *
+ *	IRQs are already disabled.
+ */
+ENTRY(cpu_v7m_do_idle)
+	wfi
+	mov	pc, lr
+ENDPROC(cpu_v7m_do_idle)
+
+ENTRY(cpu_v7m_dcache_clean_area)
+	mov	pc, lr
+ENDPROC(cpu_v7m_dcache_clean_area)
+
+/*
+ *	cpu_v7m_switch_mm(pgd_phys, tsk)
+ *
+ *	Set the translation table base pointer to be pgd_phys
+ *
+ *	- pgd_phys - physical address of new TTB
+ *
+ *	It is assumed that:
+ *	- we are not using split page tables
+ */
+ENTRY(cpu_v7m_switch_mm)
+	mov	pc, lr
+ENDPROC(cpu_v7m_switch_mm)
+
+cpu_v7m_name:
+	.ascii	"ARMv7-M Processor"
+	.align
+
+	.section ".text.init", #alloc, #execinstr
+
+/*
+ *	__v7m_setup
+ *
+ *	This should be able to cover all ARMv7-M cores.
+ */
+__v7m_setup:
+	@ Configure the vector table base address
+	ldr	r0, =0xe000ed08		@ vector table base address
+	ldr	r12, =vector_table
+	str	r12, [r0]
+
+	@ Lower the priority of the SVC and PendSV exceptions
+	ldr	r0, =0xe000ed1c
+	mov	r5, #0x80000000
+	str	r5, [r0]		@ set SVC priority
+	ldr	r0, =0xe000ed20
+	mov	r5, #0x00800000
+	str	r5, [r0]		@ set PendSV priority
+
+	@ SVC to run the kernel in this mode
+	adr	r0, BSYM(1f)
+	ldr	r5, [r12, #11 * 4]	@ read the SVC vector entry
+	str	r0, [r12, #11 * 4]	@ write the temporary SVC vector entry
+	mov	r6, lr			@ save LR
+	mov	r7, sp			@ save SP
+	ldr	sp, =__v7m_setup_stack_top
+	cpsie	i
+	svc	#0
+1:	cpsid	i
+	str	r5, [r12, #11 * 4]	@ restore the original SVC vector entry
+	mov	lr, r6			@ restore LR
+	mov	sp, r7			@ restore SP
+
+	@ Special-purpose control register
+	mov	r0, #1
+	msr	control, r0		@ Thread mode has unpriviledged access
+
+	@ Configure the System Control Register
+	ldr	r0, =0xe000ed14		@ system control register
+	ldr	r12, [r0]
+	orr	r12, #1 << 9		@ STKALIGN
+	str	r12, [r0]
+	mov	pc, lr
+ENDPROC(__v7m_setup)
+
+	.align	2
+	.type	v7m_processor_functions, #object
+ENTRY(v7m_processor_functions)
+	.word	nommu_early_abort
+	.word	cpu_v7m_proc_init
+	.word	cpu_v7m_proc_fin
+	.word	cpu_v7m_reset
+	.word	cpu_v7m_do_idle
+	.word	cpu_v7m_dcache_clean_area
+	.word	cpu_v7m_switch_mm
+	.word	0			@ cpu_v7m_set_pte_ext
+	.word	legacy_pabort
+	.size	v7m_processor_functions, . - v7m_processor_functions
+
+	.type	cpu_arch_name, #object
+cpu_arch_name:
+	.asciz	"armv7m"
+	.size	cpu_arch_name, . - cpu_arch_name
+
+	.type	cpu_elf_name, #object
+cpu_elf_name:
+	.asciz	"v7m"
+	.size	cpu_elf_name, . - cpu_elf_name
+	.align
+
+	.section ".proc.info.init", #alloc, #execinstr
+
+	/*
+	 * Match any ARMv7-M processor core.
+	 */
+	.type	__v7m_proc_info, #object
+__v7m_proc_info:
+	.long	0x000f0000		@ Required ID value
+	.long	0x000f0000		@ Mask for ID
+	.long   0			@ proc_info_list.__cpu_mm_mmu_flags
+	.long   0			@ proc_info_list.__cpu_io_mmu_flags
+	b	__v7m_setup		@ proc_info_list.__cpu_flush
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+	.long	cpu_v7m_name
+	.long	v7m_processor_functions	@ proc_info_list.proc
+	.long	0			@ proc_info_list.tlb
+	.long	0			@ proc_info_list.user
+	.long	0			@ proc_info_list.cache
+	.size	__v7m_proc_info, . - __v7m_proc_info
+
+__v7m_setup_stack:
+	.space	4 * 8				@ 8 registers
+__v7m_setup_stack_top:
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 5/5] Cortex-M3: Add support for exception handling
  2012-03-05 17:04               ` [PATCH v2 4/5] Cortex-M3: Add base support for Cortex-M3 Uwe Kleine-König
@ 2012-03-05 17:04                 ` Uwe Kleine-König
  2012-03-09 17:10                   ` Catalin Marinas
  2012-03-08 10:52                 ` [PATCH v2 4/5] Cortex-M3: Add base support for Cortex-M3 Catalin Marinas
  1 sibling, 1 reply; 40+ messages in thread
From: Uwe Kleine-König @ 2012-03-05 17:04 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
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

diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 9fd0ba9..953e517 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -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
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 9a8531e..6e03c8b 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -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)
 #error "Please fix"
 #endif
 
@@ -44,6 +44,144 @@
 #endif
 	.endm
 
+#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.
+	@ 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
+
+	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
+	@ another 32-bit value is included in the stack.
+
+	tst	lr, #0x10
+	addeq	r0, r0, #576
+
+	tst	r3, #0x100
+	addne	r0, r0, #4
+
+	@ save original sp, lr, return address, xPSR and EXC_RETURN
+	add	r12, sp, #52
+	stmia	r12, {r0-r3, lr}
+
+	@ restore registers for system calls
+	ldmia	sp, {r0-r12}
+	.endm
+
+	.macro	v7m_exception_fast_exit
+	@ read r12, sp, lr, return address, xPSR and EXC_RETURN
+	add	r12, sp, #48
+	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
+	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
+
+	.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
+	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
+
+	msr	psp, r2
+
+	ldmia	sp, {r0-r12}			@ restore original r4-r11
+
+	add	sp, #S_FRAME_SIZE		@ restore the original MSP
+	cpsie	i
+	bx	lr
+	.endm
+#endif	/* CONFIG_CPU_V7M */
+
 	@
 	@ Store/load the USER SP and LR registers by switching to the SYS
 	@ mode. Useful in Thumb-2 mode where "stm/ldm rd, {sp, lr}^" is not
@@ -131,6 +269,14 @@
 	rfeia	sp!
 	.endm
 
+#ifdef CONFIG_CPU_V7M
+	.macro	restore_user_regs, fast = 0, offset = 0
+	.if	\offset
+	add	sp, #\offset
+	.endif
+	v7m_exception_slow_exit ret_r0 = \fast
+	.endm
+#else	/* !CONFIG_CPU_V7M */
 	.macro	restore_user_regs, fast = 0, offset = 0
 	clrex					@ clear the exclusive monitor
 	mov	r2, sp
@@ -147,6 +293,7 @@
 	add	sp, sp, #S_FRAME_SIZE - S_SP
 	movs	pc, lr				@ return & move spsr_svc into cpsr
 	.endm
+#endif	/* CONFIG_CPU_V7M */
 
 	.macro	get_thread_info, rd
 	mov	\rd, sp
diff --git a/arch/arm/kernel/entry-v7m.S b/arch/arm/kernel/entry-v7m.S
new file mode 100644
index 0000000..5bca10b
--- /dev/null
+++ b/arch/arm/kernel/entry-v7m.S
@@ -0,0 +1,135 @@
+/*
+ * linux/arch/arm/kernel/entry-v7m.S
+ *
+ * Copyright (C) 2008 ARM Ltd.
+ *
+ * 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.
+ *
+ * Low-level vector interface routines for the ARMv7-M architecture
+ */
+#include <asm/memory.h>
+#include <asm/glue.h>
+#include <asm/thread_notify.h>
+
+#include <mach/entry-macro.S>
+
+#include "entry-header.S"
+
+#ifdef CONFIG_PREEMPT
+#error "CONFIG_PREEMPT not supported on the current ARMv7M implementation"
+#endif
+#ifdef CONFIG_TRACE_IRQFLAGS
+#error "CONFIG_TRACE_IRQFLAGS not supported on the current ARMv7M implementation"
+#endif
+
+__invalid_entry:
+	v7m_exception_entry
+	adr	r0, strerr
+	mrs	r1, ipsr
+	mov	r2, lr
+	mov	r3, sp
+	bl	printk
+	mov	r0, sp
+	bl	__show_regs
+1:	b	1b
+ENDPROC(__invalid_entry)
+
+strerr:	.asciz	"\nUnhandled exception: IPSR = %08lx LR = %08lx SP = %08lx\n"
+
+	.align	2
+__irq_entry:
+	v7m_exception_entry
+
+	@
+	@ Invoke the IRQ handler
+	@
+	mrs	r0, ipsr
+	and	r0, #0xff
+	sub	r0, #16			@ IRQ number
+	mov	r1, sp
+	@ routine called with r0 = irq number, r1 = struct pt_regs *
+	bl	asm_do_IRQ
+
+	@
+	@ Check for any pending work if returning to user
+	@
+	ldr	lr, [sp, #S_EXCRET]
+	tst	lr, #0x8		@ check the return stack
+	beq	2f			@ returning to handler mode
+	get_thread_info tsk
+	ldr	r1, [tsk, #TI_FLAGS]
+	tst	r1, #_TIF_WORK_MASK
+	beq	2f			@ no work pending
+	ldr	r1, =0xe000ed04		@ ICSR
+	mov	r0, #1 << 28		@ ICSR.PENDSVSET
+	str	r0, [r1]		@ raise PendSV
+
+2:
+	v7m_exception_fast_exit
+ENDPROC(__irq_entry)
+
+__pendsv_entry:
+	v7m_exception_entry
+
+	ldr	r1, =0xe000ed04		@ ICSR
+	mov	r0, #1 << 27		@ ICSR.PENDSVCLR
+	str	r0, [r1]		@ clear PendSV
+
+	@ execute the pending work, including reschedule
+	get_thread_info tsk
+	mov	why, #0
+	b	ret_to_user
+ENDPROC(__pendsv_entry)
+
+/*
+ * Register switch for ARMv7-M processors.
+ * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info
+ * previous and next are guaranteed not to be the same.
+ */
+ENTRY(__switch_to)
+	.fnstart
+	.cantunwind
+	add	ip, r1, #TI_CPU_SAVE
+	stmia	ip!, {r4 - r11}		@ Store most regs on stack
+	str	sp, [ip], #4
+	str	lr, [ip], #4
+	mov	r5, r0
+	add	r4, r2, #TI_CPU_SAVE
+	ldr	r0, =thread_notify_head
+	mov	r1, #THREAD_NOTIFY_SWITCH
+	bl	atomic_notifier_call_chain
+	mov	ip, r4
+	mov	r0, r5
+	ldmia	ip!, {r4 - r11}		@ Load all regs saved previously
+	ldr	sp, [ip], #4
+	ldr	pc, [ip]
+	.fnend
+ENDPROC(__switch_to)
+
+	.data
+	.align	8
+/*
+ * Vector table (64 words => 256 bytes natural alignment)
+ */
+ENTRY(vector_table)
+	.long	0			@ 0 - Reset stack pointer
+	.long	__invalid_entry		@ 1 - Reset
+	.long	__invalid_entry		@ 2 - NMI
+	.long	__invalid_entry		@ 3 - HardFault
+	.long	__invalid_entry		@ 4 - MemManage
+	.long	__invalid_entry		@ 5 - BusFault
+	.long	__invalid_entry		@ 6 - UsageFault
+	.long	__invalid_entry		@ 7 - Reserved
+	.long	__invalid_entry		@ 8 - Reserved
+	.long	__invalid_entry		@ 9 - Reserved
+	.long	__invalid_entry		@ 10 - Reserved
+	.long	vector_swi		@ 11 - SVCall
+	.long	__invalid_entry		@ 12 - Debug Monitor
+	.long	__invalid_entry		@ 13 - Reserved
+	.long	__pendsv_entry		@ 14 - PendSV
+	.long	__invalid_entry		@ 15 - SysTick
+	.rept	64 - 16
+	.long	__irq_entry		@ 16..64 - External Interrupts
+	.endr
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 971d65c..bdccb8f 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -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);
 }
-- 
1.7.9.1

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 4/5] Cortex-M3: Add base support for Cortex-M3
  2012-03-05 17:04               ` [PATCH v2 4/5] Cortex-M3: Add base support for Cortex-M3 Uwe Kleine-König
  2012-03-05 17:04                 ` [PATCH v2 5/5] Cortex-M3: Add support for exception handling Uwe Kleine-König
@ 2012-03-08 10:52                 ` Catalin Marinas
  1 sibling, 0 replies; 40+ messages in thread
From: Catalin Marinas @ 2012-03-08 10:52 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Uwe,

On Mon, Mar 05, 2012 at 05:04:01PM +0000, Uwe Kleine-K?nig wrote:
> --- a/arch/arm/include/asm/processor.h
> +++ b/arch/arm/include/asm/processor.h
> @@ -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)
...
> --- a/arch/arm/include/asm/ptrace.h
> +++ b/arch/arm/include/asm/ptrace.h
> @@ -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.

-- 
Catalin

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH v2 5/5] Cortex-M3: Add support for exception handling
  2012-03-05 17:04                 ` [PATCH v2 5/5] Cortex-M3: Add support for exception handling Uwe Kleine-König
@ 2012-03-09 17:10                   ` Catalin Marinas
  2012-03-13 20:39                     ` Uwe Kleine-König
  0 siblings, 1 reply; 40+ messages in thread
From: Catalin Marinas @ 2012-03-09 17:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 05, 2012 at 05:04:02PM +0000, Uwe Kleine-K?nig wrote:
> 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).

> --- a/arch/arm/kernel/entry-common.S
> +++ b/arch/arm/kernel/entry-common.S
> @@ -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.

> --- a/arch/arm/kernel/entry-header.S
> +++ b/arch/arm/kernel/entry-header.S
> @@ -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.

> +#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.
> +	@ 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?

> +	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
> +	@ 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.

> +	@ 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.

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

> +	.endm
> +
> +	.macro	v7m_exception_fast_exit
> +	@ read r12, sp, lr, return address, xPSR and EXC_RETURN
> +	add	r12, sp, #48

S_ARM_R12?

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

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

> +	msr	psp, r2
> +
> +	ldmia	sp, {r0-r12}			@ restore original r4-r11

Isn't this reading too much (optimisation)?

> +	add	sp, #S_FRAME_SIZE		@ restore the original MSP
> +	cpsie	i
> +	bx	lr
> +	.endm
> +#endif	/* CONFIG_CPU_V7M */
...
> --- a/arch/arm/kernel/process.c
> +++ b/arch/arm/kernel/process.c
> @@ -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

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?

-- 
Catalin

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH v2 5/5] Cortex-M3: Add support for exception handling
  2012-03-09 17:10                   ` Catalin Marinas
@ 2012-03-13 20:39                     ` Uwe Kleine-König
  0 siblings, 0 replies; 40+ messages in thread
From: Uwe Kleine-König @ 2012-03-13 20:39 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Catalin,

On Fri, Mar 09, 2012 at 05:10:26PM +0000, Catalin Marinas wrote:
> On Mon, Mar 05, 2012 at 05:04:02PM +0000, Uwe Kleine-K?nig wrote:
> > 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.

> > --- a/arch/arm/kernel/entry-common.S
> > +++ b/arch/arm/kernel/entry-common.S
> > @@ -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.
 
> > --- a/arch/arm/kernel/entry-header.S
> > +++ b/arch/arm/kernel/entry-header.S
> > @@ -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 ;-)
> 
> > +#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.
> > +	@ 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?

> > +	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
> > +	@ 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?

> > +	@ 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.

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

> > +	.endm
> > +
> > +	.macro	v7m_exception_fast_exit
> > +	@ read r12, sp, lr, return address, xPSR and EXC_RETURN
> > +	add	r12, sp, #48
> 
> S_ARM_R12?
> 
> > +	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
> > +	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.
I was not sure if a task could be preempted during an exception. So I
choosed to play save.

> > +	.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
> > +	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.
> 
> > +	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?

> > +	add	sp, #S_FRAME_SIZE		@ restore the original MSP
> > +	cpsie	i
> > +	bx	lr
> > +	.endm
> > +#endif	/* CONFIG_CPU_V7M */
> ...
> > --- a/arch/arm/kernel/process.c
> > +++ b/arch/arm/kernel/process.c
> > @@ -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
> 
> 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.

> 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

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2012-03-13 20:39 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-22 11:12 [RFC PATCH 00/11] Cortex-M3 support Uwe Kleine-König
2012-01-22 11:13 ` [RFC PATCH 01/11] ARM: only show modules in the memory layout for MODULES=y Uwe Kleine-König
2012-01-26  6:16   ` Linus Walleij
2012-01-22 11:13 ` [RFC PATCH 02/11] ARM: add device tree blobs to .gitignore Uwe Kleine-König
2012-01-22 11:13 ` [RFC PATCH 03/11] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15 Uwe Kleine-König
2012-01-23  5:43   ` Jean-Christophe PLAGNIOL-VILLARD
2012-01-23  8:14     ` Uwe Kleine-König
2012-01-22 11:13 ` [RFC PATCH 04/11] ARM: Add a printk loglevel modifier Uwe Kleine-König
2012-01-23  5:50   ` Jean-Christophe PLAGNIOL-VILLARD
2012-01-22 11:13 ` [RFC PATCH 05/11] ARM: provide XIP_VIRT_ADDR for no-MMU builds Uwe Kleine-König
2012-01-22 11:13 ` [RFC PATCH 06/11] Cortex-M3: Add base support for Cortex-M3 Uwe Kleine-König
2012-01-22 19:45   ` Michał Mirosław
2012-01-22 20:42     ` Uwe Kleine-König
2012-01-22 11:13 ` [RFC PATCH 07/11] Cortex-M3: Add support for exception handling Uwe Kleine-König
2012-01-22 11:13 ` [RFC PATCH 08/11] Cortex-M3: Add NVIC support Uwe Kleine-König
2012-01-31 19:39   ` Uwe Kleine-König
2012-01-22 11:13 ` [RFC PATCH 09/11] Cortex-M3: Allow the building of Cortex-M3 kernel port Uwe Kleine-König
2012-01-22 20:05   ` Michał Mirosław
2012-02-07 19:43     ` Uwe Kleine-König
2012-01-22 11:13 ` [RFC PATCH 10/11] Cortex-M3: Add VFP support Uwe Kleine-König
2012-01-22 11:13 ` [RFC PATCH 11/11] HACK! ARM: no, we don't enter in ARM Uwe Kleine-König
2012-02-07 20:18 ` [RFC PATCH 00/11] Cortex-M3 support Uwe Kleine-König
2012-02-16 20:01   ` Uwe Kleine-König
2012-02-16 20:18     ` [PATCH 1/5] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15 Uwe Kleine-König
2012-02-16 20:18       ` [PATCH 2/5] ARM: Add a printk loglevel modifier Uwe Kleine-König
2012-02-16 20:18       ` [PATCH 3/5] ARM: force branch instructions to use long distance encoding Uwe Kleine-König
2012-02-16 20:18       ` [PATCH 4/5] ARM: Cortex-M3: Add base support for Cortex-M3 Uwe Kleine-König
2012-02-16 20:18       ` [PATCH 5/5] ARM: Cortex-M3: Add support for exception handling Uwe Kleine-König
2012-02-16 22:20         ` Russell King - ARM Linux
2012-02-24 22:01           ` Uwe Kleine-König
2012-02-24 22:12             ` Catalin Marinas
2012-02-24 22:43               ` Russell King - ARM Linux
2012-02-25  8:49                 ` Catalin Marinas
2012-02-25 14:07               ` Uwe Kleine-König
2012-03-05 17:04               ` [PATCH v2 4/5] Cortex-M3: Add base support for Cortex-M3 Uwe Kleine-König
2012-03-05 17:04                 ` [PATCH v2 5/5] Cortex-M3: Add support for exception handling Uwe Kleine-König
2012-03-09 17:10                   ` Catalin Marinas
2012-03-13 20:39                     ` Uwe Kleine-König
2012-03-08 10:52                 ` [PATCH v2 4/5] Cortex-M3: Add base support for Cortex-M3 Catalin Marinas
2012-02-17  0:28       ` [PATCH 1/5] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15 Ryan Mallon

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.