From: York Sun <yorksun@freescale.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [Patch v2 3/5] armv8/fsl-lsch3: Release secondary cores from boot hold off with Boot Page
Date: Thu, 21 Aug 2014 11:32:53 -0700 [thread overview]
Message-ID: <53F63B55.3040900@freescale.com> (raw)
In-Reply-To: <20140821134724.GM21734@leverpostej>
On 08/21/2014 06:47 AM, Mark Rutland wrote:
> Hi York,
>
> I have mostly minor comments this time; this is looking pretty good.
>
> On Tue, Aug 19, 2014 at 09:28:00PM +0100, York Sun wrote:
>> Secondary cores need to be released from holdoff by boot release
>> registers. With GPP bootrom, they can boot from main memory
>> directly. Individual spin table is used for each core. If a single
>> release address is needed, defining macro CONFIG_FSL_SMP_RELEASE_ALL
>> will use the CPU_RELEASE_ADDR. Spin table and the boot page is reserved
>> in device tree so OS won't overwrite.
>>
>> Signed-off-by: York Sun <yorksun@freescale.com>
>> Signed-off-by: Arnab Basu <arnab.basu@freescale.com>
>> ---
>> v2: Removed copying boot page. Use u-boot image as is in memory.
>> Added dealing with different size of addr_cell in device tree.
>> Added dealing with big- and little-endian.
>> Added flushing spin table after cpu_release().
>>
>> arch/arm/cpu/armv8/fsl-lsch3/Makefile | 2 +
>> arch/arm/cpu/armv8/fsl-lsch3/cpu.c | 13 ++
>> arch/arm/cpu/armv8/fsl-lsch3/cpu.h | 1 +
>> arch/arm/cpu/armv8/fsl-lsch3/fdt.c | 56 +++++++
>> arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S | 128 ++++++++++++---
>> arch/arm/cpu/armv8/fsl-lsch3/mp.c | 172 +++++++++++++++++++++
>> arch/arm/cpu/armv8/fsl-lsch3/mp.h | 36 +++++
>> arch/arm/cpu/armv8/transition.S | 63 +-------
>> arch/arm/include/asm/arch-fsl-lsch3/config.h | 3 +-
>> arch/arm/include/asm/arch-fsl-lsch3/immap_lsch3.h | 35 +++++
>> arch/arm/include/asm/macro.h | 92 +++++++++++
>> arch/arm/lib/gic_64.S | 10 +-
>> common/board_f.c | 2 +-
>> 13 files changed, 525 insertions(+), 88 deletions(-)
>> create mode 100644 arch/arm/cpu/armv8/fsl-lsch3/fdt.c
>> create mode 100644 arch/arm/cpu/armv8/fsl-lsch3/mp.c
>> create mode 100644 arch/arm/cpu/armv8/fsl-lsch3/mp.h
>>
>> diff --git a/arch/arm/cpu/armv8/fsl-lsch3/Makefile b/arch/arm/cpu/armv8/fsl-lsch3/Makefile
>> index 9249537..f920eeb 100644
>> --- a/arch/arm/cpu/armv8/fsl-lsch3/Makefile
>> +++ b/arch/arm/cpu/armv8/fsl-lsch3/Makefile
>> @@ -7,3 +7,5 @@
>> obj-y += cpu.o
>> obj-y += lowlevel.o
>> obj-y += speed.o
>> +obj-$(CONFIG_MP) += mp.o
>> +obj-$(CONFIG_OF_LIBFDT) += fdt.o
>> diff --git a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
>> index c129d03..47b947f 100644
>> --- a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
>> +++ b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
>> @@ -11,6 +11,7 @@
>> #include <asm/io.h>
>> #include <asm/arch-fsl-lsch3/immap_lsch3.h>
>> #include "cpu.h"
>> +#include "mp.h"
>> #include "speed.h"
>> #include <fsl_mc.h>
>>
>> @@ -434,3 +435,15 @@ int cpu_eth_init(bd_t *bis)
>> #endif
>> return error;
>> }
>> +
>> +
>> +int arch_early_init_r(void)
>> +{
>> + int rv;
>> + rv = fsl_lsch3_wake_seconday_cores();
>> +
>> + if (rv)
>> + printf("Did not wake secondary cores\n");
>> +
>> + return 0;
>> +}
>> diff --git a/arch/arm/cpu/armv8/fsl-lsch3/cpu.h b/arch/arm/cpu/armv8/fsl-lsch3/cpu.h
>> index 28544d7..2e3312b 100644
>> --- a/arch/arm/cpu/armv8/fsl-lsch3/cpu.h
>> +++ b/arch/arm/cpu/armv8/fsl-lsch3/cpu.h
>> @@ -5,3 +5,4 @@
>> */
>>
>> int fsl_qoriq_core_to_cluster(unsigned int core);
>> +u32 cpu_mask(void);
>> diff --git a/arch/arm/cpu/armv8/fsl-lsch3/fdt.c b/arch/arm/cpu/armv8/fsl-lsch3/fdt.c
>> new file mode 100644
>> index 0000000..2dbcdcb
>> --- /dev/null
>> +++ b/arch/arm/cpu/armv8/fsl-lsch3/fdt.c
>> @@ -0,0 +1,56 @@
>> +/*
>> + * Copyright 2014 Freescale Semiconductor, Inc.
>> + *
>> + * SPDX-License-Identifier: GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <libfdt.h>
>> +#include <fdt_support.h>
>> +#include "mp.h"
>> +
>> +#ifdef CONFIG_MP
>> +void ft_fixup_cpu(void *blob)
>> +{
>> + int off;
>> + __maybe_unused u64 spin_tbl_addr = (u64)get_spin_tbl_addr();
>> + fdt32_t *reg;
>> + int addr_cells;
>> + u64 val;
>> + size_t *boot_code_size = &(__secondary_boot_code_size);
>> +
>> + off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpus", 4);
>
> I didn't think /cpus had device_type = "cpus". I can't see any
> instances in any DTs I have to hand. Can we not find /cpus by path?
I will let Arnab to comment on this. He is coordinating with Linux device tree.
>
>> + of_bus_default_count_cells(blob, off, &addr_cells, NULL);
>> +
>> + off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
>> + while (off != -FDT_ERR_NOTFOUND) {
>> + reg = (fdt32_t *)fdt_getprop(blob, off, "reg", 0);
>> + if (reg) {
>> + val = spin_tbl_addr;
>> +#ifndef CONFIG_FSL_SMP_RELEASE_ALL
>> + val += id_to_core(of_read_number(reg, addr_cells))
>> + * SPIN_TABLE_ELEM_SIZE;
>> +#endif
>> + val = cpu_to_fdt64(val);
>> + fdt_setprop_string(blob, off, "enable-method",
>> + "spin-table");
>> + fdt_setprop(blob, off, "cpu-release-addr",
>> + &val, sizeof(val));
>> + } else {
>> + puts("cpu NULL\n");
>
> Could we change that to "Warning: found cpu node without reg property"
> or something like that which makes the problem clear?
Yes, we can.
>
>> + }
>> + off = fdt_node_offset_by_prop_value(blob, off, "device_type",
>> + "cpu", 4);
>> + }
>> +
>> + fdt_add_mem_rsv(blob, (uintptr_t)&secondary_boot_code,
>> + *boot_code_size);
>> +}
>> +#endif
>> +
>> +void ft_cpu_setup(void *blob, bd_t *bd)
>> +{
>> +#ifdef CONFIG_MP
>> + ft_fixup_cpu(blob);
>> +#endif
>> +}
>> diff --git a/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S b/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S
>> index ad32b6c..629e6d4 100644
>> --- a/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S
>> +++ b/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S
>> @@ -8,7 +8,9 @@
>>
>> #include <config.h>
>> #include <linux/linkage.h>
>> +#include <asm/gic.h>
>> #include <asm/macro.h>
>> +#include "mp.h"
>>
>> ENTRY(lowlevel_init)
>> mov x29, lr /* Save LR */
>> @@ -37,29 +39,119 @@ ENTRY(lowlevel_init)
>>
>> branch_if_master x0, x1, 1f
>>
>> + ldr x0, =secondary_boot_func
>> + blr x0
>> +
>> +1:
>> +2:
>
> Isn't the '2' label redundant?
We have some internal code dealing with trust zone between the 1 and 2. It is
not likely to be used in long term since we are trying to move them into
security monitor. I can drop label 2 here.
>
>> + mov lr, x29 /* Restore LR */
>> + ret
>> +ENDPROC(lowlevel_init)
>> +
>> + /* Keep literals not used by the secondary boot code outside it */
>> + .ltorg
>> +
>> + /* Using 64 bit alignment since the spin table is accessed as data */
>> + .align 4
>> + .global secondary_boot_code
>> + /* Secondary Boot Code starts here */
>> +secondary_boot_code:
>> + .global __spin_table
>> +__spin_table:
>> + .space CONFIG_MAX_CPUS*SPIN_TABLE_ELEM_SIZE
>> +
>> + .align 2
>> +ENTRY(secondary_boot_func)
>> /*
>> - * Slave should wait for master clearing spin table.
>> - * This sync prevent salves observing incorrect
>> - * value of spin table and jumping to wrong place.
>> + * MPIDR_EL1 Fields:
>> + * MPIDR[1:0] = AFF0_CPUID <- Core ID (0,1)
>> + * MPIDR[7:2] = AFF0_RES
>> + * MPIDR[15:8] = AFF1_CLUSTERID <- Cluster ID (0,1,2,3)
>> + * MPIDR[23:16] = AFF2_CLUSTERID
>> + * MPIDR[24] = MT
>> + * MPIDR[29:25] = RES0
>> + * MPIDR[30] = U
>> + * MPIDR[31] = ME
>> + * MPIDR[39:32] = AFF3
>> + *
>> + * Linear Processor ID (LPID) calculation from MPIDR_EL1:
>> + * (We only use AFF0_CPUID and AFF1_CLUSTERID for now
>> + * until AFF2_CLUSTERID and AFF3 have non-zero values)
>> + *
>> + * LPID = MPIDR[15:8] | MPIDR[1:0]
>> */
>> -#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
>> -#ifdef CONFIG_GICV2
>> - ldr x0, =GICC_BASE
>> + mrs x0, mpidr_el1
>> + ubfm x1, x0, #8, #15
>> + ubfm x2, x0, #0, #1
>> + orr x10, x2, x1, lsl #2 /* x10 has LPID */
>> + ubfm x9, x0, #0, #15 /* x9 contains MPIDR[15:0] */
>> + /*
>> + * offset of the spin table element for this core from start of spin
>> + * table (each elem is padded to 64 bytes)
>> + */
>> + lsl x1, x10, #6
>> + ldr x0, =__spin_table
>> + /* physical address of this cpus spin table element */
>> + add x11, x1, x0
>> +
>> + str x9, [x11, #16] /* LPID */
>> + mov x4, #1
>> + str x4, [x11, #8] /* STATUS */
>> + dsb sy
>> +#if defined(CONFIG_GICV3)
>> + gic_wait_for_interrupt_m x0
>> #endif
>> - bl gic_wait_for_interrupt
>
> Why do we only need to wait for GICv3? We previously did so for GICv2.
I think this is leftover from the attempt to boot all cores simultaneously. I
will let Arnab to comment.
>
>> +
>> + bl secondary_switch_to_el2
>> +#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
>> + secondary_switch_to_el1
>> #endif
>
> Missing bl?
Looks so.
>
> Is there any reason to have the SWITCH_TO_EL1 option other than for
> debugging?
Good question. I will let Arnab to comment here.
>
> EL2 is the preferred EL to boot at for Linux and Xen (it gives far more
> flexibility), and if dropping to EL1 is necessary I think it would make
> more sense as a run-time option than a compile-time option.
>
>>
>> - /*
>> - * All processors will enter EL2 and optionally EL1.
>> +slave_cpu:
>> + wfe
>> +#ifdef CONFIG_FSL_SMP_RELEASE_ALL
>> + /* All cores are released from the address in the 1st spin table
>> + * element
>> */
>> - bl armv8_switch_to_el2
>> -#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
>> - bl armv8_switch_to_el1
>> + ldr x1, =__spin_table
>> + ldr x0, [x1]
>> +#else
>> + ldr x0, [x11]
>> +#endif
>> + cbz x0, slave_cpu
>
> Similarly is there any reason to have the option of a single release
> addr if we can support unique addresses?
I think it was used by Linux for some ARM parts. I personally not a fun of using
single release. But if it makes everyone happy, I can keep it.
>
> [...]
>
>> diff --git a/arch/arm/cpu/armv8/fsl-lsch3/mp.c b/arch/arm/cpu/armv8/fsl-lsch3/mp.c
>> new file mode 100644
>> index 0000000..b29eda9
>> --- /dev/null
>> +++ b/arch/arm/cpu/armv8/fsl-lsch3/mp.c
>> @@ -0,0 +1,172 @@
>> +/*
>> + * Copyright 2014 Freescale Semiconductor, Inc.
>> + *
>> + * SPDX-License-Identifier: GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <asm/io.h>
>> +#include <asm/system.h>
>> +#include <asm/io.h>
>> +#include <asm/arch-fsl-lsch3/immap_lsch3.h>
>> +#include "mp.h"
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +void *get_spin_tbl_addr(void)
>> +{
>> + void *ptr = (void *)&__spin_table;
>> +
>> + return ptr;
>> +}
>
> I don't think the cast is necessary here. As far as I can see this
> could be just:
>
> void *get_spin_tbl_addr(void)
> {
> return &__spin_table;
> }
>
Let me try that.
> [...]
>
>> diff --git a/arch/arm/include/asm/macro.h b/arch/arm/include/asm/macro.h
>> index f77e4b8..0009c28 100644
>> --- a/arch/arm/include/asm/macro.h
>> +++ b/arch/arm/include/asm/macro.h
>> @@ -105,6 +105,98 @@ lr .req x30
>> cbz \xreg1, \master_label
>> .endm
>>
>> +.macro armv8_switch_to_el2_m, xreg1
>> + mov \xreg1, #0x5b1 /* Non-secure EL0/EL1 | HVC | 64bit EL2 */
>> + msr scr_el3, \xreg1
>
> When dropping to EL1 from EL2 we disable HVC via HCR_EL2; presumably due
> to lack of a handler. Would it make sense to do similarly here and
> disable SMC here until we have a user (e.g. PSCI)?
I will let Arnab to comment here.
York
next prev parent reply other threads:[~2014-08-21 18:32 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-19 20:27 [U-Boot] [Patch v2 1/5] fdt_support: Move of_read_number to fdt_support.h York Sun
2014-08-19 20:27 ` [U-Boot] [Patch v2 2/5] fdt_support: Make of_bus_default_count_cells non static York Sun
2014-08-19 20:28 ` [U-Boot] [Patch v2 3/5] armv8/fsl-lsch3: Release secondary cores from boot hold off with Boot Page York Sun
2014-08-21 13:47 ` Mark Rutland
2014-08-21 18:32 ` York Sun [this message]
2014-08-21 18:50 ` bhupesh.sharma at freescale.com
2014-08-22 7:02 ` Arnab Basu
2014-08-22 11:24 ` Mark Rutland
2014-08-22 11:38 ` Mark Rutland
2014-08-22 11:41 ` Mark Rutland
2014-08-19 20:28 ` [U-Boot] [Patch v2 4/5] ARMv8/ls2085a: Enable secondary cores York Sun
2014-08-19 20:28 ` [U-Boot] [Patch v2 5/5] ARMv8/ls2085a: Move u-boot location to make room for RCW York Sun
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=53F63B55.3040900@freescale.com \
--to=yorksun@freescale.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.