From be85508f174def8f13cac3855368a27592a6ea1b Mon Sep 17 00:00:00 2001 From: Ninad Palsule Date: Tue, 23 May 2023 16:45:19 -0500 Subject: [PATCH 1/6] hw/arm/aspeed: Add VPD data for Rainier machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current modeling of Rainier machine creates zero filled VPDs(EEPROMs). This makes some services and applications unhappy and causing them to fail. Hence this drop adds some fabricated data for system and BMC FRU so that vpd services are happy and active. Tested: - The system-vpd.service is active. - VPD service related to bmc is active. Signed-off-by: Ninad Palsule Reviewed-by: Cédric Le Goater [ clg: commit title cleanup ] Signed-off-by: Cédric Le Goater --- hw/arm/aspeed.c | 6 ++++-- hw/arm/aspeed_eeprom.c | 45 +++++++++++++++++++++++++++++++++++++++++- hw/arm/aspeed_eeprom.h | 5 +++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 0b29028fe1..bfc2070bd2 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -788,8 +788,10 @@ static void rainier_bmc_i2c_init(AspeedMachineState *bmc) 0x48); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), TYPE_TMP105, 0x4a); - at24c_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 8), 0x50, 64 * KiB); - at24c_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 8), 0x51, 64 * KiB); + at24c_eeprom_init_rom(aspeed_i2c_get_bus(&soc->i2c, 8), 0x50, + 64 * KiB, rainier_bb_fruid, rainier_bb_fruid_len); + at24c_eeprom_init_rom(aspeed_i2c_get_bus(&soc->i2c, 8), 0x51, + 64 * KiB, rainier_bmc_fruid, rainier_bmc_fruid_len); create_pca9552(soc, 8, 0x60); create_pca9552(soc, 8, 0x61); /* Bus 8: ucd90320@11 */ diff --git a/hw/arm/aspeed_eeprom.c b/hw/arm/aspeed_eeprom.c index dc33a88a54..ace5266cec 100644 --- a/hw/arm/aspeed_eeprom.c +++ b/hw/arm/aspeed_eeprom.c @@ -119,9 +119,52 @@ const uint8_t yosemitev2_bmc_fruid[] = { 0x6e, 0x66, 0x69, 0x67, 0x20, 0x41, 0xc1, 0x45, }; +const uint8_t rainier_bb_fruid[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, + 0x28, 0x00, 0x52, 0x54, 0x04, 0x56, 0x48, 0x44, 0x52, 0x56, 0x44, 0x02, + 0x01, 0x00, 0x50, 0x54, 0x0e, 0x56, 0x54, 0x4f, 0x43, 0x00, 0x00, 0x37, + 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x46, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x52, 0x54, + 0x04, 0x56, 0x54, 0x4f, 0x43, 0x50, 0x54, 0x38, 0x56, 0x49, 0x4e, 0x49, + 0x00, 0x00, 0x81, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x53, + 0x59, 0x53, 0x00, 0x00, 0xbb, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x56, 0x43, 0x45, 0x4e, 0x00, 0x00, 0xe2, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x56, 0x53, 0x42, 0x50, 0x00, 0x00, 0x09, 0x01, 0x19, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x46, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, + 0x52, 0x54, 0x04, 0x56, 0x49, 0x4e, 0x49, 0x44, 0x52, 0x04, 0x44, 0x45, + 0x53, 0x43, 0x48, 0x57, 0x02, 0x30, 0x31, 0x43, 0x43, 0x04, 0x33, 0x34, + 0x35, 0x36, 0x46, 0x4e, 0x04, 0x46, 0x52, 0x34, 0x39, 0x53, 0x4e, 0x04, + 0x53, 0x52, 0x31, 0x32, 0x50, 0x4e, 0x04, 0x50, 0x52, 0x39, 0x39, 0x50, + 0x46, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x52, 0x54, + 0x04, 0x56, 0x53, 0x59, 0x53, 0x53, 0x45, 0x07, 0x49, 0x42, 0x4d, 0x53, + 0x59, 0x53, 0x31, 0x54, 0x4d, 0x08, 0x32, 0x32, 0x32, 0x32, 0x2d, 0x32, + 0x32, 0x32, 0x50, 0x46, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, + 0x00, 0x52, 0x54, 0x04, 0x56, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x07, 0x31, + 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x46, 0x43, 0x08, 0x31, 0x31, 0x31, + 0x31, 0x2d, 0x31, 0x31, 0x31, 0x50, 0x46, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x15, 0x00, 0x52, 0x54, 0x04, 0x56, 0x53, 0x42, 0x50, 0x49, + 0x4d, 0x04, 0x50, 0x00, 0x10, 0x01, 0x50, 0x46, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, +}; + +/* Rainier BMC FRU */ +const uint8_t rainier_bmc_fruid[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, + 0x28, 0x00, 0x52, 0x54, 0x04, 0x56, 0x48, 0x44, 0x52, 0x56, 0x44, 0x02, + 0x01, 0x00, 0x50, 0x54, 0x0e, 0x56, 0x54, 0x4f, 0x43, 0x00, 0x00, 0x37, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x46, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x52, 0x54, + 0x04, 0x56, 0x54, 0x4f, 0x43, 0x50, 0x54, 0x0e, 0x56, 0x49, 0x4e, 0x49, + 0x00, 0x00, 0x57, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x46, + 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x52, 0x54, 0x04, 0x56, 0x49, 0x4e, + 0x49, 0x44, 0x52, 0x04, 0x44, 0x45, 0x53, 0x43, 0x48, 0x57, 0x02, 0x30, + 0x31, 0x50, 0x46, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + const size_t tiogapass_bmc_fruid_len = sizeof(tiogapass_bmc_fruid); const size_t fby35_nic_fruid_len = sizeof(fby35_nic_fruid); const size_t fby35_bb_fruid_len = sizeof(fby35_bb_fruid); const size_t fby35_bmc_fruid_len = sizeof(fby35_bmc_fruid); - const size_t yosemitev2_bmc_fruid_len = sizeof(yosemitev2_bmc_fruid); +const size_t rainier_bb_fruid_len = sizeof(rainier_bb_fruid); +const size_t rainier_bmc_fruid_len = sizeof(rainier_bmc_fruid); diff --git a/hw/arm/aspeed_eeprom.h b/hw/arm/aspeed_eeprom.h index 86db6f0479..bbf9e54365 100644 --- a/hw/arm/aspeed_eeprom.h +++ b/hw/arm/aspeed_eeprom.h @@ -22,4 +22,9 @@ extern const size_t fby35_bmc_fruid_len; extern const uint8_t yosemitev2_bmc_fruid[]; extern const size_t yosemitev2_bmc_fruid_len; +extern const uint8_t rainier_bb_fruid[]; +extern const size_t rainier_bb_fruid_len; +extern const uint8_t rainier_bmc_fruid[]; +extern const size_t rainier_bmc_fruid_len; + #endif From c8f48b120b31f6bbe33135ef5d478e485c37e3c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 7 Jun 2023 06:39:32 +0200 Subject: [PATCH 2/6] aspeed/hace: Initialize g_autofree pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As mentioned in docs/devel/style.rst "Automatic memory deallocation": * Variables declared with g_auto* MUST always be initialized, otherwise the cleanup function will use uninitialized stack memory This avoids QEMU to coredump when running the "hash test" command under Zephyr. Cc: Steven Lee Cc: Joel Stanley Cc: qemu-stable@nongnu.org Fixes: c5475b3f9a ("hw: Model ASPEED's Hash and Crypto Engine") Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Alex Bennée Reviewed-by: Thomas Huth Reviewed-by: Francisco Iglesias Message-Id: <20230421131547.2177449-1-clg@kaod.org> Signed-off-by: Cédric Le Goater Reviewed-by: Joel Stanley Signed-off-by: Cédric Le Goater --- hw/misc/aspeed_hace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/misc/aspeed_hace.c b/hw/misc/aspeed_hace.c index 12a761f1f5..b07506ec04 100644 --- a/hw/misc/aspeed_hace.c +++ b/hw/misc/aspeed_hace.c @@ -189,7 +189,7 @@ static void do_hash_operation(AspeedHACEState *s, int algo, bool sg_mode, bool acc_mode) { struct iovec iov[ASPEED_HACE_MAX_SG]; - g_autofree uint8_t *digest_buf; + g_autofree uint8_t *digest_buf = NULL; size_t digest_len = 0; int niov = 0; int i; From 262259eab15d04900b78b91e307bb8470438a011 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 7 Jun 2023 06:39:33 +0200 Subject: [PATCH 3/6] aspeed: Introduce a boot_rom region at the machine level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should also avoid Coverity to report a memory leak warning when the QEMU process exits. See CID 1508061. Reviewed-by: Francisco Iglesias Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Cédric Le Goater Reviewed-by: Joel Stanley Signed-off-by: Cédric Le Goater --- hw/arm/aspeed.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index bfc2070bd2..76a1e7303d 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -40,6 +40,7 @@ struct AspeedMachineState { /* Public */ AspeedSoCState soc; + MemoryRegion boot_rom; bool mmio_exec; char *fmc_model; char *spi_model; @@ -275,15 +276,15 @@ static void write_boot_rom(BlockBackend *blk, hwaddr addr, size_t rom_size, * Create a ROM and copy the flash contents at the expected address * (0x0). Boots faster than execute-in-place. */ -static void aspeed_install_boot_rom(AspeedSoCState *soc, BlockBackend *blk, +static void aspeed_install_boot_rom(AspeedMachineState *bmc, BlockBackend *blk, uint64_t rom_size) { - MemoryRegion *boot_rom = g_new(MemoryRegion, 1); + AspeedSoCState *soc = &bmc->soc; - memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom", rom_size, + memory_region_init_rom(&bmc->boot_rom, NULL, "aspeed.boot_rom", rom_size, &error_abort); memory_region_add_subregion_overlap(&soc->spi_boot_container, 0, - boot_rom, 1); + &bmc->boot_rom, 1); write_boot_rom(blk, ASPEED_SOC_SPI_BOOT_ADDR, rom_size, &error_abort); } @@ -431,8 +432,7 @@ static void aspeed_machine_init(MachineState *machine) if (mtd0) { uint64_t rom_size = memory_region_size(&bmc->soc.spi_boot); - aspeed_install_boot_rom(&bmc->soc, blk_by_legacy_dinfo(mtd0), - rom_size); + aspeed_install_boot_rom(bmc, blk_by_legacy_dinfo(mtd0), rom_size); } } From ebd643ebd2540cd54a6742eaf2e3e4864cf6dd48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 7 Jun 2023 06:39:34 +0200 Subject: [PATCH 4/6] aspeed: Use the boot_rom region of the fby35 machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change completes commits 5aa281d757 ("aspeed: Introduce a spi_boot region under the SoC") and 8b744a6a47 ("aspeed: Add a boot_rom overlap region in the SoC spi_boot container") which introduced a spi_boot container at the SoC level to map the boot rom region as an overlap. It also fixes a Coverity report (CID 1508061) for a memory leak warning when the QEMU process exits by using an bmc_boot_rom MemoryRegion available at the machine level. Cc: Peter Delevoryas Signed-off-by: Cédric Le Goater Reviewed-by: Joel Stanley Signed-off-by: Cédric Le Goater --- hw/arm/fby35.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/hw/arm/fby35.c b/hw/arm/fby35.c index f4600c290b..f2ff6c1abf 100644 --- a/hw/arm/fby35.c +++ b/hw/arm/fby35.c @@ -70,8 +70,6 @@ static void fby35_bmc_write_boot_rom(DriveInfo *dinfo, MemoryRegion *mr, static void fby35_bmc_init(Fby35State *s) { - DriveInfo *drive0 = drive_get(IF_MTD, 0, 0); - object_initialize_child(OBJECT(s), "bmc", &s->bmc, "ast2600-a3"); memory_region_init(&s->bmc_memory, OBJECT(&s->bmc), "bmc-memory", @@ -95,18 +93,21 @@ static void fby35_bmc_init(Fby35State *s) aspeed_board_init_flashes(&s->bmc.fmc, "n25q00", 2, 0); /* Install first FMC flash content as a boot rom. */ - if (drive0) { - AspeedSMCFlash *fl = &s->bmc.fmc.flashes[0]; - MemoryRegion *boot_rom = g_new(MemoryRegion, 1); - uint64_t size = memory_region_size(&fl->mmio); + if (!s->mmio_exec) { + DriveInfo *mtd0 = drive_get(IF_MTD, 0, 0); - if (!s->mmio_exec) { - memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom", - size, &error_abort); - memory_region_add_subregion(&s->bmc_memory, FBY35_BMC_FIRMWARE_ADDR, - boot_rom); - fby35_bmc_write_boot_rom(drive0, boot_rom, FBY35_BMC_FIRMWARE_ADDR, - size, &error_abort); + if (mtd0) { + AspeedSoCState *bmc = &s->bmc; + uint64_t rom_size = memory_region_size(&bmc->spi_boot); + + memory_region_init_rom(&s->bmc_boot_rom, NULL, "aspeed.boot_rom", + rom_size, &error_abort); + memory_region_add_subregion_overlap(&bmc->spi_boot_container, 0, + &s->bmc_boot_rom, 1); + + fby35_bmc_write_boot_rom(mtd0, &s->bmc_boot_rom, + FBY35_BMC_FIRMWARE_ADDR, + rom_size, &error_abort); } } } From f65f6ad5a749bc2d24a083da3544f47a19e7e81f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 7 Jun 2023 06:39:42 +0200 Subject: [PATCH 5/6] aspeed: Introduce a "bmc-console" machine option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most of the Aspeed machines use the UART5 device for the boot console, and QEMU connects the first serial Chardev to this SoC device for this purpose. See routine connect_serial_hds_to_uarts(). Nevertheless, some machines use another boot console, such as the fuji, and commit 5d63d0c76c ("hw/arm/aspeed: Allow machine to set UART default") introduced a SoC class attribute 'uart_default' and property to be able to change the boot console device. It was later changed by commit d2b3eaefb4 ("aspeed: Refactor UART init for multi-SoC machines"). The "bmc-console" machine option goes a step further and lets the user define the UART device from the QEMU command line without introducing a new machine definition. For instance, to use device UART3 (mapped on /dev/ttyS2 under Linux) instead of the default UART5, one would use : -M ast2500-evb,bmc-console=uart3 Cc: Abhishek Singh Dagur Signed-off-by: Cédric Le Goater Reviewed-by: Joel Stanley Signed-off-by: Cédric Le Goater --- docs/system/arm/aspeed.rst | 11 +++++++++++ hw/arm/aspeed.c | 40 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst index d4e293e7f9..80538422a1 100644 --- a/docs/system/arm/aspeed.rst +++ b/docs/system/arm/aspeed.rst @@ -122,6 +122,11 @@ Options specific to Aspeed machines are : * ``spi-model`` to change the SPI Flash model. + * ``bmc-console`` to change the default console device. Most of the + machines use the ``UART5`` device for a boot console, which is + mapped on ``/dev/ttyS4`` under Linux, but it is not always the + case. + For instance, to start the ``ast2500-evb`` machine with a different FMC chip and a bigger (64M) SPI chip, use : @@ -129,6 +134,12 @@ FMC chip and a bigger (64M) SPI chip, use : -M ast2500-evb,fmc-model=mx25l25635e,spi-model=mx66u51235f +To change the boot console and use device ``UART3`` (``/dev/ttyS2`` +under Linux), use : + +.. code-block:: bash + + -M ast2500-evb,bmc-console=uart3 Aspeed minibmc family boards (``ast1030-evb``) ================================================================== diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 76a1e7303d..6880998484 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -42,6 +42,7 @@ struct AspeedMachineState { AspeedSoCState soc; MemoryRegion boot_rom; bool mmio_exec; + uint32_t uart_chosen; char *fmc_model; char *spi_model; }; @@ -333,10 +334,11 @@ static void connect_serial_hds_to_uarts(AspeedMachineState *bmc) AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc); AspeedSoCState *s = &bmc->soc; AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s); + int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default; - aspeed_soc_uart_set_chr(s, amc->uart_default, serial_hd(0)); + aspeed_soc_uart_set_chr(s, uart_chosen, serial_hd(0)); for (int i = 1, uart = ASPEED_DEV_UART1; i < sc->uarts_num; i++, uart++) { - if (uart == amc->uart_default) { + if (uart == uart_chosen) { continue; } aspeed_soc_uart_set_chr(s, uart, serial_hd(i)); @@ -1078,6 +1080,35 @@ static void aspeed_set_spi_model(Object *obj, const char *value, Error **errp) bmc->spi_model = g_strdup(value); } +static char *aspeed_get_bmc_console(Object *obj, Error **errp) +{ + AspeedMachineState *bmc = ASPEED_MACHINE(obj); + AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc); + int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default; + + return g_strdup_printf("uart%d", uart_chosen - ASPEED_DEV_UART1 + 1); +} + +static void aspeed_set_bmc_console(Object *obj, const char *value, Error **errp) +{ + AspeedMachineState *bmc = ASPEED_MACHINE(obj); + AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(bmc); + AspeedSoCClass *sc = ASPEED_SOC_CLASS(object_class_by_name(amc->soc_name)); + int val; + + if (sscanf(value, "uart%u", &val) != 1) { + error_setg(errp, "Bad value for \"uart\" property"); + return; + } + + /* The number of UART depends on the SoC */ + if (val < 1 || val > sc->uarts_num) { + error_setg(errp, "\"uart\" should be in range [1 - %d]", sc->uarts_num); + return; + } + bmc->uart_chosen = ASPEED_DEV_UART1 + val - 1; +} + static void aspeed_machine_class_props_init(ObjectClass *oc) { object_class_property_add_bool(oc, "execute-in-place", @@ -1086,6 +1117,11 @@ static void aspeed_machine_class_props_init(ObjectClass *oc) object_class_property_set_description(oc, "execute-in-place", "boot directly from CE0 flash device"); + object_class_property_add_str(oc, "bmc-console", aspeed_get_bmc_console, + aspeed_set_bmc_console); + object_class_property_set_description(oc, "bmc-console", + "Change the default UART to \"uartX\""); + object_class_property_add_str(oc, "fmc-model", aspeed_get_fmc_model, aspeed_set_fmc_model); object_class_property_set_description(oc, "fmc-model", From 42bea956f6f7477c06186c7add62fa0107a27a9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 7 Jun 2023 06:39:43 +0200 Subject: [PATCH 6/6] target/arm: Allow users to set the number of VFP registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cortex A7 CPUs with an FPU implementing VFPv4 without NEON support have 16 64-bit FPU registers and not 32 registers. Let users set the number of VFP registers with a CPU property. The primary use case of this property is for the Cortex A7 of the Aspeed AST2600 SoC. Signed-off-by: Cédric Le Goater Reviewed-by: Joel Stanley Reviewed-by: Peter Maydell Signed-off-by: Cédric Le Goater --- hw/arm/aspeed_ast2600.c | 2 ++ target/arm/cpu.c | 32 ++++++++++++++++++++++++++++++++ target/arm/cpu.h | 2 ++ 3 files changed, 36 insertions(+) diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index 1bf1246148..a8b3a8065a 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -316,6 +316,8 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) &error_abort); object_property_set_bool(OBJECT(&s->cpu[i]), "neon", false, &error_abort); + object_property_set_bool(OBJECT(&s->cpu[i]), "vfp-d32", false, + &error_abort); object_property_set_link(OBJECT(&s->cpu[i]), "memory", OBJECT(s->memory), &error_abort); diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 4d5bb57f07..353fc48567 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -1277,6 +1277,9 @@ static Property arm_cpu_cfgend_property = static Property arm_cpu_has_vfp_property = DEFINE_PROP_BOOL("vfp", ARMCPU, has_vfp, true); +static Property arm_cpu_has_vfp_d32_property = + DEFINE_PROP_BOOL("vfp-d32", ARMCPU, has_vfp_d32, true); + static Property arm_cpu_has_neon_property = DEFINE_PROP_BOOL("neon", ARMCPU, has_neon, true); @@ -1408,6 +1411,22 @@ void arm_cpu_post_init(Object *obj) } } + if (cpu->has_vfp && cpu_isar_feature(aa32_simd_r32, cpu)) { + cpu->has_vfp_d32 = true; + if (!kvm_enabled()) { + /* + * The permitted values of the SIMDReg bits [3:0] on + * Armv8-A are either 0b0000 and 0b0010. On such CPUs, + * make sure that has_vfp_d32 can not be set to false. + */ + if (!(arm_feature(&cpu->env, ARM_FEATURE_V8) && + !arm_feature(&cpu->env, ARM_FEATURE_M))) { + qdev_property_add_static(DEVICE(obj), + &arm_cpu_has_vfp_d32_property); + } + } + } + if (arm_feature(&cpu->env, ARM_FEATURE_NEON)) { cpu->has_neon = true; if (!kvm_enabled()) { @@ -1674,6 +1693,19 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) return; } + if (cpu->has_vfp_d32 != cpu->has_neon) { + error_setg(errp, "ARM CPUs must have both VFP-D32 and Neon or neither"); + return; + } + + if (!cpu->has_vfp_d32) { + uint32_t u; + + u = cpu->isar.mvfr0; + u = FIELD_DP32(u, MVFR0, SIMDREG, 1); /* 16 registers */ + cpu->isar.mvfr0 = u; + } + if (!cpu->has_vfp) { uint64_t t; uint32_t u; diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 36c608f0e6..af0119addf 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -924,6 +924,8 @@ struct ArchCPU { bool has_pmu; /* CPU has VFP */ bool has_vfp; + /* CPU has 32 VFP registers */ + bool has_vfp_d32; /* CPU has Neon */ bool has_neon; /* CPU has M-profile DSP extension */