Skip to contentSkip to conversation

ARM: zImage: add support for ARMv7-M

PATCH Superseded Uwe Kleine-König 4 participants 10 messages Dec 17, 2014 – Mar 25, 2015 Arm (32-bit)

lore
Share & tools
lore
#0 lore raw

PATCH v6 1/1 ARM: zImage: add support for ARMv7-M

From: Joachim Eastwood <[email protected]>

This patch makes it possible to enter zImage in Thumb mode for ARMv7-M (Cortex-M) CPUs that do not support ARM mode. The kernel entry is also made in Thumb mode.

[ukl: fix spelling in commit log, return early in call_cache_fn]

---
Hello,

I just picked up Joachim's patch and fixed the small concerns I had in the last round.

I thought about adding a wrapper for accessing the CPUID registers that are located in cp15 on v7-A/R and memory mapped on v7-M. The corresponding registers and their address are as follows:

name cp15 reg [1] on -A/R address on -M
MIDR/CPUID CRm=c0, opc2=0 0xe000ed00

PFR0   		CRm=c1, opc2=0  	0xe000ed40
PFR1   		CRm=c1, opc2=1  	0xe000ed44
DFR0   		CRm=c1, opc2=2  	0xe000ed48
AFR0   		CRm=c1, opc2=3  	0xe000ed4c
MMFR0  		CRm=c1, opc2=4  	0xe000ed50
MMFR1  		CRm=c1, opc2=5  	0xe000ed54
MMFR2  		CRm=c1, opc2=6  	0xe000ed58
MMFR3  		CRm=c1, opc2=7  	0xe000ed5c
ISAR0  		CRm=c2, opc2=0  	0xe000ed60
ISAR1  		CRm=c2, opc2=1  	0xe000ed64
ISAR2  		CRm=c2, opc2=2  	0xe000ed68
ISAR3  		CRm=c2, opc2=3  	0xe000ed6c
ISAR4  		CRm=c2, opc2=4  	0xe000ed70
ISAR5  		CRm=c2, opc2=5  	0xe000ed74

But there is no nice translation and as cache handling is implementation defined on v7-M anyhow there is not much use and I decided to just return early in the cache function.

This patch is only compile tested as I don't have a machine with enough RAM to run a non-XIP kernel, so Tested-by tags are welcome.

Best regards
Uwe

[1] all have in common: CRn=c0, opc1=0, so only CRm and opc2 are listed

 arch/arm/boot/compressed/head.S | 33 +++++++++++++++++++++++++++------
 arch/arm/include/asm/unified.h  |  8 ++++++++
 2 files changed, 35 insertions(+), 6 deletions(-)
arch/arm/boot/compressed/head.S +27 -6
index 68be9017593d..3788eedabb15 100644
@@ -10,8 +10,11 @@
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include <asm/v7m.h>
+
+ AR_CLASS(	.arch	armv7-a	)
+ M_CLASS(	.arch	armv7-m	)
 
-	.arch	armv7-a
 /*
  * Debugging stuff
  *
@@ -114,7 +117,12 @@
  * sort out different calling conventions
  */
 		.align
-		.arm				@ Always enter in ARM state
+		/*
+		 * Always enter in ARM state for CPUs that support the ARM ISA.
+		 * As of today (2014) that's exactly the members of the A and R
+		 * classes.
+		 */
+ AR_CLASS(	.arm	)
 start:
 		.type	start,#function
 		.rept	7
@@ -132,14 +140,15 @@ start:
 
  THUMB(		.thumb			)
 1:
- ARM_BE8(	setend	be )			@ go BE8 if compiled for BE8
-		mrs	r9, cpsr
+ ARM_BE8(	setend	be		)	@ go BE8 if compiled for BE8
+ AR_CLASS(	mrs	r9, cpsr	)
 #ifdef CONFIG_ARM_VIRT_EXT
 		bl	__hyp_stub_install	@ get into SVC mode, reversibly
 #endif
 		mov	r7, r1			@ save architecture ID
 		mov	r8, r2			@ save atags pointer
 
+#ifndef CONFIG_CPU_V7M
 		/*
 		 * Booting from Angel - need to enter SVC mode and disable
 		 * FIQs/IRQs (numeric definitions from angel arm.h source).
@@ -155,6 +164,7 @@ not_angel:
 		safe_svcmode_maskall r0
 		msr	spsr_cxsf, r9		@ Save the CPU boot mode in
 						@ SPSR
+#endif
 		/*
 		 * Note that some cache flushing and other stuff may
 		 * be needed here - is there an Angel SWI call for this?
@@ -789,6 +799,16 @@ __common_mmu_cache_on:
 call_cache_fn:	adr	r12, proc_types
 #ifdef CONFIG_CPU_CP15
 		mrc	p15, 0, r9, c0, c0	@ get processor ID
+#elif defined(CONFIG_CPU_V7M)
+		/*
+		 * On v7-M the processor id is located in the V7M_SCB_CPUID
+		 * register, but as cache handling is IMPLEMENTATION DEFINED on
+		 * v7-M (if existant at all) we just return early here.
+		 * If V7M_SCB_CPUID were used the cpu ID functions (i.e.
+		 * __armv7_mmu_cache_{on,off,flush}) would be selected which
+		 * use cp15 registers that are not implemented on v7-M.
+		 */
+		bx	lr
 #else
 		ldr	r9, =CONFIG_PROCESSOR_ID
 #endif
@@ -1289,8 +1309,9 @@ __hyp_reentry_vectors:
 
 __enter_kernel:
 		mov	r0, #0			@ must be 0
