From: Peter Maydell <peter.maydell@linaro.org>
To: Anthony Liguori <aliguori@amazon.com>
Cc: Blue Swirl <blauwirbel@gmail.com>,
qemu-devel@nongnu.org, Aurelien Jarno <aurelien@aurel32.net>
Subject: [Qemu-devel] [PULL 23/62] hw/arm/boot: Allow easier swapping in of different loader code
Date: Tue, 17 Dec 2013 20:28:41 +0000 [thread overview]
Message-ID: <1387312160-12318-24-git-send-email-peter.maydell@linaro.org> (raw)
In-Reply-To: <1387312160-12318-1-git-send-email-peter.maydell@linaro.org>
For AArch64 we will obviously require a different set of
primary and secondary boot loader code fragments. However currently
we hardcode the offsets into the loader code where we must write
the entrypoint and other data into arm_load_kernel(). This makes it
hard to substitute a different loader fragment, so switch to a more
flexible scheme where instead of a raw array of instructions we use
an array of (instruction, fixup-type) pairs that indicate which
words need special action or data written into them.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1385645602-18662-6-git-send-email-peter.maydell@linaro.org
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
hw/arm/boot.c | 152 +++++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 107 insertions(+), 45 deletions(-)
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 55d552f..0c05a64 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -20,15 +20,33 @@
#define KERNEL_ARGS_ADDR 0x100
#define KERNEL_LOAD_ADDR 0x00010000
+typedef enum {
+ FIXUP_NONE = 0, /* do nothing */
+ FIXUP_TERMINATOR, /* end of insns */
+ FIXUP_BOARDID, /* overwrite with board ID number */
+ 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 */
+ FIXUP_BOOTREG, /* overwrite with boot register address */
+ FIXUP_DSB, /* overwrite with correct DSB insn for cpu */
+ FIXUP_MAX,
+} FixupType;
+
+typedef struct ARMInsnFixup {
+ uint32_t insn;
+ FixupType fixup;
+} ARMInsnFixup;
+
/* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */
-static uint32_t bootloader[] = {
- 0xe3a00000, /* mov r0, #0 */
- 0xe59f1004, /* ldr r1, [pc, #4] */
- 0xe59f2004, /* ldr r2, [pc, #4] */
- 0xe59ff004, /* ldr pc, [pc, #4] */
- 0, /* Board ID */
- 0, /* Address of kernel args. Set by integratorcp_init. */
- 0 /* Kernel entry point. Set by integratorcp_init. */
+static const ARMInsnFixup bootloader[] = {
+ { 0xe3a00000 }, /* mov r0, #0 */
+ { 0xe59f1004 }, /* ldr r1, [pc, #4] */
+ { 0xe59f2004 }, /* ldr r2, [pc, #4] */
+ { 0xe59ff004 }, /* ldr pc, [pc, #4] */
+ { 0, FIXUP_BOARDID },
+ { 0, FIXUP_ARGPTR },
+ { 0, FIXUP_ENTRYPOINT },
+ { 0, FIXUP_TERMINATOR }
};
/* Handling for secondary CPU boot in a multicore system.
@@ -48,39 +66,83 @@ static uint32_t bootloader[] = {
#define DSB_INSN 0xf57ff04f
#define CP15_DSB_INSN 0xee070f9a /* mcr cp15, 0, r0, c7, c10, 4 */
-static uint32_t smpboot[] = {
- 0xe59f2028, /* ldr r2, gic_cpu_if */
- 0xe59f0028, /* ldr r0, startaddr */
- 0xe3a01001, /* mov r1, #1 */
- 0xe5821000, /* str r1, [r2] - set GICC_CTLR.Enable */
- 0xe3a010ff, /* mov r1, #0xff */
- 0xe5821004, /* str r1, [r2, 4] - set GIC_PMR.Priority to 0xff */
- DSB_INSN, /* dsb */
- 0xe320f003, /* wfi */
- 0xe5901000, /* ldr r1, [r0] */
- 0xe1110001, /* tst r1, r1 */
- 0x0afffffb, /* beq <wfi> */
- 0xe12fff11, /* bx r1 */
- 0, /* gic_cpu_if: base address of GIC CPU interface */
- 0 /* bootreg: Boot register address is held here */
+static const ARMInsnFixup smpboot[] = {
+ { 0xe59f2028 }, /* ldr r2, gic_cpu_if */
+ { 0xe59f0028 }, /* ldr r0, bootreg_addr */
+ { 0xe3a01001 }, /* mov r1, #1 */
+ { 0xe5821000 }, /* str r1, [r2] - set GICC_CTLR.Enable */
+ { 0xe3a010ff }, /* mov r1, #0xff */
+ { 0xe5821004 }, /* str r1, [r2, 4] - set GIC_PMR.Priority to 0xff */
+ { 0, FIXUP_DSB }, /* dsb */
+ { 0xe320f003 }, /* wfi */
+ { 0xe5901000 }, /* ldr r1, [r0] */
+ { 0xe1110001 }, /* tst r1, r1 */
+ { 0x0afffffb }, /* beq <wfi> */
+ { 0xe12fff11 }, /* bx r1 */
+ { 0, FIXUP_GIC_CPU_IF }, /* gic_cpu_if: .word 0x.... */
+ { 0, FIXUP_BOOTREG }, /* bootreg_addr: .word 0x.... */
+ { 0, FIXUP_TERMINATOR }
};
+static void write_bootloader(const char *name, hwaddr addr,
+ const ARMInsnFixup *insns, uint32_t *fixupcontext)
+{
+ /* Fix up the specified bootloader fragment and write it into
+ * guest memory using rom_add_blob_fixed(). fixupcontext is
+ * an array giving the values to write in for the fixup types
+ * which write a value into the code array.
+ */
+ int i, len;
+ uint32_t *code;
+
+ len = 0;
+ while (insns[len].fixup != FIXUP_TERMINATOR) {
+ len++;
+ }
+
+ code = g_new0(uint32_t, len);
+
+ for (i = 0; i < len; i++) {
+ uint32_t insn = insns[i].insn;
+ FixupType fixup = insns[i].fixup;
+
+ switch (fixup) {
+ case FIXUP_NONE:
+ break;
+ case FIXUP_BOARDID:
+ case FIXUP_ARGPTR:
+ case FIXUP_ENTRYPOINT:
+ case FIXUP_GIC_CPU_IF:
+ case FIXUP_BOOTREG:
+ case FIXUP_DSB:
+ insn = fixupcontext[fixup];
+ break;
+ default:
+ abort();
+ }
+ code[i] = tswap32(insn);
+ }
+
+ rom_add_blob_fixed(name, code, len * sizeof(uint32_t), addr);
+
+ g_free(code);
+}
+
static void default_write_secondary(ARMCPU *cpu,
const struct arm_boot_info *info)
{
- int n;
- smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
- smpboot[ARRAY_SIZE(smpboot) - 2] = info->gic_cpu_if_addr;
- for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
- /* Replace DSB with the pre-v7 DSB if necessary. */
- if (!arm_feature(&cpu->env, ARM_FEATURE_V7) &&
- smpboot[n] == DSB_INSN) {
- smpboot[n] = CP15_DSB_INSN;
- }
- smpboot[n] = tswap32(smpboot[n]);
+ uint32_t fixupcontext[FIXUP_MAX];
+
+ fixupcontext[FIXUP_GIC_CPU_IF] = info->gic_cpu_if_addr;
+ fixupcontext[FIXUP_BOOTREG] = info->smp_bootreg_addr;
+ if (arm_feature(&cpu->env, ARM_FEATURE_V7)) {
+ fixupcontext[FIXUP_DSB] = DSB_INSN;
+ } else {
+ fixupcontext[FIXUP_DSB] = CP15_DSB_INSN;
}
- rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
- info->smp_loader_start);
+
+ write_bootloader("smpboot", info->smp_loader_start,
+ smpboot, fixupcontext);
}
static void default_reset_secondary(ARMCPU *cpu,
@@ -354,7 +416,6 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
CPUState *cs = CPU(cpu);
int kernel_size;
int initrd_size;
- int n;
int is_linux = 0;
uint64_t elf_entry;
hwaddr entry;
@@ -420,6 +481,8 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
}
info->entry = entry;
if (is_linux) {
+ uint32_t fixupcontext[FIXUP_MAX];
+
if (info->initrd_filename) {
initrd_size = load_ramdisk(info->initrd_filename,
info->initrd_start,
@@ -441,7 +504,7 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
}
info->initrd_size = initrd_size;
- bootloader[4] = info->board_id;
+ fixupcontext[FIXUP_BOARDID] = info->board_id;
/* for device tree boot, we pass the DTB directly in r2. Otherwise
* we point to the kernel args.
@@ -456,9 +519,9 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
if (load_dtb(dtb_start, info)) {
exit(1);
}
- bootloader[5] = dtb_start;
+ fixupcontext[FIXUP_ARGPTR] = dtb_start;
} else {
- bootloader[5] = info->loader_start + KERNEL_ARGS_ADDR;
+ fixupcontext[FIXUP_ARGPTR] = info->loader_start + KERNEL_ARGS_ADDR;
if (info->ram_size >= (1ULL << 32)) {
fprintf(stderr, "qemu: RAM size must be less than 4GB to boot"
" Linux kernel using ATAGS (try passing a device tree"
@@ -466,12 +529,11 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
exit(1);
}
}
- bootloader[6] = entry;
- for (n = 0; n < sizeof(bootloader) / 4; n++) {
- bootloader[n] = tswap32(bootloader[n]);
- }
- rom_add_blob_fixed("bootloader", bootloader, sizeof(bootloader),
- info->loader_start);
+ fixupcontext[FIXUP_ENTRYPOINT] = entry;
+
+ write_bootloader("bootloader", info->loader_start,
+ bootloader, fixupcontext);
+
if (info->nb_cpus > 1) {
info->write_secondary_boot(cpu, info);
}
--
1.8.5
next prev parent reply other threads:[~2013-12-17 20:57 UTC|newest]
Thread overview: 65+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-12-17 20:28 [Qemu-devel] [PULL 00/62] target-arm queue Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 01/62] target-arm: add support for v8 AES instructions Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 02/62] rename pflash_t member width to bank_width Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 03/62] Add device-width property to pflash_cfi01 Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 04/62] return status for each NOR flash device Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 05/62] Set proper device-width for vexpress flash Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 06/62] Add max device width parameter for NOR devices Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 07/62] Fix CFI query responses for NOR flash Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 08/62] Fix NOR flash device ID reading Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 09/62] target-arm/helper.c: Allow cp15.c15 dummy override Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 10/62] target-arm: Define and use ARM_FEATURE_CBAR Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 11/62] target-arm/cpu: Convert reset CBAR to a property Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 12/62] arm/highbank: Use object_new() rather than cpu_arm_init() Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 13/62] arm/highbank: Fix CBAR initialisation Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 14/62] arm/xilinx_zynq: Use object_new() rather than cpu_arm_init() Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 15/62] arm/xilinx_zynq: Implement CBAR initialisation Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 16/62] arm/highbank.c: Fix MPCore periphbase name Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 17/62] ARM: cpu: add "reset_hivecs" property Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 18/62] ARM: arm_cpu_reset: make it possible to use high vectors for reset_exc Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 19/62] target-arm/kvm: Split 32 bit only code into its own file Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 20/62] target-arm: Clean up handling of AArch64 PSTATE Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 21/62] target-arm: Add minimal KVM AArch64 support Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 22/62] configure: Enable KVM for aarch64 host/target combination Peter Maydell
2013-12-17 20:28 ` Peter Maydell [this message]
2013-12-17 20:28 ` [Qemu-devel] [PULL 24/62] hw/arm/boot: Add boot support for AArch64 processor Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 25/62] default-configs: Add config for aarch64-softmmu Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 26/62] target-arm: Split A64 from A32/T32 gen_intermediate_code_internal() Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 27/62] target-arm: A64: add set_pc cpu method Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 28/62] target-arm: A64: provide functions for accessing FPCR and FPSR Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 29/62] target-arm: Support fp registers in gdb stub Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 30/62] target-arm: A64: add stubs for a64 specific helpers Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 31/62] target-arm: A64: provide skeleton for a64 insn decoding Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 32/62] target-arm: A64: expand decoding skeleton for system instructions Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 33/62] target-arm: A64: add support for B and BL insns Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 34/62] target-arm: A64: add support for BR, BLR and RET insns Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 35/62] target-arm: A64: add support for conditional branches Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 36/62] target-arm: A64: add support for 'test and branch' imm Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 37/62] target-arm: A64: add support for compare and branch imm Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 38/62] target-arm: A64: add support for conditional select Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 39/62] target-arm: A64: add support for logical (shifted register) Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 40/62] target-arm: A64: add support for ADR and ADRP Peter Maydell
2013-12-17 20:28 ` [Qemu-devel] [PULL 41/62] target-arm: A64: add support for EXTR Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 42/62] target-arm: A64: add support for 2-src data processing and DIV Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 43/62] target-arm: A64: add support for 2-src shift reg insns Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 44/62] target-arm: A64: add support for 1-src data processing and CLZ Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 45/62] target-arm: A64: add support for 1-src RBIT insn Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 46/62] target-arm: A64: add support for 1-src REV insns Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 47/62] target-arm: A64: add support for bitfield insns Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 48/62] host-utils: add clrsb32/64 - count leading redundant sign bits Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 49/62] target-arm: A64: add support for 1-src CLS insn Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 50/62] target-arm: A64: add support for logical (immediate) insns Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 51/62] hw/arm: add very initial support for Canon DIGIC SoC Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 52/62] hw/arm/digic: prepare DIGIC-based boards support Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 53/62] hw/arm/digic: add timer support Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 54/62] hw/arm/digic: add UART support Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 55/62] hw/arm/digic: add NOR ROM support Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 56/62] MAINTAINERS: Document 'Canon DIGIC' machine Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 57/62] vmstate: Add support for an array of ptimer_state * Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 58/62] hw/timer: add allwinner a10 timer Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 59/62] hw/intc: add allwinner A10 interrupt controller Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 60/62] hw/arm: add allwinner a10 SoC support Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 61/62] hw/arm: add cubieboard support Peter Maydell
2013-12-17 20:29 ` [Qemu-devel] [PULL 62/62] MAINTAINERS: add myself to maintain allwinner-a10 Peter Maydell
2013-12-20 0:14 ` [Qemu-devel] [PULL 00/62] target-arm queue Anthony Liguori
2013-12-20 0:31 ` Peter Maydell
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=1387312160-12318-24-git-send-email-peter.maydell@linaro.org \
--to=peter.maydell@linaro.org \
--cc=aliguori@amazon.com \
--cc=aurelien@aurel32.net \
--cc=blauwirbel@gmail.com \
--cc=qemu-devel@nongnu.org \
/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 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).