From patchwork Thu Jan 10 14:20:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Thierry X-Patchwork-Id: 10755915 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A15A66C2 for ; Thu, 10 Jan 2019 14:21:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9231629945 for ; Thu, 10 Jan 2019 14:21:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9098D29957; Thu, 10 Jan 2019 14:21:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 01C7E29945 for ; Thu, 10 Jan 2019 14:21:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728734AbfAJOVA (ORCPT ); Thu, 10 Jan 2019 09:21:00 -0500 Received: from foss.arm.com ([217.140.101.70]:36834 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728681AbfAJOVA (ORCPT ); Thu, 10 Jan 2019 09:21:00 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id F33FA1650; Thu, 10 Jan 2019 06:20:59 -0800 (PST) Received: from e112298-lin.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 9D6013F5AF; Thu, 10 Jan 2019 06:20:58 -0800 (PST) From: Julien Thierry To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: will.deacon@arm.com, Sami.Mujawar@arm.com, Mark.Rutland@arm.com, andre.przywara@arm.com, Julien Thierry Subject: [PATCH kvmtool v2 4/6] arm: Support firmware loading Date: Thu, 10 Jan 2019 14:20:44 +0000 Message-Id: <1547130046-14729-5-git-send-email-julien.thierry@arm.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1547130046-14729-1-git-send-email-julien.thierry@arm.com> References: <1547130046-14729-1-git-send-email-julien.thierry@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Implement firmware image loading for arm and set the boot start address to the firmware address. Add an option for the user to specify where to map the firmware. Signed-off-by: Julien Thierry --- arm/fdt.c | 14 +++++++- arm/include/arm-common/kvm-config-arch.h | 5 ++- arm/kvm.c | 61 +++++++++++++++++++++++++++++++- 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/arm/fdt.c b/arm/fdt.c index 664bb62..2936986 100644 --- a/arm/fdt.c +++ b/arm/fdt.c @@ -131,7 +131,19 @@ static int setup_fdt(struct kvm *kvm) /* /chosen */ _FDT(fdt_begin_node(fdt, "chosen")); _FDT(fdt_property_cell(fdt, "linux,pci-probe-only", 1)); - _FDT(fdt_property_string(fdt, "bootargs", kvm->cfg.real_cmdline)); + + if (kvm->cfg.firmware_filename) { + /* + * When using a firmware, command line is not passed through DT, + * or the firmware can add it itself + */ + if (kvm->cfg.kernel_cmdline) + pr_warning("Ignoring custom bootargs: %s\n", + kvm->cfg.kernel_cmdline); + } else + _FDT(fdt_property_string(fdt, "bootargs", + kvm->cfg.real_cmdline)); + _FDT(fdt_property_u64(fdt, "kaslr-seed", kvm->cfg.arch.kaslr_seed)); /* Initrd */ diff --git a/arm/include/arm-common/kvm-config-arch.h b/arm/include/arm-common/kvm-config-arch.h index 6a196f1..5734c46 100644 --- a/arm/include/arm-common/kvm-config-arch.h +++ b/arm/include/arm-common/kvm-config-arch.h @@ -11,6 +11,7 @@ struct kvm_config_arch { bool has_pmuv3; u64 kaslr_seed; enum irqchip_type irqchip; + u64 fw_addr; }; int irqchip_parser(const struct option *opt, const char *arg, int unset); @@ -30,6 +31,8 @@ int irqchip_parser(const struct option *opt, const char *arg, int unset); OPT_CALLBACK('\0', "irqchip", &(cfg)->irqchip, \ "[gicv2|gicv2m|gicv3|gicv3-its]", \ "Type of interrupt controller to emulate in the guest", \ - irqchip_parser, NULL), + irqchip_parser, NULL), \ + OPT_U64('\0', "firmware-address", &(cfg)->fw_addr, \ + "Address where firmware should be loaded"), #endif /* ARM_COMMON__KVM_CONFIG_ARCH_H */ diff --git a/arm/kvm.c b/arm/kvm.c index c6843e5..d3f8f5d 100644 --- a/arm/kvm.c +++ b/arm/kvm.c @@ -169,9 +169,68 @@ bool kvm__arch_load_kernel_image(struct kvm *kvm, int fd_kernel, int fd_initrd, return true; } +static bool validate_fw_addr(struct kvm *kvm, u64 fw_addr) +{ + u64 ram_phys; + + ram_phys = host_to_guest_flat(kvm, kvm->ram_start); + + if (fw_addr < ram_phys || fw_addr >= ram_phys + kvm->ram_size) { + pr_err("Provide --firmware-address an address in RAM: " + "0x%016llx - 0x%016llx", + ram_phys, ram_phys + kvm->ram_size); + + return false; + } + + return true; +} + bool kvm__load_firmware(struct kvm *kvm, const char *firmware_filename) { - return false; + u64 fw_addr = kvm->cfg.arch.fw_addr; + void *host_pos; + void *limit; + ssize_t fw_sz; + int fd; + + limit = kvm->ram_start + kvm->ram_size; + + /* For default firmware address, lets load it at the begining of RAM */ + if (fw_addr == 0) + fw_addr = ARM_MEMORY_AREA; + + if (!validate_fw_addr(kvm, fw_addr)) + die("Bad firmware destination: 0x%016llx", fw_addr); + + fd = open(firmware_filename, O_RDONLY); + if (fd < 0) + return false; + + host_pos = guest_flat_to_host(kvm, fw_addr); + if (!host_pos || host_pos < kvm->ram_start) + return false; + + fw_sz = read_file(fd, host_pos, limit - host_pos); + if (fw_sz < 0) + die("failed to load firmware"); + close(fd); + + /* Kernel isn't loaded by kvm, point start address to firmware */ + kvm->arch.kern_guest_start = fw_addr; + + /* Load dtb just after the firmware image*/ + host_pos += fw_sz; + if (host_pos + FDT_MAX_SIZE > limit) + die("not enough space to load fdt"); + + kvm->arch.dtb_guest_start = ALIGN(host_to_guest_flat(kvm, host_pos), + FDT_ALIGN); + pr_info("Placing fdt at 0x%llx - 0x%llx", + kvm->arch.dtb_guest_start, + kvm->arch.dtb_guest_start + FDT_MAX_SIZE); + + return true; } int kvm__arch_setup_firmware(struct kvm *kvm)