mirror of
https://github.com/Motorhead1991/qemu.git
synced 2026-02-28 23:24:36 -07:00
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----- 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>
This commit is contained in:
commit
80db93b2b8
15 changed files with 1340 additions and 673 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
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]);
|
||||
}
|
||||
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;
|
||||
|
||||
return src_addr;
|
||||
}
|
||||
|
||||
static int hash_prepare_direct_iov(AspeedHACEState *s, struct iovec *iov,
|
||||
bool acc_mode, bool *acc_final_request)
|
||||
{
|
||||
uint32_t total_msg_len;
|
||||
uint32_t pad_offset;
|
||||
uint64_t src;
|
||||
void *haddr;
|
||||
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;
|
||||
}
|
||||
iov_count = s->iov_count;
|
||||
s->iov_count = 0;
|
||||
s->total_req_len = 0;
|
||||
return iov_count;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return iov_idx;
|
||||
}
|
||||
|
||||
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 = 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,
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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[iov_idx].iov_len = plen;
|
||||
}
|
||||
} else {
|
||||
iov[iov_idx].iov_len = plen;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
local_err = NULL;
|
||||
}
|
||||
|
||||
qcrypto_hash_free(s->hash_ctx);
|
||||
|
||||
s->hash_ctx = NULL;
|
||||
s->total_req_len = 0;
|
||||
}
|
||||
|
||||
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];
|
||||
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;
|
||||
void *haddr;
|
||||
Error *local_err = NULL;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
bool acc_final_request = false;
|
||||
int iov_idx = -1;
|
||||
|
||||
/* Prepares the iov for hashing operations based on the selected mode */
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
iov[i].iov_len = plen;
|
||||
}
|
||||
}
|
||||
iov_idx = hash_prepare_sg_iov(s, iov, acc_mode, &acc_final_request);
|
||||
} 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[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);
|
||||
}
|
||||
}
|
||||
iov_idx = hash_prepare_direct_iov(s, iov, acc_mode,
|
||||
&acc_final_request);
|
||||
}
|
||||
|
||||
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));
|
||||
error_free(local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 = {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
646
tests/qtest/aspeed-hace-utils.c
Normal file
646
tests/qtest/aspeed-hace-utils.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
|
||||
84
tests/qtest/aspeed-hace-utils.h
Normal file
84
tests/qtest/aspeed-hace-utils.h
Normal file
|
|
@ -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 */
|
||||
|
||||
|
|
@ -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 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};
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static void test_sha256_accum(const char *machine, const uint32_t base,
|
||||
const uint32_t src_addr)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static void test_sha512_accum(const char *machine, const uint32_t base,
|
||||
const uint32_t src_addr)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
struct masks {
|
||||
uint32_t src;
|
||||
uint32_t dest;
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
static const struct masks ast2600_masks = {
|
||||
static const struct AspeedMasks ast1030_masks = {
|
||||
.src = 0x7fffffff,
|
||||
.dest = 0x7ffffff8,
|
||||
.key = 0x7ffffff8,
|
||||
.len = 0x0fffffff,
|
||||
};
|
||||
|
||||
static const struct masks ast2500_masks = {
|
||||
static const struct AspeedMasks ast2600_masks = {
|
||||
.src = 0x7fffffff,
|
||||
.dest = 0x7ffffff8,
|
||||
.key = 0x7ffffff8,
|
||||
.len = 0x0fffffff,
|
||||
};
|
||||
|
||||
static const struct AspeedMasks ast2500_masks = {
|
||||
.src = 0x3fffffff,
|
||||
.dest = 0x3ffffff8,
|
||||
.key = 0x3fffffc0,
|
||||
.len = 0x0fffffff,
|
||||
};
|
||||
|
||||
static const struct masks ast2400_masks = {
|
||||
static const struct AspeedMasks ast2400_masks = {
|
||||
.src = 0x0fffffff,
|
||||
.dest = 0x0ffffff8,
|
||||
.key = 0x0fffffc0,
|
||||
.len = 0x0fffffff,
|
||||
};
|
||||
|
||||
static void test_addresses(const char *machine, const uint32_t base,
|
||||
const struct masks *expected)
|
||||
/* ast1030 */
|
||||
static void test_md5_ast1030(void)
|
||||
{
|
||||
QTestState *s = qtest_init(machine);
|
||||
aspeed_test_md5("-machine ast1030-evb", 0x7e6d0000, 0x00000000);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
static void test_sha256_ast1030(void)
|
||||
{
|
||||
aspeed_test_sha256("-machine ast1030-evb", 0x7e6d0000, 0x00000000);
|
||||
}
|
||||
|
||||
static void test_sha256_sg_ast1030(void)
|
||||
{
|
||||
aspeed_test_sha256_sg("-machine ast1030-evb", 0x7e6d0000, 0x00000000);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
static void test_sha384_ast1030(void)
|
||||
{
|
||||
aspeed_test_sha384("-machine ast1030-evb", 0x7e6d0000, 0x00000000);
|
||||
}
|
||||
|
||||
qtest_writel(s, base + HACE_HASH_DIGEST, 0xffffffff);
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DIGEST), ==, expected->dest);
|
||||
static void test_sha384_sg_ast1030(void)
|
||||
{
|
||||
aspeed_test_sha384_sg("-machine ast1030-evb", 0x7e6d0000, 0x00000000);
|
||||
}
|
||||
|
||||
qtest_writel(s, base + HACE_HASH_DATA_LEN, 0xffffffff);
|
||||
g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DATA_LEN), ==, expected->len);
|
||||
static void test_sha512_ast1030(void)
|
||||
{
|
||||
aspeed_test_sha512("-machine ast1030-evb", 0x7e6d0000, 0x00000000);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
static void test_sha512_sg_ast1030(void)
|
||||
{
|
||||
aspeed_test_sha512_sg("-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_sha256_accum_ast1030(void)
|
||||
{
|
||||
aspeed_test_sha256_accum("-machine ast1030-evb", 0x7e6d0000, 0x00000000);
|
||||
}
|
||||
|
||||
qtest_quit(s);
|
||||
static void test_sha384_accum_ast1030(void)
|
||||
{
|
||||
aspeed_test_sha384_accum("-machine ast1030-evb", 0x7e6d0000, 0x00000000);
|
||||
}
|
||||
|
||||
static void test_sha512_accum_ast1030(void)
|
||||
{
|
||||
aspeed_test_sha512_accum("-machine ast1030-evb", 0x7e6d0000, 0x00000000);
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
98
tests/qtest/ast2700-hace-test.c
Normal file
98
tests/qtest/ast2700-hace-test.c
Normal file
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue