diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2025-05-26 10:16:59 -0400 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2025-05-26 10:16:59 -0400 |
commit | 80db93b2b88f9b3ed8927ae7ac74ca30e643a83e (patch) | |
tree | e5dd1a37a1d59330134b2525a68d9172a9c8f33c | |
parent | 3c5a5e213e5f08fbfe70728237f7799ac70f5b99 (diff) | |
parent | 8eaea4012c215a610b2bd6dcc7812e805e14dd0c (diff) | |
download | qemu-80db93b2b88f9b3ed8927ae7ac74ca30e643a83e.zip qemu-80db93b2b88f9b3ed8927ae7ac74ca30e643a83e.tar.gz qemu-80db93b2b88f9b3ed8927ae7ac74ca30e643a83e.tar.bz2 |
Merge tag 'pull-aspeed-20250526' of https://github.com/legoater/qemu into staging
aspeed queue:
* Fixed memory leaks in qtest tests
* Reworked and fixed HACE (crypto) model for AST2700 SoC
* Extended HACE qtest tests
* Fixed RAM size detection on BE hosts
* Added network backends to ast2700fc machine
* Mapped main SoC memory into system memory on multi SoC machines
# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmg0IJYACgkQUaNDx8/7
# 7KFWkBAAqzVVJVH+XxVsKimljyI5hpkl1h7EiH2XS4hYyXQyGarwLjfYQs8tDSL0
# tD3+nfDAgbob4vIMSHy8KNs05paB6jYFisHIgalszQh5YqPyxQGhvXNfOCoIApVh
# pcAmdaSmW+hfDMklOk1zDgLzxHuQX74EWBMRkCQycFrJzGE5Z4EFvQ6uavOGdrxP
# 2m5ytGyuXEwtE4MYnX/5mK6CkCOFh6TC7/z8QOXJoBvXjXmjO3Iu1l216jZdnxtB
# GBmavqpoDgm+884nWpf28jNKGos60QMMC2JAdBtdcW4RUxIGzZ8VYTpgS3bfuR+y
# vvElGa3c67Ie6mu1VUlyNJ58rSqkMb5FaEz+U+V3apdJXtiHhqTwvnAyVMVnD3S8
# ajnMVw+BGJVgQWT5/w3TV3B+09IkfxJ+sh0BEVsRtvH0gKbE040o6tBoNHNANnHO
# j33aMzVpAdqQFeRmxb1ysfSwzQV+q3Dw/rz9CNn8myAxqpixUq4AqWDasnWhSRVY
# Mqou6qlTCwjFmyeuq7YCC2Y0wOm2lgIkfggG+vkIoBPEU0g/yLcnYeb5pIV0w33m
# YqBB6UcxjGEN+hC4fkbkvXrIADNdkcs639al2xsRUYPz8+uTgUxO8poZvE4G+eNR
# Jj2CrJn7a6ThjD4mG8ezEuknQ5pZ9SnX8DAL11XvDUGHRG0+CtI=
# =00WM
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 26 May 2025 04:04:38 EDT
# gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1
# gpg: Good signature from "Cédric Le Goater <clg@redhat.com>" [full]
# gpg: aka "Cédric Le Goater <clg@kaod.org>" [full]
# Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1
* tag 'pull-aspeed-20250526' of https://github.com/legoater/qemu: (39 commits)
docs: Remove ast2700fc from Aspeed family boards
hw/arm/fby35: Map BMC memory into system memory
hw/arm/aspeed_ast27x0-fc: Map ca35 memory into system memory
hw/arm/aspeed_ast27x0: Fix unimplemented region overlap with vbootrom
hw/arm/aspeed_ast2700-fc: Reduce ca35 ram size to align with ast2700a1
hw/arm/aspeed_ast2700-fc: Add network support
hw/arm/aspeed_ast27x0: Fix RAM size detection failure on BE hosts
hw/intc/aspeed Fix coding style
hw/intc/aspeed: Set impl.min_access_size to 4
test/qtest/hace: Add tests for AST2700
test/qtest/hace: Support to validate 64-bit hmac key buffer addresses
test/qtest/hace: Support to test upper 32 bits of digest and source addresses
test/qtest/hace: Support 64-bit source and digest addresses for AST2700
test/qtest/hace: Update source data and digest data type to 64-bit
test/qtest/hace: Add tests for AST1030
test/qtest/hace: Add SHA-384 tests for AST2600
test/qtest/hace: Add SHA-384 test cases for ASPEED HACE model
test/qtest/hace: Adjust test address range for AST1030 due to SRAM limitations
test/qtest/hace: Specify explicit array sizes for test vectors and hash results
test/qtest: Introduce a new aspeed-hace-utils.c to place common testcases
...
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
-rw-r--r-- | docs/system/arm/aspeed.rst | 2 | ||||
-rw-r--r-- | hw/arm/aspeed_ast27x0-fc.c | 10 | ||||
-rw-r--r-- | hw/arm/aspeed_ast27x0.c | 14 | ||||
-rw-r--r-- | hw/arm/fby35.c | 1 | ||||
-rw-r--r-- | hw/intc/aspeed_intc.c | 12 | ||||
-rw-r--r-- | hw/misc/aspeed_hace.c | 479 | ||||
-rw-r--r-- | hw/misc/trace-events | 8 | ||||
-rw-r--r-- | include/hw/misc/aspeed_hace.h | 11 | ||||
-rw-r--r-- | tests/qtest/aspeed-hace-utils.c | 646 | ||||
-rw-r--r-- | tests/qtest/aspeed-hace-utils.h | 84 | ||||
-rw-r--r-- | tests/qtest/aspeed_hace-test.c | 577 | ||||
-rw-r--r-- | tests/qtest/aspeed_smc-test.c | 5 | ||||
-rw-r--r-- | tests/qtest/ast2700-hace-test.c | 98 | ||||
-rw-r--r-- | tests/qtest/ast2700-smc-test.c | 1 | ||||
-rw-r--r-- | tests/qtest/meson.build | 13 |
15 files changed, 1314 insertions, 647 deletions
diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst index 58a8020..43d27d8 100644 --- a/docs/system/arm/aspeed.rst +++ b/docs/system/arm/aspeed.rst @@ -1,4 +1,4 @@ -Aspeed family boards (``ast2500-evb``, ``ast2600-evb``, ``ast2700-evb``, ``ast2700fc``, ``bletchley-bmc``, ``fuji-bmc``, ``fby35-bmc``, ``fp5280g2-bmc``, ``g220a-bmc``, ``palmetto-bmc``, ``qcom-dc-scm-v1-bmc``, ``qcom-firework-bmc``, ``quanta-q71l-bmc``, ``rainier-bmc``, ``romulus-bmc``, ``sonorapass-bmc``, ``supermicrox11-bmc``, ``supermicrox11spi-bmc``, ``tiogapass-bmc``, ``witherspoon-bmc``, ``yosemitev2-bmc``) +Aspeed family boards (``ast2500-evb``, ``ast2600-evb``, ``ast2700-evb``, ``bletchley-bmc``, ``fuji-bmc``, ``fby35-bmc``, ``fp5280g2-bmc``, ``g220a-bmc``, ``palmetto-bmc``, ``qcom-dc-scm-v1-bmc``, ``qcom-firework-bmc``, ``quanta-q71l-bmc``, ``rainier-bmc``, ``romulus-bmc``, ``sonorapass-bmc``, ``supermicrox11-bmc``, ``supermicrox11spi-bmc``, ``tiogapass-bmc``, ``witherspoon-bmc``, ``yosemitev2-bmc``) ================================================================================================================================================================================================================================================================================================================================================================================================================================= The QEMU Aspeed machines model BMCs of various OpenPOWER systems and diff --git a/hw/arm/aspeed_ast27x0-fc.c b/hw/arm/aspeed_ast27x0-fc.c index 125a3ad..7087be4 100644 --- a/hw/arm/aspeed_ast27x0-fc.c +++ b/hw/arm/aspeed_ast27x0-fc.c @@ -48,7 +48,7 @@ struct Ast2700FCState { bool mmio_exec; }; -#define AST2700FC_BMC_RAM_SIZE (2 * GiB) +#define AST2700FC_BMC_RAM_SIZE (1 * GiB) #define AST2700FC_CM4_DRAM_SIZE (32 * MiB) #define AST2700FC_HW_STRAP1 0x000000C0 @@ -68,6 +68,7 @@ static void ast2700fc_ca35_init(MachineState *machine) memory_region_init(&s->ca35_memory, OBJECT(&s->ca35), "ca35-memory", UINT64_MAX); + memory_region_add_subregion(get_system_memory(), 0, &s->ca35_memory); if (!memory_region_init_ram(&s->ca35_dram, OBJECT(&s->ca35), "ca35-dram", AST2700FC_BMC_RAM_SIZE, &error_abort)) { @@ -86,6 +87,13 @@ static void ast2700fc_ca35_init(MachineState *machine) AST2700FC_BMC_RAM_SIZE, &error_abort)) { return; } + + for (int i = 0; i < sc->macs_num; i++) { + if (!qemu_configure_nic_device(DEVICE(&soc->ftgmac100[i]), + true, NULL)) { + break; + } + } if (!object_property_set_int(OBJECT(&s->ca35), "hw-strap1", AST2700FC_HW_STRAP1, &error_abort)) { return; diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index 1974a25..6aa3841 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -23,14 +23,14 @@ #include "qobject/qlist.h" #include "qemu/log.h" -#define AST2700_SOC_IO_SIZE 0x01000000 +#define AST2700_SOC_IO_SIZE 0x00FE0000 #define AST2700_SOC_IOMEM_SIZE 0x01000000 #define AST2700_SOC_DPMCU_SIZE 0x00040000 #define AST2700_SOC_LTPI_SIZE 0x01000000 static const hwaddr aspeed_soc_ast2700_memmap[] = { - [ASPEED_DEV_IOMEM] = 0x00000000, [ASPEED_DEV_VBOOTROM] = 0x00000000, + [ASPEED_DEV_IOMEM] = 0x00020000, [ASPEED_DEV_SRAM] = 0x10000000, [ASPEED_DEV_DPMCU] = 0x11000000, [ASPEED_DEV_IOMEM0] = 0x12000000, @@ -346,8 +346,9 @@ static void aspeed_ram_capacity_write(void *opaque, hwaddr addr, uint64_t data, * If writes the data to the address which is beyond the ram size, * it would write the data to the "address % ram_size". */ - result = address_space_write(&s->dram_as, addr % ram_size, - MEMTXATTRS_UNSPECIFIED, &data, 4); + address_space_stl_le(&s->dram_as, addr % ram_size, data, + MEMTXATTRS_UNSPECIFIED, &result); + if (result != MEMTX_OK) { qemu_log_mask(LOG_GUEST_ERROR, "%s: DRAM write failed, addr:0x%" HWADDR_PRIx @@ -360,9 +361,10 @@ static const MemoryRegionOps aspeed_ram_capacity_ops = { .read = aspeed_ram_capacity_read, .write = aspeed_ram_capacity_write, .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 4, .valid = { - .min_access_size = 1, - .max_access_size = 8, + .min_access_size = 4, + .max_access_size = 4, }, }; diff --git a/hw/arm/fby35.c b/hw/arm/fby35.c index e123fa6..c14fc2e 100644 --- a/hw/arm/fby35.c +++ b/hw/arm/fby35.c @@ -77,6 +77,7 @@ static void fby35_bmc_init(Fby35State *s) memory_region_init(&s->bmc_memory, OBJECT(&s->bmc), "bmc-memory", UINT64_MAX); + memory_region_add_subregion(get_system_memory(), 0, &s->bmc_memory); memory_region_init_ram(&s->bmc_dram, OBJECT(&s->bmc), "bmc-dram", FBY35_BMC_RAM_SIZE, &error_abort); diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c index 33fcbe7..5cd786d 100644 --- a/hw/intc/aspeed_intc.c +++ b/hw/intc/aspeed_intc.c @@ -737,6 +737,7 @@ static const MemoryRegionOps aspeed_intc_ops = { .read = aspeed_intc_read, .write = aspeed_intc_write, .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 4, .valid = { .min_access_size = 4, .max_access_size = 4, @@ -747,6 +748,7 @@ static const MemoryRegionOps aspeed_intcio_ops = { .read = aspeed_intcio_read, .write = aspeed_intcio_write, .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 4, .valid = { .min_access_size = 4, .max_access_size = 4, @@ -757,6 +759,7 @@ static const MemoryRegionOps aspeed_ssp_intc_ops = { .read = aspeed_intc_read, .write = aspeed_ssp_intc_write, .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 4, .valid = { .min_access_size = 4, .max_access_size = 4, @@ -767,6 +770,7 @@ static const MemoryRegionOps aspeed_ssp_intcio_ops = { .read = aspeed_intcio_read, .write = aspeed_ssp_intcio_write, .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 4, .valid = { .min_access_size = 4, .max_access_size = 4, @@ -777,6 +781,7 @@ static const MemoryRegionOps aspeed_tsp_intc_ops = { .read = aspeed_intc_read, .write = aspeed_tsp_intc_write, .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 4, .valid = { .min_access_size = 4, .max_access_size = 4, @@ -787,6 +792,7 @@ static const MemoryRegionOps aspeed_tsp_intcio_ops = { .read = aspeed_intcio_read, .write = aspeed_tsp_intcio_write, .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 4, .valid = { .min_access_size = 4, .max_access_size = 4, @@ -995,7 +1001,8 @@ static AspeedINTCIRQ aspeed_2700ssp_intcio_irqs[ASPEED_INTC_MAX_INPINS] = { {5, 5, 1, R_SSPINT165_EN, R_SSPINT165_STATUS}, }; -static void aspeed_2700ssp_intcio_class_init(ObjectClass *klass, const void *data) +static void aspeed_2700ssp_intcio_class_init(ObjectClass *klass, + const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); @@ -1063,7 +1070,8 @@ static AspeedINTCIRQ aspeed_2700tsp_intcio_irqs[ASPEED_INTC_MAX_INPINS] = { {5, 5, 1, R_TSPINT165_EN, R_TSPINT165_STATUS}, }; -static void aspeed_2700tsp_intcio_class_init(ObjectClass *klass, const void *data) +static void aspeed_2700tsp_intcio_class_init(ObjectClass *klass, + const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); diff --git a/hw/misc/aspeed_hace.c b/hw/misc/aspeed_hace.c index f4bff32..8924a30 100644 --- a/hw/misc/aspeed_hace.c +++ b/hw/misc/aspeed_hace.c @@ -10,14 +10,17 @@ */ #include "qemu/osdep.h" +#include "qemu/cutils.h" #include "qemu/log.h" #include "qemu/error-report.h" +#include "qemu/iov.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" +#include "trace.h" #define R_CRYPT_CMD (0x10 / 4) @@ -27,9 +30,12 @@ #define TAG_IRQ BIT(15) #define R_HASH_SRC (0x20 / 4) -#define R_HASH_DEST (0x24 / 4) +#define R_HASH_DIGEST (0x24 / 4) #define R_HASH_KEY_BUFF (0x28 / 4) #define R_HASH_SRC_LEN (0x2c / 4) +#define R_HASH_SRC_HI (0x90 / 4) +#define R_HASH_DIGEST_HI (0x94 / 4) +#define R_HASH_KEY_BUFF_HI (0x98 / 4) #define R_HASH_CMD (0x30 / 4) /* Hash algorithm selection */ @@ -84,6 +90,42 @@ static const struct { QCRYPTO_HASH_ALGO_SHA256 }, }; +static void hace_hexdump(const char *desc, const char *buf, size_t size) +{ + g_autoptr(GString) str = g_string_sized_new(64); + size_t len; + size_t i; + + for (i = 0; i < size; i += len) { + len = MIN(16, size - i); + g_string_truncate(str, 0); + qemu_hexdump_line(str, buf + i, len, 1, 4); + trace_aspeed_hace_hexdump(desc, i, str->str); + } +} + +static void hace_iov_hexdump(const char *desc, const struct iovec *iov, + const unsigned int iov_cnt) +{ + size_t size = 0; + char *buf; + int i; + + for (i = 0; i < iov_cnt; i++) { + size += iov[i].iov_len; + } + + buf = g_malloc(size); + + if (!buf) { + return; + } + + iov_to_buf(iov, iov_cnt, 0, buf, size); + hace_hexdump(desc, buf, size); + g_free(buf); +} + static int hash_algo_lookup(uint32_t reg) { int i; @@ -142,171 +184,269 @@ static bool has_padding(AspeedHACEState *s, struct iovec *iov, return false; } -static int reconstruct_iov(AspeedHACEState *s, struct iovec *iov, int id, - uint32_t *pad_offset) +static uint64_t hash_get_source_addr(AspeedHACEState *s) { - int i, iov_count; - if (*pad_offset != 0) { - s->iov_cache[s->iov_count].iov_base = iov[id].iov_base; - s->iov_cache[s->iov_count].iov_len = *pad_offset; - ++s->iov_count; - } - for (i = 0; i < s->iov_count; i++) { - iov[i].iov_base = s->iov_cache[i].iov_base; - iov[i].iov_len = s->iov_cache[i].iov_len; + AspeedHACEClass *ahc = ASPEED_HACE_GET_CLASS(s); + uint64_t src_addr = 0; + + src_addr = deposit64(src_addr, 0, 32, s->regs[R_HASH_SRC]); + if (ahc->has_dma64) { + src_addr = deposit64(src_addr, 32, 32, s->regs[R_HASH_SRC_HI]); } - iov_count = s->iov_count; - s->iov_count = 0; - s->total_req_len = 0; - return iov_count; + + return src_addr; } -static void do_hash_operation(AspeedHACEState *s, int algo, bool sg_mode, - bool acc_mode) +static int hash_prepare_direct_iov(AspeedHACEState *s, struct iovec *iov, + bool acc_mode, bool *acc_final_request) { - struct iovec iov[ASPEED_HACE_MAX_SG]; uint32_t total_msg_len; uint32_t pad_offset; - g_autofree uint8_t *digest_buf = NULL; - size_t digest_len = 0; - bool sg_acc_mode_final_request = false; - int i; + uint64_t src; void *haddr; - Error *local_err = NULL; + hwaddr plen; + int iov_idx; + + plen = s->regs[R_HASH_SRC_LEN]; + src = hash_get_source_addr(s); + trace_aspeed_hace_hash_addr("src", src); + haddr = address_space_map(&s->dram_as, src, &plen, false, + MEMTXATTRS_UNSPECIFIED); + if (haddr == NULL) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Unable to map address, addr=0x%" HWADDR_PRIx + " ,plen=0x%" HWADDR_PRIx "\n", + __func__, src, plen); + return -1; + } - if (acc_mode && s->hash_ctx == NULL) { - s->hash_ctx = qcrypto_hash_new(algo, &local_err); - if (s->hash_ctx == NULL) { - qemu_log_mask(LOG_GUEST_ERROR, "qcrypto hash failed : %s", - error_get_pretty(local_err)); - error_free(local_err); - return; + iov[0].iov_base = haddr; + iov_idx = 1; + + if (acc_mode) { + s->total_req_len += plen; + + if (has_padding(s, &iov[0], plen, &total_msg_len, + &pad_offset)) { + /* Padding being present indicates the final request */ + *acc_final_request = true; + iov[0].iov_len = pad_offset; + } else { + iov[0].iov_len = plen; } + } else { + iov[0].iov_len = plen; } - if (sg_mode) { - uint32_t len = 0; - - for (i = 0; !(len & SG_LIST_LEN_LAST); i++) { - uint32_t addr, src; - hwaddr plen; + return iov_idx; +} - 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; - } +static int hash_prepare_sg_iov(AspeedHACEState *s, struct iovec *iov, + bool acc_mode, bool *acc_final_request) +{ + uint32_t total_msg_len; + uint32_t pad_offset; + uint32_t len = 0; + uint32_t sg_addr; + uint64_t src; + int iov_idx; + hwaddr plen; + void *haddr; - src = s->regs[R_HASH_SRC] + (i * SG_LIST_ENTRY_SIZE); + src = hash_get_source_addr(s); + for (iov_idx = 0; !(len & SG_LIST_LEN_LAST); iov_idx++) { + if (iov_idx == ASPEED_HACE_MAX_SG) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Failed to set end of sg list marker\n", + __func__); + return -1; + } - len = address_space_ldl_le(&s->dram_as, src, + len = address_space_ldl_le(&s->dram_as, src, + MEMTXATTRS_UNSPECIFIED, NULL); + sg_addr = address_space_ldl_le(&s->dram_as, src + SG_LIST_LEN_SIZE, MEMTXATTRS_UNSPECIFIED, NULL); + sg_addr &= SG_LIST_ADDR_MASK; + trace_aspeed_hace_hash_sg(iov_idx, src, sg_addr, len); + /* + * To maintain compatibility with older SoCs such as the AST2600, + * the AST2700 HW automatically set bit 34 of the 64-bit sg_addr. + * As a result, the firmware only needs to provide a 32-bit sg_addr + * containing bits [31:0]. This is sufficient for the AST2700, as + * it uses a DRAM offset rather than a DRAM address. + */ + plen = len & SG_LIST_LEN_MASK; + haddr = address_space_map(&s->dram_as, sg_addr, &plen, false, + MEMTXATTRS_UNSPECIFIED); - addr = address_space_ldl_le(&s->dram_as, src + SG_LIST_LEN_SIZE, - MEMTXATTRS_UNSPECIFIED, NULL); - addr &= SG_LIST_ADDR_MASK; + if (haddr == NULL) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Unable to map address, sg_addr=0x%x, " + "plen=0x%" HWADDR_PRIx "\n", + __func__, sg_addr, plen); + return -1; + } - plen = len & SG_LIST_LEN_MASK; - haddr = address_space_map(&s->dram_as, addr, &plen, false, - MEMTXATTRS_UNSPECIFIED); - if (haddr == NULL) { - qemu_log_mask(LOG_GUEST_ERROR, - "%s: qcrypto failed\n", __func__); - return; - } - iov[i].iov_base = haddr; - if (acc_mode) { - s->total_req_len += plen; - - if (has_padding(s, &iov[i], plen, &total_msg_len, - &pad_offset)) { - /* Padding being present indicates the final request */ - sg_acc_mode_final_request = true; - iov[i].iov_len = pad_offset; - } else { - iov[i].iov_len = plen; - } + src += SG_LIST_ENTRY_SIZE; + + iov[iov_idx].iov_base = haddr; + if (acc_mode) { + s->total_req_len += plen; + + if (has_padding(s, &iov[iov_idx], plen, &total_msg_len, + &pad_offset)) { + /* Padding being present indicates the final request */ + *acc_final_request = true; + iov[iov_idx].iov_len = pad_offset; } else { - iov[i].iov_len = plen; + iov[iov_idx].iov_len = plen; } + } else { + iov[iov_idx].iov_len = plen; } - } else { - hwaddr len = s->regs[R_HASH_SRC_LEN]; + } - haddr = address_space_map(&s->dram_as, s->regs[R_HASH_SRC], - &len, false, MEMTXATTRS_UNSPECIFIED); - if (haddr == NULL) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: qcrypto failed\n", __func__); + return iov_idx; +} + +static uint64_t hash_get_digest_addr(AspeedHACEState *s) +{ + AspeedHACEClass *ahc = ASPEED_HACE_GET_CLASS(s); + uint64_t digest_addr = 0; + + digest_addr = deposit64(digest_addr, 0, 32, s->regs[R_HASH_DIGEST]); + if (ahc->has_dma64) { + digest_addr = deposit64(digest_addr, 32, 32, s->regs[R_HASH_DIGEST_HI]); + } + + return digest_addr; +} + +static void hash_write_digest_and_unmap_iov(AspeedHACEState *s, + struct iovec *iov, + int iov_idx, + uint8_t *digest_buf, + size_t digest_len) +{ + uint64_t digest_addr = 0; + + digest_addr = hash_get_digest_addr(s); + trace_aspeed_hace_hash_addr("digest", digest_addr); + if (address_space_write(&s->dram_as, digest_addr, + MEMTXATTRS_UNSPECIFIED, + digest_buf, digest_len)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Failed to write digest to 0x%" HWADDR_PRIx "\n", + __func__, digest_addr); + } + + if (trace_event_get_state_backends(TRACE_ASPEED_HACE_HEXDUMP)) { + hace_hexdump("digest", (char *)digest_buf, digest_len); + } + + for (; iov_idx > 0; iov_idx--) { + address_space_unmap(&s->dram_as, iov[iov_idx - 1].iov_base, + iov[iov_idx - 1].iov_len, false, + iov[iov_idx - 1].iov_len); + } +} + +static void hash_execute_non_acc_mode(AspeedHACEState *s, int algo, + struct iovec *iov, int iov_idx) +{ + g_autofree uint8_t *digest_buf = NULL; + Error *local_err = NULL; + size_t digest_len = 0; + + if (qcrypto_hash_bytesv(algo, iov, iov_idx, &digest_buf, + &digest_len, &local_err) < 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: qcrypto hash bytesv failed : %s", + __func__, error_get_pretty(local_err)); + error_free(local_err); + return; + } + + hash_write_digest_and_unmap_iov(s, iov, iov_idx, digest_buf, digest_len); +} + +static void hash_execute_acc_mode(AspeedHACEState *s, int algo, + struct iovec *iov, int iov_idx, + bool final_request) +{ + g_autofree uint8_t *digest_buf = NULL; + Error *local_err = NULL; + size_t digest_len = 0; + + trace_aspeed_hace_hash_execute_acc_mode(final_request); + + if (s->hash_ctx == NULL) { + s->hash_ctx = qcrypto_hash_new(algo, &local_err); + if (s->hash_ctx == NULL) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: qcrypto hash new failed : %s", + __func__, error_get_pretty(local_err)); + error_free(local_err); return; } - iov[0].iov_base = haddr; - iov[0].iov_len = len; - i = 1; - - if (s->iov_count) { - /* - * In aspeed sdk kernel driver, sg_mode is disabled in hash_final(). - * Thus if we received a request with sg_mode disabled, it is - * required to check whether cache is empty. If no, we should - * combine cached iov and the current iov. - */ - s->total_req_len += len; - if (has_padding(s, iov, len, &total_msg_len, &pad_offset)) { - i = reconstruct_iov(s, iov, 0, &pad_offset); - } - } } - if (acc_mode) { - if (qcrypto_hash_updatev(s->hash_ctx, iov, i, &local_err) < 0) { - qemu_log_mask(LOG_GUEST_ERROR, "qcrypto hash update failed : %s", - error_get_pretty(local_err)); + if (qcrypto_hash_updatev(s->hash_ctx, iov, iov_idx, &local_err) < 0) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: qcrypto hash updatev failed : %s", + __func__, error_get_pretty(local_err)); + error_free(local_err); + return; + } + + if (final_request) { + if (qcrypto_hash_finalize_bytes(s->hash_ctx, &digest_buf, + &digest_len, &local_err)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: qcrypto hash finalize bytes failed : %s", + __func__, error_get_pretty(local_err)); error_free(local_err); - return; + local_err = NULL; } - if (sg_acc_mode_final_request) { - if (qcrypto_hash_finalize_bytes(s->hash_ctx, &digest_buf, - &digest_len, &local_err)) { - qemu_log_mask(LOG_GUEST_ERROR, - "qcrypto hash finalize failed : %s", - error_get_pretty(local_err)); - error_free(local_err); - local_err = NULL; - } + qcrypto_hash_free(s->hash_ctx); - qcrypto_hash_free(s->hash_ctx); + s->hash_ctx = NULL; + s->total_req_len = 0; + } - s->hash_ctx = NULL; - s->iov_count = 0; - s->total_req_len = 0; - } - } else if (qcrypto_hash_bytesv(algo, iov, i, &digest_buf, - &digest_len, &local_err) < 0) { - qemu_log_mask(LOG_GUEST_ERROR, "qcrypto hash bytesv failed : %s", - error_get_pretty(local_err)); - error_free(local_err); - return; + hash_write_digest_and_unmap_iov(s, iov, iov_idx, digest_buf, digest_len); +} + +static void do_hash_operation(AspeedHACEState *s, int algo, bool sg_mode, + bool acc_mode) +{ + struct iovec iov[ASPEED_HACE_MAX_SG]; + bool acc_final_request = false; + int iov_idx = -1; + + /* Prepares the iov for hashing operations based on the selected mode */ + if (sg_mode) { + iov_idx = hash_prepare_sg_iov(s, iov, acc_mode, &acc_final_request); + } else { + iov_idx = hash_prepare_direct_iov(s, iov, acc_mode, + &acc_final_request); } - if (address_space_write(&s->dram_as, s->regs[R_HASH_DEST], - MEMTXATTRS_UNSPECIFIED, - digest_buf, digest_len)) { + if (iov_idx <= 0) { qemu_log_mask(LOG_GUEST_ERROR, - "aspeed_hace: address space write failed\n"); + "%s: Failed to prepare iov\n", __func__); + return; } - 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); + if (trace_event_get_state_backends(TRACE_ASPEED_HACE_HEXDUMP)) { + hace_iov_hexdump("plaintext", iov, iov_idx); } - /* - * Set status bits to indicate completion. Testing shows hardware sets - * these irrespective of HASH_IRQ_EN. - */ - s->regs[R_STATUS] |= HASH_IRQ; + /* Executes the hash operation */ + if (acc_mode) { + hash_execute_acc_mode(s, algo, iov, iov_idx, acc_final_request); + } else { + hash_execute_non_acc_mode(s, algo, iov, iov_idx); + } } static uint64_t aspeed_hace_read(void *opaque, hwaddr addr, unsigned int size) @@ -315,12 +455,7 @@ static uint64_t aspeed_hace_read(void *opaque, hwaddr addr, unsigned int size) 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; - } + trace_aspeed_hace_read(addr << 2, s->regs[addr]); return s->regs[addr]; } @@ -333,12 +468,7 @@ static void aspeed_hace_write(void *opaque, hwaddr addr, uint64_t data, 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; - } + trace_aspeed_hace_write(addr << 2, data); switch (addr) { case R_STATUS: @@ -362,7 +492,7 @@ static void aspeed_hace_write(void *opaque, hwaddr addr, uint64_t data, case R_HASH_SRC: data &= ahc->src_mask; break; - case R_HASH_DEST: + case R_HASH_DIGEST: data &= ahc->dest_mask; break; case R_HASH_KEY_BUFF: @@ -390,10 +520,16 @@ static void aspeed_hace_write(void *opaque, hwaddr addr, uint64_t data, qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid hash algorithm selection 0x%"PRIx64"\n", __func__, data & ahc->hash_mask); - break; + } else { + do_hash_operation(s, algo, data & HASH_SG_EN, + ((data & HASH_HMAC_MASK) == HASH_DIGEST_ACCUM)); } - do_hash_operation(s, algo, data & HASH_SG_EN, - ((data & HASH_HMAC_MASK) == HASH_DIGEST_ACCUM)); + + /* + * Set status bits to indicate completion. Testing shows hardware sets + * these irrespective of HASH_IRQ_EN. + */ + s->regs[R_STATUS] |= HASH_IRQ; if (data & HASH_IRQ_EN) { qemu_irq_raise(s->irq); @@ -410,6 +546,15 @@ static void aspeed_hace_write(void *opaque, hwaddr addr, uint64_t data, } } break; + case R_HASH_SRC_HI: + data &= ahc->src_hi_mask; + break; + case R_HASH_DIGEST_HI: + data &= ahc->dest_hi_mask; + break; + case R_HASH_KEY_BUFF_HI: + data &= ahc->key_hi_mask; + break; default: break; } @@ -430,14 +575,14 @@ static const MemoryRegionOps aspeed_hace_ops = { static void aspeed_hace_reset(DeviceState *dev) { struct AspeedHACEState *s = ASPEED_HACE(dev); + AspeedHACEClass *ahc = ASPEED_HACE_GET_CLASS(s); if (s->hash_ctx != NULL) { qcrypto_hash_free(s->hash_ctx); s->hash_ctx = NULL; } - memset(s->regs, 0, sizeof(s->regs)); - s->iov_count = 0; + memset(s->regs, 0, ahc->nr_regs << 2); s->total_req_len = 0; } @@ -445,11 +590,13 @@ static void aspeed_hace_realize(DeviceState *dev, Error **errp) { AspeedHACEState *s = ASPEED_HACE(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + AspeedHACEClass *ahc = ASPEED_HACE_GET_CLASS(s); sysbus_init_irq(sbd, &s->irq); + s->regs = g_new(uint32_t, ahc->nr_regs); memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_hace_ops, s, - TYPE_ASPEED_HACE, 0x1000); + TYPE_ASPEED_HACE, ahc->nr_regs << 2); if (!s->dram_mr) { error_setg(errp, TYPE_ASPEED_HACE ": 'dram' link not set"); @@ -469,21 +616,28 @@ static const Property aspeed_hace_properties[] = { static const VMStateDescription vmstate_aspeed_hace = { .name = TYPE_ASPEED_HACE, - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .fields = (const VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, AspeedHACEState, ASPEED_HACE_NR_REGS), VMSTATE_UINT32(total_req_len, AspeedHACEState), - VMSTATE_UINT32(iov_count, AspeedHACEState), VMSTATE_END_OF_LIST(), } }; +static void aspeed_hace_unrealize(DeviceState *dev) +{ + AspeedHACEState *s = ASPEED_HACE(dev); + + g_free(s->regs); + s->regs = NULL; +} + static void aspeed_hace_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = aspeed_hace_realize; + dc->unrealize = aspeed_hace_unrealize; device_class_set_legacy_reset(dc, aspeed_hace_reset); device_class_set_props(dc, aspeed_hace_properties); dc->vmsd = &vmstate_aspeed_hace; @@ -504,6 +658,7 @@ static void aspeed_ast2400_hace_class_init(ObjectClass *klass, const void *data) dc->desc = "AST2400 Hash and Crypto Engine"; + ahc->nr_regs = 0x64 >> 2; ahc->src_mask = 0x0FFFFFFF; ahc->dest_mask = 0x0FFFFFF8; ahc->key_mask = 0x0FFFFFC0; @@ -523,6 +678,7 @@ static void aspeed_ast2500_hace_class_init(ObjectClass *klass, const void *data) dc->desc = "AST2500 Hash and Crypto Engine"; + ahc->nr_regs = 0x64 >> 2; ahc->src_mask = 0x3fffffff; ahc->dest_mask = 0x3ffffff8; ahc->key_mask = 0x3FFFFFC0; @@ -542,6 +698,7 @@ static void aspeed_ast2600_hace_class_init(ObjectClass *klass, const void *data) dc->desc = "AST2600 Hash and Crypto Engine"; + ahc->nr_regs = 0x64 >> 2; ahc->src_mask = 0x7FFFFFFF; ahc->dest_mask = 0x7FFFFFF8; ahc->key_mask = 0x7FFFFFF8; @@ -561,6 +718,7 @@ static void aspeed_ast1030_hace_class_init(ObjectClass *klass, const void *data) dc->desc = "AST1030 Hash and Crypto Engine"; + ahc->nr_regs = 0x64 >> 2; ahc->src_mask = 0x7FFFFFFF; ahc->dest_mask = 0x7FFFFFF8; ahc->key_mask = 0x7FFFFFF8; @@ -580,17 +738,36 @@ static void aspeed_ast2700_hace_class_init(ObjectClass *klass, const void *data) dc->desc = "AST2700 Hash and Crypto Engine"; + ahc->nr_regs = 0x9C >> 2; ahc->src_mask = 0x7FFFFFFF; ahc->dest_mask = 0x7FFFFFF8; ahc->key_mask = 0x7FFFFFF8; ahc->hash_mask = 0x00147FFF; /* + * The AST2700 supports a maximum DRAM size of 8 GB, with a DRAM + * addressable range from 0x0_0000_0000 to 0x1_FFFF_FFFF. Since this range + * fits within 34 bits, only bits [33:0] are needed to store the DRAM + * offset. To optimize address storage, the high physical address bits + * [1:0] of the source, digest and key buffer addresses are stored as + * dram_offset bits [33:32]. + * + * This approach eliminates the need to reduce the high part of the DRAM + * physical address for DMA operations. Previously, this was calculated as + * (high physical address bits [7:0] - 4), since the DRAM start address is + * 0x4_00000000, making the high part address [7:0] - 4. + */ + ahc->src_hi_mask = 0x00000003; + ahc->dest_hi_mask = 0x00000003; + ahc->key_hi_mask = 0x00000003; + + /* * Currently, it does not support the CRYPT command. Instead, it only * sends an interrupt to notify the firmware that the crypt command * has completed. It is a temporary workaround. */ ahc->raise_crypt_interrupt_workaround = true; + ahc->has_dma64 = true; } static const TypeInfo aspeed_ast2700_hace_info = { diff --git a/hw/misc/trace-events b/hw/misc/trace-events index 4383808..e3f64c0 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -302,6 +302,14 @@ aspeed_peci_read(uint64_t offset, uint64_t data) "offset 0x%" PRIx64 " data 0x%" aspeed_peci_write(uint64_t offset, uint64_t data) "offset 0x%" PRIx64 " data 0x%" PRIx64 aspeed_peci_raise_interrupt(uint32_t ctrl, uint32_t status) "ctrl 0x%" PRIx32 " status 0x%" PRIx32 +# aspeed_hace.c +aspeed_hace_read(uint64_t offset, uint64_t data) "offset 0x%" PRIx64 " data 0x%" PRIx64 +aspeed_hace_write(uint64_t offset, uint64_t data) "offset 0x%" PRIx64 " data 0x%" PRIx64 +aspeed_hace_hash_sg(int index, uint64_t list_addr, uint64_t buf_addr, uint32_t len) "%d: list_addr 0x%" PRIx64 " buf_addr 0x%" PRIx64 " len 0x%" PRIx32 +aspeed_hace_hash_addr(const char *s, uint64_t addr) "%s: 0x%" PRIx64 +aspeed_hace_hash_execute_acc_mode(bool final_request) "final request: %d" +aspeed_hace_hexdump(const char *desc, uint32_t offset, char *s) "%s: 0x%08x: %s" + # bcm2835_property.c bcm2835_mbox_property(uint32_t tag, uint32_t bufsize, size_t resplen) "mbox property tag:0x%08x in_sz:%u out_sz:%zu" diff --git a/include/hw/misc/aspeed_hace.h b/include/hw/misc/aspeed_hace.h index 5d4aa19..d5d07c6 100644 --- a/include/hw/misc/aspeed_hace.h +++ b/include/hw/misc/aspeed_hace.h @@ -22,7 +22,6 @@ OBJECT_DECLARE_TYPE(AspeedHACEState, AspeedHACEClass, ASPEED_HACE) -#define ASPEED_HACE_NR_REGS (0x64 >> 2) #define ASPEED_HACE_MAX_SG 256 /* max number of entries */ struct AspeedHACEState { @@ -31,10 +30,8 @@ struct AspeedHACEState { MemoryRegion iomem; qemu_irq irq; - struct iovec iov_cache[ASPEED_HACE_MAX_SG]; - uint32_t regs[ASPEED_HACE_NR_REGS]; + uint32_t *regs; uint32_t total_req_len; - uint32_t iov_count; MemoryRegion *dram_mr; AddressSpace dram_as; @@ -46,11 +43,17 @@ struct AspeedHACEState { struct AspeedHACEClass { SysBusDeviceClass parent_class; + const MemoryRegionOps *reg_ops; uint32_t src_mask; uint32_t dest_mask; uint32_t key_mask; uint32_t hash_mask; + uint64_t nr_regs; bool raise_crypt_interrupt_workaround; + uint32_t src_hi_mask; + uint32_t dest_hi_mask; + uint32_t key_hi_mask; + bool has_dma64; }; #endif /* ASPEED_HACE_H */ diff --git a/tests/qtest/aspeed-hace-utils.c b/tests/qtest/aspeed-hace-utils.c new file mode 100644 index 0000000..0f7f911 --- /dev/null +++ b/tests/qtest/aspeed-hace-utils.c @@ -0,0 +1,646 @@ +/* + * 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 "libqtest.h" +#include "qemu/bitops.h" +#include "aspeed-hace-utils.h" + +/* + * 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 sha384sum sha256sum md5sum; do $hash /tmp/test; done + * + */ +static const uint8_t test_vector[3] = {0x61, 0x62, 0x63}; + +static const uint8_t test_result_sha512[64] = { + 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_sha384[48] = { + 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, 0xb5, 0xa0, 0x3d, 0x69, + 0x9a, 0xc6, 0x50, 0x07, 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, + 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed, 0x80, 0x86, 0x07, 0x2b, + 0xa1, 0xe7, 0xcc, 0x23, 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7}; + +static const uint8_t test_result_sha256[32] = { + 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[16] = { + 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 sha384sum sha256sum; do $hash /tmp/test; done + * + */ +static const uint8_t test_vector_sg1[6] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66}; +static const uint8_t test_vector_sg2[3] = {0x67, 0x68, 0x69}; +static const uint8_t test_vector_sg3[3] = {0x6a, 0x6b, 0x6c}; + +static const uint8_t test_result_sg_sha512[64] = { + 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_sha384[48] = { + 0x10, 0x3c, 0xa9, 0x6c, 0x06, 0xa1, 0xce, 0x79, 0x8f, 0x08, 0xf8, 0xef, + 0xf0, 0xdf, 0xb0, 0xcc, 0xdb, 0x56, 0x7d, 0x48, 0xb2, 0x85, 0xb2, 0x3d, + 0x0c, 0xd7, 0x73, 0x45, 0x46, 0x67, 0xa3, 0xc2, 0xfa, 0x5f, 0x1b, 0x58, + 0xd9, 0xcd, 0xf2, 0x32, 0x9b, 0xd9, 0x97, 0x97, 0x30, 0xbf, 0xaa, 0xff}; + +static const uint8_t test_result_sg_sha256[32] = { + 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}; + +/* + * The accumulative mode requires firmware to provide internal initial state + * and message padding (including length L at the end of padding). + * + * This test vector is a ascii text "abc" with padding message. + * + * Expected results were generated using command line utitiles: + * + * echo -n -e 'abc' | dd of=/tmp/test + * for hash in sha512sum sha384sum sha256sum; do $hash /tmp/test; done + */ +static const uint8_t test_vector_accum_512[128] = { + 0x61, 0x62, 0x63, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18}; + +static const uint8_t test_vector_accum_384[128] = { + 0x61, 0x62, 0x63, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18}; + +static const uint8_t test_vector_accum_256[64] = { + 0x61, 0x62, 0x63, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18}; + +static const uint8_t test_result_accum_sha512[64] = { + 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_accum_sha384[48] = { + 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, 0xb5, 0xa0, 0x3d, 0x69, + 0x9a, 0xc6, 0x50, 0x07, 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, + 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed, 0x80, 0x86, 0x07, 0x2b, + 0xa1, 0xe7, 0xcc, 0x23, 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7}; + +static const uint8_t test_result_accum_sha256[32] = { + 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 void write_regs(QTestState *s, uint32_t base, uint64_t src, + uint32_t length, uint64_t out, uint32_t method) +{ + qtest_writel(s, base + HACE_HASH_SRC, extract64(src, 0, 32)); + qtest_writel(s, base + HACE_HASH_SRC_HI, extract64(src, 32, 32)); + qtest_writel(s, base + HACE_HASH_DIGEST, extract64(out, 0, 32)); + qtest_writel(s, base + HACE_HASH_DIGEST_HI, extract64(out, 32, 32)); + qtest_writel(s, base + HACE_HASH_DATA_LEN, length); + qtest_writel(s, base + HACE_HASH_CMD, HACE_SHA_BE_EN | method); +} + +void aspeed_test_md5(const char *machine, const uint32_t base, + const uint64_t src_addr) + +{ + QTestState *s = qtest_init(machine); + + uint64_t digest_addr = src_addr + 0x010000; + 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); +} + +void aspeed_test_sha256(const char *machine, const uint32_t base, + const uint64_t src_addr) +{ + QTestState *s = qtest_init(machine); + + const uint64_t digest_addr = src_addr + 0x10000; + 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); +} + +void aspeed_test_sha384(const char *machine, const uint32_t base, + const uint64_t src_addr) +{ + QTestState *s = qtest_init(machine); + + const uint64_t digest_addr = src_addr + 0x10000; + uint8_t digest[48] = {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_SHA384); + + /* 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_sha384, sizeof(digest)); + + qtest_quit(s); +} + +void aspeed_test_sha512(const char *machine, const uint32_t base, + const uint64_t src_addr) +{ + QTestState *s = qtest_init(machine); + + const uint64_t digest_addr = src_addr + 0x10000; + 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); +} + +void aspeed_test_sha256_sg(const char *machine, const uint32_t base, + const uint64_t src_addr) +{ + QTestState *s = qtest_init(machine); + + const uint64_t src_addr_1 = src_addr + 0x10000; + const uint64_t src_addr_2 = src_addr + 0x20000; + const uint64_t src_addr_3 = src_addr + 0x30000; + const uint64_t digest_addr = src_addr + 0x40000; + 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); +} + +void aspeed_test_sha384_sg(const char *machine, const uint32_t base, + const uint64_t src_addr) +{ + QTestState *s = qtest_init(machine); + + const uint64_t src_addr_1 = src_addr + 0x10000; + const uint64_t src_addr_2 = src_addr + 0x20000; + const uint64_t src_addr_3 = src_addr + 0x30000; + const uint64_t digest_addr = src_addr + 0x40000; + uint8_t digest[48] = {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_SHA384 | 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_sha384, sizeof(digest)); + + qtest_quit(s); +} + +void aspeed_test_sha512_sg(const char *machine, const uint32_t base, + const uint64_t src_addr) +{ + QTestState *s = qtest_init(machine); + + const uint64_t src_addr_1 = src_addr + 0x10000; + const uint64_t src_addr_2 = src_addr + 0x20000; + const uint64_t src_addr_3 = src_addr + 0x30000; + const uint64_t digest_addr = src_addr + 0x40000; + 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); +} + +void aspeed_test_sha256_accum(const char *machine, const uint32_t base, + const uint64_t src_addr) +{ + QTestState *s = qtest_init(machine); + + const uint64_t buffer_addr = src_addr + 0x10000; + const uint64_t digest_addr = src_addr + 0x40000; + uint8_t digest[32] = {0}; + struct AspeedSgList array[] = { + { cpu_to_le32(sizeof(test_vector_accum_256) | SG_LIST_LEN_LAST), + cpu_to_le32(buffer_addr) }, + }; + + /* 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, buffer_addr, test_vector_accum_256, + sizeof(test_vector_accum_256)); + qtest_memwrite(s, src_addr, array, sizeof(array)); + + write_regs(s, base, src_addr, sizeof(test_vector_accum_256), + digest_addr, HACE_ALGO_SHA256 | HACE_SG_EN | HACE_ACCUM_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_accum_sha256, sizeof(digest)); + + qtest_quit(s); +} + +void aspeed_test_sha384_accum(const char *machine, const uint32_t base, + const uint64_t src_addr) +{ + QTestState *s = qtest_init(machine); + + const uint64_t buffer_addr = src_addr + 0x10000; + const uint64_t digest_addr = src_addr + 0x40000; + uint8_t digest[48] = {0}; + struct AspeedSgList array[] = { + { cpu_to_le32(sizeof(test_vector_accum_384) | SG_LIST_LEN_LAST), + cpu_to_le32(buffer_addr) }, + }; + + /* 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, buffer_addr, test_vector_accum_384, + sizeof(test_vector_accum_384)); + qtest_memwrite(s, src_addr, array, sizeof(array)); + + write_regs(s, base, src_addr, sizeof(test_vector_accum_384), + digest_addr, HACE_ALGO_SHA384 | HACE_SG_EN | HACE_ACCUM_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_accum_sha384, sizeof(digest)); + + qtest_quit(s); +} + +void aspeed_test_sha512_accum(const char *machine, const uint32_t base, + const uint64_t src_addr) +{ + QTestState *s = qtest_init(machine); + + const uint64_t buffer_addr = src_addr + 0x10000; + const uint64_t digest_addr = src_addr + 0x40000; + uint8_t digest[64] = {0}; + struct AspeedSgList array[] = { + { cpu_to_le32(sizeof(test_vector_accum_512) | SG_LIST_LEN_LAST), + cpu_to_le32(buffer_addr) }, + }; + + /* 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, buffer_addr, test_vector_accum_512, + sizeof(test_vector_accum_512)); + qtest_memwrite(s, src_addr, array, sizeof(array)); + + write_regs(s, base, src_addr, sizeof(test_vector_accum_512), + digest_addr, HACE_ALGO_SHA512 | HACE_SG_EN | HACE_ACCUM_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_accum_sha512, sizeof(digest)); + + qtest_quit(s); +} + +void aspeed_test_addresses(const char *machine, const uint32_t base, + const struct AspeedMasks *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_SRC_HI), ==, 0); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DIGEST), ==, 0); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DIGEST_HI), ==, 0); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_KEY_BUFF), ==, 0); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_KEY_BUFF_HI), ==, 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_SRC_HI, 0xffffffff); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_SRC_HI), + ==, expected->src_hi); + + 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_DIGEST_HI, 0xffffffff); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DIGEST_HI), ==, + expected->dest_hi); + + qtest_writel(s, base + HACE_HASH_KEY_BUFF, 0xffffffff); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_KEY_BUFF), ==, + expected->key); + + qtest_writel(s, base + HACE_HASH_KEY_BUFF_HI, 0xffffffff); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_KEY_BUFF_HI), ==, + expected->key_hi); + + 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_SRC_HI, 0); + qtest_writel(s, base + HACE_HASH_DIGEST, 0); + qtest_writel(s, base + HACE_HASH_DIGEST_HI, 0); + qtest_writel(s, base + HACE_HASH_KEY_BUFF, 0); + qtest_writel(s, base + HACE_HASH_KEY_BUFF_HI, 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_SRC_HI), ==, 0); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DIGEST), ==, 0); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DIGEST_HI), ==, 0); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_KEY_BUFF), ==, 0); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_KEY_BUFF_HI), ==, 0); + g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DATA_LEN), ==, 0); + + qtest_quit(s); +} + diff --git a/tests/qtest/aspeed-hace-utils.h b/tests/qtest/aspeed-hace-utils.h new file mode 100644 index 0000000..c8b2ec4 --- /dev/null +++ b/tests/qtest/aspeed-hace-utils.h @@ -0,0 +1,84 @@ +/* + * QTest testcase for the ASPEED Hash and Crypto Engine + * + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2021 IBM Corp. + */ + +#ifndef TESTS_ASPEED_HACE_UTILS_H +#define TESTS_ASPEED_HACE_UTILS_H + +#include "qemu/osdep.h" +#include "libqtest.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_ACCUM_EN BIT(8) + +#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 +#define HACE_HASH_SRC_HI 0x90 +#define HACE_HASH_DIGEST_HI 0x94 +#define HACE_HASH_KEY_BUFF_HI 0x98 + +/* Scatter-Gather Hash */ +#define SG_LIST_LEN_LAST BIT(31) +struct AspeedSgList { + uint32_t len; + uint32_t addr; +} __attribute__ ((__packed__)); + +struct AspeedMasks { + uint32_t src; + uint32_t dest; + uint32_t key; + uint32_t len; + uint32_t src_hi; + uint32_t dest_hi; + uint32_t key_hi; +}; + +void aspeed_test_md5(const char *machine, const uint32_t base, + const uint64_t src_addr); +void aspeed_test_sha256(const char *machine, const uint32_t base, + const uint64_t src_addr); +void aspeed_test_sha384(const char *machine, const uint32_t base, + const uint64_t src_addr); +void aspeed_test_sha512(const char *machine, const uint32_t base, + const uint64_t src_addr); +void aspeed_test_sha256_sg(const char *machine, const uint32_t base, + const uint64_t src_addr); +void aspeed_test_sha384_sg(const char *machine, const uint32_t base, + const uint64_t src_addr); +void aspeed_test_sha512_sg(const char *machine, const uint32_t base, + const uint64_t src_addr); +void aspeed_test_sha256_accum(const char *machine, const uint32_t base, + const uint64_t src_addr); +void aspeed_test_sha384_accum(const char *machine, const uint32_t base, + const uint64_t src_addr); +void aspeed_test_sha512_accum(const char *machine, const uint32_t base, + const uint64_t src_addr); +void aspeed_test_addresses(const char *machine, const uint32_t base, + const struct AspeedMasks *expected); + +#endif /* TESTS_ASPEED_HACE_UTILS_H */ + diff --git a/tests/qtest/aspeed_hace-test.c b/tests/qtest/aspeed_hace-test.c index ce86a44..3877702 100644 --- a/tests/qtest/aspeed_hace-test.c +++ b/tests/qtest/aspeed_hace-test.c @@ -6,599 +6,222 @@ */ #include "qemu/osdep.h" - #include "libqtest.h" #include "qemu/bitops.h" +#include "aspeed-hace-utils.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_ACCUM_EN BIT(8) - -#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 struct AspeedMasks ast1030_masks = { + .src = 0x7fffffff, + .dest = 0x7ffffff8, + .key = 0x7ffffff8, + .len = 0x0fffffff, +}; -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 struct AspeedMasks ast2600_masks = { + .src = 0x7fffffff, + .dest = 0x7ffffff8, + .key = 0x7ffffff8, + .len = 0x0fffffff, +}; -static const uint8_t test_result_md5[] = { - 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d, - 0x28, 0xe1, 0x7f, 0x72}; +static const struct AspeedMasks ast2500_masks = { + .src = 0x3fffffff, + .dest = 0x3ffffff8, + .key = 0x3fffffc0, + .len = 0x0fffffff, +}; -/* - * 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 const struct AspeedMasks ast2400_masks = { + .src = 0x0fffffff, + .dest = 0x0ffffff8, + .key = 0x0fffffc0, + .len = 0x0fffffff, +}; -/* - * The accumulative mode requires firmware to provide internal initial state - * and message padding (including length L at the end of padding). - * - * This test vector is a ascii text "abc" with padding message. - * - * Expected results were generated using command line utitiles: - * - * echo -n -e 'abc' | dd of=/tmp/test - * for hash in sha512sum sha256sum; do $hash /tmp/test; done - */ -static const uint8_t test_vector_accum_512[] = { - 0x61, 0x62, 0x63, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18}; - -static const uint8_t test_vector_accum_256[] = { - 0x61, 0x62, 0x63, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18}; - -static const uint8_t test_result_accum_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_accum_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 void write_regs(QTestState *s, uint32_t base, uint32_t src, - uint32_t length, uint32_t out, uint32_t method) +/* ast1030 */ +static void test_md5_ast1030(void) { - 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); + aspeed_test_md5("-machine ast1030-evb", 0x7e6d0000, 0x00000000); } -static void test_md5(const char *machine, const uint32_t base, - const uint32_t src_addr) - +static void test_sha256_ast1030(void) { - 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); + aspeed_test_sha256("-machine ast1030-evb", 0x7e6d0000, 0x00000000); } -static void test_sha256(const char *machine, const uint32_t base, - const uint32_t src_addr) +static void test_sha256_sg_ast1030(void) { - 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); + aspeed_test_sha256_sg("-machine ast1030-evb", 0x7e6d0000, 0x00000000); } -static void test_sha512(const char *machine, const uint32_t base, - const uint32_t src_addr) +static void test_sha384_ast1030(void) { - 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); + aspeed_test_sha384("-machine ast1030-evb", 0x7e6d0000, 0x00000000); } -static void test_sha256_sg(const char *machine, const uint32_t base, - const uint32_t src_addr) +static void test_sha384_sg_ast1030(void) { - 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); + aspeed_test_sha384_sg("-machine ast1030-evb", 0x7e6d0000, 0x00000000); } -static void test_sha512_sg(const char *machine, const uint32_t base, - const uint32_t src_addr) +static void test_sha512_ast1030(void) { - 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); + aspeed_test_sha512("-machine ast1030-evb", 0x7e6d0000, 0x00000000); } -static void test_sha256_accum(const char *machine, const uint32_t base, - const uint32_t src_addr) +static void test_sha512_sg_ast1030(void) { - QTestState *s = qtest_init(machine); - - const uint32_t buffer_addr = src_addr + 0x1000000; - const uint32_t digest_addr = src_addr + 0x4000000; - uint8_t digest[32] = {0}; - struct AspeedSgList array[] = { - { cpu_to_le32(sizeof(test_vector_accum_256) | SG_LIST_LEN_LAST), - cpu_to_le32(buffer_addr) }, - }; - - /* 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, buffer_addr, test_vector_accum_256, - sizeof(test_vector_accum_256)); - qtest_memwrite(s, src_addr, array, sizeof(array)); - - write_regs(s, base, src_addr, sizeof(test_vector_accum_256), - digest_addr, HACE_ALGO_SHA256 | HACE_SG_EN | HACE_ACCUM_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_accum_sha256, sizeof(digest)); - - qtest_quit(s); + aspeed_test_sha512_sg("-machine ast1030-evb", 0x7e6d0000, 0x00000000); } -static void test_sha512_accum(const char *machine, const uint32_t base, - const uint32_t src_addr) +static void test_sha256_accum_ast1030(void) { - QTestState *s = qtest_init(machine); - - const uint32_t buffer_addr = src_addr + 0x1000000; - const uint32_t digest_addr = src_addr + 0x4000000; - uint8_t digest[64] = {0}; - struct AspeedSgList array[] = { - { cpu_to_le32(sizeof(test_vector_accum_512) | SG_LIST_LEN_LAST), - cpu_to_le32(buffer_addr) }, - }; - - /* 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, buffer_addr, test_vector_accum_512, - sizeof(test_vector_accum_512)); - qtest_memwrite(s, src_addr, array, sizeof(array)); - - write_regs(s, base, src_addr, sizeof(test_vector_accum_512), - digest_addr, HACE_ALGO_SHA512 | HACE_SG_EN | HACE_ACCUM_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_accum_sha512, sizeof(digest)); - - qtest_quit(s); + aspeed_test_sha256_accum("-machine ast1030-evb", 0x7e6d0000, 0x00000000); } -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) +static void test_sha384_accum_ast1030(void) { - 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); + aspeed_test_sha384_accum("-machine ast1030-evb", 0x7e6d0000, 0x00000000); +} - /* 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); +static void test_sha512_accum_ast1030(void) +{ + aspeed_test_sha512_accum("-machine ast1030-evb", 0x7e6d0000, 0x00000000); +} - qtest_quit(s); +static void test_addresses_ast1030(void) +{ + aspeed_test_addresses("-machine ast1030-evb", 0x7e6d0000, &ast1030_masks); } /* ast2600 */ static void test_md5_ast2600(void) { - test_md5("-machine ast2600-evb", 0x1e6d0000, 0x80000000); + aspeed_test_md5("-machine ast2600-evb", 0x1e6d0000, 0x80000000); } static void test_sha256_ast2600(void) { - test_sha256("-machine ast2600-evb", 0x1e6d0000, 0x80000000); + aspeed_test_sha256("-machine ast2600-evb", 0x1e6d0000, 0x80000000); } static void test_sha256_sg_ast2600(void) { - test_sha256_sg("-machine ast2600-evb", 0x1e6d0000, 0x80000000); + aspeed_test_sha256_sg("-machine ast2600-evb", 0x1e6d0000, 0x80000000); +} + +static void test_sha384_ast2600(void) +{ + aspeed_test_sha384("-machine ast2600-evb", 0x1e6d0000, 0x80000000); +} + +static void test_sha384_sg_ast2600(void) +{ + aspeed_test_sha384_sg("-machine ast2600-evb", 0x1e6d0000, 0x80000000); } static void test_sha512_ast2600(void) { - test_sha512("-machine ast2600-evb", 0x1e6d0000, 0x80000000); + aspeed_test_sha512("-machine ast2600-evb", 0x1e6d0000, 0x80000000); } static void test_sha512_sg_ast2600(void) { - test_sha512_sg("-machine ast2600-evb", 0x1e6d0000, 0x80000000); + aspeed_test_sha512_sg("-machine ast2600-evb", 0x1e6d0000, 0x80000000); } static void test_sha256_accum_ast2600(void) { - test_sha256_accum("-machine ast2600-evb", 0x1e6d0000, 0x80000000); + aspeed_test_sha256_accum("-machine ast2600-evb", 0x1e6d0000, 0x80000000); +} + +static void test_sha384_accum_ast2600(void) +{ + aspeed_test_sha384_accum("-machine ast2600-evb", 0x1e6d0000, 0x80000000); } static void test_sha512_accum_ast2600(void) { - test_sha512_accum("-machine ast2600-evb", 0x1e6d0000, 0x80000000); + aspeed_test_sha512_accum("-machine ast2600-evb", 0x1e6d0000, 0x80000000); } static void test_addresses_ast2600(void) { - test_addresses("-machine ast2600-evb", 0x1e6d0000, &ast2600_masks); + aspeed_test_addresses("-machine ast2600-evb", 0x1e6d0000, &ast2600_masks); } /* ast2500 */ static void test_md5_ast2500(void) { - test_md5("-machine ast2500-evb", 0x1e6e3000, 0x80000000); + aspeed_test_md5("-machine ast2500-evb", 0x1e6e3000, 0x80000000); } static void test_sha256_ast2500(void) { - test_sha256("-machine ast2500-evb", 0x1e6e3000, 0x80000000); + aspeed_test_sha256("-machine ast2500-evb", 0x1e6e3000, 0x80000000); } static void test_sha512_ast2500(void) { - test_sha512("-machine ast2500-evb", 0x1e6e3000, 0x80000000); + aspeed_test_sha512("-machine ast2500-evb", 0x1e6e3000, 0x80000000); } static void test_addresses_ast2500(void) { - test_addresses("-machine ast2500-evb", 0x1e6e3000, &ast2500_masks); + aspeed_test_addresses("-machine ast2500-evb", 0x1e6e3000, &ast2500_masks); } /* ast2400 */ static void test_md5_ast2400(void) { - test_md5("-machine palmetto-bmc", 0x1e6e3000, 0x40000000); + aspeed_test_md5("-machine palmetto-bmc", 0x1e6e3000, 0x40000000); } static void test_sha256_ast2400(void) { - test_sha256("-machine palmetto-bmc", 0x1e6e3000, 0x40000000); + aspeed_test_sha256("-machine palmetto-bmc", 0x1e6e3000, 0x40000000); } static void test_sha512_ast2400(void) { - test_sha512("-machine palmetto-bmc", 0x1e6e3000, 0x40000000); + aspeed_test_sha512("-machine palmetto-bmc", 0x1e6e3000, 0x40000000); } static void test_addresses_ast2400(void) { - test_addresses("-machine palmetto-bmc", 0x1e6e3000, &ast2400_masks); + aspeed_test_addresses("-machine palmetto-bmc", 0x1e6e3000, &ast2400_masks); } int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); + qtest_add_func("ast1030/hace/addresses", test_addresses_ast1030); + qtest_add_func("ast1030/hace/sha512", test_sha512_ast1030); + qtest_add_func("ast1030/hace/sha384", test_sha384_ast1030); + qtest_add_func("ast1030/hace/sha256", test_sha256_ast1030); + qtest_add_func("ast1030/hace/md5", test_md5_ast1030); + + qtest_add_func("ast1030/hace/sha512_sg", test_sha512_sg_ast1030); + qtest_add_func("ast1030/hace/sha384_sg", test_sha384_sg_ast1030); + qtest_add_func("ast1030/hace/sha256_sg", test_sha256_sg_ast1030); + + qtest_add_func("ast1030/hace/sha512_accum", test_sha512_accum_ast1030); + qtest_add_func("ast1030/hace/sha384_accum", test_sha384_accum_ast1030); + qtest_add_func("ast1030/hace/sha256_accum", test_sha256_accum_ast1030); + qtest_add_func("ast2600/hace/addresses", test_addresses_ast2600); qtest_add_func("ast2600/hace/sha512", test_sha512_ast2600); + qtest_add_func("ast2600/hace/sha384", test_sha384_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/sha384_sg", test_sha384_sg_ast2600); qtest_add_func("ast2600/hace/sha256_sg", test_sha256_sg_ast2600); qtest_add_func("ast2600/hace/sha512_accum", test_sha512_accum_ast2600); + qtest_add_func("ast2600/hace/sha384_accum", test_sha384_accum_ast2600); qtest_add_func("ast2600/hace/sha256_accum", test_sha256_accum_ast2600); qtest_add_func("ast2500/hace/addresses", test_addresses_ast2500); diff --git a/tests/qtest/aspeed_smc-test.c b/tests/qtest/aspeed_smc-test.c index 4e13893..52a00e6 100644 --- a/tests/qtest/aspeed_smc-test.c +++ b/tests/qtest/aspeed_smc-test.c @@ -228,5 +228,10 @@ int main(int argc, char **argv) unlink(ast2500_evb_data.tmp_path); unlink(ast2600_evb_data.tmp_path); unlink(ast1030_evb_data.tmp_path); + g_free(palmetto_data.tmp_path); + g_free(ast2500_evb_data.tmp_path); + g_free(ast2600_evb_data.tmp_path); + g_free(ast1030_evb_data.tmp_path); + return ret; } diff --git a/tests/qtest/ast2700-hace-test.c b/tests/qtest/ast2700-hace-test.c new file mode 100644 index 0000000..a400e29 --- /dev/null +++ b/tests/qtest/ast2700-hace-test.c @@ -0,0 +1,98 @@ +/* + * QTest testcase for the ASPEED Hash and Crypto Engine + * + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2025 ASPEED Technology Inc. + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "qemu/bitops.h" +#include "aspeed-hace-utils.h" + +static const struct AspeedMasks as2700_masks = { + .src = 0x7fffffff, + .dest = 0x7ffffff8, + .key = 0x7ffffff8, + .len = 0x0fffffff, + .src_hi = 0x00000003, + .dest_hi = 0x00000003, + .key_hi = 0x00000003, +}; + +/* ast2700 */ +static void test_md5_ast2700(void) +{ + aspeed_test_md5("-machine ast2700a1-evb", 0x12070000, 0x400000000); +} + +static void test_sha256_ast2700(void) +{ + aspeed_test_sha256("-machine ast2700a1-evb", 0x12070000, 0x400000000); +} + +static void test_sha256_sg_ast2700(void) +{ + aspeed_test_sha256_sg("-machine ast2700a1-evb", 0x12070000, 0x400000000); +} + +static void test_sha384_ast2700(void) +{ + aspeed_test_sha384("-machine ast2700a1-evb", 0x12070000, 0x400000000); +} + +static void test_sha384_sg_ast2700(void) +{ + aspeed_test_sha384_sg("-machine ast2700a1-evb", 0x12070000, 0x400000000); +} + +static void test_sha512_ast2700(void) +{ + aspeed_test_sha512("-machine ast2700a1-evb", 0x12070000, 0x400000000); +} + +static void test_sha512_sg_ast2700(void) +{ + aspeed_test_sha512_sg("-machine ast2700a1-evb", 0x12070000, 0x400000000); +} + +static void test_sha256_accum_ast2700(void) +{ + aspeed_test_sha256_accum("-machine ast2700a1-evb", 0x12070000, 0x400000000); +} + +static void test_sha384_accum_ast2700(void) +{ + aspeed_test_sha384_accum("-machine ast2700a1-evb", 0x12070000, 0x400000000); +} + +static void test_sha512_accum_ast2700(void) +{ + aspeed_test_sha512_accum("-machine ast2700a1-evb", 0x12070000, 0x400000000); +} + +static void test_addresses_ast2700(void) +{ + aspeed_test_addresses("-machine ast2700a1-evb", 0x12070000, &as2700_masks); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("ast2700/hace/addresses", test_addresses_ast2700); + qtest_add_func("ast2700/hace/sha512", test_sha512_ast2700); + qtest_add_func("ast2700/hace/sha384", test_sha384_ast2700); + qtest_add_func("ast2700/hace/sha256", test_sha256_ast2700); + qtest_add_func("ast2700/hace/md5", test_md5_ast2700); + + qtest_add_func("ast2700/hace/sha512_sg", test_sha512_sg_ast2700); + qtest_add_func("ast2700/hace/sha384_sg", test_sha384_sg_ast2700); + qtest_add_func("ast2700/hace/sha256_sg", test_sha256_sg_ast2700); + + qtest_add_func("ast2700/hace/sha512_accum", test_sha512_accum_ast2700); + qtest_add_func("ast2700/hace/sha384_accum", test_sha384_accum_ast2700); + qtest_add_func("ast2700/hace/sha256_accum", test_sha256_accum_ast2700); + + return g_test_run(); +} diff --git a/tests/qtest/ast2700-smc-test.c b/tests/qtest/ast2700-smc-test.c index d1c4856..62d538d 100644 --- a/tests/qtest/ast2700-smc-test.c +++ b/tests/qtest/ast2700-smc-test.c @@ -67,5 +67,6 @@ int main(int argc, char **argv) qtest_quit(ast2700_evb_data.s); unlink(ast2700_evb_data.tmp_path); + g_free(ast2700_evb_data.tmp_path); return ret; } diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 7daf619..43e5a86 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -212,11 +212,12 @@ qtests_npcm7xx = \ 'npcm_gmac-test'] + \ (slirp.found() ? ['npcm7xx_emc-test'] : []) qtests_aspeed = \ - ['aspeed_hace-test', - 'aspeed_smc-test', - 'aspeed_gpio-test'] + ['aspeed_gpio-test', + 'aspeed_hace-test', + 'aspeed_smc-test'] qtests_aspeed64 = \ ['ast2700-gpio-test', + 'ast2700-hace-test', 'ast2700-smc-test'] qtests_stm32l4x5 = \ @@ -361,6 +362,10 @@ if gnutls.found() endif qtests = { + 'aspeed_hace-test': files('aspeed-hace-utils.c', 'aspeed_hace-test.c'), + 'aspeed_smc-test': files('aspeed-smc-utils.c', 'aspeed_smc-test.c'), + 'ast2700-hace-test': files('aspeed-hace-utils.c', 'ast2700-hace-test.c'), + 'ast2700-smc-test': files('aspeed-smc-utils.c', 'ast2700-smc-test.c'), 'bios-tables-test': [io, 'boot-sector.c', 'acpi-utils.c', 'tpm-emu.c'], 'cdrom-test': files('boot-sector.c'), 'dbus-vmstate-test': files('migration/migration-qmp.c', @@ -382,8 +387,6 @@ qtests = { 'virtio-net-failover': migration_files, 'vmgenid-test': files('boot-sector.c', 'acpi-utils.c'), 'netdev-socket': files('netdev-socket.c', '../unit/socket-helpers.c'), - 'aspeed_smc-test': files('aspeed-smc-utils.c', 'aspeed_smc-test.c'), - 'ast2700-smc-test': files('aspeed-smc-utils.c', 'ast2700-smc-test.c'), } if vnc.found() |