On 03/13/2018 04:34 PM, Peter Maydell wrote: > The raspi3 has AArch64 CPUs, which means that our smpboot > code for keeping the secondary CPUs in a pen needs to have > a version for A64 as well as A32. Without this, the > secondary CPUs go into an infinite loop of taking undefined > instruction exceptions. > > Signed-off-by: Peter Maydell <peter.mayd...@linaro.org> > --- > hw/arm/raspi.c | 41 ++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 40 insertions(+), 1 deletion(-) > > diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c > index ae15997669..06f1e08ca9 100644 > --- a/hw/arm/raspi.c > +++ b/hw/arm/raspi.c > @@ -27,6 +27,7 @@ > #define BOARDSETUP_ADDR (MVBAR_ADDR + 0x20) /* board setup code */ > #define FIRMWARE_ADDR_2 0x8000 /* Pi 2 loads kernel.img here by default */ > #define FIRMWARE_ADDR_3 0x80000 /* Pi 3 loads kernel.img here by default */ > +#define SPINTABLE_ADDR 0xd8 /* Pi 3 bootloader spintable */ > > /* Table of Linux board IDs for different Pi versions */ > static const int raspi_boardid[] = {[1] = 0xc42, [2] = 0xc43, [3] = 0xc44}; > @@ -63,6 +64,40 @@ static void write_smpboot(ARMCPU *cpu, const struct > arm_boot_info *info) > info->smp_loader_start); > } > > +static void write_smpboot64(ARMCPU *cpu, const struct arm_boot_info *info) > +{ > + /* Unlike the AArch32 version we don't need to call the board setup hook. > + * The mechanism for doing the spin-table is also entirely different. > + * We must have four 64-bit fields at absolute addresses > + * 0xd8, 0xe0, 0xe8, 0xf0 in RAM, which are the flag variables for > + * our CPUs, and which we must ensure are zero initialized before > + * the primary CPU goes into the kernel. We put these variables inside > + * a rom blob, so that the reset for ROM contents zeroes them for us. > + */
Checking with Linux doc/Documentation/arm64/booting.txt and arch/arm/boot/dts/bcm2837.dtsi. > + static const uint32_t smpboot[] = { > + 0xd2801b05, /* mov x5, 0xd8 */ x5 = &spintable; > + 0xd53800a6, /* mrs x6, mpidr_el1 */ > + 0x924004c6, /* and x6, x6, #0x3 */ x6 = clusterid; > + 0xd503205f, /* spin: wfe */ > + 0xf86678a4, /* ldr x4, [x5,x6,lsl #3] */ x4 = &spintable[clusterid]; > + 0xb4ffffc4, /* cbz x4, spin */ loop if !x4 ... > + 0xd2800000, /* mov x0, #0x0 */ > + 0xd2800001, /* mov x1, #0x0 */ > + 0xd2800002, /* mov x2, #0x0 */ > + 0xd2800003, /* mov x3, #0x0 */ > + 0xd61f0080, /* br x4 */ ... else jump() > + }; > + > + static const uint64_t spintables[] = { > + 0, 0, 0, 0 the "naturally-aligned 64-bit zero-initalised memory" > + }; > + > + rom_add_blob_fixed("raspi_smpboot", smpboot, sizeof(smpboot), > + info->smp_loader_start); > + rom_add_blob_fixed("raspi_spintables", spintables, sizeof(spintables), > + SPINTABLE_ADDR); Reviewed-by: Philippe Mathieu-Daudé <f4...@amsat.org> > +} > + > static void write_board_setup(ARMCPU *cpu, const struct arm_boot_info *info) > { > arm_write_secure_board_setup_dummy_smc(cpu, info, MVBAR_ADDR); > @@ -99,7 +134,11 @@ static void setup_boot(MachineState *machine, int > version, size_t ram_size) > /* Pi2 and Pi3 requires SMP setup */ > if (version >= 2) { > binfo.smp_loader_start = SMPBOOT_ADDR; > - binfo.write_secondary_boot = write_smpboot; > + if (version == 2) { > + binfo.write_secondary_boot = write_smpboot; > + } else { > + binfo.write_secondary_boot = write_smpboot64; > + } > binfo.secondary_cpu_reset_hook = reset_secondary; > } > >