Cortex-M3 support
Subsystems (2)
cover Cortex-M3 support
Hello,
this series is mostly a port of patches done by Catalin Marinas for 2.6.33. It's based on 3.3-rc1. There are still a few rough edges and I'm sure I'm not aware of all of them as this deep architecture stuff is mostly news for me. Some things are noted in the respective patches, I'm sure you can find more.
My target machine is the EFM32 Giant Gecko by Energy Micro and my complete tree can be found at
git://git.pengutronix.de/git/ukl/linux.git efm32
(with a gitweb being available at
http://git.pengutronix.de/?p=ukl/linux.git;a=shortlog;h=efm32
).
I look forward to your comments.
Best regards
Uwe
Signature · 2 lines
Pengutronix e.K. | Uwe Kleine-K?nig | Industrial Linux Solutions | http://www.pengutronix.de/ |
RFC PATCH 1/11 ARM: only show modules in the memory layout for MODULES=y
This line is irritating and wrong when modules are not supported, so don't show it then.
--- arch/arm/mm/init.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
arch/arm/mm/init.c +4 -0
@@ -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 ), +#endifMLK_ROUNDUP (_text, _etext), MLK_ROUNDUP(__init_begin, __init_end),
Signature · 1 line
1.7.8.3
RFC PATCH 1/11 ARM: only show modules in the memory layout for MODULES=y
2012/1/22 Uwe Kleine-K?nig <[email protected]>:
Quoted 5 lines
This line is irritating and wrong when modules are not supported, so don't show it then.
Signed-off-by Uwe Kleine-K?nig <[email protected]>Acked-by Nicolas Pitre <[email protected]>
Pretty straight-forward....
Yours,
Linus Walleij
RFC PATCH 2/11 ARM: add device tree blobs to .gitignore
In reply to Uwe Kleine-König*.dtb files are a build result and so should be ignored.
Forwarded: id:1323808612-14976-1-git-send-email-u.kleine-koenig at pengutronix.de
--- arch/arm/boot/.gitignore | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
arch/arm/boot/.gitignore +1 -0
@@ -3,3 +3,4 @@ zImage xipImage bootpImage uImage +*.dtb
Signature · 1 line
1.7.8.3
RFC PATCH 3/11 ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15
In reply to Uwe Kleine-König--- arch/arm/include/asm/system.h | 2 ++ arch/arm/kernel/entry-armv.S | 4 ++++ arch/arm/kernel/head-common.S | 9 +++++++-- arch/arm/kernel/setup.c | 8 ++++++-- arch/arm/mm/alignment.c | 6 ++++++ arch/arm/mm/mmu.c | 8 +++++++- 6 files changed, 32 insertions(+), 5 deletions(-)
arch/arm/include/asm/system.h +2 -0
@@ -185,6 +185,7 @@ extern unsigned int user_debug;#define set_mb (var, value) do { var = value; smp_mb(); } while (0)#define nop () __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t"); +#ifdef CONFIG_CPU_CP15 extern unsigned long cr_no_alignment;/* defined in entry-armv.S */ extern unsigned long cr_alignment;/* defined in entry-armv.S */
@@ -224,6 +225,7 @@ static inline void set_copro_access(unsigned int val) : : "r" (val) : "cc"); isb(); } +#endif /* * switch_mm() may do a full cache flush over the context switch,
arch/arm/kernel/entry-armv.S +4 -0
@@ -314,8 +314,10 @@ __pabt_svc: ENDPROC(__pabt_svc) .align 5 +#ifdef CONFIG_CPU_CP15 .LCcralign: .word cr_alignment +#endif #ifdef MULTI_DABORT .LCprocfns: .word processor
@@ -1146,12 +1148,14 @@ __vectors_end: .data +#ifdef CONFIG_CPU_CP15 .globl cr_alignment .globl cr_no_alignment cr_alignment: .space 4 cr_no_alignment: .space 4 +#endif #ifdef CONFIG_MULTI_IRQ_HANDLER .globl handle_arch_irq
arch/arm/kernel/head-common.S +7 -2
@@ -98,8 +98,9 @@ __mmap_switched: str r9, [r4] @ Save processor ID str r1, [r5] @ Save machine type str r2, [r6] @ Save atags pointer - bic r4, r0, #CR_A @ Clear 'A' bit - stmia r7, {r0, r4} @ Save control register values + cmp r7, #0 + bicne r4, r0, #CR_A @ Clear 'A' bit + stmneia r7, {r0, r4} @ Save control register values b start_kernel ENDPROC(__mmap_switched)
@@ -113,7 +114,11 @@ __mmap_switched_data: .long processor_id @ r4 .long __machine_arch_type @ r5 .long __atags_pointer @ r6 +#ifdef CONFIG_CPU_CP15 .long cr_alignment @ r7 +#else + .long 0 +#endif .long init_thread_union + THREAD_START_SP @ sp .size __mmap_switched_data, . - __mmap_switched_data
arch/arm/kernel/setup.c +6 -2
@@ -459,9 +459,13 @@ static void __init setup_processor(void) cpu_cache = *list->cache;#endif -printk ("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n" , +printk ("CPU: %s [%08x] revision %d (ARMv%s)" , cpu_name,read_cpuid_id (),read_cpuid_id () &15 , - proc_arch[cpu_architecture ()], cr_alignment); + proc_arch[cpu_architecture ()]); + +#ifdef CONFIG_CPU_CP15 +printk (KERN_CONT ", cr=%08lx\n" , cr_alignment); +#endif snprintf (init_utsname ()->machine, __NEW_UTS_LEN +1 ,"%s%c" , list->arch_name,ENDIANNESS );
arch/arm/mm/alignment.c +6 -0
@@ -89,7 +89,11 @@ core_param(alignment, ai_usermode, int, 0600);/* Return true if and only if the ARMv6 unaligned access model is in use. */ static bool cpu_is_v6_unaligned (void ) { +#ifdef CONFIG_CPU_CP15 return cpu_architecture () >= CPU_ARCH_ARMv6 && (cr_alignment &CR_U ); +#else +return 0 ; +#endif }static int safe_usermode (int new_usermode,bool warn)
@@ -961,12 +965,14 @@ static int __init alignment_init(void)return -ENOMEM ;#endif +#ifdef CONFIG_CPU_CP15 if (cpu_is_v6_unaligned ()) { cr_alignment &= ~CR_A ; cr_no_alignment &= ~CR_A ;set_cr (cr_alignment); ai_usermode =safe_usermode (ai_usermode, false); } +#endif hook_fault_code (FAULT_CODE_ALIGNMENT , do_alignment,SIGBUS ,BUS_ADRALN ,"alignment exception" );
arch/arm/mm/mmu.c +7 -1
@@ -109,8 +109,10 @@ static int __init early_cachepolicy(char *p)if (memcmp (p, cache_policies[i].policy, len) ==0 ) { cachepolicy = i; +#ifdef CONFIG_CPU_CP15 cr_alignment &= ~cache_policies[i].cr_mask; cr_no_alignment &= ~cache_policies[i].cr_mask; +#endif break ; } }
@@ -128,7 +130,9 @@ static int __init early_cachepolicy(char *p) cachepolicy =CPOLICY_WRITEBACK ; }flush_cache_all (); +#ifdef CONFIG_CPU_CP15 set_cr (cr_alignment); +#endif return 0 ; }early_param ("cachepolicy" , early_cachepolicy);
@@ -163,6 +167,7 @@ static int __init early_ecc(char *p)early_param ("ecc" , early_ecc);#endif +#ifdef CONFIG_CPU_CP15 static int __init noalign_setup (char *__unused) { cr_alignment &= ~CR_A ;
@@ -171,8 +176,9 @@ static int __init noalign_setup(char *__unused)return 1 ; }__setup ("noalign" , noalign_setup); +#endif -#ifndef CONFIG_SMP +#if !defined(CONFIG_SMP ) && defined(CONFIG_CPU_CP15 )void adjust_cr (unsigned long mask,unsigned long set) {unsigned long flags;
Signature · 1 line
1.7.8.3
RFC PATCH 3/11 ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15
Quoted 126 lines · Uwe Kleine-K?nig
Signed-off-by Uwe Kleine-K?nig <[email protected]>--- arch/arm/include/asm/system.h | 2 ++ arch/arm/kernel/entry-armv.S | 4 ++++ arch/arm/kernel/head-common.S | 9 +++++++-- arch/arm/kernel/setup.c | 8 ++++++-- arch/arm/mm/alignment.c | 6 ++++++ arch/arm/mm/mmu.c | 8 +++++++- 6 files changed, 32 insertions(+), 5 deletions(-)arch/arm/include/asm/system.h +2
-0@@ -185,6 +185,7 @@ extern unsigned int user_debug;#define set_mb (var, value) do { var = value; smp_mb(); } while (0)#define nop () __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t"); +#ifdef CONFIG_CPU_CP15 extern unsigned long cr_no_alignment;/* defined in entry-armv.S */ extern unsigned long cr_alignment;/* defined in entry-armv.S */ @@ -224,6 +225,7 @@ static inline void set_copro_access(unsigned int val) : : "r" (val) : "cc"); isb(); } +#endif /* * switch_mm() may do a full cache flush over the context switch, arch/arm/kernel/entry-armv.S +4
-0@@ -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_irqarch/arm/kernel/head-common.S +7
-2@@ -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_dataarch/arm/kernel/setup.c +6
-2@@ -459,9 +459,13 @@ static void __init setup_processor(void) cpu_cache = *list->cache;#endif -printk ("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n" , +printk ("CPU: %s [%08x] revision %d (ARMv%s)" , cpu_name,read_cpuid_id (),read_cpuid_id () &15 , - proc_arch[cpu_architecture ()], cr_alignment); + proc_arch[cpu_architecture ()]); + +#ifdef CONFIG_CPU_CP15 +printk (KERN_CONT ", cr=%08lx\n" , cr_alignment); +#endif snprintf (init_utsname ()->machine, __NEW_UTS_LEN +1 ,"%s%c" , list->arch_name,ENDIANNESS );arch/arm/mm/alignment.c +4
-0@@ -89,7 +89,11 @@ core_param(alignment, ai_usermode, int, 0600);/* Return true if and only if the ARMv6 unaligned access model is in use. */ static bool cpu_is_v6_unaligned (void ) { +#ifdef CONFIG_CPU_CP15 return cpu_architecture () >= CPU_ARCH_ARMv6 && (cr_alignment &CR_U ); +#else +return 0 ; +#endif }static int safe_usermode (int new_usermode,bool warn)@@ -961,12 +965,14 @@ static int __init alignment_init(void)return -ENOMEM ;
arch/arm/mm/alignment.c static int __init alignment_init(void) · line 975
Quoted 10 lines
arch/arm/mm/alignment.c +2
-0#endif +#ifdef CONFIG_CPU_CP15 if (cpu_is_v6_unaligned ()) { cr_alignment &= ~CR_A ; cr_no_alignment &= ~CR_A ;set_cr (cr_alignment); ai_usermode =safe_usermode (ai_usermode, false); } +#endif
why if CPU_CP15 is not supported cpu_is_v6_unaligned return 0
arch/arm/mm/mmu.c static int __init early_cachepolicy(char *p) · line 112
Quoted 12 lines
arch/arm/mm/alignment.c +0
-0hook_fault_code (FAULT_CODE_ALIGNMENT , do_alignment,SIGBUS ,BUS_ADRALN ,"alignment exception" );arch/arm/mm/mmu.c +1
-0@@ -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.
RFC PATCH 3/11 ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15
Hi Jean-Christophe,
Quoted 21 lines · Jean-Christophe PLAGNIOL-VILLARD
Quoted 20 lines · Uwe Kleine-K?nig
arch/arm/mm/alignment.c +4
-0@@ -89,7 +89,11 @@ core_param(alignment, ai_usermode, int, 0600);/* Return true if and only if the ARMv6 unaligned access model is in use. */ static bool cpu_is_v6_unaligned (void ) { +#ifdef CONFIG_CPU_CP15 return cpu_architecture () >= CPU_ARCH_ARMv6 && (cr_alignment &CR_U ); +#else +return 0 ; +#endif }static int safe_usermode (int new_usermode,bool warn)@@ -961,12 +965,14 @@ static int __init alignment_init(void)return -ENOMEM ;#endif
Quoted 9 lines
arch/arm/mm/alignment.c static int __init alignment_init(void) · line 975
Quoted 8 lines
arch/arm/mm/alignment.c +2
-0+#ifdef CONFIG_CPU_CP15 if (cpu_is_v6_unaligned ()) { cr_alignment &= ~CR_A ; cr_no_alignment &= ~CR_A ;set_cr (cr_alignment); ai_usermode =safe_usermode (ai_usermode, false); } +#endif why if
CPU_CP15is not supportedcpu_is_v6_unalignedreturn 0
on v7M I could probably check the CCR register's UNALIGN_TRP flag which has the semantic matching the CP15 U-flag. I don't know how a v7m machine should be handled here. The only affected (and relevant) code is in safe_usermode():
/*
* ARMv6 and later CPUs can perform unaligned accesses for
* most single load and store instructions up to word size.
* LDM, STM, LDRD and STRD still need to be handled.
*
* Ignoring the alignment fault is not an option on these
* CPUs since we spin re-faulting the instruction without
* making any progress.
*/
if (cpu_is_v6_unaligned() && !(new_usermode & (UM_FIXUP | UM_SIGNAL))) {
new_usermode |= UM_FIXUP;
if (warn)
printk(KERN_WARNING "alignment: ignoring faults is unsafe on this CPU. Defaulting to fixup mode.\n");
}
return new_usermode;Does this apply for v7m, too? If so, cpu_is_v6_unaligned needs fixing. Catalin? Russell?
Quoted 8 lines
Quoted 8 lines
arch/arm/mm/alignment.c +0
-0hook_fault_code (FAULT_CODE_ALIGNMENT , do_alignment,SIGBUS ,BUS_ADRALN ,"alignment exception" );arch/arm/mm/mmu.c +0
-0@@ -109,8 +109,10 @@ static int __init early_cachepolicy(char *p)
Quoted 4 lines
arch/arm/mm/mmu.c static int __init early_cachepolicy(char *p) · line 112
Quoted 3 lines
arch/arm/mm/mmu.c +1
-0if (memcmp (p, cache_policies[i].policy, len) ==0 ) { cachepolicy = i; +#ifdef CONFIG_CPU_CP15 can you use if (
IS_ENABLED(x)) instead
IS_ENABLED is defined as:
#define IS_ENABLED(option) (__enabled_ ## option || __enabled_ ## option ## _MODULE)
CPU_CP15 isn't tristate, so I don't see the benefit.
Best regards
Uwe
Signature · 2 lines
Pengutronix e.K. | Uwe Kleine-K?nig | Industrial Linux Solutions | http://www.pengutronix.de/ |
RFC PATCH 4/11 ARM: Add a printk loglevel modifier
In reply to Uwe Kleine-KönigThis is a needed followup for
ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15
otherwise no newline is printed for !CONFIG_CPU_CP15
---
Should this be folded into the
ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15
patch? Or should it come before it?
--- arch/arm/kernel/setup.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/arm/kernel/setup.c +1 -1
@@ -326,7 +326,7 @@ static void __init cacheid_init(void) cacheid =CACHEID_VIVT ; } - printk("CPU: %s data cache, %s instruction cache\n", + printk(KERN_INFO "CPU: %s data cache, %s instruction cache\n", cache_is_vivt() ? "VIVT" : cache_is_vipt_aliasing() ? "VIPT aliasing" : cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown",
Signature · 1 line
1.7.8.3
RFC PATCH 4/11 ARM: Add a printk loglevel modifier
Quoted 22 lines · Uwe Kleine-K?nig
This is a needed followup for
ARM: protect usage of
cr_alignmentby #ifdefCONFIG_CPU_CP15otherwise no newline is printed for !CONFIG_CPU_CP15
Signed-off-by Uwe Kleine-K?nig <[email protected]>---
Should this be folded into theARM: protect usage of
cr_alignmentby #ifdefCONFIG_CPU_CP15patch? Or should it come before it?
--- arch/arm/kernel/setup.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)arch/arm/kernel/setup.c +0
-0
arch/arm/kernel/setup.c static void __init cacheid_init(void) · line 332
Quoted 8 lines
arch/arm/kernel/setup.c +1
-1@@ -326,7 +326,7 @@ static void __init cacheid_init(void) cacheid =CACHEID_VIVT ; } - printk("CPU: %s data cache, %s instruction cache\n", + printk(KERN_INFO "CPU: %s data cache, %s instruction cache\n", cache_is_vivt() ? "VIVT" : cache_is_vipt_aliasing() ? "VIPT aliasing" : cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown",
pr_info?
Best Regrds,
J.
RFC PATCH 5/11 ARM: provide XIP_VIRT_ADDR for no-MMU builds
In reply to Uwe Kleine-KönigXIP_VIRT_ADDR is needed for XIP builds and currently only defined for builds with CONFIG_MMU.
Also provide it for no-MMU builds to make it possible to build an XIP kernel for MMU-less machines. As these lack an MMU it has to be an identity mapping.
Forwarded: id:1323467451-12128-1-git-send-email-u.kleine-koenig at pengutronix.de
--- arch/arm/include/asm/memory.h | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
arch/arm/include/asm/memory.h +2 -0
@@ -116,6 +116,8 @@#define MODULES_END (END_MEM)#define MODULES_VADDR (PHYS_OFFSET) +#define XIP_VIRT_ADDR (physaddr) (physaddr) +#endif /* !CONFIG_MMU */ /*
Signature · 1 line
1.7.8.3
RFC PATCH 6/11 Cortex-M3: Add base support for Cortex-M3
In reply to Uwe Kleine-KönigFrom: Catalin Marinas <[email protected]>
This patch adds the base support for the Cortex-M3 processor (ARMv7-M architecture). It consists of the corresponding arch/arm/mm/ files and various #ifdef's around the kernel. Exception handling is implemented by a subsequent patch.
[ukleinek: squash in some changes originating from commit
b5717ba (Cortex-M3: Add support for the Microcontroller Prototyping System)
from the v2.6.33-arm1 patch stack, port to post 3.2, drop zImage support, and a few cosmetic changes]
---
Russell already pointed out that setmode being empty looks wrong because it should handle the irq flag. According to Catalin there are hardly calling sides where this matters. I admit I didn't look at this, yet.
arch/arm/include/asm/assembler.h | 13 +++- arch/arm/include/asm/cputype.h | 3 + arch/arm/include/asm/glue-cache.h | 24 +++++ arch/arm/include/asm/glue-df.h | 8 ++ arch/arm/include/asm/glue-proc.h | 9 ++ arch/arm/include/asm/irqflags.h | 51 ++++++++++- arch/arm/include/asm/processor.h | 8 ++ arch/arm/include/asm/ptrace.h | 43 +++++++++- arch/arm/include/asm/system.h | 3 + arch/arm/kernel/asm-offsets.c | 3 + arch/arm/kernel/head-common.S | 4 +- arch/arm/kernel/head-nommu.S | 9 ++- arch/arm/kernel/setup.c | 13 +++- arch/arm/kernel/traps.c | 2 + arch/arm/mm/nommu.c | 2 + arch/arm/mm/proc-v7m.S | 178 +++++++++++++++++++++++++++++++++++++ 16 files changed, 363 insertions(+), 10 deletions(-) create mode 100644 arch/arm/mm/proc-v7m.S
arch/arm/include/asm/assembler.h +12 -1
@@ -133,7 +133,11 @@* assumes FIQs are enabled, and that the processor is in SVC mode. */ .macro save_and_disable_irqs, oldcpsr +#ifdef CONFIG_CPU_V7M + mrs \oldcpsr, primask +#else mrs \oldcpsr, cpsr +#endif disable_irq .endm
@@ -142,7 +146,11 @@* guarantee that this will preserve the flags. */ .macro restore_irqs_notrace, oldcpsr +#ifdef CONFIG_CPU_V7M + msr primask, \oldcpsr +#else msr cpsr_c, \oldcpsr +#endif .endm .macro restore_irqs, oldcpsr
@@ -221,7 +229,10 @@#endif .endm -#ifdef CONFIG_THUMB2_KERNEL +#if defined(CONFIG_CPU_V7M ) + .macro setmode, mode, reg + .endm +#elif defined(CONFIG_THUMB2_KERNEL ) .macro setmode, mode, reg mov \reg, #\mode msr cpsr_c, \reg
arch/arm/include/asm/cputype.h +3 -0
@@ -46,6 +46,9 @@ extern unsigned int processor_id; : "cc"); \ __val; \ }) +#elif defined(CONFIG_CPU_V7M ) +#define read_cpuid (reg) (*(unsigned int *)0xe000ed00) +#define read_cpuid_ext (reg) 0#else #define read_cpuid (reg) (processor_id)#define read_cpuid_ext (reg) 0
arch/arm/include/asm/glue-cache.h +24 -0
@@ -125,10 +125,34 @@//# endif #endif +#if defined(CONFIG_CPU_V7M ) +# ifdef _CACHE +# error "Multi-cache not supported on ARMv7-M" +# else +# define _CACHE nop +# endif +#endif +#if !defined(_CACHE) && !defined(MULTI_CACHE )#error Unknown cache maintenance model#endif +#ifndef __ASSEMBLER__ +static inline void nop_flush_icache_all (void ) { } +static inline void nop_flush_kern_cache_all (void ) { } +static inline void nop_flush_user_cache_all (void ) { } +static inline void nop_flush_user_cache_range (unsigned long a,unsigned long b,unsigned int c) { } + +static inline void nop_coherent_kern_range (unsigned long a,unsigned long b) { } +static inline void nop_coherent_user_range (unsigned long a,unsigned long b) { } +static inline void nop_flush_kern_dcache_area (void *a,size_t s) { } + +static inline void nop_dma_flush_range (const void *a,const void *b) { } + +static inline void nop_dma_map_area (const void *s,size_t l,int f) { } +static inline void nop_dma_unmap_area (const void *s,size_t l,int f) { } +#endif +#ifndef MULTI_CACHE #define __cpuc_flush_icache_all __glue(_CACHE,_flush_icache_all)#define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all)
arch/arm/include/asm/glue-df.h +8 -0
@@ -103,6 +103,14 @@# endif #endif +#ifdef CONFIG_CPU_ABRT_NOMMU +# ifdef CPU_DABORT_HANDLER +# define MULTI_DABORT 1 +# else +# define CPU_DABORT_HANDLER nommu_early_abort +# endif +#endif +#ifndef CPU_DABORT_HANDLER #error Unknown data abort handler type#endif
arch/arm/include/asm/glue-proc.h +9 -0
@@ -248,6 +248,15 @@# endif #endif +#ifdef CONFIG_CPU_V7M +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_v7m +# endif +#endif +#ifndef MULTI_CPU #define cpu_proc_init __glue(CPU_NAME,_proc_init)#define cpu_proc_fin __glue(CPU_NAME,_proc_fin)
arch/arm/include/asm/irqflags.h +49 -2
72 lines not on this page · raw message
arch/arm/include/asm/processor.h +8 -0
@@ -49,7 +49,15 @@ struct thread_struct {#ifdef CONFIG_MMU #define nommu_start_thread (regs) do { } while (0)#else +#ifndef CONFIG_CPU_V7M #define nommu_start_thread (regs) regs->ARM_r10 = current->mm->start_data +#else +#define nommu_start_thread (regs) do { \ + regs->ARM_r10 = current->mm->start_data; \ + regs->ARM_sp -= 32;/* exception return state */ \ + regs->ARM_EXC_lr =0xfffffffdL ;/* exception lr */ \ +} while (0) +#endif#endif #define start_thread (regs,pc,sp) \
arch/arm/include/asm/ptrace.h +42 -1
86 lines not on this page · raw message
arch/arm/include/asm/system.h +3 -0
@@ -13,6 +13,7 @@#define CPU_ARCH_ARMv5TEJ 7#define CPU_ARCH_ARMv6 8#define CPU_ARCH_ARMv7 9 +#define CPU_ARCH_ARMv7M 10/* * CR1 bits (CP#15 CR1)
@@ -232,7 +233,9 @@ static inline void set_copro_access(unsigned int val)* so enable interrupts over the context switch to avoid high * latency. */ +#ifndef CONFIG_CPU_V7M #define __ARCH_WANT_INTERRUPTS_ON_CTXSW +#endif /* * switch_to(prev, next) should switch from task `prev' to `next'
arch/arm/kernel/asm-offsets.c +3 -0
@@ -91,6 +91,9 @@ int main(void)DEFINE (S_PC , offsetof(struct pt_regs , ARM_pc));DEFINE (S_PSR , offsetof(struct pt_regs , ARM_cpsr));DEFINE (S_OLD_R0 , offsetof(struct pt_regs , ARM_ORIG_r0)); +#ifdef CONFIG_CPU_V7M +DEFINE (S_EXC_LR , offsetof(struct pt_regs , ARM_EXC_lr)); +#endif DEFINE (S_FRAME_SIZE ,sizeof (struct pt_regs ));BLANK ();#ifdef CONFIG_CACHE_L2X0
arch/arm/kernel/head-common.S +2 -2
@@ -100,7 +100,7 @@ __mmap_switched: str r2, [r6] @ Save atags pointer cmp r7, #0 bicne r4, r0, #CR_A @ Clear 'A' bit - stmneia r7, {r0, r4} @ Save control register values + stmiane r7, {r0, r4} @ Save control register values b start_kernel ENDPROC(__mmap_switched)
@@ -117,7 +117,7 @@ __mmap_switched_data: #ifdef CONFIG_CPU_CP15 .long cr_alignment @ r7 #else - .long 0 + .long 0 @ r7 #endif .long init_thread_union + THREAD_START_SP @ sp .size __mmap_switched_data, . - __mmap_switched_data
arch/arm/kernel/head-nommu.S +6 -3
@@ -44,10 +44,13 @@ ENTRY(stext) setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode @ and irqs disabled -#ifndef CONFIG_CPU_CP15 - ldr r9, =CONFIG_PROCESSOR_ID -#else +#if defined(CONFIG_CPU_CP15) mrc p15, 0, r9, c0, c0 @ get processor id +#elif defined(CONFIG_CPU_V7M) + ldr r9, =0xe000ed00 @ CPUID register address + ldr r9, [r9] +#else + ldr r9, =CONFIG_PROCESSOR_ID #endif bl __lookup_processor_type @ r5=procinfo r9=cpuid movs r10, r5 @ invalid processor (r5=0)?
arch/arm/kernel/setup.c +12 -1
@@ -133,7 +133,9 @@ struct stack {u32 und[3 ]; }____cacheline_aligned ; +#ifndef CONFIG_CPU_V7M static struct stack stacks[NR_CPUS ]; +#endif char elf_platform[ELF_PLATFORM_SIZE ];EXPORT_SYMBOL (elf_platform);
@@ -213,7 +215,7 @@ static const char *proc_arch[] = {"5TEJ" ,"6TEJ" ,"7" , -"?(11)" , +"7M" ,"?(12)" ,"?(13)" , "?(14)",
@@ -222,6 +224,12 @@ static const char *proc_arch[] = { "?(17)", }; +#ifdef CONFIG_CPU_V7M +static int __get_cpu_architecture (void ) +{ +return CPU_ARCH_ARMv7M; +} +#else static int __get_cpu_architecture (void ) {int cpu_arch;
@@ -254,6 +262,7 @@ static int __get_cpu_architecture(void) return cpu_arch; } +#endif int __pure cpu_architecture (void ) {
@@ -381,6 +390,7 @@ static void __init feat_v6_fixup(void)*/ void cpu_init (void ) { +#ifndef CONFIG_CPU_V7M unsigned int cpu =smp_processor_id ();struct stack *stk = &stacks[cpu];
@@ -425,6 +435,7 @@ void cpu_init(void) "I" (offsetof(struct stack, und[0])), PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE) : "r14"); +#endif }static void __init setup_processor (void )
arch/arm/kernel/traps.c +2 -0
@@ -783,6 +783,7 @@ static void __init kuser_get_tls_init(unsigned long vectors)void __init early_trap_init (void ) { +#ifndef CONFIG_CPU_V7M #if defined(CONFIG_CPU_USE_DOMAINS )unsigned long vectors =CONFIG_VECTORS_BASE ;#else
@@ -818,4 +819,5 @@ void __init early_trap_init(void)flush_icache_range (vectors, vectors +PAGE_SIZE );modify_domain (DOMAIN_USER ,DOMAIN_CLIENT ); +#endif }
arch/arm/mm/nommu.c +2 -0
@@ -19,12 +19,14 @@void __init arm_mm_memblock_reserve (void ) { +#ifndef CONFIG_CPU_V7M /* * Register the exception vector page. * some architectures which the DRAM is the exception vector to trap, * alloc_page breaks with error, although it is not NULL, but "0." */ memblock_reserve (CONFIG_VECTORS_BASE ,PAGE_SIZE ); +#endif }void __init sanity_check_meminfo (void )
arch/arm/mm/proc-v7m.S new file +178 -0
178 lines not on this page · raw message
Signature · 1 line
1.7.8.3
RFC PATCH 6/11 Cortex-M3: Add base support for Cortex-M3
2012/1/22 Uwe Kleine-K?nig <[email protected]>:
Quoted 11 lines
arch/arm/kernel/head-common.S +0
-0@@ -100,7 +100,7 @@ __mmap_switched:? ? ? ?str ? ? r2, [r6] ? ? ? ? ? ? ? ? ? ? ? ?@ Save atags pointer ? ? ? ?cmp ? ? r7, #0
? ? ? ?bicne ? r4, r0, #CR_A ? ? ? ? ? ? ? ? ? @ Clear 'A' bit
- ? ? ? stmneia r7, {r0, r4} ? ? ? ? ? ? ? ? ? ?@ Save control register values
+ ? ? ? stmiane r7, {r0, r4} ? ? ? ? ? ? ? ? ? ?@ Save control register values ? ? ? ?b ? ? ?start_kernel
?ENDPROC(__mmap_switched)
This fixes one of previous patches, doesn't it?
Best Regards,
Micha? Miros?aw
RFC PATCH 6/11 Cortex-M3: Add base support for Cortex-M3
Hello Micha?,
Quoted 14 lines · Micha? Miros?aw
2012/1/22 Uwe Kleine-K?nig <[email protected]>:
Quoted 11 lines
arch/arm/kernel/head-common.S +0
-0@@ -100,7 +100,7 @@ __mmap_switched:? ? ? ?str ? ? r2, [r6] ? ? ? ? ? ? ? ? ? ? ? ?@ Save atags pointer ? ? ? ?cmp ? ? r7, #0
? ? ? ?bicne ? r4, r0, #CR_A ? ? ? ? ? ? ? ? ? @ Clear 'A' bit
- ? ? ? stmneia r7, {r0, r4} ? ? ? ? ? ? ? ? ? ?@ Save control register values
+ ? ? ? stmiane r7, {r0, r4} ? ? ? ? ? ? ? ? ? ?@ Save control register values ? ? ? ?b ? ? ?start_kernel
?ENDPROC(__mmap_switched)This fixes one of previous patches, doesn't it?
Thanks for noticing, and no, stmiane is an undefined instruction, but only the non-thumb build barfs on that. It seems my conflict resolution failed somehow :-(. I fixed it now.
Thanks
Uwe
Signature · 2 lines
Pengutronix e.K. | Uwe Kleine-K?nig | Industrial Linux Solutions | http://www.pengutronix.de/ |
RFC PATCH 7/11 Cortex-M3: Add support for exception handling
In reply to Uwe Kleine-KönigFrom: Catalin Marinas <[email protected]>
This patch implements the exception handling for the ARMv7-M architecture (pretty different from the A or R profiles).
[ukleinek: small adaptions, e.g. use show_regs instead of __show_regs in invalid_entry]
--- arch/arm/kernel/entry-common.S | 18 +++++- arch/arm/kernel/entry-header.S | 94 ++++++++++++++++++++++++++++- arch/arm/kernel/entry-v7m.S | 131 ++++++++++++++++++++++++++++++++++++++++ arch/arm/kernel/process.c | 8 +++ 4 files changed, 249 insertions(+), 2 deletions(-) create mode 100644 arch/arm/kernel/entry-v7m.S
arch/arm/kernel/entry-common.S +17 -1
@@ -43,7 +43,13 @@ ret_fast_syscall: * Ok, we need to do extra processing, enter the slow path. */ fast_work_pending: +#ifdef CONFIG_CPU_V7M + @ S_R0 not at the beginning of struct pt_regs + add sp, #S_OFF + str r0, [sp, #S_R0] @ returned r0 +#else str r0, [sp, #S_R0+S_OFF]! @ returned r0 +#endif work_pending: tst r1, #_TIF_NEED_RESCHED bne work_resched
@@ -342,6 +348,9 @@ ENDPROC(ftrace_stub) .align 5 ENTRY(vector_swi) +#ifdef CONFIG_CPU_V7M + v7m_exception_entry +#else sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ Calling r0 - r12 ARM( add r8, sp, #S_PC )
@@ -351,6 +360,7 @@ ENTRY(vector_swi) mrs r8, spsr @ called from non-FIQ mode, so ok. str lr, [sp, #S_PC] @ Save calling PC str r8, [sp, #S_PSR] @ Save CPSR +#endif str r0, [sp, #S_OLD_R0] @ Save OLD_R0 zero_fp
@@ -470,14 +480,20 @@ __sys_trace: adr lr, BSYM(__sys_trace_return) @ return address mov scno, r0 @ syscall number (possibly new) - add r1, sp, #S_R0 + S_OFF @ pointer to regs + add r1, sp, #S_OFF @ pointer to regs cmp scno, #NR_syscalls @ check upper syscall limit ldmccia r1, {r0 - r3} @ have to reload r0 - r3 ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine b 2b __sys_trace_return: +#ifdef CONFIG_CPU_V7M + @ S_R0 not at the beginning of struct pt_regs + add sp, #S_OFF + str r0, [sp, #S_R0] @ save returned r0 +#else str r0, [sp, #S_R0 + S_OFF]! @ save returned r0 +#endif mov r2, scno mov r1, sp mov r0, #1 @ trace exit [IP = 1]
arch/arm/kernel/entry-header.S +93 -1
118 lines not on this page · raw message
arch/arm/kernel/entry-v7m.S new file +131 -0
131 lines not on this page · raw message
arch/arm/kernel/process.c +8 -0
@@ -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 ); }
Signature · 1 line
1.7.8.3
RFC PATCH 8/11 Cortex-M3: Add NVIC support
In reply to Uwe Kleine-KönigFrom: Catalin Marinas <[email protected]>
This patch implements the NVIC (interrupt controller) support for Cortex-M3.
---
Actually it should be able to share much code with/use arch/arm/common/gic.c, but I didn't manage to get it up.
My problem is that I need hardware irq 13 but in gic.c hw_irq is set to at least 16. I guess I didn't understood something correctly and would be glad to get a tip who to fix that.
--- arch/arm/common/Kconfig | 3 + arch/arm/common/Makefile | 1 + arch/arm/common/nvic.c | 98 ++++++++++++++++++++++++++++++++++ arch/arm/include/asm/hardware/nvic.h | 34 ++++++++++++ 4 files changed, 136 insertions(+), 0 deletions(-) create mode 100644 arch/arm/common/nvic.c create mode 100644 arch/arm/include/asm/hardware/nvic.h
arch/arm/common/Kconfig +3 -0
@@ -21,6 +21,9 @@ config ARM_VIC_NR The maximum number of VICs available in the system, for power management. +config ARM_NVIC + bool + config ICST bool
arch/arm/common/Makefile +1 -0
@@ -4,6 +4,7 @@ obj-$(CONFIG_ARM_GIC) += gic.o obj-$(CONFIG_ARM_VIC) += vic.o +obj-$(CONFIG_ARM_NVIC) += nvic.o obj-$(CONFIG_ICST) += icst.o obj-$(CONFIG_PL330) += pl330.o obj-$(CONFIG_SA1111) += sa1111.o
arch/arm/common/nvic.c new file +98 -0
98 lines not on this page · raw message
arch/arm/include/asm/hardware/nvic.h new file +34 -0
@@ -0,0 +1,34 @@ +/* +* linux/include/asm-arm/hardware/nvic.h +* +* Copyright (C) 2008 ARM Limited, All Rights Reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +*/ +#ifndef __ASM_ARM_HARDWARE_NVIC_H +#define __ASM_ARM_HARDWARE_NVIC_H + +#include <linux/compiler.h> + +#define V7M_SCS 0xe000e000 +#define NVIC_INTR_CTRL (V7M_SCS + 0x004) +#define NVIC_SYSTICK_CTRL (V7M_SCS + 0x010) +#define NVIC_SYSTICK_RELOAD (V7M_SCS + 0x014) +#define NVIC_SYSTICK_CURRENT (V7M_SCS + 0x018) +#define NVIC_SYSTICK_CALIBRATION (V7M_SCS + 0x01c) +#define NVIC_SET_ENABLE (V7M_SCS + 0x100) +#define NVIC_CLEAR_ENABLE (V7M_SCS + 0x180) +#define NVIC_SET_PENDING (V7M_SCS + 0x200) +#define NVIC_CLEAR_PENDING (V7M_SCS + 0x280) +#define NVIC_ACTIVE_BIT (V7M_SCS + 0x300) +#define NVIC_PRIORITY (V7M_SCS + 0x400) +#define NVIC_INTR_CTRL_STATE (V7M_SCS + 0xd04) +#define NVIC_SOFTWARE_INTR (V7M_SCS + 0xf00) + +#ifndef __ASSEMBLY__ +void nvic_init (void ); +#endif + +#endif
Signature · 1 line
1.7.8.3
RFC PATCH 8/11 Cortex-M3: Add NVIC support
Hello,
Quoted 8 lines · Uwe Kleine-K?nig
From: Catalin Marinas <[email protected]>
This patch implements the NVIC (interrupt controller) support for Cortex-M3.
[ukleinek: use a raw spinlock]Signed-off-by Catalin Marinas <[email protected]>Signed-off-by Uwe Kleine-K?nig <[email protected]>
Quoted 7 lines
---
Actually it should be able to share much code with/usearch/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.chw_irqis set to at least 16. I guess I didn't understood something correctly and would be glad to get a tip who to fix that.
s/who/how/ of course.
I added a few people to Cc that recently touched arch/arm/common/gic.c.
Can anybody help?
Best regards
Uwe
Signature · 2 lines
Pengutronix e.K. | Uwe Kleine-K?nig | Industrial Linux Solutions | http://www.pengutronix.de/ |
RFC PATCH 9/11 Cortex-M3: Allow the building of Cortex-M3 kernel port
In reply to Uwe Kleine-KönigFrom: Catalin Marinas <[email protected]>
This patch modifies the required Kconfig and Makefile files to allow the building of kernel for Cortex-M3.
[ukleinek: don't make CPU_V7M user visible]
--- arch/arm/Kconfig | 2 +- arch/arm/Kconfig-nommu | 2 +- arch/arm/Makefile | 1 + arch/arm/kernel/Makefile | 8 +++++++- arch/arm/mm/Kconfig | 24 +++++++++++++++++++++++- arch/arm/mm/Makefile | 1 + 6 files changed, 34 insertions(+), 4 deletions(-)
arch/arm/Kconfig +1 -1
@@ -1599,7 +1599,7 @@ config HZ config THUMB2_KERNEL bool "Compile the kernel in Thumb-2 mode (EXPERIMENTAL)" - depends on CPU_V7 && !CPU_V6 && !CPU_V6K && EXPERIMENTAL + depends on (CPU_V7 || CPU_V7M) && !CPU_V6 && !CPU_V6K && EXPERIMENTAL select AEABI select ARM_ASM_UNIFIED select ARM_UNWIND
arch/arm/Kconfig-nommu +1 -1
@@ -28,7 +28,7 @@ config FLASH_SIZE config PROCESSOR_ID hex 'Hard wire the processor ID' default 0x00007700 - depends on !CPU_CP15 + depends on !(CPU_CP15 || CPU_V7M) help If processor has no CP15 register, this processor ID is used instead of the auto-probing which utilizes the register.
arch/arm/Makefile +1 -0
@@ -57,6 +57,7 @@ comma = , # Note that GCC does not numerically define an architecture version # macro, but instead defines a whole series of macros which makes # testing for a specific architecture or later rather impossible. +arch-$(CONFIG_CPU_32v7M) :=-D__LINUX_ARM_ARCH__=7 -march=armv7-m -Wa,-march=armv7-m arch-$(CONFIG_CPU_32v7) :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7-a,-march=armv5t -Wa$(comma)-march=armv7-a) arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6) # Only override the compiler option if ARMv6. The ARMv6K extensions are
arch/arm/kernel/Makefile +7 -1
@@ -13,10 +13,16 @@ CFLAGS_REMOVE_return_address.o = -pg # Object file lists. -obj-y := elf.o entry-armv.o entry-common.o irq.o opcodes.o \ +obj-y := elf.o entry-common.o irq.o opcodes.o \ process.o ptrace.o return_address.o setup.o signal.o \ sys_arm.o stacktrace.o time.o traps.o +ifeq ($(CONFIG_CPU_V7M),y) +obj-y += entry-v7m.o +else +obj-y += entry-armv.o +endif + obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += compat.o obj-$(CONFIG_LEDS) += leds.o
arch/arm/mm/Kconfig +23 -1
@@ -429,6 +429,18 @@ config CPU_V7 select CPU_COPY_V6 if MMU select CPU_TLB_V7 if MMU +# ARMv7 +config CPU_V7M + bool + select THUMB2_KERNEL + select ARM_THUMB + select CPU_32v7M + select CPU_32v6K + select CPU_ABRT_NOMMU + select CPU_PABRT_LEGACY + select CPU_CACHE_V7M + select CPU_CACHE_VIPT + # Figure out what processor architecture version we should be using. # This defines the compiler instruction set which depends on the machine type. config CPU_32v3
@@ -466,6 +478,9 @@ config CPU_32v6K config CPU_32v7 bool +config CPU_32v7M + bool + # The abort model config CPU_ABRT_NOMMU bool
@@ -519,6 +534,9 @@ config CPU_CACHE_V6 config CPU_CACHE_V7 bool +config CPU_CACHE_V7M + bool + config CPU_CACHE_VIVT bool
@@ -648,7 +666,11 @@ config ARCH_DMA_ADDR_T_64BIT config ARM_THUMB bool "Support Thumb user binaries" - depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_V6 || CPU_V6K || CPU_V7 || CPU_FEROCEON + depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || \ + CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || \ + CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || \ + CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_V6 || CPU_V6K || CPU_V7 || \ + CPU_FEROCEON || CPU_V7M default y help Say Y if you want to include kernel support for running user space
arch/arm/mm/Makefile +1 -0
@@ -92,6 +92,7 @@ obj-$(CONFIG_CPU_FEROCEON) += proc-feroceon.o obj-$(CONFIG_CPU_V6) += proc-v6.o obj-$(CONFIG_CPU_V6K) += proc-v6.o obj-$(CONFIG_CPU_V7) += proc-v7.o +obj-$(CONFIG_CPU_V7M) += proc-v7m.o AFLAGS_proc-v6.o :=-Wa,-march=armv6 AFLAGS_proc-v7.o :=-Wa,-march=armv7-a
Signature · 1 line
1.7.8.3
RFC PATCH 9/11 Cortex-M3: Allow the building of Cortex-M3 kernel port
2012/1/22 Uwe Kleine-K?nig <[email protected]>:
[...]
Quoted 11 lines
arch/arm/kernel/Makefile +0
-0@@ -13,10 +13,16 @@ CFLAGS_REMOVE_return_address.o = -pg?# Object file lists.
arch/arm/kernel/Makefile +1
-1-obj-y ? ? ? ? ?:= elf.o entry-armv.o entry-common.o irq.o opcodes.o \ +obj-y ? ? ? ? ?:= elf.o entry-common.o irq.o opcodes.o \? ? ? ? ? ? ? ? ? process.o ptrace.o return_address.o setup.o signal.o \
? ? ? ? ? ? ? ? ? sys_arm.o stacktrace.o time.o traps.o
arch/arm/kernel/Makefile CFLAGS_REMOVE_return_address.o = -pg · line 25
Quoted 6 lines
arch/arm/kernel/Makefile +6
-0+ifeq ($(CONFIG_CPU_V7M),y) +obj-y ? ? ? ? ?+= entry-v7m.o +else +obj-y ? ? ? ? ?+= entry-armv.o +endif +
Maybe something shorter, like this? '-)
obj-$(CONFIG_CPU_V7M) += entry-v7m.o
obj-$(if $(CONFIG_CPU_V7M),,y) += entry-armv.o
Best Regards,
Micha? Miros?aw
RFC PATCH 9/11 Cortex-M3: Allow the building of Cortex-M3 kernel port
Quoted 22 lines · Micha? Miros?aw
2012/1/22 Uwe Kleine-K?nig <[email protected]>:
[...]Quoted 11 lines
arch/arm/kernel/Makefile +0
-0@@ -13,10 +13,16 @@ CFLAGS_REMOVE_return_address.o = -pg?# Object file lists.
arch/arm/kernel/Makefile +1
-1-obj-y ? ? ? ? ?:= elf.o entry-armv.o entry-common.o irq.o opcodes.o \ +obj-y ? ? ? ? ?:= elf.o entry-common.o irq.o opcodes.o \? ? ? ? ? ? ? ? ? process.o ptrace.o return_address.o setup.o signal.o \
? ? ? ? ? ? ? ? ? sys_arm.o stacktrace.o time.o traps.oarch/arm/kernel/Makefile CFLAGS_REMOVE_return_address.o = -pg · line 25
Quoted 6 lines
arch/arm/kernel/Makefile +6
-0+ifeq ($(CONFIG_CPU_V7M),y) +obj-y ? ? ? ? ?+= entry-v7m.o +else +obj-y ? ? ? ? ?+= entry-armv.o +endif +Maybe something shorter, like this? '-)
Quoted 2 lines
obj-$(CONFIG_CPU_V7M) += entry-v7m.o
obj-$(if $(CONFIG_CPU_V7M),,y) += entry-armv.o
It's shorter, but for readability I prefer my version.
Best regards
Uwe
Signature · 2 lines
Pengutronix e.K. | Uwe Kleine-K?nig | Industrial Linux Solutions | http://www.pengutronix.de/ |
RFC PATCH 10/11 Cortex-M3: Add VFP support
In reply to Uwe Kleine-KönigFrom: Catalin Marinas <[email protected]>
This patch adds support for the ARMv7-M VFP extension. It uses the lazy state preservation mechanism available in hardware for the S0-S15 registers. The S16-S32 registers are saved at a context switch if the thread being scheduled out ever used the VFP. Similarly, the S16-S31 registers are restored if the thread being scheduled in ever used the VFP.
--- arch/arm/Kconfig | 7 +++ arch/arm/include/asm/fpstate.h | 3 + arch/arm/kernel/Makefile | 2 + arch/arm/kernel/asm-offsets.c | 3 + arch/arm/kernel/entry-header.S | 14 ++++++ arch/arm/kernel/vfp-m.c | 102 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 131 insertions(+), 0 deletions(-) create mode 100644 arch/arm/kernel/vfp-m.c
arch/arm/Kconfig +7 -0
@@ -2227,6 +2227,13 @@ config NEON Say Y to include support code for NEON, the ARMv7 Advanced SIMD Extension. +config VFPM + bool "ARMv7-M VFP Extension support" + depends on CPU_V7M + help + Say Y to include support for the ARMv7-M VFP Extension + (single-precision floating point hardware). + endmenu menu "Userspace binary formats"
arch/arm/include/asm/fpstate.h +3 -0
@@ -43,6 +43,9 @@ struct vfp_hard_struct {#ifdef CONFIG_SMP __u32 cpu;#endif +#ifdef CONFIG_VFPM +__u32 clean; +#endif };union vfp_state {
arch/arm/kernel/Makefile +2 -0
@@ -81,6 +81,8 @@ obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt obj-$(CONFIG_ARM_CPU_TOPOLOGY) += topology.o +obj-$(CONFIG_VFPM) += vfp-m.o + ifneq ($(CONFIG_ARCH_EBSA110),y) obj-y += io.o endif
arch/arm/kernel/asm-offsets.c +3 -0
@@ -60,6 +60,9 @@ int main(void)DEFINE (TI_TP_VALUE , offsetof(struct thread_info , tp_value));DEFINE (TI_FPSTATE , offsetof(struct thread_info , fpstate));DEFINE (TI_VFPSTATE , offsetof(struct thread_info , vfpstate)); +#ifdef CONFIG_VFPM + DEFINE(TI_VFPSTATE_CLEAN, offsetof(struct thread_info, vfpstate.hard.clean)); +#endif #ifdef CONFIG_SMP DEFINE(VFP_CPU, offsetof(union vfp_state, hard.cpu));#endif
arch/arm/kernel/entry-header.S +14 -0
@@ -72,7 +72,15 @@ */ .macro v7m_exception_entry cpsid i +#ifdef CONFIG_VFPM + get_thread_info r0 + and r1, lr, #1 << 4 @ VFP clean state + str r1, [r0, #TI_VFPSTATE_CLEAN] +#endif cmp lr, #0xfffffffd @ check the return stack +#ifdef CONFIG_VFPM + cmpne lr, #0xffffffed +#endif beq 1f @ exception on process stack add r12, sp, #32 @ MSP before exception stmdb sp!, {r4-r12, lr} @ push unsaved registers
@@ -90,6 +98,9 @@ .macro v7m_exception_fast_exit ldmia sp!, {r4-r12, lr} @ restore previously saved state cmp lr, #0xfffffffd @ check the return stack +#ifdef CONFIG_VFPM + cmpne lr, #0xffffffed +#endif addeq sp, #32 @ returning to PSP, just restore MSP cpsie i bx lr
@@ -99,6 +110,9 @@ cpsid i ldr lr, [sp, #S_EXC_LR] @ read exception LR cmp lr, #0xfffffffd @ check the return stack +#ifdef CONFIG_VFPM + cmpne lr, #0xffffffed +#endif beq 1f @ returning to PSP @ Prepare the MSP stack ldmia sp, {r4-r11} @ restore previously saved state
arch/arm/kernel/vfp-m.c new file +102 -0
102 lines not on this page · raw message
Signature · 1 line
1.7.8.3
RFC PATCH 11/11 HACK! ARM: no, we don't enter in ARM
In reply to Uwe Kleine-König... as a Cortex-M3 can only do Thumb-2 ...
---
This probably needs a new Kconfig symbol as THUMB2_KERNEL doesn't have the right meaning. Something like "CPU_THUMB_ONLY"?
--- arch/arm/kernel/head-nommu.S | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-)
arch/arm/kernel/head-nommu.S +4 -3
@@ -32,13 +32,14 @@ * numbers for r1. * */ - .arm + + @.arm __HEAD ENTRY(stext) - THUMB( adr r9, BSYM(1f) ) @ Kernel is always entered in ARM. - THUMB( bx r9 ) @ If this is a Thumb-2 kernel, + @THUMB( adr r9, BSYM(1f) ) @ Kernel is always entered in ARM. + @THUMB( bx r9 ) @ If this is a Thumb-2 kernel, THUMB( .thumb ) @ switch to Thumb now. THUMB(1: )
Signature · 1 line
1.7.8.3
cover Cortex-M3 support
In reply to Uwe Kleine-KönigQuoted 11 lines · Uwe Kleine-K?nig
this series is mostly a port of patches done by Catalin Marinas for 2.6.33. It's based on 3.3-rc1. There are still a few rough edges and I'm sure I'm not aware of all of them as this deep architecture stuff is mostly news for me. Some things are noted in the respective patches, I'm sure you can find more.
My target machine is the EFM32 Giant Gecko by Energy Micro and my complete tree can be found at
git://git.pengutronix.de/git/ukl/linux.gitefm32
Quoted 7 lines
(with a gitweb being available at
http://git.pengutronix.de/?p=ukl/linux.git;a=shortlog;h=efm32).
I look forward to your comments.
I didn't get much comments apart from a few trivial ones. I'd like to plan how to go forward here.
Catalin, Russell, I guess it's just lack of time on your side that you didn't comment?
There are a few things to fix and follow up (e.g. platform support, ftrace, adapt unwinding to the v7m model), but I first want to see the base patches in before I invest the time to address these.
Best regards
Uwe
Signature · 2 lines
Pengutronix e.K. | Uwe Kleine-K?nig | Industrial Linux Solutions | http://www.pengutronix.de/ |
cover Cortex-M3 support
Quoted 22 lines · Uwe Kleine-K?nig
Quoted 11 lines · Uwe Kleine-K?nig
this series is mostly a port of patches done by Catalin Marinas for 2.6.33. It's based on 3.3-rc1. There are still a few rough edges and I'm sure I'm not aware of all of them as this deep architecture stuff is mostly news for me. Some things are noted in the respective patches, I'm sure you can find more.
My target machine is the EFM32 Giant Gecko by Energy Micro and my complete tree can be found at
git://git.pengutronix.de/git/ukl/linux.gitefm32Quoted 7 lines
(with a gitweb being available at
http://git.pengutronix.de/?p=ukl/linux.git;a=shortlog;h=efm32).
I look forward to your comments.
I didn't get much comments apart from a few trivial ones. I'd like to plan how to go forward here.
Quoted 6 lines
Catalin, Russell, I guess it's just lack of time on your side that you didn't comment?
There are a few things to fix and follow up (e.g. platform support, ftrace, adapt unwinding to the v7m model), but I first want to see the base patches in before I invest the time to address these.
I improved a few things, most notably I fixed a stack overflow. Other than that the following changes are included, too:
- update to 3.3-rc3
- only check bit 3 of lr to determine which mode the machine was in when the current exception triggered
- several updates to the efm32 platform (that should IMHO only go in when the M3 support is available in mainline)
I'd be really happy to get some feedback on Catalin's and my patches and will repost the patches I think are mature enough to go in for a start.
The updated and complete stack is available from the URLs above.
Best regards
Uwe
Signature · 2 lines
Pengutronix e.K. | Uwe Kleine-K?nig | Industrial Linux Solutions | http://www.pengutronix.de/ |
PATCH 1/5 ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15
--- arch/arm/include/asm/system.h | 2 ++ arch/arm/kernel/entry-armv.S | 4 ++++ arch/arm/kernel/head-common.S | 10 ++++++++-- arch/arm/kernel/setup.c | 8 ++++++-- arch/arm/mm/alignment.c | 6 ++++++ arch/arm/mm/mmu.c | 8 +++++++- 6 files changed, 33 insertions(+), 5 deletions(-)
arch/arm/include/asm/system.h +2 -0
@@ -185,6 +185,7 @@ extern unsigned int user_debug;#define set_mb (var, value) do { var = value; smp_mb(); } while (0)#define nop () __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t"); +#ifdef CONFIG_CPU_CP15 extern unsigned long cr_no_alignment;/* defined in entry-armv.S */ extern unsigned long cr_alignment;/* defined in entry-armv.S */
@@ -224,6 +225,7 @@ static inline void set_copro_access(unsigned int val) : : "r" (val) : "cc"); isb(); } +#endif /* * switch_mm() may do a full cache flush over the context switch,
arch/arm/kernel/entry-armv.S +4 -0
@@ -314,8 +314,10 @@ __pabt_svc: ENDPROC(__pabt_svc) .align 5 +#ifdef CONFIG_CPU_CP15 .LCcralign: .word cr_alignment +#endif #ifdef MULTI_DABORT .LCprocfns: .word processor
@@ -1146,12 +1148,14 @@ __vectors_end: .data +#ifdef CONFIG_CPU_CP15 .globl cr_alignment .globl cr_no_alignment cr_alignment: .space 4 cr_no_alignment: .space 4 +#endif #ifdef CONFIG_MULTI_IRQ_HANDLER .globl handle_arch_irq
arch/arm/kernel/head-common.S +8 -2
@@ -98,8 +98,10 @@ __mmap_switched: str r9, [r4] @ Save processor ID str r1, [r5] @ Save machine type str r2, [r6] @ Save atags pointer - bic r4, r0, #CR_A @ Clear 'A' bit - stmia r7, {r0, r4} @ Save control register values + cmp r7, #0 + itt ne + bicne r4, r0, #CR_A @ Clear 'A' bit + stmneia r7, {r0, r4} @ Save control register values b start_kernel ENDPROC(__mmap_switched)
@@ -113,7 +115,11 @@ __mmap_switched_data: .long processor_id @ r4 .long __machine_arch_type @ r5 .long __atags_pointer @ r6 +#ifdef CONFIG_CPU_CP15 .long cr_alignment @ r7 +#else + .long 0 +#endif .long init_thread_union + THREAD_START_SP @ sp .size __mmap_switched_data, . - __mmap_switched_data
arch/arm/kernel/setup.c +6 -2
@@ -472,9 +472,13 @@ static void __init setup_processor(void) cpu_cache = *list->cache;#endif -printk ("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n" , +printk ("CPU: %s [%08x] revision %d (ARMv%s)" , cpu_name,read_cpuid_id (),read_cpuid_id () &15 , - proc_arch[cpu_architecture ()], cr_alignment); + proc_arch[cpu_architecture ()]); + +#ifdef CONFIG_CPU_CP15 +printk (KERN_CONT ", cr=%08lx\n" , cr_alignment); +#endif snprintf (init_utsname ()->machine, __NEW_UTS_LEN +1 ,"%s%c" , list->arch_name,ENDIANNESS );
arch/arm/mm/alignment.c +6 -0
@@ -89,7 +89,11 @@ core_param(alignment, ai_usermode, int, 0600);/* Return true if and only if the ARMv6 unaligned access model is in use. */ static bool cpu_is_v6_unaligned (void ) { +#ifdef CONFIG_CPU_CP15 return cpu_architecture () >= CPU_ARCH_ARMv6 && (cr_alignment &CR_U ); +#else +return 0 ; +#endif }static int safe_usermode (int new_usermode,bool warn)
@@ -961,12 +965,14 @@ static int __init alignment_init(void)return -ENOMEM ;#endif +#ifdef CONFIG_CPU_CP15 if (cpu_is_v6_unaligned ()) { cr_alignment &= ~CR_A ; cr_no_alignment &= ~CR_A ;set_cr (cr_alignment); ai_usermode =safe_usermode (ai_usermode, false); } +#endif hook_fault_code (FAULT_CODE_ALIGNMENT , do_alignment,SIGBUS ,BUS_ADRALN ,"alignment exception" );
arch/arm/mm/mmu.c +7 -1
@@ -109,8 +109,10 @@ static int __init early_cachepolicy(char *p)if (memcmp (p, cache_policies[i].policy, len) ==0 ) { cachepolicy = i; +#ifdef CONFIG_CPU_CP15 cr_alignment &= ~cache_policies[i].cr_mask; cr_no_alignment &= ~cache_policies[i].cr_mask; +#endif break ; } }
@@ -128,7 +130,9 @@ static int __init early_cachepolicy(char *p) cachepolicy =CPOLICY_WRITEBACK ; }flush_cache_all (); +#ifdef CONFIG_CPU_CP15 set_cr (cr_alignment); +#endif return 0 ; }early_param ("cachepolicy" , early_cachepolicy);
@@ -163,6 +167,7 @@ static int __init early_ecc(char *p)early_param ("ecc" , early_ecc);#endif +#ifdef CONFIG_CPU_CP15 static int __init noalign_setup (char *__unused) { cr_alignment &= ~CR_A ;
@@ -171,8 +176,9 @@ static int __init noalign_setup(char *__unused)return 1 ; }__setup ("noalign" , noalign_setup); +#endif -#ifndef CONFIG_SMP +#if !defined(CONFIG_SMP ) && defined(CONFIG_CPU_CP15 )void adjust_cr (unsigned long mask,unsigned long set) {unsigned long flags;
Signature · 1 line
1.7.9
PATCH 2/5 ARM: Add a printk loglevel modifier
This is a needed followup for
ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15
otherwise no newline is printed for !CONFIG_CPU_CP15
---
Should this be folded into the
ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15
patch? Or should it come before it?
--- arch/arm/kernel/setup.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/arm/kernel/setup.c +1 -1
@@ -325,7 +325,7 @@ static void __init cacheid_init(void) cacheid =CACHEID_VIVT ; } - printk("CPU: %s data cache, %s instruction cache\n", + printk(KERN_INFO "CPU: %s data cache, %s instruction cache\n", cache_is_vivt() ? "VIVT" : cache_is_vipt_aliasing() ? "VIPT aliasing" : cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown",
Signature · 1 line
1.7.9
PATCH 3/5 ARM: force branch instructions to use long distance encoding
In reply to Uwe Kleine-KönigThis fixes a linker error when the kernel image gets bigger than approx. 1 MiB.
This is done analogous to the change to head.S in commit
a75e524 (ARM: 6504/1: Thumb-2: Fix long-distance conditional branches in head.S for Thumb-2.)
--- arch/arm/kernel/head-nommu.S | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
arch/arm/kernel/head-nommu.S +1 -0
@@ -51,6 +51,7 @@ ENTRY(stext) #endif bl __lookup_processor_type @ r5=procinfo r9=cpuid movs r10, r5 @ invalid processor (r5=0)? + it eq beq __error_p @ yes, error 'p' adr lr, BSYM(__after_proc_init) @ return (PIC) address
Signature · 1 line
1.7.9
PATCH 4/5 ARM: Cortex-M3: Add base support for Cortex-M3
In reply to Uwe Kleine-KönigFrom: Catalin Marinas <[email protected]>
This patch adds the base support for the Cortex-M3 processor (ARMv7-M architecture). It consists of the corresponding arch/arm/mm/ files and various #ifdef's around the kernel. Exception handling is implemented by a subsequent patch.
[ukleinek: squash in some changes originating from commit
b5717ba (Cortex-M3: Add support for the Microcontroller Prototyping System)
from the v2.6.33-arm1 patch stack, port to post 3.2, drop zImage support, and a few cosmetic changes]
--- arch/arm/include/asm/assembler.h | 13 +++- arch/arm/include/asm/cputype.h | 3 + arch/arm/include/asm/glue-cache.h | 24 +++++ arch/arm/include/asm/glue-df.h | 8 ++ arch/arm/include/asm/glue-proc.h | 9 ++ arch/arm/include/asm/irqflags.h | 51 ++++++++++- arch/arm/include/asm/processor.h | 8 ++ arch/arm/include/asm/ptrace.h | 43 +++++++++- arch/arm/include/asm/system.h | 3 + arch/arm/kernel/asm-offsets.c | 3 + arch/arm/kernel/head-common.S | 2 +- arch/arm/kernel/head-nommu.S | 9 ++- arch/arm/kernel/setup.c | 13 +++- arch/arm/kernel/traps.c | 2 + arch/arm/mm/nommu.c | 2 + arch/arm/mm/proc-v7m.S | 178 +++++++++++++++++++++++++++++++++++++ 16 files changed, 362 insertions(+), 9 deletions(-) create mode 100644 arch/arm/mm/proc-v7m.S
arch/arm/include/asm/assembler.h +12 -1
@@ -133,7 +133,11 @@* assumes FIQs are enabled, and that the processor is in SVC mode. */ .macro save_and_disable_irqs, oldcpsr +#ifdef CONFIG_CPU_V7M + mrs \oldcpsr, primask +#else mrs \oldcpsr, cpsr +#endif disable_irq .endm
@@ -142,7 +146,11 @@* guarantee that this will preserve the flags. */ .macro restore_irqs_notrace, oldcpsr +#ifdef CONFIG_CPU_V7M + msr primask, \oldcpsr +#else msr cpsr_c, \oldcpsr +#endif .endm .macro restore_irqs, oldcpsr
@@ -221,7 +229,10 @@#endif .endm -#ifdef CONFIG_THUMB2_KERNEL +#if defined(CONFIG_CPU_V7M ) + .macro setmode, mode, reg + .endm +#elif defined(CONFIG_THUMB2_KERNEL ) .macro setmode, mode, reg mov \reg, #\mode msr cpsr_c, \reg
arch/arm/include/asm/cputype.h +3 -0
@@ -46,6 +46,9 @@ extern unsigned int processor_id; : "cc"); \ __val; \ }) +#elif defined(CONFIG_CPU_V7M ) +#define read_cpuid (reg) (*(unsigned int *)0xe000ed00) +#define read_cpuid_ext (reg) 0#else #define read_cpuid (reg) (processor_id)#define read_cpuid_ext (reg) 0
arch/arm/include/asm/glue-cache.h +24 -0
@@ -125,10 +125,34 @@//# endif #endif +#if defined(CONFIG_CPU_V7M ) +# ifdef _CACHE +# error "Multi-cache not supported on ARMv7-M" +# else +# define _CACHE nop +# endif +#endif +#if !defined(_CACHE) && !defined(MULTI_CACHE )#error Unknown cache maintenance model#endif +#ifndef __ASSEMBLER__ +static inline void nop_flush_icache_all (void ) { } +static inline void nop_flush_kern_cache_all (void ) { } +static inline void nop_flush_user_cache_all (void ) { } +static inline void nop_flush_user_cache_range (unsigned long a,unsigned long b,unsigned int c) { } + +static inline void nop_coherent_kern_range (unsigned long a,unsigned long b) { } +static inline void nop_coherent_user_range (unsigned long a,unsigned long b) { } +static inline void nop_flush_kern_dcache_area (void *a,size_t s) { } + +static inline void nop_dma_flush_range (const void *a,const void *b) { } + +static inline void nop_dma_map_area (const void *s,size_t l,int f) { } +static inline void nop_dma_unmap_area (const void *s,size_t l,int f) { } +#endif +#ifndef MULTI_CACHE #define __cpuc_flush_icache_all __glue(_CACHE,_flush_icache_all)#define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all)
arch/arm/include/asm/glue-df.h +8 -0
@@ -103,6 +103,14 @@# endif #endif +#ifdef CONFIG_CPU_ABRT_NOMMU +# ifdef CPU_DABORT_HANDLER +# define MULTI_DABORT 1 +# else +# define CPU_DABORT_HANDLER nommu_early_abort +# endif +#endif +#ifndef CPU_DABORT_HANDLER #error Unknown data abort handler type#endif
arch/arm/include/asm/glue-proc.h +9 -0
@@ -248,6 +248,15 @@# endif #endif +#ifdef CONFIG_CPU_V7M +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_v7m +# endif +#endif +#ifndef MULTI_CPU #define cpu_proc_init __glue(CPU_NAME,_proc_init)#define cpu_proc_fin __glue(CPU_NAME,_proc_fin)
arch/arm/include/asm/irqflags.h +49 -2
72 lines not on this page · raw message
arch/arm/include/asm/processor.h +8 -0
@@ -49,7 +49,15 @@ struct thread_struct {#ifdef CONFIG_MMU #define nommu_start_thread (regs) do { } while (0)#else +#ifndef CONFIG_CPU_V7M #define nommu_start_thread (regs) regs->ARM_r10 = current->mm->start_data +#else +#define nommu_start_thread (regs) do { \ + regs->ARM_r10 = current->mm->start_data; \ + regs->ARM_sp -= 32;/* exception return state */ \ + regs->ARM_EXC_lr =0xfffffffdL ;/* exception lr */ \ +} while (0) +#endif#endif #define start_thread (regs,pc,sp) \
arch/arm/include/asm/ptrace.h +42 -1
86 lines not on this page · raw message
arch/arm/include/asm/system.h +3 -0
@@ -13,6 +13,7 @@#define CPU_ARCH_ARMv5TEJ 7#define CPU_ARCH_ARMv6 8#define CPU_ARCH_ARMv7 9 +#define CPU_ARCH_ARMv7M 10/* * CR1 bits (CP#15 CR1)
@@ -232,7 +233,9 @@ static inline void set_copro_access(unsigned int val)* so enable interrupts over the context switch to avoid high * latency. */ +#ifndef CONFIG_CPU_V7M #define __ARCH_WANT_INTERRUPTS_ON_CTXSW +#endif /* * switch_to(prev, next) should switch from task `prev' to `next'
arch/arm/kernel/asm-offsets.c +3 -0
@@ -91,6 +91,9 @@ int main(void)DEFINE (S_PC , offsetof(struct pt_regs , ARM_pc));DEFINE (S_PSR , offsetof(struct pt_regs , ARM_cpsr));DEFINE (S_OLD_R0 , offsetof(struct pt_regs , ARM_ORIG_r0)); +#ifdef CONFIG_CPU_V7M +DEFINE (S_EXC_LR , offsetof(struct pt_regs , ARM_EXC_lr)); +#endif DEFINE (S_FRAME_SIZE ,sizeof (struct pt_regs ));BLANK ();#ifdef CONFIG_CACHE_L2X0
arch/arm/kernel/head-common.S +1 -1
@@ -118,7 +118,7 @@ __mmap_switched_data: #ifdef CONFIG_CPU_CP15 .long cr_alignment @ r7 #else - .long 0 + .long 0 @ r7 #endif .long init_thread_union + THREAD_START_SP @ sp .size __mmap_switched_data, . - __mmap_switched_data
arch/arm/kernel/head-nommu.S +6 -3
@@ -44,10 +44,13 @@ ENTRY(stext) setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode @ and irqs disabled -#ifndef CONFIG_CPU_CP15 - ldr r9, =CONFIG_PROCESSOR_ID -#else +#if defined(CONFIG_CPU_CP15) mrc p15, 0, r9, c0, c0 @ get processor id +#elif defined(CONFIG_CPU_V7M) + ldr r9, =0xe000ed00 @ CPUID register address + ldr r9, [r9] +#else + ldr r9, =CONFIG_PROCESSOR_ID #endif bl __lookup_processor_type @ r5=procinfo r9=cpuid movs r10, r5 @ invalid processor (r5=0)?
arch/arm/kernel/setup.c +12 -1
@@ -132,7 +132,9 @@ struct stack {u32 und[3 ]; }____cacheline_aligned ; +#ifndef CONFIG_CPU_V7M static struct stack stacks[NR_CPUS ]; +#endif char elf_platform[ELF_PLATFORM_SIZE ];EXPORT_SYMBOL (elf_platform);
@@ -212,7 +214,7 @@ static const char *proc_arch[] = {"5TEJ" ,"6TEJ" ,"7" , -"?(11)" , +"7M" ,"?(12)" ,"?(13)" , "?(14)",
@@ -221,6 +223,12 @@ static const char *proc_arch[] = { "?(17)", }; +#ifdef CONFIG_CPU_V7M +static int __get_cpu_architecture (void ) +{ +return CPU_ARCH_ARMv7M; +} +#else static int __get_cpu_architecture (void ) {int cpu_arch;
@@ -253,6 +261,7 @@ static int __get_cpu_architecture(void) return cpu_arch; } +#endif int __pure cpu_architecture (void ) {
@@ -380,6 +389,7 @@ static void __init feat_v6_fixup(void)*/ void cpu_init (void ) { +#ifndef CONFIG_CPU_V7M unsigned int cpu =smp_processor_id ();struct stack *stk = &stacks[cpu];
@@ -424,6 +434,7 @@ void cpu_init(void) "I" (offsetof(struct stack, und[0])), PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE) : "r14"); +#endif }int __cpu_logical_map[NR_CPUS ];
arch/arm/kernel/traps.c +2 -0
@@ -783,6 +783,7 @@ static void __init kuser_get_tls_init(unsigned long vectors)void __init early_trap_init (void ) { +#ifndef CONFIG_CPU_V7M #if defined(CONFIG_CPU_USE_DOMAINS )unsigned long vectors =CONFIG_VECTORS_BASE ;#else
@@ -818,4 +819,5 @@ void __init early_trap_init(void)flush_icache_range (vectors, vectors +PAGE_SIZE );modify_domain (DOMAIN_USER ,DOMAIN_CLIENT ); +#endif }
arch/arm/mm/nommu.c +2 -0
@@ -19,12 +19,14 @@void __init arm_mm_memblock_reserve (void ) { +#ifndef CONFIG_CPU_V7M /* * Register the exception vector page. * some architectures which the DRAM is the exception vector to trap, * alloc_page breaks with error, although it is not NULL, but "0." */ memblock_reserve (CONFIG_VECTORS_BASE ,PAGE_SIZE ); +#endif }void __init sanity_check_meminfo (void )
arch/arm/mm/proc-v7m.S new file +178 -0
178 lines not on this page · raw message
Signature · 1 line
1.7.9
PATCH 5/5 ARM: Cortex-M3: Add support for exception handling
In reply to Uwe Kleine-KönigFrom: Catalin Marinas <[email protected]>
This patch implements the exception handling for the ARMv7-M architecture (pretty different from the A or R profiles).
[ukleinek: small adaptions, e.g. use show_regs instead of __show_regs in invalid_entry, fix stack corruption in v7m_exception_fast_exit, check for bit 3 in exception lr only instead of explicit values]
--- arch/arm/kernel/entry-common.S | 18 +++++- arch/arm/kernel/entry-header.S | 94 ++++++++++++++++++++++++++++- arch/arm/kernel/entry-v7m.S | 131 ++++++++++++++++++++++++++++++++++++++++ arch/arm/kernel/process.c | 8 +++ 4 files changed, 249 insertions(+), 2 deletions(-) create mode 100644 arch/arm/kernel/entry-v7m.S
arch/arm/kernel/entry-common.S +17 -1
@@ -43,7 +43,13 @@ ret_fast_syscall: * Ok, we need to do extra processing, enter the slow path. */ fast_work_pending: +#ifdef CONFIG_CPU_V7M + @ S_R0 not at the beginning of struct pt_regs + add sp, #S_OFF + str r0, [sp, #S_R0] @ returned r0 +#else str r0, [sp, #S_R0+S_OFF]! @ returned r0 +#endif work_pending: tst r1, #_TIF_NEED_RESCHED bne work_resched
@@ -345,6 +351,9 @@ ENDPROC(ftrace_stub) .align 5 ENTRY(vector_swi) +#ifdef CONFIG_CPU_V7M + v7m_exception_entry +#else sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ Calling r0 - r12 ARM( add r8, sp, #S_PC )
@@ -354,6 +363,7 @@ ENTRY(vector_swi) mrs r8, spsr @ called from non-FIQ mode, so ok. str lr, [sp, #S_PC] @ Save calling PC str r8, [sp, #S_PSR] @ Save CPSR +#endif str r0, [sp, #S_OLD_R0] @ Save OLD_R0 zero_fp
@@ -473,14 +483,20 @@ __sys_trace: adr lr, BSYM(__sys_trace_return) @ return address mov scno, r0 @ syscall number (possibly new) - add r1, sp, #S_R0 + S_OFF @ pointer to regs + add r1, sp, #S_OFF @ pointer to regs cmp scno, #NR_syscalls @ check upper syscall limit ldmccia r1, {r0 - r3} @ have to reload r0 - r3 ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine b 2b __sys_trace_return: +#ifdef CONFIG_CPU_V7M + @ S_R0 not at the beginning of struct pt_regs + add sp, #S_OFF + str r0, [sp, #S_R0] @ save returned r0 +#else str r0, [sp, #S_R0 + S_OFF]! @ save returned r0 +#endif mov r2, scno mov r1, sp mov r0, #1 @ trace exit [IP = 1]
arch/arm/kernel/entry-header.S +93 -1
118 lines not on this page · raw message
arch/arm/kernel/entry-v7m.S new file +131 -0
131 lines not on this page · raw message
arch/arm/kernel/process.c +8 -0
@@ -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 ); }
Signature · 1 line
1.7.9
PATCH 5/5 ARM: Cortex-M3: Add support for exception handling
Quoted 4 lines · Uwe Kleine-K?nig
arch/arm/kernel/entry-header.S +4
-0+ .macro v7m_exception_entry + cpsid i + tst lr, #0x8 @ check the return stack + bne 1f @ exception on process stack
arch/arm/kernel/entry-header.S line 86
Quoted 10 lines
arch/arm/kernel/entry-header.S +10
-0+ add r12, sp, #32 @ MSP before exception + stmdb sp!, {r4-r12, lr} @ push unsaved registers + b 2f +1: + mrs r12, psp @ get the process stack + sub sp, #S_FRAME_SIZE + stmia sp, {r4-r12, lr} @ push unsaved registers + ldmia r12, {r0-r3, r6, r8-r10} @ load automatically saved registers + add r12, sp, #S_R0 + stmia r12, {r0-r3, r6, r8-r10} @ fill in the rest of struct pt_regs
I guess this means that pt_regs no longer contains r0..pc, cpsr, old_r0 on this Cortex-M ?
If so, that's a problem - tools like gdb, strace, and other user programs which make use of siginfo stuff all expect ARM to have a certain ptrace layout. This is major ABI breakage.
PATCH 5/5 ARM: Cortex-M3: Add support for exception handling
Hello Catalin,
Quoted 10 lines · Russell King - ARM Linux
Quoted 9 lines · Uwe Kleine-K?nig
arch/arm/kernel/entry-header.S +9
-0+ .macro v7m_exception_entry + cpsid i + tst lr, #0x8 @ check the return stack + bne 1f @ exception on process stack + add r12, sp, #32 @ MSP before exception + stmdb sp!, {r4-r12, lr} @ push unsaved registers + b 2f +1: + mrs r12, psp @ get the process stack
Quoted 8 lines
arch/arm/kernel/entry-header.S line 86
Quoted 5 lines
arch/arm/kernel/entry-header.S +5
-0+ sub sp, #S_FRAME_SIZE + stmia sp, {r4-r12, lr} @ push unsaved registers + ldmia r12, {r0-r3, r6, r8-r10} @ load automatically saved registers + add r12, sp, #S_R0 + stmia r12, {r0-r3, r6, r8-r10} @ fill in the rest of struct pt_regsI guess this means that
pt_regsno longer contains r0..pc, cpsr,old_r0on this Cortex-M ?
I stared at the code now for some time and I wonder if it wouldn't be the most nice solution to just do something like this on exception entry:
cpsid i
sub sp, #S_FRAME_SIZE
stmia sp, {r0-r12}
put_the_right_sp_to_sp[13]
put_lr_returnaddr_and_xPSR_from_right_stack_to_sp[14-16]For returning you could just do:
add sp, #S_FRAME_SIZE
cpsie i
bx lr
after fixing r0 on the right stack in case you need to return something.
The machine takes care to restore {r0-r3,r12,lr} and the remaining registers should be untouched as everything we called between entry and exit is AAPCS conformant.
This way we would even need one value less in pt_regs (namely orig_r0).
Does this make sense? (Note it's just before bedtime here, so it might not.)
Anyhow, I will try to implement that if I still think it could work after sleeping.
Quoted 3 lines
If so, that's a problem - tools like gdb, strace, and other user programs which make use of siginfo stuff all expect ARM to have a certain ptrace layout. This is major ABI breakage.
Best regards
Uwe
Signature · 2 lines
Pengutronix e.K. | Uwe Kleine-K?nig | Industrial Linux Solutions | http://www.pengutronix.de/ |
PATCH 5/5 ARM: Cortex-M3: Add support for exception handling
Hi Uwe,
2012/2/24 Uwe Kleine-K?nig <[email protected]>:
Quoted 17 lines · Russell King - ARM Linux
Quoted 16 lines · Uwe Kleine-K?nig
Quoted 14 lines
+ ? .macro ?v7m_exception_entry
+ ? cpsid ? i
+ ? tst ? ? lr, #0x8 ? ? ? ? ? ? ? ?@ check the return stack
+ ? bne ? ? 1f ? ? ? ? ? ? ? ? ? ? ?@ exception on process stack
+ ? add ? ? r12, sp, #32 ? ? ? ? ? ?@ MSP before exception
+ ? stmdb ? sp!, {r4-r12, lr} ? ? ? @ push unsaved registers
+ ? b ? ? ? 2f
+1:
+ ? mrs ? ? r12, psp ? ? ? ? ? ? ? ?@ get the process stack
+ ? sub ? ? sp, #S_FRAME_SIZE
+ ? stmia ? sp, {r4-r12, lr} ? ? ? ?@ push unsaved registers
+ ? ldmia ? r12, {r0-r3, r6, r8-r10} @ load automatically saved registers
+ ? add ? ? r12, sp, #S_R0
+ ? stmia ? r12, {r0-r3, r6, r8-r10} @ fill in the rest of structpt_regs
Quoted 2 lines
Quoted 2 lines
I guess this means that
pt_regsno longer contains r0..pc, cpsr,old_r0on this Cortex-M ?
Just to reply to Russell - yes, this part needs changing (could be the pt_regs saving or just the signal and trace code that copies them to user so that we preserve the ABI).
Quoted 10 lines
I stared at the code now for some time and I wonder if it wouldn't be the most nice solution to just do something like this on exception entry:
? ? ? ?cpsid ? i
? ? ? ?sub ? ? sp, #S_FRAME_SIZE
? ? ? ?stmia ? sp, {r0-r12}
? ? ? ?put_the_right_sp_to_sp[13]
? ? ? ?put_lr_returnaddr_and_xPSR_from_right_stack_to_sp[14-16]
Quoted 5 lines
For returning you could just do:
? ? ? ?add ? ? sp, #S_FRAME_SIZE
? ? ? ?cpsie ? i
? ? ? ?bx ? ? ?lr
For this kind of returning, do we actually change between Process and Handler stack?
But we still need to set the pt_regs to the user stack. The kernel would touch all of them if a signal is to be delivered (actually restoring them when returning from the signal handler).
Quoted 5 lines
after fixing r0 on the right stack in case you need to return something.
The machine takes care to restore {r0-r3,r12,lr} and the remaining registers should be untouched as everything we called between entry and exit is AAPCS conformant.
As I said, we have sys_sigreturn which modifies those registers.
Quoted 2 lines
Anyhow, I will try to implement that if I still think it could work after sleeping.
It's late here as well :). We'll see next week.
Signature · 1 line
Catalin
PATCH 5/5 ARM: Cortex-M3: Add support for exception handling
Quoted 3 lines · Catalin Marinas
Just to reply to Russell - yes, this part needs changing (could be the
pt_regssaving 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.
PATCH 5/5 ARM: Cortex-M3: Add support for exception handling
Quoted 9 lines · Russell King - ARM Linux
Quoted 3 lines · Catalin Marinas
Just to reply to Russell - yes, this part needs changing (could be the
pt_regssaving 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
PATCH 5/5 ARM: Cortex-M3: Add support for exception handling
In reply to Catalin MarinasQuoted 37 lines · Catalin Marinas
Hi Uwe,
2012/2/24 Uwe Kleine-K?nig <[email protected]>:
Quoted 17 lines · Russell King - ARM Linux
Quoted 16 lines · Uwe Kleine-K?nig
Quoted 14 lines
+ ? .macro ?v7m_exception_entry
+ ? cpsid ? i
+ ? tst ? ? lr, #0x8 ? ? ? ? ? ? ? ?@ check the return stack
+ ? bne ? ? 1f ? ? ? ? ? ? ? ? ? ? ?@ exception on process stack
+ ? add ? ? r12, sp, #32 ? ? ? ? ? ?@ MSP before exception
+ ? stmdb ? sp!, {r4-r12, lr} ? ? ? @ push unsaved registers
+ ? b ? ? ? 2f
+1:
+ ? mrs ? ? r12, psp ? ? ? ? ? ? ? ?@ get the process stack
+ ? sub ? ? sp, #S_FRAME_SIZE
+ ? stmia ? sp, {r4-r12, lr} ? ? ? ?@ push unsaved registers
+ ? ldmia ? r12, {r0-r3, r6, r8-r10} @ load automatically saved registers
+ ? add ? ? r12, sp, #S_R0
+ ? stmia ? r12, {r0-r3, r6, r8-r10} @ fill in the rest of structpt_regsQuoted 2 lines
Quoted 2 lines
I guess this means that
pt_regsno longer contains r0..pc, cpsr,old_r0on this Cortex-M ?Just to reply to Russell - yes, this part needs changing (could be the
pt_regssaving or just the signal and trace code that copies them to user so that we preserve the ABI).Quoted 10 lines
I stared at the code now for some time and I wonder if it wouldn't be the most nice solution to just do something like this on exception entry:
? ? ? ?cpsid ? i
? ? ? ?sub ? ? sp, #S_FRAME_SIZE
? ? ? ?stmia ? sp, {r0-r12}
? ? ? ?put_the_right_sp_to_sp[13]
? ? ? ?put_lr_returnaddr_and_xPSR_from_right_stack_to_sp[14-16]
Quoted 8 lines
Quoted 5 lines
For returning you could just do:
? ? ? ?add ? ? sp, #S_FRAME_SIZE
? ? ? ?cpsie ? i
? ? ? ?bx ? ? ?lrFor this kind of returning, do we actually change between Process and Handler stack?
According to ARMARM-v7-M when pc is written to 0xfXXXXXXX (with X denoting don't care) also the stack is restored.
Quoted 3 lines
But we still need to set the
pt_regsto the user stack. The kernel would touch all of them if a signal is to be delivered (actually restoring them when returning from the signal handler).
Ah, I thought only r0 might be changed. I will bear that in mind.
Thanks for your insights
Uwe
Signature · 2 lines
Pengutronix e.K. | Uwe Kleine-K?nig | Industrial Linux Solutions | http://www.pengutronix.de/ |
PATCH v2 4/5 Cortex-M3: Add base support for Cortex-M3
In reply to Catalin MarinasFrom: Catalin Marinas <[email protected]>
This patch adds the base support for the Cortex-M3 processor (ARMv7-M architecture). It consists of the corresponding arch/arm/mm/ files and various #ifdef's around the kernel. Exception handling is implemented by a subsequent patch.
[ukleinek: squash in some changes originating from commit
b5717ba (Cortex-M3: Add support for the Microcontroller Prototyping System)
from the v2.6.33-arm1 patch stack, port to post 3.2, drop zImage support, and a few cosmetic changes, rework to preserve layout of pt_regs]
--- arch/arm/include/asm/assembler.h | 13 +++- arch/arm/include/asm/cputype.h | 3 + arch/arm/include/asm/glue-cache.h | 24 +++++ arch/arm/include/asm/glue-df.h | 8 ++ arch/arm/include/asm/glue-proc.h | 9 ++ arch/arm/include/asm/irqflags.h | 51 +++++++++++- arch/arm/include/asm/processor.h | 8 ++ arch/arm/include/asm/ptrace.h | 21 ++++- arch/arm/include/asm/system.h | 3 + arch/arm/kernel/asm-offsets.c | 4 + arch/arm/kernel/head-common.S | 2 +- arch/arm/kernel/head-nommu.S | 9 ++- arch/arm/kernel/ptrace.c | 4 + arch/arm/kernel/setup.c | 13 +++- arch/arm/kernel/signal.c | 5 + arch/arm/kernel/traps.c | 2 + arch/arm/mm/nommu.c | 2 + arch/arm/mm/proc-v7m.S | 168 +++++++++++++++++++++++++++++++++++++ 18 files changed, 339 insertions(+), 10 deletions(-) create mode 100644 arch/arm/mm/proc-v7m.S
arch/arm/include/asm/assembler.h +12 -1
@@ -133,7 +133,11 @@* assumes FIQs are enabled, and that the processor is in SVC mode. */ .macro save_and_disable_irqs, oldcpsr +#ifdef CONFIG_CPU_V7M + mrs \oldcpsr, primask +#else mrs \oldcpsr, cpsr +#endif disable_irq .endm
@@ -142,7 +146,11 @@* guarantee that this will preserve the flags. */ .macro restore_irqs_notrace, oldcpsr +#ifdef CONFIG_CPU_V7M + msr primask, \oldcpsr +#else msr cpsr_c, \oldcpsr +#endif .endm .macro restore_irqs, oldcpsr
@@ -221,7 +229,10 @@#endif .endm -#ifdef CONFIG_THUMB2_KERNEL +#if defined(CONFIG_CPU_V7M ) + .macro setmode, mode, reg + .endm +#elif defined(CONFIG_THUMB2_KERNEL ) .macro setmode, mode, reg mov \reg, #\mode msr cpsr_c, \reg
arch/arm/include/asm/cputype.h +3 -0
@@ -46,6 +46,9 @@ extern unsigned int processor_id; : "cc"); \ __val; \ }) +#elif defined(CONFIG_CPU_V7M ) +#define read_cpuid (reg) (*(unsigned int *)0xe000ed00) +#define read_cpuid_ext (reg) 0#else #define read_cpuid (reg) (processor_id)#define read_cpuid_ext (reg) 0
arch/arm/include/asm/glue-cache.h +24 -0
@@ -125,10 +125,34 @@//# endif #endif +#if defined(CONFIG_CPU_V7M ) +# ifdef _CACHE +# error "Multi-cache not supported on ARMv7-M" +# else +# define _CACHE nop +# endif +#endif +#if !defined(_CACHE) && !defined(MULTI_CACHE )#error Unknown cache maintenance model#endif +#ifndef __ASSEMBLER__ +static inline void nop_flush_icache_all (void ) { } +static inline void nop_flush_kern_cache_all (void ) { } +static inline void nop_flush_user_cache_all (void ) { } +static inline void nop_flush_user_cache_range (unsigned long a,unsigned long b,unsigned int c) { } + +static inline void nop_coherent_kern_range (unsigned long a,unsigned long b) { } +static inline void nop_coherent_user_range (unsigned long a,unsigned long b) { } +static inline void nop_flush_kern_dcache_area (void *a,size_t s) { } + +static inline void nop_dma_flush_range (const void *a,const void *b) { } + +static inline void nop_dma_map_area (const void *s,size_t l,int f) { } +static inline void nop_dma_unmap_area (const void *s,size_t l,int f) { } +#endif +#ifndef MULTI_CACHE #define __cpuc_flush_icache_all __glue(_CACHE,_flush_icache_all)#define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all)
arch/arm/include/asm/glue-df.h +8 -0
@@ -103,6 +103,14 @@# endif #endif +#ifdef CONFIG_CPU_ABRT_NOMMU +# ifdef CPU_DABORT_HANDLER +# define MULTI_DABORT 1 +# else +# define CPU_DABORT_HANDLER nommu_early_abort +# endif +#endif +#ifndef CPU_DABORT_HANDLER #error Unknown data abort handler type#endif
arch/arm/include/asm/glue-proc.h +9 -0
@@ -248,6 +248,15 @@# endif #endif +#ifdef CONFIG_CPU_V7M +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_v7m +# endif +#endif +#ifndef MULTI_CPU #define cpu_proc_init __glue(CPU_NAME,_proc_init)#define cpu_proc_fin __glue(CPU_NAME,_proc_fin)
arch/arm/include/asm/irqflags.h +49 -2
72 lines not on this page · raw message
arch/arm/include/asm/processor.h +8 -0
@@ -49,7 +49,15 @@ struct thread_struct {#ifdef CONFIG_MMU #define nommu_start_thread (regs) do { } while (0)#else +#ifndef CONFIG_CPU_V7M #define nommu_start_thread (regs) regs->ARM_r10 = current->mm->start_data +#else +#define nommu_start_thread(regs) do { \ + regs->ARM_r10 = current->mm->start_data; \ + regs->ARM_sp -= 32; /* exception return state */ \ + regs->ARM_EXCRET = 0xfffffffdL; \ +} while (0) +#endif #endif #define start_thread (regs,pc,sp) \
arch/arm/include/asm/ptrace.h +19 -2
@@ -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 definedCONFIG_CPU_V7M +#define ARM_EXCRET uregs[17] +#else #define ARM_ORIG_r0 uregs[17] +#endif /* * The size of the user-visible VFP state as seen by PTRACE_GET/SETVFPREGS
@@ -165,6 +178,7 @@ struct pt_regs {*/ static inline int valid_user_regs (struct pt_regs *regs) { +#ifndef CONFIG_CPU_V7M unsigned long mode = regs->ARM_cpsr &MODE_MASK ;/*
@@ -187,6 +201,9 @@ static inline int valid_user_regs(struct pt_regs *regs) regs->ARM_cpsr |=USR_MODE ;return 0 ; +#else /* ifndef CONFIG_CPU_V7M */ +return 1 ; +#endif }static inline long regs_return_value (struct pt_regs *regs)
@@ -218,7 +235,7 @@ extern unsigned long profile_pc(struct pt_regs *regs);*/ #include <linux/stddef.h> #include <linux/types.h> -#define MAX_REG_OFFSET (offsetof(struct pt_regs, ARM_ORIG_r0)) +#define MAX_REG_OFFSET (offsetof(struct pt_regs, ARM_cpsr) + 4)extern int regs_query_register_offset (const char *name);extern const char *regs_query_register_name (unsigned int offset);
arch/arm/include/asm/system.h +3 -0
@@ -13,6 +13,7 @@#define CPU_ARCH_ARMv5TEJ 7#define CPU_ARCH_ARMv6 8#define CPU_ARCH_ARMv7 9 +#define CPU_ARCH_ARMv7M 10/* * CR1 bits (CP#15 CR1)
@@ -232,7 +233,9 @@ static inline void set_copro_access(unsigned int val)* so enable interrupts over the context switch to avoid high * latency. */ +#ifndef CONFIG_CPU_V7M #define __ARCH_WANT_INTERRUPTS_ON_CTXSW +#endif /* * switch_to(prev, next) should switch from task `prev' to `next'
arch/arm/kernel/asm-offsets.c +4 -0
@@ -90,7 +90,11 @@ int main(void)DEFINE (S_LR , offsetof(struct pt_regs , ARM_lr));DEFINE (S_PC , offsetof(struct pt_regs , ARM_pc));DEFINE (S_PSR , offsetof(struct pt_regs , ARM_cpsr)); +#ifdef CONFIG_CPU_V7M +DEFINE (S_EXCRET , offsetof(struct pt_regs , ARM_EXCRET)); +#else DEFINE (S_OLD_R0 , offsetof(struct pt_regs , ARM_ORIG_r0)); +#endif DEFINE (S_FRAME_SIZE ,sizeof (struct pt_regs ));BLANK ();#ifdef CONFIG_CACHE_L2X0
arch/arm/kernel/head-common.S +1 -1
@@ -118,7 +118,7 @@ __mmap_switched_data: #ifdef CONFIG_CPU_CP15 .long cr_alignment @ r7 #else - .long 0 + .long 0 @ r7 #endif .long init_thread_union + THREAD_START_SP @ sp .size __mmap_switched_data, . - __mmap_switched_data
arch/arm/kernel/head-nommu.S +6 -3
@@ -44,10 +44,13 @@ ENTRY(stext) setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode @ and irqs disabled -#ifndef CONFIG_CPU_CP15 - ldr r9, =CONFIG_PROCESSOR_ID -#else +#if defined(CONFIG_CPU_CP15) mrc p15, 0, r9, c0, c0 @ get processor id +#elif defined(CONFIG_CPU_V7M) + ldr r9, =0xe000ed00 @ CPUID register address + ldr r9, [r9] +#else + ldr r9, =CONFIG_PROCESSOR_ID #endif bl __lookup_processor_type @ r5=procinfo r9=cpuid movs r10, r5 @ invalid processor (r5=0)?
arch/arm/kernel/ptrace.c +4 -0
@@ -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 ), +#elseREG_OFFSET_NAME (ORIG_r0), +#endif REG_OFFSET_END, };
arch/arm/kernel/setup.c +12 -1
@@ -132,7 +132,9 @@ struct stack {u32 und[3 ]; }____cacheline_aligned ; +#ifndef CONFIG_CPU_V7M static struct stack stacks[NR_CPUS ]; +#endif char elf_platform[ELF_PLATFORM_SIZE ];EXPORT_SYMBOL (elf_platform);
@@ -212,7 +214,7 @@ static const char *proc_arch[] = {"5TEJ" ,"6TEJ" ,"7" , -"?(11)" , +"7M" ,"?(12)" ,"?(13)" , "?(14)",
@@ -221,6 +223,12 @@ static const char *proc_arch[] = { "?(17)", }; +#ifdef CONFIG_CPU_V7M +static int __get_cpu_architecture (void ) +{ +return CPU_ARCH_ARMv7M; +} +#else static int __get_cpu_architecture (void ) {int cpu_arch;
@@ -253,6 +261,7 @@ static int __get_cpu_architecture(void) return cpu_arch; } +#endif int __pure cpu_architecture (void ) {
@@ -380,6 +389,7 @@ static void __init feat_v6_fixup(void)*/ void cpu_init (void ) { +#ifndef CONFIG_CPU_V7M unsigned int cpu =smp_processor_id ();struct stack *stk = &stacks[cpu];
@@ -424,6 +434,7 @@ void cpu_init(void) "I" (offsetof(struct stack, und[0])), PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE) : "r14"); +#endif }int __cpu_logical_map[NR_CPUS ];
arch/arm/kernel/signal.c +5 -0
@@ -688,7 +688,12 @@ static void do_signal(struct pt_regs *regs, int syscall)case -ERESTARTNOHAND :case -ERESTARTSYS :case -ERESTARTNOINTR : +#ifdef CONFIG_CPU_V7M +pr_info ("%s: cannot restart yet!\n" , __func__); +while (1 ); +#else regs->ARM_r0 = regs->ARM_ORIG_r0; +#endif regs->ARM_pc = restart_addr;break ;case -ERESTART_RESTARTBLOCK :
arch/arm/kernel/traps.c +2 -0
@@ -783,6 +783,7 @@ static void __init kuser_get_tls_init(unsigned long vectors)void __init early_trap_init (void ) { +#ifndef CONFIG_CPU_V7M #if defined(CONFIG_CPU_USE_DOMAINS )unsigned long vectors =CONFIG_VECTORS_BASE ;#else
@@ -818,4 +819,5 @@ void __init early_trap_init(void)flush_icache_range (vectors, vectors +PAGE_SIZE );modify_domain (DOMAIN_USER ,DOMAIN_CLIENT ); +#endif }
arch/arm/mm/nommu.c +2 -0
@@ -19,12 +19,14 @@void __init arm_mm_memblock_reserve (void ) { +#ifndef CONFIG_CPU_V7M /* * Register the exception vector page. * some architectures which the DRAM is the exception vector to trap, * alloc_page breaks with error, although it is not NULL, but "0." */ memblock_reserve (CONFIG_VECTORS_BASE ,PAGE_SIZE ); +#endif }void __init sanity_check_meminfo (void )
arch/arm/mm/proc-v7m.S new file +168 -0
168 lines not on this page · raw message
Signature · 1 line
1.7.9.1
PATCH v2 5/5 Cortex-M3: Add support for exception handling
This patch implements the exception handling for the ARMv7-M architecture (pretty different from the A or R profiles).
Initially this based on a patch by Catalin Marinas but was completely reworked to use a pt_regs layout similar to the A profile.
Note this is broken in at least two ways:
- r0 isn't saved for signal restarting (should be easy)
- crashes early after reaching userspace.
---
Hello,
To save r0, I'd readd OLD_R0 at the end of pt_regs (plus one buffer word to get even alignment). Or would that already be unacceptable because it's an ABI change, too?
Anyhow, this is (once more :-) a great opportunity for you to blame me in public by pointing out why my machine crashes with this patch. But to be honest this time I wouldn't mind because hopefully after describing your findings I'd be able to fix the problem.
Best regards
Uwe
arch/arm/kernel/entry-common.S | 9 ++- arch/arm/kernel/entry-header.S | 149 +++++++++++++++++++++++++++++++++++++++- arch/arm/kernel/entry-v7m.S | 135 ++++++++++++++++++++++++++++++++++++ arch/arm/kernel/process.c | 8 ++ 4 files changed, 299 insertions(+), 2 deletions(-) create mode 100644 arch/arm/kernel/entry-v7m.S
arch/arm/kernel/entry-common.S +8 -1
@@ -345,6 +345,9 @@ ENDPROC(ftrace_stub) .align 5 ENTRY(vector_swi) +#ifdef CONFIG_CPU_V7M + v7m_exception_entry +#else sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ Calling r0 - r12 ARM( add r8, sp, #S_PC )
@@ -354,7 +357,11 @@ ENTRY(vector_swi) mrs r8, spsr @ called from non-FIQ mode, so ok. str lr, [sp, #S_PC] @ Save calling PC str r8, [sp, #S_PSR] @ Save CPSR +#endif +#if XXX + /* XXX: fixme: we need to preserve r0 somewhere for signal stuff */ str r0, [sp, #S_OLD_R0] @ Save OLD_R0 +#endif zero_fp /*
@@ -473,7 +480,7 @@ __sys_trace: adr lr, BSYM(__sys_trace_return) @ return address mov scno, r0 @ syscall number (possibly new) - add r1, sp, #S_R0 + S_OFF @ pointer to regs + add r1, sp, #S_OFF @ pointer to regs cmp scno, #NR_syscalls @ check upper syscall limit ldmccia r1, {r0 - r3} @ have to reload r0 - r3 ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
arch/arm/kernel/entry-header.S +148 -1
173 lines not on this page · raw message
arch/arm/kernel/entry-v7m.S new file +135 -0
135 lines not on this page · raw message
arch/arm/kernel/process.c +8 -0
@@ -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 ); }
Signature · 1 line
1.7.9.1
PATCH v2 5/5 Cortex-M3: Add support for exception handling
Quoted 3 lines · Uwe Kleine-K?nig
To save r0, I'd readd
OLD_R0at the end ofpt_regs(plus one buffer word to get even alignment). Or would that already be unacceptable because it's an ABI change, too?
If we preserve the first part of the pt_regs structure, we could add the exception return at the end (with two additional 32-bit words to preserve the 64-bit alignment).
arch/arm/kernel/entry-common.S __sys_trace: · line 483
Quoted 8 lines
arch/arm/kernel/entry-common.S +1
-1@@ -473,7 +480,7 @@ __sys_trace: adr lr, BSYM(__sys_trace_return) @ return address mov scno, r0 @ syscall number (possibly new) - add r1, sp, #S_R0 + S_OFF @ pointer to regs + add r1, sp, #S_OFF @ pointer to regs
This change is no longer needed since S_R0 is no 0.
arch/arm/kernel/entry-header.S line 29
Quoted 8 lines
arch/arm/kernel/entry-header.S +1
-1@@ -26,7 +26,7 @@ * The SWI code relies on the fact that R0 is at the bottom of the stack * (due to slow/fast restore user regs). */ -#if S_R0 != 0 +#if S_R0 != 0 && !defined(CONFIG_CPU_V7M)
Same here.
Quoted 24 lines
arch/arm/kernel/entry-header.S +24
-0+#ifdef CONFIG_CPU_V7M +/* + * ARMv7-M exception entry/exit macros. + * + * xPSR, ReturnAddress(), LR (R14), R12, R3, R2, R1, and R0 are + * automatically saved on the current stack (32 words) before + * switching to the exception stack (SP_main). + * + * If exception is taken while in user mode, SP_main is + * empty. Otherwise, SP_main is aligned to 64 bit automatically + * (CCR.STKALIGN set). + * + * Linux assumes that the interrupts are disabled when entering an + * exception handler and it may BUG if this is not the case. Interrupts + * are disabled during entry and reenabled in the exit macro. + * + * v7m_exception_fast_exit is used when returning from interrupts. + * + * v7m_exception_slow_exit is used when returning from SVC or PendSV. + * When returning to kernel mode, we don't return from exception. + */ + .macro v7m_exception_entry + cpsid i + sub sp, #S_FRAME_SIZE
arch/arm/kernel/entry-header.S line 80
Quoted 10 lines
arch/arm/kernel/entry-header.S +10
-0+ stmia sp, {r0-r12} + + @ set r0 to the location of the registers saved by the core during + @ exception entry. Depending on the mode the cpu was in when the + @ exception happend that is either on the main or the process stack. + @ Bit 2 of EXC_RETURN stored in the lr register specifies which stack + @ was used. + tst lr, #0x4 + mrsne r0, psp + addeq r0, sp, #S_FRAME_SIZE
Could we use some other registers here like r8-r12 so that we keep r0-r7 for syscall handling later and avoid another ldmia?
Quoted 4 lines
arch/arm/kernel/entry-header.S +4
-0+ add r0, r0, #20 @ skip over r0-r3, r12 + ldmia r0!, {r1-r3} @ load saved lr, return address and xPSR + + @ calculate the orignal stack pointer value.
arch/arm/kernel/entry-header.S line 95
Quoted 10 lines
arch/arm/kernel/entry-header.S +10
-0+ @ r0 currently points to the memory location just above the auto saved + @ xPSR. If the FP extension is implemented and bit 4 of EXC_RETURN is 0 + @ then space was allocated for FP state. That is space for 18 32-bit + @ values. (If FP extension is unimplemented, bit 4 is 1.) + @ Additionally the cpu might automatically 8-byte align the stack. Bit 9 + @ of the saved xPSR specifies if stack aligning took place. In this case + @ another 32-bit value is included in the stack. + + tst lr, #0x10 + addeq r0, r0, #576
I think you can ignore VFP for now. We could change it to do lazy save/restore and avoid the automatic state saving. If it does this while in kernel, it takes a bit of extra stack space.
arch/arm/kernel/entry-header.S line 101
Quoted 2 lines
arch/arm/kernel/entry-header.S +2
-0+ @ save original sp, lr, return address, xPSR and EXC_RETURN + add r12, sp, #52
Just use S_ARM_SP or whatever asm offsets, it's easier to read.
arch/arm/kernel/entry-header.S line 105
Quoted 4 lines
arch/arm/kernel/entry-header.S +4
-0+ stmia r12, {r0-r3, lr} + + @ restore registers for system calls + ldmia sp, {r0-r12}
We could avoid reloading r0-r7 (that's what we actually need for syscalls) if we don't corrupt them.
arch/arm/kernel/entry-header.S line 110
Quoted 5 lines
arch/arm/kernel/entry-header.S +5
-0+ .endm + + .macro v7m_exception_fast_exit + @ read r12, sp, lr, return address, xPSR and EXC_RETURN + add r12, sp, #48
S_ARM_R12?
Quoted 11 lines
arch/arm/kernel/entry-header.S +11
-0+ ldmia r12, {r1-r5, lr} + + tst r5, #0x100 + subne r2, r2, #4 + + tst lr, #0x10 + subeq r2, r2, #576 + + stmdb r2!, {r1, r3-r5} @ write saved r12, lr, return address and xPSR + + ldmia sp, {r1, r3-r5} @ read saved r0-r3
arch/arm/kernel/entry-header.S line 131
Quoted 10 lines
arch/arm/kernel/entry-header.S +10
-0+ stmdb r2!, {r1, r3-r5} @ write r0-r3 to basic exception frame + + tst lr, #0x4 + msrne psp, r2 + + ldmia sp, {r0-r12} + add sp, #S_FRAME_SIZE + cpsie i + bx lr + .endm
In the context v7m_exception_fast_exit is used (return from interrupts), the previously saved r0-r4,r12 etc. are still on the return stack and restored from there. There is no need for the ldmia/stmdb to re-create the interrupted process stack. Here we only need to make sure that we restore the registers that were not automatically saved and also move the kernel SP back to the original location (add S_FRAME_SIZE).
We handle rescheduling and work pending by raising PendSV, so we get another interrupt which would be returned via the slow_exit macro.
Quoted 30 lines
arch/arm/kernel/entry-header.S +30
-0+ .macro v7m_exception_slow_exit ret_r0 + cpsid i + ldr lr, [sp, #S_EXCRET] @ read exception LR + tst lr, #0x8 + bne 1f @ go to thread mode using exception return + + /* + * return to kernel thread + * sp is already set up (and might be unset in pt_regs), so only + * restore r0-r12 and pc + */ + ldmia sp, {r0-r12} + ldr lr, [sp, #S_PC] + add sp, sp, #S_FRAME_SIZE + cpsie i + bx lr + /* + * return to userspace + */ +1: + @ read original r12, sp, lr, pc, xPSR + add r12, sp, #48 + ldmia r12, {r1-r5} + + /* stack aligning */ + tst r5, #0x100 + subne r2, r2, #4 + + /* skip over stack space for fp extension */ + tst lr, #0x10
arch/arm/kernel/entry-header.S line 173
Quoted 10 lines
arch/arm/kernel/entry-header.S +10
-0+ subeq r2, r2, #576 + + /* write basic exception frame */ + stmdb r2!, {r1, r3-r5} @ saved r12, lr, return address and xPSR + ldmia sp, {r1, r3-r5} @ read saved r0-r3 + .if \ret_r0 + stmdb r2!, {r0, r3-r5} @ restore r0-r3 + .else + stmdb r2!, {r1, r3-r5} @ restore r0-r3 + .endif
This looks fine.
arch/arm/kernel/entry-header.S line 177
Quoted 3 lines
arch/arm/kernel/entry-header.S +3
-0+ msr psp, r2 + + ldmia sp, {r0-r12} @ restore original r4-r11
Isn't this reading too much (optimisation)?
Quoted 5 lines
arch/arm/kernel/entry-header.S +5
-0+ add sp, #S_FRAME_SIZE @ restore the original MSP + cpsie i + bx lr + .endm +#endif /* CONFIG_CPU_V7M */
...
Quoted 15 lines
arch/arm/kernel/process.c +4
-0@@ -452,7 +452,11 @@ asm( ".pushsection .text\n"#ifdef CONFIG_TRACE_IRQFLAGS " bl trace_hardirqs_on\n"#endif +#ifdef CONFIG_CPU_V7M +" msr primask, r7\n" +#else " msr cpsr_c, r7\n" +#endif " mov r0, r4\n" " mov lr, r6\n" " mov pc, r5\n"
arch/arm/kernel/process.c pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) · line 501
Quoted 7 lines
arch/arm/kernel/process.c +4
-0@@ -491,6 +495,10 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) regs.ARM_r7 =SVC_MODE |PSR_ENDSTATE |PSR_ISETSTATE ; regs.ARM_pc = (unsigned long )kernel_thread_helper; regs.ARM_cpsr = regs.ARM_r7 |PSR_I_BIT ; +#ifdef CONFIG_CPU_V7M +/* Return to Handler mode */ + regs.ARM_EXCRET =0xfffffff1L ; +#endif
BTW, do we need to set this here? We don't return to a kernel thread via exception return.
I currently cannot see any obvious bugs in the code. Since you said it doesn't work, what are the symptoms?
Signature · 1 line
Catalin
PATCH v2 5/5 Cortex-M3: Add support for exception handling
Hello Catalin,
Quoted 8 lines · Catalin Marinas
Quoted 3 lines · Uwe Kleine-K?nig
To save r0, I'd readd
OLD_R0at the end ofpt_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_regsstructure, we could add the exception return at the end (with two additional 32-bit words to preserve the 64-bit alignment).
I will do that.
Quoted 10 lines
arch/arm/kernel/entry-common.S __sys_trace: · line 483
Quoted 8 lines
arch/arm/kernel/entry-common.S +1
-1@@ -473,7 +480,7 @@ __sys_trace: adr lr, BSYM(__sys_trace_return) @ return address mov scno, r0 @ syscall number (possibly new) - add r1, sp, #S_R0 + S_OFF @ pointer to regs + add r1, sp, #S_OFF @ pointer to regsThis change is no longer needed since
S_R0is no 0.
hmm, I thought I had removed them. Seems I didn't.
Quoted 10 lines
arch/arm/kernel/entry-header.S line 29
Quoted 8 lines
arch/arm/kernel/entry-header.S +1
-1@@ -26,7 +26,7 @@ * The SWI code relies on the fact that R0 is at the bottom of the stack * (due to slow/fast restore user regs). */ -#if S_R0 != 0 +#if S_R0 != 0 && !defined(CONFIG_CPU_V7M)Same here.
Same here ;-)
Quoted 30 lines
Quoted 30 lines
arch/arm/kernel/entry-header.S +29
-0+#ifdef CONFIG_CPU_V7M +/* + * ARMv7-M exception entry/exit macros. + * + * xPSR, ReturnAddress(), LR (R14), R12, R3, R2, R1, and R0 are + * automatically saved on the current stack (32 words) before + * switching to the exception stack (SP_main). + * + * If exception is taken while in user mode, SP_main is + * empty. Otherwise, SP_main is aligned to 64 bit automatically + * (CCR.STKALIGN set). + * + * Linux assumes that the interrupts are disabled when entering an + * exception handler and it may BUG if this is not the case. Interrupts + * are disabled during entry and reenabled in the exit macro. + * + * v7m_exception_fast_exit is used when returning from interrupts. + * + * v7m_exception_slow_exit is used when returning from SVC or PendSV. + * When returning to kernel mode, we don't return from exception. + */ + .macro v7m_exception_entry + cpsid i + sub sp, #S_FRAME_SIZE + stmia sp, {r0-r12} + + @ set r0 to the location of the registers saved by the core during + @ exception entry. Depending on the mode the cpu was in when the + @ exception happend that is either on the main or the process stack.
Quoted 8 lines
arch/arm/kernel/entry-header.S line 80
Quoted 5 lines
arch/arm/kernel/entry-header.S +5
-0+ @ Bit 2 of EXC_RETURN stored in the lr register specifies which stack + @ was used. + tst lr, #0x4 + mrsne r0, psp + addeq r0, sp, #S_FRAME_SIZECould we use some other registers here like r8-r12 so that we keep r0-r7 for syscall handling later and avoid another ldmia?
One upside of using r0 is that
addeq r0, sp, #S_FRAME_SIZE
can be encoded in 16 bits while this is not possible and 32 bits are needed. And I wonder if it's allowed to corrupt r8-r12?
Quoted 10 lines
Quoted 10 lines
arch/arm/kernel/entry-header.S +10
-0+ add r0, r0, #20 @ skip over r0-r3, r12 + ldmia r0!, {r1-r3} @ load saved lr, return address and xPSR + + @ calculate the orignal stack pointer value. + @ r0 currently points to the memory location just above the auto saved + @ xPSR. If the FP extension is implemented and bit 4 of EXC_RETURN is 0 + @ then space was allocated for FP state. That is space for 18 32-bit + @ values. (If FP extension is unimplemented, bit 4 is 1.) + @ Additionally the cpu might automatically 8-byte align the stack. Bit 9 + @ of the saved xPSR specifies if stack aligning took place. In this case
Quoted 8 lines
arch/arm/kernel/entry-header.S line 95
Quoted 4 lines
arch/arm/kernel/entry-header.S +4
-0+ @ another 32-bit value is included in the stack. + + tst lr, #0x10 + addeq r0, r0, #576I think you can ignore VFP for now. We could change it to do lazy save/restore and avoid the automatic state saving. If it does this while in kernel, it takes a bit of extra stack space.
If I understood correctly this will never trigger for kernel tasks, won't it?
Quoted 4 lines
arch/arm/kernel/entry-header.S line 101
Quoted 2 lines
arch/arm/kernel/entry-header.S +2
-0+ @ save original sp, lr, return address, xPSR and EXC_RETURN + add r12, sp, #52Just use
S_ARM_SPor whatever asm offsets, it's easier to read.
OK, right.
Quoted 7 lines
arch/arm/kernel/entry-header.S line 105
Quoted 4 lines
arch/arm/kernel/entry-header.S +4
-0+ stmia r12, {r0-r3, lr} + + @ restore registers for system calls + ldmia sp, {r0-r12}We could avoid reloading r0-r7 (that's what we actually need for syscalls) if we don't corrupt them.
See question above. And I noticed that because of tail-chaining we need to load the register values from the exception frame at least once anyhow. I will try to optimise here.
Quoted 37 lines
arch/arm/kernel/entry-header.S line 110
Quoted 5 lines
arch/arm/kernel/entry-header.S +5
-0+ .endm + + .macro v7m_exception_fast_exit + @ read r12, sp, lr, return address, xPSR and EXC_RETURN + add r12, sp, #48
S_ARM_R12?Quoted 11 lines
arch/arm/kernel/entry-header.S +11
-0+ ldmia r12, {r1-r5, lr} + + tst r5, #0x100 + subne r2, r2, #4 + + tst lr, #0x10 + subeq r2, r2, #576 + + stmdb r2!, {r1, r3-r5} @ write saved r12, lr, return address and xPSR + + ldmia sp, {r1, r3-r5} @ read saved r0-r3arch/arm/kernel/entry-header.S line 131
Quoted 10 lines
arch/arm/kernel/entry-header.S +10
-0+ stmdb r2!, {r1, r3-r5} @ write r0-r3 to basic exception frame + + tst lr, #0x4 + msrne psp, r2 + + ldmia sp, {r0-r12} + add sp, #S_FRAME_SIZE + cpsie i + bx lr + .endmIn the context
v7m_exception_fast_exitis 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 (addS_FRAME_SIZE).
Quoted 2 lines
We handle rescheduling and work pending by raising PendSV, so we get another interrupt which would be returned via the
slow_exitmacro.
I was not sure if a task could be preempted during an exception. So I choosed to play save.
Quoted 43 lines
Quoted 30 lines
arch/arm/kernel/entry-header.S +30
-0+ .macro v7m_exception_slow_exit ret_r0 + cpsid i + ldr lr, [sp, #S_EXCRET] @ read exception LR + tst lr, #0x8 + bne 1f @ go to thread mode using exception return + + /* + * return to kernel thread + * sp is already set up (and might be unset in pt_regs), so only + * restore r0-r12 and pc + */ + ldmia sp, {r0-r12} + ldr lr, [sp, #S_PC] + add sp, sp, #S_FRAME_SIZE + cpsie i + bx lr + /* + * return to userspace + */ +1: + @ read original r12, sp, lr, pc, xPSR + add r12, sp, #48 + ldmia r12, {r1-r5} + + /* stack aligning */ + tst r5, #0x100 + subne r2, r2, #4 + + /* skip over stack space for fp extension */ + tst lr, #0x10arch/arm/kernel/entry-header.S line 173
Quoted 10 lines
arch/arm/kernel/entry-header.S +10
-0+ subeq r2, r2, #576 + + /* write basic exception frame */ + stmdb r2!, {r1, r3-r5} @ saved r12, lr, return address and xPSR + ldmia sp, {r1, r3-r5} @ read saved r0-r3 + .if \ret_r0 + stmdb r2!, {r0, r3-r5} @ restore r0-r3 + .else + stmdb r2!, {r1, r3-r5} @ restore r0-r3 + .endifThis looks fine.
Quoted 5 lines
arch/arm/kernel/entry-header.S line 177
Quoted 3 lines
arch/arm/kernel/entry-header.S +3
-0+ msr psp, r2 + + ldmia sp, {r0-r12} @ restore original r4-r11Isn'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_SIZEvs.
add sp, #S_R4
ldmia sp, {r4-r11}
add sp, #S_FRAME_SIZE - S_R4It's not described in the V7-M reverence. Do you know a document where I can look that up?
Quoted 23 lines
Quoted 5 lines
arch/arm/kernel/entry-header.S +5
-0+ add sp, #S_FRAME_SIZE @ restore the original MSP + cpsie i + bx lr + .endm +#endif /* CONFIG_CPU_V7M */...
Quoted 17 lines
arch/arm/kernel/process.c +4
-0@@ -452,7 +452,11 @@ asm( ".pushsection .text\n"#ifdef CONFIG_TRACE_IRQFLAGS " bl trace_hardirqs_on\n"#endif +#ifdef CONFIG_CPU_V7M +" msr primask, r7\n" +#else " msr cpsr_c, r7\n" +#endif " mov r0, r4\n" " mov lr, r6\n" " mov pc, r5\n" @@ -491,6 +495,10 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) regs.ARM_r7 =SVC_MODE |PSR_ENDSTATE |PSR_ISETSTATE ; regs.ARM_pc = (unsigned long )kernel_thread_helper;
Quoted 8 lines
arch/arm/kernel/process.c pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) · line 501
Quoted 5 lines
arch/arm/kernel/process.c +4
-0regs.ARM_cpsr = regs.ARM_r7 |PSR_I_BIT ; +#ifdef CONFIG_CPU_V7M +/* Return to Handler mode */ + regs.ARM_EXCRET =0xfffffff1L ; +#endif BTW, do we need to set this here? We don't return to a kernel thread via exception return.
But we need it to decide in slow_return if we should use exception return or not. So yes, I think it's needed.
Quoted 2 lines
I currently cannot see any obvious bugs in the code. Since you said it doesn't work, what are the symptoms?
I found two problems. One is I wasn't aware that r0-r3,r12 doesn't necessarily need to match the values on exception entry (because of tail-chaining) and in start_thread decreasing sp is wrong.
I will reimplement the three macros now with the new lessons learned.
Best regards and thanks for your input (here and on irc) Uwe
Signature · 2 lines
Pengutronix e.K. | Uwe Kleine-K?nig | Industrial Linux Solutions | http://www.pengutronix.de/ |
PATCH v2 4/5 Cortex-M3: Add base support for Cortex-M3
In reply to Uwe Kleine-KönigHi Uwe,
Quoted 14 lines · Uwe Kleine-K?nig
arch/arm/include/asm/processor.h +7
-0@@ -49,7 +49,15 @@ struct thread_struct {#ifdef CONFIG_MMU #define nommu_start_thread (regs) do { } while (0)#else +#ifndef CONFIG_CPU_V7M #define nommu_start_thread (regs) regs->ARM_r10 = current->mm->start_data +#else +#define nommu_start_thread(regs) do { \ + regs->ARM_r10 = current->mm->start_data; \ + regs->ARM_sp -= 32; /* exception return state */ \ + regs->ARM_EXCRET = 0xfffffffdL; \ +} while (0)
...
arch/arm/include/asm/ptrace.h struct pt_regs { · line 143
Quoted 12 lines
arch/arm/include/asm/ptrace.h +4
-0@@ -39,16 +39,25 @@@@ -127,7 +136,11 @@ struct pt_regs {#define ARM_r2 uregs[2]#define ARM_r1 uregs[1]#define ARM_r0 uregs[0] +#if definedCONFIG_CPU_V7M +#define ARM_EXCRET uregs[17] +#else #define ARM_ORIG_r0 uregs[17] +#endif
Could we save the exception return somewhere in thread_info and preserve ORIG_r0?
Alternatively, with some care, we could extend the kernel pt_regs definition with two more registers and use one of them for exception return. The user variant would remain the same as it's used by ptrace.
Signature · 1 line
Catalin
PATCH 1/5 ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15
In reply to Uwe Kleine-KönigQuoted 9 lines · Uwe Kleine-K?nig
Signed-off-by Uwe Kleine-K?nig <[email protected]>--- arch/arm/include/asm/system.h | 2 ++ arch/arm/kernel/entry-armv.S | 4 ++++ arch/arm/kernel/head-common.S | 10 ++++++++-- arch/arm/kernel/setup.c | 8 ++++++-- arch/arm/mm/alignment.c | 6 ++++++ arch/arm/mm/mmu.c | 8 +++++++- 6 files changed, 33 insertions(+), 5 deletions(-)
Hi Uwe,
Couple of points below,
Thanks,
~Ryan
Quoted 55 lines
arch/arm/include/asm/system.h +2
-0@@ -185,6 +185,7 @@ extern unsigned int user_debug;#define set_mb (var, value) do { var = value; smp_mb(); } while (0)#define nop () __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t"); +#ifdef CONFIG_CPU_CP15 extern unsigned long cr_no_alignment;/* defined in entry-armv.S */ extern unsigned long cr_alignment;/* defined in entry-armv.S */ @@ -224,6 +225,7 @@ static inline void set_copro_access(unsigned int val) : : "r" (val) : "cc"); isb(); } +#endif /* * switch_mm() may do a full cache flush over the context switch, arch/arm/kernel/entry-armv.S +4
-0@@ -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_irqarch/arm/kernel/head-common.S +0
-0
arch/arm/kernel/head-common.S __mmap_switched: · line 104
Quoted 9 lines
arch/arm/kernel/head-common.S +4
-2@@ -98,8 +98,10 @@ __mmap_switched: str r9, [r4] @ Save processor ID str r1, [r5] @ Save machine type str r2, [r6] @ Save atags pointer - bic r4, r0, #CR_A @ Clear 'A' bit - stmia r7, {r0, r4} @ Save control register values + cmp r7, #0 + itt ne + bicne r4, r0, #CR_A @ Clear 'A' bit + stmneia r7, {r0, r4} @ Save control register values
Can the cr_alignment variable ever have a value of zero if CONFIG_CPU_15 is enabled? If so you fail to do the stmnia which is possibly not correct? Why do the registers not need to be stored if cr_alignment is zero? I think this at least deserves a comment explaining.
Also, couldn't it just be done like this:
#ifndef CONFIG_CPU_CP15
bic r4, r0, #CR_A
stimia r7, {r0, r4}#endif
Since r7 will always be zero in the !CP15 case?
Quoted 21 lines
arch/arm/kernel/head-common.S +4
-0b 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_dataarch/arm/kernel/setup.c +0
-0@@ -472,9 +472,13 @@ static void __init setup_processor(void) cpu_cache = *list->cache;
arch/arm/kernel/setup.c static void __init setup_processor(void) · line 480
Quoted 10 lines
arch/arm/kernel/setup.c +5
-2#endif -printk ("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n" , +printk ("CPU: %s [%08x] revision %d (ARMv%s)" , cpu_name,read_cpuid_id (),read_cpuid_id () &15 , - proc_arch[cpu_architecture ()], cr_alignment); + proc_arch[cpu_architecture ()]); + +#ifdef CONFIG_CPU_CP15 +printk (KERN_CONT ", cr=%08lx\n" , cr_alignment);
#else printk(KERN_CONT "\n");
?
Quoted 82 lines
arch/arm/kernel/setup.c +1
-0+#endif snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c",arch/arm/kernel/setup.c +0
-0list->arch_name, ENDIANNESS);arch/arm/mm/alignment.c +4
-0@@ -89,7 +89,11 @@ core_param(alignment, ai_usermode, int, 0600);/* Return true if and only if the ARMv6 unaligned access model is in use. */ static bool cpu_is_v6_unaligned (void ) { +#ifdef CONFIG_CPU_CP15 return cpu_architecture () >= CPU_ARCH_ARMv6 && (cr_alignment &CR_U ); +#else +return 0 ; +#endif }static int
safe_usermode(int new_usermode, bool warn)arch/arm/mm/alignment.c +2
-0@@ -961,12 +965,14 @@ static int __init alignment_init(void)return -ENOMEM ;#endif +#ifdef CONFIG_CPU_CP15 if (cpu_is_v6_unaligned ()) { cr_alignment &= ~CR_A ; cr_no_alignment &= ~CR_A ;set_cr (cr_alignment); ai_usermode =safe_usermode (ai_usermode, false); } +#endif hook_fault_code (FAULT_CODE_ALIGNMENT , do_alignment,SIGBUS ,BUS_ADRALN ,"alignment exception" );arch/arm/mm/mmu.c +7
-1@@ -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;