- ARM(		mov	pc, r4	)		@ call kernel
- THUMB(		bx	r4	)		@ entry point is always ARM
+ ARM(		mov	pc, r4		)	@ call kernel
+ M_CLASS(	add	r4, r4, #1	)	@ enter in Thumb mode for M class
+ THUMB(		bx	r4		)	@ entry point is always ARM for A/R classes
 
 reloc_code_end:
 
arch/arm/include/asm/unified.h +8 -0
index b88beaba6b4a..200f9a7cd623 100644
@@ -24,6 +24,14 @@
 	.syntax unified
 #endif
 
+#ifdef CONFIG_CPU_V7M
+#define AR_CLASS(x...)
+#define M_CLASS(x...)	x
+#else
+#define AR_CLASS(x...)	x
+#define M_CLASS(x...)
+#endif
+
 #ifdef CONFIG_THUMB2_KERNEL
 
 #if __GNUC__ < 4
Signature · 1 line
2.1.3
#1 lore raw

PATCH v6 1/1 ARM: zImage: add support for ARMv7-M

Quoted 36 lines · Uwe Kleine-K?nig

From: Joachim Eastwood <[email protected]>

This patch makes it possible to enter zImage in Thumb mode for ARMv7-M (Cortex-M) CPUs that do not support ARM mode. The kernel entry is also made in Thumb mode.

[ukl: fix spelling in commit log, return early in call_cache_fn]

---
Hello,

I just picked up Joachim's patch and fixed the small concerns I had in the last round.

I thought about adding a wrapper for accessing the CPUID registers that are located in cp15 on v7-A/R and memory mapped on v7-M. The corresponding registers and their address are as follows:

name cp15 reg [1] on -A/R address on -M
MIDR/CPUID CRm=c0, opc2=0 0xe000ed00

PFR0   		CRm=c1, opc2=0  	0xe000ed40
PFR1   		CRm=c1, opc2=1  	0xe000ed44
DFR0   		CRm=c1, opc2=2  	0xe000ed48
AFR0   		CRm=c1, opc2=3  	0xe000ed4c
MMFR0  		CRm=c1, opc2=4  	0xe000ed50
MMFR1  		CRm=c1, opc2=5  	0xe000ed54
MMFR2  		CRm=c1, opc2=6  	0xe000ed58
MMFR3  		CRm=c1, opc2=7  	0xe000ed5c
ISAR0  		CRm=c2, opc2=0  	0xe000ed60
ISAR1  		CRm=c2, opc2=1  	0xe000ed64
ISAR2  		CRm=c2, opc2=2  	0xe000ed68
ISAR3  		CRm=c2, opc2=3  	0xe000ed6c
ISAR4  		CRm=c2, opc2=4  	0xe000ed70
ISAR5  		CRm=c2, opc2=5  	0xe000ed74
Quoted 6 lines

But there is no nice translation and as cache handling is implementation defined on v7-M anyhow there is not much use and I decided to just return early in the cache function.

This patch is only compile tested as I don't have a machine with enough RAM to run a non-XIP kernel, so Tested-by tags are welcome.

Hi Uwe,

Tried the patch on Vybrid's M4 CPU. Since the M4 has full access to the DDR3 RAM, it is even possible to use AUTO_ZRELADDR for both CPU's: The Colibri VF61 has 256MB of RAM: A5 relocates to 0x80008000, M4 to 0x88008000.

The uncompressing stage seems to work fine, however it seems I hit a different bug which is triggered by using the zImage: Freeing the memory location used by the compressed image seems to fail:

Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
Linux version 3.18.0-10889-ga84c884 (ags at trochilidae) (gcc version 4.8.3 20140401 (prerelease) (Linaro GCC 4.8-2014.04) ) #377 Sat Dec 20 14:08:07 CET 2014
CPU: ARMv7-M [410fc241] revision 1 (ARMv7M), cr=00000000
CPU: unknown data cache, unknown instruction cache
Machine model: VF610 Cortex-M4
bootconsole [earlycon0] enabled
Built 1 zonelists in Zone order, mobility grouping on. Total pages:
12192
Kernel command line: console=ttyLP2,115200 ihash_entries=64 dhash_entries=64 earlyprintk clk_ignore_unused init=/linuxrc rw PID hash table entries: 256 (order: -2, 1024 bytes)
Dentry cache hash table entries: 64 (order: -4, 256 bytes) Inode-cache hash table entries: 64 (order: -4, 256 bytes)

BUG: Bad page state in process swapper  pfn:8c000
page:8f020000 count:0 mapcount:0 mapping:da2fe79e index:0x6e563b3a
flags:
0x4248e05f(locked|error|referenced|uptodate|dirty|active|writeback|head|tail|swapbacked)
page dumped because: PAGE_FLAGS_CHECK_AT_FREE flag(s) set
bad because of flags:
flags: 0x2041(locked|active|writeback)
CPU: 0 PID: 0 Comm: swapper Not tainted 3.18.0-10889-ga84c884 #377
Hardware name: Freescale Vybrid VF610 (Device Tree)
[<8800b129>] (unwind_backtrace) from [<8800a53f>] (show_stack+0xb/0xc)
[<8800a53f>] (show_stack) from [<8803a40d>] (bad_page+0x85/0xb8)
[<8803a40d>] (bad_page) from [<8803a4e9>] (free_pages_prepare+0xa9/0xac)

[<8803a4e9>] (free_pages_prepare) from [<8803b2ed>] (__free_pages_ok+0x19/0x260)
[<8803b2ed>] (__free_pages_ok) from [<881978db>] (free_all_bootmem+0xaf/0xf8)
[<881978db>] (free_all_bootmem) from [<8819201d>] (mem_init+0xb5/0x1c8) [<8819201d>] (mem_init) from [<8818f5af>] (start_kernel+0x17b/0x2c0) [<8818f5af>] (start_kernel) from [<08008023>] (0x8008023)

My loaders output, zImage has been loaded to the region in question (0x8f000080...)

# ./m4boot zImage initramfs.cpio.lzo vf610m4-colibri.dtb
zImage: 1103944 bytes loaded
initramfs.cpio.lzo: 1632028 bytes loaded
vf610m4-colibri.dtb: 9911 bytes loaded
vf610m4bootldr: 128 bytes copied to 0x8f000000 through 0x8f000080
zImage: 1103944 bytes copied to 0x8f000080 through 0x8f10d8c8
initramfs.cpio.lzo: 1632028 bytes copied to 0x8d000000 through
0x8d18e71c
vf610m4-colibri.dtb: 9979 bytes copied to 0x8fff0000 through 0x8fff26fb
Entry point set to 0x0f000001
Argument set to 0x8fff0000
Cortex-M4 started...

Virtual kernel memory layout:

    vector  : 0x00000000 - 0x00001000   (   4 kB)
    fixmap  : 0xffc00000 - 0xfff00000   (3072 kB)
    vmalloc : 0x00000000 - 0xffffffff   (4095 MB)
    lowmem  : 0x88000000 - 0x8f000000   ( 112 MB)
      .text : 0x88008000 - 0x8818acfc   (1548 kB)
      .init : 0x8818b000 - 0x8819e000   (  76 kB)
      .data : 0x8819e000 - 0x881b2900   (  83 kB)
       .bss : 0x881b2900 - 0x881dc210   ( 167 kB)

I used CONFIG_SET_MEM_PARAM and configured the RAM at those fixed values:
CONFIG_DRAM_BASE=0x88000000

CONFIG_DRAM_SIZE=0x08000000

Any idea what could be the issue here?

--
Stefan

Quoted 115 lines

Best regards
Uwe

[1] all have in common: CRn=c0, opc1=0, so only CRm and opc2 are listed

 arch/arm/boot/compressed/head.S | 33 +++++++++++++++++++++++++++------
 arch/arm/include/asm/unified.h  |  8 ++++++++
 2 files changed, 35 insertions(+), 6 deletions(-)
arch/arm/boot/compressed/head.S +27 -6
index 68be9017593d..3788eedabb15 100644
@@ -10,8 +10,11 @@
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include <asm/v7m.h>
+
+ AR_CLASS(	.arch	armv7-a	)
+ M_CLASS(	.arch	armv7-m	)
 
-	.arch	armv7-a
 /*
  * Debugging stuff
  *
@@ -114,7 +117,12 @@
  * sort out different calling conventions
  */
 		.align
-		.arm				@ Always enter in ARM state
+		/*
+		 * Always enter in ARM state for CPUs that support the ARM ISA.
+		 * As of today (2014) that's exactly the members of the A and R
+		 * classes.
+		 */
+ AR_CLASS(	.arm	)
 start:
 		.type	start,#function
 		.rept	7
@@ -132,14 +140,15 @@ start:
 
  THUMB(		.thumb			)
 1:
- ARM_BE8(	setend	be )			@ go BE8 if compiled for BE8
-		mrs	r9, cpsr
+ ARM_BE8(	setend	be		)	@ go BE8 if compiled for BE8
+ AR_CLASS(	mrs	r9, cpsr	)
 #ifdef CONFIG_ARM_VIRT_EXT
 		bl	__hyp_stub_install	@ get into SVC mode, reversibly
 #endif
 		mov	r7, r1			@ save architecture ID
 		mov	r8, r2			@ save atags pointer
 
+#ifndef CONFIG_CPU_V7M
 		/*
 		 * Booting from Angel - need to enter SVC mode and disable
 		 * FIQs/IRQs (numeric definitions from angel arm.h source).
@@ -155,6 +164,7 @@ not_angel:
 		safe_svcmode_maskall r0
 		msr	spsr_cxsf, r9		@ Save the CPU boot mode in
 						@ SPSR
+#endif
 		/*
 		 * Note that some cache flushing and other stuff may
 		 * be needed here - is there an Angel SWI call for this?
@@ -789,6 +799,16 @@ __common_mmu_cache_on:
 call_cache_fn:	adr	r12, proc_types
 #ifdef CONFIG_CPU_CP15
 		mrc	p15, 0, r9, c0, c0	@ get processor ID
+#elif defined(CONFIG_CPU_V7M)
+		/*
+		 * On v7-M the processor id is located in the V7M_SCB_CPUID
+		 * register, but as cache handling is IMPLEMENTATION DEFINED on
+		 * v7-M (if existant at all) we just return early here.
+		 * If V7M_SCB_CPUID were used the cpu ID functions (i.e.
+		 * __armv7_mmu_cache_{on,off,flush}) would be selected which
+		 * use cp15 registers that are not implemented on v7-M.
+		 */
+		bx	lr
 #else
 		ldr	r9, =CONFIG_PROCESSOR_ID
 #endif
@@ -1289,8 +1309,9 @@ __hyp_reentry_vectors:
 
 __enter_kernel:
 		mov	r0, #0			@ must be 0
- ARM(		mov	pc, r4	)		@ call kernel
- THUMB(		bx	r4	)		@ entry point is always ARM
+ ARM(		mov	pc, r4		)	@ call kernel
+ M_CLASS(	add	r4, r4, #1	)	@ enter in Thumb mode for M class
+ THUMB(		bx	r4		)	@ entry point is always ARM for A/R classes
 
 reloc_code_end:
 
arch/arm/include/asm/unified.h +8 -0
index b88beaba6b4a..200f9a7cd623 100644
@@ -24,6 +24,14 @@
 	.syntax unified
 #endif
 
+#ifdef CONFIG_CPU_V7M
+#define AR_CLASS(x...)
+#define M_CLASS(x...)	x
+#else
+#define AR_CLASS(x...)	x
+#define M_CLASS(x...)
+#endif
+
 #ifdef CONFIG_THUMB2_KERNEL
 
 #if __GNUC__ < 4
#2 lore raw

PATCH v6 1/1 ARM: zImage: add support for ARMv7-M

Stefan,

Quoted 46 lines · Stefan Agner
Quoted 36 lines · Uwe Kleine-K?nig

From: Joachim Eastwood <[email protected]>

This patch makes it possible to enter zImage in Thumb mode for ARMv7-M (Cortex-M) CPUs that do not support ARM mode. The kernel entry is also made in Thumb mode.

[ukl: fix spelling in commit log, return early in call_cache_fn]

---
Hello,

I just picked up Joachim's patch and fixed the small concerns I had in the last round.

I thought about adding a wrapper for accessing the CPUID registers that are located in cp15 on v7-A/R and memory mapped on v7-M. The corresponding registers and their address are as follows:

name cp15 reg [1] on -A/R address on -M
MIDR/CPUID CRm=c0, opc2=0 0xe000ed00

PFR0   		CRm=c1, opc2=0  	0xe000ed40
PFR1   		CRm=c1, opc2=1  	0xe000ed44
DFR0   		CRm=c1, opc2=2  	0xe000ed48
AFR0   		CRm=c1, opc2=3  	0xe000ed4c
MMFR0  		CRm=c1, opc2=4  	0xe000ed50
MMFR1  		CRm=c1, opc2=5  	0xe000ed54
MMFR2  		CRm=c1, opc2=6  	0xe000ed58
MMFR3  		CRm=c1, opc2=7  	0xe000ed5c
ISAR0  		CRm=c2, opc2=0  	0xe000ed60
ISAR1  		CRm=c2, opc2=1  	0xe000ed64
ISAR2  		CRm=c2, opc2=2  	0xe000ed68
ISAR3  		CRm=c2, opc2=3  	0xe000ed6c
ISAR4  		CRm=c2, opc2=4  	0xe000ed70
ISAR5  		CRm=c2, opc2=5  	0xe000ed74
Quoted 6 lines

But there is no nice translation and as cache handling is implementation defined on v7-M anyhow there is not much use and I decided to just return early in the cache function.

This patch is only compile tested as I don't have a machine with enough RAM to run a non-XIP kernel, so Tested-by tags are welcome.

Hi Uwe,

Quoted 9 lines

Tried the patch on Vybrid's M4 CPU. Since the M4 has full access to the DDR3 RAM, it is even possible to use AUTO_ZRELADDR for both CPU's: The Colibri VF61 has 256MB of RAM: A5 relocates to 0x80008000, M4 to 0x88008000.

The uncompressing stage seems to work fine, however it seems I hit a different bug which is triggered by using the zImage: Freeing the memory location used by the compressed image seems to fail:

Does this happen systematically for you?

I tried this patch on a LPC4337 based board, and came across very strange and random memory corruptions, ranging from hitting strange WARN(), BUG(), to OOM, to unhandled exceptions.

Rebuilding the kernel caused the different results (perhaps due to link differences?).

The problem is this machine is not yet mainlined, so I'm not yet sure it's this patch the one to blame.

Signature · 2 lines
Ezequiel Garcia, VanguardiaSur
www.vanguardiasur.com.ar
#3 lore raw

PATCH v6 1/1 ARM: zImage: add support for ARMv7-M

Quoted 54 lines · Ezequiel Garcia

Stefan,

Quoted 51 lines · Stefan Agner
Quoted 36 lines · Uwe Kleine-K?nig

From: Joachim Eastwood <[email protected]>

This patch makes it possible to enter zImage in Thumb mode for ARMv7-M (Cortex-M) CPUs that do not support ARM mode. The kernel entry is also made in Thumb mode.

[ukl: fix spelling in commit log, return early in call_cache_fn]

---
Hello,

I just picked up Joachim's patch and fixed the small concerns I had in the last round.

I thought about adding a wrapper for accessing the CPUID registers that are located in cp15 on v7-A/R and memory mapped on v7-M. The corresponding registers and their address are as follows:

name cp15 reg [1] on -A/R address on -M
MIDR/CPUID CRm=c0, opc2=0 0xe000ed00

PFR0   		CRm=c1, opc2=0  	0xe000ed40
PFR1   		CRm=c1, opc2=1  	0xe000ed44
DFR0   		CRm=c1, opc2=2  	0xe000ed48
AFR0   		CRm=c1, opc2=3  	0xe000ed4c
MMFR0  		CRm=c1, opc2=4  	0xe000ed50
MMFR1  		CRm=c1, opc2=5  	0xe000ed54
MMFR2  		CRm=c1, opc2=6  	0xe000ed58
MMFR3  		CRm=c1, opc2=7  	0xe000ed5c
ISAR0  		CRm=c2, opc2=0  	0xe000ed60
ISAR1  		CRm=c2, opc2=1  	0xe000ed64
ISAR2  		CRm=c2, opc2=2  	0xe000ed68
ISAR3  		CRm=c2, opc2=3  	0xe000ed6c
ISAR4  		CRm=c2, opc2=4  	0xe000ed70
ISAR5  		CRm=c2, opc2=5  	0xe000ed74
Quoted 6 lines

But there is no nice translation and as cache handling is implementation defined on v7-M anyhow there is not much use and I decided to just return early in the cache function.

This patch is only compile tested as I don't have a machine with enough RAM to run a non-XIP kernel, so Tested-by tags are welcome.

Hi Uwe,

Tried the patch on Vybrid's M4 CPU. Since the M4 has full access to the DDR3 RAM, it is even possible to use AUTO_ZRELADDR for both CPU's: The Colibri VF61 has 256MB of RAM: A5 relocates to 0x80008000, M4 to 0x88008000.

Quoted 6 lines
Quoted 4 lines

The uncompressing stage seems to work fine, however it seems I hit a different bug which is triggered by using the zImage: Freeing the memory location used by the compressed image seems to fail:

Does this happen systematically for you?

Yes, that happens all the time, same address.

Quoted 10 lines

I tried this patch on a LPC4337 based board, and came across very strange and random memory corruptions, ranging from hitting strange WARN(), BUG(), to OOM, to unhandled exceptions.

Rebuilding the kernel caused the different results (perhaps due to link differences?).

The problem is this machine is not yet mainlined, so I'm not yet sure it's this patch the one to blame.

Does it happen for you with xipImage?

I had some issues with kuser helpers, which now are disabled by default for non-MMU systems:

http://www.spinics.net/lists/arm-kernel/msg374425.html

--
Stefan

#4 lore raw

PATCH v6 1/1 ARM: zImage: add support for ARMv7-M

Quoted 69 lines · Stefan Agner
Quoted 54 lines · Ezequiel Garcia

Stefan,

Quoted 51 lines · Stefan Agner
Quoted 36 lines · Uwe Kleine-K?nig

From: Joachim Eastwood <[email protected]>

This patch makes it possible to enter zImage in Thumb mode for ARMv7-M (Cortex-M) CPUs that do not support ARM mode. The kernel entry is also made in Thumb mode.

[ukl: fix spelling in commit log, return early in call_cache_fn]

---
Hello,

I just picked up Joachim's patch and fixed the small concerns I had in the last round.

I thought about adding a wrapper for accessing the CPUID registers that are located in cp15 on v7-A/R and memory mapped on v7-M. The corresponding registers and their address are as follows:

name cp15 reg [1] on -A/R address on -M
MIDR/CPUID CRm=c0, opc2=0 0xe000ed00

PFR0   		CRm=c1, opc2=0  	0xe000ed40
PFR1   		CRm=c1, opc2=1  	0xe000ed44
DFR0   		CRm=c1, opc2=2  	0xe000ed48
AFR0   		CRm=c1, opc2=3  	0xe000ed4c
MMFR0  		CRm=c1, opc2=4  	0xe000ed50
MMFR1  		CRm=c1, opc2=5  	0xe000ed54
MMFR2  		CRm=c1, opc2=6  	0xe000ed58
MMFR3  		CRm=c1, opc2=7  	0xe000ed5c
ISAR0  		CRm=c2, opc2=0  	0xe000ed60
ISAR1  		CRm=c2, opc2=1  	0xe000ed64
ISAR2  		CRm=c2, opc2=2  	0xe000ed68
ISAR3  		CRm=c2, opc2=3  	0xe000ed6c
ISAR4  		CRm=c2, opc2=4  	0xe000ed70
ISAR5  		CRm=c2, opc2=5  	0xe000ed74
Quoted 6 lines

But there is no nice translation and as cache handling is implementation defined on v7-M anyhow there is not much use and I decided to just return early in the cache function.

This patch is only compile tested as I don't have a machine with enough RAM to run a non-XIP kernel, so Tested-by tags are welcome.

Hi Uwe,

Tried the patch on Vybrid's M4 CPU. Since the M4 has full access to the DDR3 RAM, it is even possible to use AUTO_ZRELADDR for both CPU's: The Colibri VF61 has 256MB of RAM: A5 relocates to 0x80008000, M4 to 0x88008000.

Quoted 6 lines
Quoted 4 lines

The uncompressing stage seems to work fine, however it seems I hit a different bug which is triggered by using the zImage: Freeing the memory location used by the compressed image seems to fail:

Does this happen systematically for you?

Yes, that happens all the time, same address.

Quoted 5 lines

I tried this patch on a LPC4337 based board, and came across very strange and random memory corruptions, ranging from hitting strange WARN(), BUG(), to OOM, to unhandled exceptions.

Quoted 8 lines
Quoted 5 lines

Rebuilding the kernel caused the different results (perhaps due to link differences?).

The problem is this machine is not yet mainlined, so I'm not yet sure it's this patch the one to blame.

Does it happen for you with xipImage?

Unfortunately, I haven't been able to prepare a XIP image and boot it.

Quoted 5 lines

I had some issues with kuser helpers, which now are disabled by default for non-MMU systems:

http://www.spinics.net/lists/arm-kernel/msg374425.html

Yeah, saw that, but my unhandled exceptions are different to that (and different each time I build and boot a new kernel).

Signature · 2 lines
Ezequiel Garcia, VanguardiaSur
www.vanguardiasur.com.ar
#5 lore raw

PATCH v6 1/1 ARM: zImage: add support for ARMv7-M

In reply to Ezequiel Garcia
Quoted 60 lines · Ezequiel Garcia

Stefan,

Quoted 41 lines · Stefan Agner
Quoted 30 lines · Uwe Kleine-K?nig

From: Joachim Eastwood <[email protected]>

This patch makes it possible to enter zImage in Thumb mode for ARMv7-M (Cortex-M) CPUs that do not support ARM mode. The kernel entry is also made in Thumb mode.

spelling in commit log, return early in call_cache_fn]

--- Hello,

I just picked up Joachim's patch and fixed the small concerns I had in the last round.

I thought about adding a wrapper for accessing the CPUID registers that are located in cp15 on v7-A/R and memory mapped on v7-M. The corresponding registers and their address are as follows:

name cp15 reg [1] on -A/R address on -M MIDR/CPUID CRm=c0,
opc2=0 0xe000ed00 PFR0 CRm=c1, opc2=0 0xe000ed40 PFR1
CRm=c1, opc2=1 0xe000ed44 DFR0 CRm=c1, opc2=2 0xe000ed48
AFR0 CRm=c1, opc2=3 0xe000ed4c MMFR0 CRm=c1, opc2=4
0xe000ed50 MMFR1 CRm=c1, opc2=5 0xe000ed54 MMFR2 CRm=c1,
opc2=6 0xe000ed58 MMFR3 CRm=c1, opc2=7 0xe000ed5c ISAR0
CRm=c2, opc2=0 0xe000ed60 ISAR1 CRm=c2, opc2=1 0xe000ed64
ISAR2 CRm=c2, opc2=2 0xe000ed68 ISAR3 CRm=c2, opc2=3
0xe000ed6c ISAR4 CRm=c2, opc2=4 0xe000ed70 ISAR5 CRm=c2,
opc2=5 0xe000ed74

Quoted 7 lines

But there is no nice translation and as cache handling is implementation defined on v7-M anyhow there is not much use and I decided to just return early in the cache function.

This patch is only compile tested as I don't have a machine with enough RAM to run a non-XIP kernel, so Tested-by tags are welcome.

Hi Uwe,

Quoted 9 lines

Tried the patch on Vybrid's M4 CPU. Since the M4 has full access to the DDR3 RAM, it is even possible to use AUTO_ZRELADDR for both CPU's: The Colibri VF61 has 256MB of RAM: A5 relocates to 0x80008000, M4 to 0x88008000.

The uncompressing stage seems to work fine, however it seems I hit a different bug which is triggered by using the zImage: Freeing the memory location used by the compressed image seems to fail:

Does this happen systematically for you?

I tried this patch on a LPC4337 based board, and came across very strange and random memory corruptions, ranging from hitting strange WARN(), BUG(), to OOM, to unhandled exceptions.

Quoted 6 lines

Rebuilding the kernel caused the different results (perhaps due to link differences?).

The problem is this machine is not yet mainlined, so I'm not yet sure it's this patch the one to blame.

OK, after fixing the SDRAM config on the LPC43xx board, I managed to test this and it seems to work just fine.

Thanks a lot Uwe!

Signature · 2 lines
Ezequiel Garcia, VanguardiaSur
www.vanguardiasur.com.ar
#6 lore raw

PATCH v6 1/1 ARM: zImage: add support for ARMv7-M

In reply to Stefan Agner

Hello Stefan,

Quoted 6 lines · Stefan Agner
Quoted 2 lines

This patch is only compile tested as I don't have a machine with enough RAM to run a non-XIP kernel, so Tested-by tags are welcome.

Tried the patch on Vybrid's M4 CPU. Since the M4 has full access to the DDR3 RAM, it is even possible to use AUTO_ZRELADDR for both CPU's: The Colibri VF61 has 256MB of RAM: A5 relocates to 0x80008000, M4 to 0x88008000.

Ok, let me summarize what I understood, please correct me if I'm wrong. You have 256 MiB of RAM at address 0x80000000 (same address for both cpus), the A5 uses [0x80000000-0x87ffffff], the M4 uses [0x88000000-0x8fffffff]. To boot the M4

Quoted 3 lines

The uncompressing stage seems to work fine, however it seems I hit a different bug which is triggered by using the zImage: Freeing the memory location used by the compressed image seems to fail:

Does booting an Image work? Does it help to

I don't understand much about all that memory management, but I guess it would help if you add bootmem_debug to the kernel parameters.

Quoted 40 lines

Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
Linux version 3.18.0-10889-ga84c884 (ags at trochilidae) (gcc version 4.8.3 20140401 (prerelease) (Linaro GCC 4.8-2014.04) ) #377 Sat Dec 20 14:08:07 CET 2014
CPU: ARMv7-M [410fc241] revision 1 (ARMv7M), cr=00000000
CPU: unknown data cache, unknown instruction cache
Machine model: VF610 Cortex-M4
bootconsole [earlycon0] enabled
Built 1 zonelists in Zone order, mobility grouping on. Total pages:
12192
Kernel command line: console=ttyLP2,115200 ihash_entries=64 dhash_entries=64 earlyprintk clk_ignore_unused init=/linuxrc rw PID hash table entries: 256 (order: -2, 1024 bytes)
Dentry cache hash table entries: 64 (order: -4, 256 bytes) Inode-cache hash table entries: 64 (order: -4, 256 bytes)

BUG: Bad page state in process swapper  pfn:8c000
page:8f020000 count:0 mapcount:0 mapping:da2fe79e index:0x6e563b3a
flags:
0x4248e05f(locked|error|referenced|uptodate|dirty|active|writeback|head|tail|swapbacked)
page dumped because: PAGE_FLAGS_CHECK_AT_FREE flag(s) set
bad because of flags:
flags: 0x2041(locked|active|writeback)
CPU: 0 PID: 0 Comm: swapper Not tainted 3.18.0-10889-ga84c884 #377
Hardware name: Freescale Vybrid VF610 (Device Tree)
[<8800b129>] (unwind_backtrace) from [<8800a53f>] (show_stack+0xb/0xc)
[<8800a53f>] (show_stack) from [<8803a40d>] (bad_page+0x85/0xb8)
[<8803a40d>] (bad_page) from [<8803a4e9>] (free_pages_prepare+0xa9/0xac)

[<8803a4e9>] (free_pages_prepare) from [<8803b2ed>] (__free_pages_ok+0x19/0x260)
[<8803b2ed>] (__free_pages_ok) from [<881978db>] (free_all_bootmem+0xaf/0xf8)
[<881978db>] (free_all_bootmem) from [<8819201d>] (mem_init+0xb5/0x1c8) [<8819201d>] (mem_init) from [<8818f5af>] (start_kernel+0x17b/0x2c0) [<8818f5af>] (start_kernel) from [<08008023>] (0x8008023)

My loaders output, zImage has been loaded to the region in question (0x8f000080...)

Quoted 6 lines
# ./m4boot zImage initramfs.cpio.lzo vf610m4-colibri.dtb
zImage: 1103944 bytes loaded
initramfs.cpio.lzo: 1632028 bytes loaded
vf610m4-colibri.dtb: 9911 bytes loaded
vf610m4bootldr: 128 bytes copied to 0x8f000000 through 0x8f000080
zImage: 1103944 bytes copied to 0x8f000080 through 0x8f10d8c8

This is a bad location because this overlaps with the final image location. So the zImage is relocated which might overwrite something. I would expect a different failure then, but still, can you try to put the zImage to a different position, say 0x88408000?

Quoted 4 lines

initramfs.cpio.lzo: 1632028 bytes copied to 0x8d000000 through 0x8d18e71c
vf610m4-colibri.dtb: 9979 bytes copied to 0x8fff0000 through 0x8fff26fb Entry point set to 0x0f000001

What is "Entry point" here?

Quoted 5 lines

Argument set to 0x8fff0000
Cortex-M4 started...

Virtual kernel memory layout:

Quoted 8 lines
    vector  : 0x00000000 - 0x00001000   (   4 kB)
    fixmap  : 0xffc00000 - 0xfff00000   (3072 kB)
    vmalloc : 0x00000000 - 0xffffffff   (4095 MB)
    lowmem  : 0x88000000 - 0x8f000000   ( 112 MB)
      .text : 0x88008000 - 0x8818acfc   (1548 kB)
      .init : 0x8818b000 - 0x8819e000   (  76 kB)
      .data : 0x8819e000 - 0x881b2900   (  83 kB)
       .bss : 0x881b2900 - 0x881dc210   ( 167 kB)

You got memory map that from a boot without zImage?

Quoted 5 lines

I used CONFIG_SET_MEM_PARAM and configured the RAM at those fixed values:
CONFIG_DRAM_BASE=0x88000000

CONFIG_DRAM_SIZE=0x08000000

This looks correct.

Best regards
Uwe

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

PATCH v6 1/1 ARM: zImage: add support for ARMv7-M

Quoted 5 lines · Uwe Kleine-K?nig

Hello Stefan,

Quoted 2 lines · Stefan Agner
Quoted 2 lines

This patch is only compile tested as I don't have a machine with enough RAM to run a non-XIP kernel, so Tested-by tags are welcome.

Quoted 8 lines
Quoted 4 lines

Tried the patch on Vybrid's M4 CPU. Since the M4 has full access to the DDR3 RAM, it is even possible to use AUTO_ZRELADDR for both CPU's: The Colibri VF61 has 256MB of RAM: A5 relocates to 0x80008000, M4 to 0x88008000.

Ok, let me summarize what I understood, please correct me if I'm wrong. You have 256 MiB of RAM at address 0x80000000 (same address for both cpus), the A5 uses [0x80000000-0x87ffffff], the M4 uses [0x88000000-0x8fffffff]. To boot the M4

Yes that is it...

Quoted 60 lines
Quoted 4 lines

The uncompressing stage seems to work fine, however it seems I hit a different bug which is triggered by using the zImage: Freeing the memory location used by the compressed image seems to fail:

Does booting an Image work? Does it help to

I don't understand much about all that memory management, but I guess it would help if you add bootmem_debug to the kernel parameters.

Quoted 40 lines

Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
Linux version 3.18.0-10889-ga84c884 (ags at trochilidae) (gcc version 4.8.3 20140401 (prerelease) (Linaro GCC 4.8-2014.04) ) #377 Sat Dec 20 14:08:07 CET 2014
CPU: ARMv7-M [410fc241] revision 1 (ARMv7M), cr=00000000
CPU: unknown data cache, unknown instruction cache
Machine model: VF610 Cortex-M4
bootconsole [earlycon0] enabled
Built 1 zonelists in Zone order, mobility grouping on. Total pages:
12192
Kernel command line: console=ttyLP2,115200 ihash_entries=64 dhash_entries=64 earlyprintk clk_ignore_unused init=/linuxrc rw PID hash table entries: 256 (order: -2, 1024 bytes)
Dentry cache hash table entries: 64 (order: -4, 256 bytes) Inode-cache hash table entries: 64 (order: -4, 256 bytes)

BUG: Bad page state in process swapper  pfn:8c000
page:8f020000 count:0 mapcount:0 mapping:da2fe79e index:0x6e563b3a
flags:
0x4248e05f(locked|error|referenced|uptodate|dirty|active|writeback|head|tail|swapbacked)
page dumped because: PAGE_FLAGS_CHECK_AT_FREE flag(s) set
bad because of flags:
flags: 0x2041(locked|active|writeback)
CPU: 0 PID: 0 Comm: swapper Not tainted 3.18.0-10889-ga84c884 #377
Hardware name: Freescale Vybrid VF610 (Device Tree)
[<8800b129>] (unwind_backtrace) from [<8800a53f>] (show_stack+0xb/0xc)
[<8800a53f>] (show_stack) from [<8803a40d>] (bad_page+0x85/0xb8)
[<8803a40d>] (bad_page) from [<8803a4e9>] (free_pages_prepare+0xa9/0xac)

[<8803a4e9>] (free_pages_prepare) from [<8803b2ed>] (__free_pages_ok+0x19/0x260)
[<8803b2ed>] (__free_pages_ok) from [<881978db>] (free_all_bootmem+0xaf/0xf8)
[<881978db>] (free_all_bootmem) from [<8819201d>] (mem_init+0xb5/0x1c8) [<8819201d>] (mem_init) from [<8818f5af>] (start_kernel+0x17b/0x2c0) [<8818f5af>] (start_kernel) from [<08008023>] (0x8008023)

My loaders output, zImage has been loaded to the region in question (0x8f000080...)

Quoted 6 lines
# ./m4boot zImage initramfs.cpio.lzo vf610m4-colibri.dtb
zImage: 1103944 bytes loaded
initramfs.cpio.lzo: 1632028 bytes loaded
vf610m4-colibri.dtb: 9911 bytes loaded
vf610m4bootldr: 128 bytes copied to 0x8f000000 through 0x8f000080
zImage: 1103944 bytes copied to 0x8f000080 through 0x8f10d8c8

This is a bad location because this overlaps with the final image location. So the zImage is relocated which might overwrite something. I would expect a different failure then, but still, can you try to put the zImage to a different position, say 0x88408000?

Quoted 5 lines
Quoted 4 lines

initramfs.cpio.lzo: 1632028 bytes copied to 0x8d000000 through 0x8d18e71c
vf610m4-colibri.dtb: 9979 bytes copied to 0x8fff0000 through 0x8fff26fb Entry point set to 0x0f000001

What is "Entry point" here?

This is the code bus alias of 0x8f000001.

Quoted 14 lines
Quoted 6 lines

Argument set to 0x8fff0000
Cortex-M4 started...

Virtual kernel memory layout:

Quoted 8 lines
    vector  : 0x00000000 - 0x00001000   (   4 kB)
    fixmap  : 0xffc00000 - 0xfff00000   (3072 kB)
    vmalloc : 0x00000000 - 0xffffffff   (4095 MB)
    lowmem  : 0x88000000 - 0x8f000000   ( 112 MB)
      .text : 0x88008000 - 0x8818acfc   (1548 kB)
      .init : 0x8818b000 - 0x8819e000   (  76 kB)
      .data : 0x8819e000 - 0x881b2900   (  83 kB)
       .bss : 0x881b2900 - 0x881dc210   ( 167 kB)
Quoted 8 lines

You got memory map that from a boot without zImage?

Quoted 5 lines

I used CONFIG_SET_MEM_PARAM and configured the RAM at those fixed values:
CONFIG_DRAM_BASE=0x88000000

CONFIG_DRAM_SIZE=0x08000000

This looks correct.

The problem was on my side: I overwrote the memory layout in my device tree file:

memory {
	reg = <0x8c000000 0x3000000>;"
};

Which is of course a problem since the kernel relocates it to 0x88008000... After fixing this, the zImage booted fine!

So, this patch works as intended:

Fwiw, for Vybrid I likely will still use XIP since this allows to use the code alias quite easily (at least for the kernel...) I'm not aware of a kernel infrastructure which would allow to fetch code generically from the code alias. But would be an interesting feature.

--
Stefan

#8 lore raw

PATCH v6 1/1 ARM: zImage: add support for ARMv7-M

In reply to Uwe Kleine-König

Hi Uwe,

I tested this patch for STM32F429 SoC (Cortex-M4) on STM32F429IDISCOVERY board. After applied this patch on latest Linux Kernel (v4.0-rc4),
I completed the kernel booting (uImage) with u-boot.

Looks good to me of this patch.

Thanks,
Chanwoo Choi

Quoted 158 lines · Uwe Kleine-K?nig

From: Joachim Eastwood <[email protected]>

This patch makes it possible to enter zImage in Thumb mode for ARMv7-M (Cortex-M) CPUs that do not support ARM mode. The kernel entry is also made in Thumb mode.

[ukl: fix spelling in commit log, return early in call_cache_fn]

---
Hello,

I just picked up Joachim's patch and fixed the small concerns I had in the last round.

I thought about adding a wrapper for accessing the CPUID registers that are located in cp15 on v7-A/R and memory mapped on v7-M. The corresponding registers and their address are as follows:

name cp15 reg [1] on -A/R address on -M
MIDR/CPUID CRm=c0, opc2=0 0xe000ed00

PFR0   		CRm=c1, opc2=0  	0xe000ed40
PFR1   		CRm=c1, opc2=1  	0xe000ed44
DFR0   		CRm=c1, opc2=2  	0xe000ed48
AFR0   		CRm=c1, opc2=3  	0xe000ed4c
MMFR0  		CRm=c1, opc2=4  	0xe000ed50
MMFR1  		CRm=c1, opc2=5  	0xe000ed54
MMFR2  		CRm=c1, opc2=6  	0xe000ed58
MMFR3  		CRm=c1, opc2=7  	0xe000ed5c
ISAR0  		CRm=c2, opc2=0  	0xe000ed60
ISAR1  		CRm=c2, opc2=1  	0xe000ed64
ISAR2  		CRm=c2, opc2=2  	0xe000ed68
ISAR3  		CRm=c2, opc2=3  	0xe000ed6c
ISAR4  		CRm=c2, opc2=4  	0xe000ed70
ISAR5  		CRm=c2, opc2=5  	0xe000ed74

But there is no nice translation and as cache handling is implementation defined on v7-M anyhow there is not much use and I decided to just return early in the cache function.

This patch is only compile tested as I don't have a machine with enough RAM to run a non-XIP kernel, so Tested-by tags are welcome.

Best regards
Uwe

[1] all have in common: CRn=c0, opc1=0, so only CRm and opc2 are listed

 arch/arm/boot/compressed/head.S | 33 +++++++++++++++++++++++++++------
 arch/arm/include/asm/unified.h  |  8 ++++++++
 2 files changed, 35 insertions(+), 6 deletions(-)
arch/arm/boot/compressed/head.S +27 -6
index 68be9017593d..3788eedabb15 100644
@@ -10,8 +10,11 @@
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include <asm/v7m.h>
+
+ AR_CLASS(	.arch	armv7-a	)
+ M_CLASS(	.arch	armv7-m	)
 
-	.arch	armv7-a
 /*
  * Debugging stuff
  *
@@ -114,7 +117,12 @@
  * sort out different calling conventions
  */
 		.align
-		.arm				@ Always enter in ARM state
+		/*
+		 * Always enter in ARM state for CPUs that support the ARM ISA.
+		 * As of today (2014) that's exactly the members of the A and R
+		 * classes.
+		 */
+ AR_CLASS(	.arm	)
 start:
 		.type	start,#function
 		.rept	7
@@ -132,14 +140,15 @@ start:
 
  THUMB(		.thumb			)
 1:
- ARM_BE8(	setend	be )			@ go BE8 if compiled for BE8
-		mrs	r9, cpsr
+ ARM_BE8(	setend	be		)	@ go BE8 if compiled for BE8
+ AR_CLASS(	mrs	r9, cpsr	)
 #ifdef CONFIG_ARM_VIRT_EXT
 		bl	__hyp_stub_install	@ get into SVC mode, reversibly
 #endif
 		mov	r7, r1			@ save architecture ID
 		mov	r8, r2			@ save atags pointer
 
+#ifndef CONFIG_CPU_V7M
 		/*
 		 * Booting from Angel - need to enter SVC mode and disable
 		 * FIQs/IRQs (numeric definitions from angel arm.h source).
@@ -155,6 +164,7 @@ not_angel:
 		safe_svcmode_maskall r0
 		msr	spsr_cxsf, r9		@ Save the CPU boot mode in
 						@ SPSR
+#endif
 		/*
 		 * Note that some cache flushing and other stuff may
 		 * be needed here - is there an Angel SWI call for this?
@@ -789,6 +799,16 @@ __common_mmu_cache_on:
 call_cache_fn:	adr	r12, proc_types
 #ifdef CONFIG_CPU_CP15
 		mrc	p15, 0, r9, c0, c0	@ get processor ID
+#elif defined(CONFIG_CPU_V7M)
+		/*
+		 * On v7-M the processor id is located in the V7M_SCB_CPUID
+		 * register, but as cache handling is IMPLEMENTATION DEFINED on
+		 * v7-M (if existant at all) we just return early here.
+		 * If V7M_SCB_CPUID were used the cpu ID functions (i.e.
+		 * __armv7_mmu_cache_{on,off,flush}) would be selected which
+		 * use cp15 registers that are not implemented on v7-M.
+		 */
+		bx	lr
 #else
 		ldr	r9, =CONFIG_PROCESSOR_ID
 #endif
@@ -1289,8 +1309,9 @@ __hyp_reentry_vectors:
 
 __enter_kernel:
 		mov	r0, #0			@ must be 0
- ARM(		mov	pc, r4	)		@ call kernel
- THUMB(		bx	r4	)		@ entry point is always ARM
+ ARM(		mov	pc, r4		)	@ call kernel
+ M_CLASS(	add	r4, r4, #1	)	@ enter in Thumb mode for M class
+ THUMB(		bx	r4		)	@ entry point is always ARM for A/R classes
 
 reloc_code_end:
 
arch/arm/include/asm/unified.h +8 -0
index b88beaba6b4a..200f9a7cd623 100644
@@ -24,6 +24,14 @@
 	.syntax unified
 #endif
 
+#ifdef CONFIG_CPU_V7M
+#define AR_CLASS(x...)
+#define M_CLASS(x...)	x
+#else
+#define AR_CLASS(x...)	x
+#define M_CLASS(x...)
+#endif
+
 #ifdef CONFIG_THUMB2_KERNEL
 
 #if __GNUC__ < 4
#9 lore raw

PATCH v6 1/1 ARM: zImage: add support for ARMv7-M

Hello,

Quoted 9 lines · Chanwoo Choi

Hi Uwe,

I tested this patch for STM32F429 SoC (Cortex-M4) on STM32F429IDISCOVERY board. After applied this patch on latest Linux Kernel (v4.0-rc4),
I completed the kernel booting (uImage) with u-boot.

Looks good to me of this patch.

oh, I thought this patch to be applied since long already. I just submitted it to rmk's patch tracker with your tested-by.

Thanks
Uwe

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