* [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 +++++-
| 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]
--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, ®s, 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 +
| 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
--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 = ¤t_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 +++++-
| 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]
--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, ®s, 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 ++-
| 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
--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, ®s, 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.