From nobody Mon Jun 8 08:31:44 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=1780281185; cv=none; d=zohomail.com; s=zohoarc; b=JoECQ7B0SRVpfHlj7DpylQTM7eqb1/K2/X29P0spuO6aXk5T3p9R6TNZZxeaN31EUK2Zb/LUeqZDYijphI8jRxY51nRIA0tHsi8xktqtLYZOwae0kUFwYbEA+P4CTOI+e7mv9vrGN1046sN+MArpi6V/O+GSl4e9XJXaL1H1fx8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1780281185; 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=3TBsUfwmemwQZHXKywM1wtnn7hiv4TzzDjeX5OGa+do=; b=ayjtKvIwnM6n4l3LtWq84Z23yZYSQ3lgVWHbzd/r9jzRqwBNmri9r52qLJ7GoBFsgz+btk7n80TBVmUNFo9tATF2SgtaLmn14cutHQ7PzkPqT68eeth3tRNQH37RssYG2o4Pt2rKE8I/e64qxUccJy3KOd0QEJ562GWRn7Cdq28= 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 1780281185610249.9471266148838; Sun, 31 May 2026 19:33:05 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wTsRh-0007J3-Ae; Sun, 31 May 2026 22:32:05 -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 1wTsRg-0007Ia-98; Sun, 31 May 2026 22:32:04 -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 1wTsRe-0004V7-6Y; Sun, 31 May 2026 22:32:04 -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; Mon, 1 Jun 2026 10:31:49 +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; Mon, 1 Jun 2026 10:31:49 +0800 To: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= , Peter Maydell , Troy Lee , Jamin Lin , Kane Chen , "Andrew Jeffery" , Joel Stanley , Pierrick Bouvier , Fabiano Rosas , Laurent Vivier , Paolo Bonzini , "open list:All patches CC here" , "open list:ASPEED BMCs" CC: , , , Subject: [PATCH 1/6] hw/misc/aspeed_scu: Add AST1040 SCU model Date: Mon, 1 Jun 2026 10:31:42 +0800 Message-ID: <20260601023149.2309299-2-steven_lee@aspeedtech.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260601023149.2309299-1-steven_lee@aspeedtech.com> References: <20260601023149.2309299-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: 1780281189552154100 Content-Type: text/plain; charset="utf-8" Add an AST1040 variant of the ASPEED SCU with reset values, APB clock calcu= lation, clock-stop handling, and CPTRA page-select registers. Expose the Caliptra page aperture as a QOM link so the SoC model can wire t= he remap window without callbacks. Signed-off-by: Steven Lee --- include/hw/misc/aspeed_scu.h | 10 ++ hw/misc/aspeed_scu.c | 251 +++++++++++++++++++++++++++++++++++ hw/misc/trace-events | 2 + 3 files changed, 263 insertions(+) diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h index c30940ab76..6445ae5cf4 100644 --- a/include/hw/misc/aspeed_scu.h +++ b/include/hw/misc/aspeed_scu.h @@ -22,6 +22,7 @@ OBJECT_DECLARE_TYPE(AspeedSCUState, AspeedSCUClass, ASPEE= D_SCU) #define TYPE_ASPEED_2700_SCU TYPE_ASPEED_SCU "-ast2700" #define TYPE_ASPEED_2700_SCUIO TYPE_ASPEED_SCU "io" "-ast2700" #define TYPE_ASPEED_1030_SCU TYPE_ASPEED_SCU "-ast1030" +#define TYPE_ASPEED_1040_SCU TYPE_ASPEED_SCU "-ast1040" =20 #define ASPEED_SCU_NR_REGS (0x1A8 >> 2) #define ASPEED_AST2600_SCU_NR_REGS (0xE20 >> 2) @@ -39,6 +40,15 @@ struct AspeedSCUState { uint32_t hw_strap1; uint32_t hw_strap2; uint32_t hw_prot_key; + + /* + * AST1040 only: alias region (the Caliptra MCI page aperture) whose + * target offset is selected by SCU_CPTRA_PAGE_REG0, linked in by the = SoC. + * cptra_page_window_base is its base in the address map, used to reje= ct a + * self-referential remap. + */ + MemoryRegion *cptra_page_window; + uint64_t cptra_page_window_base; }; =20 #define AST2400_A1_SILICON_REV 0x02010303U diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c index 19da6c075f..028677880f 100644 --- a/hw/misc/aspeed_scu.c +++ b/hw/misc/aspeed_scu.c @@ -17,6 +17,7 @@ #include "qapi/visitor.h" #include "qemu/bitops.h" #include "qemu/log.h" +#include "qemu/range.h" #include "qemu/guest-random.h" #include "qemu/module.h" #include "trace.h" @@ -179,6 +180,41 @@ #define AST2700_SCUIO_CLK_DUTY_MEAS_RST TO_REG(0x388) #define AST2700_SCUIO_FREQ_CNT_CTL TO_REG(0x3A0) =20 +/* AST1040 SCU */ +#define AST1040_SILICON_REV TO_REG(0x00) +#define AST1040_HW_STRAP1 TO_REG(0x10) +#define AST1040_HW_STRAP1_CLR TO_REG(0x14) +#define AST1040_HW_STRAP1_LOCK TO_REG(0x20) +#define AST1040_HW_STRAP1_SEC1 TO_REG(0x24) +#define AST1040_SCU_CPTRA_PAGE_REG0 TO_REG(0x120) +#define AST1040_SCU_CPTRA_PAGE_REG1 TO_REG(0x124) +#define AST1040_SCU_CPTRA_PAGE_REG2 TO_REG(0x128) +#define AST1040_SCU_CPTRA_PAGE_REG3 TO_REG(0x12C) +#define AST1040_SCU_CPTRA_PAGE_REG4 TO_REG(0x130) +#define AST1040_SCU_CPTRA_PAGE_REG5 TO_REG(0x134) +#define AST1040_SCU_CLK_STOP_CTL_1 TO_REG(0x240) +#define AST1040_SCU_CLK_STOP_CLR_1 TO_REG(0x244) +#define AST1040_SCU_CLK_STOP_CTL_2 TO_REG(0x260) +#define AST1040_SCU_CLK_STOP_CLR_2 TO_REG(0x264) +#define AST1040_SCU_CLK_SEL_1 TO_REG(0x280) +#define AST1040_SCU_CLK_SEL_2 TO_REG(0x284) +#define AST1040_SCU_HPLL_PARAM TO_REG(0x300) +#define AST1040_SCU_HPLL_EXT_PARAM TO_REG(0x304) +#define AST1040_SCU_APLL_PARAM TO_REG(0x310) +#define AST1040_SCU_APLL_EXT_PARAM TO_REG(0x314) +#define AST1040_SCU_DPLL_PARAM TO_REG(0x320) +#define AST1040_SCU_DPLL_EXT_PARAM TO_REG(0x324) +#define AST1040_SCU_DPLL_PARAM_READ TO_REG(0x328) +#define AST1040_SCU_DPLL_EXT_PARAM_READ TO_REG(0x32c) +#define AST1040_SCU_UARTCLK_GEN TO_REG(0x330) +#define AST1040_SCU_HUARTCLK_GEN TO_REG(0x334) +#define AST1040_SCU_CLK_DUTY_MEAS_RST TO_REG(0x388) +#define AST1040_SCU_FREQ_CNT_CTL TO_REG(0x3A0) +#define AST1040_SCU_CLK_GET_PCLK_DIV(x) (((x) >> 18) & 0x7) + +#define ASPEED_AST1040_SCU_NR_REGS (0xE20 >> 2) +#define AST1040_SCU_CPTRA_PAGE_SIZE 0x1000 + #define SCU_IO_REGION_SIZE 0x1000 =20 static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] =3D { @@ -1165,6 +1201,220 @@ static const TypeInfo aspeed_1030_scu_info =3D { .class_init =3D aspeed_1030_scu_class_init, }; =20 +/* AST1040 SCU */ + +static void aspeed_ast1040_scu_update_cptra_page(AspeedSCUState *s) +{ + hwaddr page_base =3D s->regs[AST1040_SCU_CPTRA_PAGE_REG0] & + ~(hwaddr)(AST1040_SCU_CPTRA_PAGE_SIZE - 1); + + if (!s->cptra_page_window) { + return; + } + + if (ranges_overlap(page_base, AST1040_SCU_CPTRA_PAGE_SIZE, + s->cptra_page_window_base, + AST1040_SCU_CPTRA_PAGE_SIZE)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: refusing self-referential remap to 0x%" HWADDR_= PRIx + "\n", __func__, page_base); + memory_region_set_enabled(s->cptra_page_window, false); + return; + } + + memory_region_set_alias_offset(s->cptra_page_window, page_base); + memory_region_set_enabled(s->cptra_page_window, true); +} + +static uint64_t aspeed_ast1040_scu_read(void *opaque, hwaddr offset, + unsigned size) +{ + AspeedSCUState *s =3D ASPEED_SCU(opaque); + int reg =3D TO_REG(offset); + + if (reg >=3D ASPEED_AST1040_SCU_NR_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "= \n", + __func__, offset); + return 0; + } + + trace_aspeed_ast1040_scu_read(offset, size, s->regs[reg]); + return s->regs[reg]; +} + +static void aspeed_ast1040_scu_write(void *opaque, hwaddr offset, + uint64_t data64, unsigned size) +{ + AspeedSCUState *s =3D ASPEED_SCU(opaque); + int reg =3D TO_REG(offset); + uint32_t data =3D data64; + bool updated =3D false; + + if (reg >=3D ASPEED_AST1040_SCU_NR_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx = "\n", + __func__, offset); + return; + } + + trace_aspeed_ast1040_scu_write(offset, size, data); + + switch (reg) { + case AST1040_SCU_CLK_STOP_CTL_1: + case AST1040_SCU_CLK_STOP_CTL_2: + s->regs[reg] |=3D data; + updated =3D true; + break; + case AST1040_SCU_CLK_STOP_CLR_1: + case AST1040_SCU_CLK_STOP_CLR_2: + s->regs[reg - 1] &=3D ~data; + updated =3D true; + break; + case AST1040_SCU_FREQ_CNT_CTL: + s->regs[reg] =3D deposit32(s->regs[reg], 6, 1, !!(data & BIT(1))); + updated =3D true; + break; + case AST1040_SCU_CPTRA_PAGE_REG0: + s->regs[reg] =3D data; + aspeed_ast1040_scu_update_cptra_page(s); + updated =3D true; + break; + case AST1040_SCU_CPTRA_PAGE_REG1: + case AST1040_SCU_CPTRA_PAGE_REG2: + case AST1040_SCU_CPTRA_PAGE_REG3: + case AST1040_SCU_CPTRA_PAGE_REG4: + case AST1040_SCU_CPTRA_PAGE_REG5: + s->regs[reg] =3D data; + updated =3D true; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Unhandled write at offset 0x%" HWADDR_PRIx "\n", + __func__, offset); + break; + } + + if (!updated) { + s->regs[reg] =3D data; + } +} + +static const MemoryRegionOps aspeed_ast1040_scu_ops =3D { + .read =3D aspeed_ast1040_scu_read, + .write =3D aspeed_ast1040_scu_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .impl.min_access_size =3D 4, + .impl.max_access_size =3D 4, + .valid.min_access_size =3D 1, + .valid.max_access_size =3D 8, + .valid.unaligned =3D false, +}; + +static uint32_t aspeed_1040_scu_calc_hpll(AspeedSCUState *s, uint32_t hpll= _reg) +{ + uint32_t multiplier =3D 1; + uint32_t clkin =3D aspeed_scu_get_clkin(s); + + if (hpll_reg & SCU_AST2600_H_PLL_OFF) { + return 0; + } + + if (!(hpll_reg & SCU_AST2600_H_PLL_BYPASS_EN)) { + uint32_t p =3D (hpll_reg >> 19) & 0xf; + uint32_t n =3D (hpll_reg >> 13) & 0x3f; + uint32_t m =3D hpll_reg & 0x1fff; + + multiplier =3D ((m + 1) / (n + 1)) / (p + 1); + } + + return clkin * multiplier; +} + +static uint32_t aspeed_1040_scu_get_apb_freq(AspeedSCUState *s) +{ + AspeedSCUClass *asc =3D ASPEED_SCU_GET_CLASS(s); + uint32_t hpll =3D asc->calc_hpll(s, s->regs[AST1040_SCU_HPLL_PARAM]); + + return hpll / + (AST1040_SCU_CLK_GET_PCLK_DIV(s->regs[AST1040_SCU_CLK_SEL_1]) + 1) + / asc->apb_divider; +} + +static void aspeed_ast1040_scu_reset_hold(Object *obj, ResetType type) +{ + AspeedSCUState *s =3D ASPEED_SCU(obj); + AspeedSCUClass *asc =3D ASPEED_SCU_GET_CLASS(obj); + + memcpy(s->regs, asc->resets, asc->nr_regs * 4); + s->regs[AST1040_SILICON_REV] =3D s->silicon_rev; + s->regs[AST1040_HW_STRAP1] =3D s->hw_strap1; + aspeed_ast1040_scu_update_cptra_page(s); +} + +static const uint32_t ast1040_a0_scu_resets[ASPEED_AST1040_SCU_NR_REGS] = =3D { + [AST1040_HW_STRAP1_CLR] =3D 0xFFF0FFF0, + [AST1040_HW_STRAP1_LOCK] =3D 0x00000FFF, + [AST1040_HW_STRAP1_SEC1] =3D 0x000000FF, + [AST1040_SCU_CLK_STOP_CTL_1] =3D 0xffff8400, + [AST1040_SCU_CLK_STOP_CTL_2] =3D 0x00005f30, + [AST1040_SCU_CLK_SEL_1] =3D 0x86900000, + [AST1040_SCU_CLK_SEL_2] =3D 0x00400000, + [AST1040_SCU_HPLL_PARAM] =3D 0x10000027, + [AST1040_SCU_HPLL_EXT_PARAM] =3D 0x80000014, + [AST1040_SCU_APLL_PARAM] =3D 0x1000001f, + [AST1040_SCU_APLL_EXT_PARAM] =3D 0x8000000f, + [AST1040_SCU_DPLL_PARAM] =3D 0x106e42ce, + [AST1040_SCU_DPLL_EXT_PARAM] =3D 0x80000167, + [AST1040_SCU_DPLL_PARAM_READ] =3D 0x106e42ce, + [AST1040_SCU_DPLL_EXT_PARAM_READ] =3D 0x80000167, + [AST1040_SCU_UARTCLK_GEN] =3D 0x00014506, + [AST1040_SCU_HUARTCLK_GEN] =3D 0x000145c0, + [AST1040_SCU_CLK_DUTY_MEAS_RST] =3D 0x0c9100d2, + [AST1040_SCU_FREQ_CNT_CTL] =3D 0x00000080, +}; + +static const Property aspeed_1040_scu_props[] =3D { + DEFINE_PROP_UINT64("cptra-page-window-base", AspeedSCUState, + cptra_page_window_base, 0), +}; + +static void aspeed_1040_scu_init(Object *obj) +{ + AspeedSCUState *s =3D ASPEED_SCU(obj); + + object_property_add_link(obj, "cptra-page-window", TYPE_MEMORY_REGION, + (Object **)&s->cptra_page_window, + qdev_prop_allow_set_link_before_realize, + OBJ_PROP_LINK_STRONG); +} + +static void aspeed_1040_scu_class_init(ObjectClass *klass, const void *dat= a) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + AspeedSCUClass *asc =3D ASPEED_SCU_CLASS(klass); + + dc->desc =3D "ASPEED 1040 System Control Unit"; + rc->phases.hold =3D aspeed_ast1040_scu_reset_hold; + device_class_set_props(dc, aspeed_1040_scu_props); + asc->resets =3D ast1040_a0_scu_resets; + asc->calc_hpll =3D aspeed_1040_scu_calc_hpll; + asc->get_apb =3D aspeed_1040_scu_get_apb_freq; + asc->apb_divider =3D 2; + asc->nr_regs =3D ASPEED_AST1040_SCU_NR_REGS; + asc->clkin_25Mhz =3D true; + asc->ops =3D &aspeed_ast1040_scu_ops; +} + +static const TypeInfo aspeed_1040_scu_info =3D { + .name =3D TYPE_ASPEED_1040_SCU, + .parent =3D TYPE_ASPEED_SCU, + .instance_size =3D sizeof(AspeedSCUState), + .instance_init =3D aspeed_1040_scu_init, + .class_init =3D aspeed_1040_scu_class_init, +}; + static void aspeed_scu_register_types(void) { type_register_static(&aspeed_scu_info); @@ -1174,6 +1424,7 @@ static void aspeed_scu_register_types(void) type_register_static(&aspeed_1030_scu_info); type_register_static(&aspeed_2700_scu_info); type_register_static(&aspeed_2700_scuio_info); + type_register_static(&aspeed_1040_scu_info); } =20 type_init(aspeed_scu_register_types); diff --git a/hw/misc/trace-events b/hw/misc/trace-events index b88accc437..82ddbf4d15 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -103,6 +103,8 @@ aspeed_ast2700_scu_write(uint64_t offset, unsigned size= , uint32_t data) "To 0x%" aspeed_ast2700_scu_read(uint64_t offset, unsigned size, uint32_t data) "To= 0x%" PRIx64 " of size %u: 0x%" PRIx32 aspeed_ast2700_scuio_write(uint64_t offset, unsigned size, uint32_t data) = "To 0x%" PRIx64 " of size %u: 0x%" PRIx32 aspeed_ast2700_scuio_read(uint64_t offset, unsigned size, uint32_t data) "= To 0x%" PRIx64 " of size %u: 0x%" PRIx32 +aspeed_ast1040_scu_write(uint64_t offset, unsigned size, uint32_t data) "T= o 0x%" PRIx64 " of size %u: 0x%" PRIx32 +aspeed_ast1040_scu_read(uint64_t offset, unsigned size, uint32_t data) "To= 0x%" PRIx64 " of size %u: 0x%" PRIx32 =20 # mps2-scc.c mps2_scc_read(uint64_t offset, uint64_t data, unsigned size) "MPS2 SCC rea= d: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" --=20 2.43.0 From nobody Mon Jun 8 08:31:44 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=1780281185; cv=none; d=zohomail.com; s=zohoarc; b=UeidG+7fW86tz5RTsMI38VxeXMoYuXV6YUXj4/TTJBGXxnLnDsB3A0Zgp5mQK3DQJ0nLfHXuPo3tS8q0dU38o2DuEbhZoILU54vl2FZE3eWzci9xVLL5y29zSJcD21n7/bA7dhB5SpvUkjCqS5AsjXLdVVW8hIiWs45S98Rz6Cc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1780281185; 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=CUK8gx9b0b1ujkrZYYQBPQM8p+ZZpyrafTODPq+wcPI=; b=GY/kg8zqKC9yKR6c6FWR9BeRmfozIMxLuLFCmSDph0CWjOL6rOurGX2KQ9vO7CgFm6JbBbHHfU1G6qaK0xwMgnlRPh/fv5EoVDavz2K87AqPrALEVgR+q4qhgb3UpEgpqtzOCY4ilQZj2lMaNVCLcNGbTSy5v+AnxDez+it/ddk= 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 1780281185861678.808308069895; Sun, 31 May 2026 19:33:05 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wTsRl-0007K2-Mv; Sun, 31 May 2026 22:32:09 -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 1wTsRj-0007Ja-Fw; Sun, 31 May 2026 22:32:07 -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 1wTsRh-0004V7-3O; Sun, 31 May 2026 22:32:07 -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; Mon, 1 Jun 2026 10:31:50 +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; Mon, 1 Jun 2026 10:31:50 +0800 To: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= , Peter Maydell , Troy Lee , Jamin Lin , Kane Chen , "Andrew Jeffery" , Joel Stanley , Pierrick Bouvier , Fabiano Rosas , Laurent Vivier , Paolo Bonzini , "open list:All patches CC here" , "open list:ASPEED BMCs" CC: , , , Subject: [PATCH 2/6] hw/misc: Add ASPEED Caliptra mailbox frontend Date: Mon, 1 Jun 2026 10:31:43 +0800 Message-ID: <20260601023149.2309299-3-steven_lee@aspeedtech.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260601023149.2309299-1-steven_lee@aspeedtech.com> References: <20260601023149.2309299-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: 1780281189274154100 Content-Type: text/plain; charset="utf-8" Add a Caliptra mailbox frontend device with SRAM and CSR regions for the AS= T1040 MCI mailbox window. Model the mailbox lock, command registers, execute flow and completion path= through a pluggable peer interface so backends can service commands synchr= onously or asynchronously. Signed-off-by: Steven Lee --- include/hw/misc/aspeed_cptra_mbox.h | 133 ++++++++++ hw/misc/aspeed_cptra_mbox.c | 380 ++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + hw/misc/trace-events | 4 + 4 files changed, 518 insertions(+) create mode 100644 include/hw/misc/aspeed_cptra_mbox.h create mode 100644 hw/misc/aspeed_cptra_mbox.c diff --git a/include/hw/misc/aspeed_cptra_mbox.h b/include/hw/misc/aspeed_c= ptra_mbox.h new file mode 100644 index 0000000000..470e91597f --- /dev/null +++ b/include/hw/misc/aspeed_cptra_mbox.h @@ -0,0 +1,133 @@ +/* + * ASPEED Caliptra mailbox model (Caliptra 2.x subsystem mode) + * + * Copyright (C) 2026 ASPEED Technology Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_MISC_ASPEED_CPTRA_MBOX_H +#define HW_MISC_ASPEED_CPTRA_MBOX_H + +#include "qom/object.h" +#include "hw/core/sysbus.h" + +typedef struct Error Error; + +/* SRAM size: 2 MiB (matches MCU_MAILBOX0_SRAM_SIZE in caliptra-mcu-sw) */ +#define CPTRA_MBOX0_SRAM_SIZE (2u * 1024u * 1024u) +#define CPTRA_MBOX0_SRAM_WORDS (CPTRA_MBOX0_SRAM_SIZE / 4) + +/* CSR window: 4 KiB (covers all defined registers) */ +#define CPTRA_MBOX0_CSR_SIZE 0x1000u + +/* CSR register offsets (relative to CSR BAR) */ +#define CPTRA_MBOX0_LOCK_OFF 0x000 +#define CPTRA_MBOX0_USER_OFF 0x004 +#define CPTRA_MBOX0_TARGET_USER_OFF 0x008 +#define CPTRA_MBOX0_TARGET_USER_VAL_OFF 0x00C +#define CPTRA_MBOX0_CMD_OFF 0x010 +#define CPTRA_MBOX0_DLEN_OFF 0x014 +#define CPTRA_MBOX0_EXECUTE_OFF 0x018 +#define CPTRA_MBOX0_TARGET_STATUS_OFF 0x01C +#define CPTRA_MBOX0_CMD_STATUS_OFF 0x020 +#define CPTRA_MBOX0_HW_STATUS_OFF 0x024 + +/* CMD_STATUS values */ +#define CPTRA_MBOX0_STATUS_BUSY 0 +#define CPTRA_MBOX0_STATUS_DATA_READY 1 +#define CPTRA_MBOX0_STATUS_COMPLETE 2 +#define CPTRA_MBOX0_STATUS_CMD_FAILURE 3 + +/* SoC agent ID reported in the USER register when the lock is acquired */ +#define CPTRA_MBOX0_SOC_USER_ID 1u + +/* + * Caliptra mailbox interface (frontend), implemented as a QOM interface so + * that backends can deliver an asynchronous response without depending on= the + * concrete frontend device type. + */ +#define TYPE_CPTRA_MBOX_IF "cptra-mbox-if" +typedef struct CptraMboxIfClass CptraMboxIfClass; +DECLARE_CLASS_CHECKERS(CptraMboxIfClass, CPTRA_MBOX_IF, TYPE_CPTRA_MBOX_IF) +typedef struct CptraMboxIf CptraMboxIf; +#define CPTRA_MBOX_IF(obj) \ + INTERFACE_CHECK(CptraMboxIf, (obj), TYPE_CPTRA_MBOX_IF) + +struct CptraMboxIfClass { + InterfaceClass parent; + + /* + * Called by the peer when a command submitted via handle_execute() has + * completed. @status is a CPTRA_MBOX0_STATUS_* value; @data/@len carr= y the + * response payload to be written back into the mailbox SRAM (@len byt= es, + * @dlen is the reported DLEN). + */ + void (*complete)(CptraMboxIf *s, uint32_t status, uint32_t dlen, + const uint8_t *data, uint32_t len); +}; + +/* + * Caliptra mailbox peer (backend) base class. + */ +#define TYPE_CPTRA_MBOX_PEER "cptra-mbox-peer" +OBJECT_DECLARE_TYPE(CptraMboxPeer, CptraMboxPeerClass, CPTRA_MBOX_PEER) + +struct CptraMboxPeer { + DeviceState parent; + + /* Set by the frontend when this peer is linked to it. */ + CptraMboxIf *intf; +}; + +struct CptraMboxPeerClass { + DeviceClass parent; + + /* + * Process a command. @data/@len is a copy of the request payload from= the + * mailbox SRAM. The peer must eventually report completion by calling= the + * interface's complete() method (synchronously or asynchronously). + */ + void (*handle_execute)(CptraMboxPeer *p, uint32_t cmd, uint32_t dlen, + const uint8_t *data, uint32_t len); + + /* Optional: notify the peer of a mailbox reset. */ + void (*handle_reset)(CptraMboxPeer *p); +}; + +/* Concrete frontend device type. */ +#define TYPE_ASPEED_CPTRA_MBOX "aspeed-cptra-mbox" +OBJECT_DECLARE_SIMPLE_TYPE(AspeedCptraMboxState, ASPEED_CPTRA_MBOX) + +struct AspeedCptraMboxState { + SysBusDevice parent_obj; + + /* Linked backend; NULL means no Caliptra peer is present. */ + CptraMboxPeer *peer; + + bool locked; + bool command_pending; + bool release_pending; + uint32_t user; + uint32_t target_user; + uint32_t target_user_valid; + uint32_t cmd; + uint32_t dlen; + uint32_t execute; + uint32_t target_status; + uint32_t cmd_status; + uint32_t hw_status; + + uint32_t sram[CPTRA_MBOX0_SRAM_WORDS]; + + MemoryRegion sram_mr; + MemoryRegion csr_mr; +}; + +bool aspeed_cptra_mbox_set_peer(AspeedCptraMboxState *s, CptraMboxPeer *pe= er, + Error **errp); + +/* Concrete external (chardev) peer type. */ +#define TYPE_CPTRA_MBOX_PEER_EXTERN "cptra-mbox-peer-extern" + +#endif /* HW_MISC_ASPEED_CPTRA_MBOX_H */ diff --git a/hw/misc/aspeed_cptra_mbox.c b/hw/misc/aspeed_cptra_mbox.c new file mode 100644 index 0000000000..8c1faf69df --- /dev/null +++ b/hw/misc/aspeed_cptra_mbox.c @@ -0,0 +1,380 @@ +/* + * ASPEED Caliptra mailbox host interface (frontend) and peer base class. + * + * Copyright (C) 2026 ASPEED Technology Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/misc/aspeed_cptra_mbox.h" +#include "hw/core/qdev-properties.h" +#include "migration/vmstate.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "system/memory.h" +#include "trace.h" + +static size_t cptra_mbox_padded_len(uint32_t dlen) +{ + return (size_t)((dlen + 3) / 4) * 4; +} + +static void cptra_mbox_clear(AspeedCptraMboxState *s) +{ + s->locked =3D false; + s->release_pending =3D false; + s->user =3D 0; + s->target_user =3D 0; + s->target_user_valid =3D 0; + s->cmd =3D 0; + s->dlen =3D 0; + s->execute =3D 0; + s->target_status =3D 0; + s->cmd_status =3D 0; + s->hw_status =3D 0; + memset(s->sram, 0, sizeof(s->sram)); +} + +static void cptra_mbox_submit(AspeedCptraMboxState *s) +{ + CptraMboxPeerClass *pc; + g_autofree uint8_t *data =3D NULL; + size_t len; + + if (s->dlen > CPTRA_MBOX0_SRAM_SIZE) { + s->cmd_status =3D CPTRA_MBOX0_STATUS_CMD_FAILURE; + qemu_log_mask(LOG_GUEST_ERROR, + "%s: DLEN 0x%x exceeds SRAM size\n", __func__, s->dl= en); + return; + } + + if (!s->peer) { + /* No Caliptra peer present: the command cannot be serviced. */ + s->cmd_status =3D CPTRA_MBOX0_STATUS_CMD_FAILURE; + return; + } + + len =3D cptra_mbox_padded_len(s->dlen); + if (len) { + data =3D g_malloc(len); + for (size_t i =3D 0; i < len / 4; i++) { + stl_le_p(data + i * 4, s->sram[i]); + } + } + + s->command_pending =3D true; + s->release_pending =3D false; + trace_cptra_mbox_execute(s->cmd, s->dlen); + + pc =3D CPTRA_MBOX_PEER_GET_CLASS(s->peer); + pc->handle_execute(s->peer, s->cmd, s->dlen, data, len); +} + +/* CptraMboxIf::complete - called by the peer when a command finishes. */ +static void cptra_mbox_complete(CptraMboxIf *iface, uint32_t status, + uint32_t dlen, const uint8_t *data, + uint32_t len) +{ + AspeedCptraMboxState *s =3D ASPEED_CPTRA_MBOX(iface); + + s->command_pending =3D false; + trace_cptra_mbox_complete(status, dlen); + + if (s->release_pending) { + cptra_mbox_clear(s); + return; + } + + /* + * Report the peer's status verbatim and write back whatever response + * payload it returned. The peer signals a transport/command failure w= ith + * CPTRA_MBOX0_STATUS_CMD_FAILURE and no data. + */ + s->cmd_status =3D status; + s->dlen =3D dlen; + if (data && len) { + size_t words =3D MIN(len, CPTRA_MBOX0_SRAM_SIZE) / 4; + + for (size_t i =3D 0; i < words; i++) { + s->sram[i] =3D ldl_le_p(data + i * 4); + } + } +} + +static uint64_t cptra_mbox_sram_read(void *opaque, hwaddr offset, unsigned= size) +{ + AspeedCptraMboxState *s =3D opaque; + uint32_t idx =3D offset / 4; + + if (idx >=3D CPTRA_MBOX0_SRAM_WORDS) { + return 0; + } + return s->sram[idx]; +} + +static void cptra_mbox_sram_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + AspeedCptraMboxState *s =3D opaque; + uint32_t idx =3D offset / 4; + + if (idx < CPTRA_MBOX0_SRAM_WORDS) { + s->sram[idx] =3D (uint32_t)value; + } +} + +static const MemoryRegionOps cptra_mbox_sram_ops =3D { + .read =3D cptra_mbox_sram_read, + .write =3D cptra_mbox_sram_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid.min_access_size =3D 4, + .valid.max_access_size =3D 4, +}; + +static uint64_t cptra_mbox_csr_read(void *opaque, hwaddr offset, unsigned = size) +{ + AspeedCptraMboxState *s =3D opaque; + + switch (offset) { + case CPTRA_MBOX0_LOCK_OFF: + if (!s->locked) { + s->locked =3D true; + s->user =3D CPTRA_MBOX0_SOC_USER_ID; + return 0; + } + return 1; + case CPTRA_MBOX0_USER_OFF: + return s->user; + case CPTRA_MBOX0_TARGET_USER_OFF: + return s->target_user; + case CPTRA_MBOX0_TARGET_USER_VAL_OFF: + return s->target_user_valid; + case CPTRA_MBOX0_CMD_OFF: + return s->cmd; + case CPTRA_MBOX0_DLEN_OFF: + return s->dlen; + case CPTRA_MBOX0_EXECUTE_OFF: + return s->execute; + case CPTRA_MBOX0_TARGET_STATUS_OFF: + return s->target_status; + case CPTRA_MBOX0_CMD_STATUS_OFF: + return s->cmd_status; + case CPTRA_MBOX0_HW_STATUS_OFF: + return s->hw_status; + default: + return 0; + } +} + +static void cptra_mbox_csr_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + AspeedCptraMboxState *s =3D opaque; + uint32_t val =3D (uint32_t)value; + + switch (offset) { + case CPTRA_MBOX0_LOCK_OFF: + case CPTRA_MBOX0_USER_OFF: + case CPTRA_MBOX0_HW_STATUS_OFF: + break; + case CPTRA_MBOX0_TARGET_USER_OFF: + s->target_user =3D val; + break; + case CPTRA_MBOX0_TARGET_USER_VAL_OFF: + s->target_user_valid =3D val; + break; + case CPTRA_MBOX0_CMD_OFF: + s->cmd =3D val; + break; + case CPTRA_MBOX0_DLEN_OFF: + if (val > CPTRA_MBOX0_SRAM_SIZE) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: DLEN 0x%x exceeds SRAM size, clamped\n", + __func__, val); + val =3D CPTRA_MBOX0_SRAM_SIZE; + } + s->dlen =3D val; + break; + case CPTRA_MBOX0_EXECUTE_OFF: + if (val =3D=3D 1 && s->execute !=3D 1 && !s->command_pending) { + s->execute =3D 1; + s->cmd_status =3D CPTRA_MBOX0_STATUS_BUSY; + cptra_mbox_submit(s); + } else if (val =3D=3D 0 && s->execute !=3D 0) { + if (s->command_pending) { + s->release_pending =3D true; + } else { + cptra_mbox_clear(s); + } + } + break; + case CPTRA_MBOX0_TARGET_STATUS_OFF: + s->target_status =3D val; + break; + case CPTRA_MBOX0_CMD_STATUS_OFF: + s->cmd_status =3D val; + break; + default: + break; + } +} + +static const MemoryRegionOps cptra_mbox_csr_ops =3D { + .read =3D cptra_mbox_csr_read, + .write =3D cptra_mbox_csr_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid.min_access_size =3D 4, + .valid.max_access_size =3D 4, +}; + +static void cptra_mbox_reset_hold(Object *obj, ResetType type) +{ + AspeedCptraMboxState *s =3D ASPEED_CPTRA_MBOX(obj); + + if (s->command_pending) { + /* Defer the clear until the in-flight command completes. */ + s->release_pending =3D true; + return; + } + cptra_mbox_clear(s); + + if (s->peer) { + CptraMboxPeerClass *pc =3D CPTRA_MBOX_PEER_GET_CLASS(s->peer); + if (pc->handle_reset) { + pc->handle_reset(s->peer); + } + } +} + +static void cptra_mbox_peer_check(const Object *obj, const char *name, + Object *val, Error **errp) +{ + CptraMboxPeer *peer; + + if (!val) { + return; + } + + peer =3D CPTRA_MBOX_PEER(val); + if (peer->intf) { + error_setg(errp, "Caliptra mailbox peer is already in use"); + } +} + +bool aspeed_cptra_mbox_set_peer(AspeedCptraMboxState *s, CptraMboxPeer *pe= er, + Error **errp) +{ + CptraMboxPeer *old_peer =3D s->peer; + + if (old_peer =3D=3D peer) { + if (s->peer) { + s->peer->intf =3D CPTRA_MBOX_IF(s); + } + return true; + } + if (!object_property_set_link(OBJECT(s), "peer", + peer ? OBJECT(peer) : NULL, errp)) { + return false; + } + if (old_peer) { + old_peer->intf =3D NULL; + } + if (s->peer) { + s->peer->intf =3D CPTRA_MBOX_IF(s); + } + return true; +} + +static void cptra_mbox_init(Object *obj) +{ + AspeedCptraMboxState *s =3D ASPEED_CPTRA_MBOX(obj); + + object_property_add_link(obj, "peer", TYPE_CPTRA_MBOX_PEER, + (Object **)&s->peer, cptra_mbox_peer_check, + OBJ_PROP_LINK_STRONG); +} + +static void cptra_mbox_realize(DeviceState *dev, Error **errp) +{ + AspeedCptraMboxState *s =3D ASPEED_CPTRA_MBOX(dev); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(dev); + + if (s->peer) { + if (!aspeed_cptra_mbox_set_peer(s, s->peer, errp)) { + return; + } + } + + memory_region_init_io(&s->sram_mr, OBJECT(s), &cptra_mbox_sram_ops, s, + "cptra-mbox.sram", CPTRA_MBOX0_SRAM_SIZE); + sysbus_init_mmio(sbd, &s->sram_mr); + + memory_region_init_io(&s->csr_mr, OBJECT(s), &cptra_mbox_csr_ops, s, + "cptra-mbox.csr", CPTRA_MBOX0_CSR_SIZE); + sysbus_init_mmio(sbd, &s->csr_mr); +} + +static const VMStateDescription vmstate_cptra_mbox =3D { + .name =3D TYPE_ASPEED_CPTRA_MBOX, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (const VMStateField[]) { + VMSTATE_BOOL(locked, AspeedCptraMboxState), + VMSTATE_UINT32(user, AspeedCptraMboxState), + VMSTATE_UINT32(target_user, AspeedCptraMboxState), + VMSTATE_UINT32(target_user_valid, AspeedCptraMboxState), + VMSTATE_UINT32(cmd, AspeedCptraMboxState), + VMSTATE_UINT32(dlen, AspeedCptraMboxState), + VMSTATE_UINT32(execute, AspeedCptraMboxState), + VMSTATE_UINT32(target_status, AspeedCptraMboxState), + VMSTATE_UINT32(cmd_status, AspeedCptraMboxState), + VMSTATE_UINT32(hw_status, AspeedCptraMboxState), + VMSTATE_UINT32_ARRAY(sram, AspeedCptraMboxState, + CPTRA_MBOX0_SRAM_WORDS), + VMSTATE_END_OF_LIST() + }, +}; + +static void cptra_mbox_class_init(ObjectClass *oc, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(oc); + ResettableClass *rc =3D RESETTABLE_CLASS(oc); + CptraMboxIfClass *ic =3D CPTRA_MBOX_IF_CLASS(oc); + + dc->desc =3D "Caliptra mailbox host interface"; + dc->realize =3D cptra_mbox_realize; + dc->vmsd =3D &vmstate_cptra_mbox; + rc->phases.hold =3D cptra_mbox_reset_hold; + ic->complete =3D cptra_mbox_complete; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); +} + +static const TypeInfo cptra_mbox_types[] =3D { + { + .name =3D TYPE_CPTRA_MBOX_IF, + .parent =3D TYPE_INTERFACE, + .class_size =3D sizeof(CptraMboxIfClass), + }, + { + .name =3D TYPE_CPTRA_MBOX_PEER, + .parent =3D TYPE_DEVICE, + .instance_size =3D sizeof(CptraMboxPeer), + .class_size =3D sizeof(CptraMboxPeerClass), + .abstract =3D true, + }, + { + .name =3D TYPE_ASPEED_CPTRA_MBOX, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(AspeedCptraMboxState), + .instance_init =3D cptra_mbox_init, + .class_init =3D cptra_mbox_class_init, + .interfaces =3D (const InterfaceInfo[]) { + { TYPE_CPTRA_MBOX_IF }, + { } + }, + }, +}; + +DEFINE_TYPES(cptra_mbox_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index fa6a961ac9..d23045c4b5 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -135,6 +135,7 @@ system_ss.add(when: 'CONFIG_PVPANIC_PCI', if_true: file= s('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_cptra_mbox.c', 'aspeed_hace.c', 'aspeed_lpc.c', 'aspeed_ltpi.c', diff --git a/hw/misc/trace-events b/hw/misc/trace-events index 82ddbf4d15..9fe2d27fef 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -106,6 +106,10 @@ aspeed_ast2700_scuio_read(uint64_t offset, unsigned si= ze, uint32_t data) "To 0x% aspeed_ast1040_scu_write(uint64_t offset, unsigned size, uint32_t data) "T= o 0x%" PRIx64 " of size %u: 0x%" PRIx32 aspeed_ast1040_scu_read(uint64_t offset, unsigned size, uint32_t data) "To= 0x%" PRIx64 " of size %u: 0x%" PRIx32 =20 +# aspeed_cptra_mbox.c +cptra_mbox_execute(uint32_t cmd, uint32_t dlen) "EXECUTE cmd 0x%" PRIx32 "= dlen 0x%" PRIx32 +cptra_mbox_complete(uint32_t status, uint32_t dlen) "complete status %u dl= en 0x%" PRIx32 + # mps2-scc.c mps2_scc_read(uint64_t offset, uint64_t data, unsigned size) "MPS2 SCC rea= d: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" mps2_scc_write(uint64_t offset, uint64_t data, unsigned size) "MPS2 SCC wr= ite: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" --=20 2.43.0 From nobody Mon Jun 8 08:31:44 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=1780281196; cv=none; d=zohomail.com; s=zohoarc; b=Vc2z90tfLpP6mhPI0xn/4GQrMELAFYojTNxs8wFyQXb+xX/Agtlm0RjJk4zMbbBTyKOiWJKMmf93bbqEEklQULuhZrDqdSQYg51woZVcAJbA8qlasEoXpfM8TMsqLmuZ364K5munN2Crxw3FadOZMkx8wFZCtJjMpDFI/DG9Ceo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1780281196; 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=3bwholUXHwQNJH0QKknbtn5t7zxZhnG4pRuqawPjESg=; b=nBGuYBiAN4vhggDbmi1OnYm9Yf1WuvXk1cy7dJVQBE66/5aqyhNbdybJEIiAM3Z/NUZrxHDpa5OGqHFsZqFo/SkN4PRyf6PWuzXg4yOjuufUphg1k2pnCxt68WFPuoyrH6xdhh1ZjiMGGWWKYICzV8SuOFI3CQbAehPN9OS2zCk= 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 1780281196655759.1872247841568; Sun, 31 May 2026 19:33:16 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wTsRo-0007LE-Fu; Sun, 31 May 2026 22:32:12 -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 1wTsRm-0007KY-SS; Sun, 31 May 2026 22:32:10 -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 1wTsRk-0004V7-Un; Sun, 31 May 2026 22:32:10 -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; Mon, 1 Jun 2026 10:31:50 +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; Mon, 1 Jun 2026 10:31:50 +0800 To: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= , Peter Maydell , Troy Lee , Jamin Lin , Kane Chen , "Andrew Jeffery" , Joel Stanley , Pierrick Bouvier , Fabiano Rosas , Laurent Vivier , Paolo Bonzini , "open list:All patches CC here" , "open list:ASPEED BMCs" CC: , , , Subject: [PATCH 3/6] hw/misc: Add external Caliptra mailbox peer Date: Mon, 1 Jun 2026 10:31:44 +0800 Message-ID: <20260601023149.2309299-4-steven_lee@aspeedtech.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260601023149.2309299-1-steven_lee@aspeedtech.com> References: <20260601023149.2309299-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: 1780281197992158500 Content-Type: text/plain; charset="utf-8" Add a cptra-mbox-peer-extern backend that forwards mailbox execute requests= to a chardev peer using a small framed protocol. Run the blocking chardev transaction from the thread pool and report comple= tion back through the mailbox peer interface. Block migration while this ex= ternal backend is realized because the peer state lives outside QEMU. Signed-off-by: Steven Lee --- MAINTAINERS | 1 + hw/misc/cptra_mbox_peer_extern.c | 318 +++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + 3 files changed, 320 insertions(+) create mode 100644 hw/misc/cptra_mbox_peer_extern.c diff --git a/MAINTAINERS b/MAINTAINERS index cd5c4831e2..a0e11d4a0e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1270,6 +1270,7 @@ L: qemu-arm@nongnu.org S: Maintained F: hw/*/*aspeed* F: include/hw/*/*aspeed* +F: hw/misc/cptra_mbox_peer_extern.c F: hw/net/ftgmac100.c F: include/hw/net/ftgmac100.h F: docs/system/arm/aspeed.rst diff --git a/hw/misc/cptra_mbox_peer_extern.c b/hw/misc/cptra_mbox_peer_ext= ern.c new file mode 100644 index 0000000000..f8d5886880 --- /dev/null +++ b/hw/misc/cptra_mbox_peer_extern.c @@ -0,0 +1,318 @@ +/* + * Caliptra mailbox external peer (backend). + * + * Copyright (C) 2026 ASPEED Technology Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "block/thread-pool.h" +#include "chardev/char-fe.h" +#include "hw/misc/aspeed_cptra_mbox.h" +#include "hw/core/qdev-properties.h" +#include "hw/core/qdev-properties-system.h" +#include "migration/blocker.h" +#include "qapi/error.h" +#include "qemu/bswap.h" +#include "qemu/error-report.h" + +#define CPTRA_MBOX_PROTO_MAGIC 0x4D424F58u /* "MBOX" */ +#define CPTRA_MBOX_PROTO_VERSION 1u +#define CPTRA_MBOX_CMD_EXECUTE 1u +#define CPTRA_MBOX_CMD_RESPONSE 2u +#define CPTRA_MBOX_PROTO_MAX_PAYLOAD (8 + CPTRA_MBOX0_SRAM_SIZE) + +typedef struct QEMU_PACKED CptraMboxProtoHdr { + uint32_t magic; + uint16_t version; + uint16_t command; + uint32_t payload_len; +} CptraMboxProtoHdr; + +OBJECT_DECLARE_SIMPLE_TYPE(CptraMboxPeerExtern, CPTRA_MBOX_PEER_EXTERN) + +struct CptraMboxPeerExtern { + CptraMboxPeer parent; + + CharFrontend chr; + Error *migration_blocker; +}; + +typedef struct CptraMboxExternReq { + CptraMboxPeerExtern *p; + + uint32_t cmd; + uint32_t dlen; + uint8_t *req_data; + size_t req_len; + + uint32_t rsp_status; + uint32_t rsp_dlen; + uint8_t *rsp_data; + size_t rsp_len; + + char *error; +} CptraMboxExternReq; + +static size_t cptra_padded_len(uint32_t dlen) +{ + return (size_t)((dlen + 3) / 4) * 4; +} + +static int G_GNUC_PRINTF(2, 3) +cptra_req_fail(CptraMboxExternReq *req, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + g_free(req->error); + req->error =3D g_strdup_vprintf(fmt, ap); + va_end(ap); + + return -1; +} + +static int cptra_write_all(CptraMboxExternReq *req, const void *buf, size_= t len) +{ + int ret; + + if (len > INT_MAX) { + return cptra_req_fail(req, "write too large: %zu", len); + } + ret =3D qemu_chr_fe_write_all(&req->p->chr, buf, len); + if (ret < 0 || (size_t)ret !=3D len) { + return cptra_req_fail(req, "backend write failed"); + } + return 0; +} + +static int cptra_read_all(CptraMboxExternReq *req, void *buf, size_t len) +{ + int ret; + + if (len > INT_MAX) { + return cptra_req_fail(req, "read too large: %zu", len); + } + ret =3D qemu_chr_fe_read_all(&req->p->chr, buf, len); + if (ret < 0 || (size_t)ret !=3D len) { + return cptra_req_fail(req, "backend read failed"); + } + return 0; +} + +/* + * Wire protocol (magic 0x4D424F58 "MBOX"): + * + * Header (12 bytes, little-endian): + * u32 magic =3D 0x4D424F58 + * u16 version =3D 1 + * u16 command + * u32 payload_len + * + * MBOX_EXECUTE (1) QEMU -> backend + * payload: u32 cmd, u32 dlen, u8 sram[ROUND_UP(dlen, 4)] + * + * MBOX_RESPONSE (2) backend -> QEMU + * payload: u32 status, u32 dlen, u8 sram[ROUND_UP(dlen, 4)] + */ +static int cptra_extern_worker(gpointer data) +{ + CptraMboxExternReq *req =3D data; + CptraMboxProtoHdr hdr; + size_t tx_payload_len =3D 8 + req->req_len; + g_autofree uint8_t *payload =3D NULL; + size_t rsp_data_len; + + if (!qemu_chr_fe_backend_open(&req->p->chr)) { + return cptra_req_fail(req, "backend is not connected"); + } + + payload =3D g_malloc0(tx_payload_len); + stl_le_p(payload, req->cmd); + stl_le_p(payload + 4, req->dlen); + if (req->req_len) { + memcpy(payload + 8, req->req_data, req->req_len); + } + + hdr.magic =3D cpu_to_le32(CPTRA_MBOX_PROTO_MAGIC); + hdr.version =3D cpu_to_le16(CPTRA_MBOX_PROTO_VERSION); + hdr.command =3D cpu_to_le16(CPTRA_MBOX_CMD_EXECUTE); + hdr.payload_len =3D cpu_to_le32(tx_payload_len); + + if (cptra_write_all(req, &hdr, sizeof(hdr)) < 0 || + cptra_write_all(req, payload, tx_payload_len) < 0) { + return -1; + } + + if (cptra_read_all(req, &hdr, sizeof(hdr)) < 0) { + return -1; + } + + 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 CPTRA_MBOX_PROTO_MAGIC) { + return cptra_req_fail(req, "bad response magic 0x%08x", hdr.magic); + } + if (hdr.version !=3D CPTRA_MBOX_PROTO_VERSION) { + return cptra_req_fail(req, "bad response version %u", hdr.version); + } + if (hdr.command !=3D CPTRA_MBOX_CMD_RESPONSE) { + return cptra_req_fail(req, "unexpected response command %u", + hdr.command); + } + if (hdr.payload_len < 8 || hdr.payload_len > CPTRA_MBOX_PROTO_MAX_PAYL= OAD) { + return cptra_req_fail(req, "invalid response payload length %u", + hdr.payload_len); + } + + g_free(payload); + payload =3D g_malloc(hdr.payload_len); + if (cptra_read_all(req, payload, hdr.payload_len) < 0) { + return -1; + } + + req->rsp_status =3D ldl_le_p(payload); + req->rsp_dlen =3D ldl_le_p(payload + 4); + if (req->rsp_dlen > CPTRA_MBOX0_SRAM_SIZE) { + return cptra_req_fail(req, "response DLEN 0x%x exceeds SRAM", + req->rsp_dlen); + } + + rsp_data_len =3D cptra_padded_len(req->rsp_dlen); + if (8 + rsp_data_len > hdr.payload_len) { + return cptra_req_fail(req, "short response payload for DLEN 0x%x", + req->rsp_dlen); + } + + if (rsp_data_len) { + req->rsp_data =3D g_malloc0(rsp_data_len); + memcpy(req->rsp_data, payload + 8, rsp_data_len); + req->rsp_len =3D rsp_data_len; + } + + return 0; +} + +static void cptra_extern_req_free(CptraMboxExternReq *req) +{ + g_free(req->req_data); + g_free(req->rsp_data); + g_free(req->error); + g_free(req); +} + +static void cptra_extern_complete(void *opaque, int ret) +{ + CptraMboxExternReq *req =3D opaque; + CptraMboxPeerExtern *p =3D req->p; + CptraMboxIf *intf =3D p->parent.intf; + CptraMboxIfClass *ic =3D intf ? CPTRA_MBOX_IF_GET_CLASS(intf) : NULL; + + if (req->error) { + error_report("cptra-mbox-peer-extern: %s", req->error); + } + + if (ic) { + if (ret =3D=3D 0) { + ic->complete(intf, req->rsp_status, req->rsp_dlen, + req->rsp_data, req->rsp_len); + } else { + ic->complete(intf, CPTRA_MBOX0_STATUS_CMD_FAILURE, 0, NULL, 0); + } + } + + cptra_extern_req_free(req); + object_unref(OBJECT(p)); +} + +static void cptra_extern_handle_execute(CptraMboxPeer *peer, uint32_t cmd, + uint32_t dlen, const uint8_t *data, + uint32_t len) +{ + CptraMboxPeerExtern *p =3D CPTRA_MBOX_PEER_EXTERN(peer); + CptraMboxIf *intf =3D peer->intf; + CptraMboxExternReq *req; + + if (!qemu_chr_fe_backend_connected(&p->chr) || + !qemu_chr_fe_backend_open(&p->chr)) { + if (intf) { + CPTRA_MBOX_IF_GET_CLASS(intf)->complete( + intf, CPTRA_MBOX0_STATUS_CMD_FAILURE, 0, NULL, 0); + } + return; + } + + req =3D g_new0(CptraMboxExternReq, 1); + req->p =3D p; + req->cmd =3D cmd; + req->dlen =3D dlen; + if (len) { + req->req_data =3D g_memdup2(data, len); + req->req_len =3D len; + } + + object_ref(OBJECT(p)); + thread_pool_submit_aio(cptra_extern_worker, req, + cptra_extern_complete, req); +} + +static void cptra_extern_realize(DeviceState *dev, Error **errp) +{ + CptraMboxPeerExtern *p =3D CPTRA_MBOX_PEER_EXTERN(dev); + + if (!qemu_chr_fe_backend_connected(&p->chr)) { + error_setg(errp, "cptra-mbox-peer-extern requires a chardev attrib= ute"); + return; + } + + qemu_chr_fe_set_open(&p->chr, true); + error_setg(&p->migration_blocker, + "Migration disabled: cptra-mbox-peer-extern chardev backend= " + "state is external"); + if (migrate_add_blocker(&p->migration_blocker, errp) < 0) { + return; + } +} + +static void cptra_extern_finalize(Object *obj) +{ + CptraMboxPeerExtern *p =3D CPTRA_MBOX_PEER_EXTERN(obj); + + migrate_del_blocker(&p->migration_blocker); + qemu_chr_fe_deinit(&p->chr, false); +} + +static const Property cptra_extern_props[] =3D { + DEFINE_PROP_CHR("chardev", CptraMboxPeerExtern, chr), +}; + +static void cptra_extern_class_init(ObjectClass *oc, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(oc); + CptraMboxPeerClass *pc =3D CPTRA_MBOX_PEER_CLASS(oc); + + dc->desc =3D "Caliptra mailbox external (chardev) peer"; + dc->realize =3D cptra_extern_realize; + dc->hotpluggable =3D false; + device_class_set_props(dc, cptra_extern_props); + pc->handle_execute =3D cptra_extern_handle_execute; +} + +static const TypeInfo cptra_extern_type =3D { + .name =3D TYPE_CPTRA_MBOX_PEER_EXTERN, + .parent =3D TYPE_CPTRA_MBOX_PEER, + .instance_size =3D sizeof(CptraMboxPeerExtern), + .instance_finalize =3D cptra_extern_finalize, + .class_init =3D cptra_extern_class_init, +}; + +static void cptra_extern_register_types(void) +{ + type_register_static(&cptra_extern_type); +} + +type_init(cptra_extern_register_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index d23045c4b5..9d545e8fb7 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -136,6 +136,7 @@ system_ss.add(when: 'CONFIG_PVPANIC_MMIO', if_true: fil= es('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_cptra_mbox.c', + 'cptra_mbox_peer_extern.c', 'aspeed_hace.c', 'aspeed_lpc.c', 'aspeed_ltpi.c', --=20 2.43.0 From nobody Mon Jun 8 08:31:44 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=1780281186; cv=none; d=zohomail.com; s=zohoarc; b=TWsdJPSNZpi6/yNUd0KzbhrrsSfW3WY5A0lN6bPJcKh6gVF4KLSefh2z88Zq/hXaVBh6DdLfNYfouPL9257XDpscc2azo85vLiB2PPudLOELCl4WEp2qgnqWq7EexZOqqR1z8cEDx/HhIxqFK+BedYuLSGrMz/cZ5OKhcfFDoEk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1780281186; 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=8tO01KXHl1vruksi1Q48y8OrETz1Dzsq3tTMMsp3rb8=; b=Ydd5c6WsVQr0r5cb65anXTyA/yiF0ByxWHEA7SRkmaVXxJmcXzfSJrh299EETqzAMA9Z76QXkPvv/rRoODdif/xifyPHJjIMfx9+sW0xHa1KJqvzXX/lxV0ZYYOAnyaGjVCNvbUPzRbhfLl/Av/myy9D3IxL8jxRLddnsjYvWxM= 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 1780281186036629.4218837953068; Sun, 31 May 2026 19:33:06 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wTsRr-0007M2-3B; Sun, 31 May 2026 22:32:15 -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 1wTsRp-0007LI-HB; Sun, 31 May 2026 22:32: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 1wTsRn-0004V7-NN; Sun, 31 May 2026 22:32:13 -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; Mon, 1 Jun 2026 10:31:51 +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; Mon, 1 Jun 2026 10:31:51 +0800 To: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= , Peter Maydell , Troy Lee , Jamin Lin , Kane Chen , "Andrew Jeffery" , Joel Stanley , Pierrick Bouvier , Fabiano Rosas , Laurent Vivier , Paolo Bonzini , "open list:All patches CC here" , "open list:ASPEED BMCs" CC: , , , Subject: [PATCH 4/6] hw/arm/aspeed_ast1040: Wire Caliptra mailbox Date: Mon, 1 Jun 2026 10:31:45 +0800 Message-ID: <20260601023149.2309299-5-steven_lee@aspeedtech.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260601023149.2309299-1-steven_lee@aspeedtech.com> References: <20260601023149.2309299-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: 1780281189404158500 Content-Type: text/plain; charset="utf-8" Instantiate the Caliptra mailbox in the AST1040 SoC and map its SRAM and CS= R windows at the guest-visible MCI addresses. Add the 4 KiB MCI aperture controlled by the AST1040 SCU CPTRA page registe= r, switch the SoC to the AST1040 SCU model, and expose a machine option tha= t links an external mailbox peer after machine initialization. Signed-off-by: Steven Lee --- include/hw/arm/aspeed_soc.h | 11 ++++++ hw/arm/aspeed_ast1040.c | 60 ++++++++++++++++++++++++++++-- hw/arm/aspeed_ast1040_evb.c | 74 ++++++++++++++++++++++++++++++++++++- 3 files changed, 140 insertions(+), 5 deletions(-) diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index 3aac144cd4..9fad3bc082 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -46,6 +46,7 @@ #include "hw/intc/arm_gicv3.h" #include "hw/misc/aspeed_ltpi.h" #include "hw/arm/aspeed_ast1700.h" +#include "hw/misc/aspeed_cptra_mbox.h" =20 #define VBOOTROM_FILE_NAME "ast27x0_bootrom.bin" =20 @@ -165,6 +166,16 @@ struct Aspeed10x0SoCState { #define TYPE_ASPEED10X0_SOC "aspeed10x0-soc" OBJECT_DECLARE_SIMPLE_TYPE(Aspeed10x0SoCState, ASPEED10X0_SOC) =20 +struct Aspeed1040SoCState { + Aspeed10x0SoCState parent; + + AspeedCptraMboxState cptra_mbox; + MemoryRegion cptra_mci_window; +}; + +#define TYPE_ASPEED1040_SOC "ast1040-a0" +OBJECT_DECLARE_SIMPLE_TYPE(Aspeed1040SoCState, ASPEED1040_SOC) + struct AspeedSoCClass { DeviceClass parent_class; =20 diff --git a/hw/arm/aspeed_ast1040.c b/hw/arm/aspeed_ast1040.c index 8efcdad8f6..c597982bc5 100644 --- a/hw/arm/aspeed_ast1040.c +++ b/hw/arm/aspeed_ast1040.c @@ -8,12 +8,17 @@ =20 #include "qemu/osdep.h" #include "qapi/error.h" -#include "system/address-spaces.h" #include "system/system.h" #include "hw/core/qdev-clock.h" #include "hw/misc/unimp.h" +#include "hw/misc/aspeed_cptra_mbox.h" #include "hw/arm/aspeed_soc.h" =20 +#define AST1040_CPTRA_MCI_WINDOW_BASE 0x74200000 +#define AST1040_CPTRA_MCI_WINDOW_SIZE 0x1000 +#define AST1040_CPTRA_MBOX_SRAM_BASE 0x21400000 +#define AST1040_CPTRA_MBOX_CSR_BASE 0x21600000 + static const hwaddr aspeed_soc_ast1040_memmap[] =3D { [ASPEED_DEV_SRAM1] =3D 0x00000000, /* Hyper RAM */ [ASPEED_DEV_FMC] =3D 0x74000000, @@ -88,6 +93,7 @@ static qemu_irq aspeed_soc_ast1040_get_irq(AspeedSoCState= *s, int dev) =20 static void aspeed_soc_ast1040_init(Object *obj) { + Aspeed1040SoCState *a1040 =3D ASPEED1040_SOC(obj); Aspeed10x0SoCState *a =3D ASPEED10X0_SOC(obj); AspeedSoCState *s =3D ASPEED_SOC(obj); AspeedSoCClass *sc =3D ASPEED_SOC_GET_CLASS(s); @@ -96,12 +102,13 @@ static void aspeed_soc_ast1040_init(Object *obj) =20 s->sysclk =3D qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0); =20 - /* AST1040 uses the AST2700 SCUIO model */ - object_initialize_child(obj, "scu", &s->scu, TYPE_ASPEED_2700_SCUIO); + object_initialize_child(obj, "scu", &s->scu, TYPE_ASPEED_1040_SCU); qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev", sc->silicon_rev); =20 object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu), "hw-strap= 1"); object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu), "hw-strap= 2"); + object_initialize_child(obj, "cptra-mbox", &a1040->cptra_mbox, + TYPE_ASPEED_CPTRA_MBOX); =20 for (i =3D 0; i < sc->uarts_num; i++) { object_initialize_child(obj, "uart[*]", &s->uart[i], TYPE_SERIAL_M= M); @@ -120,8 +127,31 @@ static void aspeed_soc_ast1040_init(Object *obj) TYPE_UNIMPLEMENTED_DEVICE); } =20 +static bool aspeed_soc_ast1040_realize_cptra_mbox(Aspeed1040SoCState *a104= 0, + Error **errp) +{ + AspeedSoCState *s =3D ASPEED_SOC(a1040); + DeviceState *mbox =3D DEVICE(&a1040->cptra_mbox); + + /* + * Caliptra is an AST1040 integrated RoT IP. The external peer is + * optional; without a peer, the mailbox registers remain present and + * EXECUTE completes with CMD_FAILURE. + */ + if (!sysbus_realize(SYS_BUS_DEVICE(mbox), errp)) { + return false; + } + + aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(mbox), 0, + AST1040_CPTRA_MBOX_SRAM_BASE); + aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(mbox), 1, + AST1040_CPTRA_MBOX_CSR_BASE); + return true; +} + static void aspeed_soc_ast1040_realize(DeviceState *dev_soc, Error **errp) { + Aspeed1040SoCState *a1040 =3D ASPEED1040_SOC(dev_soc); Aspeed10x0SoCState *a =3D ASPEED10X0_SOC(dev_soc); AspeedSoCState *s =3D ASPEED_SOC(dev_soc); AspeedSoCClass *sc =3D ASPEED_SOC_GET_CLASS(s); @@ -171,6 +201,27 @@ static void aspeed_soc_ast1040_realize(DeviceState *de= v_soc, Error **errp) memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_SRAM1], &s->sram[1]); =20 + if (!aspeed_soc_ast1040_realize_cptra_mbox(a1040, errp)) { + return; + } + + /* + * The Caliptra MCI aperture is a 4 KiB alias whose target is selected= by + * AST1040_SCU_CPTRA_PAGE_REG0. Firmware commonly switches it between + * mailbox SRAM (0x21400000) and mailbox CSR (0x21600000), then access= es + * the selected page through 0x74200000. + */ + memory_region_init_alias(&a1040->cptra_mci_window, OBJECT(s), + "aspeed.ast1040.cptra-mci-window", s->memory, + 0, AST1040_CPTRA_MCI_WINDOW_SIZE); + memory_region_add_subregion(s->memory, AST1040_CPTRA_MCI_WINDOW_BASE, + &a1040->cptra_mci_window); + /* The SCU drives the aperture's target offset via SCU_CPTRA_PAGE_REG0= . */ + object_property_set_link(OBJECT(&s->scu), "cptra-page-window", + OBJECT(&a1040->cptra_mci_window), &error_abor= t); + object_property_set_uint(OBJECT(&s->scu), "cptra-page-window-base", + AST1040_CPTRA_MCI_WINDOW_BASE, &error_abort); + /* SCU */ if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) { return; @@ -244,8 +295,9 @@ static void aspeed_soc_ast1040_class_init(ObjectClass *= klass, const void *data) =20 static const TypeInfo aspeed_soc_ast1040_types[] =3D { { - .name =3D "ast1040-a0", + .name =3D TYPE_ASPEED1040_SOC, .parent =3D TYPE_ASPEED10X0_SOC, + .instance_size =3D sizeof(Aspeed1040SoCState), .instance_init =3D aspeed_soc_ast1040_init, .class_init =3D aspeed_soc_ast1040_class_init, } diff --git a/hw/arm/aspeed_ast1040_evb.c b/hw/arm/aspeed_ast1040_evb.c index 1d9b55247f..eb325a1095 100644 --- a/hw/arm/aspeed_ast1040_evb.c +++ b/hw/arm/aspeed_ast1040_evb.c @@ -8,17 +8,59 @@ =20 #include "qemu/osdep.h" #include "qapi/error.h" +#include "qemu/error-report.h" #include "hw/arm/boot.h" #include "hw/arm/machines-qom.h" #include "hw/arm/aspeed.h" #include "hw/arm/aspeed_soc.h" #include "hw/core/qdev-clock.h" +#include "hw/misc/aspeed_cptra_mbox.h" #include "system/system.h" =20 #define AST1040_INTERNAL_FLASH_SIZE (4 * MiB) /* Main SYSCLK frequency in Hz (400MHz) */ #define SYSCLK_FRQ 400000000ULL =20 +#define TYPE_AST1040_EVB_MACHINE MACHINE_TYPE_NAME("ast1040-evb") +OBJECT_DECLARE_SIMPLE_TYPE(Ast1040EvbMachineState, AST1040_EVB_MACHINE) + +struct Ast1040EvbMachineState { + AspeedMachineState parent_obj; + + char *cptra_peer; + Notifier machine_done; +}; + +static void aspeed_bic_machine_done(Notifier *notifier, void *data) +{ + Ast1040EvbMachineState *m =3D container_of(notifier, + Ast1040EvbMachineState, + machine_done); + AspeedMachineState *bmc =3D ASPEED_MACHINE(m); + Aspeed1040SoCState *a1040 =3D ASPEED1040_SOC(bmc->soc); + bool ambiguous =3D false; + Object *peer; + Error *err =3D NULL; + + if (!m->cptra_peer) { + return; + } + + peer =3D object_resolve_path_type(m->cptra_peer, TYPE_CPTRA_MBOX_PEER, + &ambiguous); + if (!peer || ambiguous) { + error_report("cptra-peer: peer '%s' not found%s", + m->cptra_peer, ambiguous ? " (ambiguous)" : ""); + exit(1); + } + + if (!aspeed_cptra_mbox_set_peer(&a1040->cptra_mbox, + CPTRA_MBOX_PEER(peer), &err)) { + error_report_err(err); + exit(1); + } +} + static void aspeed_bic_machine_init(MachineState *machine) { AspeedMachineState *bmc =3D ASPEED_MACHINE(machine); @@ -38,12 +80,35 @@ static void aspeed_bic_machine_init(MachineState *machi= ne) aspeed_connect_serial_hds_to_uarts(bmc); qdev_realize(DEVICE(bmc->soc), NULL, &error_abort); =20 + if (AST1040_EVB_MACHINE(machine)->cptra_peer) { + AST1040_EVB_MACHINE(machine)->machine_done.notify =3D + aspeed_bic_machine_done; + qemu_add_machine_init_done_notifier( + &AST1040_EVB_MACHINE(machine)->machine_done); + } + armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0, AST1040_INTERNAL_FLASH_SIZE); } =20 +static char *aspeed_bic_get_cptra_peer(Object *obj, Error **errp) +{ + Ast1040EvbMachineState *m =3D AST1040_EVB_MACHINE(obj); + + return g_strdup(m->cptra_peer); +} + +static void aspeed_bic_set_cptra_peer(Object *obj, const char *value, + Error **errp) +{ + Ast1040EvbMachineState *m =3D AST1040_EVB_MACHINE(obj); + + g_free(m->cptra_peer); + m->cptra_peer =3D g_strdup(value); +} + static void aspeed_machine_ast1040_evb_class_init(ObjectClass *oc, const void *data) { @@ -59,12 +124,19 @@ static void aspeed_machine_ast1040_evb_class_init(Obje= ctClass *oc, amc->macs_mask =3D 0; amc->uart_default =3D ASPEED_DEV_UART12; aspeed_machine_class_init_cpus_defaults(mc); + + object_class_property_add_str(oc, "cptra-peer", + aspeed_bic_get_cptra_peer, + aspeed_bic_set_cptra_peer); + object_class_property_set_description(oc, "cptra-peer", + "Caliptra mailbox peer object id"); } =20 static const TypeInfo aspeed_ast1040_evb_types[] =3D { { - .name =3D MACHINE_TYPE_NAME("ast1040-evb"), + .name =3D TYPE_AST1040_EVB_MACHINE, .parent =3D TYPE_ASPEED_MACHINE, + .instance_size =3D sizeof(Ast1040EvbMachineState), .class_init =3D aspeed_machine_ast1040_evb_class_init, .interfaces =3D arm_machine_interfaces, } --=20 2.43.0 From nobody Mon Jun 8 08:31:44 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=1780281185; cv=none; d=zohomail.com; s=zohoarc; b=H94Wt6rUA/WgFUw/TViSPZ72HC9cC4RkXjY5ZnYpMJsXG1sVUqd4IXHzCQZ6jfaXrGHZUjlZSaxMeXX70eJbxvB229XSEizD0lBxjRRfRuLXaMcxPcn4pl3aIe7H7iy6Nr2dTlK11K2sPP7MsETAfEFx1dnQx8lzCs0w7vJHxZo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1780281185; 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=91Bxvb4LyKUjpJsaM9DXT/C+XKYGin9SxlOrd4FCUqo=; b=ABH2FmkBOvYhpQPUK3EQWJy4ABBM3ZoeOT1xP7tl/K05ULo0NpsJ0LaMhgwuFUI2qJl3Zdr/YR/vvAtvyxemJOMK0x/bn+UGQcwos++DB+k5un+cx3QOfTn/1Fz0fCa3gZ2wc/JToF/Hp34NDqckH1QJszHIgApXt5dkkZ74suY= 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 1780281185896109.89709414439005; Sun, 31 May 2026 19:33:05 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wTsRu-0007Mh-73; Sun, 31 May 2026 22:32:18 -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 1wTsRs-0007MU-BZ; Sun, 31 May 2026 22:32:16 -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 1wTsRq-0004V7-Dd; Sun, 31 May 2026 22:32:16 -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; Mon, 1 Jun 2026 10:31:51 +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; Mon, 1 Jun 2026 10:31:51 +0800 To: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= , Peter Maydell , Troy Lee , Jamin Lin , Kane Chen , "Andrew Jeffery" , Joel Stanley , Pierrick Bouvier , Fabiano Rosas , Laurent Vivier , Paolo Bonzini , "open list:All patches CC here" , "open list:ASPEED BMCs" CC: , , , Subject: [PATCH 5/6] tests/qtest: Add ASPEED Caliptra mailbox test Date: Mon, 1 Jun 2026 10:31:46 +0800 Message-ID: <20260601023149.2309299-6-steven_lee@aspeedtech.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260601023149.2309299-1-steven_lee@aspeedtech.com> References: <20260601023149.2309299-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: 1780281189427154100 Content-Type: text/plain; charset="utf-8" Cover the AST1040 Caliptra mailbox execute flow through the external peer p= rotocol and verify that the SCU CPTRA page register remaps the MCI aperture= between CSR and SRAM pages. Signed-off-by: Steven Lee --- tests/qtest/aspeed_cptra_mbox-test.c | 223 +++++++++++++++++++++++++++ tests/qtest/meson.build | 3 +- 2 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 tests/qtest/aspeed_cptra_mbox-test.c diff --git a/tests/qtest/aspeed_cptra_mbox-test.c b/tests/qtest/aspeed_cptr= a_mbox-test.c new file mode 100644 index 0000000000..4d0e1682da --- /dev/null +++ b/tests/qtest/aspeed_cptra_mbox-test.c @@ -0,0 +1,223 @@ +/* + * QTest for the ASPEED Caliptra mailbox on the ast1040-evb machine. + * + * Copyright (C) 2026 ASPEED Technology Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "libqtest-single.h" +#include "qemu/sockets.h" + +/* AST1040 guest-visible mailbox bases. */ +#define SRAM_BASE 0x21400000ULL +#define CSR_BASE 0x21600000ULL + +#define CSR_LOCK 0x000 +#define CSR_USER 0x004 +#define CSR_CMD 0x010 +#define CSR_DLEN 0x014 +#define CSR_EXECUTE 0x018 +#define CSR_CMD_STATUS 0x020 + +#define STATUS_BUSY 0 +#define STATUS_COMPLETE 2 +#define STATUS_CMD_FAILURE 3 + +/* SCU CPTRA page-select register (SCU base 0x74C02000 + 0x120). */ +#define SCU_CPTRA_PAGE_REG0 0x74C02120ULL +/* MCI remap aperture. */ +#define MCI_WINDOW 0x74200000ULL + +/* Wire protocol. */ +#define PROTO_MAGIC 0x4D424F58u +#define PROTO_VERSION 1u +#define CMD_EXECUTE 1u +#define CMD_RESPONSE 2u + +static int peer_lfd =3D -1; +static int peer_fd =3D -1; + +static void peer_read(void *buf, size_t len) +{ + size_t off =3D 0; + + while (off < len) { + ssize_t r =3D read(peer_fd, (uint8_t *)buf + off, len - off); + g_assert_cmpint(r, >, 0); + off +=3D r; + } +} + +static void peer_write(const void *buf, size_t len) +{ + size_t off =3D 0; + + while (off < len) { + ssize_t w =3D write(peer_fd, (const uint8_t *)buf + off, len - off= ); + g_assert_cmpint(w, >, 0); + off +=3D w; + } +} + +static uint32_t ld32(const uint8_t *p) +{ + return p[0] | (p[1] << 8) | (p[2] << 16) | ((uint32_t)p[3] << 24); +} + +static void st32(uint8_t *p, uint32_t v) +{ + p[0] =3D v; p[1] =3D v >> 8; p[2] =3D v >> 16; p[3] =3D v >> 24; +} + +/* + * Service one MBOX_EXECUTE: read the request, optionally check it, then r= eply + * with MBOX_RESPONSE carrying @rsp_status and @rsp_data. + */ +static void peer_serve_execute(uint32_t expect_cmd, uint32_t expect_dlen, + uint32_t rsp_status, + const uint8_t *rsp_data, uint32_t rsp_dlen) +{ + uint8_t hdr[12]; + uint32_t plen, cmd, dlen; + g_autofree uint8_t *payload =3D NULL; + uint32_t rsp_padded =3D (rsp_dlen + 3) & ~3u; + uint32_t rsp_plen =3D 8 + rsp_padded; + g_autofree uint8_t *rsp =3D g_malloc0(12 + rsp_plen); + + peer_read(hdr, sizeof(hdr)); + g_assert_cmpuint(ld32(hdr), =3D=3D, PROTO_MAGIC); + g_assert_cmpuint(hdr[4] | (hdr[5] << 8), =3D=3D, PROTO_VERSION); + g_assert_cmpuint(hdr[6] | (hdr[7] << 8), =3D=3D, CMD_EXECUTE); + plen =3D ld32(hdr + 8); + g_assert_cmpuint(plen, >=3D, 8); + + payload =3D g_malloc(plen); + peer_read(payload, plen); + cmd =3D ld32(payload); + dlen =3D ld32(payload + 4); + g_assert_cmpuint(cmd, =3D=3D, expect_cmd); + g_assert_cmpuint(dlen, =3D=3D, expect_dlen); + + st32(rsp, PROTO_MAGIC); + rsp[4] =3D PROTO_VERSION; rsp[5] =3D 0; + rsp[6] =3D CMD_RESPONSE; rsp[7] =3D 0; + st32(rsp + 8, rsp_plen); + st32(rsp + 12, rsp_status); + st32(rsp + 16, rsp_dlen); + if (rsp_dlen) { + memcpy(rsp + 20, rsp_data, rsp_dlen); + } + peer_write(rsp, 12 + rsp_plen); +} + +static uint32_t poll_cmd_status(void) +{ + uint32_t s =3D STATUS_BUSY; + int tries =3D 1000; + + while (tries--) { + s =3D qtest_readl(global_qtest, CSR_BASE + CSR_CMD_STATUS); + if (s !=3D STATUS_BUSY) { + break; + } + } + return s; +} + +/* + * Realistic mailbox transaction: acquire the lock, run an EXECUTE roundtr= ip + * against the peer, verify the response lands in SRAM, then release. + */ +static void test_execute(void) +{ + static const uint8_t resp[] =3D { + 0x11, 0xf9, 0xff, 0xff, /* checksum */ + 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, /* inner dlen =3D 20 */ + 'C', 'a', 'l', 'i', 'p', 't', 'r', 'a', + '_', 'C', 'o', 'r', 'e', '_', 'v', '2', '.', '0', '.', '0', + }; + uint32_t status; + + /* + * Acquire: first read returns 0, USER reflects the SoC agent, busy af= ter. + */ + g_assert_cmpuint(qtest_readl(global_qtest, CSR_BASE + CSR_LOCK), =3D= =3D, 0); + g_assert_cmpuint(qtest_readl(global_qtest, CSR_BASE + CSR_USER), =3D= =3D, 1); + g_assert_cmpuint(qtest_readl(global_qtest, CSR_BASE + CSR_LOCK), =3D= =3D, 1); + + qtest_writel(global_qtest, SRAM_BASE + 0, 0xfffffec0); + qtest_writel(global_qtest, CSR_BASE + CSR_CMD, 0x4d465756); + qtest_writel(global_qtest, CSR_BASE + CSR_DLEN, 8); + qtest_writel(global_qtest, CSR_BASE + CSR_EXECUTE, 1); + + peer_serve_execute(0x4d465756, 8, STATUS_COMPLETE, resp, sizeof(resp)); + + status =3D poll_cmd_status(); + g_assert_cmpuint(status, =3D=3D, STATUS_COMPLETE); + g_assert_cmpuint(qtest_readl(global_qtest, CSR_BASE + CSR_DLEN), + =3D=3D, sizeof(resp)); + g_assert_cmpuint(qtest_readl(global_qtest, SRAM_BASE + 0), =3D=3D, 0xf= ffff911); + g_assert_cmpuint(qtest_readl(global_qtest, SRAM_BASE + 8), =3D=3D, 0x1= 4); + g_assert_cmpuint(qtest_readl(global_qtest, SRAM_BASE + 12), =3D=3D, 0x= 696c6143); + + /* Completing the transaction (EXECUTE 1->0) releases the lock. */ + qtest_writel(global_qtest, CSR_BASE + CSR_EXECUTE, 0); + g_assert_cmpuint(qtest_readl(global_qtest, CSR_BASE + CSR_LOCK), =3D= =3D, 0); + qtest_writel(global_qtest, CSR_BASE + CSR_EXECUTE, 0); +} + +/* SCU CPTRA_PAGE_REG0 selects the target page seen through the MCI window= . */ +static void test_scu_remap(void) +{ + /* Window pointed at the CSR page exposes the CMD register. */ + qtest_writel(global_qtest, CSR_BASE + CSR_CMD, 0xdeadbeef); + qtest_writel(global_qtest, SCU_CPTRA_PAGE_REG0, CSR_BASE); + g_assert_cmpuint(qtest_readl(global_qtest, MCI_WINDOW + CSR_CMD), + =3D=3D, 0xdeadbeef); + + /* Re-point at the SRAM page. */ + qtest_writel(global_qtest, SRAM_BASE + 0, 0x12345678); + qtest_writel(global_qtest, SCU_CPTRA_PAGE_REG0, SRAM_BASE); + g_assert_cmpuint(qtest_readl(global_qtest, MCI_WINDOW + 0), + =3D=3D, 0x12345678); +} + +int main(int argc, char **argv) +{ + g_autofree char *sock_path =3D NULL; + g_autofree char *cmdline =3D NULL; + int ret; + + g_test_init(&argc, &argv, NULL); + + sock_path =3D g_strdup_printf("%s/cptra-mbox-%u.sock", + g_get_tmp_dir(), getpid()); + unlink(sock_path); + peer_lfd =3D qtest_socket_server(sock_path); + + cmdline =3D g_strdup_printf( + "-machine ast1040-evb,cptra-peer=3Dpeer0 " + "-chardev socket,id=3Dcptra0,path=3D%s " + "-device cptra-mbox-peer-extern,id=3Dpeer0,chardev=3Dcptra0", sock= _path); + qtest_start(cmdline); + + peer_fd =3D accept(peer_lfd, NULL, NULL); + g_assert_cmpint(peer_fd, >=3D, 0); + + qtest_add_func("/cptra-mbox/execute", test_execute); + qtest_add_func("/cptra-mbox/scu-remap", test_scu_remap); + + ret =3D g_test_run(); + + qtest_end(); + if (peer_fd >=3D 0) { + close(peer_fd); + } + close(peer_lfd); + unlink(sock_path); + + return ret; +} diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 728dde54b3..c50da850f7 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -219,7 +219,8 @@ qtests_aspeed =3D \ ['aspeed_gpio-test', 'aspeed_hace-test', 'aspeed_scu-test', - 'aspeed_smc-test'] + 'aspeed_smc-test', + 'aspeed_cptra_mbox-test'] qtests_aspeed64 =3D \ ['ast2700-gpio-test', 'ast2700-hace-test', --=20 2.43.0 From nobody Mon Jun 8 08:31:44 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=1780281193; cv=none; d=zohomail.com; s=zohoarc; b=UOmDDMiddUhJRaGaEAlhu8xh8JHUjgidMQoF+OfNWAH6x3rqs7b0eTDOZbUna5EXr++XnGjpFP3LrjWFPGPV4Zr0PA8FtKHHROpzx3qwpp8/4x6Urj1LD1Km9zkjillcfC2JA4hSZHyVTa87ZDtsD5YjQMdbFcsQmCznRn4M3SI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1780281193; 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=sZuSRHEu8Zvod0RJk5NpNWWbYZie8ycs7DTwLVySUfc=; b=LrqIr6XlLMP7Z7CBA+zmEqL0Uq+ItfdY2YR4yiVDN6+D5OoURpEvEO0IH/GlUsP3QZvysp1insFgfCbqCsB45veWLd5Ow7m6ON5mEo+o1m6dJBqrdpJHZjBTqCu/Evt6vQtzYZwbzHyqeC2Aa00wwWLL5eBH7JUr6sNhQILSmkA= 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 1780281193090873.2781193661536; Sun, 31 May 2026 19:33:13 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wTsRv-0007Nb-MR; Sun, 31 May 2026 22:32:19 -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 1wTsRu-0007N9-Il; Sun, 31 May 2026 22:32:18 -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 1wTsRt-0004V7-5d; Sun, 31 May 2026 22:32:18 -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; Mon, 1 Jun 2026 10:31:51 +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; Mon, 1 Jun 2026 10:31:51 +0800 To: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= , Peter Maydell , Troy Lee , Jamin Lin , Kane Chen , "Andrew Jeffery" , Joel Stanley , Pierrick Bouvier , Fabiano Rosas , Laurent Vivier , Paolo Bonzini , "open list:All patches CC here" , "open list:ASPEED BMCs" CC: , , , Subject: [PATCH 6/6] docs/system/arm: Document AST1040 Caliptra mailbox Date: Mon, 1 Jun 2026 10:31:47 +0800 Message-ID: <20260601023149.2309299-7-steven_lee@aspeedtech.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260601023149.2309299-1-steven_lee@aspeedtech.com> References: <20260601023149.2309299-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: 1780281194178158500 Content-Type: text/plain; charset="utf-8" Document the AST1040 Caliptra MCI mailbox windows, the SCU-controlled remap= aperture, and how to connect the external mailbox peer through a chardev b= ackend. Signed-off-by: Steven Lee --- docs/system/arm/aspeed.rst | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst index 2d51ceeb84..1ffa88c2ae 100644 --- a/docs/system/arm/aspeed.rst +++ b/docs/system/arm/aspeed.rst @@ -483,6 +483,7 @@ Supported devices * ADC * Secure Boot Controller * PECI Controller (minimal) + * Caliptra MCI mailbox (AST1040 only) =20 =20 Missing devices @@ -512,3 +513,34 @@ To boot a kernel directly from a Zephyr build tree: =20 $ qemu-system-arm -M ast1030-evb -nographic \ -kernel zephyr.bin + +Caliptra MCI mailbox (ast1040-evb) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The AST1040 chip provides a mechanism to map the Caliptra MCI mailbox +register space into the Cortex-M4F address space. The Caliptra MCI mailbox +SRAM and CSR are accessible at fixed addresses: + +- Mailbox SRAM at ``0x21400000`` (2 MiB, command/response payload) +- Mailbox CSR at ``0x21600000`` (4 KiB, LOCK/CMD/DLEN/EXECUTE/STATUS) + +The SCU ``CPTRA_PAGE_REG0`` register (at ``0x74C02120``) selects which +Caliptra MCI page (SRAM or CSR) is exposed through the 4 KiB aperture at +``0x74200000``, allowing firmware to access either window through a single +address. + +By default the mailbox has no Caliptra peer, so writing ``EXECUTE`` reports +``CMD_FAILURE``. To service commands with an external Caliptra simulator (= for +example caliptra-server) over a UNIX socket, start the simulator first, th= en +create an external peer device and link it with the machine's ``cptra-peer= `` +option: + +.. code-block:: bash + + $ qemu-system-arm -M ast1040-evb,cptra-peer=3Dpeer0 -nographic \ + -chardev socket,id=3Dcptra0,path=3D/tmp/mcu_mbox.sock \ + -device cptra-mbox-peer-extern,id=3Dpeer0,chardev=3Dcptra0 \ + -kernel zephyr.elf + +Writing ``EXECUTE`` bridges the command and the mailbox SRAM payload to the +peer over the socket, and writes the response back into the mailbox SRAM. --=20 2.43.0