@@ -137,6 +137,12 @@ struct arm_boot_info {
arm_endianness endianness;
+ /*
+ * Instead of starting in a small bootloader that jumps to the kernel,
+ * immediately start in the kernel.
+ */
+ bool skip_bootloader;
+
/*
* Confidential guest boot loads everything into RAM so it can be measured.
*/
@@ -762,7 +762,13 @@ static void do_cpu_reset(void *opaque)
if (cs == first_cpu) {
AddressSpace *as = arm_boot_address_space(cpu, info);
- cpu_set_pc(cs, info->loader_start);
+ if (info->skip_bootloader) {
+ assert(is_a64(env));
+ env->xregs[0] = info->dtb_start;
+ cpu_set_pc(cs, info->entry);
+ } else {
+ cpu_set_pc(cs, info->loader_start);
+ }
if (!have_dtb(info)) {
if (old_param) {
@@ -860,7 +866,8 @@ static ssize_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
}
static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
- hwaddr *entry, AddressSpace *as)
+ hwaddr *entry, AddressSpace *as,
+ bool skip_bootloader)
{
hwaddr kernel_load_offset = KERNEL64_LOAD_ADDR;
uint64_t kernel_size = 0;
@@ -912,7 +919,8 @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
* bootloader, we can just load it starting at 2MB+offset rather
* than 0MB + offset.
*/
- if (kernel_load_offset < BOOTLOADER_MAX_SIZE) {
+ if (kernel_load_offset < BOOTLOADER_MAX_SIZE &&
+ !skip_bootloader) {
kernel_load_offset += 2 * MiB;
}
}
@@ -996,7 +1004,8 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
}
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && kernel_size < 0) {
kernel_size = load_aarch64_image(info->kernel_filename,
- info->loader_start, &entry, as);
+ info->loader_start, &entry, as,
+ info->skip_bootloader);
is_linux = 1;
if (kernel_size >= 0) {
image_low_addr = entry;
@@ -1136,8 +1145,10 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
fixupcontext[FIXUP_ENTRYPOINT_LO] = entry;
fixupcontext[FIXUP_ENTRYPOINT_HI] = entry >> 32;
- arm_write_bootloader("bootloader", as, info->loader_start,
- primary_loader, fixupcontext);
+ if (!info->skip_bootloader) {
+ arm_write_bootloader("bootloader", as, info->loader_start,
+ primary_loader, fixupcontext);
+ }
if (info->write_board_setup) {
info->write_board_setup(cpu, info);
@@ -2509,6 +2509,7 @@ static void machvirt_init(MachineState *machine)
vms->bootinfo.firmware_max_size = vms->memmap[VIRT_FLASH].size;
vms->bootinfo.psci_conduit = vms->psci_conduit;
vms->bootinfo.confidential = virt_machine_is_confidential(vms);
+ vms->bootinfo.skip_bootloader = vms->bootinfo.confidential;
arm_load_kernel(ARM_CPU(first_cpu), machine, &vms->bootinfo);
vms->machine_done.notify = virt_machine_done;
An independent verifier needs to reconstruct the content of guest memory in order to attest that it is running trusted code. To avoid having to reconstruct the bootloader generated by QEMU, skip this step and jump directly to the kernel, with the DTB address in x0 as specified by the Linux boot protocol [1]. [1] https://docs.kernel.org/arch/arm64/booting.html Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> --- v2->v3: new --- include/hw/arm/boot.h | 6 ++++++ hw/arm/boot.c | 23 +++++++++++++++++------ hw/arm/virt.c | 1 + 3 files changed, 24 insertions(+), 6 deletions(-)