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 <[email protected]>
---
 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 09d0515271..a807cc1422 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
@@ -719,7 +737,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,
@@ -760,7 +778,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 {
@@ -796,7 +814,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 {
@@ -960,6 +978,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

Reply via email to