The AST2700 crypto engine addresses DRAM with 64 bits, supplying the high
half of the source, destination and context addresses through HACE80,
HACE84 and HACE88. Add those registers and a crypt_get_addr() helper that
combines the low and high halves when the SoC has 64-bit DMA, mirroring
the hash engine. SoCs without 64-bit DMA (AST2500/AST2600/AST1030) ignore
the high registers, so their behaviour is unchanged.
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
hw/misc/aspeed_hace.c | 33 ++++++++++++++++++++++++++++++---
1 file changed, 30 insertions(+), 3 deletions(-)
diff --git a/hw/misc/aspeed_hace.c b/hw/misc/aspeed_hace.c
index b7a7c0b7ff..60dedee6a3 100644
--- a/hw/misc/aspeed_hace.c
+++ b/hw/misc/aspeed_hace.c
@@ -58,6 +58,11 @@
#define CRYPT_CTX_KEY_OFFSET 0x10
#define CRYPT_CTX_SIZE 0x30
+/* AST2700 64-bit DMA high address registers for the crypto command */
+#define R_CRYPT_SRC_HI (0x80 / 4)
+#define R_CRYPT_DEST_HI (0x84 / 4)
+#define R_CRYPT_CONTEXT_HI (0x88 / 4)
+
#define R_STATUS (0x1c / 4)
#define HASH_IRQ BIT(9)
#define CRYPT_IRQ BIT(12)
@@ -672,6 +677,19 @@ static void crypt_be_add(uint8_t *ctr, size_t len, uint64_t add)
}
}
+static uint64_t crypt_get_addr(AspeedHACEState *s, int reg, int reg_hi)
+{
+ AspeedHACEClass *ahc = ASPEED_HACE_GET_CLASS(s);
+ uint64_t addr;
+
+ addr = deposit64(0, 0, 32, s->regs[reg]);
+ if (ahc->has_dma64) {
+ addr = deposit64(addr, 32, 32, s->regs[reg_hi]);
+ }
+
+ return addr;
+}
+
/*
* Perform an AES/DES/3DES ECB/CBC operation. The source and destination are
* either single contiguous buffers (direct access mode) or scatter-gather
@@ -712,7 +730,7 @@ static void do_crypt_operation(AspeedHACEState *s, uint32_t cmd)
}
/* Fetch the IV and key from the context buffer in DRAM. */
- ctx_addr = s->regs[R_CRYPT_CONTEXT];
+ ctx_addr = crypt_get_addr(s, R_CRYPT_CONTEXT, R_CRYPT_CONTEXT_HI);
if (address_space_read(&s->dram_as, ctx_addr, MEMTXATTRS_UNSPECIFIED,
ctx, sizeof(ctx))) {
qemu_log_mask(LOG_GUEST_ERROR,
@@ -753,7 +771,7 @@ static void do_crypt_operation(AspeedHACEState *s, uint32_t cmd)
dst_buf = g_malloc0(buf_len);
/* Gather the source into the bounce buffer, per the selected mode. */
- src_addr = s->regs[R_CRYPT_SRC];
+ src_addr = crypt_get_addr(s, R_CRYPT_SRC, R_CRYPT_SRC_HI);
if (sg_mode) {
status = crypt_prepare_sg(s, src_addr, src_buf, len, false);
} else {
@@ -789,7 +807,7 @@ static void do_crypt_operation(AspeedHACEState *s, uint32_t cmd)
}
/* Scatter the result back out, per the selected mode. */
- dst_addr = s->regs[R_CRYPT_DEST];
+ dst_addr = crypt_get_addr(s, R_CRYPT_DEST, R_CRYPT_DEST_HI);
if (sg_mode) {
status = crypt_prepare_sg(s, dst_addr, dst_buf, len, true);
} else {
@@ -953,6 +971,15 @@ static void aspeed_hace_write(void *opaque, hwaddr addr, uint64_t data,
case R_HASH_KEY_BUFF_HI:
data &= ahc->key_hi_mask;
break;
+ case R_CRYPT_SRC_HI:
+ data &= ahc->src_hi_mask;
+ break;
+ case R_CRYPT_DEST_HI:
+ data &= ahc->dest_hi_mask;
+ break;
+ case R_CRYPT_CONTEXT_HI:
+ data &= ahc->key_hi_mask;
+ break;
default:
break;
}
--
2.43.0