[PATCH v6] ARM: zImage: add support for ARMv7-M
Stefan Agner
stefan at agner.ch
Sat Dec 20 05:33:16 PST 2014
On 2014-12-17 09:56, Uwe Kleine-König wrote:
> From: Joachim Eastwood <manabian at 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 at gmail.com>
> [ukl: fix spelling in commit log, return early in call_cache_fn]
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig at 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 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
>
> 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
More information about the linux-arm-kernel
mailing list