From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([209.51.188.92]:36418) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gr5Gd-0002cS-W7 for qemu-devel@nongnu.org; Tue, 05 Feb 2019 13:16:21 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gr5Gc-00047r-BQ for qemu-devel@nongnu.org; Tue, 05 Feb 2019 13:16:19 -0500 Received: from mail-wr1-x441.google.com ([2a00:1450:4864:20::441]:37937) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gr5Gb-0003zj-LO for qemu-devel@nongnu.org; Tue, 05 Feb 2019 13:16:17 -0500 Received: by mail-wr1-x441.google.com with SMTP id v13so4717969wrw.5 for ; Tue, 05 Feb 2019 10:16:08 -0800 (PST) Sender: Paolo Bonzini From: Paolo Bonzini Date: Tue, 5 Feb 2019 19:14:48 +0100 Message-Id: <1549390526-24246-39-git-send-email-pbonzini@redhat.com> In-Reply-To: <1549390526-24246-1-git-send-email-pbonzini@redhat.com> References: <1549390526-24246-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PULL 38/76] i386: allow to load initrd below 4 GB for recent linux List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Li Zhijian , Richard Henderson , Eduardo Habkost , "Michael S. Tsirkin" , Marcel Apfelbaum From: Li Zhijian Since linux commit: cf8fa920cb42 ("i386: handle an initrd in highmem (version 2)") linux has supported initrd up to 4 GB, but the header field ramdisk_max is still set to 2 GB to avoid "possible bootloader bugs". When use '-kernel vmlinux -initrd initrd.cgz' to launch a VM, the firmware(it could be linuxboot_dma.bin) helps to read initrd contents into guest memory(below ramdisk_max) and jump to kernel. that's similar with what bootloader does, like grub. In addition, initrd_max is uint32_t simply because QEMU doesn't support the 64-bit boot protocol (specifically the ext_ramdisk_image field). Therefore here just limit initrd_max to UINT32_MAX simply as well to allow initrd to be loaded below 4 GB. NOTE: it's possible that linux protocol within [0x208, 0x20c] supports up to 4 GB initrd as well. CC: Paolo Bonzini CC: Richard Henderson CC: Eduardo Habkost CC: "Michael S. Tsirkin" CC: Marcel Apfelbaum Signed-off-by: Li Zhijian Reviewed-by: Eduardo Habkost Reviewed-by: Stefano Garzarella Signed-off-by: Paolo Bonzini --- hw/i386/pc.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 9664822..7d8f351 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1299,7 +1299,26 @@ static void load_linux(PCMachineState *pcms, #endif /* highest address for loading the initrd */ - if (protocol >= 0x203) { + if (protocol >= 0x20c && + lduw_p(header+0x236) & XLF_CAN_BE_LOADED_ABOVE_4G) { + /* + * Linux has supported initrd up to 4 GB for a very long time (2007, + * long before XLF_CAN_BE_LOADED_ABOVE_4G which was added in 2013), + * though it only sets initrd_max to 2 GB to "work around bootloader + * bugs". Luckily, QEMU firmware(which does something like bootloader) + * has supported this. + * + * It's believed that if XLF_CAN_BE_LOADED_ABOVE_4G is set, initrd can + * be loaded into any address. + * + * In addition, initrd_max is uint32_t simply because QEMU doesn't + * support the 64-bit boot protocol (specifically the ext_ramdisk_image + * field). + * + * Therefore here just limit initrd_max to UINT32_MAX simply as well. + */ + initrd_max = UINT32_MAX; + } else if (protocol >= 0x203) { initrd_max = ldl_p(header+0x22c); } else { initrd_max = 0x37ffffff; -- 1.8.3.1