From nobody Mon May 25 13:48:45 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1777952904; cv=none; d=zohomail.com; s=zohoarc; b=VxiYxL8xmhgraXMiyFDLFiwhgKEvmEMzit9uhMgR0Cwh2MUuU/TPHdr2IzX/Pn+hzhephJoI11pxajSGTHSXeL/3FqvsIX6c98pD6kqpwx/ffb9gblC3Adb92WpOkvFoOhrHYqGSrCbnJaBihpSHKXm+ld18VHtcw/EY8PRKjHc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1777952904; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=2l7x96XHacI/TVqGPf23sitFitnDedFeCyrqvsS24Gk=; b=KWbbY3KV38FMqAMVI0mL2hdollFxMsb6Phlf599b7uygiDpKwFhv1PcfzYRqpktRqfDNOKSc9XoqwQJO2TUVwh8lX57BW4F8I4Rc1XqNyuPgNW0fvDJbIwiXmM/baCfJBzTIPYObCyNo6Yw6gKg8M4I0VPORpfvQOAcPSs1TLhY= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1777952904053366.51870801329835; Mon, 4 May 2026 20:48:24 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wK6ke-000402-G5; Mon, 04 May 2026 23:47:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wK6kb-0003zB-6P; Mon, 04 May 2026 23:47:13 -0400 Received: from mail.aspeedtech.com ([211.20.114.72] helo=twmbx01.aspeedtech.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wK6kX-00029X-NW; Mon, 04 May 2026 23:47:12 -0400 Received: from TWMBX01.aspeed.com (192.168.0.62) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.10; Tue, 5 May 2026 11:46:55 +0800 Received: from mail.aspeedtech.com (192.168.10.10) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server id 15.2.1748.10 via Frontend Transport; Tue, 5 May 2026 11:46:55 +0800 To: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= , Peter Maydell , Troy Lee , Jamin Lin , Kane Chen , "Andrew Jeffery" , Joel Stanley , Pierrick Bouvier , "open list:All patches CC here" , "open list:ASPEED BMCs" CC: , , , Subject: [RFC PATCH v2 1/1] hw/arm: aspeed: PoC integration for Caliptra Root of Trust Date: Tue, 5 May 2026 11:46:54 +0800 Message-ID: <20260505034654.815746-2-steven_lee@aspeedtech.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260505034654.815746-1-steven_lee@aspeedtech.com> References: <20260505034654.815746-1-steven_lee@aspeedtech.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=211.20.114.72; envelope-from=steven_lee@aspeedtech.com; helo=twmbx01.aspeedtech.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: Steven Lee From: Steven Lee via qemu development Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1777952906942154100 Content-Type: text/plain; charset="utf-8" ast27x0 integrates a Caliptra Root of Trust core, but QEMU does not currently have an agreed model for ASPEED Caliptra emulation. This patch adds an ASPEED-specific sysbus device that exposes the Caliptra mailbox/SOC-IFC MMIO window and forwards guest register accesses to an external `caliptra-server` backend over a Unix socket. This allows evaluation of the QEMU/Caliptra integration shape without pulling the upstream `caliptra-sw` hw-model into the QEMU build. The reference `caliptra-server` implementation used in this RFC is available at: https://github.com/stevenlee7189/caliptra-server The device provides a 128 KiB MMIO window at 0x14c60000, matching the ast27x0 bootmcu Caliptra mailbox node, and maps it onto the backend APB register space. https://github.com/AspeedTech-BMC/zephyr/blob/v00.03.07/dts/riscv/aspeed/as= t27xx.dtsi#L310-L312 On the real ast27x0, Caliptra bring-up and secure-boot orchestration are handled by bootmcu; CA35 is not involved in that path. This patch uses the CA35-visible Caliptra MMIO window as an initial integration point to validate the socket-backed external backend approach, not to model the final boot architecture. This is an RFC PoC only. It assumes the backend is already running, does not implement boot/reset handshaking or migration support, and uses a minimal wire protocol designed to be replaced with a standardized IPC scheme. Signed-off-by: Steven Lee --- MAINTAINERS | 2 + docs/system/arm/aspeed.rst | 35 +++ include/hw/arm/aspeed_caliptra_emu.h | 29 +++ hw/arm/aspeed_ast27x0-fc.c | 55 +++++ hw/arm/aspeed_caliptra_emu.c | 338 +++++++++++++++++++++++++++ hw/arm/meson.build | 1 + 6 files changed, 460 insertions(+) create mode 100644 include/hw/arm/aspeed_caliptra_emu.h create mode 100644 hw/arm/aspeed_caliptra_emu.c diff --git a/MAINTAINERS b/MAINTAINERS index afa178c5cc..eb01ab4c11 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1263,6 +1263,8 @@ L: qemu-arm@nongnu.org S: Maintained F: hw/*/*aspeed* F: include/hw/*/*aspeed* +F: hw/arm/aspeed_caliptra_emu.c +F: include/hw/arm/aspeed_caliptra_emu.h F: hw/net/ftgmac100.c F: include/hw/net/ftgmac100.h F: docs/system/arm/aspeed.rst diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst index d0054a7dbb..e0f511f098 100644 --- a/docs/system/arm/aspeed.rst +++ b/docs/system/arm/aspeed.rst @@ -423,6 +423,41 @@ Steps to boot the AST2700fc machine: -snapshot \ -S -nographic =20 +The ``ast2700fc`` machine can also forward CA35 accesses to the on-die +Caliptra Root-of-Trust core to an external Caliptra backend over a Unix +socket. The backend (``caliptra-server``) is launched independently with +the Caliptra ROM and firmware bundle, boots the Caliptra emulated model +to runtime-ready, then listens on a Unix socket. QEMU connects to that +socket from the device's ``realize()`` and forwards every CA35 read/write +in the Caliptra MMIO window as an APB transaction on the socket. + +The socket path is configured with the ``caliptra-socket`` machine +property. If the property is not set, no Caliptra backend is attached +and the Caliptra MMIO window is left unmapped. + +For example, to run Caliptra firmware from ``caliptra-sw``: + +.. code-block:: bash + + # Terminal 1: start caliptra-server with the ROM/firmware images. + # It boots the model to runtime-ready before opening the socket. + $ caliptra-server \ + --socket /tmp/caliptra.sock \ + --rom images/caliptra-rom-with-log.bin \ + --firmware images/caliptra-fw.bundle + + # Terminal 2: launch QEMU; the CA35 starts running immediately. + $ qemu-system-aarch64 \ + -M ast2700fc,caliptra-socket=3D/tmp/caliptra.sock \ + ... + +There is no boot handshake between QEMU and the backend: by the time the +device's ``realize()`` runs, ``caliptra-server`` is already at +runtime-ready, so the CA35 is not held in reset. The wire protocol +between QEMU and the backend is APB-level: ``APB_READ`` / ``APB_WRITE`` +requests from QEMU are answered by ``APB_RDATA`` / ``APB_WACK`` from the +backend. This protocol is RFC-stage and may change. + After launching QEMU, serial devices will be automatically redirected. Example output: =20 diff --git a/include/hw/arm/aspeed_caliptra_emu.h b/include/hw/arm/aspeed_c= aliptra_emu.h new file mode 100644 index 0000000000..a4b70bbe18 --- /dev/null +++ b/include/hw/arm/aspeed_caliptra_emu.h @@ -0,0 +1,29 @@ +/* + * ASPEED Caliptra emulator backend + * + * Copyright (C) 2026 ASPEED Technology Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef ASPEED_CALIPTRA_EMU_H +#define ASPEED_CALIPTRA_EMU_H + +#define TYPE_ASPEED_CALIPTRA_EMU "aspeed-caliptra-emu" + +/* + * RFC/PoC integration hook only. + * + * This address is used by the current QEMU experiment to attach the + * external Caliptra backend to the AST2700fc machine. It must not be + * interpreted as the final functional interface used by real hardware: + * early Caliptra interaction is bootmcu-owned, and CA35 does not use + * this path for functional access to the Caliptra core. + * + * The 128 KiB region covers: + * +0x00000 mailbox CSR (caliptra APB 0x30020000) + * +0x10000 SOC IFC (caliptra APB 0x30030000) + */ +#define ASPEED_CALIPTRA_MMIO_BASE 0x14c60000ULL + +#endif /* ASPEED_CALIPTRA_EMU_H */ diff --git a/hw/arm/aspeed_ast27x0-fc.c b/hw/arm/aspeed_ast27x0-fc.c index 5eb6680da9..ac452a5a2a 100644 --- a/hw/arm/aspeed_ast27x0-fc.c +++ b/hw/arm/aspeed_ast27x0-fc.c @@ -22,6 +22,8 @@ #include "hw/arm/boot.h" #include "hw/block/flash.h" #include "hw/arm/aspeed_coprocessor.h" +#include "hw/arm/aspeed_caliptra_emu.h" +#include "hw/core/sysbus.h" #include "hw/arm/machines-qom.h" =20 #define TYPE_AST2700FC MACHINE_TYPE_NAME("ast2700fc") @@ -34,6 +36,8 @@ static struct arm_boot_info ast2700fc_board_info =3D { struct Ast2700FCState { MachineState parent_obj; =20 + char *caliptra_socket; + MemoryRegion ca35_memory; MemoryRegion ca35_dram; MemoryRegion ca35_boot_rom; @@ -198,9 +202,51 @@ static bool ast2700fc_tsp_init(MachineState *machine, = Error **errp) =20 static void ast2700fc_init(MachineState *machine) { + Ast2700FCState *s =3D AST2700FC(machine); + ast2700fc_ca35_init(machine, &error_abort); ast2700fc_ssp_init(machine, &error_abort); ast2700fc_tsp_init(machine, &error_abort); + + if (s->caliptra_socket) { + SysBusDevice *sbd; + DeviceState *dev =3D qdev_new(TYPE_ASPEED_CALIPTRA_EMU); + + qdev_prop_set_string(dev, "socket-path", s->caliptra_socket); + sbd =3D SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(sbd, &error_abort); + /* + * Map the Caliptra APB MMIO region into the CA35 address space. + * 0x14000000..0x14FFFFFF. + */ + memory_region_add_subregion_overlap(&s->ca35_memory, + ASPEED_CALIPTRA_MMIO_BASE, + sysbus_mmio_get_region(sbd, 0), + 1); + } +} + +static char *ast2700fc_get_caliptra_socket(Object *obj, Error **errp) +{ + Ast2700FCState *s =3D AST2700FC(obj); + + return g_strdup(s->caliptra_socket ? s->caliptra_socket : ""); +} + +static void ast2700fc_set_caliptra_socket(Object *obj, const char *value, + Error **errp) +{ + Ast2700FCState *s =3D AST2700FC(obj); + + g_free(s->caliptra_socket); + s->caliptra_socket =3D g_strdup(value); +} + +static void ast2700fc_instance_finalize(Object *obj) +{ + Ast2700FCState *s =3D AST2700FC(obj); + + g_free(s->caliptra_socket); } =20 static void ast2700fc_class_init(ObjectClass *oc, const void *data) @@ -212,6 +258,14 @@ static void ast2700fc_class_init(ObjectClass *oc, cons= t void *data) mc->no_floppy =3D 1; mc->no_cdrom =3D 1; mc->min_cpus =3D mc->max_cpus =3D mc->default_cpus =3D 6; + + object_class_property_add_str(oc, "caliptra-socket", + ast2700fc_get_caliptra_socket, + ast2700fc_set_caliptra_socket); + object_class_property_set_description(oc, "caliptra-socket", + "Unix socket path for the external Caliptra backend (caliptra-serv= er). " + "caliptra-server is launched independently with the ROM/firmware i= mages " + "and must be listening before QEMU is started."); } =20 static const TypeInfo ast2700fc_types[] =3D { @@ -220,6 +274,7 @@ static const TypeInfo ast2700fc_types[] =3D { .parent =3D TYPE_MACHINE, .class_init =3D ast2700fc_class_init, .instance_size =3D sizeof(Ast2700FCState), + .instance_finalize =3D ast2700fc_instance_finalize, .interfaces =3D aarch64_machine_interfaces, }, }; diff --git a/hw/arm/aspeed_caliptra_emu.c b/hw/arm/aspeed_caliptra_emu.c new file mode 100644 index 0000000000..e91ca6e83d --- /dev/null +++ b/hw/arm/aspeed_caliptra_emu.c @@ -0,0 +1,338 @@ +/* + * ASPEED Caliptra external backend (PoC) + * + * Forwards CA35 MMIO accesses on the Caliptra APB window to an external + * caliptra-server process over a Unix socket. caliptra-server is expected + * to be started independently with the Caliptra ROM and firmware bundle + * and to be listening on socket-path before QEMU is launched. + * + * Copyright (C) 2026 ASPEED Technology Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/arm/aspeed_caliptra_emu.h" +#include "hw/core/qdev-properties.h" +#include "hw/core/sysbus.h" +#include "io/channel.h" +#include "io/channel-socket.h" +#include "qapi/error.h" +#include "qemu/bswap.h" +#include "qemu/error-report.h" +#include "qemu/main-loop.h" +#include "qemu/units.h" +#include "system/memory.h" + +/* + * Wire protocol (little-endian). Symmetric with caliptra-server. + * + * Header (12 bytes): + * u32 magic -- 0x43505452 ("CPTR") + * u16 version -- 1 + * u16 command + * u32 payload_len + * + * Commands (after the connection is established): + * APB_READ QEMU -> server {u32 apb_addr} + * APB_RDATA server -> QEMU {u32 data} + * APB_WRITE QEMU -> server {u32 apb_addr, u32 data} + * APB_WACK server -> QEMU {} (empty payload) + * + * There is no boot handshake: caliptra-server boots its emulated model to + * runtime-ready before listen()/accept(), and QEMU just connects and star= ts + * forwarding APB traffic. + */ +#define CALIPTRA_SOCKET_MAGIC 0x43505452 +#define CALIPTRA_SOCKET_VERSION 1 +#define CALIPTRA_SOCKET_CMD_APB_READ 3 +#define CALIPTRA_SOCKET_CMD_APB_RDATA 4 +#define CALIPTRA_SOCKET_CMD_APB_WRITE 5 +#define CALIPTRA_SOCKET_CMD_APB_WACK 6 +#define CALIPTRA_SOCKET_MAX_PAYLOAD (4 * MiB) + +/* + * Base address of the Caliptra APB register space as seen by caliptra-hw-= model. + * Mailbox CSR starts at 0x30020000; SOC IFC starts at 0x30030000. + * Total mapped size: 0x20000 (128 KiB). + * + * MMIO offset from ASPEED_CALIPTRA_MMIO_BASE in the CA35 address space is + * mapped 1:1 to APB address CALIPTRA_APB_BASE + offset. + */ +#define CALIPTRA_APB_BASE 0x30020000 +#define CALIPTRA_MMIO_SIZE 0x20000 + +typedef struct QEMU_PACKED CaliptraSocketHeader { + uint32_t magic; + uint16_t version; + uint16_t command; + uint32_t payload_len; +} CaliptraSocketHeader; + +OBJECT_DECLARE_SIMPLE_TYPE(AspeedCaliptraEmuState, ASPEED_CALIPTRA_EMU) + +struct AspeedCaliptraEmuState { + SysBusDevice parent_obj; + char *socket_path; + QIOChannelSocket *sioc; + QemuMutex ioc_mutex; + MemoryRegion mmio; +}; + +static bool caliptra_socket_write_msg(QIOChannel *ioc, uint16_t command, + const uint8_t *payload, size_t len, + Error **errp) +{ + CaliptraSocketHeader hdr =3D { + .magic =3D cpu_to_le32(CALIPTRA_SOCKET_MAGIC), + .version =3D cpu_to_le16(CALIPTRA_SOCKET_VERSION), + .command =3D cpu_to_le16(command), + .payload_len =3D cpu_to_le32(len), + }; + + if (qio_channel_write_all(ioc, (const char *)&hdr, sizeof(hdr), errp) = < 0) { + return false; + } + if (len && + qio_channel_write_all(ioc, (const char *)payload, len, errp) < 0) { + return false; + } + return true; +} + +static bool caliptra_socket_read_header(QIOChannel *ioc, uint16_t command, + CaliptraSocketHeader *hdr, + Error **errp) +{ + if (qio_channel_read_all(ioc, (char *)hdr, sizeof(*hdr), errp) < 0) { + return false; + } + + hdr->magic =3D le32_to_cpu(hdr->magic); + hdr->version =3D le16_to_cpu(hdr->version); + hdr->command =3D le16_to_cpu(hdr->command); + hdr->payload_len =3D le32_to_cpu(hdr->payload_len); + + if (hdr->magic !=3D CALIPTRA_SOCKET_MAGIC) { + error_setg(errp, "Invalid Caliptra socket magic 0x%08x", hdr->magi= c); + return false; + } + if (hdr->version !=3D CALIPTRA_SOCKET_VERSION) { + error_setg(errp, "Unsupported Caliptra socket version %u", + hdr->version); + return false; + } + if (hdr->command !=3D command) { + error_setg(errp, "Unexpected Caliptra socket command %u (expected = %u)", + hdr->command, command); + return false; + } + if (hdr->payload_len > CALIPTRA_SOCKET_MAX_PAYLOAD) { + error_setg(errp, "Caliptra socket response too large: %u bytes", + hdr->payload_len); + return false; + } + return true; +} + +static bool caliptra_apb_send_recv(AspeedCaliptraEmuState *s, + uint16_t req_cmd, uint16_t rsp_cmd, + const uint8_t *req_payload, size_t req_= len, + uint8_t *rsp_buf, size_t rsp_len, + Error **errp) +{ + CaliptraSocketHeader hdr; + QIOChannel *ioc; + + if (!s->sioc) { + error_setg(errp, "Caliptra APB access with no backend connection"); + return false; + } + ioc =3D QIO_CHANNEL(s->sioc); + + if (!caliptra_socket_write_msg(ioc, req_cmd, req_payload, req_len, err= p)) { + return false; + } + if (!caliptra_socket_read_header(ioc, rsp_cmd, &hdr, errp)) { + return false; + } + + if (rsp_len) { + if (hdr.payload_len < rsp_len) { + error_setg(errp, + "Caliptra short response for cmd %u: got %u, expect= ed %zu", + rsp_cmd, hdr.payload_len, rsp_len); + return false; + } + if (qio_channel_read_all(ioc, (char *)rsp_buf, rsp_len, errp) < 0)= { + return false; + } + /* Discard any trailing bytes. */ + if (hdr.payload_len > rsp_len) { + g_autofree uint8_t *extra =3D g_malloc(hdr.payload_len - rsp_l= en); + if (qio_channel_read_all(ioc, (char *)extra, + hdr.payload_len - rsp_len, errp) < 0)= { + return false; + } + } + } else if (hdr.payload_len) { + g_autofree uint8_t *extra =3D g_malloc(hdr.payload_len); + if (qio_channel_read_all(ioc, (char *)extra, + hdr.payload_len, errp) < 0) { + return false; + } + } + return true; +} + +static uint64_t caliptra_mmio_read(void *opaque, hwaddr offset, unsigned s= ize) +{ + AspeedCaliptraEmuState *s =3D opaque; + uint8_t req[4], rsp[4] =3D {}; + Error *err =3D NULL; + + stl_le_p(req, CALIPTRA_APB_BASE + (uint32_t)offset); + + /* + * Release the BQL before blocking on the socket so the QEMU event loop + * stays responsive while caliptra-server processes the request. + */ + bql_unlock(); + qemu_mutex_lock(&s->ioc_mutex); + caliptra_apb_send_recv(s, + CALIPTRA_SOCKET_CMD_APB_READ, + CALIPTRA_SOCKET_CMD_APB_RDATA, + req, sizeof(req), + rsp, sizeof(rsp), &err); + qemu_mutex_unlock(&s->ioc_mutex); + bql_lock(); + + if (err) { + error_report("caliptra APB read 0x%08" PRIx32 ": %s", + CALIPTRA_APB_BASE + (uint32_t)offset, + error_get_pretty(err)); + error_free(err); + return 0xdeadbeef; + } + return ldl_le_p(rsp); +} + +static void caliptra_mmio_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + AspeedCaliptraEmuState *s =3D opaque; + uint8_t req[8]; + Error *err =3D NULL; + + stl_le_p(req + 0, CALIPTRA_APB_BASE + (uint32_t)offset); + stl_le_p(req + 4, (uint32_t)value); + + bql_unlock(); + qemu_mutex_lock(&s->ioc_mutex); + caliptra_apb_send_recv(s, + CALIPTRA_SOCKET_CMD_APB_WRITE, + CALIPTRA_SOCKET_CMD_APB_WACK, + req, sizeof(req), + NULL, 0, &err); + qemu_mutex_unlock(&s->ioc_mutex); + bql_lock(); + + if (err) { + error_report("caliptra APB write 0x%08" PRIx32 " =3D 0x%08" PRIx32= ": %s", + CALIPTRA_APB_BASE + (uint32_t)offset, (uint32_t)value, + error_get_pretty(err)); + error_free(err); + } +} + +static const MemoryRegionOps caliptra_mmio_ops =3D { + .read =3D caliptra_mmio_read, + .write =3D caliptra_mmio_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + }, +}; + +static void aspeed_caliptra_emu_realize(DeviceState *dev, Error **errp) +{ + AspeedCaliptraEmuState *s =3D ASPEED_CALIPTRA_EMU(dev); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(dev); + SocketAddress addr; + QIOChannelSocket *sioc; + + if (!s->socket_path || !s->socket_path[0]) { + error_setg(errp, "caliptra-emu: socket-path must be set"); + return; + } + + memory_region_init_io(&s->mmio, OBJECT(s), &caliptra_mmio_ops, s, + "caliptra-apb", CALIPTRA_MMIO_SIZE); + sysbus_init_mmio(sbd, &s->mmio); + + /* + * Connect to caliptra-server synchronously. The server is expected t= o be + * already listening with the Caliptra ROM/firmware booted to runtime-= ready. + */ + memset(&addr, 0, sizeof(addr)); + addr.type =3D SOCKET_ADDRESS_TYPE_UNIX; + addr.u.q_unix.path =3D s->socket_path; + + sioc =3D qio_channel_socket_new(); + if (qio_channel_socket_connect_sync(sioc, &addr, errp) < 0) { + object_unref(OBJECT(sioc)); + return; + } + if (!qio_channel_set_blocking(QIO_CHANNEL(sioc), true, errp)) { + object_unref(OBJECT(sioc)); + return; + } + s->sioc =3D sioc; +} + +static void aspeed_caliptra_emu_instance_init(Object *obj) +{ + AspeedCaliptraEmuState *s =3D ASPEED_CALIPTRA_EMU(obj); + + qemu_mutex_init(&s->ioc_mutex); +} + +static void aspeed_caliptra_emu_finalize(Object *obj) +{ + AspeedCaliptraEmuState *s =3D ASPEED_CALIPTRA_EMU(obj); + + if (s->sioc) { + object_unref(OBJECT(s->sioc)); + } + qemu_mutex_destroy(&s->ioc_mutex); +} + +static const Property aspeed_caliptra_emu_props[] =3D { + DEFINE_PROP_STRING("socket-path", AspeedCaliptraEmuState, socket_path), +}; + +static void aspeed_caliptra_emu_class_init(ObjectClass *oc, const void *da= ta) +{ + DeviceClass *dc =3D DEVICE_CLASS(oc); + + dc->realize =3D aspeed_caliptra_emu_realize; + dc->desc =3D "ASPEED Caliptra external backend (PoC)"; + device_class_set_props(dc, aspeed_caliptra_emu_props); + set_bit(DEVICE_CATEGORY_MISC, dc->categories); +} + +static const TypeInfo aspeed_caliptra_emu_type_info =3D { + .name =3D TYPE_ASPEED_CALIPTRA_EMU, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(AspeedCaliptraEmuState), + .instance_init =3D aspeed_caliptra_emu_instance_init, + .instance_finalize =3D aspeed_caliptra_emu_finalize, + .class_init =3D aspeed_caliptra_emu_class_init, +}; + +static void aspeed_caliptra_emu_register_type(void) +{ + type_register_static(&aspeed_caliptra_emu_type_info); +} +type_init(aspeed_caliptra_emu_register_type) diff --git a/hw/arm/meson.build b/hw/arm/meson.build index 84b8ec5fb5..25e2b58284 100644 --- a/hw/arm/meson.build +++ b/hw/arm/meson.build @@ -72,6 +72,7 @@ arm_common_ss.add(when: ['CONFIG_ASPEED_SOC', 'TARGET_AAR= CH64'], if_true: files( 'aspeed_ast1700.c', 'aspeed_ast27x0.c', 'aspeed_ast27x0_evb.c', + 'aspeed_caliptra_emu.c', 'aspeed_ast27x0-fc.c', 'aspeed_ast27x0-ssp.c', 'aspeed_ast27x0-tsp.c', --=20 2.43.0