[RFC PATCH 3/4] ARM64: Big Endian fixes for kernel booting

Ankit Jindal ankit.jindal at linaro.org
Fri Oct 11 08:52:34 EDT 2013


On 11 October 2013 17:52, Ankit Jindal <ankit.jindal at linaro.org> wrote:
>
> - Enable appropriate bits for big endian kernel in SYSCTLR.EL2 and
>   SYSCTLR.EL1 registers
> - Swap entry point for secondary core for big endian kernel
> - Set machine type to "aarch64b" for big endian and "aarch64l"
>   for little endian.
>
> Signed-off-by: Ankit Jindal <ankit.jindal at linaro.org>
> Signed-off-by: Tushar Jagad <tushar.jagad at linaro.org>
> ---
>  arch/arm64/include/asm/assembler.h |    7 +++++++
>  arch/arm64/kernel/head.S           |   34 ++++++++++++++++++++++++++++++++++
>  arch/arm64/kernel/setup.c          |   19 +++++++++++++++----
>  arch/arm64/kernel/smp_spin_table.c |    5 +++--
>  arch/arm64/mm/proc.S               |    2 +-
>  5 files changed, 60 insertions(+), 7 deletions(-)
>
> diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
> index 5aceb83..473faf3 100644
> --- a/arch/arm64/include/asm/assembler.h
> +++ b/arch/arm64/include/asm/assembler.h
> @@ -22,6 +22,13 @@
>
>  #include <asm/ptrace.h>
>
> +/* Select code for any configuration running in BE mode */
> +#ifdef CONFIG_CPU_BIG_ENDIAN
> +#define ARM_BE(code...) code
> +#else
> +#define ARM_BE(code...)
> +#endif
> +
>  /*
>   * Stack pushing/popping (register pairs only). Equivalent to store decrement
>   * before, load increment after.
> diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
> index 7090c12..45dc50d 100644
> --- a/arch/arm64/kernel/head.S
> +++ b/arch/arm64/kernel/head.S
> @@ -122,6 +122,7 @@
>         .word   0                               // reserved
>
>  ENTRY(stext)
> +       ARM_BE(bl      setend_be)
>         mov     x21, x0                         // x21=FDT
>         bl      __calc_phys_offset              // x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET
>         bl      el2_setup                       // Drop to EL1
> @@ -148,6 +149,34 @@ ENTRY(stext)
>  ENDPROC(stext)
>
>  /*
> + * Set el0-el1-el2 to Big endian
> + */
> +
> +#if defined(CONFIG_CPU_BIG_ENDIAN)
> +ENTRY(setend_be)
> +       mrs     x21, CurrentEL
> +        cmp     x21, #PSR_MODE_EL2t
> +       b.ne    setend_be_el1_el0
> +
> +setend_be_el2:
> +       mrs     x21, sctlr_el2
> +        mov     x22, #(1<<25)
> +        orr     x21, x21, x22
> +        msr     sctlr_el2, x21
> +       isb
> +
> +setend_be_el1_el0:
> +       mrs     x21, sctlr_el1
> +        mov     x22, #(3<<24)
> +        orr     x21, x21, x22
> +        msr     sctlr_el1, x21
> +       isb
> +
> +       ret
> +ENDPROC(setend_be)
> +#endif /* defined(CONFIG_CPU_BIG_ENDIAN) */
> +
> +/*
>   * If we're fortunate enough to boot at EL2, ensure that the world is
>   * sane before dropping to EL1.
>   */
> @@ -181,7 +210,11 @@ ENTRY(el2_setup)
>
>         /* sctlr_el1 */
>         mov     x0, #0x0800                     // Set/clear RES{1,0} bits
> +#if defined(CONFIG_CPU_BIG_ENDIAN)
> +       movk    x0, #0x33d0, lsl #16
> +#else
>         movk    x0, #0x30d0, lsl #16
> +#endif
>         msr     sctlr_el1, x0
>
>         /* Coprocessor traps. */
> @@ -235,6 +268,7 @@ ENTRY(__boot_cpu_mode)
>          * cores are held until we're ready for them to initialise.
>          */
>  ENTRY(secondary_holding_pen)
> +       ARM_BE(bl       setend_be)
>         bl      __calc_phys_offset              // x24=phys offset
>         bl      el2_setup                       // Drop to EL1
>         mrs     x0, mpidr_el1
> diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
> index 055cfb8..d47ae6d 100644
> --- a/arch/arm64/kernel/setup.c
> +++ b/arch/arm64/kernel/setup.c
> @@ -64,6 +64,9 @@ static const char *cpu_name;
>  static const char *machine_name;
>  phys_addr_t __fdt_pointer __initdata;
>
> +static union { char c[8]; unsigned long l; } endian_test = { { 'l', '?', '?',  '?', '?', '?', '?','b' } };
> +#define ENDIANNESS ((char)endian_test.l)
> +
>  /*
>   * Standard memory resources
>   */
> @@ -117,8 +120,10 @@ static void __init setup_processor(void)
>
>         printk("CPU: %s [%08x] revision %d\n",
>                cpu_name, read_cpuid_id(), read_cpuid_id() & 15);
> -
> -       sprintf(init_utsname()->machine, "aarch64");
> +
> +       snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c",
> +                 "aarch64", ENDIANNESS);
> +
>         elf_hwcap = 0;
>  }
>
> @@ -310,9 +315,15 @@ static const char *hwcap_str[] = {
>  static int c_show(struct seq_file *m, void *v)
>  {
>         int i;
> +#if 0
> +       int num = 1;
> +       char c;
> +       char *cptr = (char *)#
> +       c = (*cptr) ? 'l' : 'b';
> +#endif

Oops, forgot to remove this #if 0. Please ignore this small change.

>
> -       seq_printf(m, "Processor\t: %s rev %d (%s)\n",
> -                  cpu_name, read_cpuid_id() & 15, ELF_PLATFORM);
> +       seq_printf(m, "Processor\t: %s rev %d (%s%c)\n",
> +                  cpu_name, read_cpuid_id() & 15, ELF_PLATFORM, ENDIANNESS);
>
>         for_each_online_cpu(i) {
>                 /*
> diff --git a/arch/arm64/kernel/smp_spin_table.c b/arch/arm64/kernel/smp_spin_table.c
> index 7c35fa6..7ad68bc 100644
> --- a/arch/arm64/kernel/smp_spin_table.c
> +++ b/arch/arm64/kernel/smp_spin_table.c
> @@ -46,9 +46,10 @@ static int __init smp_spin_table_prepare_cpu(int cpu)
>
>         if (!cpu_release_addr[cpu])
>                 return -ENODEV;
> -
> +
>         release_addr = __va(cpu_release_addr[cpu]);
> -       release_addr[0] = (void *)__pa(secondary_holding_pen);
> +       release_addr[0] = (void *)cpu_to_le64(__pa(secondary_holding_pen));
> +
>         __flush_dcache_area(release_addr, sizeof(release_addr[0]));
>
>         /*
> diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
> index b1b31bb..380a707 100644
> --- a/arch/arm64/mm/proc.S
> +++ b/arch/arm64/mm/proc.S
> @@ -166,5 +166,5 @@ ENDPROC(__cpu_setup)
>          */
>         .type   crval, #object
>  crval:
> -       .word   0x030802e2                      // clear
> +       .word   0x000802e2                      // clear
>         .word   0x0405d11d                      // set
> --
> 1.7.9.5
>



More information about the linux-arm-kernel mailing list