QEMU-Devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Wadim Mueller <wafgo01@gmail.com>
To: qemu-devel@nongnu.org
Cc: qemu-arm@nongnu.org, "Peter Maydell" <peter.maydell@linaro.org>,
	"Philippe Mathieu-Daudé" <philmd@mailo.com>,
	"Bin Meng" <bmeng.cn@gmail.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Fabiano Rosas" <farosas@suse.de>,
	"Wadim Mueller" <wafgo01@gmail.com>
Subject: [RFC PATCH v2 09/14] hw/misc: add TI K3 secure proxy model
Date: Thu, 20 Aug 2026 14:48:09 +0200	[thread overview]
Message-ID: <20260820124824.618671-10-wafgo01@gmail.com> (raw)
In-Reply-To: <20260820124824.618671-1-wafgo01@gmail.com>

The secure proxy is the message transport between the K3 host cores and
the device management and security controller (DMSC). Model the per-thread
RT/SCFG register banks and the message buffers, and provide a callback
interface, which the DMSC model plugs into.

Signed-off-by: Wadim Mueller <wafgo01@gmail.com>
---
 hw/misc/Kconfig                |   3 +
 hw/misc/meson.build            |   1 +
 hw/misc/ti-sec-proxy.c         | 446 +++++++++++++++++++++++++++++++++
 hw/misc/trace-events           |   8 +
 include/hw/misc/ti-sec-proxy.h | 108 ++++++++
 5 files changed, 566 insertions(+)
 create mode 100644 hw/misc/ti-sec-proxy.c
 create mode 100644 include/hw/misc/ti-sec-proxy.h

diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index e80fdc3214..bea8e9341f 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -161,6 +161,9 @@ config TI_K3_SDHCI_PHY
 config TI_K3_TRNG
     bool
 
+config TI_SEC_PROXY
+    bool
+
 config TI_MAILBOX
     bool
 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index d190d8608a..a8a40ea2a7 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -129,6 +129,7 @@ system_ss.add(when: 'CONFIG_TI_K3_GTC', if_true: files('ti-k3-gtc.c'))
 system_ss.add(when: 'CONFIG_TI_K3_DDRSS', if_true: files('ti-k3-ddrss.c'))
 system_ss.add(when: 'CONFIG_TI_K3_SDHCI_PHY', if_true: files('ti-k3-sdhci-phy.c'))
 system_ss.add(when: 'CONFIG_TI_K3_TRNG', if_true: files('ti-k3-trng.c'))
+system_ss.add(when: 'CONFIG_TI_SEC_PROXY', if_true: files('ti-sec-proxy.c'))
 system_ss.add(when: 'CONFIG_TI_MAILBOX', if_true: files('ti-mailbox.c'))
 system_ss.add(when: 'CONFIG_TZ_MPC', if_true: files('tz-mpc.c'))
 system_ss.add(when: 'CONFIG_TZ_MSC', if_true: files('tz-msc.c'))
