diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2021-05-04 17:05:53 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-05-04 17:05:53 +0100 |
commit | 87c6cef605a077b20a245d54167127ccf7996e23 (patch) | |
tree | 62553013584befc8e93edc79bdd9752450f50c04 | |
parent | 3e13d8e34b53d8f9a3421a816ccfbdc5fa874e98 (diff) | |
parent | 9cccb912cfa865f0bae6b156fa94e2f216dd8835 (diff) |
Merge remote-tracking branch 'remotes/legoater/tags/pull-aspeed-20210503' into staging
Aspeed patches :
* Fixes for the DMA space
* New model for ASPEED's Hash and Crypto Engine (Joel and Klaus)
* Acceptance tests (Joel)
* A fix for the XDMA model
* Some extra features for the SMC controller.
* Two new boards : rainier-bmc and quanta-q7l1-bmc (Patrick)
# gpg: Signature made Mon 03 May 2021 06:23:36 BST
# gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1
# gpg: Good signature from "Cédric Le Goater <clg@kaod.org>" [undefined]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg: There is no indication that the signature belongs to the owner.
# Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1
* remotes/legoater/tags/pull-aspeed-20210503:
aspeed: Add support for the quanta-q7l1-bmc board
hw/block: m25p80: Add support for mt25ql02g and mt25qu02g
aspeed: Add support for the rainier-bmc board
aspeed: Deprecate the swift-bmc machine
tests/qtest: Rename m25p80 test in aspeed_smc test
aspeed/smc: Add extra controls to request DMA
aspeed/smc: Add a 'features' attribute to the object class
hw/misc/aspeed_xdma: Add AST2600 support
tests/acceptance: Test ast2600 machine
tests/acceptance: Test ast2400 and ast2500 machines
tests/qtest: Add test for Aspeed HACE
aspeed: Integrate HACE
hw: Model ASPEED's Hash and Crypto Engine
hw/arm/aspeed: Do not sysbus-map mmio flash region directly, use alias
aspeed/i2c: Rename DMA address space
aspeed/i2c: Fix DMA address mask
aspeed/smc: Remove unused "sdram-base" property
aspeed/smc: Use the RAM memory region for DMAs
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | docs/system/arm/aspeed.rst | 2 | ||||
-rw-r--r-- | docs/system/deprecated.rst | 7 | ||||
-rw-r--r-- | hw/arm/aspeed.c | 146 | ||||
-rw-r--r-- | hw/arm/aspeed_ast2600.c | 22 | ||||
-rw-r--r-- | hw/arm/aspeed_soc.c | 23 | ||||
-rw-r--r-- | hw/block/m25p80.c | 2 | ||||
-rw-r--r-- | hw/i2c/aspeed_i2c.c | 5 | ||||
-rw-r--r-- | hw/misc/aspeed_hace.c | 389 | ||||
-rw-r--r-- | hw/misc/aspeed_xdma.c | 124 | ||||
-rw-r--r-- | hw/misc/meson.build | 1 | ||||
-rw-r--r-- | hw/ssi/aspeed_smc.c | 119 | ||||
-rw-r--r-- | include/hw/arm/aspeed_soc.h | 3 | ||||
-rw-r--r-- | include/hw/misc/aspeed_hace.h | 43 | ||||
-rw-r--r-- | include/hw/misc/aspeed_xdma.h | 17 | ||||
-rw-r--r-- | include/hw/ssi/aspeed_smc.h | 7 | ||||
-rw-r--r-- | tests/acceptance/boot_linux_console.py | 68 | ||||
-rw-r--r-- | tests/qtest/aspeed_hace-test.c | 469 | ||||
-rw-r--r-- | tests/qtest/aspeed_smc-test.c (renamed from tests/qtest/m25p80-test.c) | 12 | ||||
-rw-r--r-- | tests/qtest/meson.build | 5 |
20 files changed, 1389 insertions, 76 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 8e4e329810..6c5b5693a8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1027,6 +1027,7 @@ F: include/hw/misc/pca9552*.h F: hw/net/ftgmac100.c F: include/hw/net/ftgmac100.h F: docs/system/arm/aspeed.rst +F: tests/qtest/*aspeed* NRF51 M: Joel Stanley <joel@jms.id.au> diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst index d1fb8f25b3..a1911f9403 100644 --- a/docs/system/arm/aspeed.rst +++ b/docs/system/arm/aspeed.rst @@ -49,6 +49,7 @@ Supported devices * Ethernet controllers * Front LEDs (PCA9552 on I2C bus) * LPC Peripheral Controller (a subset of subdevices are supported) + * Hash/Crypto Engine (HACE) - Hash support only. TODO: HMAC and RSA Missing devices @@ -59,7 +60,6 @@ Missing devices * PWM and Fan Controller * Slave GPIO Controller * Super I/O Controller - * Hash/Crypto Engine * PCI-Express 1 Controller * Graphic Display Controller * PECI Controller diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst index 80cae86252..f9169077ae 100644 --- a/docs/system/deprecated.rst +++ b/docs/system/deprecated.rst @@ -245,6 +245,13 @@ The Raspberry Pi machines come in various models (A, A+, B, B+). To be able to distinguish which model QEMU is implementing, the ``raspi2`` and ``raspi3`` machines have been renamed ``raspi2b`` and ``raspi3b``. +Aspeed ``swift-bmc`` machine (since 6.1) +'''''''''''''''''''''''''''''''''''''''' + +This machine is deprecated because we have enough AST2500 based OpenPOWER +machines. It can be easily replaced by the ``witherspoon-bmc`` or the +``romulus-bmc`` machines. + Device options -------------- diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index a17b75f494..a10909fa83 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -138,6 +138,19 @@ struct AspeedMachineState { /* Witherspoon hardware value: 0xF10AD216 (but use romulus definition) */ #define WITHERSPOON_BMC_HW_STRAP1 ROMULUS_BMC_HW_STRAP1 +/* Quanta-Q71l hardware value */ +#define QUANTA_Q71L_BMC_HW_STRAP1 ( \ + SCU_AST2400_HW_STRAP_DRAM_SIZE(DRAM_SIZE_128MB) | \ + SCU_AST2400_HW_STRAP_DRAM_CONFIG(2/* DDR3 with CL=6, CWL=5 */) | \ + SCU_AST2400_HW_STRAP_ACPI_DIS | \ + SCU_AST2400_HW_STRAP_SET_CLK_SOURCE(AST2400_CLK_24M_IN) | \ + SCU_HW_STRAP_VGA_CLASS_CODE | \ + SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_PASS_THROUGH) | \ + SCU_AST2400_HW_STRAP_SET_CPU_AHB_RATIO(AST2400_CPU_AHB_RATIO_2_1) | \ + SCU_HW_STRAP_SPI_WIDTH | \ + SCU_HW_STRAP_VGA_SIZE_SET(VGA_8M_DRAM) | \ + SCU_AST2400_HW_STRAP_BOOT_MODE(AST2400_SPI_BOOT)) + /* AST2600 evb hardware value */ #define AST2600_EVB_HW_STRAP1 0x000000C0 #define AST2600_EVB_HW_STRAP2 0x00000003 @@ -146,6 +159,10 @@ struct AspeedMachineState { #define TACOMA_BMC_HW_STRAP1 0x00000000 #define TACOMA_BMC_HW_STRAP2 0x00000040 +/* Rainier hardware value: (QEMU prototype) */ +#define RAINIER_BMC_HW_STRAP1 0x00000000 +#define RAINIER_BMC_HW_STRAP2 0x00000000 + /* * The max ram region is for firmwares that scan the address space * with load/store to guess how much RAM the SoC has. @@ -327,7 +344,7 @@ static void aspeed_machine_init(MachineState *machine) object_property_set_int(OBJECT(&bmc->soc), "num-cs", amc->num_cs, &error_abort); object_property_set_link(OBJECT(&bmc->soc), "dram", - OBJECT(&bmc->ram_container), &error_abort); + OBJECT(machine->ram), &error_abort); if (machine->kernel_filename) { /* * When booting with a -kernel command line there is no u-boot @@ -433,6 +450,34 @@ static void palmetto_bmc_i2c_init(AspeedMachineState *bmc) object_property_set_int(OBJECT(dev), "temperature3", 110000, &error_abort); } +static void quanta_q71l_bmc_i2c_init(AspeedMachineState *bmc) +{ + AspeedSoCState *soc = &bmc->soc; + + /* + * The quanta-q71l platform expects tmp75s which are compatible with + * tmp105s. + */ + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 1), "tmp105", 0x4c); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 1), "tmp105", 0x4e); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 1), "tmp105", 0x4f); + + /* TODO: i2c-1: Add baseboard FRU eeprom@54 24c64 */ + /* TODO: i2c-1: Add Frontpanel FRU eeprom@57 24c64 */ + /* TODO: Add Memory Riser i2c mux and eeproms. */ + + /* TODO: i2c-2: pca9546@74 */ + /* TODO: i2c-2: pca9548@77 */ + /* TODO: i2c-3: Add BIOS FRU eeprom@56 24c64 */ + /* TODO: i2c-7: Add pca9546@70 */ + /* - i2c@0: pmbus@59 */ + /* - i2c@1: pmbus@58 */ + /* - i2c@2: pmbus@58 */ + /* - i2c@3: pmbus@59 */ + /* TODO: i2c-7: Add PDB FRU eeprom@52 */ + /* TODO: i2c-8: Add BMC FRU eeprom@50 */ +} + static void ast2500_evb_i2c_init(AspeedMachineState *bmc) { AspeedSoCState *soc = &bmc->soc; @@ -629,6 +674,58 @@ static void g220a_bmc_i2c_init(AspeedMachineState *bmc) eeprom_buf); } +static void rainier_bmc_i2c_init(AspeedMachineState *bmc) +{ + AspeedSoCState *soc = &bmc->soc; + + /* The rainier expects a TMP275 but a TMP105 is compatible */ + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), TYPE_TMP105, + 0x48); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), TYPE_TMP105, + 0x49); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), TYPE_TMP105, + 0x4a); + + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), TYPE_TMP105, + 0x48); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), TYPE_TMP105, + 0x49); + + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), TYPE_TMP105, + 0x48); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), TYPE_TMP105, + 0x4a); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), TYPE_TMP105, + 0x4b); + + /* Bus 7: TODO dps310@76 */ + /* Bus 7: TODO max31785@52 */ + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), "pca9552", 0x61); + /* Bus 7: TODO si7021-a20@20 */ + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), TYPE_TMP105, + 0x48); + + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), TYPE_TMP105, + 0x48); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), TYPE_TMP105, + 0x4a); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), "pca9552", 0x61); + /* Bus 8: ucd90320@11 */ + /* Bus 8: ucd90320@b */ + /* Bus 8: ucd90320@c */ + + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp423", 0x4c); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp423", 0x4d); + + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), "tmp423", 0x4c); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), "tmp423", 0x4d); + + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), TYPE_TMP105, + 0x48); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), TYPE_TMP105, + 0x49); +} + static bool aspeed_get_mmio_exec(Object *obj, Error **errp) { return ASPEED_MACHINE(obj)->mmio_exec; @@ -728,6 +825,23 @@ static void aspeed_machine_palmetto_class_init(ObjectClass *oc, void *data) aspeed_soc_num_cpus(amc->soc_name); }; +static void aspeed_machine_quanta_q71l_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); + + mc->desc = "Quanta-Q71l BMC (ARM926EJ-S)"; + amc->soc_name = "ast2400-a1"; + amc->hw_strap1 = QUANTA_Q71L_BMC_HW_STRAP1; + amc->fmc_model = "n25q256a"; + amc->spi_model = "mx25l25635e"; + amc->num_cs = 1; + amc->i2c_init = quanta_q71l_bmc_i2c_init; + mc->default_ram_size = 128 * MiB; + mc->default_cpus = mc->min_cpus = mc->max_cpus = + aspeed_soc_num_cpus(amc->soc_name); +} + static void aspeed_machine_supermicrox11_bmc_class_init(ObjectClass *oc, void *data) { @@ -811,6 +925,9 @@ static void aspeed_machine_swift_class_init(ObjectClass *oc, void *data) mc->default_ram_size = 512 * MiB; mc->default_cpus = mc->min_cpus = mc->max_cpus = aspeed_soc_num_cpus(amc->soc_name); + + mc->deprecation_reason = "redundant system. Please use a similar " + "OpenPOWER BMC, Witherspoon or Romulus."; }; static void aspeed_machine_witherspoon_class_init(ObjectClass *oc, void *data) @@ -886,6 +1003,25 @@ static void aspeed_machine_g220a_class_init(ObjectClass *oc, void *data) aspeed_soc_num_cpus(amc->soc_name); }; +static void aspeed_machine_rainier_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); + + mc->desc = "IBM Rainier BMC (Cortex A7)"; + amc->soc_name = "ast2600-a1"; + amc->hw_strap1 = RAINIER_BMC_HW_STRAP1; + amc->hw_strap2 = RAINIER_BMC_HW_STRAP2; + amc->fmc_model = "mx66l1g45g"; + amc->spi_model = "mx66l1g45g"; + amc->num_cs = 2; + amc->macs_mask = ASPEED_MAC2_ON | ASPEED_MAC3_ON; + amc->i2c_init = rainier_bmc_i2c_init; + mc->default_ram_size = 1 * GiB; + mc->default_cpus = mc->min_cpus = mc->max_cpus = + aspeed_soc_num_cpus(amc->soc_name); +}; + static const TypeInfo aspeed_machine_types[] = { { .name = MACHINE_TYPE_NAME("palmetto-bmc"), @@ -928,6 +1064,14 @@ static const TypeInfo aspeed_machine_types[] = { .parent = TYPE_ASPEED_MACHINE, .class_init = aspeed_machine_g220a_class_init, }, { + .name = MACHINE_TYPE_NAME("quanta-q71l-bmc"), + .parent = TYPE_ASPEED_MACHINE, + .class_init = aspeed_machine_quanta_q71l_class_init, + }, { + .name = MACHINE_TYPE_NAME("rainier-bmc"), + .parent = TYPE_ASPEED_MACHINE, + .class_init = aspeed_machine_rainier_class_init, + }, { .name = TYPE_ASPEED_MACHINE, .parent = TYPE_MACHINE, .instance_size = sizeof(AspeedMachineState), diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index bc87e754a3..c60824bfee 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -42,6 +42,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { [ASPEED_DEV_ETH2] = 0x1E680000, [ASPEED_DEV_ETH4] = 0x1E690000, [ASPEED_DEV_VIC] = 0x1E6C0000, + [ASPEED_DEV_HACE] = 0x1E6D0000, [ASPEED_DEV_SDMC] = 0x1E6E0000, [ASPEED_DEV_SCU] = 0x1E6E2000, [ASPEED_DEV_XDMA] = 0x1E6E7000, @@ -102,6 +103,7 @@ static const int aspeed_soc_ast2600_irqmap[] = { [ASPEED_DEV_I2C] = 110, /* 110 -> 125 */ [ASPEED_DEV_ETH1] = 2, [ASPEED_DEV_ETH2] = 3, + [ASPEED_DEV_HACE] = 4, [ASPEED_DEV_ETH3] = 32, [ASPEED_DEV_ETH4] = 33, [ASPEED_DEV_KCS] = 138, /* 138 -> 142 */ @@ -185,7 +187,8 @@ static void aspeed_soc_ast2600_init(Object *obj) object_initialize_child(obj, "mii[*]", &s->mii[i], TYPE_ASPEED_MII); } - object_initialize_child(obj, "xdma", &s->xdma, TYPE_ASPEED_XDMA); + snprintf(typename, sizeof(typename), TYPE_ASPEED_XDMA "-%s", socname); + object_initialize_child(obj, "xdma", &s->xdma, typename); snprintf(typename, sizeof(typename), "aspeed.gpio-%s", socname); object_initialize_child(obj, "gpio", &s->gpio, typename); @@ -213,6 +216,9 @@ static void aspeed_soc_ast2600_init(Object *obj) TYPE_SYSBUS_SDHCI); object_initialize_child(obj, "lpc", &s->lpc, TYPE_ASPEED_LPC); + + snprintf(typename, sizeof(typename), "aspeed.hace-%s", socname); + object_initialize_child(obj, "hace", &s->hace, typename); } /* @@ -344,10 +350,6 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) /* FMC, The number of CS is set at the board level */ object_property_set_link(OBJECT(&s->fmc), "dram", OBJECT(s->dram_mr), &error_abort); - if (!object_property_set_int(OBJECT(&s->fmc), "sdram-base", - sc->memmap[ASPEED_DEV_SDRAM], errp)) { - return; - } if (!sysbus_realize(SYS_BUS_DEVICE(&s->fmc), errp)) { return; } @@ -498,6 +500,16 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->lpc), 1 + aspeed_lpc_kcs_4, qdev_get_gpio_in(DEVICE(&s->a7mpcore), sc->irqmap[ASPEED_DEV_KCS] + aspeed_lpc_kcs_4)); + + /* HACE */ + object_property_set_link(OBJECT(&s->hace), "dram", OBJECT(s->dram_mr), + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->hace), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->hace), 0, sc->memmap[ASPEED_DEV_HACE]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->hace), 0, + aspeed_soc_get_irq(s, ASPEED_DEV_HACE)); } static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data) diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index 057d053c84..4a95d27d9d 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -34,6 +34,7 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = { [ASPEED_DEV_VIC] = 0x1E6C0000, [ASPEED_DEV_SDMC] = 0x1E6E0000, [ASPEED_DEV_SCU] = 0x1E6E2000, + [ASPEED_DEV_HACE] = 0x1E6E3000, [ASPEED_DEV_XDMA] = 0x1E6E7000, [ASPEED_DEV_VIDEO] = 0x1E700000, [ASPEED_DEV_ADC] = 0x1E6E9000, @@ -65,6 +66,7 @@ static const hwaddr aspeed_soc_ast2500_memmap[] = { [ASPEED_DEV_VIC] = 0x1E6C0000, [ASPEED_DEV_SDMC] = 0x1E6E0000, [ASPEED_DEV_SCU] = 0x1E6E2000, + [ASPEED_DEV_HACE] = 0x1E6E3000, [ASPEED_DEV_XDMA] = 0x1E6E7000, [ASPEED_DEV_ADC] = 0x1E6E9000, [ASPEED_DEV_VIDEO] = 0x1E700000, @@ -117,6 +119,7 @@ static const int aspeed_soc_ast2400_irqmap[] = { [ASPEED_DEV_ETH2] = 3, [ASPEED_DEV_XDMA] = 6, [ASPEED_DEV_SDHCI] = 26, + [ASPEED_DEV_HACE] = 4, }; #define aspeed_soc_ast2500_irqmap aspeed_soc_ast2400_irqmap @@ -196,7 +199,8 @@ static void aspeed_soc_init(Object *obj) TYPE_FTGMAC100); } - object_initialize_child(obj, "xdma", &s->xdma, TYPE_ASPEED_XDMA); + snprintf(typename, sizeof(typename), TYPE_ASPEED_XDMA "-%s", socname); + object_initialize_child(obj, "xdma", &s->xdma, typename); snprintf(typename, sizeof(typename), "aspeed.gpio-%s", socname); object_initialize_child(obj, "gpio", &s->gpio, typename); @@ -212,6 +216,9 @@ static void aspeed_soc_init(Object *obj) } object_initialize_child(obj, "lpc", &s->lpc, TYPE_ASPEED_LPC); + + snprintf(typename, sizeof(typename), "aspeed.hace-%s", socname); + object_initialize_child(obj, "hace", &s->hace, typename); } static void aspeed_soc_realize(DeviceState *dev, Error **errp) @@ -301,10 +308,6 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) /* FMC, The number of CS is set at the board level */ object_property_set_link(OBJECT(&s->fmc), "dram", OBJECT(s->dram_mr), &error_abort); - if (!object_property_set_int(OBJECT(&s->fmc), "sdram-base", - sc->memmap[ASPEED_DEV_SDRAM], errp)) { - return; - } if (!sysbus_realize(SYS_BUS_DEVICE(&s->fmc), errp)) { return; } @@ -425,6 +428,16 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->lpc), 1 + aspeed_lpc_kcs_4, qdev_get_gpio_in(DEVICE(&s->lpc), aspeed_lpc_kcs_4)); + + /* HACE */ + object_property_set_link(OBJECT(&s->hace), "dram", OBJECT(s->dram_mr), + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->hace), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->hace), 0, sc->memmap[ASPEED_DEV_HACE]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->hace), 0, + aspeed_soc_get_irq(s, ASPEED_DEV_HACE)); } static Property aspeed_soc_properties[] = { DEFINE_PROP_LINK("dram", AspeedSoCState, dram_mr, TYPE_MEMORY_REGION, diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index 183d3f44c2..b77503dc84 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -259,6 +259,8 @@ static const FlashPartInfo known_devices[] = { { INFO_STACKED("n25q00a", 0x20bb21, 0x1000, 64 << 10, 2048, ER_4K, 4) }, { INFO_STACKED("mt25ql01g", 0x20ba21, 0x1040, 64 << 10, 2048, ER_4K, 2) }, { INFO_STACKED("mt25qu01g", 0x20bb21, 0x1040, 64 << 10, 2048, ER_4K, 2) }, + { INFO_STACKED("mt25ql02g", 0x20ba22, 0x1040, 64 << 10, 4096, ER_4K | ER_32K, 2) }, + { INFO_STACKED("mt25qu02g", 0x20bb22, 0x1040, 64 << 10, 4096, ER_4K | ER_32K, 2) }, /* Spansion -- single (large) sector size only, at least * for the chips listed here (without boot sectors). diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c index 518a3f5c6f..8d276d9ed3 100644 --- a/hw/i2c/aspeed_i2c.c +++ b/hw/i2c/aspeed_i2c.c @@ -601,7 +601,7 @@ static void aspeed_i2c_bus_write(void *opaque, hwaddr offset, break; } - bus->dma_addr = value & 0xfffffffc; + bus->dma_addr = value & 0x3ffffffc; break; case I2CD_DMA_LEN: @@ -816,7 +816,8 @@ static void aspeed_i2c_realize(DeviceState *dev, Error **errp) return; } - address_space_init(&s->dram_as, s->dram_mr, "dma-dram"); + address_space_init(&s->dram_as, s->dram_mr, + TYPE_ASPEED_I2C "-dma-dram"); } } diff --git a/hw/misc/aspeed_hace.c b/hw/misc/aspeed_hace.c new file mode 100644 index 0000000000..10f00e65f4 --- /dev/null +++ b/hw/misc/aspeed_hace.c @@ -0,0 +1,389 @@ +/* + * ASPEED Hash and Crypto Engine + * + * Copyright (C) 2021 IBM Corp. + * + * Joel Stanley <joel@jms.id.au> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "hw/misc/aspeed_hace.h" +#include "qapi/error.h" +#include "migration/vmstate.h" +#include "crypto/hash.h" +#include "hw/qdev-properties.h" +#include "hw/irq.h" + +#define R_CRYPT_CMD (0x10 / 4) + +#define R_STATUS (0x1c / 4) +#define HASH_IRQ BIT(9) +#define CRYPT_IRQ BIT(12) +#define TAG_IRQ BIT(15) + +#define R_HASH_SRC (0x20 / 4) +#define R_HASH_DEST (0x24 / 4) +#define R_HASH_SRC_LEN (0x2c / 4) + +#define R_HASH_CMD (0x30 / 4) +/* Hash algorithm selection */ +#define HASH_ALGO_MASK (BIT(4) | BIT(5) | BIT(6)) +#define HASH_ALGO_MD5 0 +#define HASH_ALGO_SHA1 BIT(5) +#define HASH_ALGO_SHA224 BIT(6) +#define HASH_ALGO_SHA256 (BIT(4) | BIT(6)) +#define HASH_ALGO_SHA512_SERIES (BIT(5) | BIT(6)) +/* SHA512 algorithm selection */ +#define SHA512_HASH_ALGO_MASK (BIT(10) | BIT(11) | BIT(12)) +#define HASH_ALGO_SHA512_SHA512 0 +#define HASH_ALGO_SHA512_SHA384 BIT(10) +#define HASH_ALGO_SHA512_SHA256 BIT(11) +#define HASH_ALGO_SHA512_SHA224 (BIT(10) | BIT(11)) +/* HMAC modes */ +#define HASH_HMAC_MASK (BIT(7) | BIT(8)) +#define HASH_DIGEST 0 +#define HASH_DIGEST_HMAC BIT(7) +#define HASH_DIGEST_ACCUM BIT(8) +#define HASH_HMAC_KEY (BIT(7) | BIT(8)) +/* Cascaded operation modes */ +#define HASH_ONLY 0 +#define HASH_ONLY2 BIT(0) +#define HASH_CRYPT_THEN_HASH BIT(1) +#define HASH_HASH_THEN_CRYPT (BIT(0) | BIT(1)) +/* Other cmd bits */ +#define HASH_IRQ_EN BIT(9) +#define HASH_SG_EN BIT(18) +/* Scatter-gather data list */ +#define SG_LIST_LEN_SIZE 4 +#define SG_LIST_LEN_MASK 0x0FFFFFFF +#define SG_LIST_LEN_LAST BIT(31) +#define SG_LIST_ADDR_SIZE 4 +#define SG_LIST_ADDR_MASK 0x7FFFFFFF +#define SG_LIST_ENTRY_SIZE (SG_LIST_LEN_SIZE + SG_LIST_ADDR_SIZE) +#define ASPEED_HACE_MAX_SG 256 /* max number of entries */ + +static const struct { + uint32_t mask; + QCryptoHashAlgorithm algo; +} hash_algo_map[] = { + { HASH_ALGO_MD5, QCRYPTO_HASH_ALG_MD5 }, + { HASH_ALGO_SHA1, QCRYPTO_HASH_ALG_SHA1 }, + { HASH_ALGO_SHA224, QCRYPTO_HASH_ALG_SHA224 }, + { HASH_ALGO_SHA256, QCRYPTO_HASH_ALG_SHA256 }, + { HASH_ALGO_SHA512_SERIES | HASH_ALGO_SHA512_SHA512, QCRYPTO_HASH_ALG_SHA512 }, + { HASH_ALGO_SHA512_SERIES | HASH_ALGO_SHA512_SHA384, QCRYPTO_HASH_ALG_SHA384 }, + { HASH_ALGO_SHA512_SERIES | HASH_ALGO_SHA512_SHA256, QCRYPTO_HASH_ALG_SHA256 }, +}; + +static int hash_algo_lookup(uint32_t reg) +{ + int i; + + reg &= HASH_ALGO_MASK | SHA512_HASH_ALGO_MASK; + + for (i = 0; i < ARRAY_SIZE(hash_algo_map); i++) { + if (reg == hash_algo_map[i].mask) { + return hash_algo_map[i].algo; + } + } + + return -1; +} + +static void do_hash_operation(AspeedHACEState *s, int algo, bool sg_mode) +{ + struct iovec iov[ASPEED_HACE_MAX_SG]; + g_autofree uint8_t *digest_buf; + size_t digest_len = 0; + int i; + + if (sg_mode) { + uint32_t len = 0; + + for (i = 0; !(len & SG_LIST_LEN_LAST); i++) { + uint32_t addr, src; + hwaddr plen; + + if (i == ASPEED_HACE_MAX_SG) { + qemu_log_mask(LOG_GUEST_ERROR, + "aspeed_hace: guest failed to set end of sg list marker\n"); + break; + } + + src = s->regs[R_HASH_SRC] + (i * SG_LIST_ENTRY_SIZE); + + len = address_space_ldl_le(&s->dram_as, src, + MEMTXATTRS_UNSPECIFIED, NULL); + + addr = address_space_ldl_le(&s->dram_as, src + SG_LIST_LEN_SIZE, + MEMTXATTRS_UNSPECIFIED, NULL); + addr &= SG_LIST_ADDR_MASK; + + iov[i].iov_len = len & SG_LIST_LEN_MASK; + plen = iov[i].iov_len; + iov[i].iov_base = address_space_map(&s->dram_as, addr, &plen, false, + MEMTXATTRS_UNSPECIFIED); + } + } else { + hwaddr len = s->regs[R_HASH_SRC_LEN]; + + iov[0].iov_len = len; + iov[0].iov_base = address_space_map(&s->dram_as, s->regs[R_HASH_SRC], + &len, false, + MEMTXATTRS_UNSPECIFIED); + i = 1; + } + + if (qcrypto_hash_bytesv(algo, iov, i, &digest_buf, &digest_len, NULL) < 0) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: qcrypto failed\n", __func__); + return; + } + + if (address_space_write(&s->dram_as, s->regs[R_HASH_DEST], + MEMTXATTRS_UNSPECIFIED, + digest_buf, digest_len)) { + qemu_log_mask(LOG_GUEST_ERROR, + "aspeed_hace: address space write failed\n"); + } + + for (; i > 0; i--) { + address_space_unmap(&s->dram_as, iov[i - 1].iov_base, + iov[i - 1].iov_len, false, + iov[i - 1].iov_len); + } + + /* + * Set status bits to indicate completion. Testing shows hardware sets + * these irrespective of HASH_IRQ_EN. + */ + s->regs[R_STATUS] |= HASH_IRQ; +} + +static uint64_t aspeed_hace_read(void *opaque, hwaddr addr, unsigned int size) +{ + AspeedHACEState *s = ASPEED_HACE(opaque); + + addr >>= 2; + + if (addr >= ASPEED_HACE_NR_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", + __func__, addr << 2); + return 0; + } + + return s->regs[addr]; +} + +static void aspeed_hace_write(void *opaque, hwaddr addr, uint64_t data, + unsigned int size) +{ + AspeedHACEState *s = ASPEED_HACE(opaque); + AspeedHACEClass *ahc = ASPEED_HACE_GET_CLASS(s); + + addr >>= 2; + + if (addr >= ASPEED_HACE_NR_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n", + __func__, addr << 2); + return; + } + + switch (addr) { + case R_STATUS: + if (data & HASH_IRQ) { + data &= ~HASH_IRQ; + + if (s->regs[addr] & HASH_IRQ) { + qemu_irq_lower(s->irq); + } + } + break; + case R_HASH_SRC: + data &= ahc->src_mask; + break; + case R_HASH_DEST: + data &= ahc->dest_mask; + break; + case R_HASH_SRC_LEN: + data &= 0x0FFFFFFF; + break; + case R_HASH_CMD: { + int algo; + data &= ahc->hash_mask; + + if ((data & HASH_HMAC_MASK)) { + qemu_log_mask(LOG_UNIMP, + "%s: HMAC engine command mode %"PRIx64" not implemented", + __func__, (data & HASH_HMAC_MASK) >> 8); + } + if (data & BIT(1)) { + qemu_log_mask(LOG_UNIMP, + "%s: Cascaded mode not implemented", + __func__); + } + algo = hash_algo_lookup(data); + if (algo < 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Invalid hash algorithm selection 0x%"PRIx64"\n", + __func__, data & ahc->hash_mask); + break; + } + do_hash_operation(s, algo, data & HASH_SG_EN); + + if (data & HASH_IRQ_EN) { + qemu_irq_raise(s->irq); + } + break; + } + case R_CRYPT_CMD: + qemu_log_mask(LOG_UNIMP, "%s: Crypt commands not implemented\n", + __func__); + break; + default: + break; + } + + s->regs[addr] = data; +} + +static const MemoryRegionOps aspeed_hace_ops = { + .read = aspeed_hace_read, + .write = aspeed_hace_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 4, + }, +}; + +static void aspeed_hace_reset(DeviceState *dev) +{ + struct AspeedHACEState *s = ASPEED_HACE(dev); + + memset(s->regs, 0, sizeof(s->regs)); +} + +static void aspeed_hace_realize(DeviceState *dev, Error **errp) +{ + AspeedHACEState *s = ASPEED_HACE(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + + sysbus_init_irq(sbd, &s->irq); + + memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_hace_ops, s, + TYPE_ASPEED_HACE, 0x1000); + + if (!s->dram_mr) { + error_setg(errp, TYPE_ASPEED_HACE ": 'dram' link not set"); + return; + } + + address_space_init(&s->dram_as, s->dram_mr, "dram"); + + sysbus_init_mmio(sbd, &s->iomem); +} + +static Property aspeed_hace_properties[] = { + DEFINE_PROP_LINK("dram", AspeedHACEState, dram_mr, + TYPE_MEMORY_REGION, MemoryRegion *), + DEFINE_PROP_END_OF_LIST(), +}; + + +static const VMStateDescription vmstate_aspeed_hace = { + .name = TYPE_ASPEED_HACE, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, AspeedHACEState, ASPEED_HACE_NR_REGS), + VMSTATE_END_OF_LIST(), + } +}; + +static void aspeed_hace_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = aspeed_hace_realize; + dc->reset = aspeed_hace_reset; + device_class_set_props(dc, aspeed_hace_properties); + dc->vmsd = &vmstate_aspeed_hace; +} + +static const TypeInfo aspeed_hace_info = { + .name = TYPE_ASPEED_HACE, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(AspeedHACEState), + .class_init = aspeed_hace_class_init, + .class_size = sizeof(AspeedHACEClass) +}; + +static void aspeed_ast2400_hace_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedHACEClass *ahc = ASPEED_HACE_CLASS(klass); + + dc->desc = "AST2400 Hash and Crypto Engine"; + + ahc->src_mask = 0x0FFFFFFF; + ahc->dest_mask = 0x0FFFFFF8; + ahc->hash_mask = 0x000003ff; /* No SG or SHA512 modes */ +} + +static const TypeInfo aspeed_ast2400_hace_info = { + .name = TYPE_ASPEED_AST2400_HACE, + .parent = TYPE_ASPEED_HACE, + .class_init = aspeed_ast2400_hace_class_init, +}; + +static void aspeed_ast2500_hace_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedHACEClass *ahc = ASPEED_HACE_CLASS(klass); + + dc->desc = "AST2500 Hash and Crypto Engine"; + + ahc->src_mask = 0x3fffffff; + ahc->dest_mask = 0x3ffffff8; + ahc->hash_mask = 0x000003ff; /* No SG or SHA512 modes */ +} + +static const TypeInfo aspeed_ast2500_hace_info = { + .name = TYPE_ASPEED_AST2500_HACE, + .parent = TYPE_ASPEED_HACE, + .class_init = aspeed_ast2500_hace_class_init, +}; + +static void aspeed_ast2600_hace_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedHACEClass *ahc = ASPEED_HACE_CLASS(klass); + + dc->desc = "AST2600 Hash and Crypto Engine"; + + ahc->src_mask = 0x7FFFFFFF; + ahc->dest_mask = 0x7FFFFFF8; + ahc->hash_mask = 0x00147FFF; +} + +static const TypeInfo aspeed_ast2600_hace_info = { + .name = TYPE_ASPEED_AST2600_HACE, + .parent = TYPE_ASPEED_HACE, + .class_init = aspeed_ast2600_hace_class_init, +}; + +static void aspeed_hace_register_types(void) +{ + type_register_static(&aspeed_ast2400_hace_info); + type_register_static(&aspeed_ast2500_hace_info); + type_register_static(&aspeed_ast2600_hace_info); + type_register_static(&aspeed_hace_info); +} + +type_init(aspeed_hace_register_types); diff --git a/hw/misc/aspeed_xdma.c b/hw/misc/aspeed_xdma.c index 533d237e3c..1c21577c98 100644 --- a/hw/misc/aspeed_xdma.c +++ b/hw/misc/aspeed_xdma.c @@ -30,6 +30,19 @@ #define XDMA_IRQ_ENG_STAT_US_COMP BIT(4) #define XDMA_IRQ_ENG_STAT_DS_COMP BIT(5) #define XDMA_IRQ_ENG_STAT_RESET 0xF8000000 + +#define XDMA_AST2600_BMC_CMDQ_ADDR 0x14 +#define XDMA_AST2600_BMC_CMDQ_ENDP 0x18 +#define XDMA_AST2600_BMC_CMDQ_WRP 0x1c +#define XDMA_AST2600_BMC_CMDQ_RDP 0x20 +#define XDMA_AST2600_IRQ_CTRL 0x38 +#define XDMA_AST2600_IRQ_CTRL_US_COMP BIT(16) +#define XDMA_AST2600_IRQ_CTRL_DS_COMP BIT(17) +#define XDMA_AST2600_IRQ_CTRL_W_MASK 0x017003FF +#define XDMA_AST2600_IRQ_STATUS 0x3c +#define XDMA_AST2600_IRQ_STATUS_US_COMP BIT(16) +#define XDMA_AST2600_IRQ_STATUS_DS_COMP BIT(17) + #define XDMA_MEM_SIZE 0x1000 #define TO_REG(addr) ((addr) / sizeof(uint32_t)) @@ -52,56 +65,48 @@ static void aspeed_xdma_write(void *opaque, hwaddr addr, uint64_t val, unsigned int idx; uint32_t val32 = (uint32_t)val; AspeedXDMAState *xdma = opaque; + AspeedXDMAClass *axc = ASPEED_XDMA_GET_CLASS(xdma); if (addr >= ASPEED_XDMA_REG_SIZE) { return; } - switch (addr) { - case XDMA_BMC_CMDQ_ENDP: + if (addr == axc->cmdq_endp) { xdma->regs[TO_REG(addr)] = val32 & XDMA_BMC_CMDQ_W_MASK; - break; - case XDMA_BMC_CMDQ_WRP: + } else if (addr == axc->cmdq_wrp) { idx = TO_REG(addr); xdma->regs[idx] = val32 & XDMA_BMC_CMDQ_W_MASK; - xdma->regs[TO_REG(XDMA_BMC_CMDQ_RDP)] = xdma->regs[idx]; + xdma->regs[TO_REG(axc->cmdq_rdp)] = xdma->regs[idx]; trace_aspeed_xdma_write(addr, val); if (xdma->bmc_cmdq_readp_set) { xdma->bmc_cmdq_readp_set = 0; } else { - xdma->regs[TO_REG(XDMA_IRQ_ENG_STAT)] |= - XDMA_IRQ_ENG_STAT_US_COMP | XDMA_IRQ_ENG_STAT_DS_COMP; + xdma->regs[TO_REG(axc->intr_status)] |= axc->intr_complete; - if (xdma->regs[TO_REG(XDMA_IRQ_ENG_CTRL)] & - (XDMA_IRQ_ENG_CTRL_US_COMP | XDMA_IRQ_ENG_CTRL_DS_COMP)) + if (xdma->regs[TO_REG(axc->intr_ctrl)] & axc->intr_complete) { qemu_irq_raise(xdma->irq); + } } - break; - case XDMA_BMC_CMDQ_RDP: + } else if (addr == axc->cmdq_rdp) { trace_aspeed_xdma_write(addr, val); if (val32 == XDMA_BMC_CMDQ_RDP_MAGIC) { xdma->bmc_cmdq_readp_set = 1; } - break; - case XDMA_IRQ_ENG_CTRL: - xdma->regs[TO_REG(addr)] = val32 & XDMA_IRQ_ENG_CTRL_W_MASK; - break; - case XDMA_IRQ_ENG_STAT: + } else if (addr == axc->intr_ctrl) { + xdma->regs[TO_REG(addr)] = val32 & axc->intr_ctrl_mask; + } else if (addr == axc->intr_status) { trace_aspeed_xdma_write(addr, val); idx = TO_REG(addr); - if (val32 & (XDMA_IRQ_ENG_STAT_US_COMP | XDMA_IRQ_ENG_STAT_DS_COMP)) { - xdma->regs[idx] &= - ~(XDMA_IRQ_ENG_STAT_US_COMP | XDMA_IRQ_ENG_STAT_DS_COMP); + if (val32 & axc->intr_complete) { + xdma->regs[idx] &= ~axc->intr_complete; qemu_irq_lower(xdma->irq); } - break; - default: + } else { xdma->regs[TO_REG(addr)] = val32; - break; } } @@ -127,10 +132,11 @@ static void aspeed_xdma_realize(DeviceState *dev, Error **errp) static void aspeed_xdma_reset(DeviceState *dev) { AspeedXDMAState *xdma = ASPEED_XDMA(dev); + AspeedXDMAClass *axc = ASPEED_XDMA_GET_CLASS(xdma); xdma->bmc_cmdq_readp_set = 0; memset(xdma->regs, 0, ASPEED_XDMA_REG_SIZE); - xdma->regs[TO_REG(XDMA_IRQ_ENG_STAT)] = XDMA_IRQ_ENG_STAT_RESET; + xdma->regs[TO_REG(axc->intr_status)] = XDMA_IRQ_ENG_STAT_RESET; qemu_irq_lower(xdma->irq); } @@ -144,6 +150,73 @@ static const VMStateDescription aspeed_xdma_vmstate = { }, }; +static void aspeed_2600_xdma_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedXDMAClass *axc = ASPEED_XDMA_CLASS(klass); + + dc->desc = "ASPEED 2600 XDMA Controller"; + + axc->cmdq_endp = XDMA_AST2600_BMC_CMDQ_ENDP; + axc->cmdq_wrp = XDMA_AST2600_BMC_CMDQ_WRP; + axc->cmdq_rdp = XDMA_AST2600_BMC_CMDQ_RDP; + axc->intr_ctrl = XDMA_AST2600_IRQ_CTRL; + axc->intr_ctrl_mask = XDMA_AST2600_IRQ_CTRL_W_MASK; + axc->intr_status = XDMA_AST2600_IRQ_STATUS; + axc->intr_complete = XDMA_AST2600_IRQ_STATUS_US_COMP | + XDMA_AST2600_IRQ_STATUS_DS_COMP; +} + +static const TypeInfo aspeed_2600_xdma_info = { + .name = TYPE_ASPEED_2600_XDMA, + .parent = TYPE_ASPEED_XDMA, + .class_init = aspeed_2600_xdma_class_init, +}; + +static void aspeed_2500_xdma_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedXDMAClass *axc = ASPEED_XDMA_CLASS(klass); + + dc->desc = "ASPEED 2500 XDMA Controller"; + + axc->cmdq_endp = XDMA_BMC_CMDQ_ENDP; + axc->cmdq_wrp = XDMA_BMC_CMDQ_WRP; + axc->cmdq_rdp = XDMA_BMC_CMDQ_RDP; + axc->intr_ctrl = XDMA_IRQ_ENG_CTRL; + axc->intr_ctrl_mask = XDMA_IRQ_ENG_CTRL_W_MASK; + axc->intr_status = XDMA_IRQ_ENG_STAT; + axc->intr_complete = XDMA_IRQ_ENG_STAT_US_COMP | XDMA_IRQ_ENG_STAT_DS_COMP; +}; + +static const TypeInfo aspeed_2500_xdma_info = { + .name = TYPE_ASPEED_2500_XDMA, + .parent = TYPE_ASPEED_XDMA, + .class_init = aspeed_2500_xdma_class_init, +}; + +static void aspeed_2400_xdma_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedXDMAClass *axc = ASPEED_XDMA_CLASS(klass); + + dc->desc = "ASPEED 2400 XDMA Controller"; + + axc->cmdq_endp = XDMA_BMC_CMDQ_ENDP; + axc->cmdq_wrp = XDMA_BMC_CMDQ_WRP; + axc->cmdq_rdp = XDMA_BMC_CMDQ_RDP; + axc->intr_ctrl = XDMA_IRQ_ENG_CTRL; + axc->intr_ctrl_mask = XDMA_IRQ_ENG_CTRL_W_MASK; + axc->intr_status = XDMA_IRQ_ENG_STAT; + axc->intr_complete = XDMA_IRQ_ENG_STAT_US_COMP | XDMA_IRQ_ENG_STAT_DS_COMP; +}; + +static const TypeInfo aspeed_2400_xdma_info = { + .name = TYPE_ASPEED_2400_XDMA, + .parent = TYPE_ASPEED_XDMA, + .class_init = aspeed_2400_xdma_class_init, +}; + static void aspeed_xdma_class_init(ObjectClass *classp, void *data) { DeviceClass *dc = DEVICE_CLASS(classp); @@ -158,10 +231,15 @@ static const TypeInfo aspeed_xdma_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(AspeedXDMAState), .class_init = aspeed_xdma_class_init, + .class_size = sizeof(AspeedXDMAClass), + .abstract = true, }; static void aspeed_xdma_register_type(void) { type_register_static(&aspeed_xdma_info); + type_register_static(&aspeed_2400_xdma_info); + type_register_static(&aspeed_2500_xdma_info); + type_register_static(&aspeed_2600_xdma_info); } type_init(aspeed_xdma_register_type); diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 21034dc60a..1e7b8b064b 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -109,6 +109,7 @@ softmmu_ss.add(when: 'CONFIG_PVPANIC_ISA', if_true: files('pvpanic-isa.c')) softmmu_ss.add(when: 'CONFIG_PVPANIC_PCI', if_true: files('pvpanic-pci.c')) softmmu_ss.add(when: 'CONFIG_AUX', if_true: files('auxbus.c')) softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files( + 'aspeed_hace.c', 'aspeed_lpc.c', 'aspeed_scu.c', 'aspeed_sdmc.c', diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index 16addee4dc..189b35637c 100644 --- a/hw/ssi/aspeed_smc.c +++ b/hw/ssi/aspeed_smc.c @@ -127,6 +127,8 @@ /* DMA Control/Status Register */ #define R_DMA_CTRL (0x80 / 4) +#define DMA_CTRL_REQUEST (1 << 31) +#define DMA_CTRL_GRANT (1 << 30) #define DMA_CTRL_DELAY_MASK 0xf #define DMA_CTRL_DELAY_SHIFT 8 #define DMA_CTRL_FREQ_MASK 0xf @@ -178,10 +180,8 @@ * 0: 4 bytes * 0x7FFFFF: 32M bytes */ -#define DMA_DRAM_ADDR(s, val) ((s)->sdram_base | \ - ((val) & (s)->ctrl->dma_dram_mask)) -#define DMA_FLASH_ADDR(s, val) ((s)->ctrl->flash_window_base | \ - ((val) & (s)->ctrl->dma_flash_mask)) +#define DMA_DRAM_ADDR(s, val) ((val) & (s)->ctrl->dma_dram_mask) +#define DMA_FLASH_ADDR(s, val) ((val) & (s)->ctrl->dma_flash_mask) #define DMA_LENGTH(val) ((val) & 0x01FFFFFC) /* Flash opcodes. */ @@ -230,6 +230,7 @@ static uint32_t aspeed_smc_segment_to_reg(const AspeedSMCState *s, const AspeedSegments *seg); static void aspeed_smc_reg_to_segment(const AspeedSMCState *s, uint32_t reg, AspeedSegments *seg); +static void aspeed_smc_dma_ctrl(AspeedSMCState *s, uint32_t value); /* * AST2600 definitions @@ -259,6 +260,15 @@ static uint32_t aspeed_2600_smc_segment_to_reg(const AspeedSMCState *s, const AspeedSegments *seg); static void aspeed_2600_smc_reg_to_segment(const AspeedSMCState *s, uint32_t reg, AspeedSegments *seg); +static void aspeed_2600_smc_dma_ctrl(AspeedSMCState *s, uint32_t value); + +#define ASPEED_SMC_FEATURE_DMA 0x1 +#define ASPEED_SMC_FEATURE_DMA_GRANT 0x2 + +static inline bool aspeed_smc_has_dma(const AspeedSMCState *s) +{ + return !!(s->ctrl->features & ASPEED_SMC_FEATURE_DMA); +} static const AspeedSMCController controllers[] = { { @@ -273,10 +283,11 @@ static const AspeedSMCController controllers[] = { .segments = aspeed_segments_legacy, .flash_window_base = ASPEED_SOC_SMC_FLASH_BASE, .flash_window_size = 0x6000000, - .has_dma = false, + .features = 0x0, .nregs = ASPEED_SMC_R_SMC_MAX, .segment_to_reg = aspeed_smc_segment_to_reg, .reg_to_segment = aspeed_smc_reg_to_segment, + .dma_ctrl = aspeed_smc_dma_ctrl, }, { .name = "aspeed.fmc-ast2400", .r_conf = R_CONF, @@ -289,12 +300,13 @@ static const AspeedSMCController controllers[] = { .segments = aspeed_segments_fmc, .flash_window_base = ASPEED_SOC_FMC_FLASH_BASE, .flash_window_size = 0x10000000, - .has_dma = true, + .features = ASPEED_SMC_FEATURE_DMA, .dma_flash_mask = 0x0FFFFFFC, .dma_dram_mask = 0x1FFFFFFC, .nregs = ASPEED_SMC_R_MAX, .segment_to_reg = aspeed_smc_segment_to_reg, .reg_to_segment = aspeed_smc_reg_to_segment, + .dma_ctrl = aspeed_smc_dma_ctrl, }, { .name = "aspeed.spi1-ast2400", .r_conf = R_SPI_CONF, @@ -307,10 +319,11 @@ static const AspeedSMCController controllers[] = { .segments = aspeed_segments_spi, .flash_window_base = ASPEED_SOC_SPI_FLASH_BASE, .flash_window_size = 0x10000000, - .has_dma = false, + .features = 0x0, .nregs = ASPEED_SMC_R_SPI_MAX, .segment_to_reg = aspeed_smc_segment_to_reg, .reg_to_segment = aspeed_smc_reg_to_segment, + .dma_ctrl = aspeed_smc_dma_ctrl, }, { .name = "aspeed.fmc-ast2500", .r_conf = R_CONF, @@ -323,12 +336,13 @@ static const AspeedSMCController controllers[] = { .segments = aspeed_segments_ast2500_fmc, .flash_window_base = ASPEED_SOC_FMC_FLASH_BASE, .flash_window_size = 0x10000000, - .has_dma = true, + .features = ASPEED_SMC_FEATURE_DMA, .dma_flash_mask = 0x0FFFFFFC, .dma_dram_mask = 0x3FFFFFFC, .nregs = ASPEED_SMC_R_MAX, .segment_to_reg = aspeed_smc_segment_to_reg, .reg_to_segment = aspeed_smc_reg_to_segment, + .dma_ctrl = aspeed_smc_dma_ctrl, }, { .name = "aspeed.spi1-ast2500", .r_conf = R_CONF, @@ -341,10 +355,11 @@ static const AspeedSMCController controllers[] = { .segments = aspeed_segments_ast2500_spi1, .flash_window_base = ASPEED_SOC_SPI_FLASH_BASE, .flash_window_size = 0x8000000, - .has_dma = false, + .features = 0x0, .nregs = ASPEED_SMC_R_MAX, .segment_to_reg = aspeed_smc_segment_to_reg, .reg_to_segment = aspeed_smc_reg_to_segment, + .dma_ctrl = aspeed_smc_dma_ctrl, }, { .name = "aspeed.spi2-ast2500", .r_conf = R_CONF, @@ -357,10 +372,11 @@ static const AspeedSMCController controllers[] = { .segments = aspeed_segments_ast2500_spi2, .flash_window_base = ASPEED_SOC_SPI2_FLASH_BASE, .flash_window_size = 0x8000000, - .has_dma = false, + .features = 0x0, .nregs = ASPEED_SMC_R_MAX, .segment_to_reg = aspeed_smc_segment_to_reg, .reg_to_segment = aspeed_smc_reg_to_segment, + .dma_ctrl = aspeed_smc_dma_ctrl, }, { .name = "aspeed.fmc-ast2600", .r_conf = R_CONF, @@ -373,12 +389,13 @@ static const AspeedSMCController controllers[] = { .segments = aspeed_segments_ast2600_fmc, .flash_window_base = ASPEED26_SOC_FMC_FLASH_BASE, .flash_window_size = 0x10000000, - .has_dma = true, + .features = ASPEED_SMC_FEATURE_DMA, .dma_flash_mask = 0x0FFFFFFC, .dma_dram_mask = 0x3FFFFFFC, .nregs = ASPEED_SMC_R_MAX, .segment_to_reg = aspeed_2600_smc_segment_to_reg, .reg_to_segment = aspeed_2600_smc_reg_to_segment, + .dma_ctrl = aspeed_2600_smc_dma_ctrl, }, { .name = "aspeed.spi1-ast2600", .r_conf = R_CONF, @@ -391,12 +408,14 @@ static const AspeedSMCController controllers[] = { .segments = aspeed_segments_ast2600_spi1, .flash_window_base = ASPEED26_SOC_SPI_FLASH_BASE, .flash_window_size = 0x10000000, - .has_dma = true, + .features = ASPEED_SMC_FEATURE_DMA | + ASPEED_SMC_FEATURE_DMA_GRANT, .dma_flash_mask = 0x0FFFFFFC, .dma_dram_mask = 0x3FFFFFFC, .nregs = ASPEED_SMC_R_MAX, .segment_to_reg = aspeed_2600_smc_segment_to_reg, .reg_to_segment = aspeed_2600_smc_reg_to_segment, + .dma_ctrl = aspeed_2600_smc_dma_ctrl, }, { .name = "aspeed.spi2-ast2600", .r_conf = R_CONF, @@ -409,12 +428,14 @@ static const AspeedSMCController controllers[] = { .segments = aspeed_segments_ast2600_spi2, .flash_window_base = ASPEED26_SOC_SPI2_FLASH_BASE, .flash_window_size = 0x10000000, - .has_dma = true, + .features = ASPEED_SMC_FEATURE_DMA | + ASPEED_SMC_FEATURE_DMA_GRANT, .dma_flash_mask = 0x0FFFFFFC, .dma_dram_mask = 0x3FFFFFFC, .nregs = ASPEED_SMC_R_MAX, .segment_to_reg = aspeed_2600_smc_segment_to_reg, .reg_to_segment = aspeed_2600_smc_reg_to_segment, + .dma_ctrl = aspeed_2600_smc_dma_ctrl, }, }; @@ -999,11 +1020,11 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size) addr == R_CE_CMD_CTRL || addr == R_INTR_CTRL || addr == R_DUMMY_DATA || - (s->ctrl->has_dma && addr == R_DMA_CTRL) || - (s->ctrl->has_dma && addr == R_DMA_FLASH_ADDR) || - (s->ctrl->has_dma && addr == R_DMA_DRAM_ADDR) || - (s->ctrl->has_dma && addr == R_DMA_LEN) || - (s->ctrl->has_dma && addr == R_DMA_CHECKSUM) || + (aspeed_smc_has_dma(s) && addr == R_DMA_CTRL) || + (aspeed_smc_has_dma(s) && addr == R_DMA_FLASH_ADDR) || + (aspeed_smc_has_dma(s) && addr == R_DMA_DRAM_ADDR) || + (aspeed_smc_has_dma(s) && addr == R_DMA_LEN) || + (aspeed_smc_has_dma(s) && addr == R_DMA_CHECKSUM) || (addr >= R_SEG_ADDR0 && addr < R_SEG_ADDR0 + s->ctrl->max_peripherals) || (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->ctrl->max_peripherals)) { @@ -1236,7 +1257,7 @@ static void aspeed_smc_dma_done(AspeedSMCState *s) } } -static void aspeed_smc_dma_ctrl(AspeedSMCState *s, uint64_t dma_ctrl) +static void aspeed_smc_dma_ctrl(AspeedSMCState *s, uint32_t dma_ctrl) { if (!(dma_ctrl & DMA_CTRL_ENABLE)) { s->regs[R_DMA_CTRL] = dma_ctrl; @@ -1261,6 +1282,46 @@ static void aspeed_smc_dma_ctrl(AspeedSMCState *s, uint64_t dma_ctrl) aspeed_smc_dma_done(s); } +static inline bool aspeed_smc_dma_granted(AspeedSMCState *s) +{ + if (!(s->ctrl->features & ASPEED_SMC_FEATURE_DMA_GRANT)) { + return true; + } + + if (!(s->regs[R_DMA_CTRL] & DMA_CTRL_GRANT)) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA not granted\n", __func__); + return false; + } + + return true; +} + +static void aspeed_2600_smc_dma_ctrl(AspeedSMCState *s, uint32_t dma_ctrl) +{ + /* Preserve DMA bits */ + dma_ctrl |= s->regs[R_DMA_CTRL] & (DMA_CTRL_REQUEST | DMA_CTRL_GRANT); + + if (dma_ctrl == 0xAEED0000) { + /* automatically grant request */ + s->regs[R_DMA_CTRL] |= (DMA_CTRL_REQUEST | DMA_CTRL_GRANT); + return; + } + + /* clear request */ + if (dma_ctrl == 0xDEEA0000) { + s->regs[R_DMA_CTRL] &= ~(DMA_CTRL_REQUEST | DMA_CTRL_GRANT); + return; + } + + if (!aspeed_smc_dma_granted(s)) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA not granted\n", __func__); + return; + } + + aspeed_smc_dma_ctrl(s, dma_ctrl); + s->regs[R_DMA_CTRL] &= ~(DMA_CTRL_REQUEST | DMA_CTRL_GRANT); +} + static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data, unsigned int size) { @@ -1292,13 +1353,16 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data, s->regs[addr] = value & 0xff; } else if (addr == R_INTR_CTRL) { s->regs[addr] = value; - } else if (s->ctrl->has_dma && addr == R_DMA_CTRL) { - aspeed_smc_dma_ctrl(s, value); - } else if (s->ctrl->has_dma && addr == R_DMA_DRAM_ADDR) { + } else if (aspeed_smc_has_dma(s) && addr == R_DMA_CTRL) { + s->ctrl->dma_ctrl(s, value); + } else if (aspeed_smc_has_dma(s) && addr == R_DMA_DRAM_ADDR && + aspeed_smc_dma_granted(s)) { s->regs[addr] = DMA_DRAM_ADDR(s, value); - } else if (s->ctrl->has_dma && addr == R_DMA_FLASH_ADDR) { + } else if (aspeed_smc_has_dma(s) && addr == R_DMA_FLASH_ADDR && + aspeed_smc_dma_granted(s)) { s->regs[addr] = DMA_FLASH_ADDR(s, value); - } else if (s->ctrl->has_dma && addr == R_DMA_LEN) { + } else if (aspeed_smc_has_dma(s) && addr == R_DMA_LEN && + aspeed_smc_dma_granted(s)) { s->regs[addr] = DMA_LENGTH(value); } else { qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n", @@ -1386,7 +1450,9 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp) memory_region_init_io(&s->mmio_flash, OBJECT(s), &aspeed_smc_flash_default_ops, s, name, s->ctrl->flash_window_size); - sysbus_init_mmio(sbd, &s->mmio_flash); + memory_region_init_alias(&s->mmio_flash_alias, OBJECT(s), name, + &s->mmio_flash, 0, s->ctrl->flash_window_size); + sysbus_init_mmio(sbd, &s->mmio_flash_alias); s->flashes = g_new0(AspeedSMCFlash, s->ctrl->max_peripherals); @@ -1412,7 +1478,7 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp) } /* DMA support */ - if (s->ctrl->has_dma) { + if (aspeed_smc_has_dma(s)) { aspeed_smc_dma_setup(s, errp); } } @@ -1432,7 +1498,6 @@ static const VMStateDescription vmstate_aspeed_smc = { static Property aspeed_smc_properties[] = { DEFINE_PROP_UINT32("num-cs", AspeedSMCState, num_cs, 1), DEFINE_PROP_BOOL("inject-failure", AspeedSMCState, inject_failure, false), - DEFINE_PROP_UINT64("sdram-base", AspeedSMCState, sdram_base, 0), DEFINE_PROP_LINK("dram", AspeedSMCState, dram_mr, TYPE_MEMORY_REGION, MemoryRegion *), DEFINE_PROP_END_OF_LIST(), diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index 9359d6da33..d9161d26d6 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -21,6 +21,7 @@ #include "hw/rtc/aspeed_rtc.h" #include "hw/i2c/aspeed_i2c.h" #include "hw/ssi/aspeed_smc.h" +#include "hw/misc/aspeed_hace.h" #include "hw/watchdog/wdt_aspeed.h" #include "hw/net/ftgmac100.h" #include "target/arm/cpu.h" @@ -50,6 +51,7 @@ struct AspeedSoCState { AspeedTimerCtrlState timerctrl; AspeedI2CState i2c; AspeedSCUState scu; + AspeedHACEState hace; AspeedXDMAState xdma; AspeedSMCState fmc; AspeedSMCState spi[ASPEED_SPIS_NUM]; @@ -133,6 +135,7 @@ enum { ASPEED_DEV_XDMA, ASPEED_DEV_EMMC, ASPEED_DEV_KCS, + ASPEED_DEV_HACE, }; #endif /* ASPEED_SOC_H */ diff --git a/include/hw/misc/aspeed_hace.h b/include/hw/misc/aspeed_hace.h new file mode 100644 index 0000000000..94d5ada95f --- /dev/null +++ b/include/hw/misc/aspeed_hace.h @@ -0,0 +1,43 @@ +/* + * ASPEED Hash and Crypto Engine + * + * Copyright (C) 2021 IBM Corp. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef ASPEED_HACE_H +#define ASPEED_HACE_H + +#include "hw/sysbus.h" + +#define TYPE_ASPEED_HACE "aspeed.hace" +#define TYPE_ASPEED_AST2400_HACE TYPE_ASPEED_HACE "-ast2400" +#define TYPE_ASPEED_AST2500_HACE TYPE_ASPEED_HACE "-ast2500" +#define TYPE_ASPEED_AST2600_HACE TYPE_ASPEED_HACE "-ast2600" +OBJECT_DECLARE_TYPE(AspeedHACEState, AspeedHACEClass, ASPEED_HACE) + +#define ASPEED_HACE_NR_REGS (0x64 >> 2) + +struct AspeedHACEState { + SysBusDevice parent; + + MemoryRegion iomem; + qemu_irq irq; + + uint32_t regs[ASPEED_HACE_NR_REGS]; + + MemoryRegion *dram_mr; + AddressSpace dram_as; +}; + + +struct AspeedHACEClass { + SysBusDeviceClass parent_class; + + uint32_t src_mask; + uint32_t dest_mask; + uint32_t hash_mask; +}; + +#endif /* _ASPEED_HACE_H_ */ diff --git a/include/hw/misc/aspeed_xdma.h b/include/hw/misc/aspeed_xdma.h index a2dea96984..b1478fd1c6 100644 --- a/include/hw/misc/aspeed_xdma.h +++ b/include/hw/misc/aspeed_xdma.h @@ -13,7 +13,10 @@ #include "qom/object.h" #define TYPE_ASPEED_XDMA "aspeed.xdma" -OBJECT_DECLARE_SIMPLE_TYPE(AspeedXDMAState, ASPEED_XDMA) +#define TYPE_ASPEED_2400_XDMA TYPE_ASPEED_XDMA "-ast2400" +#define TYPE_ASPEED_2500_XDMA TYPE_ASPEED_XDMA "-ast2500" +#define TYPE_ASPEED_2600_XDMA TYPE_ASPEED_XDMA "-ast2600" +OBJECT_DECLARE_TYPE(AspeedXDMAState, AspeedXDMAClass, ASPEED_XDMA) #define ASPEED_XDMA_NUM_REGS (ASPEED_XDMA_REG_SIZE / sizeof(uint32_t)) #define ASPEED_XDMA_REG_SIZE 0x7C @@ -28,4 +31,16 @@ struct AspeedXDMAState { uint32_t regs[ASPEED_XDMA_NUM_REGS]; }; +struct AspeedXDMAClass { + SysBusDeviceClass parent_class; + + uint8_t cmdq_endp; + uint8_t cmdq_wrp; + uint8_t cmdq_rdp; + uint8_t intr_ctrl; + uint32_t intr_ctrl_mask; + uint8_t intr_status; + uint32_t intr_complete; +}; + #endif /* ASPEED_XDMA_H */ diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h index 16c03fe64f..cdaf165300 100644 --- a/include/hw/ssi/aspeed_smc.h +++ b/include/hw/ssi/aspeed_smc.h @@ -47,7 +47,7 @@ typedef struct AspeedSMCController { const AspeedSegments *segments; hwaddr flash_window_base; uint32_t flash_window_size; - bool has_dma; + uint32_t features; hwaddr dma_flash_mask; hwaddr dma_dram_mask; uint32_t nregs; @@ -55,6 +55,7 @@ typedef struct AspeedSMCController { const AspeedSegments *seg); void (*reg_to_segment)(const struct AspeedSMCState *s, uint32_t reg, AspeedSegments *seg); + void (*dma_ctrl)(struct AspeedSMCState *s, uint32_t value); } AspeedSMCController; typedef struct AspeedSMCFlash { @@ -84,6 +85,7 @@ struct AspeedSMCState { MemoryRegion mmio; MemoryRegion mmio_flash; + MemoryRegion mmio_flash_alias; qemu_irq irq; int irqline; @@ -103,9 +105,6 @@ struct AspeedSMCState { uint8_t r_timings; uint8_t conf_enable_w0; - /* for DMA support */ - uint64_t sdram_base; - AddressSpace flash_as; MemoryRegion *dram_mr; AddressSpace dram_as; diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py index 1ca32ecf25..276a53f146 100644 --- a/tests/acceptance/boot_linux_console.py +++ b/tests/acceptance/boot_linux_console.py @@ -1010,6 +1010,74 @@ class BootLinuxConsole(LinuxKernelTest): self.vm.add_args('-dtb', self.workdir + '/day16/vexpress-v2p-ca9.dtb') self.do_test_advcal_2018('16', tar_hash, 'winter.zImage') + def test_arm_ast2400_palmetto_openbmc_v2_9_0(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:palmetto-bmc + """ + + image_url = ('https://github.com/openbmc/openbmc/releases/download/2.9.0/' + 'obmc-phosphor-image-palmetto.static.mtd') + image_hash = ('3e13bbbc28e424865dc42f35ad672b10f2e82cdb11846bb28fa625b48beafd0d') + image_path = self.fetch_asset(image_url, asset_hash=image_hash, + algorithm='sha256') + + self.do_test_arm_aspeed(image_path) + + def test_arm_ast2500_romulus_openbmc_v2_9_0(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:romulus-bmc + """ + + image_url = ('https://github.com/openbmc/openbmc/releases/download/2.9.0/' + 'obmc-phosphor-image-romulus.static.mtd') + image_hash = ('820341076803f1955bc31e647a512c79f9add4f5233d0697678bab4604c7bb25') + image_path = self.fetch_asset(image_url, asset_hash=image_hash, + algorithm='sha256') + + self.do_test_arm_aspeed(image_path) + + def do_test_arm_aspeed(self, image): + self.vm.set_console() + self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw', + '-net', 'nic') + self.vm.launch() + + self.wait_for_console_pattern("U-Boot 2016.07") + self.wait_for_console_pattern("## Loading kernel from FIT Image at 20080000") + self.wait_for_console_pattern("Starting kernel ...") + self.wait_for_console_pattern("Booting Linux on physical CPU 0x0") + self.wait_for_console_pattern( + "aspeed-smc 1e620000.spi: read control register: 203b0641") + self.wait_for_console_pattern("ftgmac100 1e660000.ethernet eth0: irq ") + self.wait_for_console_pattern("systemd[1]: Set hostname to") + + def test_arm_ast2600_debian(self): + """ + :avocado: tags=arch:arm + :avocado: tags=machine:tacoma-bmc + """ + deb_url = ('http://snapshot.debian.org/archive/debian/' + '20210302T203551Z/' + 'pool/main/l/linux/' + 'linux-image-5.10.0-3-armmp_5.10.13-1_armhf.deb') + deb_hash = 'db40d32fe39255d05482bea48d72467b67d6225bb2a2a4d6f618cb8976f1e09e' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash, + algorithm='sha256') + kernel_path = self.extract_from_deb(deb_path, '/boot/vmlinuz-5.10.0-3-armmp') + dtb_path = self.extract_from_deb(deb_path, + '/usr/lib/linux-image-5.10.0-3-armmp/aspeed-bmc-opp-tacoma.dtb') + + self.vm.set_console() + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-net', 'nic') + self.vm.launch() + self.wait_for_console_pattern("Booting Linux on physical CPU 0xf00") + self.wait_for_console_pattern("SMP: Total of 2 processors activated") + self.wait_for_console_pattern("No filesystem could mount root") + def test_m68k_mcf5208evb(self): """ :avocado: tags=arch:m68k diff --git a/tests/qtest/aspeed_hace-test.c b/tests/qtest/aspeed_hace-test.c new file mode 100644 index 0000000000..09ee31545e --- /dev/null +++ b/tests/qtest/aspeed_hace-test.c @@ -0,0 +1,469 @@ +/* + * QTest testcase for the ASPEED Hash and Crypto Engine + * + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2021 IBM Corp. + */ + +#include "qemu/osdep.h" + +#include "libqos/libqtest.h" +#include "qemu-common.h" +#include "qemu/bitops.h" + +#define HACE_CMD 0x10 +#define HACE_SHA_BE_EN BIT(3) +#define HACE_MD5_LE_EN BIT(2) +#define HACE_ALGO_MD5 0 +#define HACE_ALGO_SHA1 BIT(5) +#define HACE_ALGO_SHA224 BIT(6) +#define HACE_ALGO_SHA256 (BIT(4) | BIT(6)) +#define HACE_ALGO_SHA512 (BIT(5) | BIT(6)) +#define HACE_ALGO_SHA384 (BIT(5) | BIT(6) | BIT(10)) +#define HACE_SG_EN BIT(18) + +#define HACE_STS 0x1c +#define HACE_RSA_ISR BIT(13) +#define HACE_CRYPTO_ISR BIT(12) +#define HACE_HASH_ISR BIT(9) +#define HACE_RSA_BUSY BIT(2) +#define HACE_CRYPTO_BUSY BIT(1) +#define HACE_HASH_BUSY BIT(0) +#define HACE_HASH_SRC 0x20 +#define HACE_HASH_DIGEST 0x24 +#define HACE_HASH_KEY_BUFF 0x28 +#define HACE_HASH_DATA_LEN 0x2c +#define HACE_HASH_CMD 0x30 +/* Scatter-Gather Hash */ +#define SG_LIST_LEN_LAST BIT(31) +struct AspeedSgList { + uint32_t len; + uint32_t addr; +} __attribute__ ((__packed__)); + +/* + * Test vector is the ascii "abc" + * + * Expected results were generated using command line utitiles: + * + * echo -n -e 'abc' | dd of=/tmp/test + * for hash in sha512sum sha256sum md5sum; do $hash /tmp/test; done + * + */ +static const uint8_t test_vector[] = {0x61, 0x62, 0x63}; + +static const uint8_t test_result_sha512[] = { + 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49, + 0xae, 0x20, 0x41, 0x31, 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, + 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, 0x21, 0x92, 0x99, 0x2a, + 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, + 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f, + 0xa5, 0x4c, 0xa4, 0x9f}; + +static const uint8_t test_result_sha256[] = { + 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, + 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad}; + +static const uint8_t test_result_md5[] = { + 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d, + 0x28, 0xe1, 0x7f, 0x72}; + +/* + * The Scatter-Gather Test vector is the ascii "abc" "def" "ghi", broken + * into blocks of 3 characters as shown + * + * Expected results were generated using command line utitiles: + * + * echo -n -e 'abcdefghijkl' | dd of=/tmp/test + * for hash in sha512sum sha256sum; do $hash /tmp/test; done + * + */ +static const uint8_t test_vector_sg1[] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66}; +static const uint8_t test_vector_sg2[] = {0x67, 0x68, 0x69}; +static const uint8_t test_vector_sg3[] = {0x6a, 0x6b, 0x6c}; + +static const uint8_t test_result_sg_sha512[] = { + 0x17, 0x80, 0x7c, 0x72, 0x8e, 0xe3, 0xba, 0x35, 0xe7, 0xcf, 0x7a, 0xf8, + 0x23, 0x11, 0x6d, 0x26, 0xe4, 0x1e, 0x5d, 0x4d, 0x6c, 0x2f, 0xf1, 0xf3, + 0x72, 0x0d, 0x3d, 0x96, 0xaa, 0xcb, 0x6f, 0x69, 0xde, 0x64, 0x2e, 0x63, + 0xd5, 0xb7, 0x3f, 0xc3, 0x96, 0xc1, 0x2b, 0xe3, 0x8b, 0x2b, 0xd5, 0xd8, + 0x84, 0x25, 0x7c, 0x32, 0xc8, 0xf6, 0xd0, 0x85, 0x4a, 0xe6, 0xb5, 0x40, + 0xf8, 0x6d, 0xda, 0x2e}; + +static const uint8_t test_result_sg_sha256[] = { + 0xd6, 0x82, 0xed, 0x4c, 0xa4, 0xd9, 0x89, 0xc1, 0x34, 0xec, 0x94, 0xf1, + 0x55, 0x1e, 0x1e, 0xc5, 0x80, 0xdd, 0x6d, 0x5a, 0x6e, 0xcd, 0xe9, 0xf3, + 0xd3, 0x5e, 0x6e, 0x4a, 0x71, 0x7f, 0xbd, 0xe4}; + + +static void write_regs(QTestState *s, uint32_t base, uint32_t src, + uint32_t length, uint32_t out, uint32_t method) +{ + qtest_writel(s, base + HACE_HASH_SRC, src); + qtest_writel(s, base + HACE_HASH_DIGEST, out); + qtest_writel(s, base + HACE_HASH_DATA_LEN, length); + qtest_writel(s, base + HACE_HASH_CMD, HACE_SHA_BE_EN | method); +} + +static void test_md5(const char *machine, const uint32_t base, + const uint32_t src_addr) + +{ + QTestState *s = qtest_init(machine); + + uint32_t digest_addr = src_addr + 0x01000000; + uint8_t digest[16] = {0}; + + /* Check engine is idle, no busy or irq bits set */ + g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0); + + /* Write test vector into memory */ + qtest_memwrite(s, src_addr, test_vector, sizeof(test_vector)); + + write_regs(s, base, src_addr, sizeof(test_vector), digest_addr, HACE_ALGO_MD5); + + /* Check hash IRQ status is asserted */ + g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200); + + /* Clear IRQ status and check status is deasserted */ + qtest_writel(s, base + HACE_STS, 0x00000200); + g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0); + + /* Read computed digest from memory */ + qtest_memread(s, digest_addr, digest, sizeof(digest)); + + /* Check result of computation */ + g_assert_cmpmem(digest, sizeof(digest), + test_result_md5, sizeof(digest)); + + qtest_quit(s); +} + +static void test_sha256(const char *machine, const uint32_t base, + const uint32_t src_addr) +{ + QTestState *s = qtest_init(machine); + + const uint32_t digest_addr = src_addr + 0x1000000; + uint8_t digest[32] = {0}; + + /* Check engine is idle, no busy or irq bits set */ + g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0); + + /* Write test vector into memory */ + qtest_memwrite(s, src_addr, test_vector, sizeof(test_vector)); + + write_regs(s, base, src_addr, sizeof(test_vector), digest_addr, HACE_ALGO_SHA256); + + /* Check hash IRQ status is asserted */ + g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200); + + /* Clear IRQ status and check status is deasserted */ + qtest_writel(s, base + HACE_STS, 0x00000200); + g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0); + + /* Read computed digest from memory */ + qtest_memread(s, digest_addr, digest, sizeof(digest)); + + /* Check result of computation */ + g_assert_cmpmem(digest, sizeof(digest), + test_result_sha256, sizeof(digest)); + + qtest_quit(s); +} + +static void test_sha512(const char *machine, const uint32_t base, + const uint32_t src_addr) +{ + QTestState *s = qtest_init(machine); + + const uint32_t digest_addr = src_addr + 0x1000000; + uint8_t digest[64] = {0}; + + /* Check engine is idle, no busy or irq bits set */ + g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0); + + /* Write test vector into memory */ + qtest_memwrite(s, src_addr, test_vector, sizeof(test_vector)); + + write_regs(s, base, src_addr, sizeof(test_vector), digest_addr, HACE_ALGO_SHA512); + + /* Check hash IRQ status is asserted */ + g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200); + + /* Clear IRQ status and check status is deasserted */ + qtest_writel(s, base + HACE_STS, 0x00000200); + g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0); + + /* Read computed digest from memory */ + qtest_memread(s, digest_addr, digest, sizeof(digest)); + + /* Check result of computation */ + g_assert_cmpmem(digest, sizeof(digest), + test_result_sha512, sizeof(digest)); + + qtest_quit(s); +} + +static void test_sha256_sg(const char *machine, const uint32_t base, + const uint32_t src_addr) +{ + QTestState *s = qtest_init(machine); + + const uint32_t src_addr_1 = src_addr + 0x1000000; + const uint32_t src_addr_2 = src_addr + 0x2000000; + const uint32_t src_addr_3 = src_addr + 0x3000000; + const uint32_t digest_addr = src_addr + 0x4000000; + uint8_t digest[32] = {0}; + struct AspeedSgList array[] = { + { cpu_to_le32(sizeof(test_vector_sg1)), + cpu_to_le32(src_addr_1) }, + { cpu_to_le32(sizeof(test_vector_sg2)), + cpu_to_le32(src_addr_2) }, + { cpu_to_le32(sizeof(test_vector_sg3) | SG_LIST_LEN_LAST), + cpu_to_le32(src_addr_3) }, + }; + + /* Check engine is idle, no busy or irq bits set */ + g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0); + + /* Write test vector into memory */ + qtest_memwrite(s, src_addr_1, test_vector_sg1, sizeof(test_vector_sg1)); + qtest_memwrite(s, src_addr_2, test_vector_sg2, sizeof(test_vector_sg2)); + qtest_memwrite(s, src_addr_3, test_vector_sg3, sizeof(test_vector_sg3)); + qtest_memwrite(s, src_addr, array, sizeof(array)); + + write_regs(s, base, src_addr, + (sizeof(test_vector_sg1) + + sizeof(test_vector_sg2) + + sizeof(test_vector_sg3)), + digest_addr, HACE_ALGO_SHA256 | HACE_SG_EN); + + /* Check hash IRQ status is asserted */ + g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200); + + /* Clear IRQ status and check status is deasserted */ + qtest_writel(s, base + HACE_STS, 0x00000200); + g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0); + + /* Read computed digest from memory */ + qtest_memread(s, digest_addr, digest, sizeof(digest)); + + /* Check result of computation */ + g_assert_cmpmem(digest, sizeof(digest), + test_result_sg_sha256, sizeof(digest)); + + qtest_quit(s); +} + +static void test_sha512_sg(const char *machine, const uint32_t base, + const uint32_t src_addr) +{ + QTestState *s = qtest_init(machine); + + const uint32_t src_addr_1 = src_addr + 0x1000000; + const uint32_t src_addr_2 = src_addr + 0x2000000; + const uint32_t src_addr_3 = src_addr + 0x3000000; + const uint32_t digest_addr = src_addr + 0x4000000; + uint8_t digest[64] = {0}; + struct AspeedSgList array[] = { + { cpu_to_le32(sizeof(test_vector_sg1)), + cpu_to_le32(src_addr_1) }, + { cpu_to_le32(sizeof(test_vector_sg2)), + cpu_to_le32(src_addr_2) }, + { cpu_to_le32(sizeof(test_vector_sg3) | SG_LIST_LEN_LAST), + cpu_to_le32(src_addr_3) }, + }; + + /* Check engine is idle, no busy or irq bits set */ + g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0); + + /* Write test vector into memory */ + qtest_memwrite(s, src_addr_1, test_vector_sg1, sizeof(test_vector_sg1)); + qtest_memwrite(s, src_addr_2, test_vector_sg2, sizeof(test_vector_sg2)); + qtest_memwrite(s, src_addr_3, test_vector_sg3, sizeof(test_vector_sg3)); + qtest_memwrite(s, src_addr, array, sizeof(array)); + + write_regs(s, base, src_addr, + (sizeof(test_vector_sg1) + + sizeof(test_vector_sg2) + + sizeof(test_vector_sg3)), + digest_addr, HACE_ALGO_SHA512 | HACE_SG_EN); + + /* Check hash IRQ status is asserted */ + g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200); + + /* Clear IRQ status and check status is deasserted */ + qtest_writel(s, base + HACE_STS, 0x00000200); + g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0); + + /* Read computed digest from memory */ + qtest_memread(s, digest_addr, digest, sizeof(digest)); + + /* Check result of computation */ + g_assert_cmpmem(digest, sizeof(digest), + test_result_sg_sha512, sizeof(digest)); + + qtest_quit(s); +} + +struct masks { + uint32_t src; + uint32_t dest; + uint32_t len; +}; + +static const struct masks ast2600_masks = { + .src = 0x7fffffff, + .dest = 0x7ffffff8, + .len = 0x0fffffff, +}; + +static const struct masks ast2500_masks = { + .src = 0x3fffffff, + .dest = 0x3ffffff8, + .len = 0x0fffffff, +}; + +static const struct masks ast2400_masks = { + .src = 0x0fffffff, + .dest = 0x0ffffff8, + .len = 0x0fffffff, +}; + +static void test_addresses(const char *machine, const uint32_t base, + const struct masks *expected) +{ + QTestState *s = qtest_init(machine); + + /* + * Check command mode is zero, meaning engine is in direct access mode, + * as this affects the masking behavior of the HASH_SRC register. + */ + g_assert_cmphex(qtest_readl(s, base + HACE_CMD), ==, 0); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_SRC), ==, 0); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DIGEST), ==, 0); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DATA_LEN), ==, 0); + + + /* Check that the address masking is correct */ + qtest_writel(s, base + HACE_HASH_SRC, 0xffffffff); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_SRC), ==, expected->src); + + qtest_writel(s, base + HACE_HASH_DIGEST, 0xffffffff); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DIGEST), ==, expected->dest); + + qtest_writel(s, base + HACE_HASH_DATA_LEN, 0xffffffff); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DATA_LEN), ==, expected->len); + + /* Reset to zero */ + qtest_writel(s, base + HACE_HASH_SRC, 0); + qtest_writel(s, base + HACE_HASH_DIGEST, 0); + qtest_writel(s, base + HACE_HASH_DATA_LEN, 0); + + /* Check that all bits are now zero */ + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_SRC), ==, 0); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DIGEST), ==, 0); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DATA_LEN), ==, 0); + + qtest_quit(s); +} + +/* ast2600 */ +static void test_md5_ast2600(void) +{ + test_md5("-machine ast2600-evb", 0x1e6d0000, 0x80000000); +} + +static void test_sha256_ast2600(void) +{ + test_sha256("-machine ast2600-evb", 0x1e6d0000, 0x80000000); +} + +static void test_sha256_sg_ast2600(void) +{ + test_sha256_sg("-machine ast2600-evb", 0x1e6d0000, 0x80000000); +} + +static void test_sha512_ast2600(void) +{ + test_sha512("-machine ast2600-evb", 0x1e6d0000, 0x80000000); +} + +static void test_sha512_sg_ast2600(void) +{ + test_sha512_sg("-machine ast2600-evb", 0x1e6d0000, 0x80000000); +} + +static void test_addresses_ast2600(void) +{ + test_addresses("-machine ast2600-evb", 0x1e6d0000, &ast2600_masks); +} + +/* ast2500 */ +static void test_md5_ast2500(void) +{ + test_md5("-machine ast2500-evb", 0x1e6e3000, 0x80000000); +} + +static void test_sha256_ast2500(void) +{ + test_sha256("-machine ast2500-evb", 0x1e6e3000, 0x80000000); +} + +static void test_sha512_ast2500(void) +{ + test_sha512("-machine ast2500-evb", 0x1e6e3000, 0x80000000); +} + +static void test_addresses_ast2500(void) +{ + test_addresses("-machine ast2500-evb", 0x1e6e3000, &ast2500_masks); +} + +/* ast2400 */ +static void test_md5_ast2400(void) +{ + test_md5("-machine palmetto-bmc", 0x1e6e3000, 0x40000000); +} + +static void test_sha256_ast2400(void) +{ + test_sha256("-machine palmetto-bmc", 0x1e6e3000, 0x40000000); +} + +static void test_sha512_ast2400(void) +{ + test_sha512("-machine palmetto-bmc", 0x1e6e3000, 0x40000000); +} + +static void test_addresses_ast2400(void) +{ + test_addresses("-machine palmetto-bmc", 0x1e6e3000, &ast2400_masks); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("ast2600/hace/addresses", test_addresses_ast2600); + qtest_add_func("ast2600/hace/sha512", test_sha512_ast2600); + qtest_add_func("ast2600/hace/sha256", test_sha256_ast2600); + qtest_add_func("ast2600/hace/md5", test_md5_ast2600); + + qtest_add_func("ast2600/hace/sha512_sg", test_sha512_sg_ast2600); + qtest_add_func("ast2600/hace/sha256_sg", test_sha256_sg_ast2600); + + qtest_add_func("ast2500/hace/addresses", test_addresses_ast2500); + qtest_add_func("ast2500/hace/sha512", test_sha512_ast2500); + qtest_add_func("ast2500/hace/sha256", test_sha256_ast2500); + qtest_add_func("ast2500/hace/md5", test_md5_ast2500); + + qtest_add_func("ast2400/hace/addresses", test_addresses_ast2400); + qtest_add_func("ast2400/hace/sha512", test_sha512_ast2400); + qtest_add_func("ast2400/hace/sha256", test_sha256_ast2400); + qtest_add_func("ast2400/hace/md5", test_md5_ast2400); + + return g_test_run(); +} diff --git a/tests/qtest/m25p80-test.c b/tests/qtest/aspeed_smc-test.c index f860cef5f0..87b40a0ef1 100644 --- a/tests/qtest/m25p80-test.c +++ b/tests/qtest/aspeed_smc-test.c @@ -367,12 +367,12 @@ int main(int argc, char **argv) "-drive file=%s,format=raw,if=mtd", tmp_path); - qtest_add_func("/m25p80/read_jedec", test_read_jedec); - qtest_add_func("/m25p80/erase_sector", test_erase_sector); - qtest_add_func("/m25p80/erase_all", test_erase_all); - qtest_add_func("/m25p80/write_page", test_write_page); - qtest_add_func("/m25p80/read_page_mem", test_read_page_mem); - qtest_add_func("/m25p80/write_page_mem", test_write_page_mem); + qtest_add_func("/ast2400/smc/read_jedec", test_read_jedec); + qtest_add_func("/ast2400/smc/erase_sector", test_erase_sector); + qtest_add_func("/ast2400/smc/erase_all", test_erase_all); + qtest_add_func("/ast2400/smc/write_page", test_write_page); + qtest_add_func("/ast2400/smc/read_page_mem", test_read_page_mem); + qtest_add_func("/ast2400/smc/write_page_mem", test_write_page_mem); ret = g_test_run(); diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 0c76738921..966bc93efa 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -161,16 +161,19 @@ qtests_npcm7xx = \ 'npcm7xx_timer-test', 'npcm7xx_watchdog_timer-test'] + \ (slirp.found() ? ['npcm7xx_emc-test'] : []) +qtests_aspeed = \ + ['aspeed_hace-test', + 'aspeed_smc-test'] qtests_arm = \ (config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \ (config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-dualtimer-test'] : []) + \ (config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \ (config_all_devices.has_key('CONFIG_CMSDK_APB_WATCHDOG') ? ['cmsdk-apb-watchdog-test'] : []) + \ (config_all_devices.has_key('CONFIG_PFLASH_CFI02') ? ['pflash-cfi02-test'] : []) + \ + (config_all_devices.has_key('CONFIG_ASPEED_SOC') ? qtests_aspeed : []) + \ (config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \ ['arm-cpu-features', 'microbit-test', - 'm25p80-test', 'test-arm-mptimer', 'boot-serial-test', 'hexloader-test'] |