From 27d543b88016e05dd2f02113d3fc4373b595b251 Mon Sep 17 00:00:00 2001 From: Jian Zhang Date: Fri, 12 Jun 2026 14:08:57 +0800 Subject: [PATCH 1/8] hw/intc/aspeed: Drop stale pending interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Aspeed INTC records an interrupt source in the pending bitmap when the source is masked or another status bit is still being handled. When the guest later clears the status register, the model promotes all saved pending bits back to status unconditionally. This is not correct for level-triggered sources. A source can deassert while another source connected to the same OR gate keeps the aggregated INTC line asserted. Promoting the stale bit later makes the guest demux a child interrupt whose device status has already been cleared. This is visible on AST2700 I2C, where the I2C buses are aggregated through INTCIO GICINT194 before reaching the GIC. A stale I2C source bit can be promoted back to the INTCIO status register, causing Linux to run the corresponding I2C ISR with an empty I2C interrupt status register. For example, the Linux aspeed-i2c debug ring shows a transfer that first receives a valid status interrupt, then receives a spurious ISR with both isr and raw status equal to zero. The zero-status ISR clears the saved command error and the transfer completes with ret=0: event=start isr=0x00000000 raw=0x00000000 cmd_err=0 msgs_idx=0 event=isr isr=0x00010011 raw=0x00010011 cmd_err=0 msgs_idx=0 event=isr isr=0x00000000 raw=0x00000000 cmd_err=1 msgs_idx=1 event=complete ret=0 cmd_err=0 msgs_idx=1 A normal command can then be reported as zero transferred messages, which is converted to -EIO by Linux i2c_smbus_xfer_emulated(). The race is more likely when multiple I2C buses are accessed concurrently. Drop pending bits that no longer correspond to an asserted and enabled source before they can be promoted back to status. Signed-off-by: Jian Zhang Reviewed-by: Jamin Lin Link: https://lore.kernel.org/qemu-devel/20260612060857.1842819-1-zhangjian.3032@bytedance.com Signed-off-by: Cédric Le Goater --- hw/intc/aspeed_intc.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c index 5a36fff520..ab80c239bc 100644 --- a/hw/intc/aspeed_intc.c +++ b/hw/intc/aspeed_intc.c @@ -107,6 +107,27 @@ static const AspeedINTCIRQ *aspeed_intc_get_irq(AspeedINTCClass *aic, g_assert_not_reached(); } +static uint32_t aspeed_intc_orgate_levels(AspeedINTCState *s, int inpin_idx) +{ + AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); + uint32_t levels = 0; + int i; + + for (i = 0; i < aic->num_lines && i < 32; i++) { + if (s->orgates[inpin_idx].levels[i]) { + levels |= BIT(i); + } + } + + return levels; +} + +static void aspeed_intc_drop_stale_pending(AspeedINTCState *s, int inpin_idx) +{ + s->pending[inpin_idx] &= aspeed_intc_orgate_levels(s, inpin_idx) & + s->enable[inpin_idx]; +} + /* * Update the state of an interrupt controller pin by setting * the specified output pin to the given level. @@ -231,6 +252,8 @@ static void aspeed_intc_set_irq(void *opaque, int irq, int level) trace_aspeed_intc_set_irq(name, inpin_idx, level); enable = s->enable[inpin_idx]; + aspeed_intc_drop_stale_pending(s, inpin_idx); + if (!level) { return; } @@ -343,6 +366,7 @@ static void aspeed_intc_status_handler(AspeedINTCState *s, hwaddr offset, /* All source ISR execution are done */ if (!s->regs[reg]) { trace_aspeed_intc_all_isr_done(name, inpin_idx); + aspeed_intc_drop_stale_pending(s, inpin_idx); if (s->pending[inpin_idx]) { /* * handle pending source interrupt @@ -402,6 +426,7 @@ static void aspeed_intc_status_handler_multi_outpins(AspeedINTCState *s, /* All source ISR executions are done from a specific bit */ if (data & BIT(i)) { trace_aspeed_intc_all_isr_done_bit(name, inpin_idx, i); + aspeed_intc_drop_stale_pending(s, inpin_idx); if (s->pending[inpin_idx] & BIT(i)) { /* * Handle pending source interrupt. From b04746bd0d7c116b94fe3cd7e105849d481c21a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Jun 2026 06:27:18 +0200 Subject: [PATCH 2/8] tests/functional/aspeed: unify boot completion detection on 'login:' prompt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The boot completion check in AspeedTest waits for the systemd "Hostname set to" message, which occasionally causes intermittent test timeouts, e.g. on ast2500 SoC machines. The root cause seems to be console output interleaving of both systemd and the getty login process. This results in the expected pattern string being broken up. Unify and simplify all boot completion checks by looking for the generic 'login:' substring in AspeedTest.wait_for_boot_complete(). With the override gone, remove the redundant FacebookAspeedTest class and update the Anacapa, Bletchley, and Catalina tests to inherit directly from AspeedTest. Also drop the now-dead image_hostname parameter from do_test_arm_aspeed_openbmc(). Reported-by: Peter Maydell Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3117 Reviewed-by: Thomas Huth Link: https://lore.kernel.org/qemu-devel/20260617042718.2883655-1-clg@redhat.com Signed-off-by: Cédric Le Goater --- tests/functional/arm/test_aspeed_anacapa.py | 6 +++--- tests/functional/arm/test_aspeed_bletchley.py | 6 +++--- tests/functional/arm/test_aspeed_catalina.py | 6 +++--- .../arm/test_aspeed_gb200nvl_bmc.py | 3 +-- tests/functional/aspeed.py | 21 ++++--------------- 5 files changed, 14 insertions(+), 28 deletions(-) diff --git a/tests/functional/arm/test_aspeed_anacapa.py b/tests/functional/arm/test_aspeed_anacapa.py index b16c6035c9..363b4c2a1d 100644 --- a/tests/functional/arm/test_aspeed_anacapa.py +++ b/tests/functional/arm/test_aspeed_anacapa.py @@ -5,10 +5,10 @@ # SPDX-License-Identifier: GPL-2.0-or-later from qemu_test import Asset -from aspeed import FacebookAspeedTest +from aspeed import AspeedTest -class AnacapaMachine(FacebookAspeedTest): +class AnacapaMachine(AspeedTest): ASSET_ANACAPA_FLASH = Asset( 'https://github.com/legoater/qemu-aspeed-boot/raw/refs/heads/master/images/anacapa-bmc/openbmc-20260616025349/obmc-phosphor-image-anacapa-20260616025349.static.mtd.xz', @@ -22,4 +22,4 @@ def test_arm_ast2600_anacapa_openbmc(self): soc='AST2600 rev A3') if __name__ == '__main__': - FacebookAspeedTest.main() + AspeedTest.main() diff --git a/tests/functional/arm/test_aspeed_bletchley.py b/tests/functional/arm/test_aspeed_bletchley.py index 3000d0c302..5a60b24b3d 100755 --- a/tests/functional/arm/test_aspeed_bletchley.py +++ b/tests/functional/arm/test_aspeed_bletchley.py @@ -5,10 +5,10 @@ # SPDX-License-Identifier: GPL-2.0-or-later from qemu_test import Asset -from aspeed import FacebookAspeedTest +from aspeed import AspeedTest -class BletchleyMachine(FacebookAspeedTest): +class BletchleyMachine(AspeedTest): ASSET_BLETCHLEY_FLASH = Asset( 'https://github.com/legoater/qemu-aspeed-boot/raw/master/images/bletchley-bmc/openbmc-20250128071329/obmc-phosphor-image-bletchley-20250128071329.static.mtd.xz', @@ -22,4 +22,4 @@ def test_arm_ast2600_bletchley_openbmc(self): soc='AST2600 rev A3') if __name__ == '__main__': - FacebookAspeedTest.main() + AspeedTest.main() diff --git a/tests/functional/arm/test_aspeed_catalina.py b/tests/functional/arm/test_aspeed_catalina.py index 2694e4b005..dc2f24e7b4 100755 --- a/tests/functional/arm/test_aspeed_catalina.py +++ b/tests/functional/arm/test_aspeed_catalina.py @@ -5,10 +5,10 @@ # SPDX-License-Identifier: GPL-2.0-or-later from qemu_test import Asset -from aspeed import FacebookAspeedTest +from aspeed import AspeedTest -class CatalinaMachine(FacebookAspeedTest): +class CatalinaMachine(AspeedTest): ASSET_CATALINA_FLASH = Asset( 'https://github.com/legoater/qemu-aspeed-boot/raw/a866feb5ef81245b4827a214584bf6bcc72939f6/images/catalina-bmc/obmc-phosphor-image-catalina-20250619123021.static.mtd.xz', @@ -22,4 +22,4 @@ def test_arm_ast2600_catalina_openbmc(self): soc='AST2600 rev A3') if __name__ == '__main__': - FacebookAspeedTest.main() + AspeedTest.main() diff --git a/tests/functional/arm/test_aspeed_gb200nvl_bmc.py b/tests/functional/arm/test_aspeed_gb200nvl_bmc.py index e5f2dce0f5..f9e736d047 100755 --- a/tests/functional/arm/test_aspeed_gb200nvl_bmc.py +++ b/tests/functional/arm/test_aspeed_gb200nvl_bmc.py @@ -19,8 +19,7 @@ def test_arm_aspeed_gb200_openbmc(self): self.do_test_arm_aspeed_openbmc('gb200nvl-bmc', image=image_path, uboot='2019.04', cpu_id='0xf00', - soc='AST2600 rev A3', - image_hostname='gb200nvl-obmc') + soc='AST2600 rev A3') if __name__ == '__main__': AspeedTest.main() diff --git a/tests/functional/aspeed.py b/tests/functional/aspeed.py index 88b6590934..076da1036c 100644 --- a/tests/functional/aspeed.py +++ b/tests/functional/aspeed.py @@ -8,14 +8,7 @@ class AspeedTest(LinuxKernelTest): def do_test_arm_aspeed_openbmc(self, machine, image, uboot='2019.04', - cpu_id='0x0', soc='AST2500 rev A1', - image_hostname=None): - # Allow for the image hostname to not end in "-bmc" - if image_hostname is not None: - hostname = image_hostname - else: - hostname = machine.removesuffix('-bmc') - + cpu_id='0x0', soc='AST2500 rev A1'): self.set_machine(machine) self.vm.set_console() self.vm.add_args('-drive', f'file={image},if=mtd,format=raw', @@ -28,10 +21,10 @@ def do_test_arm_aspeed_openbmc(self, machine, image, uboot='2019.04', self.wait_for_console_pattern(f'Booting Linux on physical CPU {cpu_id}') self.wait_for_console_pattern(f'ASPEED {soc}') self.wait_for_console_pattern('/init as init process') - self.wait_for_boot_complete(hostname) + self.wait_for_boot_complete() - def wait_for_boot_complete(self, hostname): - self.wait_for_console_pattern(f'systemd[1]: Hostname set to <{hostname}>.') + def wait_for_boot_complete(self): + self.wait_for_console_pattern('login:') def do_test_arm_aspeed_buildroot_start(self, image, cpu_id, pattern='Aspeed EVB'): self.require_netdev('user') @@ -71,9 +64,3 @@ def generate_otpmem_image(self): with open(path, "wb") as f: f.write(pattern) return path - - -class FacebookAspeedTest(AspeedTest): - - def wait_for_boot_complete(self, hostname): - self.wait_for_console_pattern(f'{hostname} login:') From d4671ff2d974792845ae006c6563d073f13e4054 Mon Sep 17 00:00:00 2001 From: yujun Date: Mon, 29 Jun 2026 15:41:33 +0800 Subject: [PATCH 3/8] hw/gpio/pca9552: fix off-by-one in QOM led index validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pca955x_get_led() and pca955x_set_led() accept led indices equal to pin_count, but valid indices are 0..pin_count-1. For a 16-pin device, led16 passes the current check and then accesses an LS register past max_reg. Use the same >= pin_count bounds check as pca9554_set_pin() and the gpio input handler assert in this file. Fixes: a90d8f84674 ("misc/pca9552: Add qom set and get") Signed-off-by: yujun Reviewed-by: Peter Maydell Reviewed-by: Glenn Miles Link: https://lore.kernel.org/qemu-devel/20260629074133.187549-1-yujun@kylinos.cn Signed-off-by: Cédric Le Goater --- hw/gpio/pca9552.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/gpio/pca9552.c b/hw/gpio/pca9552.c index 472d8ad957..b13ac9fd9c 100644 --- a/hw/gpio/pca9552.c +++ b/hw/gpio/pca9552.c @@ -311,8 +311,8 @@ static void pca955x_get_led(Object *obj, Visitor *v, const char *name, error_setg(errp, "%s: error reading %s", __func__, name); return; } - if (led < 0 || led > k->pin_count) { - error_setg(errp, "%s invalid led %s", __func__, name); + if (led < 0 || led >= k->pin_count) { + error_setg(errp, "%s: invalid led %s", __func__, name); return; } /* @@ -352,8 +352,8 @@ static void pca955x_set_led(Object *obj, Visitor *v, const char *name, error_setg(errp, "%s: error reading %s", __func__, name); return; } - if (led < 0 || led > k->pin_count) { - error_setg(errp, "%s invalid led %s", __func__, name); + if (led < 0 || led >= k->pin_count) { + error_setg(errp, "%s: invalid led %s", __func__, name); return; } From 5c03a6501ba82d6d4051eae088012a00ac56142e Mon Sep 17 00:00:00 2001 From: Jamin Lin Date: Mon, 6 Jul 2026 05:27:03 +0000 Subject: [PATCH 4/8] hw/arm/aspeed_ast27x0-fc: Fix hardware strap settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hardware strap settings in the AST2700 FC machine model were incorrect. Update HW_STRAP1 and HW_STRAP2 to match the values observed from the real EVB dump. These values are also consistent with the current aspeed_ast27x0_evb.c machine setup. Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Link: https://lore.kernel.org/qemu-devel/20260706052701.1141740-2-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater --- hw/arm/aspeed_ast27x0-fc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/arm/aspeed_ast27x0-fc.c b/hw/arm/aspeed_ast27x0-fc.c index 5eb6680da9..7d9fade68d 100644 --- a/hw/arm/aspeed_ast27x0-fc.c +++ b/hw/arm/aspeed_ast27x0-fc.c @@ -50,8 +50,10 @@ struct Ast2700FCState { #define AST2700FC_BMC_RAM_SIZE (2 * GiB) -#define AST2700FC_HW_STRAP1 0x000000C0 -#define AST2700FC_HW_STRAP2 0x00000003 +/* SCU HW Strap1 */ +#define AST2700FC_HW_STRAP1 0x00000800 +/* SCUIO HW Strap1 */ +#define AST2700FC_HW_STRAP2 0x00000700 #define AST2700FC_FMC_MODEL "w25q01jvq" #define AST2700FC_SPI_MODEL "w25q512jv" From 5b881dcc77c4e54f168c15400efea4fb869c98d3 Mon Sep 17 00:00:00 2001 From: Jamin Lin Date: Mon, 6 Jul 2026 05:27:04 +0000 Subject: [PATCH 5/8] hw/misc/aspeed_scu: Drop noisy unhandled read logs for AST2700 SCU/SCUIO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The AST2700 SCU/SCUIO read handlers currently emit LOG_GUEST_ERROR messages for all registers that are not explicitly handled. However, most SCU registers are simple read-back registers without side effects, and do not require explicit handling in the read path. Returning the stored register value is sufficient. Emitting "Unhandled read" logs for these cases generates excessive and misleading noise during normal guest operation, making it harder to spot real issues. Remove the default unhandled read logging from the SCU and SCUIO read handlers to reduce log noise and align with common QEMU device model behavior for passive registers. Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Link: https://lore.kernel.org/qemu-devel/20260706052701.1141740-3-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater --- hw/misc/aspeed_scu.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c index fe731a28bd..ed7f5e648d 100644 --- a/hw/misc/aspeed_scu.c +++ b/hw/misc/aspeed_scu.c @@ -849,13 +849,6 @@ static uint64_t aspeed_ast2700_scu_read(void *opaque, hwaddr offset, return 0; } - switch (reg) { - default: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: Unhandled read at offset 0x%" HWADDR_PRIx "\n", - __func__, offset); - } - trace_aspeed_ast2700_scu_read(offset, size, s->regs[reg]); return s->regs[reg]; } @@ -961,13 +954,6 @@ static uint64_t aspeed_ast2700_scuio_read(void *opaque, hwaddr offset, return 0; } - switch (reg) { - default: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: Unhandled read at offset 0x%" HWADDR_PRIx "\n", - __func__, offset); - } - trace_aspeed_ast2700_scuio_read(offset, size, s->regs[reg]); return s->regs[reg]; } From 8ce9e7af057f9f4763d3f8e7d2a3add791c7b084 Mon Sep 17 00:00:00 2001 From: Jamin Lin Date: Mon, 6 Jul 2026 05:27:07 +0000 Subject: [PATCH 6/8] hw/misc/aspeed_scu: Add AST2700 SCUIO RNG control and data registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement basic behavior for RNG_CTRL and RNG_DATA: - RNG_CTRL allows guest to enable/disable the RNG via the DIS bit. Only bits [0:3] and bit 5 are writable; other bits are masked. - The VLD bit (bit 31) is updated by the model to reflect the RNG enable state, and is not writable by the guest. - When RNG is enabled, reads from RNG_DATA return a newly generated random value. - When RNG is disabled, RNG_DATA return 0. This provides a minimal functional model of the RNG sufficient for software that expects readable random data without modeling full hardware behavior. Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Link: https://lore.kernel.org/qemu-devel/20260706052701.1141740-4-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater --- hw/misc/aspeed_scu.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c index ed7f5e648d..5dbf81c0ce 100644 --- a/hw/misc/aspeed_scu.c +++ b/hw/misc/aspeed_scu.c @@ -160,6 +160,11 @@ #define AST2700_SCU_CPU_SCRATCH_1 TO_REG(0x784) #define AST2700_SCU_VGA_SCRATCH_0 TO_REG(0x900) +#define AST2700_SCUIO_RNG_CTRL TO_REG(0xF0) +#define AST2700_SCUIO_RNG_CTRL_MASK 0x2F +#define AST2700_SCUIO_RNG_CTRL_DIS BIT(0) +#define AST2700_SCUIO_RNG_CTRL_VLD BIT(31) +#define AST2700_SCUIO_RNG_DATA TO_REG(0xF4) #define AST2700_SCUIO_CLK_STOP_CTL_1 TO_REG(0x240) #define AST2700_SCUIO_CLK_STOP_CLR_1 TO_REG(0x244) #define AST2700_SCUIO_CLK_STOP_CTL_2 TO_REG(0x260) @@ -954,6 +959,14 @@ static uint64_t aspeed_ast2700_scuio_read(void *opaque, hwaddr offset, return 0; } + switch (reg) { + case AST2700_SCUIO_RNG_DATA: + if (!(s->regs[AST2700_SCUIO_RNG_CTRL] & AST2700_SCUIO_RNG_CTRL_DIS)) { + s->regs[AST2700_SCUIO_RNG_DATA] = aspeed_scu_get_random(); + } + break; + } + trace_aspeed_ast2700_scuio_read(offset, size, s->regs[reg]); return s->regs[reg]; } @@ -977,6 +990,18 @@ static void aspeed_ast2700_scuio_write(void *opaque, hwaddr offset, trace_aspeed_ast2700_scuio_write(offset, size, data); switch (reg) { + case AST2700_SCUIO_RNG_CTRL: + data &= AST2700_SCUIO_RNG_CTRL_MASK; + if (data & AST2700_SCUIO_RNG_CTRL_DIS) { + data &= ~AST2700_SCUIO_RNG_CTRL_VLD; + s->regs[AST2700_SCUIO_RNG_DATA] = 0; + } else { + s->regs[AST2700_SCUIO_RNG_DATA] = aspeed_scu_get_random(); + data |= AST2700_SCUIO_RNG_CTRL_VLD; + } + s->regs[reg] = data; + updated = true; + break; case AST2700_SCUIO_CLK_STOP_CTL_1: case AST2700_SCUIO_CLK_STOP_CTL_2: s->regs[reg] |= data; From 59a3b57bab6c1e7104b9ebaa70b3f1c85fc4f2e4 Mon Sep 17 00:00:00 2001 From: Jamin Lin Date: Mon, 6 Jul 2026 05:27:08 +0000 Subject: [PATCH 7/8] hw/arm/aspeed_ast27x0: Add unimplemented Privilege Controller MMIO regions for SSP/TSP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The AST2700 SSP/TSP firmware accesses Privilege Controller MMIO regions that are not yet implemented in QEMU. This change adds unimplemented MMIO devices for the Privilege Controller blocks and maps them to their corresponding physical addresses in the SSP/TSP address space. These stub devices allow QEMU to safely handle firmware accesses and prevent spurious exceptions, while accurately reflecting the hardware memory map. No functional changes. Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Reviewed-by: Philippe Mathieu-Daudé Link: https://lore.kernel.org/qemu-devel/20260706052701.1141740-5-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater --- hw/arm/aspeed_ast27x0-ssp.c | 12 ++++++++++++ hw/arm/aspeed_ast27x0-tsp.c | 12 ++++++++++++ include/hw/arm/aspeed_coprocessor.h | 1 + include/hw/arm/aspeed_soc.h | 2 ++ 4 files changed, 27 insertions(+) diff --git a/hw/arm/aspeed_ast27x0-ssp.c b/hw/arm/aspeed_ast27x0-ssp.c index b3c4eb1915..e35c0c9a5a 100644 --- a/hw/arm/aspeed_ast27x0-ssp.c +++ b/hw/arm/aspeed_ast27x0-ssp.c @@ -22,10 +22,12 @@ static const hwaddr aspeed_soc_ast27x0ssp_memmap[] = { [ASPEED_DEV_SDRAM] = 0x00000000, [ASPEED_DEV_SRAM0] = 0x70000000, [ASPEED_DEV_INTC] = 0x72100000, + [ASPEED_DEV_PRIC0] = 0x72140000, [ASPEED_DEV_SCU] = 0x72C02000, [ASPEED_DEV_TIMER1] = 0x72C10000, [ASPEED_DEV_UART4] = 0x72C1A000, [ASPEED_DEV_IPC0] = 0x72C1C000, + [ASPEED_DEV_PRIC1] = 0x74100000, [ASPEED_DEV_SCUIO] = 0x74C02000, [ASPEED_DEV_INTCIO] = 0x74C18000, [ASPEED_DEV_UART0] = 0x74C33000, @@ -141,6 +143,10 @@ static void aspeed_soc_ast27x0ssp_init(Object *obj) TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "scuio", &a->scuio, TYPE_UNIMPLEMENTED_DEVICE); + object_initialize_child(obj, "pric0", &a->pric[0], + TYPE_UNIMPLEMENTED_DEVICE); + object_initialize_child(obj, "pric1", &a->pric[1], + TYPE_UNIMPLEMENTED_DEVICE); } static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp) @@ -255,6 +261,12 @@ static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp) aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->scuio), "aspeed.scuio", sc->memmap[ASPEED_DEV_SCUIO], 0x1000); + aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->pric[0]), + "aspeed.pric0", + sc->memmap[ASPEED_DEV_PRIC0], 0x1000); + aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->pric[1]), + "aspeed.pric1", + sc->memmap[ASPEED_DEV_PRIC1], 0x1000); } static void aspeed_soc_ast27x0ssp_class_init(ObjectClass *klass, diff --git a/hw/arm/aspeed_ast27x0-tsp.c b/hw/arm/aspeed_ast27x0-tsp.c index 6098d1aae3..fdc279cbf6 100644 --- a/hw/arm/aspeed_ast27x0-tsp.c +++ b/hw/arm/aspeed_ast27x0-tsp.c @@ -22,10 +22,12 @@ static const hwaddr aspeed_soc_ast27x0tsp_memmap[] = { [ASPEED_DEV_SDRAM] = 0x00000000, [ASPEED_DEV_SRAM0] = 0x70000000, [ASPEED_DEV_INTC] = 0x72100000, + [ASPEED_DEV_PRIC0] = 0x72140000, [ASPEED_DEV_SCU] = 0x72C02000, [ASPEED_DEV_TIMER1] = 0x72C10000, [ASPEED_DEV_UART4] = 0x72C1A000, [ASPEED_DEV_IPC0] = 0x72C1C000, + [ASPEED_DEV_PRIC1] = 0x74100000, [ASPEED_DEV_SCUIO] = 0x74C02000, [ASPEED_DEV_INTCIO] = 0x74C18000, [ASPEED_DEV_UART0] = 0x74C33000, @@ -141,6 +143,10 @@ static void aspeed_soc_ast27x0tsp_init(Object *obj) TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "scuio", &a->scuio, TYPE_UNIMPLEMENTED_DEVICE); + object_initialize_child(obj, "pric0", &a->pric[0], + TYPE_UNIMPLEMENTED_DEVICE); + object_initialize_child(obj, "pric1", &a->pric[1], + TYPE_UNIMPLEMENTED_DEVICE); } static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp) @@ -255,6 +261,12 @@ static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp) aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->scuio), "aspeed.scuio", sc->memmap[ASPEED_DEV_SCUIO], 0x1000); + aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->pric[0]), + "aspeed.pric0", + sc->memmap[ASPEED_DEV_PRIC0], 0x1000); + aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->pric[1]), + "aspeed.pric1", + sc->memmap[ASPEED_DEV_PRIC1], 0x1000); } static void aspeed_soc_ast27x0tsp_class_init(ObjectClass *klass, diff --git a/include/hw/arm/aspeed_coprocessor.h b/include/hw/arm/aspeed_coprocessor.h index 4a50f688ec..700cbfb4bb 100644 --- a/include/hw/arm/aspeed_coprocessor.h +++ b/include/hw/arm/aspeed_coprocessor.h @@ -48,6 +48,7 @@ struct Aspeed27x0CoprocessorState { AspeedINTCState intc[2]; UnimplementedDeviceState ipc[2]; UnimplementedDeviceState scuio; + UnimplementedDeviceState pric[2]; ARMv7MState armv7m; }; diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index 3aac144cd4..a0d2432620 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -295,6 +295,8 @@ enum { ASPEED_DEV_IOEXP1_INTCIO, ASPEED_DEV_IOEXP0_I3C, ASPEED_DEV_IOEXP1_I3C, + ASPEED_DEV_PRIC0, + ASPEED_DEV_PRIC1, }; const char *aspeed_soc_cpu_type(const char * const *valid_cpu_types); From 21eac78874d3404cb26c83f261af25e0cdcb9686 Mon Sep 17 00:00:00 2001 From: Jamin Lin Date: Mon, 6 Jul 2026 05:27:09 +0000 Subject: [PATCH 8/8] hw/arm/aspeed_ast27x0: Add unimplemented OTP controller MMIO regions for SSP/TSP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The AST2700 SSP/TSP firmware accesses OTP MMIO regions that are not yet implemented in QEMU. This change adds unimplemented MMIO devices for the OTP and maps them to their corresponding physical addresses in the SSP/TSP address space. These stub devices allow QEMU to safely handle firmware accesses and prevent spurious exceptions, while accurately reflecting the hardware memory map. No functional changes. Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Reviewed-by: Philippe Mathieu-Daudé Link: https://lore.kernel.org/qemu-devel/20260706052701.1141740-6-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater --- hw/arm/aspeed_ast27x0-ssp.c | 6 ++++++ hw/arm/aspeed_ast27x0-tsp.c | 6 ++++++ include/hw/arm/aspeed_coprocessor.h | 1 + include/hw/arm/aspeed_soc.h | 1 + 4 files changed, 14 insertions(+) diff --git a/hw/arm/aspeed_ast27x0-ssp.c b/hw/arm/aspeed_ast27x0-ssp.c index e35c0c9a5a..68a8ab26f7 100644 --- a/hw/arm/aspeed_ast27x0-ssp.c +++ b/hw/arm/aspeed_ast27x0-ssp.c @@ -29,6 +29,7 @@ static const hwaddr aspeed_soc_ast27x0ssp_memmap[] = { [ASPEED_DEV_IPC0] = 0x72C1C000, [ASPEED_DEV_PRIC1] = 0x74100000, [ASPEED_DEV_SCUIO] = 0x74C02000, + [ASPEED_DEV_OTP] = 0x74C07000, [ASPEED_DEV_INTCIO] = 0x74C18000, [ASPEED_DEV_UART0] = 0x74C33000, [ASPEED_DEV_UART1] = 0x74C33100, @@ -147,6 +148,8 @@ static void aspeed_soc_ast27x0ssp_init(Object *obj) TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "pric1", &a->pric[1], TYPE_UNIMPLEMENTED_DEVICE); + object_initialize_child(obj, "otp", &a->otp, + TYPE_UNIMPLEMENTED_DEVICE); } static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp) @@ -267,6 +270,9 @@ static void aspeed_soc_ast27x0ssp_realize(DeviceState *dev_soc, Error **errp) aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->pric[1]), "aspeed.pric1", sc->memmap[ASPEED_DEV_PRIC1], 0x1000); + aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->otp), + "aspeed.otp", + sc->memmap[ASPEED_DEV_OTP], 0x800); } static void aspeed_soc_ast27x0ssp_class_init(ObjectClass *klass, diff --git a/hw/arm/aspeed_ast27x0-tsp.c b/hw/arm/aspeed_ast27x0-tsp.c index fdc279cbf6..b8a4f7c91d 100644 --- a/hw/arm/aspeed_ast27x0-tsp.c +++ b/hw/arm/aspeed_ast27x0-tsp.c @@ -29,6 +29,7 @@ static const hwaddr aspeed_soc_ast27x0tsp_memmap[] = { [ASPEED_DEV_IPC0] = 0x72C1C000, [ASPEED_DEV_PRIC1] = 0x74100000, [ASPEED_DEV_SCUIO] = 0x74C02000, + [ASPEED_DEV_OTP] = 0x74C07000, [ASPEED_DEV_INTCIO] = 0x74C18000, [ASPEED_DEV_UART0] = 0x74C33000, [ASPEED_DEV_UART1] = 0x74C33100, @@ -147,6 +148,8 @@ static void aspeed_soc_ast27x0tsp_init(Object *obj) TYPE_UNIMPLEMENTED_DEVICE); object_initialize_child(obj, "pric1", &a->pric[1], TYPE_UNIMPLEMENTED_DEVICE); + object_initialize_child(obj, "otp", &a->otp, + TYPE_UNIMPLEMENTED_DEVICE); } static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp) @@ -267,6 +270,9 @@ static void aspeed_soc_ast27x0tsp_realize(DeviceState *dev_soc, Error **errp) aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->pric[1]), "aspeed.pric1", sc->memmap[ASPEED_DEV_PRIC1], 0x1000); + aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&a->otp), + "aspeed.otp", + sc->memmap[ASPEED_DEV_OTP], 0x800); } static void aspeed_soc_ast27x0tsp_class_init(ObjectClass *klass, diff --git a/include/hw/arm/aspeed_coprocessor.h b/include/hw/arm/aspeed_coprocessor.h index 700cbfb4bb..ac58a5f424 100644 --- a/include/hw/arm/aspeed_coprocessor.h +++ b/include/hw/arm/aspeed_coprocessor.h @@ -49,6 +49,7 @@ struct Aspeed27x0CoprocessorState { UnimplementedDeviceState ipc[2]; UnimplementedDeviceState scuio; UnimplementedDeviceState pric[2]; + UnimplementedDeviceState otp; ARMv7MState armv7m; }; diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index a0d2432620..41dc04e293 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -297,6 +297,7 @@ enum { ASPEED_DEV_IOEXP1_I3C, ASPEED_DEV_PRIC0, ASPEED_DEV_PRIC1, + ASPEED_DEV_OTP, }; const char *aspeed_soc_cpu_type(const char * const *valid_cpu_types);