diff mbox

[v6] ARM: zImage: add support for ARMv7-M

Message ID 1418806573-14897-1-git-send-email-u.kleine-koenig@pengutronix.de
State New
Headers show

Commit Message

Uwe Kleine-König Dec. 17, 2014, 8:56 a.m. UTC
From: Joachim Eastwood <manabian@gmail.com>

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.

Signed-off-by: Joachim Eastwood <manabian@gmail.com>
[ukl: fix spelling in commit log, return early in call_cache_fn]
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
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(-)

Comments

Stefan Agner Dec. 20, 2014, 1:33 p.m. UTC | #1
On 2014-12-17 09:56, Uwe Kleine-König wrote:
> From: Joachim Eastwood <manabian@gmail.com>
> 
> 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.
> 
> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
> [ukl: fix spelling in commit log, return early in call_cache_fn]
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> ---
> 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.

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


> 
> 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(-)
> 
> diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
> index 68be9017593d..3788eedabb15 100644
> --- a/arch/arm/boot/compressed/head.S
> +++ b/arch/arm/boot/compressed/head.S
> @@ -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:
>  
> diff --git a/arch/arm/include/asm/unified.h b/arch/arm/include/asm/unified.h
> index b88beaba6b4a..200f9a7cd623 100644
> --- a/arch/arm/include/asm/unified.h
> +++ b/arch/arm/include/asm/unified.h
> @@ -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
Ezequiel Garcia Dec. 20, 2014, 7:12 p.m. UTC | #2
Stefan,

On 12/20/2014 10:33 AM, Stefan Agner wrote:
> On 2014-12-17 09:56, Uwe Kleine-König wrote:
>> From: Joachim Eastwood <manabian@gmail.com>
>>
>> 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.
>>
>> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
>> [ukl: fix spelling in commit log, return early in call_cache_fn]
>> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
>> ---
>> 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.
> 
> 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:
> 

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.
Stefan Agner Dec. 20, 2014, 10:48 p.m. UTC | #3
On 2014-12-20 20:12, Ezequiel Garcia wrote:
> Stefan,
> 
> On 12/20/2014 10:33 AM, Stefan Agner wrote:
>> On 2014-12-17 09:56, Uwe Kleine-König wrote:
>>> From: Joachim Eastwood <manabian@gmail.com>
>>>
>>> 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.
>>>
>>> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
>>> [ukl: fix spelling in commit log, return early in call_cache_fn]
>>> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
>>> ---
>>> 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.
>>
>> 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:
>>
> 
> Does this happen systematically for you?

Yes, that happens all the time, same address.

> 
> 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
Ezequiel Garcia Dec. 20, 2014, 11:28 p.m. UTC | #4
On 12/20/2014 07:48 PM, Stefan Agner wrote:
> On 2014-12-20 20:12, Ezequiel Garcia wrote:
>> Stefan,
>>
>> On 12/20/2014 10:33 AM, Stefan Agner wrote:
>>> On 2014-12-17 09:56, Uwe Kleine-König wrote:
>>>> From: Joachim Eastwood <manabian@gmail.com>
>>>>
>>>> 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.
>>>>
>>>> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
>>>> [ukl: fix spelling in commit log, return early in call_cache_fn]
>>>> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
>>>> ---
>>>> 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.
>>>
>>> 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:
>>>
>>
>> Does this happen systematically for you?
> 
> Yes, that happens all the time, same address.
> 
>>
>> 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?
> 

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

> 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).
Uwe Kleine-König Dec. 21, 2014, 10:25 a.m. UTC | #5
Hello Stefan,

On Sat, Dec 20, 2014 at 02:33:16PM +0100, Stefan Agner wrote:
> > 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 

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

> Uncompressing Linux... done, booting the kernel.
> Booting Linux on physical CPU 0x0
> Linux version 3.18.0-10889-ga84c884 (ags@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
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?

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

> 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)
You got memory map that from a boot without zImage?

> 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
Stefan Agner Dec. 27, 2014, 10:53 p.m. UTC | #6
On 2014-12-21 11:25, Uwe Kleine-König wrote:
> Hello Stefan,
> 
> On Sat, Dec 20, 2014 at 02:33:16PM +0100, Stefan Agner wrote:
>> > 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 

Yes that is it...

> 
>> 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.
> 
>> Uncompressing Linux... done, booting the kernel.
>> Booting Linux on physical CPU 0x0
>> Linux version 3.18.0-10889-ga84c884 (ags@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
> 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?
> 
>> 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.

> 
>> 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)
> You got memory map that from a boot without zImage?
> 
>> 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:
Tested-by: Stefan Agner <stefan@agner.ch>

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
Ezequiel Garcia Dec. 29, 2014, 12:02 p.m. UTC | #7
On 12/20/2014 04:12 PM, Ezequiel Garcia wrote:
> Stefan,
> 
> On 12/20/2014 10:33 AM, Stefan Agner wrote:
>> On 2014-12-17 09:56, Uwe Kleine-König wrote:
>>> From: Joachim Eastwood <manabian@gmail.com>
>>> 
>>> 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.
>>> 
>>> Signed-off-by: Joachim Eastwood <manabian@gmail.com> [ukl: fix
>>> spelling in commit log, return early in call_cache_fn] 
>>> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> 
>>> --- 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.
>> 
>> 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:
>> 
> 
> 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.
> 

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

Tested-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>

Thanks a lot Uwe!
Chanwoo Choi March 25, 2015, 12:13 a.m. UTC | #8
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.

Tested-by: Chanwoo Choi <cw00.choi@samsung.com>

Thanks,
Chanwoo Choi

On 12/17/2014 05:56 PM, Uwe Kleine-König wrote:
> From: Joachim Eastwood <manabian@gmail.com>
> 
> 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.
> 
> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
> [ukl: fix spelling in commit log, return early in call_cache_fn]
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> ---
> 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(-)
> 
> diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
> index 68be9017593d..3788eedabb15 100644
> --- a/arch/arm/boot/compressed/head.S
> +++ b/arch/arm/boot/compressed/head.S
> @@ -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:
>  
> diff --git a/arch/arm/include/asm/unified.h b/arch/arm/include/asm/unified.h
> index b88beaba6b4a..200f9a7cd623 100644
> --- a/arch/arm/include/asm/unified.h
> +++ b/arch/arm/include/asm/unified.h
> @@ -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
>
Uwe Kleine-König March 25, 2015, 7:47 a.m. UTC | #9
Hello,

On Wed, Mar 25, 2015 at 09:13:28AM +0900, Chanwoo Choi wrote:
> 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.
> 
> Tested-by: Chanwoo Choi <cw00.choi@samsung.com>
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
diff mbox

Patch

diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 68be9017593d..3788eedabb15 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -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:
 
diff --git a/arch/arm/include/asm/unified.h b/arch/arm/include/asm/unified.h
index b88beaba6b4a..200f9a7cd623 100644
--- a/arch/arm/include/asm/unified.h
+++ b/arch/arm/include/asm/unified.h
@@ -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