From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954367; cv=none; d=zohomail.com; s=zohoarc; b=nOj+Az1yvZsBlJ8oAWwmnXFfJ70nO892gh+Mda7iI8dycvU8L9F75193P1SbEM4xmib3XbzjDi+RSTEspgi6BJ7NX35FU0nU7bSLjqNAScNs/KeD2oIDTbjmK+kxuVVSpxMlTwkEMl8pdR0JZb422pTHzaMjWsHjBMxds7kldBM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954367; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=+xp85ow5kpVEIh7GcBSWk2I9/oWDLBJKDiTKs7ARoRw=; b=F6LkVd0IqkshjEfDTxL2xMoOq0T7yowp/qNa0qXJdfdq6Y+i5IdECShjey+Pu5zoGp7Bxe8iOTdb3iPYzcpvYqWwekJ//aEQeZ9fEjaqrO7taFwYt8rm2NoFaUS9c+Mx4q3tkHRFu7shM/iUXhGvv7KiG2+5TIuoyS7jiYw8OeE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954367891957.4414172521147; Sat, 7 Mar 2026 23:19:27 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8PP-0006ab-M9; Sun, 08 Mar 2026 03:18:39 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8PO-0006Zr-21 for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:18:38 -0400 Received: from mail-dy1-x1344.google.com ([2607:f8b0:4864:20::1344]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8PM-0001Em-AB for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:18:37 -0400 Received: by mail-dy1-x1344.google.com with SMTP id 5a478bee46e88-2be3bdfda8eso3686710eec.1 for ; Sat, 07 Mar 2026 23:18:35 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.18.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:18:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954315; x=1773559115; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=+xp85ow5kpVEIh7GcBSWk2I9/oWDLBJKDiTKs7ARoRw=; b=SWQrwajeQgQrO3U8qG73hYzhoxIIWO1JKgckolTj2Gp3wqyovDm2l0U76AOxhVhNNC oW6Msz42nPERA30TDY48ELGbsf7JoaN1r9Gb1f+HBirHHWjKq838/9hFk90wfZ2zW0qp t/X5ox/cn8+3dpFjY+yA9DBQ1Q37XPdc4xfH9/Ah811KpCAJkk4agkb5QW25B/ZBloT8 AXzNDwGOsVDWa3oakV6iR04m3uvtd5mXyWsuYMwbQe3BYfi3vEIJeH9T/2/A0kt2/Iv/ Rh5pkIEMGZ1CufHFPdsc9SsMq7Otu8kgrJNak+i4dTit9R0JSArnzSspkMF1bIvcwxHe 1xlg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954315; x=1773559115; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=+xp85ow5kpVEIh7GcBSWk2I9/oWDLBJKDiTKs7ARoRw=; b=TSuvTLEjDPXEgPO8zEAao+furBiqvn1QQG/7lz+9gA6p4AS0WZhlTALdjs63Fq6nvV FIcaQI/IkUgsxZqfduKzTYZrRpLPM2n03JwX14edPWz5LCdTt/vOmoC8e63iujBlS/mC JtAkPUCuyQLd1+lyPQt/B99hBFbW3+W4ypQ2Y1opYo3Kx0qHSI8AG80jV7pXgCsiLj/c 0ny06bTsK4Z/R0Wr/JkaGBKlzCJhM2uoIqrpLVGUfCVo+zG2/TXN6D/QcXCeL16i5Hd9 o2rpT2G3Xu4YV3djxoTX/0ZSsWxMTR8TvUXUDivZnravOwqJOEq67G8uW/cqx1uj9S0X XF+g== X-Forwarded-Encrypted: i=1; AJvYcCXvTWKNKnIskGRjyh8OEsN14wrIQdlCja6Lm/FdKTnZGX4y2xgWOmKe0msD1KLpd7h4xLGGUO4vR3d4@nongnu.org X-Gm-Message-State: AOJu0YxZg2iPdAwLK9lHey1ppOjOYNGUzjwNN6/jGGUrcJF4s2wD3Grf mWJxoCemJG+pPpLYTBafRMSQlcVp+aPfftUPf3cSfdtZFLm85/0+ZwqV X-Gm-Gg: ATEYQzx6DsjIAdEaqayk5nexYvNmpQOMUTWEHan479j7/jX0nHvBX10ihlnuBVIHHiN S3UQENscmI4cAT9m+YcIi23KNcy0kosoOntrs3Z3+AovfjnJbYX7OaofRtPoszxOH/MixgzmEUc BbG5zMZLrGrE571yHEOSuNQgeCLBCtJUNEiaIwUr/L3/M01s94s0pwa2Hy7AojtRuU+vzfbqqeg nbD8dw7qs85LBSm2lf1cQBwn8CtjTw0fgazMYTKRa4vjeG0bI0cVocaXBw1jHmaQAE/jBVjsipY 282HQ9vFgn8LHUVkbRDlndLEP/KupVz+79fOLZKQL36eUPYhDg1DXcLfGkAkYtsuX1+aJrkCsBL YEm2yzQLztGIJ3l7kAO1QrIPrl3seIpfPTBbdPm4zLq7IqCE6ZKpmXOdZWxXsxhsKeA+V14xqpk U734p0M+HpXRAxfVkvjBIBcpCwaf/CITpzK0fLsMlyKcfUFW/Bi2fzDBV+yWwcOEltEDWXRp3ih VCfLhl6KtsUKnDuSrBgQlZR4i0= X-Received: by 2002:a05:7300:5711:b0:2be:1946:857e with SMTP id 5a478bee46e88-2be4de8fc67mr2577367eec.12.1772954314717; Sat, 07 Mar 2026 23:18:34 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 01/28] target/riscv: track pending Debug Module halt requests Date: Sun, 8 Mar 2026 15:17:04 +0800 Message-ID: <4baa12f9284a5a4fc543ae7c82cc26814a10c973.1772936778.git.chao.liu.zevorn@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1344; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1344.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954368961158500 Content-Type: text/plain; charset="utf-8" Track a pending board-level Debug Module halt request in the CPU state so machine code can queue haltreq and reset-haltreq before the hart reaches the normal debug entry path. Add the CPU-side helper, the GPIO input, and the migration state needed to preserve the pending request and its debug cause across machine resets and VM state transfers. Later patches will route this state through the regular interrupt and Debug Mode entry flow. Signed-off-by: Chao Liu --- target/riscv/cpu.c | 68 +++++++++++++++++++++++++++++++++++++++++ target/riscv/cpu.h | 5 +++ target/riscv/cpu_bits.h | 1 + target/riscv/machine.c | 2 ++ 4 files changed, 76 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 470c2d5b39..fce778a67d 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -784,6 +784,8 @@ static void riscv_cpu_reset_hold(Object *obj, ResetType= type) =20 #ifndef CONFIG_USER_ONLY env->debug_mode =3D false; + env->dm_halt_request =3D false; + env->dm_halt_cause =3D DCSR_CAUSE_HALTREQ; env->dcsr =3D DCSR_DEBUGVER(4); env->dpc =3D 0; env->dscratch[0] =3D 0; @@ -1086,6 +1088,70 @@ static void riscv_cpu_set_nmi(void *opaque, int irq,= int level) { riscv_cpu_set_rnmi(RISCV_CPU(opaque), irq, level); } + +/* + * Debug cause priority (higher to lower), per Debug Spec v1.0 Table 4.2: + * reset-haltreq, halt-group, haltreq, trigger, ebreak, step. + */ +static int riscv_debug_cause_priority(uint32_t cause) +{ + switch (cause & 0x7) { + case DCSR_CAUSE_RESET: + return 0; + case DCSR_CAUSE_GROUP: + return 1; + case DCSR_CAUSE_HALTREQ: + return 2; + case DCSR_CAUSE_TRIGGER: + return 3; + case DCSR_CAUSE_EBREAK: + return 4; + case DCSR_CAUSE_STEP: + return 5; + case DCSR_CAUSE_OTHER: + return 6; + default: + return 7; + } +} + +static bool riscv_debug_cause_is_higher(uint32_t new_cause, + uint32_t current_cause) +{ + return riscv_debug_cause_priority(new_cause) < + riscv_debug_cause_priority(current_cause); +} + +void riscv_cpu_request_dm_halt(RISCVCPU *cpu, uint32_t cause) +{ + CPURISCVState *env =3D &cpu->env; + CPUState *cs =3D CPU(cpu); + + if (!riscv_cpu_cfg(env)->ext_sdext) { + return; + } + + if (env->dm_halt_request && + !riscv_debug_cause_is_higher(cause, env->dm_halt_cause)) { + return; + } + + env->dm_halt_request =3D true; + env->dm_halt_cause =3D cause & 0x7; + cpu_interrupt(cs, CPU_INTERRUPT_DM_HALT); +} + +static void riscv_cpu_dm_halt_req(void *opaque, int irq, int level) +{ + RISCVCPU *cpu =3D RISCV_CPU(opaque); + CPURISCVState *env =3D &cpu->env; + + qemu_log_mask(CPU_LOG_INT, "dm_halt_req: level=3D%d ext_sdext=3D%d\n", + level, riscv_cpu_cfg(env)->ext_sdext); + if (level) { + riscv_cpu_request_dm_halt(cpu, DCSR_CAUSE_HALTREQ); + } +} #endif /* CONFIG_USER_ONLY */ =20 static bool riscv_cpu_is_dynamic(Object *cpu_obj) @@ -1106,6 +1172,8 @@ static void riscv_cpu_init(Object *obj) IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX); qdev_init_gpio_in_named(DEVICE(cpu), riscv_cpu_set_nmi, "riscv.cpu.rnmi", RNMI_MAX); + qdev_init_gpio_in_named(DEVICE(cpu), riscv_cpu_dm_halt_req, + "dm-halt-req", 1); #endif /* CONFIG_USER_ONLY */ =20 general_user_opts =3D g_hash_table_new(g_str_hash, g_str_equal); diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 0d6b70c9f0..6fb255c7c3 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -481,6 +481,10 @@ struct CPUArchState { target_ulong dpc; target_ulong dscratch[2]; =20 + /* Pending Debug Module halt request from the board-level controller. = */ + bool dm_halt_request; + uint8_t dm_halt_cause; + uint64_t mstateen[SMSTATEEN_MAX_COUNT]; uint64_t hstateen[SMSTATEEN_MAX_COUNT]; uint64_t sstateen[SMSTATEEN_MAX_COUNT]; @@ -642,6 +646,7 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env); int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts); uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask, uint64_t value); +void riscv_cpu_request_dm_halt(RISCVCPU *cpu, uint32_t cause); void riscv_cpu_set_rnmi(RISCVCPU *cpu, uint32_t irq, bool level); void riscv_cpu_interrupt(CPURISCVState *env); #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value = */ diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index bb59f7ff56..01ec2a69c4 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -1177,6 +1177,7 @@ typedef enum CTRType { =20 /* RISC-V-specific interrupt pending bits. */ #define CPU_INTERRUPT_RNMI CPU_INTERRUPT_TGT_EXT_0 +#define CPU_INTERRUPT_DM_HALT CPU_INTERRUPT_TGT_INT_0 =20 /* JVT CSR bits */ #define JVT_MODE 0x3F diff --git a/target/riscv/machine.c b/target/riscv/machine.c index ddd0569d9e..e811abc868 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -263,6 +263,8 @@ static const VMStateDescription vmstate_sdext =3D { VMSTATE_UINTTL(env.dcsr, RISCVCPU), VMSTATE_UINTTL(env.dpc, RISCVCPU), VMSTATE_UINTTL_ARRAY(env.dscratch, RISCVCPU, 2), + VMSTATE_BOOL(env.dm_halt_request, RISCVCPU), + VMSTATE_UINT8(env.dm_halt_cause, RISCVCPU), VMSTATE_END_OF_LIST() } }; --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954426; cv=none; d=zohomail.com; s=zohoarc; b=UK3WOSoxnZwKNnhT27OHFuV1MTzhKtkq7vXsOE68okSOu+XE/Xmq5/sEslYQGqI0ikOTRsL9S1sHqPsmUkeqX4Ny+g8+7uJJtrNk9TdSgvMHc30OnLM/zrtT0IIekvLBn/mmCLYLdEKUvLjS6NRehf7+B2x148LPMNTft56DkDE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954426; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=KK9Uyjy96zs7twHNYpg5aWknY8afXFteBSqdlJa3j3g=; b=TiYycX5tEnVtkfUqBGJmH35KgNJrNz5iXrSDEu4o4fE1NkBzaHJHMdkD0Ov3O9DoAvmTD9bes0X79nRgOOiVdgDTecXfTakeraag1+7AHQBDUh9jG9hF8kdKQbqm6AqoaGyTfNuZkz2zSGr0eA24AwMADqColDmZdIdrlr7Egzo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954426288210.57651358802082; Sat, 7 Mar 2026 23:20:26 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8PV-0006bX-Of; Sun, 08 Mar 2026 03:18:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8PT-0006ay-U7 for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:18:44 -0400 Received: from mail-dy1-x1341.google.com ([2607:f8b0:4864:20::1341]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8PS-0001He-8b for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:18:43 -0400 Received: by mail-dy1-x1341.google.com with SMTP id 5a478bee46e88-2ba9c484e5eso9940140eec.1 for ; Sat, 07 Mar 2026 23:18:41 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.18.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:18:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954321; x=1773559121; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=KK9Uyjy96zs7twHNYpg5aWknY8afXFteBSqdlJa3j3g=; b=TomvkPgq7YOqx0j7KRMg7C5JttXpWAPozXSQrEOhN5LlgKEXr39z5P92m5l3S7NFRK tHf9Crk567/D/jKh8bke5LFycLYYZ8wrQWOnVccesJhbcYP1wUyJu9el3KHbu5HYYp7W 9z+vKZDuREH5TNwAONI1GRA3fqvfDNaNIs3Q8iAXkxLNwXvnlQJbE3Ft0sUcUVVLxMRi 619bd+wWBtx016Y0k0ZiCSSiLB555/cX1NO+E4+rShlP96a2zoaFHBNkYT9yFPFyEt0R dKpoQs4PGE9FwxGY0ptxc5pqjd5sfggZlQCzl3q2gAmAVBH+cIRPsbodfTb/7TQ2YkiX UGNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954321; x=1773559121; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=KK9Uyjy96zs7twHNYpg5aWknY8afXFteBSqdlJa3j3g=; b=k0og5926VNs/b4ML6wtAwHOP1Joa9g7t/laDrx20xxP5t5wwhzY/9b9d6zyPsP7GP0 3xycsJ/nkPKtB44OiVRe4uHxb4KLhBzTIoBJpXZ30FilIfoWrh7ZB6VcjWd7lb71FLGe 1v3icunzAnS2WaHkoKPGuMg8HsMP+mZAwQwmD6BS6QWfiWXxYisT2naiLbaCaC7FQXl4 hAHai1IjKlxPoXBr7BhNc4KCISe3XpfrInrYXL3+Ox/06nq6updYBJw2wlKmEt9S8Cbk 9RUM9dLeMMeLfm8XObK3TXiA3l5dIJY2MEN7hkMYFOwJE8DQc1TVr4th/tUJ6Zf8kvnI zNaA== X-Forwarded-Encrypted: i=1; AJvYcCWLVxaYA/IMR4MwrcvvMrTG9aNjWUjpLGl6BveHtLVM+2KSswEgIC88JQzyMtJghbuSzWfI7OSKhZuz@nongnu.org X-Gm-Message-State: AOJu0YyDlgakQlebC6LwOZQ+HLPrxjc9d3ElKh99pA5eib+7TJjZwigl 5CiQOS0OwPqi5I/m0nDa12OCOnGBmLF3a74T33pOAZgq+N5vsOLdKcwg X-Gm-Gg: ATEYQzzrWDfXOXtJAaEuMywYfgb/A08g428lmk1Frhzc25PCOMSoJZrFQLsfkZC8HB9 cuP0lFKmK6UGOnNX+Gz1HjDFJhg7pztaN7ZhQgCmTxEas4I00XtodIRSMpgaItKpvK/UnpYJHif s9tJNoIHKkFqNzdUDU2EHzlejH+416HsdpzM84tho8OZO/dvT6nmD2VfsHPXPWCVrHsOAJFNHu9 EdZjDRtfckLqmv0vQXu3+Bl9JOAIX3naHvngqUp+TBWYoE/bBQGPGJdbaBXtUVJetrjPnkU+8fm cU1f6fEnET7OkNYfjKk+yw9aEQgK3JRjduu7l6F6hFtdY+6bA6b/E+o+JNQPDbvWPNWf4bWpv1L nmyK/UcGKmgxhy9d0R/hyOBwqRVFsgZcifKZoZN54h+znQhZiHk5bM3nEg6pb7Y4XnPOfNG01lj 0JB1b2blw3jydaQ61XHlQGoc3Pv7EW+CLvpuP0Jw5m6aC1/LH1YJ/j6hS8uhGLGRnPoI/qPjn9y 9tu3Kop4bnSOMBMz9ytajNI1IY= X-Received: by 2002:a05:7300:cb17:b0:2b7:3281:6c64 with SMTP id 5a478bee46e88-2be4e007aebmr3003941eec.14.1772954320781; Sat, 07 Mar 2026 23:18:40 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 02/28] target/riscv: keep Debug Mode active when a DM ROM is present Date: Sun, 8 Mar 2026 15:17:05 +0800 Message-ID: <50bb827520cc1fc9e913a6293e5fe30c355a5a69.1772936778.git.chao.liu.zevorn@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1341; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1341.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954428333154100 Content-Type: text/plain; charset="utf-8" Record whether a hart has a Debug Module ROM entry point and keep the CPU in Debug Mode while that ROM is active, instead of always returning to dpc on the next exec loop entry. This updates Debug Mode entry so dpc follows the architectural cause rules, switches ROM and Program Buffer execution to M-mode, and lets later DM patches hand control to the ROM park loop. Signed-off-by: Chao Liu --- target/riscv/cpu.h | 4 +++- target/riscv/cpu_helper.c | 27 ++++++++++++++++++++++++++- target/riscv/tcg/tcg-cpu.c | 10 ++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 6fb255c7c3..0bc14f6953 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -481,9 +481,11 @@ struct CPUArchState { target_ulong dpc; target_ulong dscratch[2]; =20 - /* Pending Debug Module halt request from the board-level controller. = */ + /* DM halt request (set by external Debug Module GPIO) */ bool dm_halt_request; uint8_t dm_halt_cause; + bool dm_rom_present; + uint64_t dm_halt_addr; =20 uint64_t mstateen[SMSTATEEN_MAX_COUNT]; uint64_t hstateen[SMSTATEEN_MAX_COUNT]; diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index a0874f4e23..714dcb446e 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -141,6 +141,24 @@ static bool riscv_sdext_enabled(CPURISCVState *env) { return riscv_cpu_cfg(env)->ext_sdext; } + +/* + * Debug Spec v1.0 Table 9: + * - ebreak: dpc =3D address of the ebreak instruction. + * - step/trigger/haltreq (and reset/group/other): dpc =3D next instruction + * to execute when Debug Mode was entered. + */ +static target_ulong riscv_debug_dpc_on_entry(CPURISCVState *env, + target_ulong trap_pc, + uint32_t cause) +{ + switch (cause & 0x7) { + case DCSR_CAUSE_EBREAK: + return trap_pc & get_xepc_mask(env); + default: + return env->pc & get_xepc_mask(env); + } +} #endif =20 void riscv_cpu_enter_debug_mode(CPURISCVState *env, target_ulong pc, @@ -152,7 +170,7 @@ void riscv_cpu_enter_debug_mode(CPURISCVState *env, tar= get_ulong pc, } =20 env->debug_mode =3D true; - env->dpc =3D pc & get_xepc_mask(env); + env->dpc =3D riscv_debug_dpc_on_entry(env, pc, cause); env->dcsr &=3D ~(DCSR_CAUSE_MASK | DCSR_PRV_MASK | DCSR_V); env->dcsr |=3D ((target_ulong)(cause & 0x7)) << DCSR_CAUSE_SHIFT; env->dcsr |=3D env->priv & DCSR_PRV_MASK; @@ -168,6 +186,13 @@ void riscv_cpu_enter_debug_mode(CPURISCVState *env, ta= rget_ulong pc, } env->elp =3D false; } + + /* + * Per RISC-V Debug Spec v1.0 Section 4.1: + * "All operations are executed with machine mode privilege." + * Switch to M-mode so ROM/progbuf fetches use physical addressing. + */ + riscv_cpu_set_mode(env, PRV_M, false); #endif } =20 diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 53d862080c..4674ff3e3c 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -280,6 +280,16 @@ static void riscv_cpu_exec_enter(CPUState *cs) if (!cpu->cfg.ext_sdext || !env->debug_mode) { return; } + + /* + * When a DM ROM is present, the CPU must stay in debug mode and + * execute ROM code. DRET will leave debug mode later. Without a DM + * ROM, leave debug mode immediately (legacy shortcut). + */ + if (env->dm_rom_present) { + return; + } + target_ulong pc =3D env->dpc; riscv_cpu_leave_debug_mode(env); env->pc =3D pc; --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954366; cv=none; d=zohomail.com; s=zohoarc; b=Bj6Ir2gL6khUByF6gLE5npqTRyfeV44VlhH3Q+Ktbv7xX4dojjtvStlK8D+X8jgrBIh2Cu3C28wgVYeaXkVhGrOMvoHqvJ8ZATShCC65zjF0QlZaJ0xUepux3IBHRXczlYNkfOrwO/R7aYElcJngVx5WyWam0CtMI1v8houwLqM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954366; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=qhdf6+VhGm1VbDUsJVUdk3p4/TzAmoSvruGWW5HiuPU=; b=Wim/OQcgNMcz99PGqpQUTvu240B9+PnWIRwcXGx5nyhqx/ScffYkYULDrUawsp+mebLMmoZuaangc3b5SIx3vXqHxwxjr1Vq3RhRsPfKiFFm5kNX1YFKQvktVjngt0XmxzFNlo+0CpLqgdvos2noH9fVJ+tluQUvuYu5vyQmg50= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 177295436622945.346750154339475; Sat, 7 Mar 2026 23:19:26 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8Pb-0006dW-MD; Sun, 08 Mar 2026 03:18:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8Pa-0006dF-PK for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:18:50 -0400 Received: from mail-dy1-x1343.google.com ([2607:f8b0:4864:20::1343]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8PZ-0001Ly-BO for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:18:50 -0400 Received: by mail-dy1-x1343.google.com with SMTP id 5a478bee46e88-2be19f05d7dso3689893eec.1 for ; Sat, 07 Mar 2026 23:18:48 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.18.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:18:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954328; x=1773559128; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=qhdf6+VhGm1VbDUsJVUdk3p4/TzAmoSvruGWW5HiuPU=; b=QNKZqywTWAvGEpCfWV+RYDgKRfMLVzqoRhfxtX1TlCsAK9bIo3p9vfD0U9A6Jp+hvY 46pp843rGvkZ3RQ4SrmnvmCxrt0jbEvSL7P6JQhouZtaIZWoRDMynRJ6vXwINTd4HfcK kGh2jbKYqqn7ZiaWwC4BLuLmZ5iDkU1jSvHDonENjbpl7llnN02xurxUj7Gt5gM6RyT8 UkowlA60fMC/fpnMy7eTWXQpUqGf4JV+ZiXy8arXB9wn16zUhCrjJ1H88Q5eIKybovFK EuTKvTXihHO3Ob+Ek6rIJy1k1E9KZayCF5JOdajFWRa5/XIa4Im40IUugpCTC03t+d+Y 1iJQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954328; x=1773559128; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=qhdf6+VhGm1VbDUsJVUdk3p4/TzAmoSvruGWW5HiuPU=; b=dVtmiJ1tuM/25IETfgvaGNpbTzZteoIfeTMM0RaA72yR0BkSztagmc0IAZgKHz2Zad 2GKMbzHU9lob/NiEGRWOfPdDqr+6oJnMzRLcrO3BGdprJ7LO2JHZz7YXnDw3ZEfrxydZ npcU9XXnHZEkNGNNW+XTKL/surWwbIFkRkH3PtZzjET13BSrUMFPV0g951ZVAREq9KQG dYl4uND/3GUHx4q5d4yybrJZ8Y7K4uOAvzVXEI5M2XASNWletqGknxZV1WmYazNHUEGZ 7qegjGjiRgU+Ib+ZPhK+veWUAOMRcawxwK+izbONDyECP65aanRMw0jnw6yuy1zKaRSA jGMQ== X-Forwarded-Encrypted: i=1; AJvYcCVAl/MDwgqw04cVkPhlN2uVmKThRmDLmrbJ1MZtocFAVm4BVQe+WAfFM/Fx32iEPpbbJnrJrr4tky+C@nongnu.org X-Gm-Message-State: AOJu0Yzsc16Cw3yMunUimN6LGwQ7XtbEci2BSGS3f7gVUXhvwV+HSKMH U3gfyQuCTco9tNA7n6DG6eqaDYmCfa5QYLqsBxB5Hwl6Ry+aycGqd8Nh X-Gm-Gg: ATEYQzxJr3XYavciyu0aJ170HRHvr8kTqscX6s+gpKEqud/hf2IZC0+l3trKq5kpJM/ 6e9fp9ZaIa2ibHISF2X0sd2gKxIsg0kUhiY831xcTFUz0JWEam0MbnGqCRf1M/wyuZy6b3Lej9h 01DVG2EvUx37Zan0bwoO18/eiZjVNejjsPZ1kLsl9+KT2LiGP9rzkNt65+zEcBDg6ytF+OK16Hv 5RewYOK2daA+GKgILAqBPBv/AoLoPV3zTUG7pgLe7UWS3w41qVE2jcSXm/IDRzpfdJly5yLCXCG QC3pw5B39tEw3cjO5szJ5YtO8jo3JyCCnFIgHS+jxei5EuZcvcdERGkE/Vb5rG9BKyvXKpi7kmI wpomk4XLNnNpBJ6rslATjwEyBCIYOOg49VURxxBvSd125eFyGtVnghd0vBYuBWsXwO4ULU7PjLn vz2WPLwfMOdsbVSRM0dpHzgt0pu2rUwGGcV2w2zRVkArlL82gMc6O5NcNGTV8jWT7tT9n5PH38k ampFb+XPQbVMNVRM5/IpT3yRrc= X-Received: by 2002:a05:7300:2393:b0:2be:2912:ff66 with SMTP id 5a478bee46e88-2be4e02bf42mr3642378eec.25.1772954327896; Sat, 07 Mar 2026 23:18:47 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 03/28] target/riscv: enter Debug Mode from pending DM halt requests Date: Sun, 8 Mar 2026 15:17:06 +0800 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1343; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1343.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954367815158500 Content-Type: text/plain; charset="utf-8" Consume pending Debug Module halt requests from the regular CPU execution path and enter Debug Mode with the recorded debug cause before normal interrupt delivery. This routes haltreq and reset-haltreq through the same entry path used by other debug stops, clears the pending request once it is taken, and jumps to the Debug Module ROM when the hart is wired to one. Signed-off-by: Chao Liu --- target/riscv/cpu_helper.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 714dcb446e..e477016d4a 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -655,12 +655,31 @@ static int riscv_cpu_local_irq_pending(CPURISCVState = *env) =20 bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { - uint32_t mask =3D CPU_INTERRUPT_HARD | CPU_INTERRUPT_RNMI; + uint32_t mask =3D CPU_INTERRUPT_HARD | CPU_INTERRUPT_RNMI | + CPU_INTERRUPT_DM_HALT; =20 if (interrupt_request & mask) { RISCVCPU *cpu =3D RISCV_CPU(cs); CPURISCVState *env =3D &cpu->env; =20 + /* DM halt request: enter debug mode before checking regular IRQs = */ + if (env->dm_halt_request && !env->debug_mode) { + uint32_t halt_cause =3D env->dm_halt_cause; + + qemu_log_mask(CPU_LOG_INT, + "exec_interrupt: dm_halt cause=3D%u pc=3D0x%" PR= Ix64 + " halt_addr=3D0x%" PRIx64 "\n", + halt_cause, + (uint64_t)env->pc, + (uint64_t)env->dm_halt_addr); + env->dm_halt_request =3D false; + env->dm_halt_cause =3D DCSR_CAUSE_HALTREQ; + cpu_reset_interrupt(cs, CPU_INTERRUPT_DM_HALT); + riscv_cpu_enter_debug_mode(env, env->pc, halt_cause); + env->pc =3D env->dm_halt_addr; + return true; + } + if (cpu->cfg.ext_sdext && !env->debug_mode && (env->dcsr & DCSR_STEP) && !(env->dcsr & DCSR_STEPIE)) { return false; --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954396; cv=none; d=zohomail.com; s=zohoarc; b=dp2qqtctAjVAL5ddWwbPGCkTmMSsURTqBSK2kR1liAZiTYxXhP7wUdC7KXyUBRDwtOIVkHcLkpPf6YNWJyGm3EWY9cwacZoX4BTuDcovr7n4VBwHgrEIwvqxA/CLobZappTpT/Fvl/Ca7iUD4JHgqS+ZSDv0szs4DFk1WV2v+uY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954396; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=bYcU9A1WiITUSWFwxQC1FMA42v4mgGSsjlTStLdxexA=; b=MmSv2eXW7+V1GTld626Xr0RHhjAoUBwSm4F7L0qizj0al+ZuoYgYFGmb7xKSOUejRf2wPU9fz4XHN3/mjdAq8vuIhwxJUiHtNCKPpdQTZlm7Wr5YTbwX/12j2wgPYUGX8aDUKQj8BxH+iw4gQjMi+Y8V0DgUKErG4MJKvlYCVRw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954396811327.50825079541846; Sat, 7 Mar 2026 23:19:56 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8Pi-0006fw-Cj; Sun, 08 Mar 2026 03:18:58 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8Pg-0006ec-JQ for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:18:56 -0400 Received: from mail-dl1-x1243.google.com ([2607:f8b0:4864:20::1243]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8Pf-0001Pn-5Y for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:18:56 -0400 Received: by mail-dl1-x1243.google.com with SMTP id a92af1059eb24-12732e6a123so1413881c88.1 for ; Sat, 07 Mar 2026 23:18:54 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.18.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:18:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954333; x=1773559133; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=bYcU9A1WiITUSWFwxQC1FMA42v4mgGSsjlTStLdxexA=; b=W8sh9T4dlUUiW77XYG/o9i2eoLkP3xX67rxpxCFGhFlXRMcNacoXUpMh2AVYb82qsY 5S9BNrXzd2r/EAL2jcgYnsIrr6HXcAoULzlaQZlzKYev65WGepQcY4giKfbw06U6U43c caaNI7DiJIUSrPi2wqw0DLKJbYptB+JU+7HUjMWJXD56hlRItxoqOAF7t8ckR6qZSSfl GCqjWn2H/sxMMpzFJxIbF2NhuzowuZ04KIZqYaeGUj4+W7HEE7Y4Dq0eV84oMreoKQhK et0bRAM6KrExLLlAku9/xnbpXLKlTvFMFGzI45pKSHT+TdBc7dDTmnU2t2LCAAaJ9TeS F0ow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954333; x=1773559133; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=bYcU9A1WiITUSWFwxQC1FMA42v4mgGSsjlTStLdxexA=; b=o4uoQuly3TOirh42blwxRMJgAg/ycyBGvsc0x2KiuBMBlY3Q6tJoP5oV+Y1aAGgmX7 eBnZjqOhrBl0VIOI7QyC0m6H4rzbbT/BSYKWCnd5v1KcwcTsKo8Fr20fig4oSC9woRLu 7RxXikmZesPXeo+a6llxy1QxTRRA0y45xBylaUdADhYye/JVlwh3Tfho/4fBO84IuaN6 4R3/JlbTcRkOkrhh8oZ2CnpLQpGRoEvaXwzcFZrxugTf5dD9EEIMDc6n1g2Bck3x09PR wJIeacLFTTz5u50Hfn6EOYZFj5mDCFBeVAO+0KJIcCYoSYPJVwK3ghkWflf0SVgCVhVy coTQ== X-Forwarded-Encrypted: i=1; AJvYcCXRoYnBM+tT/g2PgkGjEcjp8VLIAVKIUOH+kuDuUuWN3dayqkyIuszvf8fVaV2yGvqRnOwUSSRncTDG@nongnu.org X-Gm-Message-State: AOJu0Yy463PNKgKYzRfEYlUOLI5xTeVO6Kknyx1J7+M7k4Uju9dPm4J2 BchDXH0uZ5QgHqDaJgjTK5BNqSHfl0Kra2qdkK9cBA43amhbNz5j9we5 X-Gm-Gg: ATEYQzx2+4SNQGS5vt9msMaP7LUePP2lnLLJ+PBO0wOp1LZEP8fF3v75MLYHMXP++CR Z71HxCwKQjM0K2u0AklWB8DS3BZo1SyEk8gHb8v8wjLf/kk146VU+8E2LfeBEzB2qJafj3iGJwi htEwRVINgTN/2VvVFeDgp/YsSxtRVowq4dkDIwNqTr81/EWEmiYfuYadjwlqCNwxvqgWdJLHxLy eY39Nj762acgMKxfaxPV0lSq9JY+ATRmEW8RkL5aSxju48cXmLyRTrxlWcdiNl7cvmfrwbeP1eS mAfVnCduydzPv2cREy7bmymj49qxwZvEDfQ+qHs8Chy3NpDxXB1Ofi5vpHENqmJq7Q6ghKoMh4M 1VKLCTZCopkVYfPNsuBREGwb0gyX50grQATkQ2/UjJ7rM4NCEdysIs/+K6/QwE7ZctI2RW4CeMU /ZuMyE0lte1z2WzAXft7RcRGlBxD7u4nITVr//OVY0YY9qCN0i83ikDfKIzRi3Fl7EaT4padkKz UB1CeKEp8mAGKXqbnIprtdACAc= X-Received: by 2002:a05:7301:1009:b0:2be:3f:307c with SMTP id 5a478bee46e88-2be4e0644camr2877195eec.29.1772954333513; Sat, 07 Mar 2026 23:18:53 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 04/28] target/riscv: route in-debug exceptions back to the DM ROM Date: Sun, 8 Mar 2026 15:17:07 +0800 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1243; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dl1-x1243.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954399231154100 Content-Type: text/plain; charset="utf-8" When a hart is already executing from the Debug Module ROM, redirect synchronous exceptions to the ROM exception entry instead of taking the normal trap path. This keeps the hart inside the Debug Module state machine and lets the ROM report command faults through its mailbox protocol. Signed-off-by: Chao Liu --- target/riscv/cpu_helper.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index e477016d4a..81b74f7e4a 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -142,6 +142,9 @@ static bool riscv_sdext_enabled(CPURISCVState *env) return riscv_cpu_cfg(env)->ext_sdext; } =20 +/* DM ROM entry window offsets: exception vector is entry + 0x10 (0x810). = */ +#define RISCV_DEBUG_ROM_EXCEPTION_OFS 0x10 + /* * Debug Spec v1.0 Table 9: * - ebreak: dpc =3D address of the ebreak instruction. @@ -2326,6 +2329,15 @@ void riscv_cpu_do_interrupt(CPUState *cs) return; } =20 + if (env->debug_mode && env->dm_rom_present) { + /* + * Exceptions taken while already in Debug Mode are handled by the + * DM ROM exception entry (0x810 in the backing ROM). + */ + env->pc =3D env->dm_halt_addr + RISCV_DEBUG_ROM_EXCEPTION_OFS; + return; + } + if (!async) { /* set tval to badaddr for traps with address information */ switch (cause) { --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954451; cv=none; d=zohomail.com; s=zohoarc; b=CKGxDcvITdQpnh2RzLmeDJhHPK4KY7YHuaULTlCoPQ4J1Mt8R0s/KLw4ITw2LstK8Frp+ot4AVMdBKiImLDqlJxbLBy9ormJ1srcNT9RGkw3j039LbATnpeCdXVNYu6jvnKlMzSOeDpjV9np3qC+caJf9oxK3p4ynU+R2WEHyQk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954451; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=9uQNT9o2GLb9giYbEOFloxBJ8zsyJlWtCC5Gm5KoDGg=; b=HOPa9qUzUS4ekwumH3EJlroDAA9meTurmr06wB24gzCDS7OzZSEou7hPs3O9I+O+F/e2ffLfnbs3AouAE7e9T2vtV5xb91haj+KIsGrIWSmCTBCaPtKTFVG6cyjji6rKWuIgAw+bTsya9dvozY8+SGLcSAOBjDoNjVf1Cs8CLFA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954451210604.6069195629044; Sat, 7 Mar 2026 23:20:51 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8Po-0006h8-Te; Sun, 08 Mar 2026 03:19:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8Pn-0006gZ-BP for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:03 -0400 Received: from mail-dy1-x1341.google.com ([2607:f8b0:4864:20::1341]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8Pl-0001UO-1C for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:03 -0400 Received: by mail-dy1-x1341.google.com with SMTP id 5a478bee46e88-2bd9a485bd6so5550973eec.1 for ; Sat, 07 Mar 2026 23:19:00 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.18.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:18:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954340; x=1773559140; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=9uQNT9o2GLb9giYbEOFloxBJ8zsyJlWtCC5Gm5KoDGg=; b=jZMHWmo8nANlGPaXPGJPKOMIOVu7JxNTOeokl9+KJa1Uwth1YV0i9ixIAo880PHuU9 VZGLhEQaj6ngv+hhNlfczpdecRHvwaIhdA3GJKD8fyJ+XSAQU4HJ2AnFBdDxMhpG/JXF XIuKbPinihtX99LYKxht1GiQkH3H4Z2DhVBc1/jv6nzXrrYEorFxEipR+apmKtCsT+EA QjY1rWCxOCCKQ3j7cMfm5WqIciXN8QhtZEehjifXodcLjg/bZWiKJYcnbCE1CWy2dVUy 2Lv8ypEbS0efk0Y5/T7xjVa4KsI9lGnFI+UjxCajQT1fkQIph8yHQbyMVJvcTqrX00iw /QMg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954340; x=1773559140; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=9uQNT9o2GLb9giYbEOFloxBJ8zsyJlWtCC5Gm5KoDGg=; b=L8vlVkvzR1R5G/M8QJw+VT9wbeYNQsFN9F0Am9RO/Rl1u9Dc8TLZqw+9Mg/olOu3Aj /uSb0HyvEXBZxZqcjBhSHSNJe8VONtdhwaVnFA9biexVlt83kBw4DSVXcoC3ZMyr3Gtb VDpVHAb84PSFksYyKdKeIQlcPMRNG0ucfAphKiLc4XnUBRUZjXwzsQ9OixcHqpN9qKFz AUP025rTv32NMcQT6kwXsKIZ369qDEfOkuGx2f7MmVKmh+rROvHR7GXl9cjAhgfU1uDT mwsNAX0x0WQyOeFKRgmAP4+OFtpUDZ6a+fQcKxO/VEYNdH1FGmLBURkO43QFVvSbQioj lJag== X-Forwarded-Encrypted: i=1; AJvYcCV97NY2DqGDz1TMwaEnFYILyMW/DSuzW/WQmRvykDKvZ6+CZLO9jG16IDqrH/BHU8GRlveU5wFK4AHe@nongnu.org X-Gm-Message-State: AOJu0Yw3HeQpZIjbzXPO9ILg8fiPQEvqXOEnfGZTaPS8k38ZsAYZQ4Ef G2QZQ0IeIwmlZ2HfU/GDHf8YfbTI7DEvYd8KS17K0lY8jg3I0pSgmNkg X-Gm-Gg: ATEYQzxv6BqAbyDR4hVHvkNLgT/9ksr+IWb1NkyJjoQvS4c1u84nAe/d0TOBMsseHdY a1+5HmfpirNhGsI0pNwXUYN0fjlgy3qJKeF6Ny0p0tJ9SnBZyhtT8D7dMF78jExYsG4Bbv58lt6 nUAd3SBPsXg2hK2IhIiWBK9OBbEGPD41ivd2geq0Sxp0MPwjTCPDwXHdbPlIpEd8r+n5fLo2LS4 pf1TGpil+hHCOQfPUhqxe7bogh3CDJLeQYc10RzhEkIxZOJlXNz/mUS3uGkT+IUvAa5Qf/Au39+ 7i7FLMcFczBcpSShvm0WCOHqJ3OORK+8/YQtyNH9c9E10p49eCDUhjlSUSLU7zpt3llM2asmxOI cXmFpdVWZl2wKQda1VZPxjtBjKue19jfoUdTAvgWUAq6mmdGcA7g01VjdP5DzJ6fdHd7YMn8hmg loTij8JIziB75cLA3RfdlDR4SgBsRoMVLBsQ+UAS0BwbaUsSaaHaxQQyQBoVZ0ZmpCsPeBR1oJv GZ9qlQ/C+bKzGXfsCfRHMq+bNA= X-Received: by 2002:a05:7300:e619:b0:2bd:d157:6786 with SMTP id 5a478bee46e88-2be4e03ab3emr3182506eec.25.1772954339699; Sat, 07 Mar 2026 23:18:59 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 05/28] target/riscv: re-enter the DM ROM after single-step completion Date: Sun, 8 Mar 2026 15:17:08 +0800 Message-ID: <6b320e8671c22dd26ad89df4fb8c90f3995514cb.1772936778.git.chao.liu.zevorn@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1341; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1341.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954453237158500 Content-Type: text/plain; charset="utf-8" When single-step finishes on a hart backed by a Debug Module ROM, restart execution at the ROM entry instead of forcing the legacy EXCP_DEBUG stop path. This lets the park loop observe step completion through the normal ROM flow and keeps single-step behavior aligned with the Debug Module run-control model. Signed-off-by: Chao Liu --- target/riscv/op_helper.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index e7878d7aa4..945688eca8 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -481,6 +481,10 @@ void helper_sdext_step(CPURISCVState *env) } =20 riscv_cpu_enter_debug_mode(env, env->pc, DCSR_CAUSE_STEP); + if (env->dm_rom_present) { + env->pc =3D env->dm_halt_addr; + cpu_loop_exit(cs); + } cs->exception_index =3D EXCP_DEBUG; cpu_loop_exit_restore(cs, GETPC()); #endif --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954370; cv=none; d=zohomail.com; s=zohoarc; b=RLH7OBaAJdGTZc+SBS2A+eOE0md1QkFF1KEpSpnpz7udjmprDrH8Ybo11qYUR/L16wLui0j1Zpng+R2bA3+wmdFWw+T6zkO8ELKwnffpq9lp4Tcd051ogo//MsQZQhdLOLvpbVb2XFvJAgBd2RNAVyPDIHtVNIepSQSc6KpE4To= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954370; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=+FYgaldNviBYwmlMbWUmbtHwZ6I6FRjtzV/+ajNVBhY=; b=GSWnTDPnzBFEC6oi0R0CfpHHw+xhfocj0dWE32GjVoM1yTmkDPBTVOcrzWmRFPaI64bkltV7nYwEN84TJgJaw1R5LUTwgbiKtaCWeSkjs/MvIh8/YuMtDgVgK+qX6abz8M/e4tVCshcsPh4y6LgfYtARFdZloBKUgkog0C0sguE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954370045753.158506041319; Sat, 7 Mar 2026 23:19:30 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8Pt-0006nR-DM; Sun, 08 Mar 2026 03:19:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8Pr-0006i2-Qu for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:07 -0400 Received: from mail-dy1-x1343.google.com ([2607:f8b0:4864:20::1343]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8Pq-0001YF-8x for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:07 -0400 Received: by mail-dy1-x1343.google.com with SMTP id 5a478bee46e88-2bdfc4b191fso6049491eec.1 for ; Sat, 07 Mar 2026 23:19:05 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.19.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:19:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954345; x=1773559145; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=+FYgaldNviBYwmlMbWUmbtHwZ6I6FRjtzV/+ajNVBhY=; b=dr+FZTy6dmyk6GYTkqE7POJtR6NBkWAtOpxNMAwHutumRXyCiI8JHF7mf4mFeDGzXZ 0YG478mKieYy4xNzFWV2Pa4QbYFV5Thy9NfuZBDeGdYHRBQHdKRX6J2rkC4EmjlQVMBI v1Ssx+ZCIpXiVqQZVghYFsUvVo3lYkYs2t7kgazstd7eHQaa37yUw4JP87swx431gHME a+Ib9aRnR5tVUGpiaIN3nxjSOFlih1G4KfNihAkACpd+wHiraORfeeiMMtgLvES9nzYn o+Ho+VCJDCBW5qDhY0zVMvDhgJgrYZgc6HQDhMZSpNNeC7c9Sb+8pxDCXi0VXPT+THYc ALFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954345; x=1773559145; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=+FYgaldNviBYwmlMbWUmbtHwZ6I6FRjtzV/+ajNVBhY=; b=LtIFHTmRYU+QI/06NykkEAS6LMk3P5GjRv0/2dg6xHRlROecgsKrSnNw3ZcdSnjg/n QpnZJw1dX6zRd27PxAe+LM8nggvWIQ0d67cIfly54/5xcOGErn5P+mJvvCu3sA15pAxR Aua83NsP8OHrfWVDxgYVuaKW49c2nJxhZc/+AfRERrvvv41Mx2txPJOaqSO7Q6WLmGkC zZwo5yeOFRKxVqhlZ97KPy/KWQE/yYqYfA3Ht4NDN4L/ChA8YSrhVf7ICB+gyDRdPzf4 jHzdaexv6WtYrDYrHd2WcXO5z5BIkXizPMqU9rvAr+gMSU/foTH4ez55f0Rn3P1xw2Zu JQ3g== X-Forwarded-Encrypted: i=1; AJvYcCWMGjyDxUd+se+dc+x2/9u+oRsHXieYqB/ZF3YDb2Z+AT+h/t59BE7Q7Bh0OI+TPqGuf3OG4HGg0fm7@nongnu.org X-Gm-Message-State: AOJu0Yz6QAv8ToSDi6VzTcKQzL7ZdEH+tj0AKHF2i9WEwCdUHPfHT+eG ugmSi6Tm4mnqfU5W6FOcNFtDNZ7Kz6qUxoMdzCjOSKuQEQ819EMesOOV X-Gm-Gg: ATEYQzzA5bblIYjGT2333TQF49hSqooESEl5xi0bP0SdJi+gCKlqo3xBo6FYaHQhe2H oHqi0oXt4kyBbK0vOG99u8nUgoc/XMnBNjtS53bV77550dmfzgl5svD7+KqyEbAe2GVtoErgmSh z7NleDXIJ9cOfz+WqHkYOeyY0+vtw8QciUt3ZgKATtS1EbQnFuVrLiR+ZsI7ccj6aTC+DoSXBRx RaCGtqdq/E75BoRagZ1eMSpgYpbN4NQytT/N4Qnwr1Wy3ypWskeZ+fsqPGv/wPpU2BsnvVBf/yf Mayb7RVb7BqAXBNrVoXzdsvf/sQQ4FLid45fioMrDGlTdDI+KMqGXphsIogadlHRwQH9SdRT7y3 mxpQwDyaQa3oX95l8HkoS51/pSimUubpNoF+/y7rdA1ziBV5Wn/LJrZrbjNTpLJmo8ldCtDxjW7 HUyydcvAuJwq4wUZ+3/FsOijfJAawmOkaijXwJEIJLQTlRFXKrt7FBgPfnmbL/hx5AUiwqBwLCG HMDjqnDV43hxkGAVA7R1uxlCvc= X-Received: by 2002:a05:7300:a887:b0:2ba:a60a:15ef with SMTP id 5a478bee46e88-2be4de8dea3mr3085524eec.1.1772954344869; Sat, 07 Mar 2026 23:19:04 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 06/28] target/riscv: let ebreak enter the DM ROM Date: Sun, 8 Mar 2026 15:17:09 +0800 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1343; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1343.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954372879154100 Content-Type: text/plain; charset="utf-8" When ebreak is configured to enter Debug Mode and a Debug Module ROM is present, restart execution from the ROM halt entry instead of reporting a legacy EXCP_DEBUG stop. This makes ebreak-driven debug entry follow the same ROM-based flow as haltreq and single-step stops. Signed-off-by: Chao Liu --- target/riscv/op_helper.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 945688eca8..7f2769f444 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -517,6 +517,10 @@ void helper_sdext_ebreak(CPURISCVState *env, target_ul= ong pc) =20 if (enter_debug) { riscv_cpu_enter_debug_mode(env, pc, DCSR_CAUSE_EBREAK); + if (env->dm_rom_present) { + env->pc =3D env->dm_halt_addr; + cpu_loop_exit(cs); + } cs->exception_index =3D EXCP_DEBUG; cpu_loop_exit_restore(cs, GETPC()); } --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954414; cv=none; d=zohomail.com; s=zohoarc; b=W9cD8ts99v0NwSWCAjYOZrlSVQ3mSHmSaBJQmWUgxpIJAxuRU9Sm27bHI4EiCHt7q9WaglKAQZ89AP0Tzf4Z+zCJ/yF9ircpkkhmWjCs0spFQbWZLLoUQHyTwhGzXyZBt5sRCBSW1L0Yl0kpbdVhOcYUN/rNSy4BIiqj0Y8CvT8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954414; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=3lqy3ttK62KbJsNvTyksmw8JT4cUz9wtpaOy468A04s=; b=d62yc5vrLlb7OvFcHinZCCO5v38tF0LII7LdiFVskLDXPAQXEbZH4S5qQqpNENr4xpzG9p5mBinkeG0UpKs/tSuHj18pejXGMRJdcD3JD7azM1eZL1tGDheC5bgvE2GglnoK/Na4leY/MIEfJDZi5NjiiaYGQeaKBsuAN4ULdCM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954414985759.827403607274; Sat, 7 Mar 2026 23:20:14 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8Py-0006sC-Or; Sun, 08 Mar 2026 03:19:14 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8Px-0006re-SP for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:13 -0400 Received: from mail-dy1-x1343.google.com ([2607:f8b0:4864:20::1343]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8Pv-0001cF-DG for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:13 -0400 Received: by mail-dy1-x1343.google.com with SMTP id 5a478bee46e88-2be27fa54feso7435714eec.0 for ; Sat, 07 Mar 2026 23:19:11 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.19.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:19:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954350; x=1773559150; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=3lqy3ttK62KbJsNvTyksmw8JT4cUz9wtpaOy468A04s=; b=F4VutP3wyrMJHbC0srd4dTDzkacwT8NPiJRbVHnPS/gFXjBvv40c40+i0CKhCPwKY0 x7kNjstiN8ZDTwhOdCxHtN0T6GK8ZGe6e32/U3Db9gqtrbd3U2N3gbIzFdUnRjCT4gHL zECWEAzYkK3DfxjM/rWnh8sUAZK2G9pLjdl6lEDjHosxum1ZTmp1sD8Ebj8dpiWrn0JM lBA6HGwCvGUTiZY593hEcwQLa1Sdg6nB6XRZ1uEcemmPpkOZyO5hQX+4PyL/z1pAxCHI VkIo95CMxc4CCweWnNnjiZKThbD8VmIcn7+5dAICgJJ+/zO1NwLpjB0EUoMllOEa4Zoy pFOA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954350; x=1773559150; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=3lqy3ttK62KbJsNvTyksmw8JT4cUz9wtpaOy468A04s=; b=Ku/KGO6cqD6HqUG+pSaFYj1fYIxUsy6gsbBtfJbgNaEjiRey2uHN5sWAEi2tnPxAw4 T1m3pdya2TEt7o9EyyTwD9/CVuJEbeNSf7WhLiFOdVL7y+BP3iloXSQ81Xtk5cfMV9+w iE/nvv2lZPn41tafgCXNpJMPGX3gYnc08vn7vdxlwuYG4pfdLvFvxf88m4XnoE4HBgFO 5DrUU/81QN/1e39o9/tf7RHxs9Sq/FEtI42sg5BSgtpi79kpT5aJWOdj4HPPxoSL+DmE s4ywUm7bouQXMDNnTf6kfpirG9w/qXr3ZHbN3g//pzc/XwB35Q8008DbIW15U5M+2OZ3 REgA== X-Forwarded-Encrypted: i=1; AJvYcCWkChAlsKNU5kjE6UQcqZ9zRHUAZqn3+uFl8NvSQK65oPeHvJphH0d2W7kyfPcO/XORMM95tYRBeWtF@nongnu.org X-Gm-Message-State: AOJu0YzzraHYElh9PnKx/N3bZiybbcBAhu6g0pLrV/RGfhewhC9V5nU7 wqm/GLXUV5DBn0gfJhr8crj54oRSWfB24PU+/f69n47tWalbCp9dtfEL X-Gm-Gg: ATEYQzwai+Lt4q/mdBn9xxpsxHx0c7Whp27cRTDdkPSmK7VNwqMwbeh6PMDtugDLeK+ LWpUlhbv+0fPJsiYliyc7PEqwe6SVSdAs0N1/CC4TVubYK51EOl1XdOoSj57abjq8sD+J6PdZeR +KlZovy6X/NOrhI2SaYdGfrMBNcVpvFxlr98gysfR9eeVLesuHYTxJ9jkw58b7Kg3rTWZyWz+13 BwqBQ3P9C3sUj6B3k1kyuaSK3mnHbR5TKG61rO/Be8wxfpMqxCDE+FkJbeVwPhae0RHaYqlvyfm WUex1grKh+gaWezGaOYmvqhNVbjGx/r+6oPnpvuIUD+8hYEOSW/b0FHnJ0pCdN7aWR1Q1wErXwU 2Kt+hwt2I8TfOEAY29ZWOmFW8ljre1fNa7ZA10HhHW9wWJpiMYf5lPW+xfThEhYHu9GNVnYZ+gT 9yNJ3Y1XbEzexdBVeYvfT7YDChR9wiGeuBKn+uh7zGc9pXMaKKdJSGTMWn+VH1OGQ5YMO9FFBFe WAZQpYDHg8SmhFYrPHwG+7cTSM= X-Received: by 2002:a05:7300:d517:b0:2ae:51fa:b7ec with SMTP id 5a478bee46e88-2be4e055db2mr2871681eec.25.1772954349994; Sat, 07 Mar 2026 23:19:09 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 07/28] target/riscv: restart the DM ROM on debug-mode ebreak Date: Sun, 8 Mar 2026 15:17:10 +0800 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1343; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1343.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954417111154100 Content-Type: text/plain; charset="utf-8" If ebreak executes while the hart is already in Debug Mode, restart the Debug Module ROM from its halt entry rather than falling back to the normal breakpoint exception path. This matches the ROM-based debug flow used by hardware debuggers that place an ebreak in Program Buffer code. Signed-off-by: Chao Liu --- target/riscv/op_helper.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 7f2769f444..406fe2ecd0 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -495,6 +495,13 @@ void helper_sdext_ebreak(CPURISCVState *env, target_ul= ong pc) CPUState *cs =3D env_cpu(env); bool enter_debug =3D false; =20 + /* ebreak in debug mode: re-enter DM ROM at halt address */ + if (riscv_cpu_cfg(env)->ext_sdext && + env->debug_mode && env->dm_rom_present) { + env->pc =3D env->dm_halt_addr; + cpu_loop_exit(cs); + } + if (riscv_cpu_cfg(env)->ext_sdext && !env->debug_mode) { if (env->virt_enabled) { if (env->priv =3D=3D PRV_S) { --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954411; cv=none; d=zohomail.com; s=zohoarc; b=LZjAAfKcHrJlnHaNhg9NL2FSUOwvPC3LlI6IKEouEfU1OEgf2mSuQZ+707GQANh1t9G/6ObY5m9/RK8iIBoNw6gzNTO/IHxcieg3vxLmhTsOSO+dxdeA5C1EQURLuNfQmJ2WaMlRLF7sOrAU/ekqMqKZ80mUTW1TUXkvXb/gZ5E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954411; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=TiAc2gpOs4pCutUIgdmQYazSr1mmoQIwHbzFJpAjzzk=; b=JWtW92FroYkhqgumB5xjNi87wAnacjWIDNKXk60zlxDr+t7Yz5WbopYdvQAb7Lzb57UgCQtmJQTgB0NHcaWsEHbC+nmst4wtBi/GS1mVksWEAremdIa2jW6vLxZxCaPuOqh/2y1cjMKCa3HlBJKMQ2FZ4hKNIqLEC29AAVwVOP8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954411332919.7603390649505; Sat, 7 Mar 2026 23:20:11 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8Q4-0006tE-1N; Sun, 08 Mar 2026 03:19:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8Q3-0006sy-1s for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:19 -0400 Received: from mail-dy1-x1344.google.com ([2607:f8b0:4864:20::1344]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8Q1-0001fg-Et for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:18 -0400 Received: by mail-dy1-x1344.google.com with SMTP id 5a478bee46e88-2bdfd129c52so7067451eec.0 for ; Sat, 07 Mar 2026 23:19:17 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.19.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:19:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954356; x=1773559156; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=TiAc2gpOs4pCutUIgdmQYazSr1mmoQIwHbzFJpAjzzk=; b=OP6gVvW7oLMDE5EN0f9DHsU5iz4l0+P+8QcdUEJm22d2j1lhyufWSUPIzcotvoZ8IP J9diYIH6YKHeugpMsClk31/dGfQlMT1DjOlg7nBAqrxQrDA/O8hBy1gmvxS/QN+f/Vfk Wm3XLEFAwypsvmOqECrqppBPk88put1KwSCUTCuKxp4kk2e/N1TIz1DDkCIcRHvDfXSi nVsauTUZlAxwT4mlRcdTm2+2ySLUfdl/WpsySpM79fqfGdyj9t3ph054L2ZyjTP7dVOI Y9KSYCnWZSTHVajU7kxrIFiKkPPfCj74BMQL7hye6xsyRWn1GUI2YoCyV1BHrcKdGhn3 Ht9Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954356; x=1773559156; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=TiAc2gpOs4pCutUIgdmQYazSr1mmoQIwHbzFJpAjzzk=; b=fWD+T2+UyKA8rHqs7G7YG6Zbj93zd/gC2s3xH80DsleOKQ/0cjiae+x8GXXltvyTVU Cqmxi26oStqY9rn2fvSkDTUAzJQN6BjRKSksZ++GKMDs7ITeF3wIfnDAiivr1j2WhRXL 9KufWIQG2IlLtF0rUcQwQqZsyiaModDgtjp3bz95s7VruAa2ZZ3kFst8oJxESWla5FK2 WqbueYZdJhjYwJiHhRfrbQbljllGxZUhO/VWJ7Ree7ne+Xkx/2wvi5OrPNEm0GiiUxpi WfULzxD7zTu0dlxYwO/RE8kmi6VuC6oaORGscO6AidR10iJeVlggEL+yVlzePKyBc5cY tdsA== X-Forwarded-Encrypted: i=1; AJvYcCUP9FcpE9tTLBoPl7Qd49UOxLBK/omHKScP3GG1XaHEjXZVnVYArxHql+xonV5EOMkWwf74/EHVe9Ex@nongnu.org X-Gm-Message-State: AOJu0YxWF3XbmG3H3dTZrIZ6PlEgdfiPEKhNQTWR3BSVSVPOD2d6tmbx f5alIysHDhDsr6iK43I7WjYy6c+cetE10/u7Z6HgQvSH6m0Yc53EAZV3 X-Gm-Gg: ATEYQzxu4/ddz2mrIaZMWO+3gWdnBWOL3uFuBgQFzC/YBoQFyOv+OsNV+juxfFKCGLI +Cut+KrN97QlSc8F+/aRUUkInBtU/z1Dfz/jpkfFHDBV1cbLXB/GHu5b0Oo1c4KVjs+gkNKh+Fv BY40iaK8HnGstGxoebQdo5iwTZ46lyPLinyKbcGFtku2tKDUd2xiUZiTnAzHQP+SAeeRFttOQK/ uH2CyED58YVTyBlHbHBCwROTyOXRqeE2uvjjuzkksO+XqBQoUuEtUTab+G5Pee6ZJbI7autOm+g S1OP4u5h8HWS7fHIwsW9xdiQrKSdY57TyeUN6Tl01I2O9s1XIY6d8mCYIdQwQz/pS4fG3sPhoVp yaz9mldkdiibSQ+D/2T8gnTb2KmXL8YAs/rhSfRcudj1IBZGeymdF67VR3yML0hob609w0bNJkL rBtAlmU+DuAVLuYymsouMf6VyQugNLsrSDWN+otjf6kiDyJPlSk2yQWOtrWbpii5vj1NKr+Dr3Z 1IZDLNF1fz7M6VLnqLKnll+LoMk9CE3ODU0Sw== X-Received: by 2002:a05:7301:1015:b0:2be:171c:5040 with SMTP id 5a478bee46e88-2be4de8fca7mr2623367eec.3.1772954356001; Sat, 07 Mar 2026 23:19:16 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 08/28] target/riscv: track the exact breakpoint trigger hit Date: Sun, 8 Mar 2026 15:17:11 +0800 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1344; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1344.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954413204158500 Content-Type: text/plain; charset="utf-8" Store the exact breakpoint trigger index in CPU state when a trigger-backed CPU breakpoint matches so later debug handling can distinguish which slot fired. This simplifies the post-hit path because the expensive matching work has already been done when the trigger was programmed into a QEMU breakpoint object. By the time debug handling runs, the matching breakpoint pointer already identifies the trigger slot, so there is no need to re-decode the execute bits or compare the program counter against tdata2 again. The remaining dynamic checks are the common privilege and textra conditions, which are still revalidated before the trigger action is taken. This avoids collapsing all breakpoint hits into a generic stop and lets ROM-backed Debug Mode entry preserve the original trigger action and metadata. Signed-off-by: Chao Liu --- target/riscv/cpu.h | 1 + target/riscv/debug.c | 81 +++++++++++++++++++++----------------------- 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 0bc14f6953..65c7b66596 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -452,6 +452,7 @@ struct CPUArchState { struct CPUWatchpoint *cpu_watchpoint[RV_MAX_TRIGGERS]; QEMUTimer *itrigger_timer[RV_MAX_TRIGGERS]; int64_t last_icount; + int pending_trigger_hit; bool itrigger_enabled; =20 /* machine specific rdtime callback */ diff --git a/target/riscv/debug.c b/target/riscv/debug.c index 6c69c2f796..ef2fafcbef 100644 --- a/target/riscv/debug.c +++ b/target/riscv/debug.c @@ -558,6 +558,34 @@ static void type2_breakpoint_remove(CPURISCVState *env= , target_ulong index) } } =20 +static int riscv_debug_find_breakpoint_trigger(CPUState *cs) +{ + RISCVCPU *cpu =3D RISCV_CPU(cs); + CPURISCVState *env =3D &cpu->env; + CPUBreakpoint *bp; + + QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { + if (!(bp->flags & BP_CPU) || bp->pc !=3D env->pc) { + continue; + } + + for (int i =3D 0; i < RV_MAX_TRIGGERS; i++) { + int trigger_type =3D get_trigger_type(env, i); + + if (!trigger_common_match(env, trigger_type, i)) { + continue; + } + + if (bp =3D=3D env->cpu_breakpoint[i]) { + env->badaddr =3D bp->pc; + return i; + } + } + } + + return -1; +} + static void type2_reg_write(CPURISCVState *env, target_ulong index, int tdata_index, target_ulong val) { @@ -975,6 +1003,9 @@ void riscv_cpu_debug_excp_handler(CPUState *cs) { RISCVCPU *cpu =3D RISCV_CPU(cs); CPURISCVState *env =3D &cpu->env; + int hit =3D env->pending_trigger_hit; + + env->pending_trigger_hit =3D -1; =20 /* Triggers must not match or fire while in Debug Mode. */ if (env->debug_mode) { @@ -986,8 +1017,11 @@ void riscv_cpu_debug_excp_handler(CPUState *cs) do_trigger_action(env, DBG_ACTION_BP); } } else { - if (cpu_breakpoint_test(cs, env->pc, BP_CPU)) { - do_trigger_action(env, DBG_ACTION_BP); + if (hit < 0) { + hit =3D riscv_debug_find_breakpoint_trigger(cs); + } + if (hit >=3D 0) { + do_trigger_action(env, hit); } } } @@ -996,47 +1030,9 @@ bool riscv_cpu_debug_check_breakpoint(CPUState *cs) { RISCVCPU *cpu =3D RISCV_CPU(cs); CPURISCVState *env =3D &cpu->env; - CPUBreakpoint *bp; - target_ulong ctrl; - target_ulong pc; - int trigger_type; - int i; - - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - for (i =3D 0; i < RV_MAX_TRIGGERS; i++) { - trigger_type =3D get_trigger_type(env, i); =20 - if (!trigger_common_match(env, trigger_type, i)) { - continue; - } - - switch (trigger_type) { - case TRIGGER_TYPE_AD_MATCH: - ctrl =3D env->tdata1[i]; - pc =3D env->tdata2[i]; - - if ((ctrl & TYPE2_EXEC) && (bp->pc =3D=3D pc)) { - env->badaddr =3D pc; - return true; - } - break; - case TRIGGER_TYPE_AD_MATCH6: - ctrl =3D env->tdata1[i]; - pc =3D env->tdata2[i]; - - if ((ctrl & TYPE6_EXEC) && (bp->pc =3D=3D pc)) { - env->badaddr =3D pc; - return true; - } - break; - default: - /* other trigger types are not supported or irrelevant */ - break; - } - } - } - - return false; + env->pending_trigger_hit =3D riscv_debug_find_breakpoint_trigger(cs); + return env->pending_trigger_hit >=3D 0; } =20 bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) @@ -1137,4 +1133,5 @@ void riscv_trigger_reset_hold(CPURISCVState *env) } =20 env->mcontext =3D 0; + env->pending_trigger_hit =3D -1; } --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954459; cv=none; d=zohomail.com; s=zohoarc; b=GRdSwieKCyJEJ6lovmpI3r/lPrXpTiRkY8ofQda38Eijzecf9oKyA5uQ8ibAS13IPqJrNVFNt7+4RX8cnmiTtTCI3G54rlPWxjn5UqKXCdAf0Ze5jEl+HoPzJzguduAmVdGO2xcei/mNH5klF5GGty7fFGxYxtBYFJUDK5IMxOY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954459; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=cU5ggE2u6aLlLixaS9h0GjEcrnhAydxbWKbYIqniY1s=; b=KIRX+SudOLnuM5m86o7foIZqMxY6ewcC5bknHs0g61IccoFvI3o1qO8bIFCJf2bCPKUiWb1KU4RlsUznCDol+wdsiWY2JsdgwwQWxMGYvce5MnwIdTuYtahTKzctVe1XN5g7X3Wo+p6qGuDSXu0QUGJ3zjpHf0SULy1a1EvWPKA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954459241315.52238882758263; Sat, 7 Mar 2026 23:20:59 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8QT-0007Ub-DE; Sun, 08 Mar 2026 03:19:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8QA-0007Fw-8y for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:26 -0400 Received: from mail-dy1-x1342.google.com ([2607:f8b0:4864:20::1342]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8Q8-0001jo-J0 for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:26 -0400 Received: by mail-dy1-x1342.google.com with SMTP id 5a478bee46e88-2be06c02f66so3614257eec.1 for ; Sat, 07 Mar 2026 23:19:24 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.19.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:19:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954363; x=1773559163; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=cU5ggE2u6aLlLixaS9h0GjEcrnhAydxbWKbYIqniY1s=; b=nbFQEx++gSd1Zw9Gt7zdkJ4+Ek5DzdIR4b4qoMoP/Jxqy317Ao3itjmp0wFjoyHth7 AIPuujycKNh6i5LDyEudr21Gf2pXsqksFEpyLMJ5QmGVf3T6ePO+d89jDOkp/IK8fPDy wXU926zv8RlxUOTFCRgEKFc3wKFCWRuvJp5rc+OypTPV7f1wndlqw0prEnj0JsLsf/Sp izrYs6Y15F8MTzubra0fkXm2ttkkNLOnWW6E2DBiVYHDFnVk57wbXjAWekcNZLCTaZDY r3yzfW+hudpqAKI+o5CCQ6WxeVxELThGP2fcTPyd/nThCxpczwQ2wmaDmiZhSC6a0f41 4B3w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954363; x=1773559163; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=cU5ggE2u6aLlLixaS9h0GjEcrnhAydxbWKbYIqniY1s=; b=Fw5/qDRkvlaF3jq0rmnt4tJKNX+mQhqMbXmaPIPEVf+PkeVYouu6uGtgK5XilrRG5a gtZxrTIbTWUDOgg7+RX/WsWGjtSXV0lw5xYyMFMLVB/dOBIA7McNrVmh2OzS0WVG3iR6 2gcn0VmjqDQK2x2s6nUR3E3m9W4EfR6NiifRdUgI4vIXSIRte5qWD+KqdABc1AKAAb/l QYvy1LvOs0tXclLLtlILtmAyJk15B2KO3x1qaguFMUHFLf87RWA+HdW1pkyLgppn+giD 8LUAquZ5PlFGoTWIupV9omzBpFDcZDuDsrkXQpiCvfWSwkzP50mIwlrlH+TYwj69jDRu 3q2w== X-Forwarded-Encrypted: i=1; AJvYcCXBJxQocR9Pmx9uBqyBLomhSDwaVgaionZ4JpdcTlmyggrzZx59ALRPQ/M+v/+gwLltXDZxISMP4Bfc@nongnu.org X-Gm-Message-State: AOJu0YyYMk6hcgbbbLVE2oUL8iUAh4r4g32VQgA/1FuWzOgHZy9EUMx4 dSE9nAWTRPS7O4H+LirIRNRMMubC7zNRd4oHzzGacmFv2kqXsRdQsCpL X-Gm-Gg: ATEYQzycohyKt1UkJopII5WEbDemTX05h31LRWlvVSxl+vxL7Sjyv0PAZv39Xgc5B2b 5aWSAubHyCeW2tuP8prYejKbYwjH6Ty03dh9gEKYE48RAOkfPB7bkhjPSxTppYyygIZTgIfE1mA M1v3nYyGRDFJWCBHYpJTmFESINVaY4Oy59XtKp52QKofaIuRHMTYxdhRTni4p09fRO18radaeyJ Abdh/1znquIGBrLXz++iTaohChQIxNE4gZTdG4mTVDctykkhNtawfxYQgEG2/4gu+92hhHqFkED z/47AKN/v8uAi5BIZaYtK61eUwtiIz1lfhW93dxF0rPxWih6LFadRSq5Pb4SuPOV13bHLrQJFaZ CI2ABsEwNrqf0U6cVLqGXfL5LmFe52/IorCXTWMZY/Yk1gZ9Jqrjy8xwDX3p6qdCtBfgNJ9xk2B AoUgSdFMlw6ryynB+c627KayXO8LNROpJb3iSWrsgFWLIn4m5CS0zl8uO6wtFkDyfe3EdSCtFhk ee/jCeDoTsLZXu5bru1sX/Vwvd857j/uC56bg== X-Received: by 2002:a05:7300:ed0b:b0:2bd:d04c:a430 with SMTP id 5a478bee46e88-2be4dfdd7ccmr3082416eec.12.1772954363103; Sat, 07 Mar 2026 23:19:23 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 09/28] target/riscv: track the exact watchpoint trigger hit Date: Sun, 8 Mar 2026 15:17:12 +0800 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1342; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1342.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954461717154100 Content-Type: text/plain; charset="utf-8" Extend trigger-hit tracking to CPU watchpoints so load and store triggers preserve the exact matching trigger index across exception delivery. This simplifies the watchpoint hit path for the same reason as the breakpoint case: the trigger programming code has already expanded the load/store bits, size, and address into the concrete QEMU watchpoint object stored in env->cpu_watchpoint[i]. When QEMU reports a watchpoint hit, matching that object back to the trigger slot is enough; there is no need to repeat the address and access-type comparisons in the debug exception handler. The remaining dynamic privilege and textra conditions are still revalidated before the trigger action is taken. This gives watchpoint-based debug entry the same precise trigger information that breakpoint triggers now carry in CPU state. Signed-off-by: Chao Liu --- target/riscv/debug.c | 103 +++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 63 deletions(-) diff --git a/target/riscv/debug.c b/target/riscv/debug.c index ef2fafcbef..eb03f306b1 100644 --- a/target/riscv/debug.c +++ b/target/riscv/debug.c @@ -586,6 +586,29 @@ static int riscv_debug_find_breakpoint_trigger(CPUStat= e *cs) return -1; } =20 +static int riscv_debug_find_watchpoint_trigger(CPUState *cs, CPUWatchpoint= *wp) +{ + RISCVCPU *cpu =3D RISCV_CPU(cs); + CPURISCVState *env =3D &cpu->env; + + for (int i =3D 0; i < RV_MAX_TRIGGERS; i++) { + int trigger_type =3D get_trigger_type(env, i); + + if (!trigger_common_match(env, trigger_type, i)) { + continue; + } + + if (wp !=3D env->cpu_watchpoint[i]) { + continue; + } + + env->badaddr =3D wp->hitaddr; + return i; + } + + return -1; +} + static void type2_reg_write(CPURISCVState *env, target_ulong index, int tdata_index, target_ulong val) { @@ -1012,17 +1035,21 @@ void riscv_cpu_debug_excp_handler(CPUState *cs) return; } =20 - if (cs->watchpoint_hit) { - if (cs->watchpoint_hit->flags & BP_CPU) { - do_trigger_action(env, DBG_ACTION_BP); - } - } else { - if (hit < 0) { - hit =3D riscv_debug_find_breakpoint_trigger(cs); - } - if (hit >=3D 0) { - do_trigger_action(env, hit); - } + if (hit < 0 && cs->watchpoint_hit && (cs->watchpoint_hit->flags & BP_C= PU)) { + hit =3D riscv_debug_find_watchpoint_trigger(cs, cs->watchpoint_hit= ); + } + + if (cs->watchpoint_hit && + (hit >=3D 0 || (cs->watchpoint_hit->flags & BP_CPU))) { + cs->watchpoint_hit =3D NULL; + } + + if (hit < 0) { + hit =3D riscv_debug_find_breakpoint_trigger(cs); + } + + if (hit >=3D 0) { + do_trigger_action(env, hit); } } =20 @@ -1039,59 +1066,9 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, = CPUWatchpoint *wp) { RISCVCPU *cpu =3D RISCV_CPU(cs); CPURISCVState *env =3D &cpu->env; - target_ulong ctrl; - target_ulong addr; - int trigger_type; - int flags; - int i; - - for (i =3D 0; i < RV_MAX_TRIGGERS; i++) { - trigger_type =3D get_trigger_type(env, i); - - if (!trigger_common_match(env, trigger_type, i)) { - continue; - } - - switch (trigger_type) { - case TRIGGER_TYPE_AD_MATCH: - ctrl =3D env->tdata1[i]; - addr =3D env->tdata2[i]; - flags =3D 0; - - if (ctrl & TYPE2_LOAD) { - flags |=3D BP_MEM_READ; - } - if (ctrl & TYPE2_STORE) { - flags |=3D BP_MEM_WRITE; - } =20 - if ((wp->flags & flags) && (wp->vaddr =3D=3D addr)) { - return true; - } - break; - case TRIGGER_TYPE_AD_MATCH6: - ctrl =3D env->tdata1[i]; - addr =3D env->tdata2[i]; - flags =3D 0; - - if (ctrl & TYPE6_LOAD) { - flags |=3D BP_MEM_READ; - } - if (ctrl & TYPE6_STORE) { - flags |=3D BP_MEM_WRITE; - } - - if ((wp->flags & flags) && (wp->vaddr =3D=3D addr)) { - return true; - } - break; - default: - /* other trigger types are not supported */ - break; - } - } - - return false; + env->pending_trigger_hit =3D riscv_debug_find_watchpoint_trigger(cs, w= p); + return env->pending_trigger_hit >=3D 0; } =20 void riscv_trigger_realize(CPURISCVState *env) --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954470; cv=none; d=zohomail.com; s=zohoarc; b=e5y3YttOcFdDyyfR7X8H/8+CCbHDUrcSI0QCUOpXzNjz+AccZRCMWg+bUchjLX3QSMy9VSNE1RCjGDEDiX+1Ml4kpIowifgAs2xDumXQkGcziRDgmebFtn/7+cMbJ91YN49gRNGbwE/RTdEnsDXipiIKbwoQNOgn7KFVFmTxgzw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954470; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=zwES2RO/KEYppoyZt0FJTIF1i34Igg6OFEnsCwkhiD4=; b=Bb/FelhHz7qM9lNT3YqeAbbIwR2ZUWttX86RSR6V010IvDzcjko910DqDIYyBe8LJsAe4i8YPW5llZtVy8T9uV1i00jXHl74wMKpcLK7VVBmxF4r43SmzFwVxV8VIfQKKzqOYhJ7tXtfAqeOWcXwXkBb4p+88/H7m6LBE7p0hTY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954470744143.93757441032062; Sat, 7 Mar 2026 23:21:10 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8QV-0007v1-E0; Sun, 08 Mar 2026 03:19:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8QI-0007Su-0q for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:37 -0400 Received: from mail-dl1-x1242.google.com ([2607:f8b0:4864:20::1242]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8QF-0001oC-DS for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:33 -0400 Received: by mail-dl1-x1242.google.com with SMTP id a92af1059eb24-128d2e3074fso356232c88.0 for ; Sat, 07 Mar 2026 23:19:30 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.19.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:19:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954369; x=1773559169; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=zwES2RO/KEYppoyZt0FJTIF1i34Igg6OFEnsCwkhiD4=; b=RYAP6W6mifDjeOnxer3IQzTpMwGmgnEXSYniSekQwEAl9uGQMjiDOueJWsEkTSKaGv TjfouSsl7zOwC/Caflj85Hzk8maNXKeRd38oyKmNH+Euyiddn+APB/WBwpyfWhdoVvRp 1DyqrZj8dt8zq5bdxTwIv03/Pfk8FEDODvLCqWn5SmaeZ0Fwgy1Th43iivGpm5KU6TSP cgtDmDg2Cn6f+RyCHAaYE8RBDPgRe/qZIHbzdKcB683J9EYp633eTMb3abWQ7au4fRaH SBCIK9iztbiKOpUigAYwKnFNinlU+faQtmD23Dg/88ZSZXcSRgg1FXSjhUwaYOpufoHr //GQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954369; x=1773559169; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=zwES2RO/KEYppoyZt0FJTIF1i34Igg6OFEnsCwkhiD4=; b=IXyA9Vuvgs0vLvzUQPCbhxjW+OUlx8rPdPkYh7J2g/FeTm+U0j8u6dtoOASTYRwoIh HO6Bh114astk9UaNYN05Ryxy6FA43XFfR7ZRb1LzwZ+1THSelotFwjKAUquVWdi3fDa5 6z4dZALvAugERp9pzdvJoOWD2vAfUUO2YMd6WFFZQ0L+aX8joufv5mV4T5CRGFVQrbiJ YTED0fZ7/muqoeUQjg0SJmFBc3Tp5ENwaOdsZ64d1CM+/cdxAnUwpm1EVe0ZtEMjkE1v EEDUE9T7Xv+PSxZPzLSuURofNf3tDUCmsy1BwqDLx3r/YKiArorbZjB9PHHBcjDCQ11L 3LDQ== X-Forwarded-Encrypted: i=1; AJvYcCWOzCgUuI8HzxBC7i7/d0P+iMlBXIH7bn8bk+nIiwwRBV6ASKs4VzZXaF2I2VTwdCE47ekTubPPCkKf@nongnu.org X-Gm-Message-State: AOJu0Yx6dYCuHfrQgFsHIr78+g8ZFbb9ydW50Zn2lYE4MuGHM3+T1aK+ 6kVFLp87ZMX/R9KoP3ciuSgSJ1oPuF5x/UX/hrA6TLUZRx3ME5xabcz5 X-Gm-Gg: ATEYQzxHJsXXK5UgJ1gddvVNH3GPYM2H3emayGpPG1703nI246uDBesBcZy4fjONltl 1JxJmEa1HVTQC2wsL4LyhwiXygE5XXR4TzyVNnA/c/yJljWsk3uU2yH6Wk0HvYm0ULVdJfAdkTc cdEryoLAlR56BLEPI+oFOgBWwiEMAWacNARV4rLX+GSz1bfyFOel7oWoYTvAEQI2xvVyLqpd6Iw 8ae4x3nKafgH56Y647SYV3wn0Xg0oN5D+sS6HkAjRa0c3rPt4UqZsZgY4kCtLSJ0GHc1wOhzfy2 Qb4hOfsKrY6t0xF7Zd2Ifdq5h3l1GU/c4OsXNPnfIuya+GRCZWUZHdudyCqHW9Zfp+vRJFHjhLA vfqkzJ75ovMIM01MlMjtEprzj7kTSh2dFYUkP0DaNFZx3alJQQdyi/gWOrPSnXuCGD9C0yAVZv/ O52o/AkVYhZmZowWyQjXfm+FtYFEUPzl6A3umWI8eiWuYS/yHSauxzdrfrFUw4dx6CFt7gXQnxu QK9xfjuohYq5QWteKKgx7mc0So= X-Received: by 2002:a05:7022:239e:b0:128:d084:e921 with SMTP id a92af1059eb24-128d084ea53mr1045105c88.14.1772954369400; Sat, 07 Mar 2026 23:19:29 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 10/28] target/riscv: send trigger debug-mode actions to the DM ROM Date: Sun, 8 Mar 2026 15:17:13 +0800 Message-ID: <786eda45594a916e59d100c8edbeb141c5e8d79c.1772936778.git.chao.liu.zevorn@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1242; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dl1-x1242.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954471263158500 Content-Type: text/plain; charset="utf-8" When a trigger configured for debug-mode action fires on a hart with a Debug Module ROM, redirect execution to the ROM entry and suppress the legacy EXCP_DEBUG stop notification. This lets breakpoint, load, and store trigger actions feed the same ROM park loop that handles the other Debug Module entry causes. Signed-off-by: Chao Liu --- target/riscv/debug.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/target/riscv/debug.c b/target/riscv/debug.c index eb03f306b1..00fd75f15f 100644 --- a/target/riscv/debug.c +++ b/target/riscv/debug.c @@ -298,9 +298,20 @@ static void do_trigger_action(CPURISCVState *env, targ= et_ulong trigger_index) riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0); } riscv_cpu_enter_debug_mode(env, env->pc, DCSR_CAUSE_TRIGGER); + if (env->dm_rom_present) { + /* + * DM ROM present: redirect to ROM entry and restart the exec + * loop. Clear exception_index so EXCP_DEBUG does not propagate + * to the MTTCG layer as a spurious GDB stop event. + */ + env->pc =3D env->dm_halt_addr; + cs->exception_index =3D -1; + cpu_loop_exit(cs); + } /* - * If this came from the Trigger Module's CPU breakpoint/watchpoin= t, - * we're already returning via EXCP_DEBUG. Otherwise, stop now. + * No DM ROM (gdbstub path): let EXCP_DEBUG propagate so the gdb + * stub stops the CPU. riscv_cpu_exec_enter leaves debug mode via + * the legacy shortcut on next exec entry. */ if (cs->exception_index !=3D EXCP_DEBUG) { cs->exception_index =3D EXCP_DEBUG; --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954596; cv=none; d=zohomail.com; s=zohoarc; b=kY1KmojDz6ozJ2yaCVNbKSz6Fm8dSbxo+fK6cuUWSJoY0MlQMnbK4L2dhZr5YXayeUtVZ+Hem92LB5uDWF1YT3bPhsDA9fJSZH9FhjOlwDaYUTJCCEHNfDmh58yL+45O4D+dkRS4yHRqZQbVT09++Y3e6CbpXGki8dRisjQYXko= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954596; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=/WGIqVmVnYrVul4QZnYM5zBGsZzKNPp+Wzo4Tq3D/fo=; b=OPuFYi1o1sXK4danTpTT9YxCrKjxueXBmcR8IZNO9gLBKBeI2XzrSNEI67ggB0ANNrU6erkn/vAQsDLQQsEGeVmHixD1X+m6Df6gXlEUoFJ20hv3ehh3TJEBPP6XHFFmZNpPhbAQV2XMqaKtEypa9imYGLV/G/61f0H5rWrVTRo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954596179207.15076314103158; Sat, 7 Mar 2026 23:23:16 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8QX-0008Fu-NI; Sun, 08 Mar 2026 03:19:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8QM-0007Ud-6I for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:39 -0400 Received: from mail-dy1-x1344.google.com ([2607:f8b0:4864:20::1344]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8QK-0001s0-BY for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:37 -0400 Received: by mail-dy1-x1344.google.com with SMTP id 5a478bee46e88-2be26d11b95so8540727eec.0 for ; Sat, 07 Mar 2026 23:19:36 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.19.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:19:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954375; x=1773559175; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=/WGIqVmVnYrVul4QZnYM5zBGsZzKNPp+Wzo4Tq3D/fo=; b=OCFDX6pQjJCFrb2RR4WmzWs+S/S1+y6dle6n1wEa8hi8MoQc21S76NcaBN/ZQFHU/Z +IVLlH7bptJQkPZqjy999qERorEUQQNMKU1QYwrarKPcZMUDs1AgIWVIKbP6sqz/kmt/ yPR2wD+KERaJbwb3X4JWcaeP73b8V3a0VAf84E3p7uNzBloYTuE/5wKcktFGJjslNeZu FVK7FNhc5ZsYl9DL40dwAdsTUARrXcZT3n6cZ7SDIR3EOMmpg9IhhaRIX5zaJS9NEh47 XTXU3VJm6w7o8kdS0w3GQU03arDOxHR/QSGOebqDVYqDMVbaMw2gw5QJsR+0aHWQjL+h GW0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954375; x=1773559175; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=/WGIqVmVnYrVul4QZnYM5zBGsZzKNPp+Wzo4Tq3D/fo=; b=COB6iHE+fUBD438QfslZJkDQfHVvMIq/7t6wuYNmDKZMuaPTU0QUMa122RsOE50XoA 2x0/FfGBafghiDwaIqQz6vw5Im0o6h2zHq4mmmcT/kXiywvN9l/MRBSRDFjb0w6nzr+T VLS0XDO3TUS3SuD/ZN44NomikvWh6jWPAv1iBP1FYJ5uFS+fvrRz+7q+QdTDhtBHmbed Sc89LlQSzujuTsArpuSfwKTi9GPloABoK1r+KM13QaWn8mhuKF95V1FKFhKAAgq2/UEK mzquE4FdJ396GwR4lhmriS+fq4/AO7Lu8RQkjtCmiQHbbsv41KUgHyIduP+4SlfGUfWt 30mQ== X-Forwarded-Encrypted: i=1; AJvYcCUrM1mNN8Gxqc0OltPimIZzW+N1QHVsSxYNKuusXJIRV6s0RDP6EVuv+Rsth2hqRIFVKgisGbSc/509@nongnu.org X-Gm-Message-State: AOJu0YwPjZbbiT6eCnLhNyJkGbvCMoKYD/DJ6Siz96zMamVCEVH8Ovre A0GhpQyQRsOcptyT75AWJDOesLyVO+gexSFfR3akf3x0+aM6Uw7Y6B4V X-Gm-Gg: ATEYQzwaGPNf7nhsKklDjb+CHVlwdX8ABK9GOsPwmEKoUG6KTa+sSKyZlWmDP6bQdeA xF0uae+jVwdNrXeSwMsroB+J0VjuhGOlOHvezs+poDxy8UWAAxZbZf26+5SylX+nSYkJYmgU5ls 1LJ9G2OYhtxXBZ3cUEJ2TUcT0rfOKAGTZQ0WdOgRcIj3bo1/Hod7PSxCtnGqDbJIop51faMIJp9 FiGFdtyH5hSpgSfRN8Qu8I4GU3f6lJt5sH/AbM5UA2onfL12Y21aTLeGfMQljw5SX9xwVUIf9rq z7IpKOo9O/1kJNUKPyKTmHMGz5A1uWvXzo4e9Sv9L3ifTiqc9o2dY4r6/Iq9Kf7wt7vvMnVCdSG eGEZyUp76hBbDYHjbphGySLPFH/4bJJX/lmbBo1DMZgOqN3PQ3MRlsKuyfcHlJpynmT1tihK3wI b6x6Zk7NFrPQEnee5IEDZgxOYtqBJc6Z3ggsURLHI6IskKZuwGKJvt1Zzv5PMb3taMoVm9rxy/p +0FNPRKh6DLuobo/tMWYAziVN0= X-Received: by 2002:a05:7300:fd0e:b0:2be:53a:5f4 with SMTP id 5a478bee46e88-2be4deac6f0mr3128572eec.9.1772954374927; Sat, 07 Mar 2026 23:19:34 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 11/28] target/riscv: suppress itrigger TB state in Debug Mode Date: Sun, 8 Mar 2026 15:17:14 +0800 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1344; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1344.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954597488154100 Content-Type: text/plain; charset="utf-8" Do not expose the native itrigger translation-block state while a hart is already in Debug Mode, because trigger matching is architecturally disabled there. Hiding the TB flag avoids stale itrigger state leaking into ROM execution and keeps translated code aligned with the active debug context. Signed-off-by: Chao Liu --- target/riscv/tcg/tcg-cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 4674ff3e3c..43d764fd59 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -180,7 +180,7 @@ static TCGTBCPUState riscv_get_tb_cpu_state(CPUState *c= s) ? EXT_STATUS_DIRTY : EXT_STATUS_DISABLED; } =20 - if (cpu->cfg.ext_sdtrig && !icount_enabled()) { + if (cpu->cfg.ext_sdtrig && !env->debug_mode && !icount_enabled()) { flags =3D FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enab= led); } #endif --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954496; cv=none; d=zohomail.com; s=zohoarc; b=nrzu5nd5JJq4x8nxlJbWQJLxxATPyEQDRqnnn9IZiI5WEO1vovRb5y1hxl5CFLOu3/38dlAourzzQgF3Hzr8QunG9qg5oxDjECsjF1qIdXnZUoorSFdNrcbMyPF+5Vq+5Ln+f7T7ACRbzIeWMGf8x71YjZ3GBQM8e8XEsfyM66o= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954496; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=MX3WB4nCG/IAxBpjVipEnn4pbM1NmDgDXTp2xeRvhWw=; b=MZatAyNTGNNuWOjMKswQ5zrXbc71cUDtzRZIQU0/WZ4MUJbLA6fUao81AHdIiBEb6fzXEnFu9qLofQ9+SqgjFPX0XHdyi6wxq0F0IoN8C7LcctUjSQebGIjlX1uE21BaCN5M6sl8J67U0uLrUZdiInYaKg8YiwkFtm5wnKuUk+o= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954496353362.3528642988816; Sat, 7 Mar 2026 23:21:36 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8QU-0007np-MC; Sun, 08 Mar 2026 03:19:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8QS-0007dy-22 for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:45 -0400 Received: from mail-dy1-x1343.google.com ([2607:f8b0:4864:20::1343]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8QQ-0001vp-84 for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:43 -0400 Received: by mail-dy1-x1343.google.com with SMTP id 5a478bee46e88-2be1b5fe11cso6988717eec.0 for ; Sat, 07 Mar 2026 23:19:41 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.19.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:19:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954381; x=1773559181; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=MX3WB4nCG/IAxBpjVipEnn4pbM1NmDgDXTp2xeRvhWw=; b=O8jaBeLFO2ltCERQ+JCR/+Q6CtNicI56aSiu7C2xT5R4eigQGh1hAlo0/yNqnLo20K vFskFzFvCT+G3ty/+wBKiSjpqVObv28wYkXfQsxQ576DV+oL1+0NKBD0PiDw8YNHejxc hP5D5uQdbBWE3eZsSsRG0K/rEzKgzf6valys8AqFhzUu4oNu8XSNZ/1eQZTH4cBLQHqD 9L92K7m1MC2BJajWyaLdwk2AZXVlrBwy2Hdga7TpXnks+nk+fbK3lQkWuIfoT0jXgRgt 1rl2K17mvxTTDieBVBWEEhdjk45jSQ1xE3MIvXO7+3sKm2Tsm3Wk0doCqG5qzNmuq3Uo 8j2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954381; x=1773559181; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=MX3WB4nCG/IAxBpjVipEnn4pbM1NmDgDXTp2xeRvhWw=; b=gR+qoiawM417atWPHDJp6rY9DGuJSTD38iu5n7UyBTTpHR3TCh3LBx3haIRy0mVhTe KzYMcCI3qaXJ8gC63yVS2HLda9hW4iPlib6zOadr0oxHtDZcPGFyLXdOpN8FFPFZYVWS /YcSXuWI3kvpS89aiYSBQFFVvKOmXcYd2rjvMiGDNSoiWayLqofqmgz22GfcbJPkhuTV JMo4896oGriLyGbddZ3KfbolI8oTlmVyaJ64pwMUgGX7rCoYWUbP6wlU/SGCm9qP5q3o kINwbXglY593nibnAykx9HuFAXpMfOh2ZvMjXeSOBGKSKvh3/zTySgW49b4lL2em9m5w ozYg== X-Forwarded-Encrypted: i=1; AJvYcCXWACA0hvIVxR8wPnGWSDs6yzdwFGDBViMHDtd2C8BMq88f19bdNNYFOXU3uOvwEplo0Myy9QkxtO7Y@nongnu.org X-Gm-Message-State: AOJu0YzqSPJg49kKuzMUqcaNVNWxKdhLy2WI3eqoP6Myxv+roCVMSFny 0MLKmMaSmryzqYvFLivPpjSkESRL99o5U9XpkJ2Oi/M47qOY8tCPcmX8 X-Gm-Gg: ATEYQzwB/s3cH2pTJ+7NquWK5KiZDACBMZZY58WiSxialk4LGdCapfLlU0yEu9d9+pK wWA4ikpWiaPgez1FjN0kFwlH4wge3ZYcrElPr7MUepR2VT+BzV/DbajICdW6Qr5dpdvfMQ+QgIJ M+cCYm+HV+btHdwzh9lwSNrXU2sT4He3aJQ+a4PClehtlO4lxo5xX6EK8nxbO5ugYNUHFS1vVM3 hdsRGFTna/BzWKJQ5I5dht0P6tdbrrwnbjMUdeWTDHiVtJxPd6nDX5fgbhxZ2iOVITRyXbGabmL gzi7DRAOiBqWF4IF+95azCZhAnEVEx8N3/3GAYfoFSQzrbIzE5Mj9nZ0Eht8kV14U5z0W+82j32 OYVc470FF1wZydHYgkFZ+jAceOKbKfrteiOssIehEyZD6Y+r0HxZ0gzMeQ04+5qmW8DsYQAXOVr poFLqYYkHxPlGp5zrXcg4ilHc51QlMO54yXyHhfNpWwrMaUDh9/TnW42zlkM4KQnL5xFYmr/4K1 NsjJMkFHGrv9kX8cw9PCZxZuiM= X-Received: by 2002:a05:7301:9f04:b0:2be:ca4:e145 with SMTP id 5a478bee46e88-2be4e08fc05mr2471853eec.21.1772954380834; Sat, 07 Mar 2026 23:19:40 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 12/28] target/riscv: tighten itrigger privilege and count checks Date: Sun, 8 Mar 2026 15:17:15 +0800 Message-ID: <6adff7fe6b74b9f25918d8c64ca0c4a9ca3b0fa0.1772936778.git.chao.liu.zevorn@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1343; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1343.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954501901158500 Content-Type: text/plain; charset="utf-8" Decode itrigger privilege enables directly from the mode bits and only advertise itrigger activity while an instruction-count trigger still has a non-zero count. This removes a looser check in the debug helper paths and keeps the exposed itrigger state aligned with the conditions under which the trigger can actually fire. Signed-off-by: Chao Liu --- target/riscv/debug.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/target/riscv/debug.c b/target/riscv/debug.c index 00fd75f15f..f3d6eaeb1e 100644 --- a/target/riscv/debug.c +++ b/target/riscv/debug.c @@ -795,30 +795,37 @@ itrigger_set_count(CPURISCVState *env, int index, int= value) static bool check_itrigger_priv(CPURISCVState *env, int index) { target_ulong tdata1 =3D env->tdata1[index]; + if (env->virt_enabled) { - /* check VU/VS bit against current privilege level */ - return (get_field(tdata1, ITRIGGER_VS) =3D=3D env->priv) || - (get_field(tdata1, ITRIGGER_VU) =3D=3D env->priv); - } else { - /* check U/S/M bit against current privilege level */ - return (get_field(tdata1, ITRIGGER_M) =3D=3D env->priv) || - (get_field(tdata1, ITRIGGER_S) =3D=3D env->priv) || - (get_field(tdata1, ITRIGGER_U) =3D=3D env->priv); + switch (env->priv) { + case PRV_S: + return !!(tdata1 & ITRIGGER_VS); + case PRV_U: + return !!(tdata1 & ITRIGGER_VU); + default: + return false; + } + } + + switch (env->priv) { + case PRV_M: + return !!(tdata1 & ITRIGGER_M); + case PRV_S: + return !!(tdata1 & ITRIGGER_S); + case PRV_U: + return !!(tdata1 & ITRIGGER_U); + default: + return false; } } =20 bool riscv_itrigger_enabled(CPURISCVState *env) { - int count; for (int i =3D 0; i < RV_MAX_TRIGGERS; i++) { if (get_trigger_type(env, i) !=3D TRIGGER_TYPE_INST_CNT) { continue; } - if (check_itrigger_priv(env, i)) { - continue; - } - count =3D itrigger_get_count(env, i); - if (!count) { + if (!itrigger_get_count(env, i)) { continue; } return true; --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954467; cv=none; d=zohomail.com; s=zohoarc; b=KKZ9m49NV/+6mLS554SkN5Kv8Rc37+w78eptncFK5Oo2x69Gtpeo8uzRoowhKwiECBnDq9AFN1fI6ECGpnN4tPDw4KTR8E5wXe7hmgs+/JuO6OkrN8IR/TYwGNPH/yeGzTfsSOfz4eNTM02AnGfKPKzCA09mWooCsGVVVXRcSmI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954467; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Arw5DkHnIHFmXLFPr7igt+8kKLdzDCKYx1CXG3qK2V4=; b=nzXkeE9qoM2CmfC5tCL0dNB+JujZNROLR1YZdPrUKIQWT+nIzKIFHUF4i02mCg3LUK4fKvhxQKmejMOo/sZPSLkEYDsIXYJ+OAnyfHyCdJxrdSUfPcSb/x+ObTKWjrGADuE9e/qPqm40VUvk/YriPD/a8DRQNA+iRFAStBfjy8A= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954467680712.9177371732603; Sat, 7 Mar 2026 23:21:07 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8Qc-0008ND-TZ; Sun, 08 Mar 2026 03:19:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8QW-00088m-QG for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:48 -0400 Received: from mail-dy1-x1341.google.com ([2607:f8b0:4864:20::1341]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8QV-0001yi-5F for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:48 -0400 Received: by mail-dy1-x1341.google.com with SMTP id 5a478bee46e88-2ba895adfeaso9005191eec.0 for ; Sat, 07 Mar 2026 23:19:46 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.19.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:19:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954386; x=1773559186; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Arw5DkHnIHFmXLFPr7igt+8kKLdzDCKYx1CXG3qK2V4=; b=f2GmZQ02Zqr1TF1/aNmX1CrUJam928cPiHcmy1JZrgJcrJzOLpmgMArtGwwYfTYea/ ARYep9549hUqxAQ6Ptw7Gb6UKCnNsY9283T38gsPApBj69I9uRJ1Z3QrMleoDiac7Msh qooNAbjp1rMrX6xIfYvJUeMWUshmOJAiWm+m9oEDjJIKOos5uUFE0cR8UVADd98E56EI xU5x/A5Ai1q+UzXUBmQCBCb/M7NxqOi90G0fADjzVInXgZ/QfzJ8YDbUVbIktr9kTLh1 mAFc53Mro41Aig83o4NHGLGrCCKSy/9x9LmbhWzQyxGiIag41d1KTonkEw6PIAkJyiQg B/+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954386; x=1773559186; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Arw5DkHnIHFmXLFPr7igt+8kKLdzDCKYx1CXG3qK2V4=; b=EjUf572lG2tyd/GFO4AN0swY13EDK7qyXhWvyPyNm2H9WXsDMfEhPGI0xeT98FaTSV j1e4yWM9/pRYlC493F5yioH0ACw6S8yaBI5sIjvHB4SOvKtYO5YXtvLS1BQRPgdM6thf Pduf6bDHwrKImMxdti7xUJ8LuvZwnGfLdvCiBv95CiK+XvaIDAeLoshxBtpCJOSmdPlK oYgvpcCDSzP95/WjOmKeUftZhzsoaIumIXC4gWBUVHC9uu0urgtovRt5hp4W+hVOOXGU weAOk2RQkLXBkyeyq8viwSL8oZaRjxg67Np3OSd1wvR8bgILOC754S2ZP2pNlFxmAJmR kx4Q== X-Forwarded-Encrypted: i=1; AJvYcCWZBdQmruqRPovFLL+0rPEuEAaijnZxoJcE35hEMgDSafrkXpkbS0c+MuP2qaRg0jXA7ZDufcvybMZ8@nongnu.org X-Gm-Message-State: AOJu0YwX8ZL7fCFRtr1GL6miTaA1ULkthPNitpij2O7GMGH/tqMo0SdZ s4jPs/khnVknG1hFjpAEJrgbCDo+hP6wwVUjb2zv+r5JIVfPijGzb1qM X-Gm-Gg: ATEYQzxpPwf8T/lwQJTu8wdlnDYriqG+jHoapDiQuSnhtMU7Seyi5RND/oADDBxaYTM K/XgBY71J2k2EA5+TSvc9YUu2ze3xIszn+Lw8sncobeREMQWolD6UOZ6TeUYPVdpaHIyY9zvdk7 zI+rTeYJmPdnsIA1fhdnTob2Caz3KGE7g2uweJO0ydZLvCVZiu21j5nB/cXofZEA5jEoMElpby8 1iKNNW7lE5tSDizOh737RNeMIfkbIOR82MhilXN4qiDe09xXyzhO6+Kd0+1A3BGpL18kOR3n11S Q9CFideMM7hJUUybnGYGJjsNWfmL8g6U6ij0ogxjfdo6LhNBxdWE2K+XYSRP3a56n3b/5l5nZNd ajZLsusLjd2eDTLwoVI4JxUQmRDxMO249Lark/s0x2qe4O+xgT+oA69n+nnEHxc9yk/PHimwivS 7SwzIB7wHp9zET8F6vddGwsIwjscWxD9mmtWyg2Bj2tEH9tZjOsLdi6ZkhBVe7vQEoSTmtPbMBV EfvkY0IawTEIeu94vvQEqd1wWM= X-Received: by 2002:a05:7300:6c28:b0:2be:e4b:60c3 with SMTP id 5a478bee46e88-2be4e027173mr2822376eec.19.1772954385681; Sat, 07 Mar 2026 23:19:45 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 13/28] target/riscv: allow debug-mode actions for itrigger Date: Sun, 8 Mar 2026 15:17:16 +0800 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1341; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1341.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954469842154100 Content-Type: text/plain; charset="utf-8" Accept action=3Ddebug-mode in itrigger tdata1 when Sdext is enabled and reject unsupported action encodings explicitly. This extends the instruction-count trigger path to the same debug-entry mode used by other trigger types and keeps invalid encodings from being silently accepted. Signed-off-by: Chao Liu --- target/riscv/debug.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/target/riscv/debug.c b/target/riscv/debug.c index f3d6eaeb1e..4dbcf289f2 100644 --- a/target/riscv/debug.c +++ b/target/riscv/debug.c @@ -916,15 +916,27 @@ static target_ulong itrigger_validate(CPURISCVState *= env, target_ulong ctrl) { target_ulong val; + uint32_t action; =20 /* validate the generic part first */ val =3D tdata1_validate(env, ctrl, TRIGGER_TYPE_INST_CNT); =20 - /* validate unimplemented (always zero) bits */ - warn_always_zero_bit(ctrl, ITRIGGER_ACTION, "action"); warn_always_zero_bit(ctrl, ITRIGGER_HIT, "hit"); warn_always_zero_bit(ctrl, ITRIGGER_PENDING, "pending"); =20 + action =3D ctrl & ITRIGGER_ACTION; + if (action =3D=3D DBG_ACTION_DBG_MODE) { + if (env_archcpu(env)->cfg.ext_sdext) { + val |=3D action; + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "trigger action=3Ddebug mode requires Sdext\n"); + } + } else if (action !=3D DBG_ACTION_BP) { + qemu_log_mask(LOG_UNIMP, "trigger action: %u is not supported\n", + action); + } + /* keep the mode and attribute bits */ val |=3D ctrl & (ITRIGGER_VU | ITRIGGER_VS | ITRIGGER_U | ITRIGGER_S | ITRIGGER_M | ITRIGGER_COUNT); --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954434; cv=none; d=zohomail.com; s=zohoarc; b=LQzGNxS32Dr04NJM7kdy+Ph+GhH9qqdr83KzKIwcTFe+qbci8iP1Cr+0R42OpHofRl+HPxtl/ZVSShjEK/x7mP4/EdwY4fadAN7O73N5fL7nBs5P1HLuaz59a6qz1gOQTGcm2p9Cjk46ZNJypcgqmE1+uIBBnfgRVi+q4RXIwn4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954434; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=MZ70pDkBubnfAy6PbUsKzZ+QirfaHkd5aNPfsmS2uPM=; b=Z8UZAtYV4D/O+kAsxlNvxOiXEet3RrU1gEusyBaLhYWUIdi5rMLVF7PKWP6mfY3Zve6DW1zLg7R0bwTmyPlURDwI9RqHDvJ5WLW8HvaJK38w3Ea0LufrUZIKsR41tMSipc5YVbTdYSXiut/gnWbjgQdxgXol4oS35VwW3Di+y/c= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954434129810.9388274061573; Sat, 7 Mar 2026 23:20:34 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8Qj-0000Be-4O; Sun, 08 Mar 2026 03:20:01 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8Qc-0008Oq-Tm for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:54 -0400 Received: from mail-dy1-x1343.google.com ([2607:f8b0:4864:20::1343]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8Qb-00023E-GD for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:19:54 -0400 Received: by mail-dy1-x1343.google.com with SMTP id 5a478bee46e88-2b4520f6b32so12156008eec.0 for ; Sat, 07 Mar 2026 23:19:52 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.19.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:19:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954392; x=1773559192; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=MZ70pDkBubnfAy6PbUsKzZ+QirfaHkd5aNPfsmS2uPM=; b=E3FjLXyavPZBtw4OQLpiUCx6U2KojuU3CuuainUOODTnP8hGOUQHib00TwN6uVauuT qYno1PYhLsJhKI9bGCFk1VP27n4Dpv/g8tshIEaLNH1srNo+Za2yPzPzdIXuFxR52Ft3 z5XM9IrUU+RFH/71gKZqJXNOuZSN6iFrQgf5ECaRITyAEpFsrtNz+YUDEmbvvHG7xHrg IJ9dyhop6jFQmeM4LEF/GWxNZtbs9ejShRFVITNIgMrPcoP7a1oYLBIyykb1/6p10EFo RtiAKG8CUQBMsalJmIwOFynsLfGQUGRDkEWgYAdjs9PhxVvpiuDBwUB0CL1OwGsG97vn I5kg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954392; x=1773559192; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=MZ70pDkBubnfAy6PbUsKzZ+QirfaHkd5aNPfsmS2uPM=; b=bVGyiB9CUoQeNCSe1wfRhnQC1zvna+Q/ij8qDiS1p0k93ivSFwteuVKbywC3nsw3IU 0YogDUdUjHnhtqwDZspOS+KdeDE1FVFwpOHGNnkeDiWhXVWDGcHg/BHEYvU/4UFnsomI uLqSgKG0Wtonmvw9nYjgOvdx1z1tx3vtFzqiEZDIYrxbf39MTZABaDpCMszvM398ReFH e56gHEE4I75P4uqPRzu3/IL172Sr0zAVMDOjOei0V/BLN8+bnwu7EH14pABh9rwtPKaL /0IQiAx0p3Z8RvuGOTEiEfbBlf5OxXWyHMUVPpCYkkESR+Fu7I5r5lJCt7l/n9lPQblg AgFA== X-Forwarded-Encrypted: i=1; AJvYcCWogCEmUZ+qWdlELU+4fMPJrCd9ZKEdLpqbbYL/y18S0vPXcFFx8VnfegZxrxJ1W7sLpOUL3TMxgSZ0@nongnu.org X-Gm-Message-State: AOJu0Yx1xBfF14Gfrjjc3XSZsYeVMg1n40Q9MM0ml7xrQlh4mnbyWdJM /i97IZLIDOYAG6/lEZVuBHI2IfJhO03pxJEXF8qEILev+0sd3aEsrhKu X-Gm-Gg: ATEYQzxrSqvt4FJx8Ru2G0aRkMK0gQ5fr+MbUoKu/MlYuMrHtfkBwRqWOeBzoWSAYSZ YWQ8UNjW5N7EQY/MMQ0GuZcVSvoXYjGjddvHeDIfFagVGiEo4YVWIhX+iUw5L+Y361rsvzd3qZg 32MGvXIhXABF0W6Jn3qTm0S6aTLRB2CBJYn4ifgAKs2ur9odkTlG8dd5Idj9DV4Fxgvr4J1ZRz3 mqDtcfs1/8XJqETuyxNR+KICWJTCqs8RhPjyjKbV+HaL6ZNkE530gTQy6GHZhybKqg1m0F0OXik op6hedLnvHlp9WQ0kH4q4cmbsgnp5zawcr2Z2LxIfMOB32Q4qfF7/D5UGNfNPOJb/NADI7iGLJg TPWHY0t1w707LWg043NUzDeK+j1FrI7Z/Nfw3jOGHoKZGFyEieKh6DfDdaAKag4pVGpGjWs9vhZ Ghcnsxm7lUi9V5k7wtGtomFl8n17TCGiCNcFoyp2PAv/W2alKq/Dgpl8UfwNHN6j+yAaqGcDLDu NBDow865TOYA6bzMkRYh+rUguY= X-Received: by 2002:a05:7300:3b24:b0:2be:2a16:4a54 with SMTP id 5a478bee46e88-2be4e03edd3mr2825263eec.25.1772954391584; Sat, 07 Mar 2026 23:19:51 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 14/28] target/riscv: stop consuming itrigger counts in Debug Mode Date: Sun, 8 Mar 2026 15:17:17 +0800 Message-ID: <378f3cac42ed118add63c496d52ea54b426ff284.1772936778.git.chao.liu.zevorn@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1343; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1343.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954435364154100 Content-Type: text/plain; charset="utf-8" Do not decrement instruction-count triggers while the hart is already in Debug Mode, and store the decremented count before testing whether it reached zero. This matches the architectural rule that triggers do not fire in Debug Mode and avoids losing a count update when the trigger transitions to its firing state. Signed-off-by: Chao Liu --- target/riscv/debug.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/target/riscv/debug.c b/target/riscv/debug.c index 4dbcf289f2..ae9b1cd42a 100644 --- a/target/riscv/debug.c +++ b/target/riscv/debug.c @@ -837,6 +837,11 @@ bool riscv_itrigger_enabled(CPURISCVState *env) void helper_itrigger_match(CPURISCVState *env) { int count; + + if (env->debug_mode) { + return; + } + for (int i =3D 0; i < RV_MAX_TRIGGERS; i++) { if (get_trigger_type(env, i) !=3D TRIGGER_TYPE_INST_CNT) { continue; @@ -848,7 +853,9 @@ void helper_itrigger_match(CPURISCVState *env) if (!count) { continue; } - itrigger_set_count(env, i, count--); + + count--; + itrigger_set_count(env, i, count); if (!count) { env->itrigger_enabled =3D riscv_itrigger_enabled(env); do_trigger_action(env, i); --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954467; cv=none; d=zohomail.com; s=zohoarc; b=VBMGmoLxL3uUpb8tx0yzH9B/XP9+MUmdEFiNRdGdvzn2oSFSNFP4BiezXJeUKLROM31EVDU3NvbDG8POXdDQytJJTPI87T0fEeiyQ9DS3cDcLaFmVQPBWIPD2C/cXiXO+gXh4VNKKN+3tpGDLp0tnB3MZB1b/Q1Kl5CULB8ANys= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954467; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=bhC8VZyeuJcb+P+nRDt5ADfRP2/AkWKt1VLXaWj5i1I=; b=YyDnQ0Tlz6zcWkxsqe0AZ4KlqtRb+JvPTgsit120R0GWtmHtjxL6emEagxSrP3x9FHkSGpSYeCdvqjiYYUc6ZWiPRiMw8VErkAXCutmrImJIuvAOwbcQCn8v3ZIpPiKqJRjfKGNBStouXAXrUNyWy10rRt8nDAwrp/G1cG5Dnq8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954467431585.3664123041577; Sat, 7 Mar 2026 23:21:07 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8Qo-0000iD-SO; Sun, 08 Mar 2026 03:20:06 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8Ql-0000VD-PY for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:20:03 -0400 Received: from mail-dy1-x1343.google.com ([2607:f8b0:4864:20::1343]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8Qh-000286-TG for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:20:03 -0400 Received: by mail-dy1-x1343.google.com with SMTP id 5a478bee46e88-2b6b0500e06so12815827eec.1 for ; Sat, 07 Mar 2026 23:19:59 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.19.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:19:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954398; x=1773559198; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=bhC8VZyeuJcb+P+nRDt5ADfRP2/AkWKt1VLXaWj5i1I=; b=G2LTtPMbu8QH0ncqICUTgyiMDQ1Erb/bMQVx4JCUiaFp1mH9WUjDleOaau7L6CIxDw ogurBTZpoIBIztMi4jKMZ5UqzVNkflEwm909cStS5t8SWGTK1/S0JUzLftgevZ6zfD0s Ipsc/PCAfZQcJCHnNeaq1u7OYpzKP7T5nob1N7pNdui1LeWg9tAt27Wk1ImW7GrSe23+ MMsqd1yTGy7bJlnQzUM9LlbhasRigD96Gw8Gi9GjIck4hzA0xGpBqoEDp7q7bGaoDMZG 3ffZJVH3kbNISlA0UTJfnlQ90s0ftZcIc6x+zbBJaNUDMrBOWqh6CI/YXCVR4bDkDkGl P6rA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954398; x=1773559198; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=bhC8VZyeuJcb+P+nRDt5ADfRP2/AkWKt1VLXaWj5i1I=; b=TKDAMy8uSU5Xnrq7YQM73To7SQHMSKjfGAC6Fd0fxhSJt+cj9NWSH099WZmC6GYITh BzlUzMdhhlGZEGLsvTUInAnKbnTUVglyYYhFqT7rq9boRCIv8BvltNXUtS7i3bNktmje m/+06fwcT40NTQ98xVTc4oFOq32G/HETCNXqN8A494LhIXEwn26SeUIeDzEVBR2XhoK6 Z3+GIzL2EMRqRYPXn2znPb4HRpzGnxUuJzD7G1YxSx/6C+q1HfUnjggWPH1F3qjeqJqI 1TstVZU6OYwJXLOWwcb9rTugTdRfGpRyRfdQ0GoXgQJHNxhsdpXkCX89XF3WE8BmkRMO 6sqQ== X-Forwarded-Encrypted: i=1; AJvYcCV0fr6Xw3JuKve6tjJwQtwrvxURJMYvWEJsjG8uLNj+xlmPCGJTkPrbVtuddVsXYhzXLvNPWKfS+bo6@nongnu.org X-Gm-Message-State: AOJu0YzaX3YcVz/mXEqQGD1lUPUBxGlFqqbeZ7Z4vc+Jhfo8FGAjiqt5 hAL1cgWa5gqypF2P5BO5z6UaoQXScGkzQs1dTuvMu8YE2BjTjlxNH7Pc+nUaUMpJ X-Gm-Gg: ATEYQzzUDMekJuJsbmHg6//69sbW8H9KWg6q6DO6bSiUsEqroUHA1Q/vnRRrc0KPlqi OST7G/UDVM4edkLDBOnGRkDjf6gHvzgaRbnLnqHe3HWu5yjPruZpjr9G3ysbMLIoAWPbcBqTFF/ ROESNLSiaWBripmkzHAcmfoVjpEGx7jaKhmu06Zwboadx/YQCQ7Y+TshsAkAB7yJgbW3+leCdYI bDknuRPczuAbpNzJkv9Jf1plLyzFDbl1o+F3CdXfHMD4lpPnHXgHgWO1F3xniLdRfj+ZEfMmdUK GYAgpRBehu8CpToolztPcET9aMmcE9+cmhDtsLqVD1atFp2Hck8vs09oiAa1q7WDMKgTAfE8nhp mLogLEB2t8lU9kHmLHDoiFv+itclwz8BI34qQ3gMTrpfiIlecYF/V1ed5EJSAmp6HqK1H8ZH53n C1U3WLSjfjYH4Fx8SodznHi6BhN43lGB6za1vmuXkGdB1dU+o9btr+4+ICFe50lQ5VGFCfDYt8r fVLEEFUJCeWgzgapEM2aac1Coe0trx4iVJIGg== X-Received: by 2002:a05:7300:3b24:b0:2be:fe8:8b0c with SMTP id 5a478bee46e88-2be4e03eda7mr2717925eec.25.1772954397842; Sat, 07 Mar 2026 23:19:57 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 15/28] hw/riscv: add an initial Debug Module device model Date: Sun, 8 Mar 2026 15:17:18 +0800 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1343; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1343.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954469431158500 Content-Type: text/plain; charset="utf-8" Add the initial QOM model for the RISC-V Debug Module and wire it into Kconfig and Meson. This introduces the public DM header, the riscv-dm SysBus device type, the basic dmcontrol, dmstatus, hartinfo, and abstractcs register state, and the backing storage for the ROM work area. It also creates separate MMIO regions for the DMI window and the ROM entry alias used by later patches. At this stage the device provides reset values, simple ROM storage, the create helper, and stub CPU callbacks. Follow-on patches will add hart state tracking, run-control, abstract commands, and system bus access. Signed-off-by: Chao Liu --- hw/riscv/Kconfig | 5 + hw/riscv/dm.c | 252 ++++++++++++++++++++++++++++++++++++++++++ hw/riscv/meson.build | 2 + include/hw/riscv/dm.h | 139 +++++++++++++++++++++++ 4 files changed, 398 insertions(+) create mode 100644 hw/riscv/dm.c create mode 100644 include/hw/riscv/dm.h diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 0222c93f87..72bcaa0028 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -1,3 +1,7 @@ +config RISCV_DM + bool + select REGISTER + config RISCV_IOMMU bool =20 @@ -68,6 +72,7 @@ config RISCV_VIRT select PLATFORM_BUS select ACPI select ACPI_PCI + select RISCV_DM =20 config SHAKTI_C bool diff --git a/hw/riscv/dm.c b/hw/riscv/dm.c new file mode 100644 index 0000000000..9ac5f2cfac --- /dev/null +++ b/hw/riscv/dm.c @@ -0,0 +1,252 @@ +/* + * RISC-V Debug Module v1.0 + * + * Copyright (c) 2025 Chao Liu + * + * Based on the RISC-V Debug Specification v1.0 (ratified 2025-02-21) + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/core/qdev-properties.h" +#include "hw/riscv/dm.h" +#include "migration/vmstate.h" + +REG32(DMCONTROL, 0x40) + FIELD(DMCONTROL, DMACTIVE, 0, 1) + +REG32(DMSTATUS, 0x44) + FIELD(DMSTATUS, VERSION, 0, 4) + FIELD(DMSTATUS, AUTHENTICATED, 7, 1) + +REG32(HARTINFO, 0x48) + +REG32(ABSTRACTCS, 0x58) + FIELD(ABSTRACTCS, DATACOUNT, 0, 4) + FIELD(ABSTRACTCS, PROGBUFSIZE, 24, 5) + +static RegisterAccessInfo riscv_dm_regs_info[] =3D { + { .name =3D "DMCONTROL", .addr =3D A_DMCONTROL, }, + { .name =3D "DMSTATUS", .addr =3D A_DMSTATUS, .ro =3D 0xffffffff, }, + { .name =3D "HARTINFO", .addr =3D A_HARTINFO, .ro =3D 0xffffffff, }, + { .name =3D "ABSTRACTCS", .addr =3D A_ABSTRACTCS, .ro =3D 0xffffffff, = }, +}; + +static uint64_t riscv_dm_read(void *opaque, hwaddr addr, unsigned size) +{ + return register_read_memory(opaque, addr, size); +} + +static void riscv_dm_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + register_write_memory(opaque, addr, value, size); +} + +static const MemoryRegionOps riscv_dm_ops =3D { + .read =3D riscv_dm_read, + .write =3D riscv_dm_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + }, +}; + +/* + * ROM device read callback. + * + * In ROMD mode (the default) reads go directly to the RAM backing store a= nd + * this callback is never invoked. It is kept as a fallback for correctne= ss + * should ROMD mode ever be disabled at runtime. + */ +static uint64_t dm_rom_read(void *opaque, hwaddr offset, unsigned size) +{ + RISCVDMState *s =3D opaque; + + return ldn_le_p(s->rom_ptr + offset, size); +} + +static void dm_rom_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + RISCVDMState *s =3D opaque; + + stn_le_p(s->rom_ptr + offset, size, value); +} + +static const MemoryRegionOps dm_rom_ops =3D { + .read =3D dm_rom_read, + .write =3D dm_rom_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .impl =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + }, +}; + +static bool dm_rom_realize(RISCVDMState *s, Error **errp) +{ + SysBusDevice *sbd =3D SYS_BUS_DEVICE(s); + + if (!memory_region_init_rom_device(&s->rom_mr, OBJECT(s), &dm_rom_ops,= s, + "riscv-dm.rom", RISCV_DM_SIZE, + errp)) { + return false; + } + + s->rom_ptr =3D memory_region_get_ram_ptr(&s->rom_mr); + + memory_region_init_alias(&s->rom_work_alias_mr, OBJECT(s), + "riscv-dm.rom-work", &s->rom_mr, + RISCV_DM_ROM_WORK_BASE, RISCV_DM_ROM_WORK_SIZ= E); + memory_region_init_alias(&s->rom_entry_alias_mr, OBJECT(s), + "riscv-dm.rom-entry", &s->rom_mr, + RISCV_DM_ROM_ENTRY, RISCV_DM_ROM_ENTRY_SIZE); + + sysbus_init_mmio(sbd, &s->rom_work_alias_mr); + sysbus_init_mmio(sbd, &s->rom_entry_alias_mr); + return true; +} + +void riscv_dm_hart_halted(RISCVDMState *s, uint32_t hartsel) +{ + (void)s; + (void)hartsel; +} + +void riscv_dm_hart_resumed(RISCVDMState *s, uint32_t hartsel) +{ + (void)s; + (void)hartsel; +} + +void riscv_dm_abstracts_done(RISCVDMState *s, uint32_t hartsel) +{ + (void)s; + (void)hartsel; +} + +void riscv_dm_abstracts_exception(RISCVDMState *s, uint32_t hartsel) +{ + (void)s; + (void)hartsel; +} + +static void dm_debug_reset(RISCVDMState *s) +{ + memset(s->regs, 0, sizeof(s->regs)); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, VERSION, 3); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, AUTHENTICATED, 1); + ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, DATACOUNT, s->num_abstract_data); + ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, PROGBUFSIZE, s->progbuf_size); + + if (s->rom_ptr) { + memset(s->rom_ptr, 0, RISCV_DM_SIZE); + } +} + +static void riscv_dm_init(Object *obj) +{ + RISCVDMState *s =3D RISCV_DM(obj); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); + + s->reg_array =3D register_init_block32(DEVICE(obj), riscv_dm_regs_info, + ARRAY_SIZE(riscv_dm_regs_info), + s->regs_info, s->regs, &riscv_dm_= ops, + false, RISCV_DM_REG_SIZE); + + sysbus_init_mmio(sbd, &s->reg_array->mem); +} + +static void riscv_dm_realize(DeviceState *dev, Error **errp) +{ + RISCVDMState *s =3D RISCV_DM(dev); + + if (s->num_harts > RISCV_DM_MAX_HARTS) { + error_setg(errp, "riscv-dm: num-harts %u exceeds maximum %d", + s->num_harts, RISCV_DM_MAX_HARTS); + return; + } + + if (!dm_rom_realize(s, errp)) { + return; + } + + dm_debug_reset(s); +} + +static void riscv_dm_reset_hold(Object *obj, ResetType type) +{ + (void)type; + dm_debug_reset(RISCV_DM(obj)); +} + +static const Property riscv_dm_props[] =3D { + DEFINE_PROP_UINT32("num-harts", RISCVDMState, num_harts, 1), + DEFINE_PROP_UINT32("datacount", RISCVDMState, num_abstract_data, 2), + DEFINE_PROP_UINT32("progbufsize", RISCVDMState, progbuf_size, 8), + DEFINE_PROP_BOOL("impebreak", RISCVDMState, impebreak, true), + DEFINE_PROP_UINT32("nscratch", RISCVDMState, nscratch, 1), + DEFINE_PROP_UINT32("sba-addr-width", RISCVDMState, sba_addr_width, 0), +}; + +static const VMStateDescription vmstate_riscv_dm =3D { + .name =3D TYPE_RISCV_DM, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (const VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, RISCVDMState, RISCV_DM_R_MAX), + VMSTATE_BOOL(dm_active, RISCVDMState), + VMSTATE_END_OF_LIST(), + } +}; + +static void riscv_dm_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + + dc->realize =3D riscv_dm_realize; + dc->vmsd =3D &vmstate_riscv_dm; + device_class_set_props(dc, riscv_dm_props); + rc->phases.hold =3D riscv_dm_reset_hold; +} + +static const TypeInfo riscv_dm_info =3D { + .name =3D TYPE_RISCV_DM, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(RISCVDMState), + .instance_init =3D riscv_dm_init, + .class_init =3D riscv_dm_class_init, +}; + +static void riscv_dm_register_types(void) +{ + type_register_static(&riscv_dm_info); +} + +type_init(riscv_dm_register_types) + +DeviceState *riscv_dm_create(MemoryRegion *sys_mem, hwaddr base, + uint32_t num_harts) +{ + DeviceState *dev =3D qdev_new(TYPE_RISCV_DM); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(dev); + + qdev_prop_set_uint32(dev, "num-harts", num_harts); + sysbus_realize_and_unref(sbd, &error_fatal); + + /* MMIO region 0: DMI register file */ + memory_region_add_subregion(sys_mem, base, + sysbus_mmio_get_region(sbd, 0)); + /* MMIO region 1: low debug work area (mailbox, cmd, data, flags) */ + memory_region_add_subregion(sys_mem, base + RISCV_DM_ROM_WORK_BASE, + sysbus_mmio_get_region(sbd, 1)); + /* MMIO region 2: debug ROM entry vector */ + memory_region_add_subregion(sys_mem, base + RISCV_DM_ROM_ENTRY, + sysbus_mmio_get_region(sbd, 2)); + return dev; +} diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index 533472e22a..2e98bfbe9a 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -18,4 +18,6 @@ riscv_ss.add(when: 'CONFIG_XIANGSHAN_KUNMINGHU', if_true:= files('xiangshan_kmh.c riscv_ss.add(when: 'CONFIG_RISCV_MIPS_CPS', if_true: files('cps.c')) riscv_ss.add(when: 'CONFIG_MIPS_BOSTON_AIA', if_true: files('boston-aia.c'= )) =20 +riscv_ss.add(when: 'CONFIG_RISCV_DM', if_true: files('dm.c')) + hw_arch +=3D {'riscv': riscv_ss} diff --git a/include/hw/riscv/dm.h b/include/hw/riscv/dm.h new file mode 100644 index 0000000000..652a1f53dd --- /dev/null +++ b/include/hw/riscv/dm.h @@ -0,0 +1,139 @@ +/* + * RISC-V Debug Module v1.0 + * + * Copyright (c) 2025 Chao Liu + * + * Based on the RISC-V Debug Specification v1.0 (ratified 2025-02-21) + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_RISCV_DM_H +#define HW_RISCV_DM_H + +#include "hw/core/sysbus.h" +#include "hw/core/register.h" + +/* Debug memory layout constants (byte offsets within DM backing store) */ +#define RISCV_DM_SIZE 0x1000 + +/* + * The DMI register window occupies 0x0..0x103. + * Place CPU<->DM mailbox words right above it. + */ +#define RISCV_DM_ROM_HARTID 0x104 +#define RISCV_DM_ROM_GOING 0x108 +#define RISCV_DM_ROM_RESUME 0x10C +#define RISCV_DM_ROM_EXCP 0x110 +#define RISCV_DM_ROM_WHERETO 0x300 +#define RISCV_DM_ROM_CMD 0x338 +#define RISCV_DM_ROM_PROGBUF 0x360 +#define RISCV_DM_ROM_DATA 0x3C0 +#define RISCV_DM_ROM_FLAGS 0x400 +#define RISCV_DM_ROM_ENTRY 0x800 +#define RISCV_DM_ROM_WORK_BASE RISCV_DM_ROM_HARTID +#define RISCV_DM_ROM_WORK_SIZE (RISCV_DM_ROM_ENTRY - RISCV_DM_ROM_WORK_BA= SE) +#define RISCV_DM_ROM_ENTRY_SIZE (RISCV_DM_SIZE - RISCV_DM_ROM_ENTRY) + +/* + * Maximum harts addressable by the ROM entry loop. + * The ROM uses `lbu s0, 0x400(s0)` with a 7-bit masked mhartid, + * giving 128 directly-addressable harts per DM instance. + */ +#define RISCV_DM_MAX_HARTS 128 +#define RISCV_DM_HAWINDOW_SIZE 32 + +/* Register space: 0x00 - 0x100, word-addressed */ +#define RISCV_DM_REG_SIZE 0x104 +#define RISCV_DM_R_MAX (RISCV_DM_REG_SIZE / 4) + +/* Hart flag values written into ROM FLAGS area */ +enum RISCVDMHartFlag { + RISCV_DM_FLAG_CLEAR =3D 0, + RISCV_DM_FLAG_GOING =3D 1, + RISCV_DM_FLAG_RESUME =3D 2, +}; + +/* Abstract command error codes (CMDERR field) */ +enum RISCVDMCmdErr { + RISCV_DM_CMDERR_NONE =3D 0, + RISCV_DM_CMDERR_BUSY =3D 1, + RISCV_DM_CMDERR_NOTSUP =3D 2, + RISCV_DM_CMDERR_EXCEPTION =3D 3, + RISCV_DM_CMDERR_HALTRESUME =3D 4, + RISCV_DM_CMDERR_BUS =3D 5, + RISCV_DM_CMDERR_OTHER =3D 7, +}; + +/* Abstract command types */ +enum RISCVDMCmdType { + RISCV_DM_CMD_ACCESS_REG =3D 0, + RISCV_DM_CMD_QUICK_ACCESS =3D 1, + RISCV_DM_CMD_ACCESS_MEM =3D 2, +}; + +/* Abstract register number ranges */ +#define RISCV_DM_REGNO_CSR_START 0x0000 +#define RISCV_DM_REGNO_CSR_END 0x0FFF +#define RISCV_DM_REGNO_GPR_START 0x1000 +#define RISCV_DM_REGNO_GPR_END 0x101F +#define RISCV_DM_REGNO_FPR_START 0x1020 +#define RISCV_DM_REGNO_FPR_END 0x103F + +#define TYPE_RISCV_DM "riscv-dm" +OBJECT_DECLARE_SIMPLE_TYPE(RISCVDMState, RISCV_DM) + +struct RISCVDMState { + SysBusDevice parent_obj; + + /* register.h framework */ + RegisterInfoArray *reg_array; + uint32_t regs[RISCV_DM_R_MAX]; + RegisterInfo regs_info[RISCV_DM_R_MAX]; + + /* DM backing store (rom_device) and exported aliases */ + MemoryRegion rom_mr; + MemoryRegion rom_work_alias_mr; + MemoryRegion rom_entry_alias_mr; + uint8_t *rom_ptr; + + /* Per-hart state */ + uint32_t num_harts; + qemu_irq *halt_irqs; + bool *hart_halted; + bool *hart_resumeack; + bool *hart_havereset; + bool *hart_resethaltreq; + + /* DM active state (from DMCONTROL.dmactive) */ + bool dm_active; + + /* Hart array mask window */ + uint32_t hawindow[RISCV_DM_MAX_HARTS / RISCV_DM_HAWINDOW_SIZE]; + + /* Last executed command (stored for autoexec) */ + uint32_t last_cmd; + + /* QOM properties */ + uint32_t num_abstract_data; /* datacount: default 2 */ + uint32_t progbuf_size; /* progbufsize: default 8 */ + bool impebreak; /* implicit ebreak */ + uint32_t nscratch; /* dscratch count: default 1 */ + uint32_t sba_addr_width; /* SBA address bits: default 0 (disabled)= */ +}; + +/* + * CPU-side callbacks: called from ROM write handler or CPU debug logic. + * These update per-hart state in the DM. + */ +void riscv_dm_hart_halted(RISCVDMState *s, uint32_t hartsel); +void riscv_dm_hart_resumed(RISCVDMState *s, uint32_t hartsel); +void riscv_dm_abstracts_done(RISCVDMState *s, uint32_t hartsel); +void riscv_dm_abstracts_exception(RISCVDMState *s, uint32_t hartsel); + +/* Convenience: create, configure, realize, and map the DM device. + * @base is the start of the DM address space (size RISCV_DM_SIZE). */ +DeviceState *riscv_dm_create(MemoryRegion *sys_mem, hwaddr base, + uint32_t num_harts); + +#endif /* HW_RISCV_DM_H */ --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954437; cv=none; d=zohomail.com; s=zohoarc; b=Zgod5ui9UnsKr5Qhci2XKE6rfoM5qzvdlVEhON1SPpo3EJPO0xLbQRNFI646CEWThfh+E92kdhK69L/gTEuCugoddKQo+dnbvjLzVrqebhht1fAXl9hjijsSDRgp1tfcoEeRkQ06Lt/63TgsI2pCJO7Ds3pOK+vNDhWHeOe2O10= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954437; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=86xon8l74W9KjFelsko2w/gQm9AVLkIxkuNw3eT+zMk=; b=fNatjAXBthzBwQEXDigTWJ/VR0ujvDi8EbiPUqk16nEN+lg7FYy3D5YUYnUFeN7OFCxiGMx7nvdAa6KnJGqfbn9pvSi85IXulcqQ4eV8e+sQMvbB4K05mXrRPKA3hK5MFtCS/ji1tdb5kBXZScwym/RAuape0AaLnhWW4iTuZrM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954437440399.2810772639625; Sat, 7 Mar 2026 23:20:37 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8Qu-0001HF-4s; Sun, 08 Mar 2026 03:20:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8Qr-00012i-JE for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:20:09 -0400 Received: from mail-dl1-x1241.google.com ([2607:f8b0:4864:20::1241]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8Qo-0002P8-4w for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:20:09 -0400 Received: by mail-dl1-x1241.google.com with SMTP id a92af1059eb24-126ea4b77adso13331210c88.1 for ; Sat, 07 Mar 2026 23:20:05 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.19.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:20:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954404; x=1773559204; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=86xon8l74W9KjFelsko2w/gQm9AVLkIxkuNw3eT+zMk=; b=IjNvOlKR9qO+bj0EVboKbjHex28DaPSeGhCjPaDZLeJKZfRSa+sv5YTIL8FJpY8D/K yRLXidmJLGmVkBZ3RouX9oYf81L51En4RJw8R1h0N1PbV8dohXFE6hVBid4TBg5JMHMx S4+9DQlOjbrwo/l7WWMGDH5/rCgRltr/sFfJxl4wUkwOT5QWowSAFdJBVjD2uQyFVD/1 2LawIs+Fs24iHmbKGloy+ALhcwmtPuhF/XJqYD7yOCXC91qmnWu31OCja+SxKX6gpuKz b6oxmF81gHStsr7eon42/TM4R9qCPtdOXTLLVKnq/QIi2rJCowMk1A/eH3h+KPDjhzY1 FhQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954404; x=1773559204; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=86xon8l74W9KjFelsko2w/gQm9AVLkIxkuNw3eT+zMk=; b=B6J0vZ9BWOg2RTUzzuGH+1VUYCoiZbYS5l0AoESxELxyie53zx7bF87+7gcQRJ0zAp YQiqd4KMke52FHVy6C+s1Pm/0fORbj/9Gc90T+/Mnmf1E96wNcAYnmV+uo9DBAHodeyR iK0MbBjbUy/EHppl3i19U2QRjgQmVzqpu7HTsHnjsA4KQseXeB0tEZhvVVoIPNcVWY/s R1zDRnj8khwT0uqItxOkfyLmvyrSQfFYi8/9aAer7ouDasdylck2l/j1J4Q+e90PoVuz Q/viBDYzpVlfZV78GetCIwUCTOzADCAT0apiYjG+tFzs7bh5R5pfAZ2YsqiCp/Gef2rR Km1A== X-Forwarded-Encrypted: i=1; AJvYcCXyeIucVxTc6qUweVzuoqsxflBMVdAYPW2W99gq7pzUPSooVW36xV0wMsNAS9zg1WV8AYE5BB85wXi+@nongnu.org X-Gm-Message-State: AOJu0YyixhCCduCwiRG0Dk/XMbw+TliV3xJk9hEerzT9cC+/b26Idl9l OKup47GRny54AS8pAFd546e7XoCpUSjrSv0kBQd330DIMjvZUES7p5N0 X-Gm-Gg: ATEYQzwqfoCc0yTPDKyeeQLolFqgqR8vbekgz1tNtIU1ccl7d0r0p9sdMzUIEDEYzAd f4nvShHWpnr9FVtIIxPQfl2xnTbccWHMr6hWsuPe8kiGR3ngVq456zXgWOWKIynYyWGt6V0lDLP vGk1WRTfPxwcyQdihOvMm89ENhAAn6cQn4aTTL1RhDe77uCI/E2MYd1rMlbl6SO4W36ZSJqmCUm f2cV1OS17xw3+0/XYZQRJbRVhyeGFNEZKb7/BP/KGw4/vl8hwRfgDwCGpWI6vScAhh9IGqfdI9U yV+fiFvnSUtFyYkw1A32Ilio97JOpMz4sTeqz55UFzejHEpaTXkMZqiKHqFEZ43/V6hvaGMe5dd fmJGHbYc4XYCScsTItCWaeQN5KUias43k7WITRiYP8J/goZsppIjVch9Iemi9vxaDqbxwMGmpSn D3gjaqMp/+JvPDXgMR7nt8dyj/qOHlizoLn+YlewbxxFqkXe/MnAVULUuRRvrTU4+qyA5ZidVDi nLPT632xYFLuYs92l7usovwAx8= X-Received: by 2002:a05:7022:68a1:b0:123:34e8:ae9f with SMTP id a92af1059eb24-128c2da5453mr2889935c88.9.1772954404383; Sat, 07 Mar 2026 23:20:04 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 16/28] hw/riscv/dm: track per-hart debug state Date: Sun, 8 Mar 2026 15:17:19 +0800 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1241; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dl1-x1241.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954439616154100 Content-Type: text/plain; charset="utf-8" Add per-hart arrays for tracking halt, resume-acknowledge, have-reset and reset-halt-request state. The initial DM reset handler clears all arrays consistently using a for loop. Signed-off-by: Chao Liu --- hw/riscv/dm.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 183 insertions(+), 10 deletions(-) diff --git a/hw/riscv/dm.c b/hw/riscv/dm.c index 9ac5f2cfac..fad8e2b2ce 100644 --- a/hw/riscv/dm.c +++ b/hw/riscv/dm.c @@ -16,32 +16,148 @@ =20 REG32(DMCONTROL, 0x40) FIELD(DMCONTROL, DMACTIVE, 0, 1) + FIELD(DMCONTROL, HARTSELLO, 6, 10) + FIELD(DMCONTROL, HARTSELHI, 16, 10) + FIELD(DMCONTROL, HASEL, 26, 1) =20 REG32(DMSTATUS, 0x44) FIELD(DMSTATUS, VERSION, 0, 4) + FIELD(DMSTATUS, HASRESETHALTREQ, 5, 1) FIELD(DMSTATUS, AUTHENTICATED, 7, 1) + FIELD(DMSTATUS, ANYHALTED, 8, 1) + FIELD(DMSTATUS, ALLHALTED, 9, 1) + FIELD(DMSTATUS, ANYRUNNING, 10, 1) + FIELD(DMSTATUS, ALLRUNNING, 11, 1) + FIELD(DMSTATUS, ANYNONEXISTENT, 14, 1) + FIELD(DMSTATUS, ALLNONEXISTENT, 15, 1) + FIELD(DMSTATUS, ANYRESUMEACK, 16, 1) + FIELD(DMSTATUS, ALLRESUMEACK, 17, 1) + FIELD(DMSTATUS, ANYHAVERESET, 18, 1) + FIELD(DMSTATUS, ALLHAVERESET, 19, 1) + FIELD(DMSTATUS, IMPEBREAK, 22, 1) =20 REG32(HARTINFO, 0x48) + FIELD(HARTINFO, DATAADDR, 0, 12) + FIELD(HARTINFO, DATASIZE, 12, 4) + FIELD(HARTINFO, DATAACCESS, 16, 1) + FIELD(HARTINFO, NSCRATCH, 20, 4) =20 REG32(ABSTRACTCS, 0x58) FIELD(ABSTRACTCS, DATACOUNT, 0, 4) + FIELD(ABSTRACTCS, CMDERR, 8, 3) + FIELD(ABSTRACTCS, BUSY, 12, 1) FIELD(ABSTRACTCS, PROGBUFSIZE, 24, 5) =20 +static inline uint32_t dm_get_hartsel(RISCVDMState *s) +{ + uint32_t hi =3D ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTSELHI); + uint32_t lo =3D ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTSELLO); + + return (hi << 10) | lo; +} + +static inline bool dm_hart_valid(RISCVDMState *s, uint32_t hartsel) +{ + return hartsel < s->num_harts; +} + +static void dm_status_refresh(RISCVDMState *s) +{ + uint32_t hartsel =3D dm_get_hartsel(s); + bool valid =3D dm_hart_valid(s, hartsel); + bool halted =3D valid && s->hart_halted[hartsel]; + bool running =3D valid && !s->hart_halted[hartsel]; + bool resumeack =3D valid && s->hart_resumeack[hartsel]; + bool havereset =3D valid && s->hart_havereset[hartsel]; + + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYNONEXISTENT, !valid); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLNONEXISTENT, !valid); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYHALTED, halted); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLHALTED, halted); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYRUNNING, running); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLRUNNING, running); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYRESUMEACK, resumeack); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLRESUMEACK, resumeack); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYHAVERESET, havereset); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLHAVERESET, havereset); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, HASRESETHALTREQ, 1); +} + +static void dm_debug_reset(RISCVDMState *s); + +static uint64_t dm_dmcontrol_pre_write(RegisterInfo *reg, uint64_t val64) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + uint32_t val =3D val64; + + if (!FIELD_EX32(val, DMCONTROL, DMACTIVE)) { + dm_debug_reset(s); + return 0; + } + + s->dm_active =3D true; + + val =3D FIELD_DP32(val, DMCONTROL, DMACTIVE, 1); + s->regs[R_DMCONTROL] =3D val; + dm_status_refresh(s); + return val; +} + +static uint64_t dm_dmstatus_post_read(RegisterInfo *reg, uint64_t val) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + + dm_status_refresh(s); + return val; +} + +static uint64_t dm_hartinfo_post_read(RegisterInfo *reg, uint64_t val) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + uint32_t v =3D val; + + v =3D FIELD_DP32(v, HARTINFO, DATAADDR, RISCV_DM_ROM_DATA); + v =3D FIELD_DP32(v, HARTINFO, DATASIZE, s->num_abstract_data); + v =3D FIELD_DP32(v, HARTINFO, DATAACCESS, 1); + v =3D FIELD_DP32(v, HARTINFO, NSCRATCH, s->nscratch); + return v; +} + static RegisterAccessInfo riscv_dm_regs_info[] =3D { - { .name =3D "DMCONTROL", .addr =3D A_DMCONTROL, }, - { .name =3D "DMSTATUS", .addr =3D A_DMSTATUS, .ro =3D 0xffffffff, }, - { .name =3D "HARTINFO", .addr =3D A_HARTINFO, .ro =3D 0xffffffff, }, - { .name =3D "ABSTRACTCS", .addr =3D A_ABSTRACTCS, .ro =3D 0xffffffff, = }, + { .name =3D "DMCONTROL", .addr =3D A_DMCONTROL, + .pre_write =3D dm_dmcontrol_pre_write, }, + { .name =3D "DMSTATUS", .addr =3D A_DMSTATUS, + .ro =3D 0xffffffff, + .post_read =3D dm_dmstatus_post_read, }, + { .name =3D "HARTINFO", .addr =3D A_HARTINFO, + .ro =3D 0xffffffff, + .post_read =3D dm_hartinfo_post_read, }, + { .name =3D "ABSTRACTCS", .addr =3D A_ABSTRACTCS, + .ro =3D 0xffffffff, }, }; =20 static uint64_t riscv_dm_read(void *opaque, hwaddr addr, unsigned size) { + RegisterInfoArray *reg_array =3D opaque; + RISCVDMState *s =3D RISCV_DM(reg_array->r[0]->opaque); + + if (!s->dm_active && addr !=3D A_DMCONTROL) { + return 0; + } + return register_read_memory(opaque, addr, size); } =20 static void riscv_dm_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { + RegisterInfoArray *reg_array =3D opaque; + RISCVDMState *s =3D RISCV_DM(reg_array->r[0]->opaque); + + if (!s->dm_active && addr !=3D A_DMCONTROL) { + return; + } + register_write_memory(opaque, addr, value, size); } =20 @@ -75,6 +191,20 @@ static void dm_rom_write(void *opaque, hwaddr offset, RISCVDMState *s =3D opaque; =20 stn_le_p(s->rom_ptr + offset, size, value); + + if (offset =3D=3D RISCV_DM_ROM_HARTID && size =3D=3D 4) { + riscv_dm_hart_halted(s, value); + return; + } + + if (offset =3D=3D RISCV_DM_ROM_RESUME && size =3D=3D 4) { + riscv_dm_hart_resumed(s, value); + return; + } + + if (offset =3D=3D RISCV_DM_ROM_EXCP && size =3D=3D 4) { + riscv_dm_abstracts_exception(s, dm_get_hartsel(s)); + } } =20 static const MemoryRegionOps dm_rom_ops =3D { @@ -113,26 +243,38 @@ static bool dm_rom_realize(RISCVDMState *s, Error **e= rrp) =20 void riscv_dm_hart_halted(RISCVDMState *s, uint32_t hartsel) { - (void)s; - (void)hartsel; + if (!dm_hart_valid(s, hartsel)) { + return; + } + + s->hart_halted[hartsel] =3D true; + riscv_dm_abstracts_done(s, hartsel); + dm_status_refresh(s); } =20 void riscv_dm_hart_resumed(RISCVDMState *s, uint32_t hartsel) { - (void)s; - (void)hartsel; + if (!dm_hart_valid(s, hartsel)) { + return; + } + + s->hart_halted[hartsel] =3D false; + s->hart_resumeack[hartsel] =3D true; + dm_status_refresh(s); } =20 void riscv_dm_abstracts_done(RISCVDMState *s, uint32_t hartsel) { - (void)s; (void)hartsel; + ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, BUSY, 0); } =20 void riscv_dm_abstracts_exception(RISCVDMState *s, uint32_t hartsel) { - (void)s; (void)hartsel; + ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, BUSY, 0); + ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, CMDERR, + RISCV_DM_CMDERR_EXCEPTION); } =20 static void dm_debug_reset(RISCVDMState *s) @@ -140,12 +282,23 @@ static void dm_debug_reset(RISCVDMState *s) memset(s->regs, 0, sizeof(s->regs)); ARRAY_FIELD_DP32(s->regs, DMSTATUS, VERSION, 3); ARRAY_FIELD_DP32(s->regs, DMSTATUS, AUTHENTICATED, 1); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, IMPEBREAK, s->impebreak); ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, DATACOUNT, s->num_abstract_data); ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, PROGBUFSIZE, s->progbuf_size); =20 + if (s->hart_halted) { + memset(s->hart_halted, 0, s->num_harts * sizeof(bool)); + memset(s->hart_resumeack, 0, s->num_harts * sizeof(bool)); + memset(s->hart_havereset, 1, s->num_harts * sizeof(bool)); + } + + s->dm_active =3D false; + if (s->rom_ptr) { memset(s->rom_ptr, 0, RISCV_DM_SIZE); } + + dm_status_refresh(s); } =20 static void riscv_dm_init(Object *obj) @@ -171,6 +324,10 @@ static void riscv_dm_realize(DeviceState *dev, Error *= *errp) return; } =20 + s->hart_halted =3D g_new0(bool, s->num_harts); + s->hart_resumeack =3D g_new0(bool, s->num_harts); + s->hart_havereset =3D g_new0(bool, s->num_harts); + if (!dm_rom_realize(s, errp)) { return; } @@ -184,6 +341,15 @@ static void riscv_dm_reset_hold(Object *obj, ResetType= type) dm_debug_reset(RISCV_DM(obj)); } =20 +static void riscv_dm_unrealize(DeviceState *dev) +{ + RISCVDMState *s =3D RISCV_DM(dev); + + g_free(s->hart_halted); + g_free(s->hart_resumeack); + g_free(s->hart_havereset); +} + static const Property riscv_dm_props[] =3D { DEFINE_PROP_UINT32("num-harts", RISCVDMState, num_harts, 1), DEFINE_PROP_UINT32("datacount", RISCVDMState, num_abstract_data, 2), @@ -200,6 +366,12 @@ static const VMStateDescription vmstate_riscv_dm =3D { .fields =3D (const VMStateField[]) { VMSTATE_UINT32_ARRAY(regs, RISCVDMState, RISCV_DM_R_MAX), VMSTATE_BOOL(dm_active, RISCVDMState), + VMSTATE_VARRAY_UINT32(hart_halted, RISCVDMState, num_harts, + 0, vmstate_info_bool, bool), + VMSTATE_VARRAY_UINT32(hart_resumeack, RISCVDMState, num_harts, + 0, vmstate_info_bool, bool), + VMSTATE_VARRAY_UINT32(hart_havereset, RISCVDMState, num_harts, + 0, vmstate_info_bool, bool), VMSTATE_END_OF_LIST(), } }; @@ -210,6 +382,7 @@ static void riscv_dm_class_init(ObjectClass *klass, con= st void *data) ResettableClass *rc =3D RESETTABLE_CLASS(klass); =20 dc->realize =3D riscv_dm_realize; + dc->unrealize =3D riscv_dm_unrealize; dc->vmsd =3D &vmstate_riscv_dm; device_class_set_props(dc, riscv_dm_props); rc->phases.hold =3D riscv_dm_reset_hold; --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954525; cv=none; d=zohomail.com; s=zohoarc; b=BzV5R/wKTrO+hL2KzmMoQVWGOo21aKvv1p5XTQZjIfZX9mGxXdC4WrXUmVJ7zKrN1+LVs0YhOGAC0mBWQgLNsdFiioVWoTY+cV0FhyAOJCRPnsnVUbFpmzQ5yxXWIlNW8pqmaTT9MRutOyDanl7iEZ+tllT6ADK9Zh+0KOYoaSw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954525; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=hqQ72NnIYBXINuVoG3HiOpoWjjk2RG4TM4kQcZaprKY=; b=dZBtFb2TC5MSPVCdUjGnkQ1HQK8Q04Ss9AY4KbHl/faKeoD/8yuNkpw3jAFoogSA8fZ6bkn+uEWA5XHXzRRXin1+Vkxwa5fM8f24j79z8MGtkEeWKZOY0RW5RhaxVe809OXf9fi0wQOY/fN3MkKo3OrNSmO5biAW2K8lx6GjNiI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 177295452555829.296025914160396; Sat, 7 Mar 2026 23:22:05 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8Rg-0002NV-Re; Sun, 08 Mar 2026 03:21:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8Qz-0001cW-Er for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:20:19 -0400 Received: from mail-dy1-x1343.google.com ([2607:f8b0:4864:20::1343]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8Qv-0002WX-Dy for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:20:17 -0400 Received: by mail-dy1-x1343.google.com with SMTP id 5a478bee46e88-2be3bdfda8eso3687281eec.1 for ; Sat, 07 Mar 2026 23:20:12 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.20.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:20:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954412; x=1773559212; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=hqQ72NnIYBXINuVoG3HiOpoWjjk2RG4TM4kQcZaprKY=; b=ayAdthtSQHM2SDQE+QuwvQ8xL2rBvnljem8OXuzr1KZdmxxhwDDKKIhpC4N6qAHQiW GTMMF0Y9+oe2P+7yzO8e6A0S7bT2ki5ns3GG4wTzk7ZtP+mcl5uI/ae1qrBDXCC2C5ux 3V/sfCP6TJ/x4te35l4ZduWmW4+gmUMySajqxuIIT/mwOse7dfOgG12R+Rqr0ZEcikpi jeGjoC1GKCetaUirGcQYy4ZzuV/vicB6MKHPqszKr8igQNzK8Y1ym2F7n8Q4+1zHOsIs ldfwiC+ugTCFzm8IgZzVlh7exgitY+kaFbfV62TTRTvjAHUx/R4Na5kJunk6nMtzTw2L 0M/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954412; x=1773559212; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=hqQ72NnIYBXINuVoG3HiOpoWjjk2RG4TM4kQcZaprKY=; b=FOgEx0TY6gCXROITlxU7jBR0JrHUFDzcWaiI/koO/3xT2lAgGWBXv8M0hxWQtLeBy5 1T6WDT4DKL5P3vm7ETYxZVeNs9gnrA4+8SymBFTsm142mJCcxJVRltMGaJNYTsdOMVSF eSpmD/7z3G7wgbZSIHwoO+9RyXUMWptUXPBUgBoMcShZA0/Jni6aW/M4WtrxjJLiEouq dNwhexf9ICl46Pj6/GrPVf73qHF+I3swrdJoHbi/NwDh/Z1fuNHd1GOqzpyb/Y+iBqAA 6vvq1U0hZwg7K/y7U16GwslmM1+/mpg6gqfFoKdJWpZfO50yjjSDose297mHjC8PfYYU +ESQ== X-Forwarded-Encrypted: i=1; AJvYcCVh+y8tEyMK3Yj+Kc8WFHOuhZg7YfQkOjX+yaccfS4VLYlcDzbezLoNFMUuWkTBpocgYnwSyjA7oVKP@nongnu.org X-Gm-Message-State: AOJu0YzBiDHOcmmpfDdmuMS/hVD2SQocnOx/XIggJsN/Bxxfw7Ail7rT wC5n/qCI0mdNfQX5zamNpAskkkg6kM4mjKcmi0L90IP/FJzEEjYBdvyQKDp4w6xu X-Gm-Gg: ATEYQzw3fGPG3OhnhiW9W7FfOsNQGh7Pb1r8TErI4sGNlvF2FbmPv6qmZAMuD5ZN1sf 7lzMgkaSfd8lZdorOHbHprZ/lIpopST3IZfzEU0UaP59XIrWadZGgqLuiVOHO/uoybjhDKD1J/0 OyByDd9psGsK3LIcxVIaSYxagWDNjmKKlVBzzDVEv1YKzaQmhUHVOCxq6LJMklG69prb8JKrvsH wodqXfWHhokjySkt005KZdEodCXNUM8nFyrUysSsWRDayhRVNtZ2q5e8ZvtbMS8yZH0Dz1LmX+z 6Dn4rTwFtR5uhuRwq8xMS+aod5mVr3+f23kG01QsNK9sCCvdJ/rSbO6/T8xQp9fUPMtP5l8RdDg VCw8n8C6Q9pvJX5ixGnfhptEh3uEv+Xe5xf+PAPi9A+mDU//8q3VQJZ0DWv/o644rWv0CWJFUlO GucH6JOIG3nOdETJzLJBREBoggtclWkvuBMw+JthOSyGCI7u+xhZzx1VNE1k829fqoebI7/6DD8 BfkvaWFYDU5/jxo7iepNP63p10= X-Received: by 2002:a05:693c:3101:b0:2be:aa:9a4a with SMTP id 5a478bee46e88-2be4dd62c65mr2585378eec.0.1772954411647; Sat, 07 Mar 2026 23:20:11 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 17/28] hw/riscv/dm: add hart run-control operations Date: Sun, 8 Mar 2026 15:17:20 +0800 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1343; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1343.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954526639154101 Content-Type: text/plain; charset="utf-8" Implement the dmcontrol operations that act on the selected hart set and expose the matching summary registers. This adds haltreq, resumereq, hartreset, ndmreset, and reset-haltreq handling, collects selected harts from hartsel, hasel, and hawindow, and computes haltsum0 and haltsum1 from the tracked hart state. It also feeds GOING, RESUME, halt, and resume acknowledgements from the ROM mailbox back into the state machine and adds tracepoints for the new transitions. Signed-off-by: Chao Liu --- hw/riscv/dm.c | 506 +++++++++++++++++++++++++++++++++++++++--- hw/riscv/trace-events | 14 ++ 2 files changed, 485 insertions(+), 35 deletions(-) diff --git a/hw/riscv/dm.c b/hw/riscv/dm.c index fad8e2b2ce..d55b5b827d 100644 --- a/hw/riscv/dm.c +++ b/hw/riscv/dm.c @@ -10,15 +10,28 @@ =20 #include "qemu/osdep.h" #include "qapi/error.h" +#include "hw/core/cpu.h" +#include "hw/core/irq.h" #include "hw/core/qdev-properties.h" #include "hw/riscv/dm.h" +#include "exec/cpu-common.h" #include "migration/vmstate.h" +#include "system/tcg.h" +#include "target/riscv/cpu.h" +#include "trace.h" =20 REG32(DMCONTROL, 0x40) FIELD(DMCONTROL, DMACTIVE, 0, 1) + FIELD(DMCONTROL, NDMRESET, 1, 1) + FIELD(DMCONTROL, CLRRESETHALTREQ, 2, 1) + FIELD(DMCONTROL, SETRESETHALTREQ, 3, 1) FIELD(DMCONTROL, HARTSELLO, 6, 10) FIELD(DMCONTROL, HARTSELHI, 16, 10) FIELD(DMCONTROL, HASEL, 26, 1) + FIELD(DMCONTROL, ACKHAVERESET, 28, 1) + FIELD(DMCONTROL, HARTRESET, 29, 1) + FIELD(DMCONTROL, RESUMEREQ, 30, 1) + FIELD(DMCONTROL, HALTREQ, 31, 1) =20 REG32(DMSTATUS, 0x44) FIELD(DMSTATUS, VERSION, 0, 4) @@ -28,6 +41,8 @@ REG32(DMSTATUS, 0x44) FIELD(DMSTATUS, ALLHALTED, 9, 1) FIELD(DMSTATUS, ANYRUNNING, 10, 1) FIELD(DMSTATUS, ALLRUNNING, 11, 1) + FIELD(DMSTATUS, ANYUNAVAIL, 12, 1) + FIELD(DMSTATUS, ALLUNAVAIL, 13, 1) FIELD(DMSTATUS, ANYNONEXISTENT, 14, 1) FIELD(DMSTATUS, ALLNONEXISTENT, 15, 1) FIELD(DMSTATUS, ANYRESUMEACK, 16, 1) @@ -35,6 +50,7 @@ REG32(DMSTATUS, 0x44) FIELD(DMSTATUS, ANYHAVERESET, 18, 1) FIELD(DMSTATUS, ALLHAVERESET, 19, 1) FIELD(DMSTATUS, IMPEBREAK, 22, 1) + FIELD(DMSTATUS, NDMRESETPENDING, 24, 1) =20 REG32(HARTINFO, 0x48) FIELD(HARTINFO, DATAADDR, 0, 12) @@ -42,12 +58,28 @@ REG32(HARTINFO, 0x48) FIELD(HARTINFO, DATAACCESS, 16, 1) FIELD(HARTINFO, NSCRATCH, 20, 4) =20 +REG32(HALTSUM1, 0x4c) + +REG32(HAWINDOWSEL, 0x50) + FIELD(HAWINDOWSEL, HAWINDOWSEL, 0, 15) + +REG32(HAWINDOW, 0x54) + REG32(ABSTRACTCS, 0x58) FIELD(ABSTRACTCS, DATACOUNT, 0, 4) FIELD(ABSTRACTCS, CMDERR, 8, 3) FIELD(ABSTRACTCS, BUSY, 12, 1) FIELD(ABSTRACTCS, PROGBUFSIZE, 24, 5) =20 +REG32(HALTSUM0, 0x100) + +typedef struct DMHartSelection { + int all[RISCV_DM_HAWINDOW_SIZE + 1]; + int all_count; + int harts[RISCV_DM_HAWINDOW_SIZE + 1]; + int valid_count; +} DMHartSelection; + static inline uint32_t dm_get_hartsel(RISCVDMState *s) { uint32_t hi =3D ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTSELHI); @@ -61,46 +93,306 @@ static inline bool dm_hart_valid(RISCVDMState *s, uint= 32_t hartsel) return hartsel < s->num_harts; } =20 -static void dm_status_refresh(RISCVDMState *s) +static inline uint32_t dm_rom_read32(RISCVDMState *s, uint32_t offset) +{ + return ldl_le_p(s->rom_ptr + offset); +} + +static inline void dm_rom_write32(RISCVDMState *s, uint32_t offset, + uint32_t val) +{ + stl_le_p(s->rom_ptr + offset, val); +} + +static inline void dm_rom_write8(RISCVDMState *s, uint32_t offset, uint8_t= val) +{ + s->rom_ptr[offset] =3D val; +} + +static void dm_selection_add(RISCVDMState *s, DMHartSelection *sel, int ha= rtsel) +{ + for (int i =3D 0; i < sel->all_count; i++) { + if (sel->all[i] =3D=3D hartsel) { + return; + } + } + + sel->all[sel->all_count++] =3D hartsel; + if (dm_hart_valid(s, hartsel)) { + sel->harts[sel->valid_count++] =3D hartsel; + } +} + +static void dm_collect_selected_harts(RISCVDMState *s, DMHartSelection *se= l) { uint32_t hartsel =3D dm_get_hartsel(s); - bool valid =3D dm_hart_valid(s, hartsel); - bool halted =3D valid && s->hart_halted[hartsel]; - bool running =3D valid && !s->hart_halted[hartsel]; - bool resumeack =3D valid && s->hart_resumeack[hartsel]; - bool havereset =3D valid && s->hart_havereset[hartsel]; - - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYNONEXISTENT, !valid); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLNONEXISTENT, !valid); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYHALTED, halted); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLHALTED, halted); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYRUNNING, running); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLRUNNING, running); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYRESUMEACK, resumeack); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLRESUMEACK, resumeack); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYHAVERESET, havereset); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLHAVERESET, havereset); + uint32_t wsel; + uint32_t window; + uint32_t base; + + memset(sel, 0, sizeof(*sel)); + dm_selection_add(s, sel, hartsel); + + if (!ARRAY_FIELD_EX32(s->regs, DMCONTROL, HASEL)) { + return; + } + + wsel =3D ARRAY_FIELD_EX32(s->regs, HAWINDOWSEL, HAWINDOWSEL); + if (wsel >=3D RISCV_DM_MAX_HARTS / RISCV_DM_HAWINDOW_SIZE) { + return; + } + + window =3D s->hawindow[wsel]; + base =3D wsel * RISCV_DM_HAWINDOW_SIZE; + for (int i =3D 0; i < RISCV_DM_HAWINDOW_SIZE; i++) { + if ((window >> i) & 1) { + dm_selection_add(s, sel, base + i); + } + } +} + +static inline bool dm_ndmreset_active(RISCVDMState *s) +{ + return ARRAY_FIELD_EX32(s->regs, DMCONTROL, NDMRESET); +} + +static bool dm_reg_present(RISCVDMState *s, hwaddr addr) +{ + switch (addr) { + case A_HALTSUM1: + return s->num_harts >=3D 33; + default: + return true; + } +} + +static void dm_status_refresh(RISCVDMState *s) +{ + DMHartSelection sel; + bool anyhalted =3D false; + bool allhalted =3D true; + bool anyrunning =3D false; + bool allrunning =3D true; + bool anyunavail =3D false; + bool allunavail =3D true; + bool anyresumeack =3D false; + bool allresumeack =3D true; + bool anyhavereset =3D false; + bool allhavereset =3D true; + bool anynonexistent; + bool allnonexistent; + bool reset_unavail =3D dm_ndmreset_active(s) || + ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTRESET); + + dm_collect_selected_harts(s, &sel); + + anynonexistent =3D sel.all_count > sel.valid_count; + allnonexistent =3D sel.valid_count =3D=3D 0 && sel.all_count > 0; + + if (sel.valid_count =3D=3D 0) { + allhalted =3D false; + allrunning =3D false; + allunavail =3D false; + allresumeack =3D false; + allhavereset =3D false; + } + + for (int i =3D 0; i < sel.valid_count; i++) { + int h =3D sel.harts[i]; + bool halted =3D s->hart_halted[h]; + bool resumeack =3D s->hart_resumeack[h]; + bool havereset =3D s->hart_havereset[h]; + + if (reset_unavail) { + anyunavail =3D true; + allhalted =3D false; + allrunning =3D false; + } else { + anyhalted |=3D halted; + allhalted &=3D halted; + anyrunning |=3D !halted; + allrunning &=3D !halted; + } + + allunavail &=3D reset_unavail; + anyresumeack |=3D resumeack; + allresumeack &=3D resumeack; + anyhavereset |=3D havereset; + allhavereset &=3D havereset; + } + + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYHALTED, anyhalted); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLHALTED, allhalted); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYRUNNING, anyrunning); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLRUNNING, allrunning); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYUNAVAIL, anyunavail); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLUNAVAIL, allunavail); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYNONEXISTENT, anynonexistent); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLNONEXISTENT, allnonexistent); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYRESUMEACK, anyresumeack); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLRESUMEACK, allresumeack); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYHAVERESET, anyhavereset); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLHAVERESET, allhavereset); ARRAY_FIELD_DP32(s->regs, DMSTATUS, HASRESETHALTREQ, 1); } =20 static void dm_debug_reset(RISCVDMState *s); =20 +static void dm_cpu_reset_on_cpu(CPUState *cpu, run_on_cpu_data data) +{ + (void)data; + cpu_reset(cpu); +} + +static void dm_note_hart_reset(RISCVDMState *s, uint32_t hartsel) +{ + CPUState *cs =3D qemu_get_cpu(hartsel); + + s->hart_halted[hartsel] =3D false; + s->hart_resumeack[hartsel] =3D false; + s->hart_havereset[hartsel] =3D true; + dm_rom_write8(s, RISCV_DM_ROM_FLAGS + hartsel, RISCV_DM_FLAG_CLEAR); + + if (cs && s->hart_resethaltreq[hartsel]) { + riscv_cpu_request_dm_halt(RISCV_CPU(cs), DCSR_CAUSE_RESET); + } +} + +static void dm_reset_hart(RISCVDMState *s, uint32_t hartsel) +{ + CPUState *cs; + + if (!dm_hart_valid(s, hartsel)) { + return; + } + + cs =3D qemu_get_cpu(hartsel); + if (cs && tcg_enabled()) { + run_on_cpu(cs, dm_cpu_reset_on_cpu, RUN_ON_CPU_NULL); + } + + dm_note_hart_reset(s, hartsel); +} + +static void dm_reset_selected_harts(RISCVDMState *s, DMHartSelection *sel) +{ + for (int i =3D 0; i < sel->valid_count; i++) { + dm_reset_hart(s, sel->harts[i]); + } +} + +static void dm_reset_all_harts(RISCVDMState *s) +{ + for (uint32_t hartsel =3D 0; hartsel < s->num_harts; hartsel++) { + dm_reset_hart(s, hartsel); + } +} + static uint64_t dm_dmcontrol_pre_write(RegisterInfo *reg, uint64_t val64) { RISCVDMState *s =3D RISCV_DM(reg->opaque); uint32_t val =3D val64; + uint32_t cur_ctl =3D s->regs[R_DMCONTROL]; + bool busy =3D ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, BUSY); + bool ndmreset_was =3D FIELD_EX32(cur_ctl, DMCONTROL, NDMRESET); + bool hartreset_was =3D FIELD_EX32(cur_ctl, DMCONTROL, HARTRESET); + bool dmactive =3D FIELD_EX32(val, DMCONTROL, DMACTIVE); + DMHartSelection sel; + uint32_t stored =3D 0; + + trace_riscv_dm_control_write(s->regs[R_DMCONTROL], val, busy); + + if (busy) { + val =3D FIELD_DP32(val, DMCONTROL, HARTSELHI, + ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTSELHI)); + val =3D FIELD_DP32(val, DMCONTROL, HARTSELLO, + ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTSELLO)); + val =3D FIELD_DP32(val, DMCONTROL, HASEL, + ARRAY_FIELD_EX32(s->regs, DMCONTROL, HASEL)); + val =3D FIELD_DP32(val, DMCONTROL, HALTREQ, 0); + val =3D FIELD_DP32(val, DMCONTROL, RESUMEREQ, 0); + val =3D FIELD_DP32(val, DMCONTROL, ACKHAVERESET, 0); + } =20 - if (!FIELD_EX32(val, DMCONTROL, DMACTIVE)) { + if (!dmactive) { dm_debug_reset(s); return 0; } =20 - s->dm_active =3D true; - - val =3D FIELD_DP32(val, DMCONTROL, DMACTIVE, 1); s->regs[R_DMCONTROL] =3D val; + dm_collect_selected_harts(s, &sel); + + if (FIELD_EX32(val, DMCONTROL, NDMRESET) && !ndmreset_was) { + dm_reset_all_harts(s); + } + + if (FIELD_EX32(val, DMCONTROL, HARTRESET) && !hartreset_was) { + dm_reset_selected_harts(s, &sel); + } + + ARRAY_FIELD_DP32(s->regs, DMSTATUS, NDMRESETPENDING, + FIELD_EX32(val, DMCONTROL, NDMRESET)); + + if (!busy && FIELD_EX32(val, DMCONTROL, ACKHAVERESET)) { + for (int i =3D 0; i < sel.valid_count; i++) { + s->hart_havereset[sel.harts[i]] =3D false; + } + } + + if (!busy && FIELD_EX32(val, DMCONTROL, SETRESETHALTREQ)) { + for (int i =3D 0; i < sel.valid_count; i++) { + s->hart_resethaltreq[sel.harts[i]] =3D true; + } + } + + if (!busy && FIELD_EX32(val, DMCONTROL, CLRRESETHALTREQ)) { + for (int i =3D 0; i < sel.valid_count; i++) { + s->hart_resethaltreq[sel.harts[i]] =3D false; + } + } + + if (!busy && FIELD_EX32(val, DMCONTROL, RESUMEREQ) && + !FIELD_EX32(val, DMCONTROL, HALTREQ)) { + for (int i =3D 0; i < sel.valid_count; i++) { + int h =3D sel.harts[i]; + + s->hart_resumeack[h] =3D false; + dm_rom_write8(s, RISCV_DM_ROM_FLAGS + h, RISCV_DM_FLAG_RESUME); + trace_riscv_dm_control_resume(h); + } + } + + if (!busy) { + if (FIELD_EX32(val, DMCONTROL, HALTREQ)) { + for (int i =3D 0; i < sel.valid_count; i++) { + int h =3D sel.harts[i]; + + dm_rom_write8(s, RISCV_DM_ROM_FLAGS + h, RISCV_DM_FLAG_CLE= AR); + qemu_set_irq(s->halt_irqs[h], 1); + trace_riscv_dm_control_halt(h); + } + } else { + for (int i =3D 0; i < sel.valid_count; i++) { + qemu_set_irq(s->halt_irqs[sel.harts[i]], 0); + } + } + } + + stored =3D FIELD_DP32(stored, DMCONTROL, DMACTIVE, 1); + stored =3D FIELD_DP32(stored, DMCONTROL, NDMRESET, + FIELD_EX32(val, DMCONTROL, NDMRESET)); + stored =3D FIELD_DP32(stored, DMCONTROL, HARTSELLO, + FIELD_EX32(val, DMCONTROL, HARTSELLO)); + stored =3D FIELD_DP32(stored, DMCONTROL, HARTSELHI, + FIELD_EX32(val, DMCONTROL, HARTSELHI)); + stored =3D FIELD_DP32(stored, DMCONTROL, HASEL, + FIELD_EX32(val, DMCONTROL, HASEL)); + stored =3D FIELD_DP32(stored, DMCONTROL, HARTRESET, + FIELD_EX32(val, DMCONTROL, HARTRESET)); + + s->dm_active =3D true; dm_status_refresh(s); - return val; + return stored; } =20 static uint64_t dm_dmstatus_post_read(RegisterInfo *reg, uint64_t val) @@ -108,7 +400,7 @@ static uint64_t dm_dmstatus_post_read(RegisterInfo *reg= , uint64_t val) RISCVDMState *s =3D RISCV_DM(reg->opaque); =20 dm_status_refresh(s); - return val; + return s->regs[R_DMSTATUS]; } =20 static uint64_t dm_hartinfo_post_read(RegisterInfo *reg, uint64_t val) @@ -123,6 +415,72 @@ static uint64_t dm_hartinfo_post_read(RegisterInfo *re= g, uint64_t val) return v; } =20 +static uint64_t dm_hawindowsel_pre_write(RegisterInfo *reg, uint64_t val64) +{ + uint32_t max_sel =3D RISCV_DM_MAX_HARTS / RISCV_DM_HAWINDOW_SIZE; + uint32_t val =3D val64 & R_HAWINDOWSEL_HAWINDOWSEL_MASK; + + (void)reg; + if (val >=3D max_sel) { + val =3D max_sel - 1; + } + return val; +} + +static uint64_t dm_hawindow_pre_write(RegisterInfo *reg, uint64_t val64) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + uint32_t wsel =3D ARRAY_FIELD_EX32(s->regs, HAWINDOWSEL, HAWINDOWSEL); + + if (wsel < RISCV_DM_MAX_HARTS / RISCV_DM_HAWINDOW_SIZE) { + s->hawindow[wsel] =3D val64; + } + return (uint32_t)val64; +} + +static uint64_t dm_hawindow_post_read(RegisterInfo *reg, uint64_t val) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + uint32_t wsel =3D ARRAY_FIELD_EX32(s->regs, HAWINDOWSEL, HAWINDOWSEL); + + (void)val; + if (wsel < RISCV_DM_MAX_HARTS / RISCV_DM_HAWINDOW_SIZE) { + return s->hawindow[wsel]; + } + return 0; +} + +static uint64_t dm_haltsum0_post_read(RegisterInfo *reg, uint64_t val) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + uint32_t sum =3D 0; + uint32_t base =3D 0; + uint32_t limit =3D MIN(s->num_harts, 32u); + + (void)val; + for (uint32_t h =3D base; h < limit; h++) { + if (s->hart_halted[h]) { + sum |=3D 1u << (h - base); + } + } + return sum; +} + +static uint64_t dm_haltsum1_post_read(RegisterInfo *reg, uint64_t val) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + uint32_t sum =3D 0; + + (void)reg; + (void)val; + for (uint32_t h =3D 0; h < s->num_harts; h++) { + if (s->hart_halted[h]) { + sum |=3D 1u << (h / 32); + } + } + return sum; +} + static RegisterAccessInfo riscv_dm_regs_info[] =3D { { .name =3D "DMCONTROL", .addr =3D A_DMCONTROL, .pre_write =3D dm_dmcontrol_pre_write, }, @@ -132,8 +490,19 @@ static RegisterAccessInfo riscv_dm_regs_info[] =3D { { .name =3D "HARTINFO", .addr =3D A_HARTINFO, .ro =3D 0xffffffff, .post_read =3D dm_hartinfo_post_read, }, + { .name =3D "HALTSUM1", .addr =3D A_HALTSUM1, + .ro =3D 0xffffffff, + .post_read =3D dm_haltsum1_post_read, }, + { .name =3D "HAWINDOWSEL", .addr =3D A_HAWINDOWSEL, + .pre_write =3D dm_hawindowsel_pre_write, }, + { .name =3D "HAWINDOW", .addr =3D A_HAWINDOW, + .pre_write =3D dm_hawindow_pre_write, + .post_read =3D dm_hawindow_post_read, }, { .name =3D "ABSTRACTCS", .addr =3D A_ABSTRACTCS, .ro =3D 0xffffffff, }, + { .name =3D "HALTSUM0", .addr =3D A_HALTSUM0, + .ro =3D 0xffffffff, + .post_read =3D dm_haltsum0_post_read, }, }; =20 static uint64_t riscv_dm_read(void *opaque, hwaddr addr, unsigned size) @@ -145,6 +514,19 @@ static uint64_t riscv_dm_read(void *opaque, hwaddr add= r, unsigned size) return 0; } =20 + if (dm_ndmreset_active(s)) { + if (addr =3D=3D A_DMSTATUS) { + return s->regs[R_DMSTATUS] & R_DMSTATUS_NDMRESETPENDING_MASK; + } + if (addr !=3D A_DMCONTROL) { + return 0; + } + } + + if (!dm_reg_present(s, addr)) { + return 0; + } + return register_read_memory(opaque, addr, size); } =20 @@ -158,6 +540,14 @@ static void riscv_dm_write(void *opaque, hwaddr addr, return; } =20 + if (dm_ndmreset_active(s) && addr !=3D A_DMCONTROL) { + return; + } + + if (!dm_reg_present(s, addr)) { + return; + } + register_write_memory(opaque, addr, value, size); } =20 @@ -181,29 +571,54 @@ static const MemoryRegionOps riscv_dm_ops =3D { static uint64_t dm_rom_read(void *opaque, hwaddr offset, unsigned size) { RISCVDMState *s =3D opaque; + uint64_t ret; =20 - return ldn_le_p(s->rom_ptr + offset, size); + ret =3D ldn_le_p(s->rom_ptr + offset, size); + trace_riscv_dm_rom_access(offset, ret, size, false); + return ret; } =20 static void dm_rom_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { RISCVDMState *s =3D opaque; + uint32_t hartsel; =20 stn_le_p(s->rom_ptr + offset, size, value); =20 + trace_riscv_dm_rom_access(offset, value, size, true); + if (offset =3D=3D RISCV_DM_ROM_HARTID && size =3D=3D 4) { - riscv_dm_hart_halted(s, value); + hartsel =3D value; + if (dm_hart_valid(s, hartsel)) { + riscv_dm_hart_halted(s, hartsel); + } + return; + } + + if (offset =3D=3D RISCV_DM_ROM_GOING && size =3D=3D 4) { + hartsel =3D dm_rom_read32(s, RISCV_DM_ROM_HARTID); + if (dm_hart_valid(s, hartsel)) { + dm_rom_write8(s, RISCV_DM_ROM_FLAGS + hartsel, + RISCV_DM_FLAG_CLEAR); + trace_riscv_dm_going(hartsel); + } return; } =20 if (offset =3D=3D RISCV_DM_ROM_RESUME && size =3D=3D 4) { - riscv_dm_hart_resumed(s, value); + hartsel =3D value; + if (dm_hart_valid(s, hartsel)) { + riscv_dm_hart_resumed(s, hartsel); + } return; } =20 if (offset =3D=3D RISCV_DM_ROM_EXCP && size =3D=3D 4) { - riscv_dm_abstracts_exception(s, dm_get_hartsel(s)); + hartsel =3D dm_rom_read32(s, RISCV_DM_ROM_HARTID); + if (dm_hart_valid(s, hartsel)) { + riscv_dm_abstracts_exception(s, hartsel); + } } } =20 @@ -250,6 +665,7 @@ void riscv_dm_hart_halted(RISCVDMState *s, uint32_t har= tsel) s->hart_halted[hartsel] =3D true; riscv_dm_abstracts_done(s, hartsel); dm_status_refresh(s); + trace_riscv_dm_hart_halted(hartsel); } =20 void riscv_dm_hart_resumed(RISCVDMState *s, uint32_t hartsel) @@ -260,21 +676,23 @@ void riscv_dm_hart_resumed(RISCVDMState *s, uint32_t = hartsel) =20 s->hart_halted[hartsel] =3D false; s->hart_resumeack[hartsel] =3D true; + dm_rom_write8(s, RISCV_DM_ROM_FLAGS + hartsel, RISCV_DM_FLAG_CLEAR); dm_status_refresh(s); + trace_riscv_dm_hart_resumed(hartsel); } =20 void riscv_dm_abstracts_done(RISCVDMState *s, uint32_t hartsel) { - (void)hartsel; ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, BUSY, 0); + trace_riscv_dm_abstract_cmd_complete(hartsel); } =20 void riscv_dm_abstracts_exception(RISCVDMState *s, uint32_t hartsel) { - (void)hartsel; ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, BUSY, 0); ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, CMDERR, RISCV_DM_CMDERR_EXCEPTION); + trace_riscv_dm_abstract_cmd_exception(hartsel); } =20 static void dm_debug_reset(RISCVDMState *s) @@ -287,11 +705,15 @@ static void dm_debug_reset(RISCVDMState *s) ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, PROGBUFSIZE, s->progbuf_size); =20 if (s->hart_halted) { - memset(s->hart_halted, 0, s->num_harts * sizeof(bool)); - memset(s->hart_resumeack, 0, s->num_harts * sizeof(bool)); - memset(s->hart_havereset, 1, s->num_harts * sizeof(bool)); + for (uint32_t i =3D 0; i < s->num_harts; i++) { + s->hart_halted[i] =3D false; + s->hart_resumeack[i] =3D false; + s->hart_havereset[i] =3D true; + s->hart_resethaltreq[i] =3D false; + } } =20 + memset(s->hawindow, 0, sizeof(s->hawindow)); s->dm_active =3D false; =20 if (s->rom_ptr) { @@ -324,11 +746,21 @@ static void riscv_dm_realize(DeviceState *dev, Error = **errp) return; } =20 - s->hart_halted =3D g_new0(bool, s->num_harts); - s->hart_resumeack =3D g_new0(bool, s->num_harts); - s->hart_havereset =3D g_new0(bool, s->num_harts); + if (s->num_harts > 0) { + s->hart_halted =3D g_new0(bool, s->num_harts); + s->hart_resumeack =3D g_new0(bool, s->num_harts); + s->hart_havereset =3D g_new0(bool, s->num_harts); + s->hart_resethaltreq =3D g_new0(bool, s->num_harts); + s->halt_irqs =3D g_new(qemu_irq, s->num_harts); + qdev_init_gpio_out(dev, s->halt_irqs, s->num_harts); + } =20 if (!dm_rom_realize(s, errp)) { + g_free(s->hart_halted); + g_free(s->hart_resumeack); + g_free(s->hart_havereset); + g_free(s->hart_resethaltreq); + g_free(s->halt_irqs); return; } =20 @@ -348,6 +780,8 @@ static void riscv_dm_unrealize(DeviceState *dev) g_free(s->hart_halted); g_free(s->hart_resumeack); g_free(s->hart_havereset); + g_free(s->hart_resethaltreq); + g_free(s->halt_irqs); } =20 static const Property riscv_dm_props[] =3D { @@ -372,6 +806,8 @@ static const VMStateDescription vmstate_riscv_dm =3D { 0, vmstate_info_bool, bool), VMSTATE_VARRAY_UINT32(hart_havereset, RISCVDMState, num_harts, 0, vmstate_info_bool, bool), + VMSTATE_VARRAY_UINT32(hart_resethaltreq, RISCVDMState, num_harts, + 0, vmstate_info_bool, bool), VMSTATE_END_OF_LIST(), } }; diff --git a/hw/riscv/trace-events b/hw/riscv/trace-events index b50b14a654..020e26607f 100644 --- a/hw/riscv/trace-events +++ b/hw/riscv/trace-events @@ -1,5 +1,19 @@ # See documentation at docs/devel/tracing.rst =20 +# dm.c +riscv_dm_control_write(uint32_t old_val, uint32_t new_val, bool busy) "old= =3D0x%08x new=3D0x%08x busy=3D%d" +riscv_dm_control_halt(uint32_t hartsel) "hartsel=3D%u" +riscv_dm_control_resume(uint32_t hartsel) "hartsel=3D%u" +riscv_dm_hart_halted(uint32_t hartsel) "hartsel=3D%u" +riscv_dm_hart_resumed(uint32_t hartsel) "hartsel=3D%u" +riscv_dm_abstract_cmd_submit(uint32_t cmdtype, uint32_t regno, bool transf= er, bool write, bool aarpostinc, bool postexec) "cmdtype=3D%u regno=3D0x%04= x transfer=3D%d write=3D%d aarpostinc=3D%d postexec=3D%d" +riscv_dm_abstract_cmd_complete(uint32_t hartsel) "hartsel=3D%u" +riscv_dm_abstract_cmd_exception(uint32_t hartsel) "hartsel=3D%u" +riscv_dm_abstract_cmd_rejected(const char *reason, uint32_t cmderr) "reaso= n=3D%s cmderr=3D%u" +riscv_dm_sba_access(uint64_t addr, uint32_t data, int bytes, bool is_write= ) "addr=3D0x%"PRIx64" data=3D0x%08x bytes=3D%d write=3D%d" +riscv_dm_rom_access(uint64_t offset, uint64_t value, unsigned size, bool i= s_write) "offset=3D0x%"PRIx64" value=3D0x%"PRIx64" size=3D%u write=3D%d" +riscv_dm_going(uint32_t hartsel) "hartsel=3D%u" + # riscv-iommu.c riscv_iommu_new(const char *id, unsigned b, unsigned d, unsigned f) "%s: d= evice attached %04x:%02x.%d" riscv_iommu_flt(const char *id, unsigned b, unsigned d, unsigned f, uint64= _t reason, uint64_t iova) "%s: fault %04x:%02x.%u reason: 0x%"PRIx64" iova:= 0x%"PRIx64 --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954545; cv=none; d=zohomail.com; s=zohoarc; b=XoYBDy41cshCiYrSnWpsNNXHwaH+cdXHiep3V1Ujf9dxSurIINNup29qmUYQ8w4fhM6rEwYCfzTIZURrLv5vsg3lnxmGFKGwPiM1juWISWl9sq7rF72uiOIt002Efpr/LpScLgvWdjHpNqcAGxev8pgumQd+Aam4pikAIGUM4Ng= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954545; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=aLL7Tl0LDKOGqVdwmIrV20atrUT/3NfBWs1jccL/0l4=; b=YbbKT/aj2yQ1ovL1ShyRAqldOAc+fvYxVjORpaggweY0U5SVn1qFsSU5C7esMF3o3qmM7AaRj07TfXeuF07NYCqGNMnJmTdu2RS3U8qJEBAAJtV0dInQ3yV7tNEnEaqhSZZ/vxz8eZEr1WP/HYfuiGj0HWoq2vygQER5vy8ghmc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 177295454596086.23566592926704; Sat, 7 Mar 2026 23:22:25 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8S8-00035H-0y; Sun, 08 Mar 2026 03:21:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8R3-0001dg-4F for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:20:22 -0400 Received: from mail-dy1-x1341.google.com ([2607:f8b0:4864:20::1341]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8R1-0002cD-Ha for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:20:20 -0400 Received: by mail-dy1-x1341.google.com with SMTP id 5a478bee46e88-2be4781d2baso4107737eec.0 for ; Sat, 07 Mar 2026 23:20:19 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.20.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:20:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954418; x=1773559218; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=aLL7Tl0LDKOGqVdwmIrV20atrUT/3NfBWs1jccL/0l4=; b=VWs+YDoyAQ+ygW55D5fkKkgkK1XD2T31liHJgvToPdb5aQAtuUk5Uto7oq/DL33O/5 fHR8PksmsdvERH0OucyXi4wIELohdm2Q3K+KUbxJZlK+DZBZkQrV/uW/LPp71hBkTrdJ EuTLv8L0Eo6CFSMICM/V//KvRXNjjt24tmcesD59SFofkHnGnI35LawPHcGpd/rDd2iE FPxuIg9teIMaJxGMk+xHlnfS1oneWbr8Mz0rhMmNZre9GDbhDg5Lnt320Du1h02rXOSg OPBkDIMIHhWYZYJy/3SxAY0n0Rl9yt+ZQ+qyZbYTK5N5ArwXJ4wB8EmqB+QiZdDYxqBB DsoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954418; x=1773559218; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=aLL7Tl0LDKOGqVdwmIrV20atrUT/3NfBWs1jccL/0l4=; b=nyiCI3ulhQzJuY+Anc3n3XXP7kuAINsBjcrU45LHYEgw5NyxhNEnhm/rrVmpNWGVql m2T3UVLlkvaD2RPH+69js4rYLIeHknvdcheEYw4mO8ku8tyVfqP7PMzx+F3no1UsQE0p RxsdxZ95aPb6v2le5MzulrtxEpfmxUgghdgQYAZfP2BaX7jVB3JKT20wvW/uVjcsLFZe yT1bibN69Jdfgj03AJInI6u/ZbPz4fVxeYM0Z4vi9RjPSC6Y8Vxp5z6AIbTPb2EP8g9j 2YyO/8MQ87jwryxFQs7cOj33+sohWLrONJNar8U6Hvk+/GtXJuiUVklhXu3F/2tK12iW VO1A== X-Forwarded-Encrypted: i=1; AJvYcCW108RHGaZiXItxrY1eBOkDImxCvXia1J762J2gYxzLYz3gaOGld4qp/XKgfL08DSWITHS7SmoF03As@nongnu.org X-Gm-Message-State: AOJu0Ywc9dIK1VmbVUrTEaqH0LRjH58wkUrGfno19K4PLdEUWZ5cvcZR 8O2LY1Z4+Bf26E7Z1qmSniIUKe8szRxvue1UNI8QaahupLOoegTYdh0R X-Gm-Gg: ATEYQzzm7EEg53c5n8F+eKft2tYPU9kM+fWYRZ7rZAyyS/D4jTcQT/34IY75Z2XHctQ LowqcToNabkSb4XJMQDs9aN/j+dIgAbx4XfPw+4WtwTJtQggyu4kGFWrtCxUxFA7T3hl/MqfM4B /lS3WYge8TlZSz8SpsModRLr47HSANvon5Ec28eD6xoavgoogBRFDvj3ix1qPH0nSnq+g6Z5KR/ IkbJSvSi1Yih0MZ2hRNhj8C1jI5VPEbjsJW7X4gyt2cXfM6uKm9GHHxV477DxMzmCm6k30jo0EW vXReeRiiRh6727d7KP1zadwnnqwOe1e36TSjqxmB9i8W9dmpySE20G6kW7zJQHWHV7Q6KxBsi/F 6Y3Sz05XcHWMkycyjsi5EloxkNtzRIlcRa5D0ZY5c9tKk2OlQ5o3KGjhyEW4nNg8tklNbFFmWXF QMuYKH9k0b5CRl7cztJrjyAPl3SbaWKHxQloGa0M2xCSHb4TNeEe7uA7jq0zDuGGLyLHFLoZeF5 T3/qsLKPzedEYpiH8a64R5+xD4= X-Received: by 2002:a05:7300:a883:b0:2be:522:2edf with SMTP id 5a478bee46e88-2be4e0d0aafmr3005632eec.39.1772954418104; Sat, 07 Mar 2026 23:20:18 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 18/28] hw/riscv/dm: queue reset halts from the reset work item Date: Sun, 8 Mar 2026 15:17:21 +0800 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1341; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1341.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954547567158500 Content-Type: text/plain; charset="utf-8" Queue reset-halt requests from the CPU reset work item so the halt is requested after the hart reset has completed, not before it starts. Keeping the ordering in one place avoids racing the pending halt against the code that clears hart state and ROM mailbox flags, and it works the same way for both TCG and non-TCG reset paths. Signed-off-by: Chao Liu --- hw/riscv/dm.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/hw/riscv/dm.c b/hw/riscv/dm.c index d55b5b827d..760cae27e2 100644 --- a/hw/riscv/dm.c +++ b/hw/riscv/dm.c @@ -240,22 +240,20 @@ static void dm_debug_reset(RISCVDMState *s); =20 static void dm_cpu_reset_on_cpu(CPUState *cpu, run_on_cpu_data data) { - (void)data; + bool request_reset_halt =3D data.host_int; + cpu_reset(cpu); + if (request_reset_halt) { + riscv_cpu_request_dm_halt(RISCV_CPU(cpu), DCSR_CAUSE_RESET); + } } =20 static void dm_note_hart_reset(RISCVDMState *s, uint32_t hartsel) { - CPUState *cs =3D qemu_get_cpu(hartsel); - s->hart_halted[hartsel] =3D false; s->hart_resumeack[hartsel] =3D false; s->hart_havereset[hartsel] =3D true; dm_rom_write8(s, RISCV_DM_ROM_FLAGS + hartsel, RISCV_DM_FLAG_CLEAR); - - if (cs && s->hart_resethaltreq[hartsel]) { - riscv_cpu_request_dm_halt(RISCV_CPU(cs), DCSR_CAUSE_RESET); - } } =20 static void dm_reset_hart(RISCVDMState *s, uint32_t hartsel) @@ -268,10 +266,15 @@ static void dm_reset_hart(RISCVDMState *s, uint32_t h= artsel) =20 cs =3D qemu_get_cpu(hartsel); if (cs && tcg_enabled()) { - run_on_cpu(cs, dm_cpu_reset_on_cpu, RUN_ON_CPU_NULL); + run_on_cpu(cs, dm_cpu_reset_on_cpu, + RUN_ON_CPU_HOST_INT(s->hart_resethaltreq[hartsel])); } =20 dm_note_hart_reset(s, hartsel); + + if (cs && !tcg_enabled() && s->hart_resethaltreq[hartsel]) { + riscv_cpu_request_dm_halt(RISCV_CPU(cs), DCSR_CAUSE_RESET); + } } =20 static void dm_reset_selected_harts(RISCVDMState *s, DMHartSelection *sel) --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954539; cv=none; d=zohomail.com; s=zohoarc; b=B+6mPP4qtCESSfABKmVWdMqoy8gql1yRX9K9/wGrKsFOjbsEvl8G3oGTu02GjQMDGUGnTTyz7PGNXRhE6DOMk9p3zrF5IobMkpYcycMxvgRGvaJn3RwLqH8x0i7Gn+LMItuyEAm1nAR1VcXsGMFFzDa0C/tJCg5CIf4dCpoYn8U= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954539; 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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=GHYY5BBIiUbYxlFw3Mg7gm0rTWiqz92vPX2RYiWNXFU=; b=bDbusOccI/67SQ4AgG7MYNVk+uwrv9uzIjKFGNnBI+gngitP2D6qEODWo/M66dTOI5/fu28F9XwaAj19D5OS9jhe0FwZEofniFt+D7rMgXD47gNcehW7K3RHzDoz/ROeOPjrLS77dUts6+wbxkFULwXharSwBrtGIml1h2W7bbc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954539635618.8311596650213; Sat, 7 Mar 2026 23:22:19 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8SY-0003Xc-Jv; Sun, 08 Mar 2026 03:21:56 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8RJ-00026G-7M for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:20:38 -0400 Received: from mail-dy1-x1341.google.com ([2607:f8b0:4864:20::1341]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8R7-0002ge-AI for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:20:28 -0400 Received: by mail-dy1-x1341.google.com with SMTP id 5a478bee46e88-2be1ab1fa7dso2553056eec.0 for ; Sat, 07 Mar 2026 23:20:24 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.20.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:20:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954424; x=1773559224; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=GHYY5BBIiUbYxlFw3Mg7gm0rTWiqz92vPX2RYiWNXFU=; b=F08gcrIZr5KqWeWdEQQaDERaIYi3kN8Hm6eBfO5kLB/LcdTFIu+vLBHkGGRuCqH3Zf 5bQRrNkOQilgneAMLcSDQ7JL4E5OHqsLhVqq4fQFi0FTNgwbd12jDxrk2yu/Ch8PVFp2 atHoKlISk5TrCgSz1MJ4wdRYaa97e5243/1BMKU3vqNJLXvfLaQ1AzgGeq4eN71MPSXS lOFJCkYoiOWDfR4FkjtjtTJSQfWaEQyiYEZm0h22eJL09Fr9mO2H5w+f7f6dBvpZsph6 ZHR0GPJwxGbVABXhDOJ3sSd+6mtv3jRA0fEXwA76FbHIRZ6rlhr2D+DpgIsRPkDer3hd bL1A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954424; x=1773559224; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=GHYY5BBIiUbYxlFw3Mg7gm0rTWiqz92vPX2RYiWNXFU=; b=l80p/2V4aQ9dz5gEGk5CSjA4rweRPUC6al9uAxpFu7S6BOXpGagx9hMtiBoc7iIV8b Jdi6yyzZnc6H/e30GEbyRNwJOx7c3n5F9D2uzswRXAQtN20+hDwMDSx+1lg3eg9c8+Iv cKjGUpRlFx1XIgq+xSjW0EU177MNpgdFNo9OF/I3np25/7kz8n1/CQfffKx1PM8US5SQ PRstQsuoF7hdhxCCZN+ebu90bo94m/3nZVYguWGd2gbksZLHGS74BSEmssT61AbM8ynt FnsQ3vR2JsSYrI0+hDj1psqMiMWm03kaLsAUPE4gX0bNQv+qpABJmCEh916eOPYLtpyl X93Q== X-Forwarded-Encrypted: i=1; AJvYcCW3FAJgI9OkLdUresyP+V58u69FLHscSC9O6ZsBhcgb/jHv5MfOt8Dd9Cnbjj1nV0/O1FNVBaQQ/Gn9@nongnu.org X-Gm-Message-State: AOJu0YxK8yzJXHFonq+LsvjlxM8AZPIW4fxZ3vKFf5BIINwFWh2EqAIN B22++8P1I68d0ZJ93m13/Q2dYPKNWmykXGj7gtC3Lhlt+QkX4pzN+84b X-Gm-Gg: ATEYQzxmltrhoVxLB5RSmVfLY/tuVDJoFPhMLERENBznnTNFoohbV9LoWiqTmqttX5U dfN1LPuoE6BHmivHW9QBkGIFMSfM8qd+EzQZ8WTg4UMwx9g9Tjy30bDTTc1Lh9ME+utLqe9Q0BC K/HckHAueubIdD5oNVyyaBL4LGFI04HfKQuCjRvn8yo4QgYYE0RzMN/td1oZWhwCqcjo8iIkYrx 8ed8o2kdhQ2CiEZRNYXxs+400GbQvXQ1N9Yo7HOJ6Z5IKQJzgZrxO73V9kI+hmrmBxqoQPukZYR C7AycKzxEqLuUtjBclJY3XjRO/xcM5S6/PQVKXEc+n2Nh1Reb/k3ySFlLxLhigMcsTtwDpLqZ3o faNdrHoOeziX0xyig0o1SUTxILDL1ZzxWPqTJfVlwxcvHN1Z9eK6PVxzqsH9Cs9V445lcFbHcfd sYIa8SaDd1Xu9Q3Ko5imG3LKjCCFLKJ+rBiG7YjZSErEfFtxFf+ETAgixU2BqzAOlMJ/N628UUy /OJM8Rtx9GVMRGVnk/5UL0AHM6sqCxT+Hcc3Q== X-Received: by 2002:a05:7301:fa0a:b0:2b8:30b8:58cf with SMTP id 5a478bee46e88-2be4de76edcmr3216133eec.8.1772954423774; Sat, 07 Mar 2026 23:20:23 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 19/28] hw/riscv/dm: add DMI register declarations and ROM entry program Date: Sun, 8 Mar 2026 15:17:22 +0800 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1341; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1341.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954540810154100 Add the complete set of DMI register field declarations per the Debug Specification v1.0 (DATA0-11, COMMAND, ABSTRACTAUTO, PROGBUF0-15, SBCS, SBADDRESS/DATA, etc.) and the instruction builder macros used to generate abstract command sequences. Lay down the ROM entry program (park loop, resume, exception vectors) and the ROM state management helpers (flush, sync, reset). Update dm_debug_reset() to use the new infrastructure. Signed-off-by: Chao Liu --- hw/riscv/dm.c | 423 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 373 insertions(+), 50 deletions(-) diff --git a/hw/riscv/dm.c b/hw/riscv/dm.c index 760cae27e2..427507e77e 100644 --- a/hw/riscv/dm.c +++ b/hw/riscv/dm.c @@ -4,61 +4,85 @@ * Copyright (c) 2025 Chao Liu * * Based on the RISC-V Debug Specification v1.0 (ratified 2025-02-21) + * Uses the QEMU register.h framework for declarative register definitions. * * SPDX-License-Identifier: GPL-2.0-or-later */ =20 #include "qemu/osdep.h" +#include "qemu/log.h" #include "qapi/error.h" #include "hw/core/cpu.h" -#include "hw/core/irq.h" #include "hw/core/qdev-properties.h" +#include "hw/core/irq.h" #include "hw/riscv/dm.h" #include "exec/cpu-common.h" #include "migration/vmstate.h" +#include "exec/translation-block.h" #include "system/tcg.h" #include "target/riscv/cpu.h" #include "trace.h" =20 +/* Addresses =3D DMI word address =C3=97 4 (byte offsets). */ + +REG32(DATA0, 0x10) +REG32(DATA1, 0x14) +REG32(DATA2, 0x18) +REG32(DATA3, 0x1C) +REG32(DATA4, 0x20) +REG32(DATA5, 0x24) +REG32(DATA6, 0x28) +REG32(DATA7, 0x2C) +REG32(DATA8, 0x30) +REG32(DATA9, 0x34) +REG32(DATA10, 0x38) +REG32(DATA11, 0x3C) + REG32(DMCONTROL, 0x40) - FIELD(DMCONTROL, DMACTIVE, 0, 1) - FIELD(DMCONTROL, NDMRESET, 1, 1) - FIELD(DMCONTROL, CLRRESETHALTREQ, 2, 1) - FIELD(DMCONTROL, SETRESETHALTREQ, 3, 1) - FIELD(DMCONTROL, HARTSELLO, 6, 10) - FIELD(DMCONTROL, HARTSELHI, 16, 10) - FIELD(DMCONTROL, HASEL, 26, 1) - FIELD(DMCONTROL, ACKHAVERESET, 28, 1) - FIELD(DMCONTROL, HARTRESET, 29, 1) - FIELD(DMCONTROL, RESUMEREQ, 30, 1) - FIELD(DMCONTROL, HALTREQ, 31, 1) + FIELD(DMCONTROL, DMACTIVE, 0, 1) + FIELD(DMCONTROL, NDMRESET, 1, 1) + FIELD(DMCONTROL, CLRRESETHALTREQ, 2, 1) + FIELD(DMCONTROL, SETRESETHALTREQ, 3, 1) + FIELD(DMCONTROL, CLRKEEPALIVE, 4, 1) + FIELD(DMCONTROL, SETKEEPALIVE, 5, 1) + FIELD(DMCONTROL, HARTSELLO, 6, 10) + FIELD(DMCONTROL, HARTSELHI, 16, 10) + FIELD(DMCONTROL, HASEL, 26, 1) + FIELD(DMCONTROL, ACKUNAVAIL, 27, 1) + FIELD(DMCONTROL, ACKHAVERESET, 28, 1) + FIELD(DMCONTROL, HARTRESET, 29, 1) + FIELD(DMCONTROL, RESUMEREQ, 30, 1) + FIELD(DMCONTROL, HALTREQ, 31, 1) =20 REG32(DMSTATUS, 0x44) - FIELD(DMSTATUS, VERSION, 0, 4) - FIELD(DMSTATUS, HASRESETHALTREQ, 5, 1) - FIELD(DMSTATUS, AUTHENTICATED, 7, 1) - FIELD(DMSTATUS, ANYHALTED, 8, 1) - FIELD(DMSTATUS, ALLHALTED, 9, 1) - FIELD(DMSTATUS, ANYRUNNING, 10, 1) - FIELD(DMSTATUS, ALLRUNNING, 11, 1) - FIELD(DMSTATUS, ANYUNAVAIL, 12, 1) - FIELD(DMSTATUS, ALLUNAVAIL, 13, 1) - FIELD(DMSTATUS, ANYNONEXISTENT, 14, 1) - FIELD(DMSTATUS, ALLNONEXISTENT, 15, 1) - FIELD(DMSTATUS, ANYRESUMEACK, 16, 1) - FIELD(DMSTATUS, ALLRESUMEACK, 17, 1) - FIELD(DMSTATUS, ANYHAVERESET, 18, 1) - FIELD(DMSTATUS, ALLHAVERESET, 19, 1) - FIELD(DMSTATUS, IMPEBREAK, 22, 1) + FIELD(DMSTATUS, VERSION, 0, 4) + FIELD(DMSTATUS, CONFSTRPTRVALID, 4, 1) + FIELD(DMSTATUS, HASRESETHALTREQ, 5, 1) + FIELD(DMSTATUS, AUTHBUSY, 6, 1) + FIELD(DMSTATUS, AUTHENTICATED, 7, 1) + FIELD(DMSTATUS, ANYHALTED, 8, 1) + FIELD(DMSTATUS, ALLHALTED, 9, 1) + FIELD(DMSTATUS, ANYRUNNING, 10, 1) + FIELD(DMSTATUS, ALLRUNNING, 11, 1) + FIELD(DMSTATUS, ANYUNAVAIL, 12, 1) + FIELD(DMSTATUS, ALLUNAVAIL, 13, 1) + FIELD(DMSTATUS, ANYNONEXISTENT, 14, 1) + FIELD(DMSTATUS, ALLNONEXISTENT, 15, 1) + FIELD(DMSTATUS, ANYRESUMEACK, 16, 1) + FIELD(DMSTATUS, ALLRESUMEACK, 17, 1) + FIELD(DMSTATUS, ANYHAVERESET, 18, 1) + FIELD(DMSTATUS, ALLHAVERESET, 19, 1) + FIELD(DMSTATUS, IMPEBREAK, 22, 1) + FIELD(DMSTATUS, STICKYUNAVAIL, 23, 1) FIELD(DMSTATUS, NDMRESETPENDING, 24, 1) =20 REG32(HARTINFO, 0x48) - FIELD(HARTINFO, DATAADDR, 0, 12) - FIELD(HARTINFO, DATASIZE, 12, 4) - FIELD(HARTINFO, DATAACCESS, 16, 1) - FIELD(HARTINFO, NSCRATCH, 20, 4) + FIELD(HARTINFO, DATAADDR, 0, 12) + FIELD(HARTINFO, DATASIZE, 12, 4) + FIELD(HARTINFO, DATAACCESS, 16, 1) + FIELD(HARTINFO, NSCRATCH, 20, 4) =20 -REG32(HALTSUM1, 0x4c) +REG32(HALTSUM1, 0x4C) =20 REG32(HAWINDOWSEL, 0x50) FIELD(HAWINDOWSEL, HAWINDOWSEL, 0, 15) @@ -66,13 +90,144 @@ REG32(HAWINDOWSEL, 0x50) REG32(HAWINDOW, 0x54) =20 REG32(ABSTRACTCS, 0x58) - FIELD(ABSTRACTCS, DATACOUNT, 0, 4) - FIELD(ABSTRACTCS, CMDERR, 8, 3) - FIELD(ABSTRACTCS, BUSY, 12, 1) + FIELD(ABSTRACTCS, DATACOUNT, 0, 4) + FIELD(ABSTRACTCS, CMDERR, 8, 3) + FIELD(ABSTRACTCS, BUSY, 12, 1) FIELD(ABSTRACTCS, PROGBUFSIZE, 24, 5) =20 +REG32(COMMAND, 0x5C) + FIELD(COMMAND, REGNO, 0, 16) + FIELD(COMMAND, WRITE, 16, 1) + FIELD(COMMAND, TRANSFER, 17, 1) + FIELD(COMMAND, POSTEXEC, 18, 1) + FIELD(COMMAND, AARPOSTINCREMENT, 19, 1) + FIELD(COMMAND, AARSIZE, 20, 3) + FIELD(COMMAND, CMDTYPE, 24, 8) + +REG32(ABSTRACTAUTO, 0x60) + FIELD(ABSTRACTAUTO, AUTOEXECDATA, 0, 12) + FIELD(ABSTRACTAUTO, AUTOEXECPROGBUF, 16, 16) + +REG32(CONFSTRPTR0, 0x64) +REG32(CONFSTRPTR1, 0x68) +REG32(CONFSTRPTR2, 0x6C) +REG32(CONFSTRPTR3, 0x70) + +REG32(NEXTDM, 0x74) + +REG32(PROGBUF0, 0x80) +REG32(PROGBUF1, 0x84) +REG32(PROGBUF2, 0x88) +REG32(PROGBUF3, 0x8C) +REG32(PROGBUF4, 0x90) +REG32(PROGBUF5, 0x94) +REG32(PROGBUF6, 0x98) +REG32(PROGBUF7, 0x9C) +REG32(PROGBUF8, 0xA0) +REG32(PROGBUF9, 0xA4) +REG32(PROGBUF10, 0xA8) +REG32(PROGBUF11, 0xAC) +REG32(PROGBUF12, 0xB0) +REG32(PROGBUF13, 0xB4) +REG32(PROGBUF14, 0xB8) +REG32(PROGBUF15, 0xBC) + +REG32(AUTHDATA, 0xC0) + +REG32(DMCS2, 0xC8) + FIELD(DMCS2, HGSELECT, 0, 1) + FIELD(DMCS2, HGWRITE, 1, 1) + FIELD(DMCS2, GROUP, 2, 5) + FIELD(DMCS2, DMEXTTRIGGER, 7, 4) + FIELD(DMCS2, GROUPTYPE, 11, 1) + +REG32(HALTSUM2, 0xD0) +REG32(HALTSUM3, 0xD4) + +REG32(SBADDRESS3, 0xDC) + +REG32(SBCS, 0xE0) + FIELD(SBCS, SBACCESS8, 0, 1) + FIELD(SBCS, SBACCESS16, 1, 1) + FIELD(SBCS, SBACCESS32, 2, 1) + FIELD(SBCS, SBACCESS64, 3, 1) + FIELD(SBCS, SBACCESS128, 4, 1) + FIELD(SBCS, SBASIZE, 5, 7) + FIELD(SBCS, SBERROR, 12, 3) + FIELD(SBCS, SBREADONDATA, 15, 1) + FIELD(SBCS, SBAUTOINCREMENT, 16, 1) + FIELD(SBCS, SBACCESS, 17, 3) + FIELD(SBCS, SBREADONADDR, 20, 1) + FIELD(SBCS, SBBUSY, 21, 1) + FIELD(SBCS, SBBUSYERROR, 22, 1) + FIELD(SBCS, SBVERSION, 29, 3) + +REG32(SBADDRESS0, 0xE4) +REG32(SBADDRESS1, 0xE8) +REG32(SBADDRESS2, 0xEC) + +REG32(SBDATA0, 0xF0) +REG32(SBDATA1, 0xF4) +REG32(SBDATA2, 0xF8) +REG32(SBDATA3, 0xFC) + REG32(HALTSUM0, 0x100) =20 + +/* Minimal instruction builders used by abstract commands and ROM mailboxe= s. */ +#define DM_I(opcode, funct3, rd, rs1, imm) \ + (((((uint32_t)(imm)) & 0xfffu) << 20) | \ + (((uint32_t)(rs1)) << 15) | (((uint32_t)(funct3)) << 12) | \ + (((uint32_t)(rd)) << 7) | ((uint32_t)(opcode))) + +#define DM_S(opcode, funct3, rs1, rs2, imm) \ + (((((((uint32_t)(imm)) >> 5) & 0x7fu) << 25) | \ + (((uint32_t)(rs2)) << 20) | (((uint32_t)(rs1)) << 15) | \ + (((uint32_t)(funct3)) << 12) | ((((uint32_t)(imm)) & 0x1fu) << 7) | \ + ((uint32_t)(opcode)))) + +#define DM_LOAD(rd, rs1, offset, size) \ + DM_I(0x03u, size, rd, rs1, offset) + +#define DM_STORE(rs2, rs1, offset, size) \ + DM_S(0x23u, size, rs1, rs2, offset) + +#define DM_FP_LOAD(rd, rs1, offset, size) \ + DM_I(0x07u, size, rd, rs1, offset) + +#define DM_FP_STORE(rs2, rs1, offset, size) \ + DM_S(0x27u, size, rs1, rs2, offset) + +#define DM_LBU(rd, rs1, offset) \ + DM_LOAD(rd, rs1, offset, 4u) + +#define DM_DATA_LOAD(rd, size) \ + DM_LOAD(rd, 0u, RISCV_DM_ROM_DATA, size) + +#define DM_DATA_STORE(rs2, size) \ + DM_STORE(rs2, 0u, RISCV_DM_ROM_DATA, size) + +#define DM_DATA_FP_LOAD(rd, size) \ + DM_FP_LOAD(rd, 0u, RISCV_DM_ROM_DATA, size) + +#define DM_DATA_FP_STORE(rs2, size) \ + DM_FP_STORE(rs2, 0u, RISCV_DM_ROM_DATA, size) + +/* csrr rd=3Ds0, csr=3Dregno */ +#define DM_CSRR(regno) \ + (0x2473u | ((uint32_t)(regno) << 20)) + +/* csrw csr=3Dregno, rs1=3Ds0 */ +#define DM_CSRW(regno) \ + (0x41073u | ((uint32_t)(regno) << 20)) + +/* jal x0, imm (imm is in units of 2 bytes, encoded in J-format) */ +#define DM_JAL(imm) \ + (0x6fu | ((uint32_t)(imm) << 21)) + +#define DM_NOP 0x13u +#define DM_EBREAK 0x100073u + typedef struct DMHartSelection { int all[RISCV_DM_HAWINDOW_SIZE + 1]; int all_count; @@ -109,6 +264,103 @@ static inline void dm_rom_write8(RISCVDMState *s, uin= t32_t offset, uint8_t val) s->rom_ptr[offset] =3D val; } =20 +static inline uint8_t dm_rom_read8(RISCVDMState *s, uint32_t offset) +{ + return s->rom_ptr[offset]; +} + +static void dm_sync_data_to_rom(RISCVDMState *s, int data_index) +{ + uint32_t val =3D s->regs[R_DATA0 + data_index]; + dm_rom_write32(s, RISCV_DM_ROM_DATA + data_index * 4, val); +} + +static void dm_sync_progbuf_to_rom(RISCVDMState *s, int progbuf_index) +{ + uint32_t val =3D s->regs[R_PROGBUF0 + progbuf_index]; + dm_rom_write32(s, RISCV_DM_ROM_PROGBUF + progbuf_index * 4, val); +} + +static void dm_flush_cmd_space(RISCVDMState *s) +{ + for (int i =3D 0; i < 8; i++) { + dm_rom_write32(s, RISCV_DM_ROM_CMD + i * 4, DM_NOP); + } + /* Restore s0 from dscratch0 */ + dm_rom_write32(s, RISCV_DM_ROM_CMD + 8 * 4, DM_CSRR(0x7b2)); + /* ebreak */ + dm_rom_write32(s, RISCV_DM_ROM_CMD + 9 * 4, DM_EBREAK); + /* Default whereto: jump to CMD space from the ROM dispatcher. */ + dm_rom_write32(s, RISCV_DM_ROM_WHERETO, DM_JAL(0x1C)); +} + +static void dm_invalidate_dynamic_code(RISCVDMState *s) +{ + if (tcg_enabled()) { + ram_addr_t base =3D memory_region_get_ram_addr(&s->rom_mr); + + tb_invalidate_phys_range(NULL, base + RISCV_DM_ROM_WHERETO, + base + RISCV_DM_ROM_DATA - 1); + } +} + +static void dm_update_impebreak(RISCVDMState *s) +{ + hwaddr ebreak_addr =3D RISCV_DM_ROM_PROGBUF + s->progbuf_size * 4; + + if (ebreak_addr + 4 > RISCV_DM_ROM_DATA) { + return; + } + + dm_rom_write32(s, ebreak_addr, s->impebreak ? DM_EBREAK : DM_NOP); +} + +static void dm_reset_rom_state(RISCVDMState *s) +{ + if (!s->rom_ptr) { + return; + } + + memset(s->rom_ptr + RISCV_DM_ROM_WORK_BASE, 0, RISCV_DM_ROM_WORK_SIZE); + + dm_flush_cmd_space(s); + + for (uint32_t i =3D 0; i < s->num_abstract_data; i++) { + dm_sync_data_to_rom(s, i); + } + for (uint32_t i =3D 0; i < s->progbuf_size; i++) { + dm_sync_progbuf_to_rom(s, i); + } + + dm_update_impebreak(s); + dm_invalidate_dynamic_code(s); +} + +static inline void dm_set_cmderr(RISCVDMState *s, uint32_t err) +{ + uint32_t cur =3D ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, CMDERR); + if (cur =3D=3D RISCV_DM_CMDERR_NONE) { + ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, CMDERR, err); + } +} + +static bool dm_abstract_cmd_completed(RISCVDMState *s, uint32_t hartsel) +{ + uint32_t selected =3D dm_get_hartsel(s); + uint8_t flags; + + if (!ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, BUSY) || selected !=3D hart= sel) { + return false; + } + + /* + * The hart only completes an execution-based abstract command after i= t has + * consumed GO and returned to the park loop. + */ + flags =3D dm_rom_read8(s, RISCV_DM_ROM_FLAGS + hartsel); + return !(flags & RISCV_DM_FLAG_GOING); +} + static void dm_selection_add(RISCVDMState *s, DMHartSelection *sel, int ha= rtsel) { for (int i =3D 0; i < sel->all_count; i++) { @@ -637,6 +889,65 @@ static const MemoryRegionOps dm_rom_ops =3D { =20 static bool dm_rom_realize(RISCVDMState *s, Error **errp) { + /* + * ROM program at 0x800: + * - entry: jump to _entry + * - resume: jump to _resume + * - exception: jump to _exception + * - _entry: fence, save s0, poll FLAGS loop + * - _exception: write EXCP, restore s0, ebreak + * - going: write GOING, restore s0, jump to whereto + * - _resume: write RESUME hartid, restore s0, dret + */ + static const uint32_t rom_code_entry[] =3D { + /* 0x800 : */ + 0x0180006f, /* j 818 <_entry> = */ + 0x00000013, /* nop = */ + + /* 0x808 : */ + 0x0600006f, /* j 868 <_resume> = */ + 0x00000013, /* nop = */ + + /* 0x810 : */ + 0x0400006f, /* j 850 <_exception> = */ + 0x00000013, /* nop = */ + + /* 0x818 <_entry>: */ + 0x0ff0000f, /* fence = */ + 0x7b241073, /* csrw dscratch0, s0 = */ + + /* 0x820 : */ + 0xf1402473, /* csrr s0, mhartid = */ + 0x07f47413, /* andi s0, s0, 127 = */ + DM_STORE(8, 0u, RISCV_DM_ROM_HARTID, 2u), /* sw s0, HARTID(zero) = */ + DM_LBU(8, 8, RISCV_DM_ROM_FLAGS), /* lbu s0, FLAGS(s0) = */ + 0x00147413, /* andi s0, s0, 1 = */ + 0x02041463, /* bnez s0, 85c = */ + 0xf1402473, /* csrr s0, mhartid = */ + 0x07f47413, /* andi s0, s0, 127 = */ + DM_LBU(8, 8, RISCV_DM_ROM_FLAGS), /* lbu s0, FLAGS(s0) = */ + 0x00247413, /* andi s0, s0, 2 = */ + 0xfc0410e3, /* bnez s0, 808 = */ + 0xfd5ff06f, /* j 820 = */ + + /* 0x850 <_exception>: */ + DM_STORE(0, 0u, RISCV_DM_ROM_EXCP, 2u), /* sw zero, EXCP(zero) = */ + 0x7b202473, /* csrr s0, dscratch0 = */ + 0x00100073, /* ebreak = */ + + /* 0x85c : */ + DM_STORE(0, 0u, RISCV_DM_ROM_GOING, 2u), /* sw zero, GOING(zero) = */ + 0x7b202473, /* csrr s0, dscratch0 = */ + 0xa9dff06f, /* j 300 = */ + + /* 0x868 <_resume>: */ + 0xf1402473, /* csrr s0, mhartid = */ + 0x07f47413, /* andi s0, s0, 127 = */ + DM_STORE(8, 0u, RISCV_DM_ROM_RESUME, 2u), /* sw s0, RESUME(zero) = */ + 0x7b202473, /* csrr s0, dscratch0 = */ + 0x7b200073, /* dret = */ + }; + SysBusDevice *sbd =3D SYS_BUS_DEVICE(s); =20 if (!memory_region_init_rom_device(&s->rom_mr, OBJECT(s), &dm_rom_ops,= s, @@ -644,9 +955,11 @@ static bool dm_rom_realize(RISCVDMState *s, Error **er= rp) errp)) { return false; } - s->rom_ptr =3D memory_region_get_ram_ptr(&s->rom_mr); =20 + memcpy(s->rom_ptr + RISCV_DM_ROM_ENTRY, rom_code_entry, + sizeof(rom_code_entry)); + memory_region_init_alias(&s->rom_work_alias_mr, OBJECT(s), "riscv-dm.rom-work", &s->rom_mr, RISCV_DM_ROM_WORK_BASE, RISCV_DM_ROM_WORK_SIZ= E); @@ -656,6 +969,7 @@ static bool dm_rom_realize(RISCVDMState *s, Error **err= p) =20 sysbus_init_mmio(sbd, &s->rom_work_alias_mr); sysbus_init_mmio(sbd, &s->rom_entry_alias_mr); + return true; } =20 @@ -666,7 +980,11 @@ void riscv_dm_hart_halted(RISCVDMState *s, uint32_t ha= rtsel) } =20 s->hart_halted[hartsel] =3D true; - riscv_dm_abstracts_done(s, hartsel); + + if (dm_abstract_cmd_completed(s, hartsel)) { + riscv_dm_abstracts_done(s, hartsel); + } + dm_status_refresh(s); trace_riscv_dm_hart_halted(hartsel); } @@ -692,22 +1010,29 @@ void riscv_dm_abstracts_done(RISCVDMState *s, uint32= _t hartsel) =20 void riscv_dm_abstracts_exception(RISCVDMState *s, uint32_t hartsel) { - ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, BUSY, 0); - ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, CMDERR, - RISCV_DM_CMDERR_EXCEPTION); + dm_set_cmderr(s, RISCV_DM_CMDERR_EXCEPTION); trace_riscv_dm_abstract_cmd_exception(hartsel); } =20 static void dm_debug_reset(RISCVDMState *s) { - memset(s->regs, 0, sizeof(s->regs)); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, VERSION, 3); + s->dm_active =3D false; + + /* Reset all registers via framework */ + for (unsigned int i =3D 0; i < ARRAY_SIZE(s->regs_info); i++) { + register_reset(&s->regs_info[i]); + } + + /* Set config-dependent reset values */ + ARRAY_FIELD_DP32(s->regs, DMSTATUS, VERSION, 3); /* v1.0 */ ARRAY_FIELD_DP32(s->regs, DMSTATUS, AUTHENTICATED, 1); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, IMPEBREAK, s->impebreak); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, IMPEBREAK, s->impebreak ? 1 : 0); + ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, DATACOUNT, s->num_abstract_data); ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, PROGBUFSIZE, s->progbuf_size); =20 - if (s->hart_halted) { + /* Reset per-hart state */ + if (s->hart_resumeack && s->num_harts > 0) { for (uint32_t i =3D 0; i < s->num_harts; i++) { s->hart_halted[i] =3D false; s->hart_resumeack[i] =3D false; @@ -717,12 +1042,9 @@ static void dm_debug_reset(RISCVDMState *s) } =20 memset(s->hawindow, 0, sizeof(s->hawindow)); - s->dm_active =3D false; - - if (s->rom_ptr) { - memset(s->rom_ptr, 0, RISCV_DM_SIZE); - } + s->last_cmd =3D 0; =20 + dm_reset_rom_state(s); dm_status_refresh(s); } =20 @@ -803,6 +1125,7 @@ static const VMStateDescription vmstate_riscv_dm =3D { .fields =3D (const VMStateField[]) { VMSTATE_UINT32_ARRAY(regs, RISCVDMState, RISCV_DM_R_MAX), VMSTATE_BOOL(dm_active, RISCVDMState), + VMSTATE_UINT32(last_cmd, RISCVDMState), VMSTATE_VARRAY_UINT32(hart_halted, RISCVDMState, num_harts, 0, vmstate_info_bool, bool), VMSTATE_VARRAY_UINT32(hart_resumeack, RISCVDMState, num_harts, --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954596; cv=none; d=zohomail.com; s=zohoarc; b=BAEc2cHCkuo/iUfAeOrnaaXqks87aZXhrjdKF20JZtBieZlC9A5SlekbJQDZzqzi/uy+Ug00yLlYZJWB4X3jNde5jJu2fLXQmsFYRclTmHAV6ZypuqckVu0Yp0d9deqZp6CqXyujX+UF5zmhCq1FXdH0k0NsqD9+plpXogvxANA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954596; 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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=tf5YP4hwd4+iXp/ZaW6QGtzdeaPjA06pKFhFFtnqSFw=; b=fZQSexaDRbouvPsI5VJEV+PUvNMHTsPHiWqaJzelev06n/gXTEYoyGoNURLTV5zoFlKwP9ABfd+ZTfDsQqJgjqDJNWLf8O/3bmij5OucnZBkWoFFn8BwRaIan8wyfxIklbSMUZlM5/188kkEwUQEzkqVdhRZruO0rZK0KaFnGcw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954596473996.4876798843769; Sat, 7 Mar 2026 23:23:16 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8Sx-0004fv-I3; Sun, 08 Mar 2026 03:22:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8RO-00029O-Rh for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:20:47 -0400 Received: from mail-dy1-x1343.google.com ([2607:f8b0:4864:20::1343]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8RJ-0002mk-26 for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:20:41 -0400 Received: by mail-dy1-x1343.google.com with SMTP id 5a478bee46e88-2bd9a485bd6so5552185eec.1 for ; Sat, 07 Mar 2026 23:20:32 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.20.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:20:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954431; x=1773559231; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=tf5YP4hwd4+iXp/ZaW6QGtzdeaPjA06pKFhFFtnqSFw=; b=kqdMW5iH+GJawH6ZFFltLy0myxGKOwh/CqyGfRuBA5im6YhzbXq1hG77aNmZT+tbp4 TbGMEIzMVTivGC3MRXs5YcnHom3OG2DqZiYkvHoE3CwHXwKD9KtRNyR0DOYz3iZ/0jCN AIQzWe4Js93TBxbsmgveo2zt7lfV8CtXejQt5xFKHqZseQPYjkW9JNa6EWp19nogEAiK AulQjbnKKEAwC94StAr4nMepx48kf5QkbWvZKPqARNeKDSXHL8pJXzFhmQptbjB67bVo NDFhpQgM3B/FrXVyaFG7mJtGyhBsbQBOBHi2/937IyYXCQqzCPfvgT2n6CEvUR+dnPt8 Mwtw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954431; x=1773559231; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=tf5YP4hwd4+iXp/ZaW6QGtzdeaPjA06pKFhFFtnqSFw=; b=GIiTfYprvNrWPDTu1WDzzADztemq2ChjTAVhlsLKYHMlxBU7copO9YwBz+tWnkvY+2 wzW+WKxoFhegPJ1K+EYPt+x14lxYUsqeyAr1rTqbT1+wH0F6DvN3cp1B5MyUTTGf1T/V o7DG6aKp1xP4fob/LKwqPkrF1KD6nzaVLOv3Y2sk7fI0gcxas9be7JwAGclknvEZkUTw SSoO+zuleBArY+q9WM8nrjVDSlUoIfGlB7J9NXkc4ra9w0k/GoRTGNWkLBX7CCBp2Fjq kQHf3IDtoLUgfYoZEwkqUmc0E0y74t5qb8tOiv0tPmXUxuCT7IS1sf3oE2v9jJHvEE3x lWVQ== X-Forwarded-Encrypted: i=1; AJvYcCXIs3E5Ozpy5c8WG9F+6DBMeS3ITOhIIRnbC6gSl8qfLT/bdcCr8/bNNQZOOGop0NNlXBCr8HDd9NkU@nongnu.org X-Gm-Message-State: AOJu0YzItayKrarwy2NDqKx70qN5S9KV9IelGvF9om92k3+gwxNaEUs0 ZNVEgrP+9BJ4CKhn64V6vHXBIacZIV/6CxRwEgdsNeAa4zl1DfexjU0w X-Gm-Gg: ATEYQzz5/HXadHusrZaysPiuRWoqhcXtaNlacNerW+cuXXe3cT5k1ucBqcYnBlrwN7q OlsTLMU6VdqKzfW46rAK7erIBFuo4oH0pM3/kUcQSdTKG1eD4GYrEHVCSmRlGeXTl0AfWSf4axd 3X0eZOxJoRoIKPmc+a8oflX9VL8sZPS3wDViTtsmoiVSE1YVbpuG2iGObpZMhXu4t3vhWQt7TQ5 pgjdgal6MVfK/4p7c1wja+o5eRbBqMZsvxOY3gtxPyNds60fo3m7tBsNlG2rUHT/mCReLev7S2M cMZ/UEAjHSsJje1aNdQbUXKzIbCQlRkg5FAf33FwDJq4e3iN8jidd7qlniLfBJM/GOY359GLYo4 Cdg9tKBd40BIou+xtayxPSjMEGiyxTwW1Ulo0ubZqsKolzc26IMBprMBpGlIdVS0zkzRQWlcJ/w VFs0mKeMX1FHr20D8IwNNNbTLvfEiNjn62/plW8n5KGXRpa/oGvyyN2p/QfVD+HxR99G3RO14mY gVcl+jcGE4ZHNFeyQAGxfBPnRmfPF0sE+rEMg== X-Received: by 2002:a05:693c:3104:b0:2ba:6b03:909b with SMTP id 5a478bee46e88-2be4e03b441mr3176842eec.19.1772954431060; Sat, 07 Mar 2026 23:20:31 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 20/28] hw/riscv/dm: add register handlers and update state management Date: Sun, 8 Mar 2026 15:17:23 +0800 Message-ID: <339a2c9cfa0a7efb1ef1c630c5b738c55ab05323.1772936778.git.chao.liu.zevorn@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1343; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1343.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954597749154100 Wire up pre_write/post_write/post_read callbacks for the newly declared registers (DATA, PROGBUF, COMMAND, ABSTRACTAUTO, ABSTRACTCS W1C) and expand the register_info table. Refactor dm_dmcontrol_pre_write for clarity, fix haltsum0/1 to use hartsel-based windowing, expand dm_reg_present for all optional registers, add DATA area remap in ROM read/write, and add realize-time validation for datacount and progbufsize. Signed-off-by: Chao Liu --- hw/riscv/dm.c | 772 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 571 insertions(+), 201 deletions(-) diff --git a/hw/riscv/dm.c b/hw/riscv/dm.c index 427507e77e..169863c54c 100644 --- a/hw/riscv/dm.c +++ b/hw/riscv/dm.c @@ -228,6 +228,7 @@ REG32(HALTSUM0, 0x100) #define DM_NOP 0x13u #define DM_EBREAK 0x100073u =20 + typedef struct DMHartSelection { int all[RISCV_DM_HAWINDOW_SIZE + 1]; int all_count; @@ -235,19 +236,6 @@ typedef struct DMHartSelection { int valid_count; } DMHartSelection; =20 -static inline uint32_t dm_get_hartsel(RISCVDMState *s) -{ - uint32_t hi =3D ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTSELHI); - uint32_t lo =3D ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTSELLO); - - return (hi << 10) | lo; -} - -static inline bool dm_hart_valid(RISCVDMState *s, uint32_t hartsel) -{ - return hartsel < s->num_harts; -} - static inline uint32_t dm_rom_read32(RISCVDMState *s, uint32_t offset) { return ldl_le_p(s->rom_ptr + offset); @@ -294,54 +282,58 @@ static void dm_flush_cmd_space(RISCVDMState *s) dm_rom_write32(s, RISCV_DM_ROM_WHERETO, DM_JAL(0x1C)); } =20 -static void dm_invalidate_dynamic_code(RISCVDMState *s) +static inline uint32_t dm_get_hartsel(RISCVDMState *s) { - if (tcg_enabled()) { - ram_addr_t base =3D memory_region_get_ram_addr(&s->rom_mr); - - tb_invalidate_phys_range(NULL, base + RISCV_DM_ROM_WHERETO, - base + RISCV_DM_ROM_DATA - 1); - } + uint32_t hi =3D ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTSELHI); + uint32_t lo =3D ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTSELLO); + return (hi << 10) | lo; } =20 -static void dm_update_impebreak(RISCVDMState *s) +static inline bool dm_hart_valid(RISCVDMState *s, uint32_t hartsel) { - hwaddr ebreak_addr =3D RISCV_DM_ROM_PROGBUF + s->progbuf_size * 4; + return hartsel < s->num_harts; +} =20 - if (ebreak_addr + 4 > RISCV_DM_ROM_DATA) { - return; +static void dm_selection_add(RISCVDMState *s, DMHartSelection *sel, int ha= rtsel) +{ + for (int i =3D 0; i < sel->all_count; i++) { + if (sel->all[i] =3D=3D hartsel) { + return; + } + } + sel->all[sel->all_count++] =3D hartsel; + if (dm_hart_valid(s, hartsel)) { + sel->harts[sel->valid_count++] =3D hartsel; } - - dm_rom_write32(s, ebreak_addr, s->impebreak ? DM_EBREAK : DM_NOP); } =20 -static void dm_reset_rom_state(RISCVDMState *s) +static void dm_collect_selected_harts(RISCVDMState *s, DMHartSelection *se= l) { - if (!s->rom_ptr) { - return; - } + uint32_t hartsel =3D dm_get_hartsel(s); =20 - memset(s->rom_ptr + RISCV_DM_ROM_WORK_BASE, 0, RISCV_DM_ROM_WORK_SIZE); + memset(sel, 0, sizeof(*sel)); + dm_selection_add(s, sel, hartsel); =20 - dm_flush_cmd_space(s); + if (!ARRAY_FIELD_EX32(s->regs, DMCONTROL, HASEL)) { + return; + } =20 - for (uint32_t i =3D 0; i < s->num_abstract_data; i++) { - dm_sync_data_to_rom(s, i); + uint32_t wsel =3D ARRAY_FIELD_EX32(s->regs, HAWINDOWSEL, HAWINDOWSEL); + if (wsel >=3D RISCV_DM_MAX_HARTS / RISCV_DM_HAWINDOW_SIZE) { + return; } - for (uint32_t i =3D 0; i < s->progbuf_size; i++) { - dm_sync_progbuf_to_rom(s, i); + uint32_t window =3D s->hawindow[wsel]; + uint32_t base =3D wsel * RISCV_DM_HAWINDOW_SIZE; + for (int i =3D 0; i < RISCV_DM_HAWINDOW_SIZE; i++) { + if ((window >> i) & 1) { + dm_selection_add(s, sel, base + i); + } } - - dm_update_impebreak(s); - dm_invalidate_dynamic_code(s); } =20 -static inline void dm_set_cmderr(RISCVDMState *s, uint32_t err) +static inline bool dm_ndmreset_active(RISCVDMState *s) { - uint32_t cur =3D ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, CMDERR); - if (cur =3D=3D RISCV_DM_CMDERR_NONE) { - ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, CMDERR, err); - } + return ARRAY_FIELD_EX32(s->regs, DMCONTROL, NDMRESET); } =20 static bool dm_abstract_cmd_completed(RISCVDMState *s, uint32_t hartsel) @@ -361,135 +353,137 @@ static bool dm_abstract_cmd_completed(RISCVDMState = *s, uint32_t hartsel) return !(flags & RISCV_DM_FLAG_GOING); } =20 -static void dm_selection_add(RISCVDMState *s, DMHartSelection *sel, int ha= rtsel) +static void dm_invalidate_dynamic_code(RISCVDMState *s) { - for (int i =3D 0; i < sel->all_count; i++) { - if (sel->all[i] =3D=3D hartsel) { - return; - } - } + if (tcg_enabled()) { + ram_addr_t base =3D memory_region_get_ram_addr(&s->rom_mr); =20 - sel->all[sel->all_count++] =3D hartsel; - if (dm_hart_valid(s, hartsel)) { - sel->harts[sel->valid_count++] =3D hartsel; + tb_invalidate_phys_range(NULL, base + RISCV_DM_ROM_WHERETO, + base + RISCV_DM_ROM_DATA - 1); } } =20 -static void dm_collect_selected_harts(RISCVDMState *s, DMHartSelection *se= l) +static bool dm_data_reg_present(RISCVDMState *s, hwaddr addr) { - uint32_t hartsel =3D dm_get_hartsel(s); - uint32_t wsel; - uint32_t window; - uint32_t base; + unsigned int index =3D (addr - A_DATA0) / 4; =20 - memset(sel, 0, sizeof(*sel)); - dm_selection_add(s, sel, hartsel); + return index < s->num_abstract_data; +} =20 - if (!ARRAY_FIELD_EX32(s->regs, DMCONTROL, HASEL)) { - return; - } +static bool dm_progbuf_reg_present(RISCVDMState *s, hwaddr addr) +{ + unsigned int index =3D (addr - A_PROGBUF0) / 4; =20 - wsel =3D ARRAY_FIELD_EX32(s->regs, HAWINDOWSEL, HAWINDOWSEL); - if (wsel >=3D RISCV_DM_MAX_HARTS / RISCV_DM_HAWINDOW_SIZE) { - return; - } + return index < s->progbuf_size; +} =20 - window =3D s->hawindow[wsel]; - base =3D wsel * RISCV_DM_HAWINDOW_SIZE; - for (int i =3D 0; i < RISCV_DM_HAWINDOW_SIZE; i++) { - if ((window >> i) & 1) { - dm_selection_add(s, sel, base + i); - } +static bool dm_sba_addr_reg_present(RISCVDMState *s, hwaddr addr) +{ + switch (addr) { + case A_SBADDRESS0: + return s->sba_addr_width > 0; + case A_SBADDRESS1: + return s->sba_addr_width > 32; + case A_SBADDRESS2: + return s->sba_addr_width > 64; + case A_SBADDRESS3: + return s->sba_addr_width > 96; + default: + return false; } } =20 -static inline bool dm_ndmreset_active(RISCVDMState *s) +static bool dm_sba_data_reg_present(RISCVDMState *s, hwaddr addr) { - return ARRAY_FIELD_EX32(s->regs, DMCONTROL, NDMRESET); + bool sbdata0 =3D ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS8) || + ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS16) || + ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS32) || + ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS64) || + ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS128); + bool sbdata1 =3D ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS64) || + ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS128); + bool sbdata23 =3D ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS128); + + switch (addr) { + case A_SBDATA0: + return sbdata0; + case A_SBDATA1: + return sbdata1; + case A_SBDATA2: + case A_SBDATA3: + return sbdata23; + default: + return false; + } } =20 static bool dm_reg_present(RISCVDMState *s, hwaddr addr) { + if (addr >=3D A_DATA0 && addr <=3D A_DATA11) { + return dm_data_reg_present(s, addr); + } + + if (addr >=3D A_PROGBUF0 && addr <=3D A_PROGBUF15) { + return dm_progbuf_reg_present(s, addr); + } + switch (addr) { + case A_AUTHDATA: + case A_DMCS2: + return false; case A_HALTSUM1: return s->num_harts >=3D 33; + case A_HALTSUM2: + return s->num_harts >=3D 1025; + case A_HALTSUM3: + return s->num_harts >=3D 32769; + case A_SBADDRESS0: + case A_SBADDRESS1: + case A_SBADDRESS2: + case A_SBADDRESS3: + return dm_sba_addr_reg_present(s, addr); + case A_SBDATA0: + case A_SBDATA1: + case A_SBDATA2: + case A_SBDATA3: + return dm_sba_data_reg_present(s, addr); default: return true; } } =20 -static void dm_status_refresh(RISCVDMState *s) +static void dm_update_impebreak(RISCVDMState *s) { - DMHartSelection sel; - bool anyhalted =3D false; - bool allhalted =3D true; - bool anyrunning =3D false; - bool allrunning =3D true; - bool anyunavail =3D false; - bool allunavail =3D true; - bool anyresumeack =3D false; - bool allresumeack =3D true; - bool anyhavereset =3D false; - bool allhavereset =3D true; - bool anynonexistent; - bool allnonexistent; - bool reset_unavail =3D dm_ndmreset_active(s) || - ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTRESET); + hwaddr ebreak_addr =3D RISCV_DM_ROM_PROGBUF + s->progbuf_size * 4; =20 - dm_collect_selected_harts(s, &sel); + if (ebreak_addr + 4 > RISCV_DM_ROM_DATA) { + return; + } =20 - anynonexistent =3D sel.all_count > sel.valid_count; - allnonexistent =3D sel.valid_count =3D=3D 0 && sel.all_count > 0; + dm_rom_write32(s, ebreak_addr, s->impebreak ? DM_EBREAK : DM_NOP); +} =20 - if (sel.valid_count =3D=3D 0) { - allhalted =3D false; - allrunning =3D false; - allunavail =3D false; - allresumeack =3D false; - allhavereset =3D false; +static void dm_reset_rom_state(RISCVDMState *s) +{ + if (!s->rom_ptr) { + return; } =20 - for (int i =3D 0; i < sel.valid_count; i++) { - int h =3D sel.harts[i]; - bool halted =3D s->hart_halted[h]; - bool resumeack =3D s->hart_resumeack[h]; - bool havereset =3D s->hart_havereset[h]; + memset(s->rom_ptr + RISCV_DM_ROM_WORK_BASE, 0, RISCV_DM_ROM_WORK_SIZE); =20 - if (reset_unavail) { - anyunavail =3D true; - allhalted =3D false; - allrunning =3D false; - } else { - anyhalted |=3D halted; - allhalted &=3D halted; - anyrunning |=3D !halted; - allrunning &=3D !halted; - } + dm_flush_cmd_space(s); =20 - allunavail &=3D reset_unavail; - anyresumeack |=3D resumeack; - allresumeack &=3D resumeack; - anyhavereset |=3D havereset; - allhavereset &=3D havereset; + for (uint32_t i =3D 0; i < s->num_abstract_data; i++) { + dm_sync_data_to_rom(s, i); + } + for (uint32_t i =3D 0; i < s->progbuf_size; i++) { + dm_sync_progbuf_to_rom(s, i); } =20 - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYHALTED, anyhalted); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLHALTED, allhalted); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYRUNNING, anyrunning); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLRUNNING, allrunning); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYUNAVAIL, anyunavail); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLUNAVAIL, allunavail); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYNONEXISTENT, anynonexistent); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLNONEXISTENT, allnonexistent); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYRESUMEACK, anyresumeack); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLRESUMEACK, allresumeack); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYHAVERESET, anyhavereset); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLHAVERESET, allhavereset); - ARRAY_FIELD_DP32(s->regs, DMSTATUS, HASRESETHALTREQ, 1); + dm_update_impebreak(s); + dm_invalidate_dynamic_code(s); } =20 -static void dm_debug_reset(RISCVDMState *s); - static void dm_cpu_reset_on_cpu(CPUState *cpu, run_on_cpu_data data) { bool request_reset_halt =3D data.host_int; @@ -543,20 +537,93 @@ static void dm_reset_all_harts(RISCVDMState *s) } } =20 + +static inline void dm_set_cmderr(RISCVDMState *s, uint32_t err) +{ + uint32_t cur =3D ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, CMDERR); + if (cur =3D=3D RISCV_DM_CMDERR_NONE) { + ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, CMDERR, err); + } +} + +static void dm_status_refresh(RISCVDMState *s) +{ + DMHartSelection sel; + bool anyhalted =3D false, allhalted =3D true; + bool anyrunning =3D false, allrunning =3D true; + bool anyunavail =3D false, allunavail =3D true; + bool anyresumeack =3D false, allresumeack =3D true; + bool anyhavereset =3D false, allhavereset =3D true; + bool anynonexistent =3D false, allnonexistent =3D false; + bool reset_unavail =3D dm_ndmreset_active(s) || + ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTRESET); + + dm_collect_selected_harts(s, &sel); + + anynonexistent =3D (sel.all_count > sel.valid_count); + allnonexistent =3D (sel.valid_count =3D=3D 0 && sel.all_count > 0); + + if (sel.valid_count =3D=3D 0) { + allhalted =3D false; + allrunning =3D false; + allunavail =3D false; + allresumeack =3D false; + allhavereset =3D false; + } + + for (int i =3D 0; i < sel.valid_count; i++) { + int h =3D sel.harts[i]; + bool halted =3D s->hart_halted[h]; + bool resumeack =3D s->hart_resumeack[h]; + bool havereset =3D s->hart_havereset[h]; + + if (reset_unavail) { + anyunavail =3D true; + allhalted =3D false; + allrunning =3D false; + } else { + anyhalted |=3D halted; + allhalted &=3D halted; + anyrunning |=3D !halted; + allrunning &=3D !halted; + } + + allunavail &=3D reset_unavail; + anyresumeack |=3D resumeack; + allresumeack &=3D resumeack; + anyhavereset |=3D havereset; + allhavereset &=3D havereset; + } + + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYHALTED, anyhalted); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLHALTED, allhalted); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYRUNNING, anyrunning); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLRUNNING, allrunning); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYUNAVAIL, anyunavail); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLUNAVAIL, allunavail); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYNONEXISTENT, anynonexistent); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLNONEXISTENT, allnonexistent); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYRESUMEACK, anyresumeack); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLRESUMEACK, allresumeack); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYHAVERESET, anyhavereset); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLHAVERESET, allhavereset); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, HASRESETHALTREQ, 1); +} + + +static void dm_debug_reset(RISCVDMState *s); static uint64_t dm_dmcontrol_pre_write(RegisterInfo *reg, uint64_t val64) { RISCVDMState *s =3D RISCV_DM(reg->opaque); - uint32_t val =3D val64; + uint32_t val =3D (uint32_t)val64; uint32_t cur_ctl =3D s->regs[R_DMCONTROL]; bool busy =3D ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, BUSY); bool ndmreset_was =3D FIELD_EX32(cur_ctl, DMCONTROL, NDMRESET); bool hartreset_was =3D FIELD_EX32(cur_ctl, DMCONTROL, HARTRESET); - bool dmactive =3D FIELD_EX32(val, DMCONTROL, DMACTIVE); - DMHartSelection sel; - uint32_t stored =3D 0; =20 trace_riscv_dm_control_write(s->regs[R_DMCONTROL], val, busy); =20 + /* If busy, preserve hart selection and suppress run-control */ if (busy) { val =3D FIELD_DP32(val, DMCONTROL, HARTSELHI, ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTSELHI)); @@ -569,25 +636,34 @@ static uint64_t dm_dmcontrol_pre_write(RegisterInfo *= reg, uint64_t val64) val =3D FIELD_DP32(val, DMCONTROL, ACKHAVERESET, 0); } =20 + bool dmactive =3D FIELD_EX32(val, DMCONTROL, DMACTIVE); + if (!dmactive) { + /* dmactive=3D0: reset the DM */ dm_debug_reset(s); + /* Return the reset value (only dmactive=3D0) */ return 0; } =20 + /* Store first so helpers see updated fields */ s->regs[R_DMCONTROL] =3D val; + + DMHartSelection sel; dm_collect_selected_harts(s, &sel); =20 - if (FIELD_EX32(val, DMCONTROL, NDMRESET) && !ndmreset_was) { + bool ndmreset =3D FIELD_EX32(val, DMCONTROL, NDMRESET); + bool hartreset =3D FIELD_EX32(val, DMCONTROL, HARTRESET); + + if (ndmreset && !ndmreset_was) { dm_reset_all_harts(s); } - - if (FIELD_EX32(val, DMCONTROL, HARTRESET) && !hartreset_was) { + if (hartreset && !hartreset_was) { dm_reset_selected_harts(s, &sel); } =20 - ARRAY_FIELD_DP32(s->regs, DMSTATUS, NDMRESETPENDING, - FIELD_EX32(val, DMCONTROL, NDMRESET)); + ARRAY_FIELD_DP32(s->regs, DMSTATUS, NDMRESETPENDING, ndmreset); =20 + /* ACKHAVERESET: clear havereset for selected harts */ if (!busy && FIELD_EX32(val, DMCONTROL, ACKHAVERESET)) { for (int i =3D 0; i < sel.valid_count; i++) { s->hart_havereset[sel.harts[i]] =3D false; @@ -606,22 +682,24 @@ static uint64_t dm_dmcontrol_pre_write(RegisterInfo *= reg, uint64_t val64) } } =20 - if (!busy && FIELD_EX32(val, DMCONTROL, RESUMEREQ) && - !FIELD_EX32(val, DMCONTROL, HALTREQ)) { + /* RESUMEREQ */ + bool resumereq =3D FIELD_EX32(val, DMCONTROL, RESUMEREQ); + bool haltreq =3D FIELD_EX32(val, DMCONTROL, HALTREQ); + + if (!busy && resumereq && !haltreq) { for (int i =3D 0; i < sel.valid_count; i++) { int h =3D sel.harts[i]; - s->hart_resumeack[h] =3D false; dm_rom_write8(s, RISCV_DM_ROM_FLAGS + h, RISCV_DM_FLAG_RESUME); trace_riscv_dm_control_resume(h); } } =20 + /* HALTREQ */ if (!busy) { - if (FIELD_EX32(val, DMCONTROL, HALTREQ)) { + if (haltreq) { for (int i =3D 0; i < sel.valid_count; i++) { int h =3D sel.harts[i]; - dm_rom_write8(s, RISCV_DM_ROM_FLAGS + h, RISCV_DM_FLAG_CLE= AR); qemu_set_irq(s->halt_irqs[h], 1); trace_riscv_dm_control_halt(h); @@ -633,6 +711,12 @@ static uint64_t dm_dmcontrol_pre_write(RegisterInfo *r= eg, uint64_t val64) } } =20 + /* + * Build the stored value: only keep fields with readable semantics. + * WARZ fields (haltreq, resumereq, ackhavereset, setresethaltreq, + * clrresethaltreq, setkeepalive, clrkeepalive, ackunavail) read as 0. + */ + uint32_t stored =3D 0; stored =3D FIELD_DP32(stored, DMCONTROL, DMACTIVE, 1); stored =3D FIELD_DP32(stored, DMCONTROL, NDMRESET, FIELD_EX32(val, DMCONTROL, NDMRESET)); @@ -643,17 +727,17 @@ static uint64_t dm_dmcontrol_pre_write(RegisterInfo *= reg, uint64_t val64) stored =3D FIELD_DP32(stored, DMCONTROL, HASEL, FIELD_EX32(val, DMCONTROL, HASEL)); stored =3D FIELD_DP32(stored, DMCONTROL, HARTRESET, - FIELD_EX32(val, DMCONTROL, HARTRESET)); + hartreset); =20 s->dm_active =3D true; dm_status_refresh(s); + return stored; } =20 static uint64_t dm_dmstatus_post_read(RegisterInfo *reg, uint64_t val) { RISCVDMState *s =3D RISCV_DM(reg->opaque); - dm_status_refresh(s); return s->regs[R_DMSTATUS]; } @@ -661,8 +745,7 @@ static uint64_t dm_dmstatus_post_read(RegisterInfo *reg= , uint64_t val) static uint64_t dm_hartinfo_post_read(RegisterInfo *reg, uint64_t val) { RISCVDMState *s =3D RISCV_DM(reg->opaque); - uint32_t v =3D val; - + uint32_t v =3D 0; v =3D FIELD_DP32(v, HARTINFO, DATAADDR, RISCV_DM_ROM_DATA); v =3D FIELD_DP32(v, HARTINFO, DATASIZE, s->num_abstract_data); v =3D FIELD_DP32(v, HARTINFO, DATAACCESS, 1); @@ -673,9 +756,7 @@ static uint64_t dm_hartinfo_post_read(RegisterInfo *reg= , uint64_t val) static uint64_t dm_hawindowsel_pre_write(RegisterInfo *reg, uint64_t val64) { uint32_t max_sel =3D RISCV_DM_MAX_HARTS / RISCV_DM_HAWINDOW_SIZE; - uint32_t val =3D val64 & R_HAWINDOWSEL_HAWINDOWSEL_MASK; - - (void)reg; + uint32_t val =3D (uint32_t)val64 & R_HAWINDOWSEL_HAWINDOWSEL_MASK; if (val >=3D max_sel) { val =3D max_sel - 1; } @@ -686,9 +767,8 @@ static uint64_t dm_hawindow_pre_write(RegisterInfo *reg= , uint64_t val64) { RISCVDMState *s =3D RISCV_DM(reg->opaque); uint32_t wsel =3D ARRAY_FIELD_EX32(s->regs, HAWINDOWSEL, HAWINDOWSEL); - if (wsel < RISCV_DM_MAX_HARTS / RISCV_DM_HAWINDOW_SIZE) { - s->hawindow[wsel] =3D val64; + s->hawindow[wsel] =3D (uint32_t)val64; } return (uint32_t)val64; } @@ -697,69 +777,312 @@ static uint64_t dm_hawindow_post_read(RegisterInfo *= reg, uint64_t val) { RISCVDMState *s =3D RISCV_DM(reg->opaque); uint32_t wsel =3D ARRAY_FIELD_EX32(s->regs, HAWINDOWSEL, HAWINDOWSEL); - - (void)val; if (wsel < RISCV_DM_MAX_HARTS / RISCV_DM_HAWINDOW_SIZE) { return s->hawindow[wsel]; } return 0; } =20 +static uint64_t dm_abstractcs_pre_write(RegisterInfo *reg, uint64_t val64) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + + if (ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, BUSY)) { + dm_set_cmderr(s, RISCV_DM_CMDERR_BUSY); + return s->regs[R_ABSTRACTCS]; + } + + /* W1C on CMDERR */ + uint32_t w1c_bits =3D FIELD_EX32((uint32_t)val64, ABSTRACTCS, CMDERR); + uint32_t cur =3D s->regs[R_ABSTRACTCS]; + uint32_t cmderr =3D FIELD_EX32(cur, ABSTRACTCS, CMDERR); + cmderr &=3D ~w1c_bits; + cur =3D FIELD_DP32(cur, ABSTRACTCS, CMDERR, cmderr); + + return cur; +} + +static uint64_t dm_command_pre_write(RegisterInfo *reg, uint64_t val64) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + + /* Stub: abstract command execution added in a follow-on patch. */ + s->last_cmd =3D (uint32_t)val64; + return s->regs[R_COMMAND]; +} + +static uint64_t dm_command_post_read(RegisterInfo *reg, uint64_t val) +{ + return 0; +} + +static uint64_t dm_abstractauto_pre_write(RegisterInfo *reg, uint64_t val6= 4) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + + if (ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, BUSY)) { + dm_set_cmderr(s, RISCV_DM_CMDERR_BUSY); + return s->regs[R_ABSTRACTAUTO]; + } + + /* Stub: autoexec trigger logic added in a follow-on patch. */ + uint32_t data_count =3D MIN(s->num_abstract_data, 12); + uint32_t pbuf_size =3D MIN(s->progbuf_size, 16); + uint32_t data_mask =3D data_count ? ((1u << data_count) - 1u) : 0; + uint32_t pbuf_mask =3D pbuf_size ? ((1u << pbuf_size) - 1u) : 0; + uint32_t mask =3D data_mask | (pbuf_mask << 16); + + return (uint32_t)val64 & mask; +} + +static uint64_t dm_data_pre_write(RegisterInfo *reg, uint64_t val64) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + + if (ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, BUSY)) { + dm_set_cmderr(s, RISCV_DM_CMDERR_BUSY); + return s->regs[reg->access->addr / 4]; + } + return (uint32_t)val64; +} + +static void dm_data_post_write(RegisterInfo *reg, uint64_t val64) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + int index =3D (reg->access->addr - A_DATA0) / 4; + + dm_sync_data_to_rom(s, index); +} + +static uint64_t dm_data_post_read(RegisterInfo *reg, uint64_t val) +{ + return val; +} + +static uint64_t dm_progbuf_pre_write(RegisterInfo *reg, uint64_t val64) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + + if (ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, BUSY)) { + dm_set_cmderr(s, RISCV_DM_CMDERR_BUSY); + return s->regs[reg->access->addr / 4]; + } + return (uint32_t)val64; +} + +static void dm_progbuf_post_write(RegisterInfo *reg, uint64_t val64) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + int index =3D (reg->access->addr - A_PROGBUF0) / 4; + + dm_sync_progbuf_to_rom(s, index); +} + +static uint64_t dm_progbuf_post_read(RegisterInfo *reg, uint64_t val) +{ + return val; +} + static uint64_t dm_haltsum0_post_read(RegisterInfo *reg, uint64_t val) { RISCVDMState *s =3D RISCV_DM(reg->opaque); - uint32_t sum =3D 0; - uint32_t base =3D 0; - uint32_t limit =3D MIN(s->num_harts, 32u); - - (void)val; - for (uint32_t h =3D base; h < limit; h++) { - if (s->hart_halted[h]) { - sum |=3D 1u << (h - base); + uint32_t result =3D 0; + uint32_t base =3D dm_get_hartsel(s) & ~0x1fu; + + for (uint32_t i =3D 0; i < 32; i++) { + uint32_t h =3D base + i; + if (h < s->num_harts && s->hart_halted[h]) { + result |=3D (1u << i); } } - return sum; + return result; } =20 static uint64_t dm_haltsum1_post_read(RegisterInfo *reg, uint64_t val) { RISCVDMState *s =3D RISCV_DM(reg->opaque); - uint32_t sum =3D 0; - - (void)reg; - (void)val; - for (uint32_t h =3D 0; h < s->num_harts; h++) { - if (s->hart_halted[h]) { - sum |=3D 1u << (h / 32); + uint32_t result =3D 0; + uint32_t base =3D dm_get_hartsel(s) & ~0x3ffu; + + for (uint32_t g =3D 0; g < 32; g++) { + for (uint32_t i =3D 0; i < 32; i++) { + uint32_t h =3D base + g * 32 + i; + if (h < s->num_harts && s->hart_halted[h]) { + result |=3D (1u << g); + break; + } } } - return sum; + return result; } =20 + static RegisterAccessInfo riscv_dm_regs_info[] =3D { + { .name =3D "DATA0", .addr =3D A_DATA0, .pre_write =3D dm_data_pre_w= rite, + .post_write =3D dm_data_post_write, .post_read =3D dm_data_post_read= , }, + { .name =3D "DATA1", .addr =3D A_DATA1, .pre_write =3D dm_data_pre_w= rite, + .post_write =3D dm_data_post_write, .post_read =3D dm_data_post_read= , }, + { .name =3D "DATA2", .addr =3D A_DATA2, .pre_write =3D dm_data_pre_w= rite, + .post_write =3D dm_data_post_write, .post_read =3D dm_data_post_read= , }, + { .name =3D "DATA3", .addr =3D A_DATA3, .pre_write =3D dm_data_pre_w= rite, + .post_write =3D dm_data_post_write, .post_read =3D dm_data_post_read= , }, + { .name =3D "DATA4", .addr =3D A_DATA4, .pre_write =3D dm_data_pre_w= rite, + .post_write =3D dm_data_post_write, .post_read =3D dm_data_post_read= , }, + { .name =3D "DATA5", .addr =3D A_DATA5, .pre_write =3D dm_data_pre_w= rite, + .post_write =3D dm_data_post_write, .post_read =3D dm_data_post_read= , }, + { .name =3D "DATA6", .addr =3D A_DATA6, .pre_write =3D dm_data_pre_w= rite, + .post_write =3D dm_data_post_write, .post_read =3D dm_data_post_read= , }, + { .name =3D "DATA7", .addr =3D A_DATA7, .pre_write =3D dm_data_pre_w= rite, + .post_write =3D dm_data_post_write, .post_read =3D dm_data_post_read= , }, + { .name =3D "DATA8", .addr =3D A_DATA8, .pre_write =3D dm_data_pre_w= rite, + .post_write =3D dm_data_post_write, .post_read =3D dm_data_post_read= , }, + { .name =3D "DATA9", .addr =3D A_DATA9, .pre_write =3D dm_data_pre_w= rite, + .post_write =3D dm_data_post_write, .post_read =3D dm_data_post_read= , }, + { .name =3D "DATA10", .addr =3D A_DATA10, .pre_write =3D dm_data_pre_w= rite, + .post_write =3D dm_data_post_write, .post_read =3D dm_data_post_read= , }, + { .name =3D "DATA11", .addr =3D A_DATA11, .pre_write =3D dm_data_pre_w= rite, + .post_write =3D dm_data_post_write, .post_read =3D dm_data_post_read= , }, + { .name =3D "DMCONTROL", .addr =3D A_DMCONTROL, .pre_write =3D dm_dmcontrol_pre_write, }, + { .name =3D "DMSTATUS", .addr =3D A_DMSTATUS, - .ro =3D 0xffffffff, + .ro =3D 0xFFFFFFFF, .post_read =3D dm_dmstatus_post_read, }, + { .name =3D "HARTINFO", .addr =3D A_HARTINFO, - .ro =3D 0xffffffff, + .ro =3D 0xFFFFFFFF, .post_read =3D dm_hartinfo_post_read, }, + { .name =3D "HALTSUM1", .addr =3D A_HALTSUM1, - .ro =3D 0xffffffff, + .ro =3D 0xFFFFFFFF, .post_read =3D dm_haltsum1_post_read, }, + { .name =3D "HAWINDOWSEL", .addr =3D A_HAWINDOWSEL, .pre_write =3D dm_hawindowsel_pre_write, }, + { .name =3D "HAWINDOW", .addr =3D A_HAWINDOW, .pre_write =3D dm_hawindow_pre_write, .post_read =3D dm_hawindow_post_read, }, + { .name =3D "ABSTRACTCS", .addr =3D A_ABSTRACTCS, - .ro =3D 0xffffffff, }, + .ro =3D R_ABSTRACTCS_DATACOUNT_MASK | R_ABSTRACTCS_BUSY_MASK | + R_ABSTRACTCS_PROGBUFSIZE_MASK, + .pre_write =3D dm_abstractcs_pre_write, }, + + { .name =3D "COMMAND", .addr =3D A_COMMAND, + .pre_write =3D dm_command_pre_write, + .post_read =3D dm_command_post_read, }, + + { .name =3D "ABSTRACTAUTO", .addr =3D A_ABSTRACTAUTO, + .pre_write =3D dm_abstractauto_pre_write, }, + + { .name =3D "CONFSTRPTR0", .addr =3D A_CONFSTRPTR0, .ro =3D 0xFFFFFFFF= , }, + { .name =3D "CONFSTRPTR1", .addr =3D A_CONFSTRPTR1, .ro =3D 0xFFFFFFFF= , }, + { .name =3D "CONFSTRPTR2", .addr =3D A_CONFSTRPTR2, .ro =3D 0xFFFFFFFF= , }, + { .name =3D "CONFSTRPTR3", .addr =3D A_CONFSTRPTR3, .ro =3D 0xFFFFFFFF= , }, + + { .name =3D "NEXTDM", .addr =3D A_NEXTDM, .ro =3D 0xFFFFFFFF, }, + + { .name =3D "PROGBUF0", .addr =3D A_PROGBUF0, + .pre_write =3D dm_progbuf_pre_write, + .post_write =3D dm_progbuf_post_write, + .post_read =3D dm_progbuf_post_read, }, + { .name =3D "PROGBUF1", .addr =3D A_PROGBUF1, + .pre_write =3D dm_progbuf_pre_write, + .post_write =3D dm_progbuf_post_write, + .post_read =3D dm_progbuf_post_read, }, + { .name =3D "PROGBUF2", .addr =3D A_PROGBUF2, + .pre_write =3D dm_progbuf_pre_write, + .post_write =3D dm_progbuf_post_write, + .post_read =3D dm_progbuf_post_read, }, + { .name =3D "PROGBUF3", .addr =3D A_PROGBUF3, + .pre_write =3D dm_progbuf_pre_write, + .post_write =3D dm_progbuf_post_write, + .post_read =3D dm_progbuf_post_read, }, + { .name =3D "PROGBUF4", .addr =3D A_PROGBUF4, + .pre_write =3D dm_progbuf_pre_write, + .post_write =3D dm_progbuf_post_write, + .post_read =3D dm_progbuf_post_read, }, + { .name =3D "PROGBUF5", .addr =3D A_PROGBUF5, + .pre_write =3D dm_progbuf_pre_write, + .post_write =3D dm_progbuf_post_write, + .post_read =3D dm_progbuf_post_read, }, + { .name =3D "PROGBUF6", .addr =3D A_PROGBUF6, + .pre_write =3D dm_progbuf_pre_write, + .post_write =3D dm_progbuf_post_write, + .post_read =3D dm_progbuf_post_read, }, + { .name =3D "PROGBUF7", .addr =3D A_PROGBUF7, + .pre_write =3D dm_progbuf_pre_write, + .post_write =3D dm_progbuf_post_write, + .post_read =3D dm_progbuf_post_read, }, + { .name =3D "PROGBUF8", .addr =3D A_PROGBUF8, + .pre_write =3D dm_progbuf_pre_write, + .post_write =3D dm_progbuf_post_write, + .post_read =3D dm_progbuf_post_read, }, + { .name =3D "PROGBUF9", .addr =3D A_PROGBUF9, + .pre_write =3D dm_progbuf_pre_write, + .post_write =3D dm_progbuf_post_write, + .post_read =3D dm_progbuf_post_read, }, + { .name =3D "PROGBUF10", .addr =3D A_PROGBUF10, + .pre_write =3D dm_progbuf_pre_write, + .post_write =3D dm_progbuf_post_write, + .post_read =3D dm_progbuf_post_read, }, + { .name =3D "PROGBUF11", .addr =3D A_PROGBUF11, + .pre_write =3D dm_progbuf_pre_write, + .post_write =3D dm_progbuf_post_write, + .post_read =3D dm_progbuf_post_read, }, + { .name =3D "PROGBUF12", .addr =3D A_PROGBUF12, + .pre_write =3D dm_progbuf_pre_write, + .post_write =3D dm_progbuf_post_write, + .post_read =3D dm_progbuf_post_read, }, + { .name =3D "PROGBUF13", .addr =3D A_PROGBUF13, + .pre_write =3D dm_progbuf_pre_write, + .post_write =3D dm_progbuf_post_write, + .post_read =3D dm_progbuf_post_read, }, + { .name =3D "PROGBUF14", .addr =3D A_PROGBUF14, + .pre_write =3D dm_progbuf_pre_write, + .post_write =3D dm_progbuf_post_write, + .post_read =3D dm_progbuf_post_read, }, + { .name =3D "PROGBUF15", .addr =3D A_PROGBUF15, + .pre_write =3D dm_progbuf_pre_write, + .post_write =3D dm_progbuf_post_write, + .post_read =3D dm_progbuf_post_read, }, + + { .name =3D "AUTHDATA", .addr =3D A_AUTHDATA, }, + + { .name =3D "DMCS2", .addr =3D A_DMCS2, }, + + { .name =3D "HALTSUM2", .addr =3D A_HALTSUM2, .ro =3D 0xFFFFFFFF, }, + { .name =3D "HALTSUM3", .addr =3D A_HALTSUM3, .ro =3D 0xFFFFFFFF, }, + + { .name =3D "SBADDRESS3", .addr =3D A_SBADDRESS3, }, + + { .name =3D "SBCS", .addr =3D A_SBCS, + .ro =3D R_SBCS_SBACCESS8_MASK | R_SBCS_SBACCESS16_MASK | + R_SBCS_SBACCESS32_MASK | R_SBCS_SBACCESS64_MASK | + R_SBCS_SBACCESS128_MASK | R_SBCS_SBASIZE_MASK | + R_SBCS_SBBUSY_MASK | R_SBCS_SBVERSION_MASK, }, + + { .name =3D "SBADDRESS0", .addr =3D A_SBADDRESS0, }, + + { .name =3D "SBADDRESS1", .addr =3D A_SBADDRESS1, }, + + { .name =3D "SBADDRESS2", .addr =3D A_SBADDRESS2, }, + + { .name =3D "SBDATA0", .addr =3D A_SBDATA0, }, + + { .name =3D "SBDATA1", .addr =3D A_SBDATA1, }, + + { .name =3D "SBDATA2", .addr =3D A_SBDATA2, }, + { .name =3D "SBDATA3", .addr =3D A_SBDATA3, }, + { .name =3D "HALTSUM0", .addr =3D A_HALTSUM0, - .ro =3D 0xffffffff, + .ro =3D 0xFFFFFFFF, .post_read =3D dm_haltsum0_post_read, }, }; =20 + static uint64_t riscv_dm_read(void *opaque, hwaddr addr, unsigned size) { RegisterInfoArray *reg_array =3D opaque; @@ -829,6 +1152,16 @@ static uint64_t dm_rom_read(void *opaque, hwaddr offs= et, unsigned size) uint64_t ret; =20 ret =3D ldn_le_p(s->rom_ptr + offset, size); + + /* DATA area remap: reads from ROM DATA area return register values */ + if (offset >=3D RISCV_DM_ROM_DATA && + offset < RISCV_DM_ROM_DATA + s->num_abstract_data * 4) { + int idx =3D (offset - RISCV_DM_ROM_DATA) / 4; + if (size =3D=3D 4) { + ret =3D s->regs[R_DATA0 + idx]; + } + } + trace_riscv_dm_rom_access(offset, ret, size, false); return ret; } @@ -837,54 +1170,59 @@ static void dm_rom_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { RISCVDMState *s =3D opaque; - uint32_t hartsel; =20 stn_le_p(s->rom_ptr + offset, size, value); =20 trace_riscv_dm_rom_access(offset, value, size, true); =20 + /* CPU wrote to HARTID register =E2=86=92 hart has halted */ if (offset =3D=3D RISCV_DM_ROM_HARTID && size =3D=3D 4) { - hartsel =3D value; + uint32_t hartsel =3D (uint32_t)value; if (dm_hart_valid(s, hartsel)) { riscv_dm_hart_halted(s, hartsel); } - return; } =20 + /* CPU wrote GOING acknowledgment */ if (offset =3D=3D RISCV_DM_ROM_GOING && size =3D=3D 4) { - hartsel =3D dm_rom_read32(s, RISCV_DM_ROM_HARTID); + uint32_t hartsel =3D dm_rom_read32(s, RISCV_DM_ROM_HARTID); if (dm_hart_valid(s, hartsel)) { dm_rom_write8(s, RISCV_DM_ROM_FLAGS + hartsel, RISCV_DM_FLAG_CLEAR); trace_riscv_dm_going(hartsel); } - return; } =20 + /* CPU wrote RESUME acknowledgment */ if (offset =3D=3D RISCV_DM_ROM_RESUME && size =3D=3D 4) { - hartsel =3D value; + uint32_t hartsel =3D (uint32_t)value; if (dm_hart_valid(s, hartsel)) { riscv_dm_hart_resumed(s, hartsel); } - return; } =20 + /* CPU wrote EXCEPTION */ if (offset =3D=3D RISCV_DM_ROM_EXCP && size =3D=3D 4) { - hartsel =3D dm_rom_read32(s, RISCV_DM_ROM_HARTID); + uint32_t hartsel =3D dm_rom_read32(s, RISCV_DM_ROM_HARTID); if (dm_hart_valid(s, hartsel)) { riscv_dm_abstracts_exception(s, hartsel); } } + + /* DATA area remap: writes to ROM DATA area update registers */ + if (offset >=3D RISCV_DM_ROM_DATA && + offset < RISCV_DM_ROM_DATA + s->num_abstract_data * 4 && size =3D= =3D 4) { + int idx =3D (offset - RISCV_DM_ROM_DATA) / 4; + s->regs[R_DATA0 + idx] =3D (uint32_t)value; + } } =20 static const MemoryRegionOps dm_rom_ops =3D { .read =3D dm_rom_read, .write =3D dm_rom_write, .endianness =3D DEVICE_LITTLE_ENDIAN, - .impl =3D { - .min_access_size =3D 1, - .max_access_size =3D 4, - }, + .impl.min_access_size =3D 1, + .impl.max_access_size =3D 4, }; =20 static bool dm_rom_realize(RISCVDMState *s, Error **errp) @@ -967,12 +1305,18 @@ static bool dm_rom_realize(RISCVDMState *s, Error **= errp) "riscv-dm.rom-entry", &s->rom_mr, RISCV_DM_ROM_ENTRY, RISCV_DM_ROM_ENTRY_SIZE); =20 + /* + * Expose debug backing store in two non-overlapping physical windows: + * - work area at low addresses (mailbox/data/progbuf/flags) + * - ROM entry vector at VIRT_DM_ROM base + */ sysbus_init_mmio(sbd, &s->rom_work_alias_mr); sysbus_init_mmio(sbd, &s->rom_entry_alias_mr); =20 return true; } =20 + void riscv_dm_hart_halted(RISCVDMState *s, uint32_t hartsel) { if (!dm_hart_valid(s, hartsel)) { @@ -998,6 +1342,7 @@ void riscv_dm_hart_resumed(RISCVDMState *s, uint32_t h= artsel) s->hart_halted[hartsel] =3D false; s->hart_resumeack[hartsel] =3D true; dm_rom_write8(s, RISCV_DM_ROM_FLAGS + hartsel, RISCV_DM_FLAG_CLEAR); + dm_status_refresh(s); trace_riscv_dm_hart_resumed(hartsel); } @@ -1014,6 +1359,7 @@ void riscv_dm_abstracts_exception(RISCVDMState *s, ui= nt32_t hartsel) trace_riscv_dm_abstract_cmd_exception(hartsel); } =20 + static void dm_debug_reset(RISCVDMState *s) { s->dm_active =3D false; @@ -1048,15 +1394,18 @@ static void dm_debug_reset(RISCVDMState *s) dm_status_refresh(s); } =20 + static void riscv_dm_init(Object *obj) { RISCVDMState *s =3D RISCV_DM(obj); SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); =20 - s->reg_array =3D register_init_block32(DEVICE(obj), riscv_dm_regs_info, - ARRAY_SIZE(riscv_dm_regs_info), - s->regs_info, s->regs, &riscv_dm_= ops, - false, RISCV_DM_REG_SIZE); + s->reg_array =3D + register_init_block32(DEVICE(obj), riscv_dm_regs_info, + ARRAY_SIZE(riscv_dm_regs_info), + s->regs_info, s->regs, + &riscv_dm_ops, false, + RISCV_DM_REG_SIZE); =20 sysbus_init_mmio(sbd, &s->reg_array->mem); } @@ -1071,6 +1420,25 @@ static void riscv_dm_realize(DeviceState *dev, Error= **errp) return; } =20 + if (s->num_abstract_data =3D=3D 0 || s->num_abstract_data > 12) { + error_setg(errp, "riscv-dm: datacount %u must be in range 1..12", + s->num_abstract_data); + return; + } + + if (s->progbuf_size > 16) { + error_setg(errp, "riscv-dm: progbufsize %u exceeds maximum 16", + s->progbuf_size); + return; + } + + if (s->progbuf_size =3D=3D 1 && !s->impebreak) { + error_setg(errp, + "riscv-dm: progbufsize 1 requires impebreak to be enabl= ed"); + return; + } + + /* Allocate per-hart state */ if (s->num_harts > 0) { s->hart_halted =3D g_new0(bool, s->num_harts); s->hart_resumeack =3D g_new0(bool, s->num_harts); @@ -1089,19 +1457,19 @@ static void riscv_dm_realize(DeviceState *dev, Erro= r **errp) return; } =20 + /* Apply initial reset */ dm_debug_reset(s); } =20 static void riscv_dm_reset_hold(Object *obj, ResetType type) { - (void)type; - dm_debug_reset(RISCV_DM(obj)); + RISCVDMState *s =3D RISCV_DM(obj); + dm_debug_reset(s); } =20 static void riscv_dm_unrealize(DeviceState *dev) { RISCVDMState *s =3D RISCV_DM(dev); - g_free(s->hart_halted); g_free(s->hart_resumeack); g_free(s->hart_havereset); @@ -1109,6 +1477,7 @@ static void riscv_dm_unrealize(DeviceState *dev) g_free(s->halt_irqs); } =20 + static const Property riscv_dm_props[] =3D { DEFINE_PROP_UINT32("num-harts", RISCVDMState, num_harts, 1), DEFINE_PROP_UINT32("datacount", RISCVDMState, num_abstract_data, 2), @@ -1183,5 +1552,6 @@ DeviceState *riscv_dm_create(MemoryRegion *sys_mem, h= waddr base, /* MMIO region 2: debug ROM entry vector */ memory_region_add_subregion(sys_mem, base + RISCV_DM_ROM_ENTRY, sysbus_mmio_get_region(sbd, 2)); + return dev; } --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954561; cv=none; d=zohomail.com; s=zohoarc; b=LRXCzhKTdXK6ZKDXIHHpIlnBSQQLzzG6bEB9y/4ZOp1+/1CZv16o+qj8Il1VvtP7a2JUT0l8XvnHTsup4gFLYR4J+4U7/eB50WaZGR+wpQRGwNf5P9yZUDje7JyaBARkpCQW+5XAlaUfdWMAXkIA6wVR6Nu23ZyCy4CsQEUgtXM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954561; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=pf7Lj7RfCx/IUDSUNJ3d5FggA7Ilj5s8BkMaCOmMuME=; b=JbPyOK7+E/a+mvE5FKOR5u2adcoX8nLzTq1CtVuwQ4IXWxXDNkrb3otd2OMfg3EsG4OjggM9ttaveBfDWnTWlUPP2b4oAcmtQ7rksJCvup2RegDNBn+0n+G9hZK6PNStSh8iNUGIIx7mZz8F44tvbkqVzhJw0NcNRmO8bvL2IfI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954561515109.8100354441599; Sat, 7 Mar 2026 23:22:41 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8S2-00030P-J3; Sun, 08 Mar 2026 03:21:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8RP-00029h-8o for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:20:47 -0400 Received: from mail-dy1-x1342.google.com ([2607:f8b0:4864:20::1342]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8RL-0002s5-KL for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:20:43 -0400 Received: by mail-dy1-x1342.google.com with SMTP id 5a478bee46e88-2be1b5fe11cso6989105eec.0 for ; Sat, 07 Mar 2026 23:20:38 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.20.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:20:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954437; x=1773559237; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=pf7Lj7RfCx/IUDSUNJ3d5FggA7Ilj5s8BkMaCOmMuME=; b=MVa5G9IKXGPxheaq2QFWcjUUHlce13sFoqObImIeojbk45/l1DOOeNe3afABqatBna eW9nClaA3gxIFPbLLZq1NKdVEODxSTFHd/Bqu73npg1J90GF+fJgGuJcAqFWWEi3MAPF 0Rn8c0BtAMgDb/kRQqJ7KZVDLnKSpxTxK1n0bXNtruFZlcKDRr2Emcz46CVFyMlaxU7y 59BYq03SU8WnCS/aXqzHjx6NXsdtfJl3eLASP7TqGdWlWqaPJv07Vux+wN0I8OhBh5R6 bqNzeCfs7cnuD1/r1dW6vchtu8qT4SBKPThlkdtAD3CdAZkUWiNjqQOD+SvUH9NY3b5X +bRQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954437; x=1773559237; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=pf7Lj7RfCx/IUDSUNJ3d5FggA7Ilj5s8BkMaCOmMuME=; b=jtmWNmxtzpP/jddA96VB3Nt82VYhsurU1GDnnCAqpZMs1IWVniZbTeYB5ISDf02T6V D9bXUOry4UGti2+GAeKMJI2GfYSjGK2SIWNgFqnU/WlWgrWXfUaC1ErFz/D3wP+b5lGE COmT7KIM12+uI2Px6kTGjrsxXe8JXSGZoGKgYjWox0tqbWHS2UyFDjY5I+CcNjxxtuC9 ow37Jik8TbMPYR5RYWOtOaqqmF4jyklGOlri3iwYC8cjbi0kJyORbEx314Sn6KIxRLQT WPqL8xhAoRenMD5+80Qn/nPbY0wOsmEESLJMdb9hDNBaUi8PuK1b+EWqbCEsM6zu/sN/ RV+w== X-Forwarded-Encrypted: i=1; AJvYcCUp5EgS+6ZzszNrQLx4FpeWCOHCr+97O/d7u41B4sZ6dB/INYokfl+Q5j2at5H/qctO2VuFGi7EkwXA@nongnu.org X-Gm-Message-State: AOJu0YztUKQZwQcQTLJejxXdW9nH0iPBHnSWlY7O/N+dK3jaafQYR4OM 2PooiS2sdNb1WZX3ZWgx9F6NSlKJ0GPx+2IHjwcKrnTDYroZ5abZ8wi1 X-Gm-Gg: ATEYQzy/gN7gCNykSW3hx1OGSrm3UQwPYU8eK/yN0brszJUTVEluEW9iZwq3XKMehpZ Tt4V0eslbsbwNp5Zixt7CBhLDL5JKYoUO3xd8ZXcbnJFfrWEH7+l73AEJjsaDegDqTpJKr+oVOE TucB4Av1IRsMQ5/AfhXhxf1jOXA87E1tQBH4r65F81PUWu4sVWfFb0nQh5D9XtvcBvHp3Fp5agr zyKrxxIyZPi9pu9Sfxld7+mKrFhphRsmaE+henC+OmO3Bl8uF4y6fW2BwRvxO0Ftcc81AvNArjN 8ZLGFTUzkn67sWXcailaMJsOO/zjuPuxfMUAgTO1LxZWOM7NmaNFKGRCGM8AEudwCKiTPZ0XWkc XoMr3/a2SPHA9k+BkM0GUvJ44o7BvcTgf1leEJxzWKuMbns5GLNotL+bGwuByZtdS4ur8n6ChXF OuQKq8L6hULTZWrd+o0OFoyQ/3k2kWdHFl/ApJy6zAQehgGbXkDM6b+8GNPr0zS352rM/D8K19p StQj4nzAoYWWw8jPLgnWbPUOz4= X-Received: by 2002:a05:7022:6892:b0:119:e569:f615 with SMTP id a92af1059eb24-128c2ddc872mr3107220c88.14.1772954437073; Sat, 07 Mar 2026 23:20:37 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 21/28] hw/riscv/dm: add abstract command execution Date: Sun, 8 Mar 2026 15:17:24 +0800 Message-ID: <07fdc457972b18350ba37019370fea56fba70019.1772936778.git.chao.liu.zevorn@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1342; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1342.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954563681158500 Content-Type: text/plain; charset="utf-8" Implement execution-based abstract commands following the pattern described in the RISC-V Debug Specification Appendix A.2. The Access Register command generates RISC-V instructions into the ROM command space for CSR (0x0000-0x0FFF), GPR (0x1000-0x101F), and FPR (0x1020-0x103F) transfers. The hart executes these instructions, and the DM detects completion when the hart returns to the park loop. This also adds the COMMAND and ABSTRACTAUTO register handlers, the autoexec mechanism that re-executes the last command on DATA or PROGBUF access, and the CMDERR sticky error reporting. Signed-off-by: Chao Liu --- hw/riscv/dm.c | 231 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 228 insertions(+), 3 deletions(-) diff --git a/hw/riscv/dm.c b/hw/riscv/dm.c index 169863c54c..818e48629f 100644 --- a/hw/riscv/dm.c +++ b/hw/riscv/dm.c @@ -336,6 +336,18 @@ static inline bool dm_ndmreset_active(RISCVDMState *s) return ARRAY_FIELD_EX32(s->regs, DMCONTROL, NDMRESET); } =20 +static RISCVCPU *dm_get_cpu(RISCVDMState *s, uint32_t hartsel) +{ + CPUState *cs; + + if (!dm_hart_valid(s, hartsel)) { + return NULL; + } + + cs =3D qemu_get_cpu(hartsel); + return cs ? RISCV_CPU(cs) : NULL; +} + static bool dm_abstract_cmd_completed(RISCVDMState *s, uint32_t hartsel) { uint32_t selected =3D dm_get_hartsel(s); @@ -545,6 +557,185 @@ static inline void dm_set_cmderr(RISCVDMState *s, uin= t32_t err) ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, CMDERR, err); } } +static void dm_execute_access_register(RISCVDMState *s, uint32_t command) +{ + uint32_t regno =3D FIELD_EX32(command, COMMAND, REGNO); + bool write =3D FIELD_EX32(command, COMMAND, WRITE); + bool transfer =3D FIELD_EX32(command, COMMAND, TRANSFER); + bool postexec =3D FIELD_EX32(command, COMMAND, POSTEXEC); + bool aarpostinc =3D FIELD_EX32(command, COMMAND, AARPOSTINCREMENT); + uint32_t aarsize =3D FIELD_EX32(command, COMMAND, AARSIZE); + + uint32_t hartsel =3D dm_get_hartsel(s); + RISCVCPU *cpu =3D dm_get_cpu(s, hartsel); + bool csr_hit =3D (regno <=3D RISCV_DM_REGNO_CSR_END); + bool gpr_hit =3D (regno >=3D RISCV_DM_REGNO_GPR_START && + regno <=3D RISCV_DM_REGNO_GPR_END); + bool fpr_hit =3D (regno >=3D RISCV_DM_REGNO_FPR_START && + regno <=3D RISCV_DM_REGNO_FPR_END); + uint32_t max_aarsize =3D 0; + + /* Hart must be halted */ + if (!dm_hart_valid(s, hartsel) || !s->hart_halted[hartsel]) { + dm_set_cmderr(s, RISCV_DM_CMDERR_HALTRESUME); + trace_riscv_dm_abstract_cmd_rejected("hart_not_halted", + ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, CMDERR)); + return; + } + + if (!cpu) { + dm_set_cmderr(s, RISCV_DM_CMDERR_HALTRESUME); + trace_riscv_dm_abstract_cmd_rejected("hart_unavailable", + ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, CMDERR)); + return; + } + + dm_flush_cmd_space(s); + + if (transfer) { + if (csr_hit || gpr_hit) { + max_aarsize =3D riscv_cpu_mxl(&cpu->env) =3D=3D MXL_RV32 ? 2 := 3; + } else if (fpr_hit) { + if (riscv_has_ext(&cpu->env, RVD)) { + max_aarsize =3D 3; + } else if (riscv_has_ext(&cpu->env, RVF)) { + max_aarsize =3D 2; + } + } + + if ((csr_hit || gpr_hit || fpr_hit) && + (aarsize < 2 || aarsize > max_aarsize)) { + dm_set_cmderr(s, RISCV_DM_CMDERR_NOTSUP); + trace_riscv_dm_abstract_cmd_rejected("unsupported_aarsize", + ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, CMDERR)); + return; + } + + if (!write) { + /* Read: copy register -> data */ + if (csr_hit) { + dm_rom_write32(s, RISCV_DM_ROM_CMD + 2 * 4, + DM_CSRR(regno & 0xFFF)); + dm_rom_write32(s, RISCV_DM_ROM_CMD + 3 * 4, + DM_DATA_STORE(8, aarsize)); + } else if (gpr_hit) { + if ((regno & 0x1F) =3D=3D 8) { + /* + * GPR 8 (s0) is used as a scratch register by the ROM. + * Read the architected x8 value from dscratch0 first. + */ + dm_rom_write32(s, RISCV_DM_ROM_CMD + 2 * 4, + DM_CSRR(0x7b2)); + dm_rom_write32(s, RISCV_DM_ROM_CMD + 3 * 4, + DM_DATA_STORE(8, aarsize)); + } else { + dm_rom_write32(s, RISCV_DM_ROM_CMD + 2 * 4, + DM_DATA_STORE(regno & 0x1F, aarsize)); + } + } else if (fpr_hit) { + dm_rom_write32(s, RISCV_DM_ROM_CMD + 2 * 4, + DM_DATA_FP_STORE(regno & 0x1F, aarsize)); + } else { + dm_set_cmderr(s, RISCV_DM_CMDERR_EXCEPTION); + trace_riscv_dm_abstract_cmd_rejected("unsupported_regno_re= ad", + ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, CMDERR)); + return; + } + } else { + /* Write: copy data -> register */ + if (csr_hit) { + dm_rom_write32(s, RISCV_DM_ROM_CMD + 2 * 4, + DM_DATA_LOAD(8, aarsize)); + dm_rom_write32(s, RISCV_DM_ROM_CMD + 3 * 4, + DM_CSRW(regno & 0xFFF)); + } else if (gpr_hit) { + if ((regno & 0x1F) =3D=3D 8) { + /* GPR 8 (s0) is saved in dscratch0 */ + dm_rom_write32(s, RISCV_DM_ROM_CMD + 2 * 4, + DM_DATA_LOAD(8, aarsize)); + dm_rom_write32(s, RISCV_DM_ROM_CMD + 3 * 4, + DM_CSRW(0x7b2)); + } else { + dm_rom_write32(s, RISCV_DM_ROM_CMD + 2 * 4, + DM_DATA_LOAD(regno & 0x1F, aarsize)); + } + } else if (fpr_hit) { + dm_rom_write32(s, RISCV_DM_ROM_CMD + 2 * 4, + DM_DATA_FP_LOAD(regno & 0x1F, aarsize)); + } else { + dm_set_cmderr(s, RISCV_DM_CMDERR_EXCEPTION); + trace_riscv_dm_abstract_cmd_rejected("unsupported_regno_wr= ite", + ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, CMDERR)); + return; + } + } + } + + /* Post-increment */ + if (aarpostinc && transfer) { + s->last_cmd =3D FIELD_DP32(command, COMMAND, REGNO, regno + 1); + } + + if (postexec) { + if (s->progbuf_size =3D=3D 0) { + dm_set_cmderr(s, RISCV_DM_CMDERR_NOTSUP); + trace_riscv_dm_abstract_cmd_rejected("postexec_without_progbuf= ", + ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, CMDERR)); + return; + } + + /* Restore s0 first, then continue with Program Buffer. */ + dm_rom_write32(s, RISCV_DM_ROM_CMD + 9 * 4, DM_JAL(2)); + } + + dm_invalidate_dynamic_code(s); + + /* Set BUSY */ + ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, BUSY, 1); + + /* Set FLAGS to going and signal hart */ + dm_rom_write8(s, RISCV_DM_ROM_FLAGS + hartsel, RISCV_DM_FLAG_GOING); + + trace_riscv_dm_abstract_cmd_submit( + FIELD_EX32(command, COMMAND, CMDTYPE), regno, transfer, + write, aarpostinc, postexec); +} + +static bool dm_execute_abstract_cmd(RISCVDMState *s, uint32_t command) +{ + uint32_t cmderr =3D ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, CMDERR); + + /* If cmderr is latched, reject silently */ + if (cmderr !=3D RISCV_DM_CMDERR_NONE) { + trace_riscv_dm_abstract_cmd_rejected("cmderr_latched", cmderr); + return false; + } + + /* If busy, set cmderr=3Dbusy */ + if (ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, BUSY)) { + dm_set_cmderr(s, RISCV_DM_CMDERR_BUSY); + trace_riscv_dm_abstract_cmd_rejected("command_while_busy", + ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, CMDERR)); + return false; + } + + uint32_t cmdtype =3D FIELD_EX32(command, COMMAND, CMDTYPE); + + switch (cmdtype) { + case RISCV_DM_CMD_ACCESS_REG: + dm_execute_access_register(s, command); + break; + default: + dm_set_cmderr(s, RISCV_DM_CMDERR_NOTSUP); + trace_riscv_dm_abstract_cmd_rejected("unsupported_cmdtype", + ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, CMDERR)); + break; + } + + return true; +} + + =20 static void dm_status_refresh(RISCVDMState *s) { @@ -805,9 +996,13 @@ static uint64_t dm_abstractcs_pre_write(RegisterInfo *= reg, uint64_t val64) static uint64_t dm_command_pre_write(RegisterInfo *reg, uint64_t val64) { RISCVDMState *s =3D RISCV_DM(reg->opaque); + uint32_t command =3D (uint32_t)val64; =20 - /* Stub: abstract command execution added in a follow-on patch. */ - s->last_cmd =3D (uint32_t)val64; + if (dm_execute_abstract_cmd(s, command)) { + s->last_cmd =3D command; + } + + /* COMMAND is WARZ: keep internal state, but reads always return 0. */ return s->regs[R_COMMAND]; } =20 @@ -825,7 +1020,6 @@ static uint64_t dm_abstractauto_pre_write(RegisterInfo= *reg, uint64_t val64) return s->regs[R_ABSTRACTAUTO]; } =20 - /* Stub: autoexec trigger logic added in a follow-on patch. */ uint32_t data_count =3D MIN(s->num_abstract_data, 12); uint32_t pbuf_size =3D MIN(s->progbuf_size, 16); uint32_t data_mask =3D data_count ? ((1u << data_count) - 1u) : 0; @@ -835,6 +1029,27 @@ static uint64_t dm_abstractauto_pre_write(RegisterInf= o *reg, uint64_t val64) return (uint32_t)val64 & mask; } =20 +static void dm_check_autoexec(RISCVDMState *s, bool is_data, int index) +{ + if (ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, BUSY)) { + dm_set_cmderr(s, RISCV_DM_CMDERR_BUSY); + return; + } + + uint32_t autoexec =3D s->regs[R_ABSTRACTAUTO]; + bool trigger; + + if (is_data) { + trigger =3D (autoexec >> index) & 1; + } else { + trigger =3D (autoexec >> (16 + index)) & 1; + } + + if (trigger) { + dm_execute_abstract_cmd(s, s->last_cmd); + } +} + static uint64_t dm_data_pre_write(RegisterInfo *reg, uint64_t val64) { RISCVDMState *s =3D RISCV_DM(reg->opaque); @@ -852,10 +1067,15 @@ static void dm_data_post_write(RegisterInfo *reg, ui= nt64_t val64) int index =3D (reg->access->addr - A_DATA0) / 4; =20 dm_sync_data_to_rom(s, index); + dm_check_autoexec(s, true, index); } =20 static uint64_t dm_data_post_read(RegisterInfo *reg, uint64_t val) { + RISCVDMState *s =3D RISCV_DM(reg->opaque); + int index =3D (reg->access->addr - A_DATA0) / 4; + + dm_check_autoexec(s, true, index); return val; } =20 @@ -876,10 +1096,15 @@ static void dm_progbuf_post_write(RegisterInfo *reg,= uint64_t val64) int index =3D (reg->access->addr - A_PROGBUF0) / 4; =20 dm_sync_progbuf_to_rom(s, index); + dm_check_autoexec(s, false, index); } =20 static uint64_t dm_progbuf_post_read(RegisterInfo *reg, uint64_t val) { + RISCVDMState *s =3D RISCV_DM(reg->opaque); + int index =3D (reg->access->addr - A_PROGBUF0) / 4; + + dm_check_autoexec(s, false, index); return val; } =20 --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954541; cv=none; d=zohomail.com; s=zohoarc; b=Kvw8fdKc0T06h/xEqojI0gaYJDasjk6KfYDKaP8iiquoKXfedrEmrOZYYF2Vmm43ev6BMFz7DEzU8/3A3Bam5YjvHhTAUoVDg2XExXK1rwRFjeDstWizmzMqLmyGQPZLLH8/b3ROeACLbtAVJCH3mtQNd49PL9wM17OpGudlAgk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954541; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Kto/w2AEorrBM5dZgT70XuVChojeFObxlu6B65tX8r8=; b=dFtWEVf6v0h5Y4o5wBV+JD+gY1jycp1brOfD2gdMLxWpe+nSMNoKOFwEAZilG9FJ9Yce0pHUE4vU5BTCLmeCXL61772e8SrmY7SGUgnVHxTFlm8e2Q/XzZ1w5rA/GpcuukOExHgsEmmTmGOEEjjfiRR6Lo6L1X99mqfu2mu7F4U= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954541683375.614149580614; Sat, 7 Mar 2026 23:22:21 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8SH-0003IL-Mv; Sun, 08 Mar 2026 03:21:39 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8RS-0002BN-Of for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:20:49 -0400 Received: from mail-dy1-x1341.google.com ([2607:f8b0:4864:20::1341]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8RQ-0002y0-N0 for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:20:46 -0400 Received: by mail-dy1-x1341.google.com with SMTP id 5a478bee46e88-2be4781d2baso4108246eec.0 for ; Sat, 07 Mar 2026 23:20:44 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.20.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:20:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954443; x=1773559243; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Kto/w2AEorrBM5dZgT70XuVChojeFObxlu6B65tX8r8=; b=LpKI2gej/9StYGbq++OIGLAxumf0k5YmqznI5zdoBWcl7GIJWHNzNg0zgbKRDQWNyC lgrhypS0aRKzuJmMQEkz6urPknOP5FjSyTiFTpbJyVAJWLEzlHSTMXVjgkYnaypWKZWq 7GhLgSy+kmDH32vO0Q2M7hjmx+bA8Da0+z6XxLaoQwe+vmsUeJ+s3WufTLqJrjC4hx5q Eqq4+NohirxjWfMtRcro0eBhcdtM/bn/RHX4rqJX2Ok8WOBDxS+F4npsC8thOvao9N35 7efrf3uSv6zRMZKBmnwa+Vnam8jv0dde2Cdf0nwn3cgeQ+0DtTe+EjETprH2EIPE8d2I htBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954443; x=1773559243; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Kto/w2AEorrBM5dZgT70XuVChojeFObxlu6B65tX8r8=; b=v6/Qm2NK2zcRPd6RQppkRyyyTIaTadO6AaitJtXZTPPSIONbzLEn7cQIti2m82kpFZ MmFp1BkusdCcAXCZr96fHjv/7/53RquYmD0ZgrLHhFX1Y46CdwyW4EgiXukVLy20NO7h ZnX8a68rSuOxalDo2IaV+e9nCPjtoOeuslPiKpU/tc8/oJTXbYMOdOTwZJwuNOfAdC72 NjqbyKV6CgPuOl5qEOpFRnw6/547KuPdP6e8fkS3WvjI6/wmXXYgxgANGj16L7Ey2n9I OiBcR2whIHvJMrdf0w4UKHmfONkuC9q46nR9NjLBdM4COPF/29xHLfjxl5TDdoCUH4YC KpDw== X-Forwarded-Encrypted: i=1; AJvYcCWwbpdYlEOjD14YQXvWBJ9DIpDG937JP7vdWZ9Lcvc/xNaIExe+G2daQSDKQ7VMs/hXDhg76Q0s85LM@nongnu.org X-Gm-Message-State: AOJu0YwXSGqe8l64+fL0pYcaITuY2cVWnp6Ug4xZZEK+YGHGVwII30wJ yDVy0awVf4YnqOTaUWK6T54DR++L2a30Q/h7V2Y29kwCTVfqzrKD0Dwv X-Gm-Gg: ATEYQzxDHvhnP2FvYn4JxjxKlyYKVhlef8OSa/ojfsu2GlA+y+TWPmt+GhW4pWvILkZ lTK75vVvd/Tm4IoK8arQiba4hk1OBsqyG7U1ASqwh4LSKu1PADXoyPblcFNO7xHCGTmh7+xd34M CXcwjMe8lHieVtEQoamzY0MQrjBCT73+2YzUZcSjvk7H4sif6C1QjdXXBSKBHpBDqxurdYx9kPN ezDHFlgCl6YVIBCTC8kVZ5NMM5Nk3upsRs8wrIos4sNAHGdWvZ7Y8E0a4NaG9sBbpYdlzPiTZP+ yHWCEGDGwwcjdd0Ky0PIN6nmrxlfPo4S9pm8X1+TH3V2vRf83Vi6rMaPgam7yWw2zmduFUIg8D4 yRH92DEMpm+cqdBE6P/ehWDxA9jJymp9sqQlRUUDs7BFU+R2EHvEuG1tz+93KBjBIZgUh1n84iQ 1O7w8JwNBjhtCjqEQa3S5SyzxuK86whKURd2EBQ7D3pMj/Kidvn7SlG42ICvK+cfsU8tVHUvJYO 0fPwx/mYDXsDLtnXjr4TOglPlI= X-Received: by 2002:a05:7300:2393:b0:2b8:66f3:2502 with SMTP id 5a478bee46e88-2be4deb8aaamr3515941eec.1.1772954443092; Sat, 07 Mar 2026 23:20:43 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 22/28] hw/riscv/dm: add system bus access Date: Sun, 8 Mar 2026 15:17:25 +0800 Message-ID: <37a88487caad84ae50b47cc190820ebfac5ecb3e.1772936778.git.chao.liu.zevorn@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1341; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1341.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954542813154100 Content-Type: text/plain; charset="utf-8" Implement the optional System Bus Access (SBA) register set that allows the debugger to read and write system memory without involving a hart. This adds SBCS, SBADDRESS0-3, and SBDATA0-3 register handlers with sticky error reporting, sbreadonaddr, sbreadondata, and sbautoincrement support. The SBA path supports 8/16/32/64-bit access widths and sets the SBA capability bits during DM reset based on the configured sba-addr-width property. Signed-off-by: Chao Liu --- hw/riscv/dm.c | 249 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 242 insertions(+), 7 deletions(-) diff --git a/hw/riscv/dm.c b/hw/riscv/dm.c index 818e48629f..bcaaffd02b 100644 --- a/hw/riscv/dm.c +++ b/hw/riscv/dm.c @@ -19,6 +19,7 @@ #include "exec/cpu-common.h" #include "migration/vmstate.h" #include "exec/translation-block.h" +#include "system/address-spaces.h" #include "system/tcg.h" #include "target/riscv/cpu.h" #include "trace.h" @@ -736,6 +737,95 @@ static bool dm_execute_abstract_cmd(RISCVDMState *s, u= int32_t command) } =20 =20 +static int dm_sba_access_bytes(uint32_t sbaccess) +{ + if (sbaccess <=3D 4) { + return 1 << sbaccess; + } + return 0; +} + +static bool dm_sba_access_supported(RISCVDMState *s, uint32_t sbaccess) +{ + switch (sbaccess) { + case 0: return ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS8); + case 1: return ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS16); + case 2: return ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS32); + case 3: return ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS64); + case 4: return ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS128); + default: return false; + } +} + +static void dm_sba_execute(RISCVDMState *s, bool is_write) +{ + uint32_t sbaccess =3D ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS); + int access_bytes =3D dm_sba_access_bytes(sbaccess); + uint8_t buf[16] =3D { 0 }; + MemTxResult result; + + if (ARRAY_FIELD_EX32(s->regs, SBCS, SBBUSYERROR) || + ARRAY_FIELD_EX32(s->regs, SBCS, SBERROR)) { + return; + } + + if (!access_bytes || !dm_sba_access_supported(s, sbaccess)) { + ARRAY_FIELD_DP32(s->regs, SBCS, SBERROR, 4); /* other error */ + return; + } + + if (s->regs[R_SBADDRESS2] || s->regs[R_SBADDRESS3]) { + ARRAY_FIELD_DP32(s->regs, SBCS, SBERROR, 2); + return; + } + + hwaddr lo =3D s->regs[R_SBADDRESS0]; + hwaddr hi =3D s->regs[R_SBADDRESS1]; + hwaddr addr =3D (hi << 32) | lo; + + if (addr & (access_bytes - 1)) { + ARRAY_FIELD_DP32(s->regs, SBCS, SBERROR, 3); /* alignment */ + return; + } + + ARRAY_FIELD_DP32(s->regs, SBCS, SBBUSY, 1); + for (int i =3D 0; i < 4; i++) { + stl_le_p(buf + i * 4, s->regs[R_SBDATA0 + i]); + } + + if (is_write) { + result =3D address_space_rw(&address_space_memory, addr, + MEMTXATTRS_UNSPECIFIED, buf, + access_bytes, true); + } else { + result =3D address_space_rw(&address_space_memory, addr, + MEMTXATTRS_UNSPECIFIED, buf, + access_bytes, false); + if (result =3D=3D MEMTX_OK) { + for (int i =3D 0; i < 4; i++) { + s->regs[R_SBDATA0 + i] =3D ldl_le_p(buf + i * 4); + } + } + } + + if (result !=3D MEMTX_OK) { + ARRAY_FIELD_DP32(s->regs, SBCS, SBERROR, + result =3D=3D MEMTX_DECODE_ERROR ? 2 : 7); + ARRAY_FIELD_DP32(s->regs, SBCS, SBBUSY, 0); + return; + } + + trace_riscv_dm_sba_access(addr, s->regs[R_SBDATA0], access_bytes, is_w= rite); + + if (ARRAY_FIELD_EX32(s->regs, SBCS, SBAUTOINCREMENT)) { + addr +=3D access_bytes; + s->regs[R_SBADDRESS0] =3D (uint32_t)addr; + s->regs[R_SBADDRESS1] =3D addr >> 32; + } + + ARRAY_FIELD_DP32(s->regs, SBCS, SBBUSY, 0); +} + =20 static void dm_status_refresh(RISCVDMState *s) { @@ -1108,6 +1198,129 @@ static uint64_t dm_progbuf_post_read(RegisterInfo *= reg, uint64_t val) return val; } =20 +static uint64_t dm_sbcs_pre_write(RegisterInfo *reg, uint64_t val64) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + uint32_t val =3D (uint32_t)val64; + + if (ARRAY_FIELD_EX32(s->regs, SBCS, SBBUSY)) { + qemu_log_mask(LOG_GUEST_ERROR, + "riscv-dm: write to sbcs while busy\n"); + return s->regs[R_SBCS]; + } + + uint32_t cur =3D s->regs[R_SBCS]; + + /* W1C: sberror and sbbusyerror */ + uint32_t sberror_clr =3D FIELD_EX32(val, SBCS, SBERROR); + uint32_t sberror_cur =3D FIELD_EX32(cur, SBCS, SBERROR); + cur =3D FIELD_DP32(cur, SBCS, SBERROR, sberror_cur & ~sberror_clr); + + uint32_t busyerr_clr =3D FIELD_EX32(val, SBCS, SBBUSYERROR); + uint32_t busyerr_cur =3D FIELD_EX32(cur, SBCS, SBBUSYERROR); + cur =3D FIELD_DP32(cur, SBCS, SBBUSYERROR, busyerr_cur & ~busyerr_clr); + + /* Writable fields */ + cur =3D FIELD_DP32(cur, SBCS, SBREADONADDR, + FIELD_EX32(val, SBCS, SBREADONADDR)); + cur =3D FIELD_DP32(cur, SBCS, SBACCESS, + FIELD_EX32(val, SBCS, SBACCESS)); + cur =3D FIELD_DP32(cur, SBCS, SBAUTOINCREMENT, + FIELD_EX32(val, SBCS, SBAUTOINCREMENT)); + cur =3D FIELD_DP32(cur, SBCS, SBREADONDATA, + FIELD_EX32(val, SBCS, SBREADONDATA)); + + return cur; +} + +static void dm_sbaddress0_post_write(RegisterInfo *reg, uint64_t val64) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + + if (ARRAY_FIELD_EX32(s->regs, SBCS, SBBUSY)) { + ARRAY_FIELD_DP32(s->regs, SBCS, SBBUSYERROR, 1); + return; + } + + if (ARRAY_FIELD_EX32(s->regs, SBCS, SBREADONADDR) && + !ARRAY_FIELD_EX32(s->regs, SBCS, SBERROR) && + !ARRAY_FIELD_EX32(s->regs, SBCS, SBBUSYERROR)) { + dm_sba_execute(s, false); + } +} + +static uint64_t dm_sbaddress1_pre_write(RegisterInfo *reg, uint64_t val64) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + + if (ARRAY_FIELD_EX32(s->regs, SBCS, SBBUSY)) { + ARRAY_FIELD_DP32(s->regs, SBCS, SBBUSYERROR, 1); + return s->regs[R_SBADDRESS1]; + } + return (uint32_t)val64; +} + +static void dm_sbdata0_post_write(RegisterInfo *reg, uint64_t val64) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + + if (ARRAY_FIELD_EX32(s->regs, SBCS, SBBUSY)) { + ARRAY_FIELD_DP32(s->regs, SBCS, SBBUSYERROR, 1); + return; + } + if (ARRAY_FIELD_EX32(s->regs, SBCS, SBBUSYERROR) || + ARRAY_FIELD_EX32(s->regs, SBCS, SBERROR)) { + return; + } + + dm_sba_execute(s, true); +} + +static uint64_t dm_sbdata0_post_read(RegisterInfo *reg, uint64_t val) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + + if (ARRAY_FIELD_EX32(s->regs, SBCS, SBBUSY)) { + ARRAY_FIELD_DP32(s->regs, SBCS, SBBUSYERROR, 1); + return val; + } + if (ARRAY_FIELD_EX32(s->regs, SBCS, SBBUSYERROR) || + ARRAY_FIELD_EX32(s->regs, SBCS, SBERROR)) { + return val; + } + + if (ARRAY_FIELD_EX32(s->regs, SBCS, SBREADONDATA)) { + dm_sba_execute(s, false); + return val; + } + return val; +} + +static uint64_t dm_sbdata1_pre_write(RegisterInfo *reg, uint64_t val64) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + + if (ARRAY_FIELD_EX32(s->regs, SBCS, SBBUSY)) { + ARRAY_FIELD_DP32(s->regs, SBCS, SBBUSYERROR, 1); + return s->regs[R_SBDATA1]; + } + if (ARRAY_FIELD_EX32(s->regs, SBCS, SBBUSYERROR) || + ARRAY_FIELD_EX32(s->regs, SBCS, SBERROR)) { + return s->regs[R_SBDATA1]; + } + return (uint32_t)val64; +} + +static uint64_t dm_sbdata_hi_post_read(RegisterInfo *reg, uint64_t val) +{ + RISCVDMState *s =3D RISCV_DM(reg->opaque); + + if (ARRAY_FIELD_EX32(s->regs, SBCS, SBBUSY)) { + ARRAY_FIELD_DP32(s->regs, SBCS, SBBUSYERROR, 1); + } + return val; +} + static uint64_t dm_haltsum0_post_read(RegisterInfo *reg, uint64_t val) { RISCVDMState *s =3D RISCV_DM(reg->opaque); @@ -1287,20 +1500,31 @@ static RegisterAccessInfo riscv_dm_regs_info[] =3D { .ro =3D R_SBCS_SBACCESS8_MASK | R_SBCS_SBACCESS16_MASK | R_SBCS_SBACCESS32_MASK | R_SBCS_SBACCESS64_MASK | R_SBCS_SBACCESS128_MASK | R_SBCS_SBASIZE_MASK | - R_SBCS_SBBUSY_MASK | R_SBCS_SBVERSION_MASK, }, + R_SBCS_SBBUSY_MASK | R_SBCS_SBVERSION_MASK, + .pre_write =3D dm_sbcs_pre_write, }, =20 - { .name =3D "SBADDRESS0", .addr =3D A_SBADDRESS0, }, + { .name =3D "SBADDRESS0", .addr =3D A_SBADDRESS0, + .post_write =3D dm_sbaddress0_post_write, }, =20 - { .name =3D "SBADDRESS1", .addr =3D A_SBADDRESS1, }, + { .name =3D "SBADDRESS1", .addr =3D A_SBADDRESS1, + .pre_write =3D dm_sbaddress1_pre_write, }, =20 { .name =3D "SBADDRESS2", .addr =3D A_SBADDRESS2, }, =20 - { .name =3D "SBDATA0", .addr =3D A_SBDATA0, }, + { .name =3D "SBDATA0", .addr =3D A_SBDATA0, + .post_write =3D dm_sbdata0_post_write, + .post_read =3D dm_sbdata0_post_read, }, =20 - { .name =3D "SBDATA1", .addr =3D A_SBDATA1, }, + { .name =3D "SBDATA1", .addr =3D A_SBDATA1, + .pre_write =3D dm_sbdata1_pre_write, + .post_read =3D dm_sbdata_hi_post_read, }, =20 - { .name =3D "SBDATA2", .addr =3D A_SBDATA2, }, - { .name =3D "SBDATA3", .addr =3D A_SBDATA3, }, + { .name =3D "SBDATA2", .addr =3D A_SBDATA2, + .pre_write =3D dm_sbdata1_pre_write, + .post_read =3D dm_sbdata_hi_post_read, }, + { .name =3D "SBDATA3", .addr =3D A_SBDATA3, + .pre_write =3D dm_sbdata1_pre_write, + .post_read =3D dm_sbdata_hi_post_read, }, =20 { .name =3D "HALTSUM0", .addr =3D A_HALTSUM0, .ro =3D 0xFFFFFFFF, @@ -1602,6 +1826,17 @@ static void dm_debug_reset(RISCVDMState *s) ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, DATACOUNT, s->num_abstract_data); ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, PROGBUFSIZE, s->progbuf_size); =20 + /* SBA capabilities */ + if (s->sba_addr_width > 0) { + ARRAY_FIELD_DP32(s->regs, SBCS, SBACCESS8, 1); + ARRAY_FIELD_DP32(s->regs, SBCS, SBACCESS16, 1); + ARRAY_FIELD_DP32(s->regs, SBCS, SBACCESS32, 1); + ARRAY_FIELD_DP32(s->regs, SBCS, SBACCESS64, 1); + ARRAY_FIELD_DP32(s->regs, SBCS, SBASIZE, s->sba_addr_width); + ARRAY_FIELD_DP32(s->regs, SBCS, SBACCESS, 2); /* default 32-bit */ + ARRAY_FIELD_DP32(s->regs, SBCS, SBVERSION, 1); + } + /* Reset per-hart state */ if (s->hart_resumeack && s->num_harts > 0) { for (uint32_t i =3D 0; i < s->num_harts; i++) { --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954543; cv=none; d=zohomail.com; s=zohoarc; b=Ihz2+gg4tmDqkJoDLAyoaAS8QW9kJuiZ86Kt4Z9+Yg5c6n3die0lGZCJr23q7DCY9VnWjkB3F9LlZekGdaNoWq1dyBCb1UCvukfVE2pnVMnD27EvSLnOcZZCbZ78o9uL44U50yuaqMJnFRXaQfhkTYUQ6BRbzh2lonvCO8DF5X8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954543; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=WzztSLe6IJjCsyASv5LBpq00D3Si30OBdTuZqVzuOjU=; b=GYbkth8VL2FnZ08DL5hSo0ZeHZ1Y2xjR+0OYGhdYsEFTmK2oNepGXW7gIpXVbVCyC5qXaGyIPxFUehSjRvgboMuuCJIXg7rKHdkNtzfoFV2BV48B3Z4bkihdGOtVDuHgSr3Jk4k38PCR18qGCWMnEiKUtK/cSi3SonokM+fGU/w= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 177295454329310.369607919430678; Sat, 7 Mar 2026 23:22:23 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8SP-0003O7-Nf; Sun, 08 Mar 2026 03:21:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8RZ-0002KP-W1 for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:20:56 -0400 Received: from mail-dy1-x1341.google.com ([2607:f8b0:4864:20::1341]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8RW-00033S-LS for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:20:52 -0400 Received: by mail-dy1-x1341.google.com with SMTP id 5a478bee46e88-2bdd40d3c61so9004119eec.1 for ; Sat, 07 Mar 2026 23:20:50 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.20.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:20:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954449; x=1773559249; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=WzztSLe6IJjCsyASv5LBpq00D3Si30OBdTuZqVzuOjU=; b=P3/nBtw5fTPH8cUv+Fg15JJGYbR79kgRDtPxzEe0i5ZFAseemWWFAByKHgxgBKBwlr ch/JXVn+RrFs8I+uPHTbHquJa4Zq1FiKV05SI+MA5juX5tpSmKlE/PYZnE2vG/dweawR R8B9IxCPR1dDKlKv4DGVVhZ4QwfEEGo7vMrUjKvTZC754JBpojGDcUo3VPgagmwZhUeL CI5T/VpIqtc9VQ9S4repVrvBEsLB2+11FRD6soJnM/8F/4WGm0rBKBVJ95u0jSMJNIwj 9IjVW4Lk5Ocas2ruwf/mquohlJJFGHNzV7MY+cQjrJrMTdXJWQDbqxeb63Lrd80m2fN4 dgYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954449; x=1773559249; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=WzztSLe6IJjCsyASv5LBpq00D3Si30OBdTuZqVzuOjU=; b=VNQfgfsY1NLdtru0+WmSI/iCuSY4VDZwWJZ1wM+IG7AYB0efUdy700RN9cJGkGQrhD wp5DLvJS6bKzvNGJh+mGal9gh+hKS46l3uneW0fVZcmUB3/RlqlVR8XRnTx0Hoc1mMZH 5OwWev6JFw5znz5JsiZ+AjoEZ6zogyedaagtClmupKdRKbeFnnu3N+e7QHa7k1gA+kjz ob2gbLBlQI/Q/X72+GkGm2kQgQmg4OsJ2x+GJVwYlDuk2Jn5DzLKU3WPOTo/tp+42AVO iuAh3JVYd0hhm3+rpory0fdGOfOfqsKl8av6dCgoFisFzH1HoWpAA/85St/xInktLMKQ VlNA== X-Forwarded-Encrypted: i=1; AJvYcCXSd2ELl5/n/NTYLiC4IpNfMKNexUOJebz1/NEn6gxR56TzrIkAhqg04k+kUKxnqkEjbArHuig4OTV6@nongnu.org X-Gm-Message-State: AOJu0YwIOX9sKiBRro09rDxvEWyL1dhfAXa5+5Wqw0BNapKtqIR1ceT3 bJQj13hsSUEKI6lEXD48gVgCNgcdRrdDb2Tnlk8U+sGjyMInYXyxuSPe X-Gm-Gg: ATEYQzwOQ9ic5/73T/HrIMgIaYseYUP8mIe67m3eClZVPsJeGYoZrLOkHGBHJ0bjyxC eEB4Pvg3LieVFV9QKfiZyvC6RmpoXDfq0EgS2yAVZGg/fpxLknf3Z2yD1WSgqQM00+sG8kzKotm ISYlPZw2ePshkraKAbXk9J7XOcXIH4EYWPs8Q9OX/K+1m7l6UJVHDRsaS4I9hzhy2lgaLycRgW6 r2hhiJaoqh7YtowEi65ZDftxj3ueqTOd8S4W/C7uT+FjcGjawHetOCk7DaD5GlQSj6JbhuNPRYS kp9ZjsteNh/GEouV4H0pXjv2EahVM+jmwUzBsNMK39OOFY6qn9E8zWIYQV5boBFPI2H09hMTWLW gBV1amKVkURraMOvHaTG+Vc7HOH1Qvg7M3ZQD8aJrUX8KYXab1CZ6Vq3hdog6+EX9kwlW+oINbS JJ97T7EZjZKfS8l0pf3bTtUixqQD3jEP5192haSGj5ScNUuzU9zXfCDWW8iu3rx/fidn5+n9R9a vsgCvlZAHljMcxO23yquYDLkCQ= X-Received: by 2002:a05:7301:1e89:b0:2b7:32fe:4bbb with SMTP id 5a478bee46e88-2be4deaed60mr2676045eec.11.1772954449182; Sat, 07 Mar 2026 23:20:49 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 23/28] hw/riscv/virt: integrate the Debug Module Date: Sun, 8 Mar 2026 15:17:26 +0800 Message-ID: <9d4f695c95229e5b28247c477f2278294f5b2cbb.1772936778.git.chao.liu.zevorn@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1341; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1341.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954544767154100 Content-Type: text/plain; charset="utf-8" Expand the VIRT_DEBUG memory map entry from 0x100 to RISCV_DM_SIZE (0x1000 =3D 4 KiB) to accommodate the full Debug Module address space: DMI registers, work area, and ROM entry vector. Create the Debug Module device via riscv_dm_create() and wire each hart's halt-request GPIO to it. Set dm_halt_addr so the CPU enters the DM ROM entry point on debug-mode entry. Signed-off-by: Chao Liu --- hw/riscv/virt.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index bbce2fb667..0a7e29a743 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -58,6 +58,7 @@ #include "qapi/qapi-visit-common.h" #include "hw/virtio/virtio-iommu.h" #include "hw/uefi/var-service-api.h" +#include "hw/riscv/dm.h" =20 /* KVM AIA only supports APLIC MSI. APLIC Wired is always emulated by QEMU= . */ static bool virt_use_kvm_aia_aplic_imsic(RISCVVirtAIAType aia_type) @@ -80,7 +81,7 @@ static bool virt_aclint_allowed(void) } =20 static const MemMapEntry virt_memmap[] =3D { - [VIRT_DEBUG] =3D { 0x0, 0x100 }, + [VIRT_DEBUG] =3D { 0x0, RISCV_DM_SIZE }, [VIRT_MROM] =3D { 0x1000, 0xf000 }, [VIRT_TEST] =3D { 0x100000, 0x1000 }, [VIRT_RTC] =3D { 0x101000, 0x1000 }, @@ -1702,6 +1703,24 @@ static void virt_machine_init(MachineState *machine) =20 create_platform_bus(s, mmio_irqchip); =20 + /* Create Debug Module and connect each hart's halt-request IRQ */ + int total_harts =3D machine->smp.cpus; + DeviceState *dm =3D riscv_dm_create(system_memory, + s->memmap[VIRT_DEBUG].base, + total_harts); + + for (int h =3D 0; h < total_harts; h++) { + CPUState *cs =3D qemu_get_cpu(h); + RISCVCPU *rcpu =3D RISCV_CPU(cs); + + qdev_connect_gpio_out(dm, h, + qdev_get_gpio_in_named(DEVICE(cs), + "dm-halt-req", 0)); + rcpu->env.dm_rom_present =3D true; + rcpu->env.dm_halt_addr =3D s->memmap[VIRT_DEBUG].base + + RISCV_DM_ROM_ENTRY; + } + serial_mm_init(system_memory, s->memmap[VIRT_UART0].base, 0, qdev_get_gpio_in(mmio_irqchip, UART0_IRQ), 399193, serial_hd(0), DEVICE_LITTLE_ENDIAN); --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954587; cv=none; d=zohomail.com; s=zohoarc; b=AwJCCmbVSXxHhFgUC28krjYIFZF/v4PSANPr4gbGKwZ506MvdI61rehIV17V8bZRtngyK82U3qKIpRrwIwyQ5hRhrrNp5VkOCRDg677agPM1JivLuGE9b2HXZ5cVAGfUGpdPVzRcvXGaoGdEqgo/eIK728/gGCIya6k5Do1sso8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954587; h=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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=rkoDc6MBlz/jZoZq6BE9pNkHGRnj/JKNI2l3ZUwxxf8=; b=EM+sgOtDmHk2/pjpIocBZJhNhfJ+mFaIaABpHv5pFasFuU8aWO1yx9OVGFidH/HwjdGBcl9uc2ZH8F8YhzR6KTmo5kwSApxTSRns02M/i2Y3CU1E7hDuy0kvwL4XAY5OBN+xEGizh0JKTd22eVizKAOx57OYVHuKcXG4rPGNWWU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954587085203.5389956696273; Sat, 7 Mar 2026 23:23:07 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8T1-00059I-Cu; Sun, 08 Mar 2026 03:22:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8Re-0002Pa-B9 for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:21:00 -0400 Received: from mail-dy1-x1341.google.com ([2607:f8b0:4864:20::1341]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8Rc-00037Q-4O for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:20:57 -0400 Received: by mail-dy1-x1341.google.com with SMTP id 5a478bee46e88-2b4520f6b32so12156485eec.0 for ; Sat, 07 Mar 2026 23:20:55 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.20.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:20:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954455; x=1773559255; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=rkoDc6MBlz/jZoZq6BE9pNkHGRnj/JKNI2l3ZUwxxf8=; b=OgiLiqtk9O+r5cDC709PfVwlmecZR6Iyb+dXaj7em+ep+FEYgQmTzRbgI2++32AuGC KdStFiarHJNpwXYBVjFb66ljKnDrO56CZ3lN8+VziF3LtPSFFY4yIin+TLJG/gjzJOHR +ZuI+WdvBTb29vcwDytuFnq8olbC4VbMKsDMxHhp8OecIqMw5n4i/VFBKB5bs9lFKFP0 KHU4ob+S9Vx0iARNsoehiMBL7skgHWH2skRMu4h3N7V8NwAAznDiVv8n3ZEEA3YcXvzE Ii7QAvTDJMZFNQj21kOz+iYPbufYuDYXWeSl3l4OCZ6Kz8AWVykueoQ6byK5qPlIF9sl Atog== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954455; x=1773559255; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=rkoDc6MBlz/jZoZq6BE9pNkHGRnj/JKNI2l3ZUwxxf8=; b=sYe5VphNmfUhN3UG5HGcshy4lKuhgZQJ24rl/5VeuURk42caiMj2llZGlrYd/3hIqA w3njsEuuvxz6eCWpfIt/Z1o1wsNaIN24aXX6TLYYsPIJWDowmMGV6Bkx0Pk0CldKhHJ5 sLWaYVa0LDIkiTuMd0TaYAmifLCGrziCrnDyFxzd9/7eL8z4f+zo2gz8mjc/QuZywiH5 0aA2Mxppp877biwqjvvaNU7An84I/UHkD3WzEJfVftYExikyAQrJN6jdnKWGR2aFVAeD xwvPevGyU6igI110mInNNbU4ccKoKM4jauHeWHMrvuRSLMddKVO+kU+nFNFbZe+UAIxJ tCsA== X-Forwarded-Encrypted: i=1; AJvYcCWT/5j2IgyxzHc9I6htDlnXE7L0rd+UuCBM3RZKHr1xoRRMgBiE5Tf1lydge4S9Q29rMIS6BiNG1OOy@nongnu.org X-Gm-Message-State: AOJu0Yy0EFgvpn2844L1h69CoeNKRAJHzYO5oecBIefy/BhaDKeiBx32 KS/D7qnr4SGdXLOubTm2pBKOXPhcisifVnolvqZuzdmSZlCXzHJVMHqv X-Gm-Gg: ATEYQzxpcpgNc25lTMBy45Z4xwl101GcapuuwW+YXnWp1003jhl+NBIV2wzUh1dbC9Z cHD0+sbMo526H7unxqDSHDvydKoQ/038Zrc4nSGgG8qCrWKckdLeYbQZbp8bgWoqrzfjKBjdK9O WSyISNnQHGhsLkI7iLbOH0RQdAqk0YX5uNwxvaxYalEjT6zYO6WEsEs18vG1yYvUGrj9cQO1HjE iaVZD7uJkSI/QD7ku3F5ej3OQ4ayP99PTYGTRk3gd+qBLmaqfKA4DQtCIDmFvrADO7cFRXHsgXx XpPkLeUcqTEv4ta/PjopRNx5Zh1kwOj+z33fWl35OeYIBIoCvLpksgD1lrfowCmzqd7JAfE6Jfz HVt+cXxRVWlBcApd34W/G0JZFPCLu5dp2vHzPGpfuSGwLNxN756kHA8HkfEaiHNxxLwqW7E2zja qU/fYr15FbDa1TsdoJTKxWwyGpWvIsJMZL0C9n6iNnuY8vxg7aFEjD/N2QBIZZYslwWp0Y7xMfD ORyn2fN07k9HyhV7ldSAAzOMMI= X-Received: by 2002:a05:7300:a10b:b0:2be:22b0:8bf3 with SMTP id 5a478bee46e88-2be4e063a50mr2384586eec.30.1772954454640; Sat, 07 Mar 2026 23:20:54 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 24/28] tests/qtest: add initial RISC-V Debug Module tests Date: Sun, 8 Mar 2026 15:17:27 +0800 Message-ID: <18d94d4d321cd011e7d61fffdff3218ad5a23cc7.1772936778.git.chao.liu.zevorn@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1341; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1341.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954587578158500 Content-Type: text/plain; charset="utf-8" Add the first qtest coverage for the virt Debug Module model. The new riscv-dm-test binary checks dmactive gating, dmstatus, hartinfo, and abstractcs reset values, then drives a basic halt/resume cycle by writing the ROM mailbox words used by the CPU park loop. Register the test for both riscv32 and riscv64 when CONFIG_RISCV_DM is enabled. Signed-off-by: Chao Liu --- MAINTAINERS | 1 + tests/qtest/meson.build | 7 +- tests/qtest/riscv-dm-test.c | 208 ++++++++++++++++++++++++++++++++++++ 3 files changed, 214 insertions(+), 2 deletions(-) create mode 100644 tests/qtest/riscv-dm-test.c diff --git a/MAINTAINERS b/MAINTAINERS index d8f326c8b2..faaa7114ec 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -361,6 +361,7 @@ F: tests/functional/riscv32 F: tests/functional/riscv64 F: tests/tcg/riscv64/ F: tests/qtest/iommu-riscv-test.c +F: tests/qtest/riscv-dm-test.c =20 RISC-V XThead* extensions M: Christoph Muellner diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index ba9f59d2f8..3bb9e3cc16 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -282,13 +282,16 @@ qtests_s390x =3D \ 'migration-test'] =20 qtests_riscv32 =3D \ - (config_all_devices.has_key('CONFIG_SIFIVE_E_AON') ? ['sifive-e-aon-watc= hdog-test'] : []) + (config_all_devices.has_key('CONFIG_SIFIVE_E_AON') ? ['sifive-e-aon-watc= hdog-test'] : []) + \ + (config_all_devices.has_key('CONFIG_RISCV_DM') ? ['riscv-dm-test'] : []) =20 qtests_riscv64 =3D ['riscv-csr-test'] + \ (unpack_edk2_blobs ? ['bios-tables-test'] : []) + \ (config_all_devices.has_key('CONFIG_IOMMU_TESTDEV') and config_all_devices.has_key('CONFIG_RISCV_IOMMU') ? - ['iommu-riscv-test'] : []) + ['iommu-riscv-test'] : []) + \ + (config_all_devices.has_key('CONFIG_RISCV_DM') ? + ['riscv-dm-test'] : []) =20 qos_test_ss =3D ss.source_set() qos_test_ss.add( diff --git a/tests/qtest/riscv-dm-test.c b/tests/qtest/riscv-dm-test.c new file mode 100644 index 0000000000..c9e3c22a20 --- /dev/null +++ b/tests/qtest/riscv-dm-test.c @@ -0,0 +1,208 @@ +/* + * QTest for RISC-V Debug Module v1.0 + * + * Copyright (c) 2025 Chao Liu + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "libqtest.h" + +#define DM_BASE 0x0 + +#define ROM_HARTID 0x104 +#define ROM_RESUME 0x10c + +#define A_DATA0 0x10 +#define A_DMCONTROL 0x40 +#define A_DMSTATUS 0x44 +#define A_HARTINFO 0x48 +#define A_ABSTRACTCS 0x58 + +#define DMCONTROL_DMACTIVE (1u << 0) +#define DMCONTROL_HALTREQ (1u << 31) +#define DMCONTROL_RESUMEREQ (1u << 30) + +#define DMSTATUS_VERSION_MASK 0xf +#define DMSTATUS_AUTHENTICATED (1u << 7) +#define DMSTATUS_ANYHALTED (1u << 8) +#define DMSTATUS_ALLHALTED (1u << 9) +#define DMSTATUS_ANYRUNNING (1u << 10) +#define DMSTATUS_ALLRUNNING (1u << 11) +#define DMSTATUS_ANYRESUMEACK (1u << 16) +#define DMSTATUS_ALLRESUMEACK (1u << 17) +#define DMSTATUS_ANYHAVERESET (1u << 18) +#define DMSTATUS_IMPEBREAK (1u << 22) + +#define HARTINFO_DATAADDR_MASK 0xfffu +#define HARTINFO_DATASIZE_SHIFT 12 +#define HARTINFO_DATASIZE_MASK (0xfu << HARTINFO_DATASIZE_SHIFT) +#define HARTINFO_DATAACCESS (1u << 16) +#define HARTINFO_NSCRATCH_SHIFT 20 +#define HARTINFO_NSCRATCH_MASK (0xfu << HARTINFO_NSCRATCH_SHIFT) + +#define ABSTRACTCS_DATACOUNT_MASK 0xf +#define ABSTRACTCS_BUSY (1u << 12) +#define ABSTRACTCS_PROGBUFSIZE_SHIFT 24 +#define ABSTRACTCS_PROGBUFSIZE_MASK (0x1fu << ABSTRACTCS_PROGBUFSIZE_S= HIFT) + +static uint32_t dm_read(QTestState *qts, uint32_t reg) +{ + return qtest_readl(qts, DM_BASE + reg); +} + +static void dm_write(QTestState *qts, uint32_t reg, uint32_t val) +{ + qtest_writel(qts, DM_BASE + reg, val); +} + +static void dm_set_active(QTestState *qts) +{ + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE); +} + +static void rom_write32(QTestState *qts, uint32_t offset, uint32_t val) +{ + qtest_writel(qts, DM_BASE + offset, val); +} + +static void sim_cpu_halt_ack(QTestState *qts, uint32_t hartid) +{ + rom_write32(qts, ROM_HARTID, hartid); +} + +static void sim_cpu_resume_ack(QTestState *qts, uint32_t hartid) +{ + rom_write32(qts, ROM_RESUME, hartid); +} + +static void test_dmactive_gate(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + + g_assert_cmpuint(dm_read(qts, A_DMCONTROL), =3D=3D, 0); + g_assert_cmpuint(dm_read(qts, A_DMSTATUS), =3D=3D, 0); + g_assert_cmpuint(dm_read(qts, A_HARTINFO), =3D=3D, 0); + g_assert_cmpuint(dm_read(qts, A_ABSTRACTCS), =3D=3D, 0); + g_assert_cmpuint(dm_read(qts, A_DATA0), =3D=3D, 0); + + dm_write(qts, A_DATA0, 0xdeadbeef); + g_assert_cmpuint(dm_read(qts, A_DATA0), =3D=3D, 0); + + dm_set_active(qts); + g_assert_cmpuint(dm_read(qts, A_DMCONTROL) & DMCONTROL_DMACTIVE, =3D= =3D, + DMCONTROL_DMACTIVE); + g_assert_cmpuint(dm_read(qts, A_DMSTATUS), !=3D, 0); + + qtest_quit(qts); +} + +static void test_dmstatus(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + uint32_t status; + + dm_set_active(qts); + status =3D dm_read(qts, A_DMSTATUS); + + g_assert_cmpuint(status & DMSTATUS_VERSION_MASK, =3D=3D, 3); + g_assert_cmpuint(status & DMSTATUS_AUTHENTICATED, =3D=3D, + DMSTATUS_AUTHENTICATED); + g_assert_cmpuint(status & DMSTATUS_ANYRUNNING, =3D=3D, + DMSTATUS_ANYRUNNING); + g_assert_cmpuint(status & DMSTATUS_ALLRUNNING, =3D=3D, + DMSTATUS_ALLRUNNING); + g_assert_cmpuint(status & DMSTATUS_ANYHALTED, =3D=3D, 0); + g_assert_cmpuint(status & DMSTATUS_ANYHAVERESET, =3D=3D, + DMSTATUS_ANYHAVERESET); + g_assert_cmpuint(status & DMSTATUS_IMPEBREAK, =3D=3D, DMSTATUS_IMPEBRE= AK); + + qtest_quit(qts); +} + +static void test_hartinfo(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + uint32_t info; + + dm_set_active(qts); + info =3D dm_read(qts, A_HARTINFO); + + g_assert_cmpuint(info & HARTINFO_DATAADDR_MASK, =3D=3D, 0x3c0); + g_assert_cmpuint(info & HARTINFO_DATAACCESS, =3D=3D, HARTINFO_DATAACCE= SS); + g_assert_cmpuint((info & HARTINFO_DATASIZE_MASK) >> + HARTINFO_DATASIZE_SHIFT, =3D=3D, 2); + g_assert_cmpuint((info & HARTINFO_NSCRATCH_MASK) >> + HARTINFO_NSCRATCH_SHIFT, =3D=3D, 1); + + qtest_quit(qts); +} + +static void test_abstractcs_config(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + uint32_t acs; + + dm_set_active(qts); + acs =3D dm_read(qts, A_ABSTRACTCS); + + g_assert_cmpuint(acs & ABSTRACTCS_DATACOUNT_MASK, =3D=3D, 2); + g_assert_cmpuint((acs & ABSTRACTCS_PROGBUFSIZE_MASK) >> + ABSTRACTCS_PROGBUFSIZE_SHIFT, =3D=3D, 8); + g_assert_cmpuint(acs & ABSTRACTCS_BUSY, =3D=3D, 0); + + qtest_quit(qts); +} + +static void test_halt_resume(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + uint32_t status; + + dm_set_active(qts); + status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ANYRUNNING, =3D=3D, + DMSTATUS_ANYRUNNING); + g_assert_cmpuint(status & DMSTATUS_ANYHALTED, =3D=3D, 0); + + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE | DMCONTROL_HALTREQ); + sim_cpu_halt_ack(qts, 0); + + status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ANYHALTED, =3D=3D, + DMSTATUS_ANYHALTED); + g_assert_cmpuint(status & DMSTATUS_ALLHALTED, =3D=3D, + DMSTATUS_ALLHALTED); + g_assert_cmpuint(status & DMSTATUS_ANYRUNNING, =3D=3D, 0); + g_assert_cmpuint(status & DMSTATUS_ALLRUNNING, =3D=3D, 0); + + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE | DMCONTROL_RESUMEREQ); + sim_cpu_resume_ack(qts, 0); + + status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ANYRESUMEACK, =3D=3D, + DMSTATUS_ANYRESUMEACK); + g_assert_cmpuint(status & DMSTATUS_ALLRESUMEACK, =3D=3D, + DMSTATUS_ALLRESUMEACK); + g_assert_cmpuint(status & DMSTATUS_ANYRUNNING, =3D=3D, + DMSTATUS_ANYRUNNING); + g_assert_cmpuint(status & DMSTATUS_ALLRUNNING, =3D=3D, + DMSTATUS_ALLRUNNING); + g_assert_cmpuint(status & DMSTATUS_ANYHALTED, =3D=3D, 0); + + qtest_quit(qts); +} + +int main(int argc, char *argv[]) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("/riscv-dm/dmactive-gate", test_dmactive_gate); + qtest_add_func("/riscv-dm/dmstatus", test_dmstatus); + qtest_add_func("/riscv-dm/hartinfo", test_hartinfo); + qtest_add_func("/riscv-dm/abstractcs-config", test_abstractcs_config); + qtest_add_func("/riscv-dm/halt-resume", test_halt_resume); + + return g_test_run(); +} --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954607; cv=none; d=zohomail.com; s=zohoarc; b=mArRObv8A6UZbw4j/pmgYzfc/tWR2x4YArrqb3b/q3YDunWo+Iz4InPxZYQTlO+boBzqi6XqVYvgnj5P8LZ84mtvp36CNqgGjHVOFZk9Bhwy80023oz11rj3VdmhrBCXg7gwu9DUpAvINMBF1VzXckjXVPbk2ppm1ADSZhOML+g= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954607; 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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=h/RSbypv/ZVnxXM1y5bTNKWJzgNjI04NBQqEcovui8E=; b=QoY9OXklMQv7IdFpdiO34VgineOQMwk4RKbrOTsQ3l+gzqEUUBVjKIc06V32wl62faVcW9vwmaNU4lLJt6qS5STl912pTmg+vcZPm6dY22hKTSGDsP8VoeB0qmN0cKdH+0j+gNbjSdYoBbKUEmcn224ZRpG2o+UiwVjKCTl9aTg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954607960199.11067504391724; Sat, 7 Mar 2026 23:23:27 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8T3-0005Lh-8D; Sun, 08 Mar 2026 03:22:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8Rp-0002gt-Ia for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:21:11 -0400 Received: from mail-dy1-x1343.google.com ([2607:f8b0:4864:20::1343]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8Rm-0003D2-FI for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:21:09 -0400 Received: by mail-dy1-x1343.google.com with SMTP id 5a478bee46e88-2be27fa54feso7436723eec.0 for ; Sat, 07 Mar 2026 23:21:02 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.20.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:20:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954461; x=1773559261; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=h/RSbypv/ZVnxXM1y5bTNKWJzgNjI04NBQqEcovui8E=; b=ScghuP+I9NFoPGH9pSCm/oeviQBj0k9eRSbahTRiA+ZmVxpBntFTicnp+aCrF2GYZW OOitppxrMVI7kIWMKruwVXjNQJCDXzBxGvBU2Lsw1sb5S4KKjv2//7aTlHRlzNCu5fMb zykOYKgDsiB8Pn+8j7qh66fVWsWswGwc1NI8peghD2DY6LzLF0tT4JBxULPv+UV+J9J4 m1s6wZojAOkIgsteEw8pAts5A5OvunKy/iGioXXonFGIy918h2k4yMHKLuzihz3+8Fxe vmjCbDfrtGkCQsussfWyAW16Aon2/l+C0axUuBzADM6C8rTeZRgYzOlFUefTG32daqqS 7hpA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954461; x=1773559261; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=h/RSbypv/ZVnxXM1y5bTNKWJzgNjI04NBQqEcovui8E=; b=INhwUUDqx+6wfDvAjxpb70NnFLotKnZB2tNfoNy1E61s/7QLIXoZtS3C6xFI7V6jVH P7FlVtk7HP3EKWJuE4IO9ulsv0zh3PKcw8YrMTipWq8+5270id9hlzlmOxQhMsoS4miw qyFRY4ziBF5XZ5CYxfY2k8Fc303EtL3ys12AszOO57yK62NS6VJ9fY/28TuTJ7IR6C82 D8O8RrL9hyHSRMJ2DhiInVaZwNjXzxIP6CBqmWN20Y2HEOLcWqPaQ0oza1Zo+TEKj2MX b8fHskDQf7oCBfHeEuXUoUdf7zbgon131SyFH8t6fk90nmBDtMzRViIed9YZxPEI7gBY 8C4A== X-Forwarded-Encrypted: i=1; AJvYcCXK2qXkGpx4N3SHpKB24JkWFCMmKOeF+MgaPPbw4j5WmAEBfjHHR5bNr8FCEAemo2Q/WaJOcigDYPyf@nongnu.org X-Gm-Message-State: AOJu0Yz/H8xFoyZYwlt8F92iX5Pk6SOrgOrAOLsCr+T9qB6QNsnkxCXh CggVuiy096CKN8fGUpipGjZjUCbqUMwa4MAc2V+2E6NB53Blsug08zLf X-Gm-Gg: ATEYQzzAeT8F195iDGSB+VREurBPJfULqVkflb7f/qrZQmBSAXRNeGHbbDlEMK70ALq JSXmwK0+z0I+sP+Utv2kmGWd7fVCq5A1JC/owyKR6gQYfagjDSDUvi0NShseiZk4t4HOwGmZH0a B3t0tCI3Dz7n44lxvnk7v7tGGA4oBubd6nhM5fz0u9pmiuaL5IYYqU6WoJM7CQvaUJTJR8Vdy0+ xw0hq5chfW5uSIEOjI0f1W0DC8zgoSS2rKCFLIFk1Tt1BjbkmzEjZT6ialE4QQp2gUU1yvjhiMK v29IGLHABzy9k2CUwBAJD63yZTHAo1ELYyBARV7Hmwq5apC+/PjU0GGTN3Jkc7XVQfACE8R143z 2165YQnJEQQZydDoqaDn3Rbm+GK4+5uxa09+FLqrgA0RcPwfapwP8vWVT6+8hBEWCEhNbU5Qlkz xNjgras6LzIyQMy1pd+CwSPklqlCVwmTb47GRCN2kA+v+EjIqk8I1gjjLR2nDparZQDpNeQwXL7 oW3vxubRoDFKYn07MFoN9EtmII= X-Received: by 2002:a05:7301:5789:b0:2be:1803:7e11 with SMTP id 5a478bee46e88-2be4e08affcmr2422026eec.30.1772954461029; Sat, 07 Mar 2026 23:21:01 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 25/28] tests/qtest: extend DM register semantics coverage Date: Sun, 8 Mar 2026 15:17:28 +0800 Message-ID: <21d42ab8e77b205319a2b085371d62edecfdf983.1772936778.git.chao.liu.zevorn@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1343; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1343.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954609792158500 Add tests for the DMI register interface exercised in qtest mode (no real CPU execution): data-rw, progbuf-rw =E2=80=93 DATA/PROGBUF read-write ro-registers =E2=80=93 read-only register enforcement abstractcs-w1c =E2=80=93 write-1-to-clear cmderr field hart-selection =E2=80=93 hartsel/hasel routing dmcontrol-warz =E2=80=93 write-any-read-zero fields hartreset =E2=80=93 per-hart reset semantics ndmreset-gate =E2=80=93 ndmreset gating other operations optional-regs-absent =E2=80=93 unimplemented register reads deactivate =E2=80=93 DM deactivation clears state ackhavereset =E2=80=93 havereset acknowledgment Also expand the define/macro header to cover the full DMI register map and rewrite the existing four basic tests to use the new constants. Signed-off-by: Chao Liu --- tests/qtest/riscv-dm-test.c | 589 +++++++++++++++++++++++++++++++++--- 1 file changed, 539 insertions(+), 50 deletions(-) diff --git a/tests/qtest/riscv-dm-test.c b/tests/qtest/riscv-dm-test.c index c9e3c22a20..3a0dd1cbd4 100644 --- a/tests/qtest/riscv-dm-test.c +++ b/tests/qtest/riscv-dm-test.c @@ -9,43 +9,150 @@ #include "qemu/osdep.h" #include "libqtest.h" =20 +/* Virt machine memory map base address for the Debug Module */ #define DM_BASE 0x0 =20 -#define ROM_HARTID 0x104 -#define ROM_RESUME 0x10c - -#define A_DATA0 0x10 -#define A_DMCONTROL 0x40 -#define A_DMSTATUS 0x44 -#define A_HARTINFO 0x48 -#define A_ABSTRACTCS 0x58 - +/* + * ROM layout offsets (byte offsets within DM ROM). + * CPU ROM code writes to these addresses to signal state changes to the D= M. + */ +#define ROM_HARTID 0x104 +#define ROM_GOING 0x108 +#define ROM_RESUME 0x10C +#define ROM_EXCP 0x110 +#define ROM_DATA 0x3C0 +#define ROM_FLAGS 0x400 +#define ROM_ENTRY 0x800 + +/* DMI register byte offsets (word address =C3=97 4) */ +#define A_DATA0 0x10 +#define A_DATA1 0x14 +#define A_DMCONTROL 0x40 +#define A_DMSTATUS 0x44 +#define A_HARTINFO 0x48 +#define A_HALTSUM1 0x4C +#define A_HAWINDOWSEL 0x50 +#define A_HAWINDOW 0x54 +#define A_ABSTRACTCS 0x58 +#define A_COMMAND 0x5C +#define A_ABSTRACTAUTO 0x60 +#define A_PROGBUF0 0x80 +#define A_PROGBUF1 0x84 +#define A_AUTHDATA 0xC0 +#define A_DMCS2 0xC8 +#define A_SBCS 0xE0 +#define A_SBADDRESS0 0xE4 +#define A_SBADDRESS1 0xE8 +#define A_SBADDRESS2 0xEC +#define A_SBDATA0 0xF0 +#define A_SBDATA1 0xF4 +#define A_SBDATA2 0xF8 +#define A_SBDATA3 0xFC +#define A_HALTSUM0 0x100 + +/* DMCONTROL fields */ #define DMCONTROL_DMACTIVE (1u << 0) +#define DMCONTROL_NDMRESET (1u << 1) +#define DMCONTROL_CLRRESETHALTREQ (1u << 2) +#define DMCONTROL_SETRESETHALTREQ (1u << 3) +#define DMCONTROL_HARTRESET (1u << 29) #define DMCONTROL_HALTREQ (1u << 31) #define DMCONTROL_RESUMEREQ (1u << 30) - -#define DMSTATUS_VERSION_MASK 0xf +#define DMCONTROL_ACKHAVERESET (1u << 28) +#define DMCONTROL_HASEL (1u << 26) +#define DMCONTROL_HARTSELHI_SHIFT 16 +#define DMCONTROL_HARTSELLO_SHIFT 6 +#define DMCONTROL_HARTSELLO_MASK (0x3FFu << 6) + +/* DMSTATUS fields */ +#define DMSTATUS_VERSION_MASK 0xF #define DMSTATUS_AUTHENTICATED (1u << 7) #define DMSTATUS_ANYHALTED (1u << 8) #define DMSTATUS_ALLHALTED (1u << 9) #define DMSTATUS_ANYRUNNING (1u << 10) #define DMSTATUS_ALLRUNNING (1u << 11) +#define DMSTATUS_ANYUNAVAIL (1u << 12) +#define DMSTATUS_ALLUNAVAIL (1u << 13) +#define DMSTATUS_ANYNONEXISTENT (1u << 14) +#define DMSTATUS_ALLNONEXISTENT (1u << 15) #define DMSTATUS_ANYRESUMEACK (1u << 16) #define DMSTATUS_ALLRESUMEACK (1u << 17) #define DMSTATUS_ANYHAVERESET (1u << 18) +#define DMSTATUS_ALLHAVERESET (1u << 19) #define DMSTATUS_IMPEBREAK (1u << 22) +#define DMSTATUS_NDMRESETPENDING (1u << 24) =20 -#define HARTINFO_DATAADDR_MASK 0xfffu +/* HARTINFO fields */ +#define HARTINFO_DATAADDR_MASK 0xFFFu #define HARTINFO_DATASIZE_SHIFT 12 -#define HARTINFO_DATASIZE_MASK (0xfu << HARTINFO_DATASIZE_SHIFT) +#define HARTINFO_DATASIZE_MASK (0xFu << HARTINFO_DATASIZE_SHIFT) #define HARTINFO_DATAACCESS (1u << 16) #define HARTINFO_NSCRATCH_SHIFT 20 -#define HARTINFO_NSCRATCH_MASK (0xfu << HARTINFO_NSCRATCH_SHIFT) +#define HARTINFO_NSCRATCH_MASK (0xFu << HARTINFO_NSCRATCH_SHIFT) =20 -#define ABSTRACTCS_DATACOUNT_MASK 0xf +/* ABSTRACTCS fields */ +#define ABSTRACTCS_DATACOUNT_MASK 0xF +#define ABSTRACTCS_CMDERR_MASK (0x7u << 8) +#define ABSTRACTCS_CMDERR_SHIFT 8 #define ABSTRACTCS_BUSY (1u << 12) +#define ABSTRACTCS_PROGBUFSIZE_MASK (0x1Fu << 24) #define ABSTRACTCS_PROGBUFSIZE_SHIFT 24 -#define ABSTRACTCS_PROGBUFSIZE_MASK (0x1fu << ABSTRACTCS_PROGBUFSIZE_S= HIFT) + +/* SBCS fields */ +#define SBCS_SBERROR_MASK (0x7u << 12) +#define SBCS_SBBUSYERROR (1u << 22) +#define SBCS_SBVERSION_MASK (0x7u << 29) +#define SBCS_SBVERSION_SHIFT 29 +#define SBCS_SBASIZE_SHIFT 5 +#define SBCS_SBASIZE_MASK (0x7Fu << SBCS_SBASIZE_SHIFT) +#define SBCS_SBACCESS32 (1u << 2) + +/* Abstract command register number space */ +#define REGNO_GPR(n) (0x1000 + (n)) /* x0..x31 */ +#define REGNO_FPR(n) (0x1020 + (n)) /* f0..f31 */ +#define REGNO_CSR(n) (n) /* CSR direct */ +#define REGNO_DPC 0x7b1 +#define REGNO_DCSR 0x7b0 + +/* DCSR fields */ +#define DCSR_STEP (1u << 2) +#define DCSR_CAUSE_SHIFT 6 +#define DCSR_CAUSE_MASK (0x7u << DCSR_CAUSE_SHIFT) +#define DCSR_CAUSE_EBREAK 1 +#define DCSR_CAUSE_TRIGGER 2 +#define DCSR_CAUSE_HALTREQ 3 +#define DCSR_CAUSE_STEP 4 +#define DCSR_CAUSE_RESET 5 + +/* Trigger CSRs (abstract command register numbers) */ +#define REGNO_TSELECT REGNO_CSR(0x7a0) +#define REGNO_TDATA1 REGNO_CSR(0x7a1) +#define REGNO_TDATA2 REGNO_CSR(0x7a2) + +/* mcontrol (type 2) tdata1 field helpers */ +#define TDATA1_TYPE2_TYPE (2u << 28) +#define TDATA1_TYPE2_DMODE (1u << 27) +#define TDATA1_TYPE2_ACTION_DBG (1u << 12) +#define TDATA1_TYPE2_M (1u << 6) +#define TDATA1_TYPE2_S (1u << 4) +#define TDATA1_TYPE2_U (1u << 3) +#define TDATA1_TYPE2_EXEC (1u << 2) +#define TDATA1_TYPE2_STORE (1u << 1) +#define TDATA1_TYPE2_LOAD (1u << 0) + +/* itrigger (type 3) tdata1 field helpers */ +#define TDATA1_ITRIGGER_TYPE (3u << 28) +#define TDATA1_ITRIGGER_ACTION_DBG 1u +#define TDATA1_ITRIGGER_U (1u << 6) +#define TDATA1_ITRIGGER_S (1u << 7) +#define TDATA1_ITRIGGER_M (1u << 9) +#define TDATA1_ITRIGGER_COUNT(n) (((n) & 0x3fffu) << 10) +#define TDATA1_ITRIGGER_COUNT_MASK TDATA1_ITRIGGER_COUNT(0x3fff) + +/* TCG test timing (wall-clock microseconds, CPU runs via MTTCG thread) */ +#define TCG_POLL_STEP_US 10000 /* 10ms per poll step */ +#define TCG_POLL_TIMEOUT_US 5000000 /* 5s max */ +#define TCG_BOOT_US 200000 /* 200ms boot */ =20 static uint32_t dm_read(QTestState *qts, uint32_t reg) { @@ -62,118 +169,491 @@ static void dm_set_active(QTestState *qts) dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE); } =20 +/* Write to DM ROM area (simulates CPU writing from ROM code) */ static void rom_write32(QTestState *qts, uint32_t offset, uint32_t val) { qtest_writel(qts, DM_BASE + offset, val); } =20 +/* + * Simulate the CPU executing the DM ROM halt entry code. + * In real hardware: CPU enters debug mode =E2=86=92 jumps to ROM entry (0= x800) =E2=86=92 + * ROM code writes mhartid to HARTID offset =E2=86=92 DM recognizes hart a= s halted. + */ static void sim_cpu_halt_ack(QTestState *qts, uint32_t hartid) { rom_write32(qts, ROM_HARTID, hartid); } =20 +/* + * Simulate the CPU executing the DM ROM resume handler. + * In real hardware: ROM detects RESUME flag =E2=86=92 writes hartid to RE= SUME offset + * =E2=86=92 DM recognizes hart as resumed =E2=86=92 CPU executes dret. + */ static void sim_cpu_resume_ack(QTestState *qts, uint32_t hartid) { rom_write32(qts, ROM_RESUME, hartid); } =20 + +/* + * Test: dmactive gate. + * When dmactive=3D0 (after reset), all non-DMCONTROL reads should return = 0. + */ static void test_dmactive_gate(void) { QTestState *qts =3D qtest_init("-machine virt"); =20 + /* DM starts inactive after reset */ g_assert_cmpuint(dm_read(qts, A_DMCONTROL), =3D=3D, 0); + + /* All other registers should return 0 when dmactive=3D0 */ g_assert_cmpuint(dm_read(qts, A_DMSTATUS), =3D=3D, 0); - g_assert_cmpuint(dm_read(qts, A_HARTINFO), =3D=3D, 0); g_assert_cmpuint(dm_read(qts, A_ABSTRACTCS), =3D=3D, 0); + g_assert_cmpuint(dm_read(qts, A_HARTINFO), =3D=3D, 0); g_assert_cmpuint(dm_read(qts, A_DATA0), =3D=3D, 0); + g_assert_cmpuint(dm_read(qts, A_PROGBUF0), =3D=3D, 0); =20 - dm_write(qts, A_DATA0, 0xdeadbeef); + /* Writes to non-DMCONTROL registers should be ignored */ + dm_write(qts, A_DATA0, 0xDEADBEEF); + /* Still inactive, so read should still return 0 */ g_assert_cmpuint(dm_read(qts, A_DATA0), =3D=3D, 0); =20 + /* Activate the DM */ dm_set_active(qts); g_assert_cmpuint(dm_read(qts, A_DMCONTROL) & DMCONTROL_DMACTIVE, =3D= =3D, DMCONTROL_DMACTIVE); + + /* Now DMSTATUS should be non-zero (version, authenticated, etc.) */ g_assert_cmpuint(dm_read(qts, A_DMSTATUS), !=3D, 0); =20 qtest_quit(qts); } =20 +/* + * Test: DMSTATUS register fields after activation. + */ static void test_dmstatus(void) { QTestState *qts =3D qtest_init("-machine virt"); - uint32_t status; - dm_set_active(qts); - status =3D dm_read(qts, A_DMSTATUS); =20 + uint32_t status =3D dm_read(qts, A_DMSTATUS); + + /* Version should be 3 (v1.0 spec) */ g_assert_cmpuint(status & DMSTATUS_VERSION_MASK, =3D=3D, 3); + + /* Should be authenticated */ g_assert_cmpuint(status & DMSTATUS_AUTHENTICATED, =3D=3D, DMSTATUS_AUTHENTICATED); - g_assert_cmpuint(status & DMSTATUS_ANYRUNNING, =3D=3D, - DMSTATUS_ANYRUNNING); - g_assert_cmpuint(status & DMSTATUS_ALLRUNNING, =3D=3D, - DMSTATUS_ALLRUNNING); + + /* impebreak should be set (default property) */ + g_assert_cmpuint(status & DMSTATUS_IMPEBREAK, =3D=3D, DMSTATUS_IMPEBRE= AK); + + /* Hart 0 should be running (not halted) */ + g_assert_cmpuint(status & DMSTATUS_ANYRUNNING, =3D=3D, DMSTATUS_ANYRUN= NING); + g_assert_cmpuint(status & DMSTATUS_ALLRUNNING, =3D=3D, DMSTATUS_ALLRUN= NING); g_assert_cmpuint(status & DMSTATUS_ANYHALTED, =3D=3D, 0); + g_assert_cmpuint(status & DMSTATUS_ALLHALTED, =3D=3D, 0); + + /* Should have havereset after initial reset */ g_assert_cmpuint(status & DMSTATUS_ANYHAVERESET, =3D=3D, DMSTATUS_ANYHAVERESET); - g_assert_cmpuint(status & DMSTATUS_IMPEBREAK, =3D=3D, DMSTATUS_IMPEBRE= AK); + g_assert_cmpuint(status & DMSTATUS_ALLHAVERESET, =3D=3D, + DMSTATUS_ALLHAVERESET); + + /* Hart 0 should not be nonexistent or unavailable */ + g_assert_cmpuint(status & DMSTATUS_ANYNONEXISTENT, =3D=3D, 0); + g_assert_cmpuint(status & DMSTATUS_ANYUNAVAIL, =3D=3D, 0); =20 qtest_quit(qts); } =20 +/* + * Test: HARTINFO fields describe memory-mapped DATA registers. + */ static void test_hartinfo(void) { QTestState *qts =3D qtest_init("-machine virt"); - uint32_t info; - dm_set_active(qts); - info =3D dm_read(qts, A_HARTINFO); =20 - g_assert_cmpuint(info & HARTINFO_DATAADDR_MASK, =3D=3D, 0x3c0); + uint32_t info =3D dm_read(qts, A_HARTINFO); + uint32_t datasize =3D + (info & HARTINFO_DATASIZE_MASK) >> HARTINFO_DATASIZE_SHIFT; + uint32_t nscratch =3D + (info & HARTINFO_NSCRATCH_MASK) >> HARTINFO_NSCRATCH_SHIFT; + g_assert_cmpuint(info & HARTINFO_DATAACCESS, =3D=3D, HARTINFO_DATAACCE= SS); - g_assert_cmpuint((info & HARTINFO_DATASIZE_MASK) >> - HARTINFO_DATASIZE_SHIFT, =3D=3D, 2); - g_assert_cmpuint((info & HARTINFO_NSCRATCH_MASK) >> - HARTINFO_NSCRATCH_SHIFT, =3D=3D, 1); + g_assert_cmpuint(info & HARTINFO_DATAADDR_MASK, =3D=3D, ROM_DATA); + g_assert_cmpuint(datasize, =3D=3D, 2); + g_assert_cmpuint(nscratch, =3D=3D, 1); =20 qtest_quit(qts); } =20 +/* + * Test: ABSTRACTCS config fields (datacount, progbufsize). + */ static void test_abstractcs_config(void) { QTestState *qts =3D qtest_init("-machine virt"); - uint32_t acs; - dm_set_active(qts); - acs =3D dm_read(qts, A_ABSTRACTCS); =20 + uint32_t acs =3D dm_read(qts, A_ABSTRACTCS); + + /* Default datacount =3D 2 */ g_assert_cmpuint(acs & ABSTRACTCS_DATACOUNT_MASK, =3D=3D, 2); - g_assert_cmpuint((acs & ABSTRACTCS_PROGBUFSIZE_MASK) >> - ABSTRACTCS_PROGBUFSIZE_SHIFT, =3D=3D, 8); + + /* Default progbufsize =3D 8 */ + uint32_t progbufsize =3D + (acs & ABSTRACTCS_PROGBUFSIZE_MASK) >> ABSTRACTCS_PROGBUFSIZE_SHIF= T; + g_assert_cmpuint(progbufsize, =3D=3D, 8); + + /* BUSY should be 0 */ g_assert_cmpuint(acs & ABSTRACTCS_BUSY, =3D=3D, 0); =20 + /* CMDERR should be 0 */ + g_assert_cmpuint(acs & ABSTRACTCS_CMDERR_MASK, =3D=3D, 0); + qtest_quit(qts); } =20 -static void test_halt_resume(void) +/* + * Test: DATA register read/write. + */ +static void test_data_rw(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + dm_set_active(qts); + + /* Write to DATA0 and DATA1 */ + dm_write(qts, A_DATA0, 0xCAFEBABE); + dm_write(qts, A_DATA1, 0x12345678); + + g_assert_cmpuint(dm_read(qts, A_DATA0), =3D=3D, 0xCAFEBABE); + g_assert_cmpuint(dm_read(qts, A_DATA1), =3D=3D, 0x12345678); + + /* Overwrite */ + dm_write(qts, A_DATA0, 0x0); + g_assert_cmpuint(dm_read(qts, A_DATA0), =3D=3D, 0x0); + + qtest_quit(qts); +} + +/* + * Test: PROGBUF register read/write. + */ +static void test_progbuf_rw(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + dm_set_active(qts); + + /* Write distinct values to progbuf0..3 */ + for (int i =3D 0; i < 4; i++) { + dm_write(qts, A_PROGBUF0 + i * 4, 0xA0000000 | i); + } + + for (int i =3D 0; i < 4; i++) { + g_assert_cmpuint(dm_read(qts, A_PROGBUF0 + i * 4), =3D=3D, + 0xA0000000 | (uint32_t)i); + } + + qtest_quit(qts); +} + +/* + * Test: Read-only register protection (DMSTATUS, HARTINFO, HALTSUM). + */ +static void test_ro_registers(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + dm_set_active(qts); + + uint32_t orig_status =3D dm_read(qts, A_DMSTATUS); + + /* Try to write DMSTATUS - should be ignored (RO) */ + dm_write(qts, A_DMSTATUS, 0xFFFFFFFF); + g_assert_cmpuint(dm_read(qts, A_DMSTATUS), =3D=3D, orig_status); + + /* Try to write HARTINFO - should be ignored (RO) */ + uint32_t orig_hartinfo =3D dm_read(qts, A_HARTINFO); + dm_write(qts, A_HARTINFO, 0xFFFFFFFF); + g_assert_cmpuint(dm_read(qts, A_HARTINFO), =3D=3D, orig_hartinfo); + + /* Try to write HALTSUM0 - should be ignored (RO) */ + uint32_t orig_haltsum0 =3D dm_read(qts, A_HALTSUM0); + dm_write(qts, A_HALTSUM0, 0xFFFFFFFF); + g_assert_cmpuint(dm_read(qts, A_HALTSUM0), =3D=3D, orig_haltsum0); + + qtest_quit(qts); +} + +/* + * Test: W1C (Write-1-to-Clear) behavior on ABSTRACTCS.CMDERR. + */ +static void test_abstractcs_w1c(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + dm_set_active(qts); + + /* + * CMDERR is 0 initially. To test W1C, we need to trigger an error. + * Issue an invalid command (cmdtype=3D0xFF) to a running hart. + * This should set CMDERR to HALTRESUME (4) since hart is not halted. + */ + dm_write(qts, A_COMMAND, 0xFF000000); + + uint32_t acs =3D dm_read(qts, A_ABSTRACTCS); + uint32_t cmderr =3D (acs & ABSTRACTCS_CMDERR_MASK) >> ABSTRACTCS_CMDER= R_SHIFT; + g_assert_cmpuint(cmderr, !=3D, 0); + + /* Clear CMDERR by writing 1s to the CMDERR field */ + dm_write(qts, A_ABSTRACTCS, ABSTRACTCS_CMDERR_MASK); + + acs =3D dm_read(qts, A_ABSTRACTCS); + cmderr =3D (acs & ABSTRACTCS_CMDERR_MASK) >> ABSTRACTCS_CMDERR_SHIFT; + g_assert_cmpuint(cmderr, =3D=3D, 0); + + qtest_quit(qts); +} + +/* + * Test: Hart selection via DMCONTROL.hartsel. + * Select a nonexistent hart and verify DMSTATUS reports it. + */ +static void test_hart_selection(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + dm_set_active(qts); + + /* Default hart 0 is selected and should be running */ + uint32_t status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ANYRUNNING, =3D=3D, DMSTATUS_ANYRUN= NING); + g_assert_cmpuint(status & DMSTATUS_ANYNONEXISTENT, =3D=3D, 0); + + /* Select nonexistent hart 99 */ + uint32_t ctl =3D DMCONTROL_DMACTIVE | + (99u << DMCONTROL_HARTSELLO_SHIFT); + dm_write(qts, A_DMCONTROL, ctl); + + status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ANYNONEXISTENT, =3D=3D, + DMSTATUS_ANYNONEXISTENT); + g_assert_cmpuint(status & DMSTATUS_ALLNONEXISTENT, =3D=3D, + DMSTATUS_ALLNONEXISTENT); + g_assert_cmpuint(status & DMSTATUS_ANYRUNNING, =3D=3D, 0); + + /* Switch back to hart 0 */ + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE); + status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ANYRUNNING, =3D=3D, DMSTATUS_ANYRUN= NING); + g_assert_cmpuint(status & DMSTATUS_ANYNONEXISTENT, =3D=3D, 0); + + qtest_quit(qts); +} + +/* + * Test: DMCONTROL WARZ (Write-Any-Read-Zero) fields. + * HALTREQ, RESUMEREQ, ACKHAVERESET etc. should not read back. + */ +static void test_dmcontrol_warz(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + dm_set_active(qts); + + /* Write HALTREQ | DMACTIVE */ + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE | DMCONTROL_HALTREQ); + + /* HALTREQ should not read back */ + uint32_t ctl =3D dm_read(qts, A_DMCONTROL); + g_assert_cmpuint(ctl & DMCONTROL_HALTREQ, =3D=3D, 0); + + /* DMACTIVE should still be set */ + g_assert_cmpuint(ctl & DMCONTROL_DMACTIVE, =3D=3D, DMCONTROL_DMACTIVE); + + /* Write RESUMEREQ | DMACTIVE */ + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE | DMCONTROL_RESUMEREQ); + ctl =3D dm_read(qts, A_DMCONTROL); + g_assert_cmpuint(ctl & DMCONTROL_RESUMEREQ, =3D=3D, 0); + + /* Write ACKHAVERESET | DMACTIVE */ + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE | DMCONTROL_ACKHAVERESET= ); + ctl =3D dm_read(qts, A_DMCONTROL); + g_assert_cmpuint(ctl & DMCONTROL_ACKHAVERESET, =3D=3D, 0); + + qtest_quit(qts); +} + +/* + * Test: HARTRESET is implemented and reads back while asserted. + */ +static void test_hartreset(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + uint32_t ctl, status; + + dm_set_active(qts); + + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE | DMCONTROL_HARTRESET); + ctl =3D dm_read(qts, A_DMCONTROL); + g_assert_cmpuint(ctl & DMCONTROL_HARTRESET, =3D=3D, DMCONTROL_HARTRESE= T); + + status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ANYHAVERESET, =3D=3D, + DMSTATUS_ANYHAVERESET); + + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE); + ctl =3D dm_read(qts, A_DMCONTROL); + g_assert_cmpuint(ctl & DMCONTROL_HARTRESET, =3D=3D, 0); + + qtest_quit(qts); +} + +/* + * Test: NDMRESET gates non-DMCONTROL accesses and exposes only pending st= ate. + */ +static void test_ndmreset_gate(void) { QTestState *qts =3D qtest_init("-machine virt"); uint32_t status; =20 dm_set_active(qts); + dm_write(qts, A_DATA0, 0xDEADBEEF); + g_assert_cmpuint(dm_read(qts, A_DATA0), =3D=3D, 0xDEADBEEF); + + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE | DMCONTROL_NDMRESET); + + status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status, =3D=3D, DMSTATUS_NDMRESETPENDING); + + dm_write(qts, A_DATA0, 0x11223344); + g_assert_cmpuint(dm_read(qts, A_DATA0), =3D=3D, 0); + + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE); + status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_NDMRESETPENDING, =3D=3D, 0); + g_assert_cmpuint(status & DMSTATUS_ANYHAVERESET, =3D=3D, + DMSTATUS_ANYHAVERESET); + + qtest_quit(qts); +} + +/* + * Test: Optional registers that are not implemented read as 0 and ignore + * writes. + */ +static void test_optional_regs_absent(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + + dm_set_active(qts); + + dm_write(qts, A_AUTHDATA, 0xFFFFFFFF); + g_assert_cmpuint(dm_read(qts, A_AUTHDATA), =3D=3D, 0); + + dm_write(qts, A_DMCS2, 0xFFFFFFFF); + g_assert_cmpuint(dm_read(qts, A_DMCS2), =3D=3D, 0); + + dm_write(qts, A_SBADDRESS0, 0xFFFFFFFF); + dm_write(qts, A_SBADDRESS1, 0xFFFFFFFF); + dm_write(qts, A_SBADDRESS2, 0xFFFFFFFF); + dm_write(qts, A_SBDATA0, 0xAAAAAAAA); + dm_write(qts, A_SBDATA1, 0xBBBBBBBB); + dm_write(qts, A_SBDATA2, 0xCCCCCCCC); + dm_write(qts, A_SBDATA3, 0xDDDDDDDD); + + g_assert_cmpuint(dm_read(qts, A_SBADDRESS0), =3D=3D, 0); + g_assert_cmpuint(dm_read(qts, A_SBADDRESS1), =3D=3D, 0); + g_assert_cmpuint(dm_read(qts, A_SBADDRESS2), =3D=3D, 0); + g_assert_cmpuint(dm_read(qts, A_SBDATA0), =3D=3D, 0); + g_assert_cmpuint(dm_read(qts, A_SBDATA1), =3D=3D, 0); + g_assert_cmpuint(dm_read(qts, A_SBDATA2), =3D=3D, 0); + g_assert_cmpuint(dm_read(qts, A_SBDATA3), =3D=3D, 0); + + qtest_quit(qts); +} + +/* + * Test: Deactivation resets all state. + */ +static void test_deactivate(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + + /* Activate and write some data */ + dm_set_active(qts); + dm_write(qts, A_DATA0, 0xDEADBEEF); + g_assert_cmpuint(dm_read(qts, A_DATA0), =3D=3D, 0xDEADBEEF); + + /* Deactivate: clear dmactive */ + dm_write(qts, A_DMCONTROL, 0); + + /* All registers should return 0 again */ + g_assert_cmpuint(dm_read(qts, A_DMSTATUS), =3D=3D, 0); + g_assert_cmpuint(dm_read(qts, A_DATA0), =3D=3D, 0); + g_assert_cmpuint(dm_read(qts, A_ABSTRACTCS), =3D=3D, 0); + + /* Re-activate: verify state was reset */ + dm_set_active(qts); + g_assert_cmpuint(dm_read(qts, A_DATA0), =3D=3D, 0); + + uint32_t status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_VERSION_MASK, =3D=3D, 3); + + qtest_quit(qts); +} + +/* + * Test: ACKHAVERESET clears havereset in DMSTATUS. + */ +static void test_ackhavereset(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + dm_set_active(qts); + + /* After reset, havereset should be set */ + uint32_t status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ANYHAVERESET, =3D=3D, + DMSTATUS_ANYHAVERESET); + + /* Acknowledge havereset */ + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE | DMCONTROL_ACKHAVERESET= ); + + status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ANYHAVERESET, =3D=3D, 0); + g_assert_cmpuint(status & DMSTATUS_ALLHAVERESET, =3D=3D, 0); + + qtest_quit(qts); +} + +/* + * Test: Halt and resume cycle via ROM simulation. + * + * Simulates the full halt/resume flow: + * 1. Debugger writes HALTREQ =E2=86=92 DM signals halt IRQ + * 2. CPU enters debug mode =E2=86=92 ROM entry code writes mhartid to HAR= TID offset + * 3. DM recognizes hart as halted (anyhalted/allhalted set) + * 4. Debugger writes RESUMEREQ =E2=86=92 DM sets FLAGS to RESUME + * 5. CPU ROM resume handler writes hartid to RESUME offset =E2=86=92 dret + * 6. DM recognizes hart as resumed (resumeack set, running) + */ +static void test_halt_resume(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + dm_set_active(qts); + + uint32_t status; + status =3D dm_read(qts, A_DMSTATUS); - g_assert_cmpuint(status & DMSTATUS_ANYRUNNING, =3D=3D, - DMSTATUS_ANYRUNNING); + g_assert_cmpuint(status & DMSTATUS_ANYRUNNING, =3D=3D, DMSTATUS_ANYRUN= NING); g_assert_cmpuint(status & DMSTATUS_ANYHALTED, =3D=3D, 0); =20 dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE | DMCONTROL_HALTREQ); sim_cpu_halt_ack(qts, 0); =20 status =3D dm_read(qts, A_DMSTATUS); - g_assert_cmpuint(status & DMSTATUS_ANYHALTED, =3D=3D, - DMSTATUS_ANYHALTED); - g_assert_cmpuint(status & DMSTATUS_ALLHALTED, =3D=3D, - DMSTATUS_ALLHALTED); + g_assert_cmpuint(status & DMSTATUS_ANYHALTED, =3D=3D, DMSTATUS_ANYHALT= ED); + g_assert_cmpuint(status & DMSTATUS_ALLHALTED, =3D=3D, DMSTATUS_ALLHALT= ED); g_assert_cmpuint(status & DMSTATUS_ANYRUNNING, =3D=3D, 0); g_assert_cmpuint(status & DMSTATUS_ALLRUNNING, =3D=3D, 0); =20 @@ -185,10 +665,8 @@ static void test_halt_resume(void) DMSTATUS_ANYRESUMEACK); g_assert_cmpuint(status & DMSTATUS_ALLRESUMEACK, =3D=3D, DMSTATUS_ALLRESUMEACK); - g_assert_cmpuint(status & DMSTATUS_ANYRUNNING, =3D=3D, - DMSTATUS_ANYRUNNING); - g_assert_cmpuint(status & DMSTATUS_ALLRUNNING, =3D=3D, - DMSTATUS_ALLRUNNING); + g_assert_cmpuint(status & DMSTATUS_ANYRUNNING, =3D=3D, DMSTATUS_ANYRUN= NING); + g_assert_cmpuint(status & DMSTATUS_ALLRUNNING, =3D=3D, DMSTATUS_ALLRUN= NING); g_assert_cmpuint(status & DMSTATUS_ANYHALTED, =3D=3D, 0); =20 qtest_quit(qts); @@ -202,6 +680,17 @@ int main(int argc, char *argv[]) qtest_add_func("/riscv-dm/dmstatus", test_dmstatus); qtest_add_func("/riscv-dm/hartinfo", test_hartinfo); qtest_add_func("/riscv-dm/abstractcs-config", test_abstractcs_config); + qtest_add_func("/riscv-dm/data-rw", test_data_rw); + qtest_add_func("/riscv-dm/progbuf-rw", test_progbuf_rw); + qtest_add_func("/riscv-dm/ro-registers", test_ro_registers); + qtest_add_func("/riscv-dm/abstractcs-w1c", test_abstractcs_w1c); + qtest_add_func("/riscv-dm/hart-selection", test_hart_selection); + qtest_add_func("/riscv-dm/dmcontrol-warz", test_dmcontrol_warz); + qtest_add_func("/riscv-dm/hartreset", test_hartreset); + qtest_add_func("/riscv-dm/ndmreset-gate", test_ndmreset_gate); + qtest_add_func("/riscv-dm/optional-regs-absent", test_optional_regs_ab= sent); + qtest_add_func("/riscv-dm/deactivate", test_deactivate); + qtest_add_func("/riscv-dm/ackhavereset", test_ackhavereset); qtest_add_func("/riscv-dm/halt-resume", test_halt_resume); =20 return g_test_run(); --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954584; cv=none; d=zohomail.com; s=zohoarc; b=Vp728+vC1h3QlVBBsdE+LrMECSWGNDHGRMNdO5n6k1WDHq19Ed8l0KnMwUsZWManI18vLd3Kwnpc5pkkQvZGVa+HEhOJr0kI+ld1FQF+H+0CunSidNL1SjCKhvPZUj7LwefATkkOuNJA4xP7wcO0GOSOhgEs8PHVVyIScBrBOKk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954584; 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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=TJZ+rBevmOiRZs5yFHqYuEbMVHGXG6seK7boNd+RNkY=; b=Bgtluvq42XT1CkybKvrBK2smNgGKmYaaax7ze8LR2H6xzNmtyG5ANy1IriqNpWFO/A4E90xZIuxOz01K7zA3La9GGHvVvR86N2JlFHSz89iv1gc4ngjpE5T2qnNgSCRQMSaef4ry/57r+SOvajUcQRQ0A8kKg3hBBN57/ZWMLHk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954584179118.4366770710393; Sat, 7 Mar 2026 23:23:04 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8Sh-0003l4-4W; Sun, 08 Mar 2026 03:22:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8Rt-0002ry-KJ for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:21:14 -0400 Received: from mail-dy1-x1344.google.com ([2607:f8b0:4864:20::1344]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8Rr-0003J9-8p for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:21:13 -0400 Received: by mail-dy1-x1344.google.com with SMTP id 5a478bee46e88-2bdfc4b191fso6050025eec.1 for ; Sat, 07 Mar 2026 23:21:09 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.21.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:21:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954468; x=1773559268; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=TJZ+rBevmOiRZs5yFHqYuEbMVHGXG6seK7boNd+RNkY=; b=aQ4jGbjuyLZgSxfnOMk0Q7hnk/N3DVn6HBNT4ypKEdTyuqIlJstNae6AJJXEEGRUQy YY9rpBV1VeWZfL3ZDP5iQBsZWrsJaotuVDmTgvdXs9u6adBQVced9b+eBiWyH/m/mcob +cMiCKN3Kt3+tdHVp/UfoPKlXY7OqHMospqmOSfk//1QPiuLeFm/D3niMeBlzJDAJ6Ap krIWSuRYcOwOJic1lZOH9zkeHBZUNfdy+6at/74PXWkCaxX0ysrvHmZsfklobI8apz3w jQWDAqJ8KQubZroKgpYyEDRT6S2xRdy+rqR61UnOy5PxlCK/i92R1Zw7V+Mfh3ENUFQG MAxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954468; x=1773559268; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=TJZ+rBevmOiRZs5yFHqYuEbMVHGXG6seK7boNd+RNkY=; b=cMuBf720oinG1OwV33YwcSuKgtz1NoCv3cQz6UdA+cEAmQAP62+iqaHCeGOlp2ylLj 9/KYBGAkdkX+cd9XhMiVXinMIOuypzHgNqDigSpryjbwuY2gd2DU1CCUcL6o6P/XglK0 wjRJtb6dU5A5VIdR0hxJgFzFT5mhpGvXRn+SMx2QcBdy4Kl2NUYAviWM4DdoOITNft5s Napz0LHROmBEm7M72Y/I7v5MV3W+TfG7QmzX22v7zXJJI8tTe12GLDVniOmeXyAkKh4H eJG3DGTnhAl9eKIPOBl9ixOKv4hmQYOVcMqSNu5QNBQqvkwHh3VcAIKw2iWWEwIIZgyd 6e0w== X-Forwarded-Encrypted: i=1; AJvYcCU7WyoPwXNcX90ViaRlzO60rQRSNo9KsuV+DPbvleLVDnSNQBYMGcviPKOib+p0ShLXMrpipo0VmJs6@nongnu.org X-Gm-Message-State: AOJu0YzQEXXz9o6dy169Sfl69U6JDtdBzID3tOP46DnubtL0rj0OGBSP eEuVrmQDkD/wG6XvmwqhEk5fKWSCnSvzzg3hJM4I4nGIfrmkJASwElVB X-Gm-Gg: ATEYQzx9ONanA9c+KTtEpLNKQWdEq+8Z10YhEJzxL3tFwccDL/OYA9WFA9veiDuBKtU wlo4qavXLtEgqUPvAAcbYAwnUq+uT4cxKDdIrAtOP08/0AT8P/+bjXkEoSIgiciZr+l30F0W0Sp mPFnwRAbIQJUYCxQwM2oAPd/rMVPU0ZTE0HDyf0SgvlTH2/NtpztY4eFL4BClPw0nWdMg8wqih1 e0U8wgV77XPEAPBiulpKhCF97rQ0kEw6GoASNpxy1a+M5LUj0+CzU3KTXHKxinlOTZDzQvY66Ku uJtwsy1itiTPZx8o697eq2+5svvQSnRALnZCpVG+3LDJWVncrfcRkup8/O0+HdaeQTCwy2FOleI iiEl4iCmYpkvS9c3XF7BbZka0foti46ltUNsWn+kZu/QecB4IuonZn1plSb+s3xuCW58Cturxnb q6M4YsA0j3FnwI6XKpOvMZ+PiEN8NZn+0iaSIybBigF10jL4GNOCgAM++SCUBeWBUr/UB+a4hrD YyYmXH1gaE2S/VlqtxdqCGkBsZjlVENpV56Sg== X-Received: by 2002:a05:7300:320a:b0:2bd:fb12:9a01 with SMTP id 5a478bee46e88-2be4deab763mr2883909eec.12.1772954468286; Sat, 07 Mar 2026 23:21:08 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 26/28] tests/qtest: add DM abstract command and halt/resume tests Date: Sun, 8 Mar 2026 15:17:29 +0800 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1344; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1344.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954585419154100 Add the ROM simulation helpers (sim_cpu_going_ack, sim_cpu_exception) and tests that exercise the abstract command interface and hart-window registers in qtest mode: abstractauto =E2=80=93 auto-execute on data/progbuf write command-not-halted =E2=80=93 command rejected when hart running invalid-regno-exception =E2=80=93 out-of-range register access abstract-cmd-flow =E2=80=93 SMP abstract read/write cycle abstract-cmd-exception =E2=80=93 exception during abstract command hawindow =E2=80=93 hart array window register haltsum0-window =E2=80=93 haltsum0 with 64-hart SMP haltsum1-window =E2=80=93 haltsum1 with 64-hart SMP Signed-off-by: Chao Liu --- tests/qtest/riscv-dm-test.c | 315 ++++++++++++++++++++++++++++++++++++ 1 file changed, 315 insertions(+) diff --git a/tests/qtest/riscv-dm-test.c b/tests/qtest/riscv-dm-test.c index 3a0dd1cbd4..1b1ab02284 100644 --- a/tests/qtest/riscv-dm-test.c +++ b/tests/qtest/riscv-dm-test.c @@ -195,6 +195,24 @@ static void sim_cpu_resume_ack(QTestState *qts, uint32= _t hartid) rom_write32(qts, ROM_RESUME, hartid); } =20 +/* + * Simulate the CPU executing the GOING acknowledgment. + * ROM code: detects GOING flag =E2=86=92 writes 0 to GOING offset =E2=86= =92 jumps to cmd. + */ +static void sim_cpu_going_ack(QTestState *qts) +{ + rom_write32(qts, ROM_GOING, 0); +} + +/* + * Simulate CPU hitting exception during abstract command. + * ROM exception handler writes 0 to EXCP offset. + */ +static void sim_cpu_exception(QTestState *qts) +{ + rom_write32(qts, ROM_EXCP, 0); +} + =20 /* * Test: dmactive gate. @@ -626,6 +644,293 @@ static void test_ackhavereset(void) qtest_quit(qts); } =20 +/* + * Test: Unsupported register numbers report CMDERR=3DEXCEPTION. + */ +static void test_invalid_regno_exception(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + uint32_t cmd, acs, cmderr; + + dm_set_active(qts); + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE | DMCONTROL_HALTREQ); + sim_cpu_halt_ack(qts, 0); + + dm_write(qts, A_ABSTRACTCS, ABSTRACTCS_CMDERR_MASK); + + cmd =3D (0u << 24) | (1u << 17) | (2u << 20) | 0x1040u; + dm_write(qts, A_COMMAND, cmd); + + acs =3D dm_read(qts, A_ABSTRACTCS); + cmderr =3D (acs & ABSTRACTCS_CMDERR_MASK) >> ABSTRACTCS_CMDERR_SHIFT; + g_assert_cmpuint(cmderr, =3D=3D, 3); + + qtest_quit(qts); +} + +/* + * Test: ABSTRACTAUTO read/write. + */ +static void test_abstractauto(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + dm_set_active(qts); + + /* Write autoexec pattern */ + dm_write(qts, A_ABSTRACTAUTO, 0x00030003); + g_assert_cmpuint(dm_read(qts, A_ABSTRACTAUTO), =3D=3D, 0x00030003); + + /* Clear */ + dm_write(qts, A_ABSTRACTAUTO, 0); + g_assert_cmpuint(dm_read(qts, A_ABSTRACTAUTO), =3D=3D, 0); + + qtest_quit(qts); +} + +/* + * Test: COMMAND write when hart is not halted should set CMDERR. + */ +static void test_command_not_halted(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + dm_set_active(qts); + + /* Clear any existing CMDERR */ + dm_write(qts, A_ABSTRACTCS, ABSTRACTCS_CMDERR_MASK); + + /* + * Issue Access Register command (cmdtype=3D0, transfer=3D1, regno=3D0= x1000) + * to a running hart. Should fail with HALTRESUME error (4). + */ + uint32_t cmd =3D (0u << 24) | /* cmdtype =3D Access Register */ + (1u << 17) | /* transfer =3D 1 */ + (2u << 20) | /* aarsize =3D 32-bit */ + 0x1000; /* regno =3D x0 */ + dm_write(qts, A_COMMAND, cmd); + + uint32_t acs =3D dm_read(qts, A_ABSTRACTCS); + uint32_t cmderr =3D (acs & ABSTRACTCS_CMDERR_MASK) >> ABSTRACTCS_CMDER= R_SHIFT; + /* HALTRESUME error =3D 4 */ + g_assert_cmpuint(cmderr, =3D=3D, 4); + + /* Clear CMDERR */ + dm_write(qts, A_ABSTRACTCS, ABSTRACTCS_CMDERR_MASK); + acs =3D dm_read(qts, A_ABSTRACTCS); + cmderr =3D (acs & ABSTRACTCS_CMDERR_MASK) >> ABSTRACTCS_CMDERR_SHIFT; + g_assert_cmpuint(cmderr, =3D=3D, 0); + + qtest_quit(qts); +} + +/* + * Test: Abstract command execution flow (Access Register). + * + * With hart halted, issue an Access Register command: + * 1. Hart must be halted first + * 2. Write COMMAND =E2=86=92 DM sets BUSY=3D1, writes instructions to CMD= space, + * sets FLAGS=3DGOING + * 3. Hart can keep reporting HALTED in the park loop before consuming GO + * 4. CPU ROM detects GOING =E2=86=92 writes to GOING offset (ack) =E2=86= =92 jumps to cmd + * 5. CPU executes cmd =E2=86=92 hits ebreak =E2=86=92 re-enters ROM =E2= =86=92 writes HARTID + * 6. DM only completes after the selected hart returns to the park loop + */ +static void test_abstract_cmd_flow(void) +{ + QTestState *qts =3D qtest_init("-machine virt -smp 2"); + dm_set_active(qts); + + /* Halt both harts first. */ + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE | DMCONTROL_HALTREQ); + sim_cpu_halt_ack(qts, 0); + sim_cpu_halt_ack(qts, 1); + + uint32_t status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ALLHALTED, =3D=3D, DMSTATUS_ALLHALT= ED); + + /* Clear any latched CMDERR */ + dm_write(qts, A_ABSTRACTCS, ABSTRACTCS_CMDERR_MASK); + + /* + * Issue Access Register command: + * cmdtype=3D0 (Access Register), transfer=3D1, write=3D0 (read), + * aarsize=3D2 (32-bit), regno=3D0x1000 (x0) + */ + uint32_t cmd =3D (0u << 24) | /* cmdtype =3D Access Register */ + (1u << 17) | /* transfer =3D 1 */ + (2u << 20) | /* aarsize =3D 32-bit */ + 0x1000; /* regno =3D x0 */ + dm_write(qts, A_COMMAND, cmd); + + /* BUSY should be set */ + uint32_t acs =3D dm_read(qts, A_ABSTRACTCS); + g_assert_cmpuint(acs & ABSTRACTCS_BUSY, =3D=3D, ABSTRACTCS_BUSY); + + /* + * A different halted hart must not complete the command, and the sele= cted + * hart must not complete it before GO has been consumed. + */ + sim_cpu_halt_ack(qts, 1); + g_assert_cmpuint(dm_read(qts, A_ABSTRACTCS) & ABSTRACTCS_BUSY, =3D=3D, + ABSTRACTCS_BUSY); + sim_cpu_halt_ack(qts, 0); + g_assert_cmpuint(dm_read(qts, A_ABSTRACTCS) & ABSTRACTCS_BUSY, =3D=3D, + ABSTRACTCS_BUSY); + + /* Simulate CPU: ROM detects GOING flag =E2=86=92 writes GOING ack. */ + sim_cpu_going_ack(qts); + + /* Simulate CPU: execute cmd, hit ebreak, then re-enter ROM. */ + sim_cpu_halt_ack(qts, 0); + + /* BUSY should be cleared, no error */ + acs =3D dm_read(qts, A_ABSTRACTCS); + g_assert_cmpuint(acs & ABSTRACTCS_BUSY, =3D=3D, 0); + uint32_t cmderr =3D + (acs & ABSTRACTCS_CMDERR_MASK) >> ABSTRACTCS_CMDERR_SHIFT; + g_assert_cmpuint(cmderr, =3D=3D, 0); + + qtest_quit(qts); +} + +/* + * Test: Abstract command exception path. + * + * When CPU hits an exception during abstract cmd execution: + * 1. ROM exception handler writes to EXCP offset + * 2. DM latches CMDERR=3DEXCEPTION(3) and stays busy until the hart parks= again + * 3. CPU ebreak =E2=86=92 re-enters ROM =E2=86=92 writes HARTID (re-halt) + */ +static void test_abstract_cmd_exception(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + dm_set_active(qts); + + /* Halt hart 0 */ + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE | DMCONTROL_HALTREQ); + sim_cpu_halt_ack(qts, 0); + + /* Clear CMDERR */ + dm_write(qts, A_ABSTRACTCS, ABSTRACTCS_CMDERR_MASK); + + /* Issue Access Register command */ + uint32_t cmd =3D (0u << 24) | (1u << 17) | (2u << 20) | 0x1000; + dm_write(qts, A_COMMAND, cmd); + + g_assert_cmpuint(dm_read(qts, A_ABSTRACTCS) & ABSTRACTCS_BUSY, =3D=3D, + ABSTRACTCS_BUSY); + + /* CPU acknowledges going */ + sim_cpu_going_ack(qts); + + /* CPU hits exception during cmd execution =E2=86=92 ROM exception han= dler */ + sim_cpu_exception(qts); + + /* BUSY stays set until the hart re-enters the park loop. */ + uint32_t acs =3D dm_read(qts, A_ABSTRACTCS); + g_assert_cmpuint(acs & ABSTRACTCS_BUSY, =3D=3D, ABSTRACTCS_BUSY); + uint32_t cmderr =3D + (acs & ABSTRACTCS_CMDERR_MASK) >> ABSTRACTCS_CMDERR_SHIFT; + g_assert_cmpuint(cmderr, =3D=3D, 3); /* EXCEPTION */ + + /* CPU ebreak in exception handler =E2=86=92 re-enters ROM =E2=86=92 w= rites HARTID */ + sim_cpu_halt_ack(qts, 0); + + acs =3D dm_read(qts, A_ABSTRACTCS); + g_assert_cmpuint(acs & ABSTRACTCS_BUSY, =3D=3D, 0); + + /* Hart should still be halted */ + uint32_t st =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(st & DMSTATUS_ALLHALTED, =3D=3D, DMSTATUS_ALLHALTED); + + /* Clear CMDERR for cleanup */ + dm_write(qts, A_ABSTRACTCS, ABSTRACTCS_CMDERR_MASK); + acs =3D dm_read(qts, A_ABSTRACTCS); + cmderr =3D (acs & ABSTRACTCS_CMDERR_MASK) >> ABSTRACTCS_CMDERR_SHIFT; + g_assert_cmpuint(cmderr, =3D=3D, 0); + + qtest_quit(qts); +} + +/* + * Test: HAWINDOWSEL and HAWINDOW read/write. + */ +static void test_hawindow(void) +{ + QTestState *qts =3D qtest_init("-machine virt"); + dm_set_active(qts); + + /* Select window 0 */ + dm_write(qts, A_HAWINDOWSEL, 0); + g_assert_cmpuint(dm_read(qts, A_HAWINDOWSEL), =3D=3D, 0); + + /* Write a mask to HAWINDOW */ + dm_write(qts, A_HAWINDOW, 0x5); + g_assert_cmpuint(dm_read(qts, A_HAWINDOW), =3D=3D, 0x5); + + /* Clear */ + dm_write(qts, A_HAWINDOW, 0); + g_assert_cmpuint(dm_read(qts, A_HAWINDOW), =3D=3D, 0); + + qtest_quit(qts); +} + +/* + * Test: HALTSUM0 window follows hartsel[19:5]. + */ +static void test_haltsum0_window(void) +{ + QTestState *qts =3D qtest_init("-machine virt -smp 64"); + dm_set_active(qts); + + /* Mark hart 40 halted. */ + sim_cpu_halt_ack(qts, 40); + + /* Window base 0: hart 40 is out of range 0..31. */ + dm_write(qts, A_DMCONTROL, + DMCONTROL_DMACTIVE | (0u << DMCONTROL_HARTSELLO_SHIFT)); + g_assert_cmpuint(dm_read(qts, A_HALTSUM0), =3D=3D, 0); + + /* Window base 32: hart 40 maps to bit 8. */ + dm_write(qts, A_DMCONTROL, + DMCONTROL_DMACTIVE | (32u << DMCONTROL_HARTSELLO_SHIFT)); + g_assert_cmpuint(dm_read(qts, A_HALTSUM0), =3D=3D, (1u << 8)); + + qtest_quit(qts); +} + +/* + * Test: HALTSUM1 window follows hartsel[19:10]. + */ +static void test_haltsum1_window(void) +{ + QTestState *qts =3D qtest_init("-machine virt -smp 64"); + + dm_set_active(qts); + + sim_cpu_halt_ack(qts, 33); + + g_assert_cmpuint(dm_read(qts, A_HALTSUM1), =3D=3D, (1u << 1)); + + dm_write(qts, A_DMCONTROL, + DMCONTROL_DMACTIVE | (1u << DMCONTROL_HARTSELHI_SHIFT)); + g_assert_cmpuint(dm_read(qts, A_HALTSUM1), =3D=3D, 0); + + qtest_quit(qts); +} + +/* TCG-mode tests: real CPU execution. */ + +/* + * Test: Halt CPU with TCG and verify DPC/DCSR. + * + * With real CPU execution: + * 1. Boot CPU, let it run briefly + * 2. Send HALTREQ =E2=86=92 CPU enters debug mode + * 3. Read DCSR via abstract command =E2=86=92 verify cause =3D HALTREQ (3) + * 4. Read DPC via abstract command =E2=86=92 verify it's a valid address + * 5. Resume CPU, then re-halt to verify the cycle works + */ + /* * Test: Halt and resume cycle via ROM simulation. * @@ -691,7 +996,17 @@ int main(int argc, char *argv[]) qtest_add_func("/riscv-dm/optional-regs-absent", test_optional_regs_ab= sent); qtest_add_func("/riscv-dm/deactivate", test_deactivate); qtest_add_func("/riscv-dm/ackhavereset", test_ackhavereset); + qtest_add_func("/riscv-dm/abstractauto", test_abstractauto); + qtest_add_func("/riscv-dm/command-not-halted", test_command_not_halted= ); + qtest_add_func("/riscv-dm/invalid-regno-exception", + test_invalid_regno_exception); + qtest_add_func("/riscv-dm/hawindow", test_hawindow); + qtest_add_func("/riscv-dm/haltsum0-window", test_haltsum0_window); + qtest_add_func("/riscv-dm/haltsum1-window", test_haltsum1_window); qtest_add_func("/riscv-dm/halt-resume", test_halt_resume); + qtest_add_func("/riscv-dm/abstract-cmd-flow", test_abstract_cmd_flow); + qtest_add_func("/riscv-dm/abstract-cmd-exception", + test_abstract_cmd_exception); =20 return g_test_run(); } --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954560; cv=none; d=zohomail.com; s=zohoarc; b=k34TIhvInbHzEZFC3lWk5bFyFGl5e/gvqZuWxb5qvXVgXWyXtO2oKteudTYLqzPpQ0e/jc7QQaKaHQ1aIDsJAz/Z/qw6tyE5pmNhRPyhsDKO2VZCrRRJIDyumvw82zM+s9DCONpbcCI8JYZKrNjM4gBMhhWvjvTHAo2ceZaQ/QI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954560; 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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=bcvnvVJoE5XYpkkYLdY/36Vds/J4Eu0RKogC8hkAKYU=; b=R1ylCk1Xwn3slAxR5h7Gr1ice6bzF1+VZsVVvL0eU4jdqqVVXs8dgIbwWGgMGmBbtnI5okJB16naZdLsVVQ4VcL8eGUJva2evHd4L1DImxprxYX+sTlUbdWX4TwhAUxxYE5FfWplxWaG50do8LMTqQ/nruTRRfAPKaiaEpDarw0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954560863677.4448466058609; Sat, 7 Mar 2026 23:22:40 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8T5-0005e4-OL; Sun, 08 Mar 2026 03:22:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8Rx-0002xA-TM for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:21:18 -0400 Received: from mail-dl1-x1243.google.com ([2607:f8b0:4864:20::1243]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8Rv-0003OG-NA for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:21:17 -0400 Received: by mail-dl1-x1243.google.com with SMTP id a92af1059eb24-126ea4e9694so4374397c88.1 for ; Sat, 07 Mar 2026 23:21:15 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.21.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:21:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954474; x=1773559274; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=bcvnvVJoE5XYpkkYLdY/36Vds/J4Eu0RKogC8hkAKYU=; b=MJKha3SgFA5Tj2E5mB0OtcpX8zF2A7DgBp3skZEcTSIGW0KjcVZbcDwjxo/6rbHYIO SFraSPqEEQwI8RFk0jUjFOY0XNpQg+sGIsYBv1IPgXf5myRTtVcnbtAj74aftMyCkATH /Md8RKfgXRWUOmhZ7Jn/h9V/9/+CucUZTDkBszfKUbDdkKxtE8qN6/mHf/mMGVnkGrZY d1Li8HL10O0iftxk1xTgumGktrtimIfmrIL13eZI6aHauxW2gM88qgYyl0kP3Ra66cfN Jc6aiproqN9F80PHWLnftI4Bpwa9+eJ+j7zSh55k+tSSGHEBPLVkeKU7U7qoJE2eBPAW YYcw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954474; x=1773559274; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=bcvnvVJoE5XYpkkYLdY/36Vds/J4Eu0RKogC8hkAKYU=; b=GjKfi+aTzEi+nVdhU8BtZ4rjIlCfwG2YxyH71uU6Ji62XmnTjxrNzlPgzr+d64PdHn ePw6MgXZO/R0OsWhXAk5KIm+E6siQjnqzc0UD4d/WuhrJfdppBxroCPPKUa771dsuCQT Fii9p7kqnrUcGhwJZSkZ7Lt++2MxJjLr9PR2VWkMWhlwApJi/lztBxsnE03MYS3qtcSi MlNZtyDVyAlxBU1qzLPJ/sdI8H/aFWZVb5+xB5JxT8/sth0NaYvT0cx2GA/QxRwsHkPH SGqwmK65z0XYqI9Tgj9kY8U38s6PLwHxNfs3t4G5o5pBObg0FsENPNJZWYs9X3y2GB1M rbIA== X-Forwarded-Encrypted: i=1; AJvYcCV8ZtxUwhUGCZtp98RQi38LUcaNCOfh7jkJiSPPwRHzyawtUNAv+ApS4CplXEIHR2iXzBVBPRzaBx+J@nongnu.org X-Gm-Message-State: AOJu0YyhNFEqpp+Sa4oYE5bIRTkQLYJk/kcVPLTjgQittgxyvpYpbOEC t80ZZRCqum8yV0Ug15an73s5+2x/pRQB9/x7qkv2UQBcDMnvrlgraPzR X-Gm-Gg: ATEYQzxkv282bfVDCI/SnNqwp/sokDz3jS3l/G4yOTfynECP7+vWp/CbmaaHtu95WvI kDOJXL+ILxOIqoz2B08i5rWbno0Ls3sB6Kk1OzukaRemBn/l6Sgm/4cI26ipv1OFi5z8dTerupR K67bTQQJUjAUnCbPBQnUmDzWL3hCaY89zqJPzEU8DKO7QbjmQMh19iRitBrydH7GYiKrpH3BqA+ Z/USMuel6TtxfOXXUjaIX7DnPwICQ6B1BqNv+tOmlyXQhIy1ZD/0jHCiSKe+rtiKnORWsN/3N/U VSHTwVzYW8/XedD8/UfCV71iX50UxSkgXqducCWGJonP3RvEMExk0Gu11yPa4JiSv9W1+tniNs5 fS6LQURfOWomX50HIvQuKZkRpfOp4R60PN7rngLikbKZ+d9SH8a9oTYKzluCDpt6t+8db6DxcGr EWWnnuaRH2buQY0ej+2r/pH7OHJZ3o4v2a3X9u/dTFSdkIi5P/IUcn+V4MFFUQmkZUdyGR82YNf uZRL33GVt2oFJ5DvQG0VtTQQAE= X-Received: by 2002:a05:7022:b81:b0:128:d4be:7428 with SMTP id a92af1059eb24-128d4be781dmr204892c88.19.1772954474197; Sat, 07 Mar 2026 23:21:14 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 27/28] tests/qtest: add DM TCG halt and register access tests Date: Sun, 8 Mar 2026 15:17:30 +0800 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1243; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dl1-x1243.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954563576154100 Add TCG-mode helper functions that boot a real CPU and interact with the Debug Module through clock stepping, then add the first batch of TCG tests: tcg/halt-dpc =E2=80=93 halt via HALTREQ, verify DPC/DCSR tcg/resethaltreq-priority =E2=80=93 resethaltreq takes effect on reset tcg/gpr-rw =E2=80=93 read/write GPRs via abstract cmds tcg/fpr-rw =E2=80=93 read/write FPRs via abstract cmds rv32-gpr64-notsup =E2=80=93 64-bit GPR access rejected on RV32 tcg/command-ignored-on-cmderr =E2=80=93 sticky cmderr blocks new cmds Signed-off-by: Chao Liu --- tests/qtest/riscv-dm-test.c | 355 ++++++++++++++++++++++++++++++++++++ 1 file changed, 355 insertions(+) diff --git a/tests/qtest/riscv-dm-test.c b/tests/qtest/riscv-dm-test.c index 1b1ab02284..2e7c29ed7c 100644 --- a/tests/qtest/riscv-dm-test.c +++ b/tests/qtest/riscv-dm-test.c @@ -213,6 +213,139 @@ static void sim_cpu_exception(QTestState *qts) rom_write32(qts, ROM_EXCP, 0); } =20 +/* TCG-mode helpers: real CPU execution with clock stepping. */ + +static QTestState *tcg_dm_init(void) +{ + const char *arch =3D qtest_get_arch(); + const char *cpu_type =3D strstr(arch, "64") ? "rv64" : "rv32"; + g_autofree char *args =3D g_strdup_printf( + "-machine virt -accel tcg -smp 1 -cpu %s,sdext=3Dtrue", cpu_type); + QTestState *qts =3D qtest_init(args); + + /* Check VM status */ + QDict *resp =3D qtest_qmp(qts, "{'execute': 'query-status'}"); + const QDict *ret =3D qdict_get_qdict(resp, "return"); + bool running =3D qdict_get_bool(ret, "running"); + const char *vm_status =3D qdict_get_str(ret, "status"); + g_test_message("VM status: %s running=3D%d", vm_status, running); + qobject_unref(resp); + + if (!running) { + resp =3D qtest_qmp(qts, "{'execute': 'cont'}"); + g_test_message("Sent cont"); + qobject_unref(resp); + } + + /* Let the CPU boot via MTTCG thread */ + g_usleep(TCG_BOOT_US); + + dm_set_active(qts); + return qts; +} + +static bool tcg_wait_for_halt(QTestState *qts) +{ + for (int t =3D 0; t < TCG_POLL_TIMEOUT_US; t +=3D TCG_POLL_STEP_US) { + g_usleep(TCG_POLL_STEP_US); + uint32_t st =3D dm_read(qts, A_DMSTATUS); + if (t < TCG_POLL_STEP_US * 5) { + g_test_message("halt poll: DMSTATUS=3D0x%08x", st); + } + if (st & DMSTATUS_ALLHALTED) { + return true; + } + } + return false; +} + +static bool tcg_wait_for_cmd_done(QTestState *qts) +{ + for (int t =3D 0; t < TCG_POLL_TIMEOUT_US; t +=3D TCG_POLL_STEP_US) { + g_usleep(TCG_POLL_STEP_US); + if (!(dm_read(qts, A_ABSTRACTCS) & ABSTRACTCS_BUSY)) { + return true; + } + } + return false; +} + +static bool tcg_halt_hart(QTestState *qts) +{ + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE | DMCONTROL_HALTREQ); + return tcg_wait_for_halt(qts); +} + +static bool tcg_resume_hart(QTestState *qts) +{ + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE | DMCONTROL_RESUMEREQ); + for (int t =3D 0; t < TCG_POLL_TIMEOUT_US; t +=3D TCG_POLL_STEP_US) { + g_usleep(TCG_POLL_STEP_US); + if (dm_read(qts, A_DMSTATUS) & DMSTATUS_ALLRESUMEACK) { + return true; + } + } + return false; +} + + +/* + * Read a register via Access Register abstract command. + * Returns true on success, false on error or timeout. + */ +static bool tcg_abstract_read_reg(QTestState *qts, uint32_t regno, + uint32_t *val) +{ + dm_write(qts, A_ABSTRACTCS, ABSTRACTCS_CMDERR_MASK); + + uint32_t cmd =3D (0u << 24) | /* cmdtype =3D Access Register */ + (1u << 17) | /* transfer =3D 1 */ + (2u << 20) | /* aarsize =3D 32-bit */ + (regno & 0xFFFF); + dm_write(qts, A_COMMAND, cmd); + + if (!tcg_wait_for_cmd_done(qts)) { + return false; + } + + uint32_t acs =3D dm_read(qts, A_ABSTRACTCS); + if (acs & ABSTRACTCS_CMDERR_MASK) { + return false; + } + + *val =3D dm_read(qts, A_DATA0); + return true; +} + +/* + * Write a register via Access Register abstract command. + * Returns true on success, false on error or timeout. + */ +static bool tcg_abstract_write_reg(QTestState *qts, uint32_t regno, + uint32_t val) +{ + dm_write(qts, A_ABSTRACTCS, ABSTRACTCS_CMDERR_MASK); + dm_write(qts, A_DATA0, val); + + uint32_t cmd =3D (0u << 24) | /* cmdtype =3D Access Register */ + (1u << 17) | /* transfer =3D 1 */ + (1u << 16) | /* write =3D 1 */ + (2u << 20) | /* aarsize =3D 32-bit */ + (regno & 0xFFFF); + dm_write(qts, A_COMMAND, cmd); + + if (!tcg_wait_for_cmd_done(qts)) { + return false; + } + + uint32_t acs =3D dm_read(qts, A_ABSTRACTCS); + return !(acs & ABSTRACTCS_CMDERR_MASK); +} + +/* + * Write a 64-bit register via Access Register abstract command (aarsize= =3D3). + * DATA1 holds high 32 bits, DATA0 holds low 32 bits. + */ =20 /* * Test: dmactive gate. @@ -930,6 +1063,218 @@ static void test_haltsum1_window(void) * 4. Read DPC via abstract command =E2=86=92 verify it's a valid address * 5. Resume CPU, then re-halt to verify the cycle works */ +static void test_tcg_halt_dpc(void) +{ + QTestState *qts =3D tcg_dm_init(); + + /* Halt the CPU */ + g_assert_true(tcg_halt_hart(qts)); + + uint32_t status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ALLHALTED, =3D=3D, DMSTATUS_ALLHALT= ED); + g_assert_cmpuint(status & DMSTATUS_ANYRUNNING, =3D=3D, 0); + + /* Read DCSR: verify cause =3D HALTREQ (3) */ + uint32_t dcsr; + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DCSR, &dcsr)); + uint32_t cause =3D (dcsr & DCSR_CAUSE_MASK) >> DCSR_CAUSE_SHIFT; + g_assert_cmpuint(cause, =3D=3D, DCSR_CAUSE_HALTREQ); + + /* Read DPC: implementation dependent, but it must stay aligned. */ + uint32_t dpc; + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DPC, &dpc)); + g_assert_cmpuint(dpc & 1u, =3D=3D, 0); + + /* Resume the CPU */ + g_assert_true(tcg_resume_hart(qts)); + status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ALLRESUMEACK, =3D=3D, + DMSTATUS_ALLRESUMEACK); + + /* Let it run a bit, then re-halt */ + g_usleep(TCG_BOOT_US); + + g_assert_true(tcg_halt_hart(qts)); + + /* DPC after re-halt is also execution dependent; only assert alignmen= t */ + uint32_t dpc2; + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DPC, &dpc2)); + g_assert_cmpuint(dpc2 & 1u, =3D=3D, 0); + + /* DCSR cause should be HALTREQ again */ + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DCSR, &dcsr)); + cause =3D (dcsr & DCSR_CAUSE_MASK) >> DCSR_CAUSE_SHIFT; + g_assert_cmpuint(cause, =3D=3D, DCSR_CAUSE_HALTREQ); + + qtest_quit(qts); +} + +/* + * Test: reset-haltreq and haltreq asserted together. + * + * Priority per Debug Spec v1.0 Table 4.2 requires reset-haltreq (cause=3D= 5) + * to win over haltreq (cause=3D3). + */ +static void test_tcg_resethaltreq_priority(void) +{ + QTestState *qts =3D tcg_dm_init(); + uint32_t status, dcsr, cause; + + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE | DMCONTROL_SETRESETHALT= REQ); + + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE | + DMCONTROL_HARTRESET | DMCONTROL_HALTREQ); + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE | DMCONTROL_HALTREQ); + + g_assert_true(tcg_wait_for_halt(qts)); + status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ALLHALTED, =3D=3D, DMSTATUS_ALLHALT= ED); + + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DCSR, &dcsr)); + cause =3D (dcsr & DCSR_CAUSE_MASK) >> DCSR_CAUSE_SHIFT; + g_assert_cmpuint(cause, =3D=3D, DCSR_CAUSE_RESET); + + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE | + DMCONTROL_CLRRESETHALTREQ | DMCONTROL_HALTR= EQ); + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE); + + qtest_quit(qts); +} + +/* + * Test: Read/Write all 32 GPR registers via abstract commands (TCG). + * + * For each GPR x0..x31: + * - x0: hardwired to 0, read should return 0 + * - x1..x31: write a test pattern, read back and verify + */ +static void test_tcg_gpr_rw(void) +{ + QTestState *qts =3D tcg_dm_init(); + + g_assert_true(tcg_halt_hart(qts)); + + /* x0 is hardwired to 0 */ + uint32_t val; + g_assert_true(tcg_abstract_read_reg(qts, REGNO_GPR(0), &val)); + g_assert_cmpuint(val, =3D=3D, 0); + + /* x1..x31: write test patterns and read back */ + for (int i =3D 1; i < 32; i++) { + uint32_t pattern =3D 0xA5000000u | (uint32_t)i; + + g_assert_true(tcg_abstract_write_reg(qts, REGNO_GPR(i), pattern)); + g_assert_true(tcg_abstract_read_reg(qts, REGNO_GPR(i), &val)); + g_assert_cmpuint(val, =3D=3D, pattern); + } + + /* Verify x0 is still 0 after all writes */ + g_assert_true(tcg_abstract_read_reg(qts, REGNO_GPR(0), &val)); + g_assert_cmpuint(val, =3D=3D, 0); + + qtest_quit(qts); +} + +/* + * Test: Read/Write all 32 FPR registers via abstract commands (TCG). + * + * For each FPR f0..f31: + * - Write a 32-bit test pattern (single-precision view) + * - Read back and verify + */ +static void test_tcg_fpr_rw(void) +{ + QTestState *qts =3D tcg_dm_init(); + + g_assert_true(tcg_halt_hart(qts)); + + uint32_t val; + + for (int i =3D 0; i < 32; i++) { + uint32_t pattern =3D 0x3F800000u + (uint32_t)i; /* 1.0f + i */ + + g_assert_true(tcg_abstract_write_reg(qts, REGNO_FPR(i), pattern)); + g_assert_true(tcg_abstract_read_reg(qts, REGNO_FPR(i), &val)); + g_assert_cmpuint(val, =3D=3D, pattern); + } + + qtest_quit(qts); +} + +/* + * Test: RV32 rejects 64-bit GPR abstract accesses at command decode time. + */ +static void test_rv32_gpr64_notsup(void) +{ + QTestState *qts; + uint32_t acs; + const char *arch =3D qtest_get_arch(); + + if (!strstr(arch, "32")) { + g_test_skip("RV32-only"); + return; + } + + qts =3D qtest_init("-machine virt"); + + dm_set_active(qts); + dm_write(qts, A_DMCONTROL, DMCONTROL_DMACTIVE | DMCONTROL_HALTREQ); + sim_cpu_halt_ack(qts, 0); + dm_write(qts, A_ABSTRACTCS, ABSTRACTCS_CMDERR_MASK); + + dm_write(qts, A_COMMAND, + (0u << 24) | (1u << 17) | (3u << 20) | REGNO_GPR(1)); + + acs =3D dm_read(qts, A_ABSTRACTCS); + g_assert_cmpuint(acs & ABSTRACTCS_BUSY, =3D=3D, 0); + g_assert_cmpuint((acs & ABSTRACTCS_CMDERR_MASK) >> + ABSTRACTCS_CMDERR_SHIFT, =3D=3D, 2); + + qtest_quit(qts); +} + +/* + * Test: COMMAND writes are ignored while CMDERR is non-zero. + */ +static void test_tcg_command_ignored_on_cmderr(void) +{ + QTestState *qts =3D tcg_dm_init(); + + g_assert_true(tcg_halt_hart(qts)); + + /* Baseline last command: read x0, result must be 0. */ + dm_write(qts, A_ABSTRACTCS, ABSTRACTCS_CMDERR_MASK); + dm_write(qts, A_COMMAND, + (0u << 24) | (1u << 17) | (2u << 20) | REGNO_GPR(0)); + g_assert_true(tcg_wait_for_cmd_done(qts)); + g_assert_cmpuint(dm_read(qts, A_DATA0), =3D=3D, 0); + + /* Latch cmderr with an unsupported command. */ + dm_write(qts, A_COMMAND, 0xFF000000); + uint32_t acs =3D dm_read(qts, A_ABSTRACTCS); + g_assert_cmpuint((acs & ABSTRACTCS_CMDERR_MASK) >> + ABSTRACTCS_CMDERR_SHIFT, =3D=3D, 2); + + /* + * This command must be ignored because cmderr !=3D 0. + * If it incorrectly overwrites last_cmd, later autoexec will read DCS= R. + */ + dm_write(qts, A_COMMAND, + (0u << 24) | (1u << 17) | (2u << 20) | REGNO_DCSR); + + dm_write(qts, A_ABSTRACTCS, ABSTRACTCS_CMDERR_MASK); + dm_write(qts, A_ABSTRACTAUTO, 0x1); /* autoexec on data0 */ + dm_write(qts, A_DATA0, 0xDEADBEEF); /* triggers autoexec of last_cm= d */ + + g_assert_true(tcg_wait_for_cmd_done(qts)); + acs =3D dm_read(qts, A_ABSTRACTCS); + g_assert_cmpuint((acs & ABSTRACTCS_CMDERR_MASK) >> + ABSTRACTCS_CMDERR_SHIFT, =3D=3D, 2); + g_assert_cmpuint(dm_read(qts, A_DATA0), =3D=3D, 0xDEADBEEF); + + qtest_quit(qts); +} + =20 /* * Test: Halt and resume cycle via ROM simulation. @@ -1008,5 +1353,15 @@ int main(int argc, char *argv[]) qtest_add_func("/riscv-dm/abstract-cmd-exception", test_abstract_cmd_exception); =20 + /* TCG-mode tests: real CPU execution */ + qtest_add_func("/riscv-dm/tcg/halt-dpc", test_tcg_halt_dpc); + qtest_add_func("/riscv-dm/tcg/resethaltreq-priority", + test_tcg_resethaltreq_priority); + qtest_add_func("/riscv-dm/tcg/gpr-rw", test_tcg_gpr_rw); + qtest_add_func("/riscv-dm/tcg/fpr-rw", test_tcg_fpr_rw); + qtest_add_func("/riscv-dm/rv32-gpr64-notsup", test_rv32_gpr64_notsup); + qtest_add_func("/riscv-dm/tcg/command-ignored-on-cmderr", + test_tcg_command_ignored_on_cmderr); + return g_test_run(); } --=20 2.53.0 From nobody Sat Apr 11 21:29:17 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1772954614; cv=none; d=zohomail.com; s=zohoarc; b=D8yiJ1Ci13SgvtvwwjWcDgBWthaev5qJIer9pque5+J9lzgbXU6Zhc/sj/N5Iaz2p2fEQuU+vx8Decsb0m/hOZS+abgz+4A1JBS+xQqrL/e0QcaQwLTAQnj1kcpuzvm6HgGiYnWkxOHhqmTRKAV/e0p5FWNl4nxdU1q72gF8zps= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772954614; 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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=a3qLbUC44VdhutdRCzgiU5V4BeYTIqYuq+q3+7FdlOk=; b=F7EMaPJ/1AWfNeKOetED0F4EmPr8sjUU4G35vOa/yI0WWlyx7wBHfaIpQZKtvgzgyf9nVKPy/RLDoYXe/Rb0hHXhqJLP6HEs5TleTuKGoshzyXxex+TC+8ekbYEjn7/lOTgsmsTNB0IwC0Ekz3m8/5PeWI/R71g0iUVx8OQWHk4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772954614234568.7402684911094; Sat, 7 Mar 2026 23:23:34 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vz8Sy-0004n2-La; Sun, 08 Mar 2026 03:22:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vz8S8-00039L-5B for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:21:29 -0400 Received: from mail-dy1-x1342.google.com ([2607:f8b0:4864:20::1342]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vz8S2-0003Uc-AG for qemu-devel@nongnu.org; Sun, 08 Mar 2026 03:21:25 -0400 Received: by mail-dy1-x1342.google.com with SMTP id 5a478bee46e88-2be3bdfda8eso3687646eec.1 for ; Sat, 07 Mar 2026 23:21:21 -0800 (PST) Received: from ZEVORN-PC.bbrouter ([38.95.120.198]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2be4f984ceasm6014081eec.32.2026.03.07.23.21.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 23:21:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772954481; x=1773559281; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=a3qLbUC44VdhutdRCzgiU5V4BeYTIqYuq+q3+7FdlOk=; b=P91mV6/Pyhvm99zyrWaGsHc8cyCK8rqZ1JnEmEVdEnDSUe0B/Jwtywr8AdLrGk7Ym9 w35IYUYAEYc91zQrfdloc/tDlZLX2g3CoZEYUdQByyVvYgf487mm5tqcKajVnOqXO96f uwYhAiOBOgMclsNLJOZNh++hpup0hgCiCX4f4fn5vnv/XwJIBSG/98QBiCjxPjneBM8i pQRZgyFRGK8APw08dM4xY4QDJ5tHcOZPx9urhQfUP1+U3GKJNH/AHVWSjN09L9eLih9M F+Pw3Fc36XaThT5Bz4rXCYEa+qgpYoIdLRbvAzt46r9idI+NzBIeV1iA++kibtbpNxF/ unhw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772954481; x=1773559281; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=a3qLbUC44VdhutdRCzgiU5V4BeYTIqYuq+q3+7FdlOk=; b=QznY4czdGmQtEkMK43Mp/te3eMxJ8oArxGBh9SJlgk/uMTnLGBSH5ER5mj9i3hv+s6 l+UBHUplA+nwkZ/18SQXseToCdYa4+oMgW2TPiROTveLtwpfeW7IFWzABiIkCSqGd0wM 9iUnxvXD4B61Yv4uqFNxld/K4qgr7qGM1YOsQrQalHLUQdCTlY8lv/o/70y3ovw9mDQ7 7IFxwt+TJlzwQgV/5tO1742CSwPXFRgyszfChBTlrgZo4O8D/J3x+MLlcv+HTNPInqTr VJTEjpoowjAECuKVDe4c6DxvCDXP4pnRjngCZE9lO9Ljg7sDlXNbwuHf3FI2RfcRgk5r hlsQ== X-Forwarded-Encrypted: i=1; AJvYcCV661dtfILbgFNOG5r13AlWar9NPGkdvFBbnLgiUh+P83VOtIMjr3VMmN9djDFJB0FLmPPMH4ohGxoB@nongnu.org X-Gm-Message-State: AOJu0Yx+BVwGrktpIU8D7yNwtcB46Pxp1pwFD06dh4PdJl9aNAfBX8Wh DFH6Pl0ODR5gpv/G9NYKrDjXziN37Tj/RRc4whoOcFMjA7qDibY4bHQk X-Gm-Gg: ATEYQzx4Px04/aoM0vR7w73S3RR7yNnHKUdA7WjBo3S7zKqxj+47pzyM/IWxtzdNKw5 OAFTIyp7Eb87dR5Z65B8WNaALcX+Rc6NbBQ2foIFmS2CyscEfdgNLTZIoLmaBO+EgEnK2wqjIOg CvZRh7Sf7LHJmvMaAM7UcTLEMaMwvDU+9LDwdrXMiEGpdRChtxapDP41PLfOzadGasEdeSRxMAW 4Cr/vJvG1NYAHCC/YE7rNOj4td9l4RU189EtDKv+ZWmS3awWZZVWYQMe6W+3aR09PqO/nFayfe4 YjUiJArUGBpqpZpzlf+/7/A+UZhPz1zox2FGDzHog6qzmbD6E7RTHd6B4ySPmBl266n0bxm20TI xRkSdUNRkO3Nha8C1KVALqsSaEHPba6QylXS5PJN5NiHNF/XWgp34WJE37hBCw1gmXt3FdTMzB8 fkoTB80eFUPFcWfnwnfvkesLOql1nclJrpfZek2OoEi8oxmFdpoTlQxY2ky3a+oFh9eL3aGFHG9 /UhMgYmoN5LqkmsGwgjBMqi+WI= X-Received: by 2002:a05:7301:608a:b0:2be:1946:8587 with SMTP id 5a478bee46e88-2be4de8f969mr2620151eec.9.1772954480839; Sat, 07 Mar 2026 23:21:20 -0800 (PST) From: Chao Liu To: Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , Fabiano Rosas , Laurent Vivier Cc: tangtao1634@phytium.com.cn, qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH v1 28/28] tests/qtest: add DM TCG single-step and trigger tests Date: Sun, 8 Mar 2026 15:17:31 +0800 Message-ID: <815a1695c1a8f39d2d4e131612602c07244bf80e.1772936778.git.chao.liu.zevorn@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1342; envelope-from=chao.liu.zevorn@gmail.com; helo=mail-dy1-x1342.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1772954615784158500 Add the remaining TCG-mode helpers (64-bit register access, resume-and-run, is_rv64) and the second batch of TCG tests: tcg/single-step =E2=80=93 single-step via DCSR.step tcg/postexec-impebreak =E2=80=93 postexec with implicit ebreak tcg/postexec-exception =E2=80=93 abstract cmd exception path tcg/trigger-debug-mode =E2=80=93 mcontrol6 breakpoint fires tcg/load-trigger-debug-mode =E2=80=93 load watchpoint enters debug tcg/store-trigger-debug-mode =E2=80=93 store watchpoint enters debug tcg/itrigger-debug-mode =E2=80=93 instruction trigger enters debug Signed-off-by: Chao Liu --- tests/qtest/riscv-dm-test.c | 547 ++++++++++++++++++++++++++++++++++++ 1 file changed, 547 insertions(+) diff --git a/tests/qtest/riscv-dm-test.c b/tests/qtest/riscv-dm-test.c index 2e7c29ed7c..b2fb47e8f0 100644 --- a/tests/qtest/riscv-dm-test.c +++ b/tests/qtest/riscv-dm-test.c @@ -288,6 +288,15 @@ static bool tcg_resume_hart(QTestState *qts) return false; } =20 +static bool tcg_resume_hart_and_run(QTestState *qts) +{ + if (!tcg_resume_hart(qts)) { + return false; + } + + g_usleep(TCG_BOOT_US); + return true; +} =20 /* * Read a register via Access Register abstract command. @@ -346,6 +355,62 @@ static bool tcg_abstract_write_reg(QTestState *qts, ui= nt32_t regno, * Write a 64-bit register via Access Register abstract command (aarsize= =3D3). * DATA1 holds high 32 bits, DATA0 holds low 32 bits. */ +static bool tcg_abstract_write_reg64(QTestState *qts, uint32_t regno, + uint64_t val) +{ + dm_write(qts, A_ABSTRACTCS, ABSTRACTCS_CMDERR_MASK); + dm_write(qts, A_DATA0, (uint32_t)val); + dm_write(qts, A_DATA1, (uint32_t)(val >> 32)); + + uint32_t cmd =3D (0u << 24) | /* cmdtype =3D Access Register */ + (1u << 17) | /* transfer =3D 1 */ + (1u << 16) | /* write =3D 1 */ + (3u << 20) | /* aarsize =3D 64-bit */ + (regno & 0xFFFF); + dm_write(qts, A_COMMAND, cmd); + + if (!tcg_wait_for_cmd_done(qts)) { + return false; + } + + uint32_t acs =3D dm_read(qts, A_ABSTRACTCS); + return !(acs & ABSTRACTCS_CMDERR_MASK); +} + +/* + * Read a 64-bit register via Access Register abstract command (aarsize=3D= 3). + * DATA0 holds low 32 bits, DATA1 holds high 32 bits. + */ +static bool tcg_abstract_read_reg64(QTestState *qts, uint32_t regno, + uint64_t *val) +{ + dm_write(qts, A_ABSTRACTCS, ABSTRACTCS_CMDERR_MASK); + + uint32_t cmd =3D (0u << 24) | /* cmdtype =3D Access Register */ + (1u << 17) | /* transfer =3D 1 */ + (3u << 20) | /* aarsize =3D 64-bit */ + (regno & 0xFFFF); + dm_write(qts, A_COMMAND, cmd); + + if (!tcg_wait_for_cmd_done(qts)) { + return false; + } + + uint32_t acs =3D dm_read(qts, A_ABSTRACTCS); + if (acs & ABSTRACTCS_CMDERR_MASK) { + return false; + } + + uint32_t lo =3D dm_read(qts, A_DATA0); + uint32_t hi =3D dm_read(qts, A_DATA1); + *val =3D ((uint64_t)hi << 32) | lo; + return true; +} + +static bool is_rv64(void) +{ + return strstr(qtest_get_arch(), "64") !=3D NULL; +} =20 /* * Test: dmactive gate. @@ -1275,6 +1340,475 @@ static void test_tcg_command_ignored_on_cmderr(void) qtest_quit(qts); } =20 +/* + * Test: Single-step via DM. + * + * Verifies the Sdext single-step mechanism end-to-end: + * 1. Halt the hart via HALTREQ + * 2. Read DPC (save initial PC) + * 3. Set DCSR.step =3D 1 via abstract command + * 4. Resume the hart =E2=86=92 CPU executes one instruction =E2=86=92 re-= enters debug mode + * 5. Verify DCSR.cause =3D STEP (4) + * 6. Verify DPC advanced from the initial value + * 7. Step again to confirm repeatability + * 8. Clear DCSR.step, resume, verify hart stays running + */ +static void test_tcg_single_step(void) +{ + QTestState *qts =3D tcg_dm_init(); + + /* Step 1: Halt the hart */ + g_assert_true(tcg_halt_hart(qts)); + uint32_t status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ALLHALTED, =3D=3D, DMSTATUS_ALLHALT= ED); + + /* Step 2: Read initial DPC */ + uint32_t dpc0; + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DPC, &dpc0)); + g_test_message("initial DPC =3D 0x%08x", dpc0); + + /* Step 3: Set DCSR.step =3D 1 */ + uint32_t dcsr; + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DCSR, &dcsr)); + g_test_message("DCSR before step =3D 0x%08x", dcsr); + dcsr |=3D DCSR_STEP; + g_assert_true(tcg_abstract_write_reg(qts, REGNO_DCSR, dcsr)); + + /* Verify step bit is set */ + uint32_t dcsr_check; + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DCSR, &dcsr_check)); + g_assert_cmpuint(dcsr_check & DCSR_STEP, =3D=3D, DCSR_STEP); + + /* Step 4: Resume =E2=86=92 hart executes one instruction =E2=86=92 re= -halts */ + g_assert_true(tcg_resume_hart_and_run(qts)); + g_assert_true(tcg_wait_for_halt(qts)); + + /* Step 5: Verify DCSR.cause =3D STEP (4) */ + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DCSR, &dcsr)); + uint32_t cause =3D (dcsr & DCSR_CAUSE_MASK) >> DCSR_CAUSE_SHIFT; + g_test_message("DCSR after step =3D 0x%08x, cause =3D %u", dcsr, cause= ); + g_assert_cmpuint(cause, =3D=3D, DCSR_CAUSE_STEP); + + /* Step 6: Verify DPC advanced */ + uint32_t dpc1; + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DPC, &dpc1)); + g_test_message("DPC after step =3D 0x%08x", dpc1); + g_assert_cmpuint(dpc1, !=3D, dpc0); + + /* Step 7: Step again to confirm repeatability */ + uint32_t dpc_prev =3D dpc1; + g_assert_true(tcg_resume_hart_and_run(qts)); + g_assert_true(tcg_wait_for_halt(qts)); + + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DCSR, &dcsr)); + cause =3D (dcsr & DCSR_CAUSE_MASK) >> DCSR_CAUSE_SHIFT; + g_assert_cmpuint(cause, =3D=3D, DCSR_CAUSE_STEP); + + uint32_t dpc2; + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DPC, &dpc2)); + g_test_message("DPC after 2nd step =3D 0x%08x", dpc2); + g_assert_cmpuint(dpc2, !=3D, dpc_prev); + + /* Step 8: Clear step bit, resume, verify hart stays running */ + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DCSR, &dcsr)); + dcsr &=3D ~DCSR_STEP; + g_assert_true(tcg_abstract_write_reg(qts, REGNO_DCSR, dcsr)); + + g_assert_true(tcg_resume_hart(qts)); + + /* Give CPU time to run freely, then verify it's still running */ + g_usleep(TCG_BOOT_US); + status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ANYRUNNING, =3D=3D, DMSTATUS_ANYRUN= NING); + g_assert_cmpuint(status & DMSTATUS_ANYHALTED, =3D=3D, 0); + + qtest_quit(qts); +} + +/* + * Test: POSTEXEC completes via the implicit ebreak after Program Buffer. + */ +static void test_tcg_postexec_impebreak(void) +{ + QTestState *qts =3D tcg_dm_init(); + uint32_t cmd, acs, status; + + g_assert_true(tcg_halt_hart(qts)); + + for (int i =3D 0; i < 8; i++) { + dm_write(qts, A_PROGBUF0 + i * 4, 0x00000013); + } + + dm_write(qts, A_ABSTRACTCS, ABSTRACTCS_CMDERR_MASK); + + cmd =3D (0u << 24) | (1u << 18); + dm_write(qts, A_COMMAND, cmd); + + g_assert_true(tcg_wait_for_cmd_done(qts)); + + acs =3D dm_read(qts, A_ABSTRACTCS); + g_assert_cmpuint(acs & ABSTRACTCS_BUSY, =3D=3D, 0); + g_assert_cmpuint(acs & ABSTRACTCS_CMDERR_MASK, =3D=3D, 0); + + status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ALLHALTED, =3D=3D, DMSTATUS_ALLHALT= ED); + + qtest_quit(qts); +} + +/* + * Test: POSTEXEC illegal instruction in Program Buffer. + * + * The hart is in Debug Mode and executes Program Buffer from DM ROM. + * If the first progbuf instruction is illegal, CPU should vector to the + * DM ROM exception entry and DM should latch CMDERR=3DEXCEPTION. + */ +static void test_tcg_postexec_exception(void) +{ + QTestState *qts =3D tcg_dm_init(); + uint32_t cmd, acs, cmderr, status; + + g_assert_true(tcg_halt_hart(qts)); + + /* 0x00000000 is an illegal instruction encoding. */ + dm_write(qts, A_PROGBUF0, 0x00000000); + for (int i =3D 1; i < 8; i++) { + dm_write(qts, A_PROGBUF0 + i * 4, 0x00000013); + } + + dm_write(qts, A_ABSTRACTCS, ABSTRACTCS_CMDERR_MASK); + + cmd =3D (0u << 24) | (1u << 18); + dm_write(qts, A_COMMAND, cmd); + + g_assert_true(tcg_wait_for_cmd_done(qts)); + + acs =3D dm_read(qts, A_ABSTRACTCS); + g_assert_cmpuint(acs & ABSTRACTCS_BUSY, =3D=3D, 0); + cmderr =3D (acs & ABSTRACTCS_CMDERR_MASK) >> ABSTRACTCS_CMDERR_SHIFT; + g_assert_cmpuint(cmderr, =3D=3D, 3); + + status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ALLHALTED, =3D=3D, DMSTATUS_ALLHALT= ED); + + dm_write(qts, A_ABSTRACTCS, ABSTRACTCS_CMDERR_MASK); + + qtest_quit(qts); +} + +/* + * Test: Trigger with action=3Ddebug_mode halts the hart via DM. + * + * Configures an mcontrol (type 2) trigger on the current DPC address with + * action=3D1 (enter debug mode). After resume the CPU hits the trigger a= nd + * re-enters debug mode. Verifies DCSR.cause =3D TRIGGER and DPC matches. + */ +static void test_tcg_trigger_debug_mode(void) +{ + QTestState *qts =3D tcg_dm_init(); + bool rv64 =3D is_rv64(); + const uint64_t code_addr =3D 0x80400000ULL; + const uint32_t nop_insn =3D 0x00000013; + const uint32_t loop_insn =3D 0x0000006f; + + /* Halt the hart */ + g_assert_true(tcg_halt_hart(qts)); + + /* + * Use a fixed code location so the test does not depend on where the = CPU + * happened to be halted during boot. + */ + qtest_writel(qts, code_addr, nop_insn); + qtest_writel(qts, code_addr + 4, loop_insn); + + uint64_t dpc =3D code_addr; + if (rv64) { + g_assert_true(tcg_abstract_write_reg64(qts, REGNO_DPC, dpc)); + } else { + g_assert_true(tcg_abstract_write_reg(qts, REGNO_DPC, (uint32_t)dpc= )); + } + g_test_message("DPC before trigger =3D 0x%lx", (unsigned long)dpc); + + /* Select trigger 1 to verify non-zero trigger index handling */ + g_assert_true(tcg_abstract_write_reg(qts, REGNO_TSELECT, 1)); + + /* + * Configure mcontrol type 2 trigger: + * - type=3D2, action=3D1 (DBG_ACTION_DBG_MODE) + * - match on EXEC in M/S/U modes + * - exact address match (match=3D0) + * + * On RV64 the type field is at bits[63:60] and tdata2 is 64-bit, + * so both require 64-bit abstract commands to avoid sign-extension. + */ + uint64_t tdata1_lo =3D TDATA1_TYPE2_ACTION_DBG | + TDATA1_TYPE2_M | TDATA1_TYPE2_S | TDATA1_TYPE2_U | + TDATA1_TYPE2_EXEC; + if (rv64) { + g_assert_true(tcg_abstract_write_reg64(qts, REGNO_TDATA2, dpc)); + uint64_t tdata1_64 =3D (2ULL << 60) | tdata1_lo; + g_assert_true(tcg_abstract_write_reg64(qts, REGNO_TDATA1, tdata1_6= 4)); + } else { + g_assert_true(tcg_abstract_write_reg(qts, REGNO_TDATA2, (uint32_t)= dpc)); + uint32_t tdata1 =3D TDATA1_TYPE2_TYPE | (uint32_t)tdata1_lo; + g_assert_true(tcg_abstract_write_reg(qts, REGNO_TDATA1, tdata1)); + } + + /* Verify trigger configuration was accepted (low 32 bits) */ + uint32_t td1_rb; + g_assert_true(tcg_abstract_read_reg(qts, REGNO_TDATA1, &td1_rb)); + g_test_message("tdata1 readback low =3D 0x%08x", td1_rb); + g_assert_cmpuint(td1_rb & TDATA1_TYPE2_EXEC, =3D=3D, TDATA1_TYPE2_EXEC= ); + + /* Resume -> CPU tries to execute at DPC -> trigger fires -> debug mod= e */ + g_assert_true(tcg_resume_hart_and_run(qts)); + g_assert_true(tcg_wait_for_halt(qts)); + + /* Verify DCSR.cause =3D TRIGGER (2) */ + uint32_t dcsr; + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DCSR, &dcsr)); + uint32_t cause =3D (dcsr & DCSR_CAUSE_MASK) >> DCSR_CAUSE_SHIFT; + g_test_message("DCSR after trigger =3D 0x%08x, cause =3D %u", dcsr, ca= use); + g_assert_cmpuint(cause, =3D=3D, DCSR_CAUSE_TRIGGER); + + /* Verify DPC is the trigger address */ + uint64_t dpc_after; + if (rv64) { + g_assert_true(tcg_abstract_read_reg64(qts, REGNO_DPC, &dpc_after)); + } else { + uint32_t tmp; + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DPC, &tmp)); + dpc_after =3D tmp; + } + g_test_message("DPC after trigger =3D 0x%lx", (unsigned long)dpc_after= ); + g_assert_cmpuint(dpc_after, =3D=3D, dpc); + + /* Disable trigger: write tdata1 with type=3D2 but no EXEC/LOAD/STORE = bits */ + g_assert_true(tcg_abstract_write_reg(qts, REGNO_TSELECT, 1)); + if (rv64) { + g_assert_true(tcg_abstract_write_reg64(qts, REGNO_TDATA1, + 2ULL << 60)); + } else { + g_assert_true(tcg_abstract_write_reg(qts, REGNO_TDATA1, + TDATA1_TYPE2_TYPE)); + } + + /* + * Advance DPC past the trigger address so resume doesn't re-trigger. + * The loop instruction keeps the hart running at a stable address. + */ + if (rv64) { + g_assert_true(tcg_abstract_write_reg64(qts, REGNO_DPC, dpc + 4)); + } else { + g_assert_true(tcg_abstract_write_reg(qts, REGNO_DPC, + (uint32_t)(dpc + 4))); + } + + /* Resume and verify hart stays running */ + g_assert_true(tcg_resume_hart(qts)); + g_usleep(TCG_BOOT_US); + uint32_t status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ANYRUNNING, =3D=3D, DMSTATUS_ANYRUN= NING); + g_assert_cmpuint(status & DMSTATUS_ANYHALTED, =3D=3D, 0); + + qtest_quit(qts); +} + + +static void test_tcg_watchpoint_trigger_debug_mode(bool store) +{ + QTestState *qts =3D tcg_dm_init(); + bool rv64 =3D is_rv64(); + const uint64_t code_addr =3D 0x80400000ULL; + const uint64_t data_addr =3D 0x80401000ULL; + const uint32_t load_insn =3D 0x0002a383; /* lw x7, 0(x5) */ + const uint32_t store_insn =3D 0x0062a023; /* sw x6, 0(x5) */ + const uint32_t loop_insn =3D 0x0000006f; /* j . */ + const uint32_t data_init =3D 0x11223344; + const uint32_t store_val =3D 0x55667788; + const uint32_t trigger_idx =3D store ? 3 : 2; + uint32_t dcsr, cause, status; + uint64_t tdata1_lo =3D TDATA1_TYPE2_ACTION_DBG | + TDATA1_TYPE2_M | TDATA1_TYPE2_S | TDATA1_TYPE2_U | + (store ? TDATA1_TYPE2_STORE : TDATA1_TYPE2_LOAD); + + g_assert_true(tcg_halt_hart(qts)); + + qtest_writel(qts, code_addr, store ? store_insn : load_insn); + qtest_writel(qts, code_addr + 4, loop_insn); + qtest_writel(qts, data_addr, data_init); + + if (rv64) { + g_assert_true(tcg_abstract_write_reg64(qts, REGNO_GPR(5), data_add= r)); + g_assert_true(tcg_abstract_write_reg64(qts, REGNO_GPR(6), store_va= l)); + g_assert_true(tcg_abstract_write_reg64(qts, REGNO_GPR(7), 0)); + g_assert_true(tcg_abstract_write_reg64(qts, REGNO_DPC, code_addr)); + } else { + g_assert_true(tcg_abstract_write_reg(qts, REGNO_GPR(5), + (uint32_t)data_addr)); + g_assert_true(tcg_abstract_write_reg(qts, REGNO_GPR(6), store_val)= ); + g_assert_true(tcg_abstract_write_reg(qts, REGNO_GPR(7), 0)); + g_assert_true(tcg_abstract_write_reg(qts, REGNO_DPC, + (uint32_t)code_addr)); + } + + g_assert_true(tcg_abstract_write_reg(qts, REGNO_TSELECT, trigger_idx)); + if (rv64) { + g_assert_true(tcg_abstract_write_reg64(qts, REGNO_TDATA2, data_add= r)); + g_assert_true(tcg_abstract_write_reg64(qts, REGNO_TDATA1, + (2ULL << 60) | tdata1_lo)); + } else { + g_assert_true(tcg_abstract_write_reg(qts, REGNO_TDATA2, + (uint32_t)data_addr)); + g_assert_true(tcg_abstract_write_reg(qts, REGNO_TDATA1, + TDATA1_TYPE2_TYPE | + (uint32_t)tdata1_lo)); + } + + g_assert_true(tcg_resume_hart_and_run(qts)); + g_assert_true(tcg_wait_for_halt(qts)); + + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DCSR, &dcsr)); + cause =3D (dcsr & DCSR_CAUSE_MASK) >> DCSR_CAUSE_SHIFT; + g_assert_cmpuint(cause, =3D=3D, DCSR_CAUSE_TRIGGER); + + if (rv64) { + uint64_t dpc; + g_assert_true(tcg_abstract_read_reg64(qts, REGNO_DPC, &dpc)); + g_assert_cmpuint(dpc, =3D=3D, code_addr); + } else { + uint32_t dpc; + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DPC, &dpc)); + g_assert_cmpuint(dpc, =3D=3D, (uint32_t)code_addr); + } + + if (store) { + g_assert_cmpuint(qtest_readl(qts, data_addr), =3D=3D, data_init); + } + + g_assert_true(tcg_abstract_write_reg(qts, REGNO_TSELECT, trigger_idx)); + if (rv64) { + g_assert_true(tcg_abstract_write_reg64(qts, REGNO_TDATA1, 2ULL << = 60)); + g_assert_true(tcg_abstract_write_reg64(qts, REGNO_DPC, code_addr)); + } else { + g_assert_true(tcg_abstract_write_reg(qts, REGNO_TDATA1, + TDATA1_TYPE2_TYPE)); + g_assert_true(tcg_abstract_write_reg(qts, REGNO_DPC, + (uint32_t)code_addr)); + } + + g_assert_true(tcg_resume_hart(qts)); + g_usleep(TCG_BOOT_US); + + if (store) { + g_assert_cmpuint(qtest_readl(qts, data_addr), =3D=3D, store_val); + status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ANYRUNNING, =3D=3D, DMSTATUS_AN= YRUNNING); + } else { + uint64_t load_val; + + g_assert_true(tcg_halt_hart(qts)); + if (rv64) { + g_assert_true(tcg_abstract_read_reg64(qts, REGNO_GPR(7), + &load_val)); + } else { + uint32_t tmp; + + g_assert_true(tcg_abstract_read_reg(qts, REGNO_GPR(7), &tmp)); + load_val =3D tmp; + } + g_assert_cmpuint(load_val, =3D=3D, data_init); + status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ALLHALTED, =3D=3D, DMSTATUS_ALL= HALTED); + } + + qtest_quit(qts); +} + +static void test_tcg_load_trigger_debug_mode(void) +{ + test_tcg_watchpoint_trigger_debug_mode(false); +} + +static void test_tcg_store_trigger_debug_mode(void) +{ + test_tcg_watchpoint_trigger_debug_mode(true); +} + +/* + * Test: itrigger with action=3Ddebug_mode enters Debug Mode. + * + * Configures an itrigger with count=3D1 so the hart executes one instruct= ion, + * re-enters debug mode with cause=3DTRIGGER, and clears the count. + */ +static void test_tcg_itrigger_debug_mode(void) +{ + QTestState *qts =3D tcg_dm_init(); + bool rv64 =3D is_rv64(); + uint64_t dpc; + uint64_t dpc_after; + uint64_t tdata1; + uint32_t dcsr; + uint32_t status; + uint32_t cause; + + g_assert_true(tcg_halt_hart(qts)); + g_assert_true(tcg_abstract_write_reg(qts, REGNO_TSELECT, 1)); + + if (rv64) { + g_assert_true(tcg_abstract_read_reg64(qts, REGNO_DPC, &dpc)); + tdata1 =3D (3ULL << 60) | + TDATA1_ITRIGGER_ACTION_DBG | + TDATA1_ITRIGGER_U | + TDATA1_ITRIGGER_S | + TDATA1_ITRIGGER_M | + TDATA1_ITRIGGER_COUNT(1); + g_assert_true(tcg_abstract_write_reg64(qts, REGNO_TDATA1, tdata1)); + } else { + uint32_t tmp; + + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DPC, &tmp)); + dpc =3D tmp; + tdata1 =3D TDATA1_ITRIGGER_TYPE | + TDATA1_ITRIGGER_ACTION_DBG | + TDATA1_ITRIGGER_U | + TDATA1_ITRIGGER_S | + TDATA1_ITRIGGER_M | + TDATA1_ITRIGGER_COUNT(1); + g_assert_true(tcg_abstract_write_reg(qts, REGNO_TDATA1, + (uint32_t)tdata1)); + } + + g_assert_true(tcg_resume_hart(qts)); + g_assert_true(tcg_wait_for_halt(qts)); + + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DCSR, &dcsr)); + cause =3D (dcsr & DCSR_CAUSE_MASK) >> DCSR_CAUSE_SHIFT; + g_assert_cmpuint(cause, =3D=3D, DCSR_CAUSE_TRIGGER); + + if (rv64) { + g_assert_true(tcg_abstract_read_reg64(qts, REGNO_DPC, &dpc_after)); + g_assert_true(tcg_abstract_read_reg64(qts, REGNO_TDATA1, &tdata1)); + } else { + uint32_t tmp; + + g_assert_true(tcg_abstract_read_reg(qts, REGNO_DPC, &tmp)); + dpc_after =3D tmp; + g_assert_true(tcg_abstract_read_reg(qts, REGNO_TDATA1, &tmp)); + tdata1 =3D tmp; + } + + g_assert_cmpuint(dpc_after, !=3D, dpc); + g_assert_cmpuint(tdata1 & TDATA1_ITRIGGER_COUNT_MASK, =3D=3D, 0); + + g_assert_true(tcg_resume_hart(qts)); + g_usleep(TCG_BOOT_US); + status =3D dm_read(qts, A_DMSTATUS); + g_assert_cmpuint(status & DMSTATUS_ANYRUNNING, =3D=3D, DMSTATUS_ANYRUN= NING); + g_assert_cmpuint(status & DMSTATUS_ANYHALTED, =3D=3D, 0); + + qtest_quit(qts); +} =20 /* * Test: Halt and resume cycle via ROM simulation. @@ -1362,6 +1896,19 @@ int main(int argc, char *argv[]) qtest_add_func("/riscv-dm/rv32-gpr64-notsup", test_rv32_gpr64_notsup); qtest_add_func("/riscv-dm/tcg/command-ignored-on-cmderr", test_tcg_command_ignored_on_cmderr); + qtest_add_func("/riscv-dm/tcg/single-step", test_tcg_single_step); + qtest_add_func("/riscv-dm/tcg/postexec-impebreak", + test_tcg_postexec_impebreak); + qtest_add_func("/riscv-dm/tcg/postexec-exception", + test_tcg_postexec_exception); + qtest_add_func("/riscv-dm/tcg/trigger-debug-mode", + test_tcg_trigger_debug_mode); + qtest_add_func("/riscv-dm/tcg/load-trigger-debug-mode", + test_tcg_load_trigger_debug_mode); + qtest_add_func("/riscv-dm/tcg/store-trigger-debug-mode", + test_tcg_store_trigger_debug_mode); + qtest_add_func("/riscv-dm/tcg/itrigger-debug-mode", + test_tcg_itrigger_debug_mode); =20 return g_test_run(); } --=20 2.53.0