RE: [PATCH v1 1/5] hw/misc/aspeed_acry: Add ASPEED ACRY model
Jamin Lin <[email protected]>
| Newsgroups | org.nongnu.qemu-arm,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <TYZPR06MB4980B589FF87405C099E73E5FCA42@TYZPR06MB4980.apcprd06.prod.outlook.com> |
Hi Cédric > Subject: Re: [PATCH v1 1/5] hw/misc/aspeed_acry: Add ASPEED ACRY model > > On 8/13/26 08:24, Jamin Lin wrote: > > Introduce a ASPEED ACRY model, which performs RSA modular > > exponentiation. The datasheet documents the engine as supporting both > > RSA and ECDSA, but ECDSA is broken on this hardware, so only RSA is > > modelled. > > > > The engine DMAs its operands (data, exponent, modulus) from a guest > > DRAM buffer and writes the result back into a memory-mapped SRAM > > region. Both regions share the same interleaved byte/dword layout: > > repeating 12-dword blocks of [4 dwords exponent][4 dwords modulus][4 > > dwords data], index 0 holding the least-significant word/byte of each > > value. > > > > The engine accesses DRAM by relative offset, so the CPU-visible > > address written to the DMA source register has its top (base) bit > > masked off. > > > > The modular exponentiation itself is delegated to QEMU's generic > > akcipher crypto API (crypto/akcipher.c) using raw (unpadded) RSA, > > matching what the real hardware performs - PKCS1 padding is handled by > > the guest's software crypto stack, not by this engine. > > > > The RSA public-key operand DER encoding needed by that API is built > > with crypto/der.h's generic encoder. Raw (unpadded) RSA is only > > implemented by that API's libgcrypt backend (its nettle backend > > rejects raw padding), so this device needs QEMU built with --enable-gcrypt. > > > > When that support is missing, the engine still completes and raises > > its completion IRQ as real hardware would, but produces an all-zero > > result so that whatever signature check the guest performs on it fails > > cleanly instead of the guest hanging forever waiting for an interrupt > > that would otherwise never come. > > > > Signed-off-by: Jamin Lin <[email protected]> > > --- > > include/hw/misc/aspeed_acry.h | 50 ++++ > > hw/misc/aspeed_acry.c | 447 > ++++++++++++++++++++++++++++++++++ > > hw/misc/meson.build | 1 + > > hw/misc/trace-events | 6 + > > 4 files changed, 504 insertions(+) > > create mode 100644 include/hw/misc/aspeed_acry.h > > create mode 100644 hw/misc/aspeed_acry.c > > > > diff --git a/include/hw/misc/aspeed_acry.h > > b/include/hw/misc/aspeed_acry.h new file mode 100644 index > > 0000000000..5af2296830 > > --- /dev/null > > +++ b/include/hw/misc/aspeed_acry.h > > @@ -0,0 +1,50 @@ > > +/* > > + * ASPEED ACRY Engine > > + * > > + * Copyright (C) 2026 ASPEED Technology Inc. > > + * > > + * SPDX-License-Identifier: GPL-2.0-or-later */ > > + > > +#ifndef ASPEED_ACRY_H > > +#define ASPEED_ACRY_H > > + > > +#include "hw/core/sysbus.h" > > +#include "system/memory.h" > > + > > +#define TYPE_ASPEED_ACRY "aspeed.acry" > > +OBJECT_DECLARE_SIMPLE_TYPE(AspeedACRYState, ASPEED_ACRY) > > + > > +#define ASPEED_ACRY_NR_REGS (0x400 >> 2) > > +/* Max size of the "data" (message) field within the SRAM buffer. */ > > +#define ASPEED_ACRY_DATA_MAX_LEN 0x800 > > +#define ASPEED_ACRY_MAX_BITS 4096 > > +/* Max exponent/modulus size for a 4096-bit RSA key, in bytes. */ > > +#define ASPEED_ACRY_MAX_BYTES (ASPEED_ACRY_MAX_BITS / 8) > > + > > +struct AspeedACRYState { > > + SysBusDevice parent_obj; > > + > > + MemoryRegion iomem; > > + qemu_irq irq; > > + > > + uint32_t regs[ASPEED_ACRY_NR_REGS]; > > + > > + /* > > + * Byte-position lookup tables: exp_map[k] / mod_map[k] / > data_map[k] > > + * give the offset in the scattered buffer of byte k (k = 0 = > > + * least significant) of the exponent / modulus / data. > > + */ > > + uint32_t exp_map[ASPEED_ACRY_MAX_BYTES]; > > + uint32_t mod_map[ASPEED_ACRY_MAX_BYTES]; > > + uint32_t data_map[ASPEED_ACRY_DATA_MAX_LEN]; > > + > > + MemoryRegion *dram_mr; > > + AddressSpace dram_as; > > + > > + MemoryRegion *sram_mr; > > + AddressSpace sram_as; > > + uint64_t sram_base; > > A device model should not know its mapping address. > > I think sram[1] should be wrapped in a container MR at offset 0 and mapped at > the physical address. With that the device can use relative offsets. > > Look at the DRAM dram_container in aspeed_soc_common.c for this. > Thanks for the review and suggestions. Will do. > > > > +}; > > + > > +#endif /* ASPEED_ACRY_H */ > > diff --git a/hw/misc/aspeed_acry.c b/hw/misc/aspeed_acry.c new file > > mode 100644 index 0000000000..53ef68d284 > > --- /dev/null > > +++ b/hw/misc/aspeed_acry.c > > @@ -0,0 +1,447 @@ > > +/* > > + * ASPEED ACRY Engine > > + * > > + * Copyright (C) 2026 ASPEED Technology Inc. > > + * > > + * SPDX-License-Identifier: GPL-2.0-or-later > > + * > > + * The datasheet documents the ACRY engine as supporting both RSA and > > + * ECDSA, but ECDSA is broken on this hardware, so only RSA is > > +modelled > > + * here. > > + */ > > + > > +#include "qemu/osdep.h" > > +#include "qemu/cutils.h" > > +#include "qemu/log.h" > > +#include "hw/misc/aspeed_acry.h" > > +#include "hw/core/qdev-properties.h" > > +#include "hw/core/irq.h" > > +#include "hw/core/registerfields.h" > > +#include "qapi/error.h" > > +#include "crypto/akcipher.h" > > +#include "crypto/der.h" > > +#include "trace.h" > > + > > +REG32(ACRY_TRIGGER, 0x000) > > + FIELD(ACRY_TRIGGER, RSA_DMA_DATA, 1, 1) > > + FIELD(ACRY_TRIGGER, RSA_START, 0, 1) REG32(ACRY_DMA_CMD, > 0x048) > > +REG32(ACRY_DMA_SRC, 0x04C) REG32(ACRY_DMA_LEN, 0x050) > > +REG32(ACRY_RSA_KEY_LEN, 0x058) REG32(ACRY_INT_MASK, 0x3F8) > > + FIELD(ACRY_INT_MASK, RSA_DMA_MASK, 2, 1) > > + FIELD(ACRY_INT_MASK, RSA_ENG_MASK, 1, 1) REG32(ACRY_STATUS, > > +0x3FC) > > + FIELD(ACRY_STATUS, RSA_DMA_DONE, 2, 1) > > + FIELD(ACRY_STATUS, RSA_ENG_DONE, 1, 1) > > + > > +/* > > + * Total size of the interleaved SRAM buffer. Data is 4 of every 12 > > + * dwords of a block (see aspeed_acry_init_mapping()), i.e. one third of > > + * the buffer, so the whole buffer is 3x the data region. > > + */ > > +#define ASPEED_ACRY_SRAM_SIZE (3 * ASPEED_ACRY_DATA_MAX_LEN) > > + > > +static void aspeed_acry_hexdump(const char *desc, const uint8_t *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_acry_hexdump(desc, i, str->str); > > + } > > +} > > + > > +/* > > + * The SRAM buffer is a series of 12-dword blocks, each split into > > + * three 4-dword regions - exp, mod, data: > > + * > > + * dword in block: 0 1 2 3 4 5 6 7 8 > 9 10 11 > > + * region: \---- exp ----/ \---- mod ----/ \---- data ----/ > > + * lane: 0 1 2 3 0 1 2 3 0 > 1 2 3 > > + * > > + * Successive blocks hold the next 4 dwords of each operand, so operand > > + * dword d is in block (d / 4), lane (d % 4). Dwords are little-endian, so > > + * byte b of the dword at SRAM dword D is at byte D * 4 + b. > > + * > > + * exp_map[op_byte] / mod_map[op_byte] / data_map[op_byte] give the > buffer > > + * offset of operand byte op_byte (op_byte = 0 = least significant). > > + */ > > +static void aspeed_acry_init_mapping(AspeedACRYState *s) > > +{ > > + int byte_in_dword; > > + int block_base; > > + int op_dword; > > + int op_byte; > > + int block; > > + int lane; > > + > > + for (op_byte = 0; op_byte < ASPEED_ACRY_DATA_MAX_LEN; > op_byte++) { > > + op_dword = op_byte / 4; > > + byte_in_dword = op_byte % 4; > > + block = op_dword / 4; > > + lane = op_dword % 4; > > + block_base = block * 12; > > + > > + /* exp starts each block; mod is +4 dwords, data +8 dwords. */ > > + s->data_map[op_byte] = (block_base + 8 + lane) * 4 + > byte_in_dword; > > + if (op_byte < ASPEED_ACRY_MAX_BYTES) { > > + s->exp_map[op_byte] = (block_base + 0 + lane) * 4 + > byte_in_dword; > > + s->mod_map[op_byte] = (block_base + 4 + lane) * 4 + > byte_in_dword; > > + } > > + } > > +} > > > This is a lot of constant values for each state. Can we build the offsets > on the fly ? > Will do. > > > +/* > > + * Read one operand out of the buffer as a big-endian magnitude. > > + * > > + * The operand's bytes are scattered through buf: buf[map[k]] is the byte > > + * at significance level k (k = 0 is the least significant). Walk from the > > + * top down, drop leading zero bytes, and write the result most significant > > + * byte first into out[]. Returns the number of bytes written (the value 0 > > + * yields a single 0x00 byte, so always >= 1). > > + */ > > +static int aspeed_acry_extract_be(const uint8_t *buf, const uint32_t *map, > > + int max_bytes, uint8_t *out) > > +{ > > + int msb; > > + int len; > > + int k; > > + > > + /* Highest significance level holding a non-zero byte (skip leading 0s). > */ > > + msb = max_bytes - 1; > > + while (msb >= 0 && buf[map[msb]] == 0) { > > + msb--; > > + } > > + > > + /* All bytes zero: the value is 0. */ > > + if (msb < 0) { > > + out[0] = 0; > > + return 1; > > + } > > + > > + /* Copy most significant byte first: level msb down to level 0. */ > > + len = 0; > > + for (k = msb; k >= 0; k--) { > > + out[len++] = buf[map[k]]; > > + } > > + > > + return len; > > +} > > + > > +/* > > + * Return a DER INTEGER body for the unsigned big-endian magnitude 'be'. > > + * > > + * DER INTEGERs are signed, so if the top byte has bit 7 set the value > > + * would decode as negative; prepend a 0x00 guard byte in that case. > > + * > > + * The padded copy is written into 'pad_buf' (caller-owned, sized len + 1) > > + * rather than a local, because qcrypto_der_encode_int() only stores the > > + * pointer we hand it - the bytes are not copied until > > + * qcrypto_der_encode_ctx_flush_and_free() - so the body must stay valid > > + * until then. Returns a pointer into 'be' or 'pad_buf' as appropriate, > > + * with the body length in *body_len. > > + */ > > +static const uint8_t *aspeed_acry_der_uint_body(const uint8_t *be, size_t > len, > > + uint8_t > *pad_buf, > > + size_t > *body_len) > > +{ > > + if (be[0] & 0x80) { > > + pad_buf[0] = 0x00; > > + memcpy(pad_buf + 1, be, len); > > + *body_len = len + 1; > > + return pad_buf; > > + } > > + > > + *body_len = len; > > + return be; > > +} > > + > > +/* > > + * DER-encode a "RsaPubKey ::= SEQUENCE { n INTEGER, e INTEGER }" (see > > + * crypto/rsakey.h), the format expected by qcrypto_akcipher_new(). n and > e > > + * are minimal big-endian magnitudes (as produced by > > + * aspeed_acry_extract_be()); the engine does a raw modexp, so the guest's > > + * exponent is always encoded here as the public 'e'. > > + */ > > +static uint8_t *aspeed_acry_der_encode_pubkey(const uint8_t *n, size_t > n_len, > > + const uint8_t *e, > size_t e_len, > > + size_t *out_len) > > +{ > > + QCryptoEncodeContext *ctx = qcrypto_der_encode_ctx_new(); > > + uint8_t n_pad[ASPEED_ACRY_MAX_BYTES + 1]; > > + uint8_t e_pad[ASPEED_ACRY_MAX_BYTES + 1]; > > + const uint8_t *n_body; > > + const uint8_t *e_body; > > + size_t n_body_len; > > + size_t e_body_len; > > + uint8_t *buf; > > + > > + n_body = aspeed_acry_der_uint_body(n, n_len, n_pad, &n_body_len); > > + e_body = aspeed_acry_der_uint_body(e, e_len, e_pad, &e_body_len); > > + > > + qcrypto_der_encode_seq_begin(ctx); > > + qcrypto_der_encode_int(ctx, n_body, n_body_len); > > + qcrypto_der_encode_int(ctx, e_body, e_body_len); > > + qcrypto_der_encode_seq_end(ctx); > > + > > + *out_len = qcrypto_der_encode_ctx_buffer_len(ctx); > > + buf = g_malloc(*out_len); > > + qcrypto_der_encode_ctx_flush_and_free(ctx, buf); > > + > > + return buf; > > +} > > + > > +/* > > + * Store the RSA result into the output SRAM, scattered through the data > > + * region via data_map[] (result_be is big-endian; the region above the > > + * result is zeroed). > > + * > > + * data_map[] holds SRAM-relative offsets, but sram_as is an AddressSpace > > + * over the SoC memory, where the SRAM is mapped at sram_base - so the > > + * absolute address is sram_base + data_map[k]. > > + */ > > +static void aspeed_acry_store_result(AspeedACRYState *s, > > + const uint8_t *result_be, int > result_len) > > +{ > > + uint8_t value; > > + int src; > > + int k; > > + > > + /* result_be is MSB-first, so its last byte is the least significant. */ > > There are address_space store/load be/le helpers which could simplify > the transactions. > Will do. > > + src = result_len - 1; > > + for (k = 0; k < ASPEED_ACRY_DATA_MAX_LEN; k++) { > > + value = 0; > > + if (src >= 0) { > > + value = result_be[src--]; > > + } > > + address_space_write(&s->sram_as, s->sram_base + > s->data_map[k], > > + MEMTXATTRS_UNSPECIFIED, &value, 1); > > the return value should be tested. > Will do. Thanks, Jamin > > Thanks, > > C. > > > > + } > > +} > > + > > +static void aspeed_acry_do_rsa(AspeedACRYState *s) > > +{ > > + QCryptoAkCipherOptions opts = { > > + .alg = QCRYPTO_AK_CIPHER_ALGO_RSA, > > + .u.rsa = { > > + .padding_alg = QCRYPTO_RSA_PADDING_ALGO_RAW, > > + }, > > + }; > > + uint8_t result[ASPEED_ACRY_MAX_BYTES] = { 0 }; > > + uint64_t src_addr = s->regs[R_ACRY_DMA_SRC]; > > + uint8_t buf[ASPEED_ACRY_SRAM_SIZE] = { 0 }; > > + uint8_t data[ASPEED_ACRY_DATA_MAX_LEN]; > > + uint32_t len = s->regs[R_ACRY_DMA_LEN]; > > + g_autofree uint8_t *der_key = NULL; > > + uint8_t n[ASPEED_ACRY_MAX_BYTES]; > > + uint8_t e[ASPEED_ACRY_MAX_BYTES]; > > + QCryptoAkCipher *cipher = NULL; > > + Error *local_err = NULL; > > + int result_len = 0; > > + size_t der_len; > > + int data_len; > > + int n_len; > > + int e_len; > > + > > + if (len == 0 || len > ASPEED_ACRY_SRAM_SIZE) { > > + len = ASPEED_ACRY_SRAM_SIZE; > > + } > > + > > + trace_aspeed_acry_rsa_trigger(src_addr, len); > > + > > + if (address_space_read(&s->dram_as, src_addr, > MEMTXATTRS_UNSPECIFIED, > > + buf, len) != MEMTX_OK) { > > + qemu_log_mask(LOG_GUEST_ERROR, > > + "%s: failed to read DMA buffer at 0x%" PRIx64 > "\n", > > + __func__, src_addr); > > + } > > + > > + n_len = aspeed_acry_extract_be(buf, s->mod_map, > ASPEED_ACRY_MAX_BYTES, n); > > + e_len = aspeed_acry_extract_be(buf, s->exp_map, > ASPEED_ACRY_MAX_BYTES, e); > > + data_len = aspeed_acry_extract_be(buf, s->data_map, > > + > ASPEED_ACRY_DATA_MAX_LEN, data); > > + > > + if (trace_event_get_state_backends(TRACE_ASPEED_ACRY_HEXDUMP)) > { > > + aspeed_acry_hexdump("buf", buf, len); > > + aspeed_acry_hexdump("n", n, n_len); > > + aspeed_acry_hexdump("e", e, e_len); > > + aspeed_acry_hexdump("data", data, data_len); > > + } > > + > > + if (!qcrypto_akcipher_supports(&opts)) { > > + qemu_log_mask(LOG_UNIMP, > > + "%s: RSA ModExp not supported by the crypto > backend; " > > + "completing with an invalid result\n", __func__); > > + return; > > + } > > + > > + der_key = aspeed_acry_der_encode_pubkey(n, n_len, e, e_len, > &der_len); > > + cipher = qcrypto_akcipher_new(&opts, > QCRYPTO_AK_CIPHER_KEY_TYPE_PUBLIC, > > + der_key, der_len, &local_err); > > + if (!cipher) { > > + qemu_log_mask(LOG_GUEST_ERROR, > > + "%s: failed to create RSA cipher: %s\n", > > + __func__, error_get_pretty(local_err)); > > + error_free(local_err); > > + } else { > > + result_len = qcrypto_akcipher_encrypt(cipher, data, data_len, > > + result, > sizeof(result), > > + &local_err); > > + if (result_len < 0) { > > + qemu_log_mask(LOG_GUEST_ERROR, "%s: RSA modexp > failed: %s\n", > > + __func__, error_get_pretty(local_err)); > > + error_free(local_err); > > + result_len = 0; > > + } > > + > > + qcrypto_akcipher_free(cipher); > > + } > > + > > + if (trace_event_get_state_backends(TRACE_ASPEED_ACRY_HEXDUMP)) > { > > + aspeed_acry_hexdump("result", result, result_len); > > + } > > + > > + aspeed_acry_store_result(s, result, result_len); > > +} > > + > > +static uint64_t aspeed_acry_read(void *opaque, hwaddr addr, unsigned int > size) > > +{ > > + AspeedACRYState *s = ASPEED_ACRY(opaque); > > + > > + addr >>= 2; > > + > > + trace_aspeed_acry_read(addr << 2, s->regs[addr]); > > + > > + return s->regs[addr]; > > +} > > + > > +static void aspeed_acry_write(void *opaque, hwaddr addr, uint64_t data, > > + unsigned int size) > > +{ > > + AspeedACRYState *s = ASPEED_ACRY(opaque); > > + > > + addr >>= 2; > > + > > + trace_aspeed_acry_write(addr << 2, data); > > + > > + switch (addr) { > > + case R_ACRY_DMA_SRC: > > + /* > > + * The DMA source register holds a CPU-visible DRAM address > (e.g. > > + * 0x8xxxxxxx on AST2600); the engine addresses DRAM from > offset 0, > > + * so mask off the top bit to get the DRAM-relative offset. > > + */ > > + data &= 0x7FFFFFFF; > > + break; > > + case R_ACRY_STATUS: > > + data = s->regs[R_ACRY_STATUS] & ~data; > > + if (!(data & (R_ACRY_STATUS_RSA_ENG_DONE_MASK | > > + R_ACRY_STATUS_RSA_DMA_DONE_MASK))) { > > + qemu_irq_lower(s->irq); > > + } > > + break; > > + case R_ACRY_TRIGGER: > > + if (FIELD_EX32(data, ACRY_TRIGGER, RSA_START)) { > > + aspeed_acry_do_rsa(s); > > + > > + s->regs[R_ACRY_STATUS] |= > R_ACRY_STATUS_RSA_ENG_DONE_MASK | > > + > R_ACRY_STATUS_RSA_DMA_DONE_MASK; > > + if (s->regs[R_ACRY_INT_MASK] & > > + (R_ACRY_INT_MASK_RSA_ENG_MASK_MASK | > > + R_ACRY_INT_MASK_RSA_DMA_MASK_MASK)) { > > + qemu_irq_raise(s->irq); > > + } > > + } > > + break; > > + default: > > + break; > > + } > > + > > + s->regs[addr] = data; > > +} > > + > > +static const MemoryRegionOps aspeed_acry_ops = { > > + .read = aspeed_acry_read, > > + .write = aspeed_acry_write, > > + .endianness = DEVICE_LITTLE_ENDIAN, > > + .valid = { > > + .min_access_size = 1, > > + .max_access_size = 4, > > + }, > > +}; > > + > > +static void aspeed_acry_reset_hold(Object *obj, ResetType type) > > +{ > > + AspeedACRYState *s = ASPEED_ACRY(obj); > > + > > + memset(s->regs, 0, sizeof(s->regs)); > > +} > > + > > +static void aspeed_acry_instance_init(Object *obj) > > +{ > > + AspeedACRYState *s = ASPEED_ACRY(obj); > > + > > + aspeed_acry_init_mapping(s); > > +} > > + > > +static void aspeed_acry_realize(DeviceState *dev, Error **errp) > > +{ > > + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); > > + AspeedACRYState *s = ASPEED_ACRY(dev); > > + > > + sysbus_init_irq(sbd, &s->irq); > > + > > + memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_acry_ops, s, > > + TYPE_ASPEED_ACRY, > ASPEED_ACRY_NR_REGS << 2); > > + sysbus_init_mmio(sbd, &s->iomem); > > + > > + if (!s->dram_mr) { > > + error_setg(errp, TYPE_ASPEED_ACRY ": 'dram' link not set"); > > + return; > > + } > > + address_space_init(&s->dram_as, s->dram_mr, "dram"); > > + > > + if (!s->sram_mr) { > > + error_setg(errp, TYPE_ASPEED_ACRY ": 'sram' link not set"); > > + return; > > + } > > + address_space_init(&s->sram_as, s->sram_mr, "sram"); > > +} > > + > > +static const Property aspeed_acry_properties[] = { > > + DEFINE_PROP_LINK("dram", AspeedACRYState, dram_mr, > > + TYPE_MEMORY_REGION, MemoryRegion *), > > + DEFINE_PROP_LINK("sram", AspeedACRYState, sram_mr, > > + TYPE_MEMORY_REGION, MemoryRegion *), > > + DEFINE_PROP_UINT64("sram-base", AspeedACRYState, sram_base, 0), > > +}; > > + > > +static void aspeed_acry_class_init(ObjectClass *klass, const void *data) > > +{ > > + DeviceClass *dc = DEVICE_CLASS(klass); > > + ResettableClass *rc = RESETTABLE_CLASS(klass); > > + > > + dc->desc = "ASPEED ACRY Engine"; > > + dc->realize = aspeed_acry_realize; > > + rc->phases.hold = aspeed_acry_reset_hold; > > + device_class_set_props(dc, aspeed_acry_properties); > > +} > > + > > +static const TypeInfo aspeed_acry_types[] = { > > + { > > + .name = TYPE_ASPEED_ACRY, > > + .parent = TYPE_SYS_BUS_DEVICE, > > + .instance_size = sizeof(AspeedACRYState), > > + .instance_init = aspeed_acry_instance_init, > > + .class_init = aspeed_acry_class_init, > > + }, > > +}; > > + > > +DEFINE_TYPES(aspeed_acry_types) > > diff --git a/hw/misc/meson.build b/hw/misc/meson.build > > index e86d9ad6b3..3912dc2bce 100644 > > --- a/hw/misc/meson.build > > +++ b/hw/misc/meson.build > > @@ -137,6 +137,7 @@ system_ss.add(when: 'CONFIG_PVPANIC_PCI', if_true: > files('pvpanic-pci.c')) > > system_ss.add(when: 'CONFIG_PVPANIC_MMIO', if_true: > files('pvpanic-mmio.c')) > > system_ss.add(when: 'CONFIG_AUX', if_true: files('auxbus.c')) > > system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files( > > + 'aspeed_acry.c', > > 'aspeed_hace.c', > > 'aspeed_lpc.c', > > 'aspeed_ltpi.c', > > diff --git a/hw/misc/trace-events b/hw/misc/trace-events > > index c9a868b3ef..bbec0d2178 100644 > > --- a/hw/misc/trace-events > > +++ b/hw/misc/trace-events > > @@ -331,6 +331,12 @@ 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_acry.c > > +aspeed_acry_read(uint64_t offset, uint64_t data) "offset 0x%" PRIx64 " data > 0x%" PRIx64 > > +aspeed_acry_write(uint64_t offset, uint64_t data) "offset 0x%" PRIx64 " > data 0x%" PRIx64 > > +aspeed_acry_rsa_trigger(uint64_t src_addr, uint32_t len) "src_addr 0x%" > PRIx64 " len 0x%" PRIx32 > > +aspeed_acry_hexdump(const char *desc, uint32_t offset, const char *s) "%s: > 0x%08x: %s" > > + > > # 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