diff --git a/hw/misc/ti-sec-proxy.c b/hw/misc/ti-sec-proxy.c
new file mode 100644
index 0000000000..524bd1353c
--- /dev/null
+++ b/hw/misc/ti-sec-proxy.c
@@ -0,0 +1,446 @@
+/*
+ * TI SEC PROXY SysBus device
+ *
+ * Copyright (c) 2025 CMBLU Energy AG
+ * Author: Wadim Mueller <wafgo01@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * TI K3 SoCs use it as mailbox transport to the DMSC/SYSFW endpoint.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/cutils.h"
+#include "hw/misc/ti-sec-proxy.h"
+#include "hw/core/sysbus.h"
+#include "hw/core/register.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "hw/core/irq.h"
+#include "trace.h"
+
+#define SEC_PROXY_MAX_MSG (16)
+
+REG32(SEC_PROXY_0_thread_status, 0x0)
+FIELD(SEC_PROXY_0_thread_status, ERROR, 31, 1)
+FIELD(SEC_PROXY_0_thread_status, DIR, 30, 1)
+FIELD(SEC_PROXY_0_thread_status, MAX_CNT, 16, 8)
+FIELD(SEC_PROXY_0_thread_status, CUR_CNT, 0, 8)
+
+REG32(SEC_PROXY_0_thread_threshold, 0x4)
+FIELD(SEC_PROXY_0_thread_threshold, THR_CNT, 0, 8)
+
+REG32(SEC_PROXY_0_thread_private, 0x0)
+FIELD(SEC_PROXY_0_thread_private, SRC_THR, 0, 10)
+
+REG32(SEC_PROXY_0_thread_message, 0x4)
+
+REG32(SEC_PROXY_0_buffer_l, 0x0)
+REG32(SEC_PROXY_0_buffer_h, 0x4)
+FIELD(SEC_PROXY_0_buffer_h, BASE_H, 0, 16)
+
+REG32(SEC_PROXY_0_target_l, 0x8)
+REG32(SEC_PROXY_0_target_h, 0xc)
+FIELD(SEC_PROXY_0_target_h, TARGET_H, 0, 16)
+
+REG32(SEC_PROXY_0_orderid, 0x10)
+FIELD(SEC_PROXY_0_orderid, ORDERID, 0, 4)
+FIELD(SEC_PROXY_0_orderid, REPLACE, 4, 1)
+
+REG32(SEC_PROXY_0_thread_ctl, 0x0)
+FIELD(SEC_PROXY_0_thread_ctl, QUEUE, 0, 16)
+FIELD(SEC_PROXY_0_thread_ctl, MAX_CNT, 16, 8)
+FIELD(SEC_PROXY_0_thread_ctl, DIR, 31, 1)
+
+REG32(SEC_PROXY_0_thread_evt_map, 0x4)
+FIELD(SEC_PROXY_0_thread_evt_map, THR_EVT, 0, 16)
+FIELD(SEC_PROXY_0_thread_evt_map, ERR_EVT, 16, 16)
+
+REG32(SEC_PROXY_0_thread_dst, 0x8)
+FIELD(SEC_PROXY_0_thread_dst, THREAD, 0, 16)
+
+REG32(SEC_PROXY_0_pid, 0x0)
+FIELD(SEC_PROXY_0_pid, SCHEME, 30, 2)
+FIELD(SEC_PROXY_0_pid, BU, 28, 2)
+FIELD(SEC_PROXY_0_pid, FUNC, 16, 12)
+FIELD(SEC_PROXY_0_pid, RTL, 11, 5)
+FIELD(SEC_PROXY_0_pid, MAJOR, 8, 3)
+FIELD(SEC_PROXY_0_pid, CUSTOM, 6, 2)
+FIELD(SEC_PROXY_0_pid, MINOR, 0, 6)
+
+REG32(SEC_PROXY_0_config, 0x4)
+FIELD(SEC_PROXY_0_config, MSG_SIZE, 16, 16)
+FIELD(SEC_PROXY_0_config, THREADS, 0, 16)
+
+REG32(SEC_PROXY_0_glb_evt, 0x14)
+FIELD(SEC_PROXY_0_glb_evt, ERR_EVENT, 0, 16)
+
+static RegisterAccessInfo sec_proxy_mmrs_regs_info[] = {
+    {
+        .name = "SEC_PROXY_0_pid",
+        .addr = A_SEC_PROXY_0_pid,
+        .ro = 0xffffffff,
+        .reset = 1714843904,
+    },
+    {
+        .name = "SEC_PROXY_0_config",
+        .addr = A_SEC_PROXY_0_config,
+        .ro = 0xffffffff,
+        .reset = 4194380,
+    },
+    {
+        .name = "SEC_PROXY_0_glb_evt",
+        .addr = A_SEC_PROXY_0_glb_evt,
+        .rsvd = 0xffff0000,
+        .reset = 65535,
+    }
+};
+
+static void ti_sec_proxy_realize(DeviceState *dev_soc, Error **errp)
+{
+    ERRP_GUARD();
+    TISecProxyState *s = TI_SEC_PROXY(dev_soc);
+
+    for (int i = 0; i < SEC_PROXY_THREAD_ID_MAX; ++i) {
+        struct TISecProxyThreadInfo *ti = &s->thread_info[i];
+        ti->thread_id = i;
+        /* K3 secure proxy alternates inbound and outbound threads. */
+        ti->is_outbound = (i % 2) ? true : false;
+        ti->num_messages = ti->is_outbound ? SEC_PROXY_MSG_MAX_WORDS : 0;
+        memset(ti->current_message, 0, sizeof(ti->current_message));
+    }
+}
+
+/* --- Backend API exported to DMSC -------------------------------------- */
+void ti_sec_proxy_register_msg_cb(TISecProxyState *sp, uint16_t thread_id,
+                                  TISecProxyMsgCb cb, void *opaque)
+{
+    if (thread_id >= ARRAY_SIZE(sp->thread_info)) {
+        return;
+    }
+
+    sp->thread_info[thread_id].cb = cb;
+    sp->thread_info[thread_id].cb_opaque = opaque;
+}
+
+size_t ti_sec_proxy_push_msg(TISecProxyState *sp, uint16_t thread_id,
+                             const uint32_t *words, size_t nbytes)
+{
+    struct TISecProxyThreadInfo *ti;
+
+    if (thread_id >= ARRAY_SIZE(sp->thread_info)) {
+        return 0;
+    }
+
+    ti = &sp->thread_info[thread_id];
+    if (nbytes > sizeof(ti->current_message) - sizeof(uint32_t)) {
+        return 0;
+    }
+
+    memcpy(&ti->current_message[1], words, nbytes);
+    qemu_irq_raise(sp->irq_evt);
+
+    ti->num_messages++;
+    return ti->num_messages;
+}
+
+uint32_t ti_sec_proxy_get_msg_words(TISecProxyState *sp)
+{
+    return sp->msg_words;
+}
+
+void ti_sec_proxy_reset_thread_count(TISecProxyState *sp, uint16_t thread_id)
+{
+    if (thread_id >= ARRAY_SIZE(sp->thread_info)) {
+        return;
+    }
+
+    sp->thread_info[thread_id].num_messages = 0;
+}
+
+static const char *
+ti_sec_proxy_get_thread_channel_name(enum TISciThreadIds thread_id)
+{
+    const char *thread_names[] = {
+        "MAIN_0_R5_0_READ_RESPONSE_THREAD", "MAIN_0_R5_0_WRITE_THREAD",
+        "MAIN_0_R5_1_READ_RESPONSE_THREAD", "MAIN_0_R5_1_WRITE_THREAD",
+        "MAIN_0_R5_2_READ_RESPONSE_THREAD", "MAIN_0_R5_2_WRITE_THREAD",
+        "MAIN_0_R5_3_READ_RESPONSE_THREAD", "MAIN_0_R5_3_WRITE_THREAD",
+        "A53_0_READ_RESPONSE_THREAD",       "A53_0_WRITE_THREAD",
+        "A53_1_READ_RESPONSE_THREAD",       "A53_1_WRITE_THREAD",
+        "A53_2_READ_RESPONSE_THREAD",       "A53_2_WRITE_THREAD",
+        "A53_3_READ_RESPONSE_THREAD",       "A53_3_WRITE_THREAD",
+        "M4_0_READ_RESPONSE_THREAD",        "M4_0_WRITE_THREAD",
+        "MAIN_1_R5_0_READ_RESPONSE_THREAD", "MAIN_1_R5_0_WRITE_THREAD",
+        "MAIN_1_R5_1_READ_RESPONSE_THREAD", "MAIN_1_R5_1_WRITE_THREAD",
+        "MAIN_1_R5_2_READ_RESPONSE_THREAD", "MAIN_1_R5_2_WRITE_THREAD",
+        "MAIN_1_R5_3_READ_RESPONSE_THREAD", "MAIN_1_R5_3_WRITE_THREAD",
+        "A53_4_READ_RESPONSE_THREAD",       "A53_4_WRITE_THREAD",
+        "ICSSG_0_READ_RESPONSE_THREAD",     "ICSSG_0_WRITE_THREAD",
+        "ICSSG_1_READ_RESPONSE_THREAD",     "ICSSG_1_WRITE_THREAD"};
+
+    if (thread_id < ARRAY_SIZE(thread_names)) {
+        return thread_names[thread_id];
+    }
+    return "UNKNOWN_THREAD";
+}
+
+static void ti_sec_proxy_reset_hold(Object *obj, ResetType type)
+{
+    TISecProxyState *s = TI_SEC_PROXY(obj);
+
+    for (int i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
+        register_reset(&s->regs_info[i]);
+    }
+}
+
+static void ti_sec_proxy_class_init(ObjectClass *klass, const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+    dc->realize = ti_sec_proxy_realize;
+    rc->phases.hold = ti_sec_proxy_reset_hold;
+}
+
+static const MemoryRegionOps ti_sec_proxy_mmr_ops = {
+    .read = register_read_memory,
+    .write = register_write_memory,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static uint64_t ti_sec_proxy_read_scfg(void *opaque, hwaddr addr, unsigned size)
+{
+    TISecProxyState *s = opaque;
+    if (addr <= 0x10) {
+        return 0;
+    }
+
+    hwaddr thread_rel_addr = addr - 0x10;
+    int thread_num = thread_rel_addr / 0x1000;
+    int reg = (thread_rel_addr % 0x1000) / 4;
+    struct TISecProxyThreadInfo *tinfo = &s->thread_info[thread_num];
+
+    trace_ti_sec_proxy_read_scfg(
+        ti_sec_proxy_get_thread_channel_name(thread_num), reg, addr);
+    return tinfo->is_outbound ? 0x0 : 0x80000000;
+}
+
+static void ti_sec_proxy_write_scfg(void *opaque, hwaddr addr, uint64_t value,
+                                    unsigned size)
+{
+    if (addr <= 0x10) {
+        return;
+    }
+
+    int thread_num = addr / 0x1000;
+    int reg = (addr % 0x1000) / 4;
+
+    trace_ti_sec_proxy_write_scfg(
+        ti_sec_proxy_get_thread_channel_name(thread_num), reg, addr, value);
+}
+
+static const MemoryRegionOps ti_sec_proxy_scfg_ops = {
+    .read = ti_sec_proxy_read_scfg,
+    .write = ti_sec_proxy_write_scfg,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+    },
+};
+
+static uint64_t ti_sec_proxy_read_rt(void *opaque, hwaddr addr, unsigned size)
+{
+    TISecProxyState *s = opaque;
+    int thread_num = addr / 0x1000;
+    hwaddr off = addr % 0x1000;
+
+    int byte = off & 0x3;
+
+    struct TISecProxyThreadInfo *tinfo = &s->thread_info[thread_num];
+
+    uint32_t reg_val = (tinfo->num_messages) |
+                       (tinfo->is_outbound ? 0x0 : 0x40000000) |
+                       (tinfo->is_outbound ? (tinfo->num_messages << 16) : 0x0);
+
+    uint64_t ret;
+
+    if (size == 1) {
+        ret = (reg_val >> (8 * byte)) & 0xff;
+    } else if (size == 2) {
+        ret = (reg_val >> (8 * (byte & ~1))) & 0xffff;
+    } else if (size == 4) {
+        ret = reg_val;
+    } else {
+        ret = 0;
+    }
+    trace_ti_sec_proxy_read_rt(ti_sec_proxy_get_thread_channel_name(thread_num),
+                               ret, addr);
+    return ret;
+}
+
+static void ti_sec_proxy_write_rt(void *opaque, hwaddr addr, uint64_t value,
+                                  unsigned size)
+{
+}
+
+static const MemoryRegionOps ti_sec_proxy_rt_ops = {
+    .read = ti_sec_proxy_read_rt,
+    .write = ti_sec_proxy_write_rt,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+    },
+};
+
+static uint64_t ti_sec_proxy_read_target(void *opaque, hwaddr addr,
+                                         unsigned size)
+{
+    TISecProxyState *s = opaque;
+    int thread_num = addr / 0x1000;
+    hwaddr off = addr % 0x1000;
+
+    int reg = off >> 2;    /* 32-bit register index */
+    int byte = off & 0x3;  /* byte offset within the 32-bit register */
+
+    struct TISecProxyThreadInfo *tinfo = &s->thread_info[thread_num];
+
+    /* First fetch the full little-endian 32-bit register. */
+    uint32_t reg_val = (uint32_t)tinfo->current_message[reg];
+    uint64_t ret = 0;
+
+    if (size == 1) {
+        ret = (reg_val >> (8 * byte)) & 0xffu;
+    } else if (size == 2) {
+        /*
+         * Odd halfword reads are rounded down. Guest drivers use aligned
+         * accesses, but this keeps byte-lane handling tolerant.
+         */
+        ret = (reg_val >> (8 * (byte & ~1))) & 0xffffu;
+    } else if (size == 4) {
+        ret = reg_val;
+    } else {
+        /* Shouldn't happen given .valid, but be defensive. */
+        ret = 0;
+    }
+
+    /* For inbound threads reset the message counter */
+    if (!tinfo->is_outbound && reg == SEC_PROXY_MAX_MSG - 1) {
+        trace_ti_sec_proxy_complete_read(
+            ti_sec_proxy_get_thread_channel_name(thread_num),
+            tinfo->num_messages);
+        tinfo->num_messages = 0;
+        qemu_irq_lower(s->irq_evt);
+    }
+    return ret;
+}
+
+static void ti_sec_proxy_write_target(void *opaque, hwaddr addr, uint64_t value,
+                                      unsigned size)
+{
+    TISecProxyState *s = opaque;
+    int thread_num = addr / 0x1000;
+    hwaddr off = addr % 0x1000;
+
+    int reg = off >> 2;    /* 32-bit register index */
+    int byte = off & 0x3;  /* byte offset within the 32-bit register */
+
+    struct TISecProxyThreadInfo *tinfo = &s->thread_info[thread_num];
+
+    if (reg >= 16) {
+        return;
+    }
+
+    uint32_t cur = (uint32_t)tinfo->current_message[reg];
+    uint32_t v32 = (uint32_t)value;
+
+    if (size == 1) {
+        uint32_t mask = 0xffu << (8 * byte);
+        cur = (cur & ~mask) | ((v32 & 0xffu) << (8 * byte));
+    } else if (size == 2) {
+        /* Round odd halfword writes down, same as in the read path. */
+        int hbyte = (byte & ~1);
+        uint32_t mask = 0xffffu << (8 * hbyte);
+        cur = (cur & ~mask) | ((v32 & 0xffffu) << (8 * hbyte));
+    } else if (size == 4) {
+        cur = v32;
+    } else {
+        return;
+    }
+
+    tinfo->current_message[reg] = cur;
+
+    /*
+     * The data-window commit point is the last register. Byte writes can
+     * hit it more than once while the last word is assembled.
+     */
+    if (reg == SEC_PROXY_MAX_MSG - 1) {
+        trace_ti_sec_proxy_complete_write(
+            ti_sec_proxy_get_thread_channel_name(thread_num),
+            tinfo->num_messages);
+
+        if (tinfo->cb) {
+            trace_ti_sec_proxy_announce_callback(
+                ti_sec_proxy_get_thread_channel_name(thread_num));
+            tinfo->cb(tinfo->cb_opaque, thread_num, &tinfo->current_message[1],
+                      SEC_PROXY_MAX_MSG);
+        }
+    }
+}
+
+static const MemoryRegionOps ti_sec_proxy_target_ops = {
+    .read = ti_sec_proxy_read_target,
+    .write = ti_sec_proxy_write_target,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+    },
+};
+
+static void ti_sec_proxy_init(Object *obj)
+{
+    TISecProxyState *s = TI_SEC_PROXY(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    s->reg_array = register_init_block32(DEVICE(obj), sec_proxy_mmrs_regs_info,
+                                         ARRAY_SIZE(sec_proxy_mmrs_regs_info),
+                                         s->regs_info, s->regs,
+                                         &ti_sec_proxy_mmr_ops, true, 0x100);
+    sysbus_init_mmio(sbd, &s->reg_array->mem);
+
+    memory_region_init_io(&s->iomem_scfg, OBJECT(s), &ti_sec_proxy_scfg_ops, s,
+                          "ti-sec-proxy-scfg", 0x80000);
+    sysbus_init_mmio(sbd, &s->iomem_scfg);
+
+    memory_region_init_io(&s->iomem_rt, OBJECT(s), &ti_sec_proxy_rt_ops, s,
+                          "ti-sec-proxy-rt", 0x80000);
+    sysbus_init_mmio(sbd, &s->iomem_rt);
+
+    memory_region_init_io(&s->iomem_target_data, OBJECT(s),
+                          &ti_sec_proxy_target_ops, s, "ti-sec-proxy-target",
+                          0x80000);
+    sysbus_init_mmio(sbd, &s->iomem_target_data);
+
+    sysbus_init_irq(sbd, &s->irq_evt);
+}
+
+static const TypeInfo ti_sec_proxy_info = {
+    .name = TYPE_TI_SEC_PROXY,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(TISecProxyState),
+    .class_init = ti_sec_proxy_class_init,
+    .instance_init = ti_sec_proxy_init,
+};
+
+static void ti_sec_proxy_types(void)
+{
+    type_register_static(&ti_sec_proxy_info);
+}
+
+type_init(ti_sec_proxy_types)
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index ea7cde021e..dfa2d04117 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -461,6 +461,14 @@ rat_enable_region(int idx, uint64_t size, uint64_t source, uint64_t dest) "Enabl
 rat_disable_region(int idx) "Disabling RAT Region %u"
 rat_read_entry(int entry, int rel_offset, uint64_t offset) "Reading Entry %i at offset %i: offset: 0x%"PRIx64
 
+# ti-sec-proxy.c
+ti_sec_proxy_read_scfg(const char *name, int reg, uint64_t addr) "thread: %s, reg: %i. read from SCFG addr 0x%" PRIx64
+ti_sec_proxy_write_scfg(const char *name, int reg, uint64_t addr, uint64_t value) "thread: %s, reg: %i. write 0x%" PRIx64 "0x%" PRIx64
+ti_sec_proxy_complete_read(const char *name, int num) "thread: %s completed read message %i. Resetting number of messages"
+ti_sec_proxy_complete_write(const char *name, int num) "thread: %s completed write message %i. Resetting number of messages"
+ti_sec_proxy_announce_callback(const char *name) "invoce callback for thread: %s"
+ti_sec_proxy_read_rt(const char *name, int reg, uint64_t addr) "thread: %s, reg: 0x%x, read from RT addr 0x%" PRIx64
+
 # ti-k3-trng.c
 ti_k3_trng_read(uint64_t addr, uint32_t val) "offset 0x%" PRIx64 " -> 0x%08x"
 ti_k3_trng_write(uint64_t addr, uint64_t val) "offset 0x%" PRIx64 " <- 0x%" PRIx64
diff --git a/include/hw/misc/ti-sec-proxy.h b/include/hw/misc/ti-sec-proxy.h
new file mode 100644
index 0000000000..d028242eff
--- /dev/null
+++ b/include/hw/misc/ti-sec-proxy.h
@@ -0,0 +1,108 @@
+/*
+ * TI K3 secure proxy
+ *
+ * Copyright (c) 2025 CMBLU Energy AG
+ * Author: Wadim Mueller <wafgo01@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef TI_SEC_PROXY_H
+#define TI_SEC_PROXY_H
+
+#include "hw/core/sysbus.h"
+#include "hw/core/register.h"
+#include "system/dma.h"
+#include "qom/object.h"
+
+#define TYPE_TI_SEC_PROXY "ti.sec-proxy"
+
+#define RMAX_TI_SEC_PROXY (3)
+
+OBJECT_DECLARE_SIMPLE_TYPE(TISecProxyState, TI_SEC_PROXY)
+
+typedef void (*TISecProxyMsgCb)(void *opaque,
+                               uint16_t thread_id,
+                               const uint32_t *words,
+                               size_t nwords);
+
+enum TISciThreadIds {
+    MAIN_0_R5_0_READ_RESPONSE_THREAD_ID = 0,
+    MAIN_0_R5_0_WRITE_THREAD_ID = 1,
+    MAIN_0_R5_1_READ_RESPONSE_THREAD_ID = 2,
+    MAIN_0_R5_1_WRITE_THREAD_ID = 3,
+    MAIN_0_R5_2_READ_RESPONSE_THREAD_ID = 4,
+    MAIN_0_R5_2_WRITE_THREAD_ID = 5,
+    MAIN_0_R5_3_READ_RESPONSE_THREAD_ID = 6,
+    MAIN_0_R5_3_WRITE_THREAD_ID = 7,
+    A53_0_READ_RESPONSE_THREAD_ID = 8,
+    A53_0_WRITE_THREAD_ID = 9,
+    A53_1_READ_RESPONSE_THREAD_ID = 10,
+    A53_1_WRITE_THREAD_ID = 11,
+    A53_2_READ_RESPONSE_THREAD_ID = 12,
+    A53_2_WRITE_THREAD_ID = 13,
+    A53_3_READ_RESPONSE_THREAD_ID = 14,
+    A53_3_WRITE_THREAD_ID = 15,
+    M4_0_READ_RESPONSE_THREAD_ID = 16,
+    M4_0_WRITE_THREAD_ID = 17,
+    MAIN_1_R5_0_READ_RESPONSE_THREAD_ID = 18,
+    MAIN_1_R5_0_WRITE_THREAD_ID = 19,
+    MAIN_1_R5_1_READ_RESPONSE_THREAD_ID = 20,
+    MAIN_1_R5_1_WRITE_THREAD_ID = 21,
+    MAIN_1_R5_2_READ_RESPONSE_THREAD_ID = 22,
+    MAIN_1_R5_2_WRITE_THREAD_ID = 23,
+    MAIN_1_R5_3_READ_RESPONSE_THREAD_ID = 24,
+    MAIN_1_R5_3_WRITE_THREAD_ID = 25,
+    A53_4_READ_RESPONSE_THREAD_ID = 26,
+    A53_4_WRITE_THREAD_ID = 27,
+    ICSSG_0_READ_RESPONSE_THREAD_ID = 28,
+    ICSSG_0_WRITE_THREAD_ID = 29,
+    ICSSG_1_READ_RESPONSE_THREAD_ID = 30,
+    ICSSG_1_WRITE_THREAD_ID = 31,
+    SEC_PROXY_THREAD_ID_MAX,
+};
+
+#define SEC_PROXY_MSG_MAX_WORDS (16)
+#define SEC_PROXY_MSG_FIFO_DEPTH (16)
+
+struct TISecProxyThreadInfo {
+    uint8_t thread_id;
+    uint8_t num_messages;
+    uint32_t current_message[SEC_PROXY_MSG_MAX_WORDS];
+    bool is_outbound;
+    /* Callback invoked on commit (outbound only) */
+    TISecProxyMsgCb cb;
+    void *cb_opaque;
+};
+
+struct TISecProxyState {
+    SysBusDevice parent_obj;
+    MemoryRegion iomem_scfg;
+    MemoryRegion iomem_rt;
+    MemoryRegion iomem_target_data;
+    RegisterInfoArray *reg_array;
+    qemu_irq irq_evt;
+    uint32_t regs[RMAX_TI_SEC_PROXY];
+    RegisterInfo regs_info[RMAX_TI_SEC_PROXY];
+    struct TISecProxyThreadInfo thread_info[SEC_PROXY_THREAD_ID_MAX];
+    uint32_t msg_words;
+};
+
+
+/* Backend API used by ti-dmsc, resp. other consumers */
+void ti_sec_proxy_register_msg_cb(TISecProxyState *sp,
+                                  uint16_t thread_id,
+                                  TISecProxyMsgCb cb,
+                                  void *opaque);
+
+size_t ti_sec_proxy_push_msg(TISecProxyState *sp, uint16_t thread_id,
+                             const uint32_t *words, size_t nbytes);
+
+uint32_t ti_sec_proxy_get_msg_words(TISecProxyState *sp);
+
+/*
+ * Clear an outbound thread counter before requeueing unsolicited messages.
+ * push_msg() only increments it; reads clear only inbound threads.
+ */
+void ti_sec_proxy_reset_thread_count(TISecProxyState *sp, uint16_t thread_id);
+#endif
-- 
2.43.0



  parent reply	other threads:[~2026-08-20 12:51 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-20 12:48 [RFC PATCH v2 00/14] hw/arm: add TI AM64x SoC and am64-virt machine Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 01/14] hw/i2c/omap_i2c: add a dedicated CONFIG_OMAP_I2C symbol Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 02/14] hw/i2c/omap_i2c: implement soft reset and NACK reporting Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 03/14] hw/sd/sdhci: complete non-interrupt ADMA descriptor chains in one pass Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 04/14] hw/char: add TI AM64x UART model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 05/14] hw/timer: add TI K3 DMTimer model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 06/14] hw/misc: add TI K3 CTRL_MMR, GTC, DDRSS, SDHCI PHY and TRNG models Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 07/14] hw/misc: add TI RAT (region address translation) model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 08/14] hw/misc: add TI mailbox (IPC) model Wadim Mueller
2026-08-20 12:48 ` Wadim Mueller [this message]
2026-08-20 12:48 ` [RFC PATCH v2 10/14] hw/misc: add TI DMSC (TI-SCI system controller) model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 11/14] hw/arm: add TI K3 combined boot image parser Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 12/14] hw/arm: add TI AM64x SoC model Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 13/14] hw/arm: add the am64-virt machine Wadim Mueller
2026-08-20 12:48 ` [RFC PATCH v2 14/14] tests: add AM64x unit, qtest and functional tests Wadim Mueller
2026-08-20 16:25   ` Alex Bennée
2026-08-22 21:04     ` Wadim Mueller
2026-08-21 10:26 ` [RFC PATCH v2 00/14] hw/arm: add TI AM64x SoC and am64-virt machine Alex Bennée
2026-08-22 21:06   ` Wadim Mueller
2026-08-21 16:35 ` Nick Huang
2026-08-22 21:07   ` Wadim Mueller
2026-08-22  5:22 ` Bin Meng
2026-08-22 21:13   ` Wadim Mueller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260820124824.618671-10-wafgo01@gmail.com \
    --to=wafgo01@gmail.com \
    --cc=bmeng.cn@gmail.com \
    --cc=farosas@suse.de \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=philmd@mailo.com \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox