From nobody Sat Oct 25 09:04:21 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1520310398854577.3504219397984; Mon, 5 Mar 2018 20:26:38 -0800 (PST) Received: from localhost ([::1]:52957 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1et4BO-00073F-4h for importer@patchew.org; Mon, 05 Mar 2018 23:26:34 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49659) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1et3o2-0001dD-Kx for qemu-devel@nongnu.org; Mon, 05 Mar 2018 23:02:29 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1et3nz-0004YJ-TC for qemu-devel@nongnu.org; Mon, 05 Mar 2018 23:02:26 -0500 Received: from ozlabs.org ([103.22.144.67]:51495) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1et3nz-0004Vv-E0; Mon, 05 Mar 2018 23:02:23 -0500 Received: by ozlabs.org (Postfix, from userid 1007) id 3zwNQ96RBcz9shf; Tue, 6 Mar 2018 15:02:07 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1520308929; bh=dY+N5FYg8TjItylbx5kueqUJgTr5hU7yixulVkRTilo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=iNRjDw3gtlEswktjkiNCHi+c4HcgpumwwCVqhBab3ihrLw/o6JVl3cp1EDQVI7iCr QNldEOTAGE58XqfMHpMvLnSklOLPeYrWlH0+RY7usbtm+quOn1JQlC4l8P2SKXbkrn CF2/KkF6zf4omOHL1TKNNy0m2Zk8exuxx+lX+Uos= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Date: Tue, 6 Mar 2018 15:01:52 +1100 Message-Id: <20180306040154.3669-29-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180306040154.3669-1-david@gibson.dropbear.id.au> References: <20180306040154.3669-1-david@gibson.dropbear.id.au> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 103.22.144.67 Subject: [Qemu-devel] [PULL 28/30] PPC: e500: Fix duplicate kernel load and device tree overlap X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: surajjs@au1.ibm.com, qemu-devel@nongnu.org, agraf@suse.de, qemu-ppc@nongnu.org, David Engraf , David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: David Engraf This patch fixes an incorrect behavior when the -kernel argument has been specified without -bios. In this case the kernel was loaded twice. At addre= ss 32M as a raw image and afterwards by load_elf/load_uimage at the corresponding load address. In this case the region for the device tree and the raw kernel image may overlap. The patch fixes the behavior by loading the kernel image once with load_elf/load_uimage and skips loading the raw image. When here do not use bios_name/size for the kernel and use a more generic name called payload_name/size. New in v3: dtb must be stored between kernel and initrd because Linux can handle the dtb only within the first 64MB. Add a comment to clarify the behavior. Signed-off-by: David Engraf Reviewed-by: David Gibson Signed-off-by: David Gibson --- hw/ppc/e500.c | 116 +++++++++++++++++++++++++++++++++++-------------------= ---- 1 file changed, 70 insertions(+), 46 deletions(-) diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index ef541a00be..43c15d18c4 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -792,8 +792,10 @@ void ppce500_init(MachineState *machine, PPCE500Params= *params) int initrd_size =3D 0; hwaddr cur_base =3D 0; char *filename; + const char *payload_name; + bool kernel_as_payload; hwaddr bios_entry =3D 0; - target_long bios_size; + target_long payload_size; struct boot_info *boot_info; int dt_size; int i; @@ -921,11 +923,6 @@ void ppce500_init(MachineState *machine, PPCE500Params= *params) /* Register spinning region */ sysbus_create_simple("e500-spin", params->spin_base, NULL); =20 - if (cur_base < (32 * 1024 * 1024)) { - /* u-boot occupies memory up to 32MB, so load blobs above */ - cur_base =3D (32 * 1024 * 1024); - } - if (params->has_mpc8xxx_gpio) { qemu_irq poweroff_irq; =20 @@ -960,8 +957,61 @@ void ppce500_init(MachineState *machine, PPCE500Params= *params) sysbus_mmio_get_region(s, 0)); } =20 - /* Load kernel. */ - if (machine->kernel_filename) { + /* + * Smart firmware defaults ahead! + * + * We follow the following table to select which payload we execute. + * + * -kernel | -bios | payload + * ---------+-------+--------- + * N | Y | u-boot + * N | N | u-boot + * Y | Y | u-boot + * Y | N | kernel + * + * This ensures backwards compatibility with how we used to expose + * -kernel to users but allows them to run through u-boot as well. + */ + kernel_as_payload =3D false; + if (bios_name =3D=3D NULL) { + if (machine->kernel_filename) { + payload_name =3D machine->kernel_filename; + kernel_as_payload =3D true; + } else { + payload_name =3D "u-boot.e500"; + } + } else { + payload_name =3D bios_name; + } + + filename =3D qemu_find_file(QEMU_FILE_TYPE_BIOS, payload_name); + + payload_size =3D load_elf(filename, NULL, NULL, &bios_entry, &loadaddr= , NULL, + 1, PPC_ELF_MACHINE, 0, 0); + if (payload_size < 0) { + /* + * Hrm. No ELF image? Try a uImage, maybe someone is giving us an + * ePAPR compliant kernel + */ + payload_size =3D load_uimage(filename, &bios_entry, &loadaddr, NUL= L, + NULL, NULL); + if (payload_size < 0) { + error_report("qemu: could not load firmware '%s'", filename); + exit(1); + } + } + + g_free(filename); + + if (kernel_as_payload) { + kernel_base =3D loadaddr; + kernel_size =3D payload_size; + } + + cur_base =3D loadaddr + payload_size; + + /* Load bare kernel only if no bios/u-boot has been provided */ + if (machine->kernel_filename && !kernel_as_payload) { kernel_base =3D cur_base; kernel_size =3D load_image_targphys(machine->kernel_filename, cur_base, @@ -975,6 +1025,11 @@ void ppce500_init(MachineState *machine, PPCE500Param= s *params) cur_base +=3D kernel_size; } =20 + if (cur_base < (32 * 1024 * 1024)) { + /* u-boot occupies memory up to 32MB, so load blobs above */ + cur_base =3D (32 * 1024 * 1024); + } + /* Load initrd. */ if (machine->initrd_filename) { initrd_base =3D (cur_base + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK; @@ -991,47 +1046,16 @@ void ppce500_init(MachineState *machine, PPCE500Para= ms *params) } =20 /* - * Smart firmware defaults ahead! - * - * We follow the following table to select which payload we execute. - * - * -kernel | -bios | payload - * ---------+-------+--------- - * N | Y | u-boot - * N | N | u-boot - * Y | Y | u-boot - * Y | N | kernel - * - * This ensures backwards compatibility with how we used to expose - * -kernel to users but allows them to run through u-boot as well. + * Reserve space for dtb behind the kernel image because Linux has a b= ug + * where it can only handle the dtb if it's within the first 64MB of w= here + * starts. dtb cannot not reach initrd_base because INITRD_LO= AD_PAD + * ensures enough space between kernel and initrd. */ - if (bios_name =3D=3D NULL) { - if (machine->kernel_filename) { - bios_name =3D machine->kernel_filename; - } else { - bios_name =3D "u-boot.e500"; - } - } - filename =3D qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - - bios_size =3D load_elf(filename, NULL, NULL, &bios_entry, &loadaddr, N= ULL, - 1, PPC_ELF_MACHINE, 0, 0); - if (bios_size < 0) { - /* - * Hrm. No ELF image? Try a uImage, maybe someone is giving us an - * ePAPR compliant kernel - */ - kernel_size =3D load_uimage(filename, &bios_entry, &loadaddr, NULL, - NULL, NULL); - if (kernel_size < 0) { - error_report("could not load firmware '%s'", filename); + dt_base =3D (loadaddr + payload_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK; + if (dt_base + DTB_MAX_SIZE > ram_size) { + error_report("qemu: not enough memory for device tree"); exit(1); - } } - g_free(filename); - - /* Reserve space for dtb */ - dt_base =3D (loadaddr + bios_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK; =20 dt_size =3D ppce500_prep_device_tree(machine, params, dt_base, initrd_base, initrd_size, --=20 2.14.3