Create a measurement log describing operations performed by QEMU to initialize the guest, and load it into guest memory above the DTB.
Cc: Stefan Berger <stef...@linux.vnet.ibm.com> Signed-off-by: Jean-Philippe Brucker <jean-phili...@linaro.org> --- v2->v3: New --- include/hw/arm/boot.h | 3 +++ include/hw/arm/virt.h | 1 + hw/arm/boot.c | 47 +++++++++++++++++++++++++++++++++++++++++++ hw/arm/virt.c | 23 +++++++++++++++++++++ 4 files changed, 74 insertions(+) diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h index 5fcbaa2625..f2518c4e81 100644 --- a/include/hw/arm/boot.h +++ b/include/hw/arm/boot.h @@ -147,6 +147,9 @@ struct arm_boot_info { * Confidential guest boot loads everything into RAM so it can be measured. */ bool confidential; + /* measurement log location in guest memory */ + hwaddr log_start; + size_t log_size; }; /** diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index e5e9f67f52..fe1c464be6 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -180,6 +180,7 @@ struct VirtMachineState { char *oem_id; char *oem_table_id; bool ns_el2_virt_timer_irq; + Object *event_log; }; #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM) diff --git a/hw/arm/boot.c b/hw/arm/boot.c index e461137595..1ced008062 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -665,6 +665,24 @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo, fdt_add_psci_node(fdt); + /* Add a reserved-memory node for the event log */ + if (binfo->log_size) { + char *nodename; + + qemu_fdt_add_subnode(fdt, "/reserved-memory"); + qemu_fdt_setprop_cell(fdt, "/reserved-memory", "#address-cells", 0x2); + qemu_fdt_setprop_cell(fdt, "/reserved-memory", "#size-cells", 0x2); + qemu_fdt_setprop(fdt, "/reserved-memory", "ranges", NULL, 0); + + nodename = g_strdup_printf("/reserved-memory/event-log@%" PRIx64, + binfo->log_start); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "compatible", "cc-event-log"); + qemu_fdt_setprop_sized_cells(fdt, nodename, "reg", 2, binfo->log_start, + 2, binfo->log_size); + g_free(nodename); + } + if (binfo->modify_dtb) { binfo->modify_dtb(binfo, fdt); } @@ -943,6 +961,30 @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base, return kernel_size; } +static void add_event_log(struct arm_boot_info *info) +{ + if (!info->log_size) { + return; + } + + if (!info->dtb_limit) { + int dtb_size = 0; + + if (!info->get_dtb(info, &dtb_size) || dtb_size == 0) { + error_report("Board does not have a DTB"); + exit(1); + } + info->dtb_limit = info->dtb_start + dtb_size; + } + + info->log_start = info->dtb_limit; + if (info->log_start + info->log_size > + info->loader_start + info->ram_size) { + error_report("Not enough space for measurement log and DTB"); + exit(1); + } +} + static void arm_setup_direct_kernel_boot(ARMCPU *cpu, struct arm_boot_info *info) { @@ -990,6 +1032,7 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu, } info->dtb_start = info->loader_start; info->dtb_limit = image_low_addr; + add_event_log(info); } } entry = elf_entry; @@ -1128,6 +1171,8 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu, error_report("Not enough space for DTB after kernel/initrd"); exit(1); } + add_event_log(info); + fixupcontext[FIXUP_ARGPTR_LO] = info->dtb_start; fixupcontext[FIXUP_ARGPTR_HI] = info->dtb_start >> 32; } else { @@ -1189,6 +1234,8 @@ static void arm_setup_confidential_firmware_boot(ARMCPU *cpu, error_report("could not load firmware '%s'", firmware_filename); exit(1); } + + add_event_log(info); } static void arm_setup_firmware_boot(ARMCPU *cpu, struct arm_boot_info *info, diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 5247f53882..1e0f664af0 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1808,6 +1808,11 @@ void virt_machine_done(Notifier *notifier, void *data) exit(1); } + if (vms->event_log) { + object_property_set_uint(vms->event_log, "load-addr", + vms->bootinfo.log_start, &error_fatal); + } + fw_cfg_add_extra_pci_roots(vms->bus, vms->fw_cfg); virt_acpi_setup(vms); @@ -2149,6 +2154,21 @@ static void virt_cpu_post_init(VirtMachineState *vms, MemoryRegion *sysmem) } } +static void create_measurement_log(VirtMachineState *vms) +{ + Error *err = NULL; + + vms->event_log = kvm_arm_rme_get_measurement_log(); + if (vms->event_log == NULL) { + return; + } + vms->bootinfo.log_size = object_property_get_uint(vms->event_log, + "max-size", &err); + if (err != NULL) { + error_report_err(err); + } +} + static void machvirt_init(MachineState *machine) { VirtMachineState *vms = VIRT_MACHINE(machine); @@ -2499,6 +2519,9 @@ static void machvirt_init(MachineState *machine) vms->fw_cfg, OBJECT(vms)); } + kvm_arm_rme_set_ipa_size(64 - clz64(vms->highest_gpa)); + create_measurement_log(vms); + vms->bootinfo.ram_size = machine->ram_size; vms->bootinfo.board_id = -1; vms->bootinfo.loader_start = vms->memmap[VIRT_MEM].base; -- 2.47.0