* [Qemu-devel] [RFC 0/3] ARM: Machine specific boot blobs
@ 2015-10-10 3:13 Peter Crosthwaite
2015-10-10 3:13 ` [Qemu-devel] [RFC 1/3] arm: boot: Add board specific setup code API Peter Crosthwaite
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Peter Crosthwaite @ 2015-10-10 3:13 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Peter Crosthwaite, linux, robh
Hi,
This adds support for machine specific primary boot blobs. This can be
used to install little bits of firmware or boot code without having
to throw the whole QEMU bootloader out and BYO (with device drivers
and all).
It is then used to fix two boards, Zynq and Highbank, both which have
small but critical expectations of pre-boot software setup.
Regards,
Peter
Peter Crosthwaite (3):
arm: boot: Add board specific setup code API
arm: highbank: Implement dummy monitor
arm: xilinx_zynq: Add linux pre-boot
hw/arm/boot.c | 11 +++++++++++
hw/arm/highbank.c | 56 +++++++++++++++++++++++++++++++++++++++++-----------
hw/arm/xilinx_zynq.c | 41 +++++++++++++++++++++++++++++++++++++-
include/hw/arm/arm.h | 7 +++++++
4 files changed, 103 insertions(+), 12 deletions(-)
--
1.9.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [Qemu-devel] [RFC 1/3] arm: boot: Add board specific setup code API
2015-10-10 3:13 [Qemu-devel] [RFC 0/3] ARM: Machine specific boot blobs Peter Crosthwaite
@ 2015-10-10 3:13 ` Peter Crosthwaite
2015-10-10 3:13 ` [Qemu-devel] [RFC 2/3] arm: highbank: Implement dummy monitor Peter Crosthwaite
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Peter Crosthwaite @ 2015-10-10 3:13 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Peter Crosthwaite, linux, robh
Add an API for boards to inject their own preboot software (or
firmware) seqeuence.
The software then returns to bootloader via the link register. This
allows boards to do their own little bits of firmware setup without
needed to replace the bootloader completely (which is the requirement
for existing firmware support).
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---
hw/arm/boot.c | 11 +++++++++++
include/hw/arm/arm.h | 7 +++++++
2 files changed, 18 insertions(+)
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index bef451b..a0dd1df 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -31,6 +31,7 @@ typedef enum {
FIXUP_NONE = 0, /* do nothing */
FIXUP_TERMINATOR, /* end of insns */
FIXUP_BOARDID, /* overwrite with board ID number */
+ FIXUP_BOARDSETUP, /* overwrite with board specific setup code address */
FIXUP_ARGPTR, /* overwrite with pointer to kernel args */
FIXUP_ENTRYPOINT, /* overwrite with kernel entry point */
FIXUP_GIC_CPU_IF, /* overwrite with GIC CPU interface address */
@@ -60,6 +61,11 @@ static const ARMInsnFixup bootloader_aarch64[] = {
/* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */
static const ARMInsnFixup bootloader[] = {
+ { 0xe28fe008 }, /* add lr, pc, #8 */
+ { 0xe59ff000 }, /* ldr pc, [pc, #0] */
+ { 0 },
+ { 0, FIXUP_BOARDSETUP },
+#define BOOTLOADER_NO_BOARDSETUP_OFFSET 4
{ 0xe3a00000 }, /* mov r0, #0 */
{ 0xe59f1004 }, /* ldr r1, [pc, #4] */
{ 0xe59f2004 }, /* ldr r2, [pc, #4] */
@@ -131,6 +137,7 @@ static void write_bootloader(const char *name, hwaddr addr,
case FIXUP_NONE:
break;
case FIXUP_BOARDID:
+ case FIXUP_BOARDSETUP:
case FIXUP_ARGPTR:
case FIXUP_ENTRYPOINT:
case FIXUP_GIC_CPU_IF:
@@ -640,6 +647,9 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
elf_machine = EM_AARCH64;
} else {
primary_loader = bootloader;
+ if (!info->board_setup_blob) {
+ primary_loader += BOOTLOADER_NO_BOARDSETUP_OFFSET;
+ }
kernel_load_offset = KERNEL_LOAD_ADDR;
elf_machine = EM_ARM;
}
@@ -745,6 +755,7 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
info->initrd_size = initrd_size;
fixupcontext[FIXUP_BOARDID] = info->board_id;
+ fixupcontext[FIXUP_BOARDSETUP] = info->board_setup_blob_addr;
/* for device tree boot, we pass the DTB directly in r2. Otherwise
* we point to the kernel args.
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index 4dcd4f9..0e3a652 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -87,6 +87,13 @@ struct arm_boot_info {
* -pflash. It also implies that fw_cfg_find() will succeed.
*/
bool firmware_loaded;
+
+ /* Address as which board specific loader/setup code exists. If enabled,
+ * this code-blob will run before anything else. It must return to the
+ * caller via the link register. There is no stack setup.
+ */
+ bool board_setup_blob;
+ hwaddr board_setup_blob_addr;
};
/**
--
1.9.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [RFC 2/3] arm: highbank: Implement dummy monitor
2015-10-10 3:13 [Qemu-devel] [RFC 0/3] ARM: Machine specific boot blobs Peter Crosthwaite
2015-10-10 3:13 ` [Qemu-devel] [RFC 1/3] arm: boot: Add board specific setup code API Peter Crosthwaite
@ 2015-10-10 3:13 ` Peter Crosthwaite
2015-10-10 3:13 ` [Qemu-devel] [RFC 3/3] arm: xilinx_zynq: Add linux pre-boot Peter Crosthwaite
2015-10-18 16:25 ` [Qemu-devel] [RFC 0/3] ARM: Machine specific boot blobs Peter Crosthwaite
3 siblings, 0 replies; 7+ messages in thread
From: Peter Crosthwaite @ 2015-10-10 3:13 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Peter Crosthwaite, linux, robh
Firstly, enable monitor mode and PSCI, both are which are features of
this board.
In addition to PSCI, this board also uses SMC for cache maintainence
ops. This means we need a secure monitor to catch these and nop them.
Use the ARM boot board setup blob to implement this.
FIXME: The blob population should be made Linux specific.
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---
hw/arm/highbank.c | 56 ++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 45 insertions(+), 11 deletions(-)
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
index be04b27..1fca057 100644
--- a/hw/arm/highbank.c
+++ b/hw/arm/highbank.c
@@ -28,6 +28,9 @@
#include "exec/address-spaces.h"
#include "qemu/error-report.h"
+#define FW_BLOB_ADDR 0x0
+#define LOAD_ADDR 0x1000
+
#define SMP_BOOT_ADDR 0x100
#define SMP_BOOT_REG 0x40
#define MPCORE_PERIPHBASE 0xfff10000
@@ -36,6 +39,36 @@
/* Board init. */
+static void hb_write_fw_blob(void)
+{
+ int n;
+ uint32_t fw_blob[] = {
+ /* Reset */
+ 0xe320f000, /* nop */
+ 0xe320f000, /* nop */
+ /* smc */
+ 0xe10f0000, /* mrs r0, CPSR */
+ 0xe200001f, /* and r0, r0, #0x1f - mask off mode bits */
+ 0xe3500016, /* cmp r0, #0x16 - are we in monitor mode? */
+ /* if (!monitor_mode) { */
+ 0x11600070, /* smcne - go to monitor mode */
+ 0x112fff1e, /* bxne lr - return to caller */
+ /* } */
+ /* do setup from monitor mode */
+ 0xe3a00000 + FW_BLOB_ADDR, /* mov r0, #FW_BLOB_ADDR */
+ 0xee0c0f30, /* mcr p15, 0, r0, c12, c0, 1 - set mvbar */
+ 0xe58fe008, /* save lr */
+ 0xe8dfc000, /* exception return */
+ 0,
+ 0,
+ 0, /* exception return link will end up here */
+ };
+ for (n = 0; n < ARRAY_SIZE(fw_blob); n++) {
+ fw_blob[n] = tswap32(fw_blob[n]);
+ }
+ rom_add_blob_fixed("firmware", fw_blob, sizeof(fw_blob), FW_BLOB_ADDR);
+}
+
static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
{
int n;
@@ -248,16 +281,13 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
cpuobj = object_new(object_class_get_name(oc));
cpu = ARM_CPU(cpuobj);
- /* By default A9 and A15 CPUs have EL3 enabled. This board does not
- * currently support EL3 so the CPU EL3 property is disabled before
- * realization.
- */
- if (object_property_find(cpuobj, "has_el3", NULL)) {
- object_property_set_bool(cpuobj, false, "has_el3", &err);
- if (err) {
- error_report_err(err);
- exit(1);
- }
+ object_property_set_int(cpuobj, QEMU_PSCI_CONDUIT_SMC,
+ "psci-conduit", &error_abort);
+
+ if (n) {
+ /* Secondary CPUs start in PSCI powered-down state */
+ object_property_set_bool(cpuobj, true,
+ "start-powered-off", &error_abort);
}
if (object_property_find(cpuobj, "reset-cbar", NULL)) {
@@ -375,9 +405,13 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
*/
highbank_binfo.board_id = -1;
highbank_binfo.nb_cpus = smp_cpus;
- highbank_binfo.loader_start = 0;
+ highbank_binfo.loader_start = LOAD_ADDR;
highbank_binfo.write_secondary_boot = hb_write_secondary;
highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
+ highbank_binfo.board_setup_blob = true;
+ highbank_binfo.board_setup_blob_addr = FW_BLOB_ADDR;
+
+ hb_write_fw_blob();
arm_load_kernel(ARM_CPU(first_cpu), &highbank_binfo);
}
--
1.9.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [RFC 3/3] arm: xilinx_zynq: Add linux pre-boot
2015-10-10 3:13 [Qemu-devel] [RFC 0/3] ARM: Machine specific boot blobs Peter Crosthwaite
2015-10-10 3:13 ` [Qemu-devel] [RFC 1/3] arm: boot: Add board specific setup code API Peter Crosthwaite
2015-10-10 3:13 ` [Qemu-devel] [RFC 2/3] arm: highbank: Implement dummy monitor Peter Crosthwaite
@ 2015-10-10 3:13 ` Peter Crosthwaite
2015-10-18 16:25 ` [Qemu-devel] [RFC 0/3] ARM: Machine specific boot blobs Peter Crosthwaite
3 siblings, 0 replies; 7+ messages in thread
From: Peter Crosthwaite @ 2015-10-10 3:13 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Peter Crosthwaite, linux, robh
Add a Linux-specific pre-boot routine that matches the device
specific bootloaders behaviour. This is needed for modern Linux that
expects the ARM PLL in SLCR to be a more even value (not 26).
FIXME: The blob population should only happen on Linux boots.
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---
hw/arm/xilinx_zynq.c | 41 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 9f89483..5bf03de 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -43,6 +43,41 @@ static const int dma_irqs[8] = {
46, 47, 48, 49, 72, 73, 74, 75
};
+#define LOAD_ADDR 0x1000
+#define FW_BLOB_ADDR 0x0
+
+#define SLCR_ARM_PLL_OFFSET 0x100
+#define SLCR_LOCK_OFFSET 0x004
+#define SLCR_UNLOCK_OFFSET 0x008
+
+#define SLCR_XILINX_UNLOCK_KEY 0xdf0d
+#define SLCR_XILINX_LOCK_KEY 0x767b
+
+#define SLCR_WRITE(addr, val) \
+ 0xe3a01000 + extract32((val), 0, 8), \
+ 0xe3811c00 + extract32((val), 8, 8), \
+ 0xe3811800 + extract32((val), 16, 8), \
+ 0xe3811400 + extract32((val), 24, 8), \
+ 0xe5801000 + (addr),
+
+static void zynq_write_fw_blob(void)
+{
+ int n;
+ uint32_t fw_blob[] = {
+ 0xe3a004f8, /* mov r0, #0xf8000000 */
+ SLCR_WRITE(SLCR_UNLOCK_OFFSET, SLCR_XILINX_UNLOCK_KEY)
+ SLCR_WRITE(SLCR_ARM_PLL_OFFSET, 0x00014008)
+ //SLCR_WRITE(0x120, 0x1f000200)
+ SLCR_WRITE(SLCR_LOCK_OFFSET, SLCR_XILINX_LOCK_KEY)
+ 0xe12fff1e, /* bx lr */
+ };
+ for (n = 0; n < ARRAY_SIZE(fw_blob); n++) {
+ fw_blob[n] = tswap32(fw_blob[n]);
+ }
+ rom_add_blob_fixed("firmware", fw_blob, sizeof(fw_blob), FW_BLOB_ADDR);
+}
+
+
static struct arm_boot_info zynq_binfo = {};
static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
@@ -251,7 +286,11 @@ static void zynq_init(MachineState *machine)
zynq_binfo.initrd_filename = initrd_filename;
zynq_binfo.nb_cpus = 1;
zynq_binfo.board_id = 0xd32;
- zynq_binfo.loader_start = 0;
+ zynq_binfo.loader_start = LOAD_ADDR;
+ zynq_binfo.board_setup_blob = true;
+ zynq_binfo.board_setup_blob_addr = FW_BLOB_ADDR;
+
+ zynq_write_fw_blob();
arm_load_kernel(ARM_CPU(first_cpu), &zynq_binfo);
}
--
1.9.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [RFC 0/3] ARM: Machine specific boot blobs
2015-10-10 3:13 [Qemu-devel] [RFC 0/3] ARM: Machine specific boot blobs Peter Crosthwaite
` (2 preceding siblings ...)
2015-10-10 3:13 ` [Qemu-devel] [RFC 3/3] arm: xilinx_zynq: Add linux pre-boot Peter Crosthwaite
@ 2015-10-18 16:25 ` Peter Crosthwaite
2015-10-19 16:49 ` Peter Maydell
3 siblings, 1 reply; 7+ messages in thread
From: Peter Crosthwaite @ 2015-10-18 16:25 UTC (permalink / raw)
To: qemu-devel@nongnu.org Developers, Alistair Francis
Cc: Peter Maydell, Peter Crosthwaite, Guenter Roeck, Rob Herring
Ping!
Although a little featurish and RFCish, this does repair the boot of
two ARM machines so it is very much a bugfix and we should consider
for 2.5. Otherwise we go to release (again) with two broken machines.
Regards,
Peter
On Fri, Oct 9, 2015 at 8:13 PM, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> Hi,
>
> This adds support for machine specific primary boot blobs. This can be
> used to install little bits of firmware or boot code without having
> to throw the whole QEMU bootloader out and BYO (with device drivers
> and all).
>
> It is then used to fix two boards, Zynq and Highbank, both which have
> small but critical expectations of pre-boot software setup.
>
> Regards,
> Peter
>
> Peter Crosthwaite (3):
> arm: boot: Add board specific setup code API
> arm: highbank: Implement dummy monitor
> arm: xilinx_zynq: Add linux pre-boot
>
> hw/arm/boot.c | 11 +++++++++++
> hw/arm/highbank.c | 56 +++++++++++++++++++++++++++++++++++++++++-----------
> hw/arm/xilinx_zynq.c | 41 +++++++++++++++++++++++++++++++++++++-
> include/hw/arm/arm.h | 7 +++++++
> 4 files changed, 103 insertions(+), 12 deletions(-)
>
> --
> 1.9.1
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [RFC 0/3] ARM: Machine specific boot blobs
2015-10-18 16:25 ` [Qemu-devel] [RFC 0/3] ARM: Machine specific boot blobs Peter Crosthwaite
@ 2015-10-19 16:49 ` Peter Maydell
2015-10-19 17:25 ` Peter Crosthwaite
0 siblings, 1 reply; 7+ messages in thread
From: Peter Maydell @ 2015-10-19 16:49 UTC (permalink / raw)
To: Peter Crosthwaite
Cc: Rob Herring, Peter Crosthwaite, qemu-devel@nongnu.org Developers,
Guenter Roeck, Alistair Francis
On 18 October 2015 at 17:25, Peter Crosthwaite
<crosthwaitepeter@gmail.com> wrote:
> Ping!
>
> Although a little featurish and RFCish, this does repair the boot of
> two ARM machines so it is very much a bugfix and we should consider
> for 2.5. Otherwise we go to release (again) with two broken machines.
The general idea looks ok to me, but sending a patchset out labelled
RFC when we hit softfreeze is a pretty good way to cause people to
ignore it :-)
Patch 1 looks OK I think; haven't looked too closely at the others.
How are you picking the firmware blob addresses ?
thanks
-- PMM
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [RFC 0/3] ARM: Machine specific boot blobs
2015-10-19 16:49 ` Peter Maydell
@ 2015-10-19 17:25 ` Peter Crosthwaite
0 siblings, 0 replies; 7+ messages in thread
From: Peter Crosthwaite @ 2015-10-19 17:25 UTC (permalink / raw)
To: Peter Maydell
Cc: Rob Herring, Peter Crosthwaite, qemu-devel@nongnu.org Developers,
Guenter Roeck, Alistair Francis
On Mon, Oct 19, 2015 at 9:49 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 18 October 2015 at 17:25, Peter Crosthwaite
> <crosthwaitepeter@gmail.com> wrote:
>> Ping!
>>
>> Although a little featurish and RFCish, this does repair the boot of
>> two ARM machines so it is very much a bugfix and we should consider
>> for 2.5. Otherwise we go to release (again) with two broken machines.
>
> The general idea looks ok to me, but sending a patchset out labelled
> RFC when we hit softfreeze is a pretty good way to cause people to
> ignore it :-)
>
> Patch 1 looks OK I think; haven't looked too closely at the others.
>
> How are you picking the firmware blob addresses ?
>
It is flexible as far as arm/boot.c is concerned and set as board
specific policy. A board could chose to place it at an arbitrary
address to mimic a real bootrom which might be desirable. For both
Highbank and Zynq I put FW @0 and relocated the QEMU bootloader to a
small non-zero.
Regards,
Peter
> thanks
> -- PMM
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2015-10-19 17:25 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-10-10 3:13 [Qemu-devel] [RFC 0/3] ARM: Machine specific boot blobs Peter Crosthwaite
2015-10-10 3:13 ` [Qemu-devel] [RFC 1/3] arm: boot: Add board specific setup code API Peter Crosthwaite
2015-10-10 3:13 ` [Qemu-devel] [RFC 2/3] arm: highbank: Implement dummy monitor Peter Crosthwaite
2015-10-10 3:13 ` [Qemu-devel] [RFC 3/3] arm: xilinx_zynq: Add linux pre-boot Peter Crosthwaite
2015-10-18 16:25 ` [Qemu-devel] [RFC 0/3] ARM: Machine specific boot blobs Peter Crosthwaite
2015-10-19 16:49 ` Peter Maydell
2015-10-19 17:25 ` Peter Crosthwaite
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).