Message ID | 20240206021002.208805-1-lixianglai@loongson.cn (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [V2] loongarch: Change the UEFI loading mode to loongarch | expand |
On Tue, Feb 06, 2024 at 10:10:02AM +0800, Xianglai Li wrote: > The UEFI loading mode in loongarch is very different > from that in other architectures:loongarch's UEFI code > is in rom, while other architectures' UEFI code is in flash. > > loongarch UEFI can be loaded as follows: > -machine virt,pflash=pflash0-format > -bios ./QEMU_EFI.fd > > Other architectures load UEFI using the following methods: > -machine virt,pflash0=pflash0-format,pflash1=pflash1-format > > loongarch's UEFI loading method makes qemu and libvirt incompatible > when using NVRAM, and the cost of loongarch's current loading method > far outweighs the benefits, so we decided to use the same UEFI loading > scheme as other architectures. > > Cc: Andrea Bolognani <abologna@redhat.com> > Cc: maobibo@loongson.cn > Cc: Philippe Mathieu-Daudé <philmd@linaro.org> > Cc: Song Gao <gaosong@loongson.cn> > Cc: zhaotianrui@loongson.cn > Signed-off-by: Xianglai Li <lixianglai@loongson.cn> > --- > hw/loongarch/acpi-build.c | 29 +++++++++-- > hw/loongarch/virt.c | 101 ++++++++++++++++++++++++++---------- > include/hw/loongarch/virt.h | 10 ++-- > 3 files changed, 107 insertions(+), 33 deletions(-) For future reference, it's usually good practice to keep track of changes between subsequent versions of the same patchset. Can you please confirm that the build of edk2 added with [1] is intended to work with a version of QEMU that contains these changes? I'd like to test things out as soon as I get a moment. Thanks. [1] https://github.com/lixianglai/LoongarchVirtFirmware/commit/985ce19438d9544968c7e921c6acf2c74fd4713e
On Tue, Feb 06, 2024 at 05:38:35AM -0800, Andrea Bolognani wrote: > On Tue, Feb 06, 2024 at 10:10:02AM +0800, Xianglai Li wrote: > > The UEFI loading mode in loongarch is very different > > from that in other architectures:loongarch's UEFI code > > is in rom, while other architectures' UEFI code is in flash. > > > > loongarch UEFI can be loaded as follows: > > -machine virt,pflash=pflash0-format > > -bios ./QEMU_EFI.fd > > > > Other architectures load UEFI using the following methods: > > -machine virt,pflash0=pflash0-format,pflash1=pflash1-format > > > > loongarch's UEFI loading method makes qemu and libvirt incompatible > > when using NVRAM, and the cost of loongarch's current loading method > > far outweighs the benefits, so we decided to use the same UEFI loading > > scheme as other architectures. > > > > Cc: Andrea Bolognani <abologna@redhat.com> > > Cc: maobibo@loongson.cn > > Cc: Philippe Mathieu-Daudé <philmd@linaro.org> > > Cc: Song Gao <gaosong@loongson.cn> > > Cc: zhaotianrui@loongson.cn > > Signed-off-by: Xianglai Li <lixianglai@loongson.cn> > > --- > > hw/loongarch/acpi-build.c | 29 +++++++++-- > > hw/loongarch/virt.c | 101 ++++++++++++++++++++++++++---------- > > include/hw/loongarch/virt.h | 10 ++-- > > 3 files changed, 107 insertions(+), 33 deletions(-) > > For future reference, it's usually good practice to keep track of > changes between subsequent versions of the same patchset. > > Can you please confirm that the build of edk2 added with [1] is > intended to work with a version of QEMU that contains these changes? > I'd like to test things out as soon as I get a moment. I've tried it now with libvirt and everything worked just as I expected it to, so Tested-by: Andrea Bolognani <abologna@redhat.com> Were changes to edk2 necessary to make it boot from pflash instead of rom? If so, have those patches already been posted?
Hi Andrea: I'm very sorry for the late reply. I just had the Spring Festival holiday, so I replied the email as soon as I saw it. > On Tue, Feb 06, 2024 at 10:10:02AM +0800, Xianglai Li wrote: >> The UEFI loading mode in loongarch is very different >> from that in other architectures:loongarch's UEFI code >> is in rom, while other architectures' UEFI code is in flash. >> >> loongarch UEFI can be loaded as follows: >> -machine virt,pflash=pflash0-format >> -bios ./QEMU_EFI.fd >> >> Other architectures load UEFI using the following methods: >> -machine virt,pflash0=pflash0-format,pflash1=pflash1-format >> >> loongarch's UEFI loading method makes qemu and libvirt incompatible >> when using NVRAM, and the cost of loongarch's current loading method >> far outweighs the benefits, so we decided to use the same UEFI loading >> scheme as other architectures. >> >> Cc: Andrea Bolognani <abologna@redhat.com> >> Cc: maobibo@loongson.cn >> Cc: Philippe Mathieu-Daudé <philmd@linaro.org> >> Cc: Song Gao <gaosong@loongson.cn> >> Cc: zhaotianrui@loongson.cn >> Signed-off-by: Xianglai Li <lixianglai@loongson.cn> >> --- >> hw/loongarch/acpi-build.c | 29 +++++++++-- >> hw/loongarch/virt.c | 101 ++++++++++++++++++++++++++---------- >> include/hw/loongarch/virt.h | 10 ++-- >> 3 files changed, 107 insertions(+), 33 deletions(-) > For future reference, it's usually good practice to keep track of > changes between subsequent versions of the same patchset. OK! Since there is only one patch, I did not add a cover letter. I saw that you replied test-by later, so I plan to resend patch V2 and bring the cover letter with change log and your test-by label. > > Can you please confirm that the build of edk2 added with [1] is > intended to work with a version of QEMU that contains these changes? > I'd like to test things out as soon as I get a moment. Yes! [1] Works well with qemu with the current patch. Thanks. Xianglai. > > Thanks. > > > [1] https://github.com/lixianglai/LoongarchVirtFirmware/commit/985ce19438d9544968c7e921c6acf2c74fd4713e
Hi Andrea: > On Tue, Feb 06, 2024 at 05:38:35AM -0800, Andrea Bolognani wrote: >> On Tue, Feb 06, 2024 at 10:10:02AM +0800, Xianglai Li wrote: >>> The UEFI loading mode in loongarch is very different >>> from that in other architectures:loongarch's UEFI code >>> is in rom, while other architectures' UEFI code is in flash. >>> >>> loongarch UEFI can be loaded as follows: >>> -machine virt,pflash=pflash0-format >>> -bios ./QEMU_EFI.fd >>> >>> Other architectures load UEFI using the following methods: >>> -machine virt,pflash0=pflash0-format,pflash1=pflash1-format >>> >>> loongarch's UEFI loading method makes qemu and libvirt incompatible >>> when using NVRAM, and the cost of loongarch's current loading method >>> far outweighs the benefits, so we decided to use the same UEFI loading >>> scheme as other architectures. >>> >>> Cc: Andrea Bolognani <abologna@redhat.com> >>> Cc: maobibo@loongson.cn >>> Cc: Philippe Mathieu-Daudé <philmd@linaro.org> >>> Cc: Song Gao <gaosong@loongson.cn> >>> Cc: zhaotianrui@loongson.cn >>> Signed-off-by: Xianglai Li <lixianglai@loongson.cn> >>> --- >>> hw/loongarch/acpi-build.c | 29 +++++++++-- >>> hw/loongarch/virt.c | 101 ++++++++++++++++++++++++++---------- >>> include/hw/loongarch/virt.h | 10 ++-- >>> 3 files changed, 107 insertions(+), 33 deletions(-) >> For future reference, it's usually good practice to keep track of >> changes between subsequent versions of the same patchset. >> >> Can you please confirm that the build of edk2 added with [1] is >> intended to work with a version of QEMU that contains these changes? >> I'd like to test things out as soon as I get a moment. > I've tried it now with libvirt and everything worked just as I > expected it to, so > > Tested-by: Andrea Bolognani <abologna@redhat.com> Thank you very much for your testing! > Were changes to edk2 necessary to make it boot from pflash instead of > rom? If so, have those patches already been posted? Yes, edk2 also has the corresponding modification. Before, I was worried that qemu community members had other opinions that would lead to the modification of the scheme, so I did not submit the modification of edk2 to the community to avoid unnecessary backoff. However, I just submitted the patch to the edk2 community and cc you. You can also get the edk2 patch from the link below: https://github.com/loongson/edk2-platforms/commit/a85dbd29b03db714702836d52c14828a2f72b74f Thanks! Xianglai. >
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c index a1c4198741..6c75f216ea 100644 --- a/hw/loongarch/acpi-build.c +++ b/hw/loongarch/acpi-build.c @@ -314,16 +314,39 @@ static void build_pci_device_aml(Aml *scope, LoongArchMachineState *lams) static void build_flash_aml(Aml *scope, LoongArchMachineState *lams) { Aml *dev, *crs; + MemoryRegion *flash_mem; - hwaddr flash_base = VIRT_FLASH_BASE; - hwaddr flash_size = VIRT_FLASH_SIZE; + hwaddr flash0_base; + hwaddr flash0_size; + + hwaddr flash1_base; + hwaddr flash1_size; + + flash_mem = pflash_cfi01_get_memory(lams->flash[0]); + flash0_base = flash_mem->addr; + flash0_size = flash_mem->size; + + flash_mem = pflash_cfi01_get_memory(lams->flash[1]); + flash1_base = flash_mem->addr; + flash1_size = flash_mem->size; dev = aml_device("FLS0"); aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015"))); aml_append(dev, aml_name_decl("_UID", aml_int(0))); crs = aml_resource_template(); - aml_append(crs, aml_memory32_fixed(flash_base, flash_size, AML_READ_WRITE)); + aml_append(crs, aml_memory32_fixed(flash0_base, flash0_size, + AML_READ_WRITE)); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); + + dev = aml_device("FLS1"); + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015"))); + aml_append(dev, aml_name_decl("_UID", aml_int(1))); + + crs = aml_resource_template(); + aml_append(crs, aml_memory32_fixed(flash1_base, flash1_size, + AML_READ_WRITE)); aml_append(dev, aml_name_decl("_CRS", crs)); aml_append(scope, dev); } diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index 0ad7d8c887..a7b9199e70 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -54,7 +54,9 @@ struct loaderparams { const char *initrd_filename; }; -static void virt_flash_create(LoongArchMachineState *lams) +static PFlashCFI01 *virt_flash_create1(LoongArchMachineState *lams, + const char *name, + const char *alias_prop_name) { DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01); @@ -66,45 +68,78 @@ static void virt_flash_create(LoongArchMachineState *lams) qdev_prop_set_uint16(dev, "id1", 0x18); qdev_prop_set_uint16(dev, "id2", 0x00); qdev_prop_set_uint16(dev, "id3", 0x00); - qdev_prop_set_string(dev, "name", "virt.flash"); - object_property_add_child(OBJECT(lams), "virt.flash", OBJECT(dev)); - object_property_add_alias(OBJECT(lams), "pflash", + qdev_prop_set_string(dev, "name", name); + object_property_add_child(OBJECT(lams), name, OBJECT(dev)); + object_property_add_alias(OBJECT(lams), alias_prop_name, OBJECT(dev), "drive"); + return PFLASH_CFI01(dev); +} - lams->flash = PFLASH_CFI01(dev); +static void virt_flash_create(LoongArchMachineState *lams) +{ + lams->flash[0] = virt_flash_create1(lams, "virt.flash0", "pflash0"); + lams->flash[1] = virt_flash_create1(lams, "virt.flash1", "pflash1"); } -static void virt_flash_map(LoongArchMachineState *lams, - MemoryRegion *sysmem) +static void virt_flash_map1(PFlashCFI01 *flash, + hwaddr base, hwaddr size, + MemoryRegion *sysmem) { - PFlashCFI01 *flash = lams->flash; DeviceState *dev = DEVICE(flash); - hwaddr base = VIRT_FLASH_BASE; - hwaddr size = VIRT_FLASH_SIZE; + BlockBackend *blk; + hwaddr real_size = size; + + blk = pflash_cfi01_get_blk(flash); + if (blk) { + real_size = blk_getlength(blk); + assert(real_size && real_size <= size); + } - assert(QEMU_IS_ALIGNED(size, VIRT_FLASH_SECTOR_SIZE)); - assert(size / VIRT_FLASH_SECTOR_SIZE <= UINT32_MAX); + assert(QEMU_IS_ALIGNED(real_size, VIRT_FLASH_SECTOR_SIZE)); + assert(real_size / VIRT_FLASH_SECTOR_SIZE <= UINT32_MAX); - qdev_prop_set_uint32(dev, "num-blocks", size / VIRT_FLASH_SECTOR_SIZE); + qdev_prop_set_uint32(dev, "num-blocks", real_size / VIRT_FLASH_SECTOR_SIZE); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); memory_region_add_subregion(sysmem, base, sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0)); +} +static void virt_flash_map(LoongArchMachineState *lams, + MemoryRegion *sysmem) +{ + PFlashCFI01 *flash0 = lams->flash[0]; + PFlashCFI01 *flash1 = lams->flash[1]; + + virt_flash_map1(flash0, VIRT_FLASH0_BASE, VIRT_FLASH0_SIZE, sysmem); + virt_flash_map1(flash1, VIRT_FLASH1_BASE, VIRT_FLASH1_SIZE, sysmem); } static void fdt_add_flash_node(LoongArchMachineState *lams) { MachineState *ms = MACHINE(lams); char *nodename; + MemoryRegion *flash_mem; + + hwaddr flash0_base; + hwaddr flash0_size; - hwaddr flash_base = VIRT_FLASH_BASE; - hwaddr flash_size = VIRT_FLASH_SIZE; + hwaddr flash1_base; + hwaddr flash1_size; - nodename = g_strdup_printf("/flash@%" PRIx64, flash_base); + flash_mem = pflash_cfi01_get_memory(lams->flash[0]); + flash0_base = flash_mem->addr; + flash0_size = flash_mem->size; + + flash_mem = pflash_cfi01_get_memory(lams->flash[1]); + flash1_base = flash_mem->addr; + flash1_size = flash_mem->size; + + nodename = g_strdup_printf("/flash@%" PRIx64, flash0_base); qemu_fdt_add_subnode(ms->fdt, nodename); qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cfi-flash"); qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", - 2, flash_base, 2, flash_size); + 2, flash0_base, 2, flash0_size, + 2, flash1_base, 2, flash1_size); qemu_fdt_setprop_cell(ms->fdt, nodename, "bank-width", 4); g_free(nodename); } @@ -637,12 +672,32 @@ static void loongarch_firmware_init(LoongArchMachineState *lams) { char *filename = MACHINE(lams)->firmware; char *bios_name = NULL; - int bios_size; + int bios_size, i; + BlockBackend *pflash_blk0; + MemoryRegion *mr; lams->bios_loaded = false; + /* Map legacy -drive if=pflash to machine properties */ + for (i = 0; i < ARRAY_SIZE(lams->flash); i++) { + pflash_cfi01_legacy_drive(lams->flash[i], + drive_get(IF_PFLASH, 0, i)); + } + virt_flash_map(lams, get_system_memory()); + pflash_blk0 = pflash_cfi01_get_blk(lams->flash[0]); + + if (pflash_blk0) { + if (filename) { + error_report("cannot use both '-bios' and '-drive if=pflash'" + "options at once"); + exit(1); + } + lams->bios_loaded = true; + return; + } + if (filename) { bios_name = qemu_find_file(QEMU_FILE_TYPE_BIOS, filename); if (!bios_name) { @@ -650,21 +705,15 @@ static void loongarch_firmware_init(LoongArchMachineState *lams) exit(1); } - bios_size = load_image_targphys(bios_name, VIRT_BIOS_BASE, VIRT_BIOS_SIZE); + mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(lams->flash[0]), 0); + bios_size = load_image_mr(bios_name, mr); if (bios_size < 0) { error_report("Could not load ROM image '%s'", bios_name); exit(1); } - g_free(bios_name); - - memory_region_init_ram(&lams->bios, NULL, "loongarch.bios", - VIRT_BIOS_SIZE, &error_fatal); - memory_region_set_readonly(&lams->bios, true); - memory_region_add_subregion(get_system_memory(), VIRT_BIOS_BASE, &lams->bios); lams->bios_loaded = true; } - } static void reset_load_elf(void *opaque) diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h index 6ef9a92394..252f7df7f4 100644 --- a/include/hw/loongarch/virt.h +++ b/include/hw/loongarch/virt.h @@ -18,10 +18,12 @@ #define VIRT_FWCFG_BASE 0x1e020000UL #define VIRT_BIOS_BASE 0x1c000000UL -#define VIRT_BIOS_SIZE (4 * MiB) +#define VIRT_BIOS_SIZE (16 * MiB) #define VIRT_FLASH_SECTOR_SIZE (128 * KiB) -#define VIRT_FLASH_BASE 0x1d000000UL -#define VIRT_FLASH_SIZE (16 * MiB) +#define VIRT_FLASH0_BASE VIRT_BIOS_BASE +#define VIRT_FLASH0_SIZE VIRT_BIOS_SIZE +#define VIRT_FLASH1_BASE 0x1d000000UL +#define VIRT_FLASH1_SIZE (16 * MiB) #define VIRT_LOWMEM_BASE 0 #define VIRT_LOWMEM_SIZE 0x10000000 @@ -49,7 +51,7 @@ struct LoongArchMachineState { int fdt_size; DeviceState *platform_bus_dev; PCIBus *pci_bus; - PFlashCFI01 *flash; + PFlashCFI01 *flash[2]; MemoryRegion system_iocsr; MemoryRegion iocsr_mem; AddressSpace as_iocsr;
The UEFI loading mode in loongarch is very different from that in other architectures:loongarch's UEFI code is in rom, while other architectures' UEFI code is in flash. loongarch UEFI can be loaded as follows: -machine virt,pflash=pflash0-format -bios ./QEMU_EFI.fd Other architectures load UEFI using the following methods: -machine virt,pflash0=pflash0-format,pflash1=pflash1-format loongarch's UEFI loading method makes qemu and libvirt incompatible when using NVRAM, and the cost of loongarch's current loading method far outweighs the benefits, so we decided to use the same UEFI loading scheme as other architectures. Cc: Andrea Bolognani <abologna@redhat.com> Cc: maobibo@loongson.cn Cc: Philippe Mathieu-Daudé <philmd@linaro.org> Cc: Song Gao <gaosong@loongson.cn> Cc: zhaotianrui@loongson.cn Signed-off-by: Xianglai Li <lixianglai@loongson.cn> --- hw/loongarch/acpi-build.c | 29 +++++++++-- hw/loongarch/virt.c | 101 ++++++++++++++++++++++++++---------- include/hw/loongarch/virt.h | 10 ++-- 3 files changed, 107 insertions(+), 33 deletions(-)