From patchwork Wed Aug 14 08:27:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Brockbank X-Patchwork-Id: 13763089 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 9A812C52D7F for ; Wed, 14 Aug 2024 08:42:32 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1se9aC-0000YX-JF; Wed, 14 Aug 2024 04:42:16 -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 1se9aA-0000Nb-1R; Wed, 14 Aug 2024 04:42:14 -0400 Received: from mx0a-001ae601.pphosted.com ([67.231.149.25] helo=mx0b-001ae601.pphosted.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1se9a8-0005rg-0d; Wed, 14 Aug 2024 04:42:13 -0400 Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 47E5pcFq028298; Wed, 14 Aug 2024 03:42:02 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s= PODMain02222019; bh=ncndYl91D3S6kjKskFlCOb7/iz5xBVK1N21SwFSv9gs=; b= iUGOhi5wb+XLHjZ9kj3K2LSwF1Rhnijol192/G/K+k8EU3NUWkbnA7sFpNrVuMmS t5Jq2aF8HuCgW1GauXL9rfnwPt7K/qzE57dnhzPiCwKLzRMdrRlbtMyj4kU/xBmy BRXloGqRqDamsCYILYLJXfrFCWkYDCg6DiAw9ciGGmvW6oCLupJTY1oO7c86B0a5 o8gSn8mlGwwrcDoS4oJ1R0/5FpQLlNawab2NX5p279iIH9WWo+bl85XVgtDUr5tS iT+XWmH1px+lXUqASfHd0Qjmb/kIhifC/rCbO+mGBc3+NPKmdyaHa9VirlJbuj0b 9CU2vt3S5R+6WHjEW5J2ZA== Received: from ausex01.ad.cirrus.com ([141.131.3.19]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 40x5kwmadk-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 14 Aug 2024 03:42:02 -0500 (CDT) Received: from ausex01.ad.cirrus.com (141.131.37.95) by ausex01.ad.cirrus.com (141.131.37.95) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 14 Aug 2024 03:42:00 -0500 Received: from EDIN7BQBTG3.ad.cirrus.com (141.131.38.212) by anon-ausex01.ad.cirrus.com (141.131.37.95) with Microsoft SMTP Server id 15.2.1544.9 via Frontend Transport; Wed, 14 Aug 2024 03:41:59 -0500 From: Ian Brockbank To: , CC: Palmer Dabbelt , Alistair Francis , Bin Meng , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Ian Brockbank , LIU Zhiwei Subject: [PATCH 01/11] target/riscv: Add CLIC CSR mintstatus Date: Wed, 14 Aug 2024 09:27:31 +0100 Message-ID: <20240814083836.12256-8-Ian.Brockbank@cirrus.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240814083836.12256-1-Ian.Brockbank@cirrus.com> References: <20240814083836.12256-1-Ian.Brockbank@cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: e4Yj6phMfVM674Ik10Ur5RNQpmyHvo-M X-Proofpoint-GUID: e4Yj6phMfVM674Ik10Ur5RNQpmyHvo-M X-Proofpoint-Spam-Reason: orgsafe Received-SPF: pass client-ip=67.231.149.25; envelope-from=prvs=5956f96c7e=ian.brockbank@cirrus.com; helo=mx0b-001ae601.pphosted.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 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, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 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: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Ian Brockbank CSR mintstatus holds the active interrupt level for each supported privilege mode. sintstatus, and user, uintstatus, provide restricted views of mintstatus. Signed-off-by: Ian Brockbank Signed-off-by: LIU Zhiwei --- target/riscv/cpu.h | 3 +++ target/riscv/cpu_bits.h | 11 +++++++++++ target/riscv/csr.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) -- 2.46.0.windows.1 This message and any attachments may contain privileged and confidential information that is intended solely for the person(s) to whom it is addressed. If you are not an intended recipient you must not: read; copy; distribute; discuss; take any action in or make any reliance upon the contents of this message; nor open or read any attachment. If you have received this message in error, please notify us as soon as possible on the following telephone number and destroy this message including any attachments. Thank you. Cirrus Logic International (UK) Ltd and Cirrus Logic International Semiconductor Ltd are companies registered in Scotland, with registered numbers SC089839 and SC495735 respectively. Our registered office is at 7B Nightingale Way, Quartermile, Edinburgh, EH3 9EG, UK. Tel: +44 (0)131 272 7000. www.cirrus.com diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 1619c3acb6..95303f50d3 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -259,6 +259,7 @@ struct CPUArchState { bool software_seip; uint64_t miclaim; + uint64_t mintstatus; /* clic-spec */ uint64_t mie; uint64_t mideleg; @@ -461,6 +462,8 @@ struct CPUArchState { QEMUTimer *vstimer; /* Internal timer for VS-mode interrupt */ bool vstime_irq; + void *clic; /* clic interrupt controller */ + hwaddr kernel_addr; hwaddr fdt_addr; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 32b068f18a..2e65495b54 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -165,6 +165,7 @@ #define CSR_MCAUSE 0x342 #define CSR_MTVAL 0x343 #define CSR_MIP 0x344 +#define CSR_MINTSTATUS 0xfb1 /* clic-spec-draft */ /* Machine-Level Window to Indirectly Accessed Registers (AIA) */ #define CSR_MISELECT 0x350 @@ -206,6 +207,7 @@ #define CSR_SCAUSE 0x142 #define CSR_STVAL 0x143 #define CSR_SIP 0x144 +#define CSR_SINTSTATUS 0xdb1 /* clic-spec-draft */ /* Sstc supervisor CSRs */ #define CSR_STIMECMP 0x14D @@ -733,6 +735,15 @@ typedef enum RISCVException { #define SIP_SEIP MIP_SEIP #define SIP_LCOFIP MIP_LCOFIP +/* mintstatus */ +#define MINTSTATUS_MIL 0xff000000 /* mil[31:24] */ +#define MINTSTATUS_SIL 0x0000ff00 /* sil[15:8] */ +#define MINTSTATUS_UIL 0x000000ff /* uil[7:0] */ + +/* sintstatus */ +#define SINTSTATUS_SIL 0x0000ff00 /* sil[15:8] */ +#define SINTSTATUS_UIL 0x000000ff /* uil[7:0] */ + /* MIE masks */ #define MIE_SEIE (1 << IRQ_S_EXT) #define MIE_UEIE (1 << IRQ_U_EXT) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index ea3560342c..f9ed7b9079 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -578,6 +578,16 @@ static RISCVException debug(CPURISCVState *env, int csrno) return RISCV_EXCP_ILLEGAL_INST; } + +static int clic(CPURISCVState *env, int csrno) +{ + if (env->clic) { + return RISCV_EXCP_NONE; + } + + return RISCV_EXCP_ILLEGAL_INST; +} + #endif static RISCVException seed(CPURISCVState *env, int csrno) @@ -2887,6 +2897,12 @@ static RISCVException rmw_mviph(CPURISCVState *env, int csrno, return ret; } +static int read_mintstatus(CPURISCVState *env, int csrno, target_ulong *val) +{ + *val = env->mintstatus; + return RISCV_EXCP_NONE; +} + /* Supervisor Trap Setup */ static RISCVException read_sstatus_i128(CPURISCVState *env, int csrno, Int128 *val) @@ -3298,6 +3314,14 @@ static RISCVException rmw_siph(CPURISCVState *env, int csrno, return ret; } +static int read_sintstatus(CPURISCVState *env, int csrno, target_ulong *val) +{ + /* sintstatus is a filtered view of mintstatus with the PRV_M removed */ + target_ulong mask = SINTSTATUS_SIL | SINTSTATUS_UIL; + *val = env->mintstatus & mask; + return RISCV_EXCP_NONE; +} + /* Supervisor Protection and Translation */ static RISCVException read_satp(CPURISCVState *env, int csrno, target_ulong *val) @@ -5594,6 +5618,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { write_mhpmcounterh }, [CSR_MHPMCOUNTER31H] = { "mhpmcounter31h", mctr32, read_hpmcounterh, write_mhpmcounterh }, + + /* Machine Mode Core Level Interrupt Controller */ + [CSR_MINTSTATUS] = { "mintstatus", clic, read_mintstatus }, + + /* Supervisor Mode Core Level Interrupt Controller */ + [CSR_SINTSTATUS] = { "sintstatus", clic, read_sintstatus }, + [CSR_SCOUNTOVF] = { "scountovf", sscofpmf, read_scountovf, .min_priv_ver = PRIV_VERSION_1_12_0 }, From patchwork Wed Aug 14 08:27:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Brockbank X-Patchwork-Id: 13763088 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 30D19C3DA4A for ; Wed, 14 Aug 2024 08:42:06 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1se9Zj-0006uY-Ks; Wed, 14 Aug 2024 04:41: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 1se9Zh-0006lb-8h; Wed, 14 Aug 2024 04:41:45 -0400 Received: from mx0b-001ae601.pphosted.com ([67.231.152.168]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1se9Zf-0005pf-A8; Wed, 14 Aug 2024 04:41:44 -0400 Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 47E7SSRd029781; Wed, 14 Aug 2024 03:41:36 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s= PODMain02222019; bh=8+MWTdLJRX6DJEFL6fYcpdlaMSw1KJielO7I/ehLkJc=; b= MMUdgCCaBQmUhq0KW+ep/eh3mAMcnV6cJh2s8KiQ229QUXDKlkhnodqeLiFzEpdu E2ZwFQTAzviFZ5A6IEyqfFv1gSdotpk/XX/PcoHolWqVbHk+7tdm2/a1ov4U3pJD ygGbvM2ZFzBuJ+9Y55qcR/Osgs0aDqGtSS060Khu7t11LVkywzG4VIGogHRB8Ojx azNFnGKTkUaTBcc2sjT477t/KrpSUdXFBMsn1345EAvGEKDvmL2bsVfM+HdZa75K Cio7GQtPtnXhfvOuMQobjhIj5sGZLBRpKUm8bAJBxGvQMCngq9clFpUdbJ6FcnFt Kbjw/bShmSSvWtNSfozmvw== Received: from ausex01.ad.cirrus.com ([141.131.3.19]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 40x4mhmb7j-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 14 Aug 2024 03:41:35 -0500 (CDT) Received: from ausex01.ad.cirrus.com (141.131.37.95) by ausex01.ad.cirrus.com (141.131.37.95) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 14 Aug 2024 03:41:35 -0500 Received: from EDIN7BQBTG3.ad.cirrus.com (141.131.38.212) by anon-ausex01.ad.cirrus.com (141.131.37.95) with Microsoft SMTP Server id 15.2.1544.9 via Frontend Transport; Wed, 14 Aug 2024 03:41:33 -0500 From: Ian Brockbank To: , CC: Palmer Dabbelt , Alistair Francis , Bin Meng , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Ian Brockbank , LIU Zhiwei Subject: [PATCH 02/11] target/riscv: Update CSR xintthresh in CLIC mode Date: Wed, 14 Aug 2024 09:27:29 +0100 Message-ID: <20240814083836.12256-6-Ian.Brockbank@cirrus.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240814083836.12256-1-Ian.Brockbank@cirrus.com> References: <20240814083836.12256-1-Ian.Brockbank@cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: wZS3Z0bjyaBknXA2mHPli4Zigkp-ctlp X-Proofpoint-GUID: wZS3Z0bjyaBknXA2mHPli4Zigkp-ctlp X-Proofpoint-Spam-Reason: orgsafe Received-SPF: pass client-ip=67.231.152.168; envelope-from=prvs=5956f96c7e=ian.brockbank@cirrus.com; helo=mx0b-001ae601.pphosted.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 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, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 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: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Ian Brockbank The interrupt-level threshold (xintthresh) CSR holds an 8-bit field for the threshold level of the associated privilege mode. For horizontal interrupts, only the ones with higher interrupt levels than the threshold level are allowed to preempt. Signed-off-by: Ian Brockbank Signed-off-by: LIU Zhiwei --- target/riscv/cpu.h | 2 ++ target/riscv/cpu_bits.h | 2 ++ target/riscv/csr.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+) -- 2.46.0.windows.1 This message and any attachments may contain privileged and confidential information that is intended solely for the person(s) to whom it is addressed. If you are not an intended recipient you must not: read; copy; distribute; discuss; take any action in or make any reliance upon the contents of this message; nor open or read any attachment. If you have received this message in error, please notify us as soon as possible on the following telephone number and destroy this message including any attachments. Thank you. Cirrus Logic International (UK) Ltd and Cirrus Logic International Semiconductor Ltd are companies registered in Scotland, with registered numbers SC089839 and SC495735 respectively. Our registered office is at 7B Nightingale Way, Quartermile, Edinburgh, EH3 9EG, UK. Tel: +44 (0)131 272 7000. www.cirrus.com diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 95303f50d3..9b5f36ad0a 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -260,6 +260,7 @@ struct CPUArchState { uint64_t miclaim; uint64_t mintstatus; /* clic-spec */ + target_ulong mintthresh; /* clic-spec */ uint64_t mie; uint64_t mideleg; @@ -283,6 +284,7 @@ struct CPUArchState { target_ulong stvec; target_ulong sepc; target_ulong scause; + target_ulong sintthresh; /* clic-spec */ target_ulong mtvec; target_ulong mepc; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 2e65495b54..ad45402370 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -166,6 +166,7 @@ #define CSR_MTVAL 0x343 #define CSR_MIP 0x344 #define CSR_MINTSTATUS 0xfb1 /* clic-spec-draft */ +#define CSR_MINTTHRESH 0x347 /* clic-spec-draft */ /* Machine-Level Window to Indirectly Accessed Registers (AIA) */ #define CSR_MISELECT 0x350 @@ -208,6 +209,7 @@ #define CSR_STVAL 0x143 #define CSR_SIP 0x144 #define CSR_SINTSTATUS 0xdb1 /* clic-spec-draft */ +#define CSR_SINTTHRESH 0x147 /* clic-spec-draft */ /* Sstc supervisor CSRs */ #define CSR_STIMECMP 0x14D diff --git a/target/riscv/csr.c b/target/riscv/csr.c index f9ed7b9079..9c824c0d8f 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -2903,6 +2903,18 @@ static int read_mintstatus(CPURISCVState *env, int csrno, target_ulong *val) return RISCV_EXCP_NONE; } +static int read_mintthresh(CPURISCVState *env, int csrno, target_ulong *val) +{ + *val = env->mintthresh; + return 0; +} + +static int write_mintthresh(CPURISCVState *env, int csrno, target_ulong val) +{ + env->mintthresh = val; + return 0; +} + /* Supervisor Trap Setup */ static RISCVException read_sstatus_i128(CPURISCVState *env, int csrno, Int128 *val) @@ -3322,6 +3334,18 @@ static int read_sintstatus(CPURISCVState *env, int csrno, target_ulong *val) return RISCV_EXCP_NONE; } +static int read_sintthresh(CPURISCVState *env, int csrno, target_ulong *val) +{ + *val = env->sintthresh; + return 0; +} + +static int write_sintthresh(CPURISCVState *env, int csrno, target_ulong val) +{ + env->sintthresh = val; + return 0; +} + /* Supervisor Protection and Translation */ static RISCVException read_satp(CPURISCVState *env, int csrno, target_ulong *val) @@ -5621,9 +5645,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { /* Machine Mode Core Level Interrupt Controller */ [CSR_MINTSTATUS] = { "mintstatus", clic, read_mintstatus }, + [CSR_MINTTHRESH] = { "mintthresh", clic, read_mintthresh, + write_mintthresh }, /* Supervisor Mode Core Level Interrupt Controller */ [CSR_SINTSTATUS] = { "sintstatus", clic, read_sintstatus }, + [CSR_SINTTHRESH] = { "sintthresh", clic, read_sintthresh, + write_sintthresh }, [CSR_SCOUNTOVF] = { "scountovf", sscofpmf, read_scountovf, .min_priv_ver = PRIV_VERSION_1_12_0 }, From patchwork Wed Aug 14 08:27:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ian Brockbank X-Patchwork-Id: 13763086 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id DC35BC3DA4A for ; Wed, 14 Aug 2024 08:40:59 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1se9Ya-0001J4-1B; Wed, 14 Aug 2024 04:40:37 -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 1se9YI-0000qa-Nq; Wed, 14 Aug 2024 04:40:23 -0400 Received: from mx0b-001ae601.pphosted.com ([67.231.152.168]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1se9YD-0005iJ-8U; Wed, 14 Aug 2024 04:40:17 -0400 Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 47E4fos9021737; Wed, 14 Aug 2024 03:40:01 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s= PODMain02222019; bh=sL+ey3cE3vPjAjclDSRNt33eW+0cxYbs7PuO1rgOhWU=; b= I4o2h2bbwT1o81Ow7md74fu3AM02e8rWTnsZ4Fm4zpMb6hi2txXlPnfLKlQ0j6b5 VGFUJvkfIpZ/B+Upeycab3/JxjwgfLIuUbTrbntCbEZPkN8mhyR2jQpGqEjZDCPM vGkQI0crG0BChngHu2xad6g1TMUzUu1p90ZxAagoslRJT9QfVnd+8BJa1Gtq0IWC KSDmwLiHpKtYW+pIQ3IciBJGKqsGIzsDy6cKx6ZQexQGSX2fGwYkwL4s8sL6PDP3 kLv6kRHcglU58lOlytDeFmqsYbmgZjtgyWhoNprVp2Q2E8iHOpfrawRTNt6966C4 i5niDei95xniPrzBzGw5yA== Received: from ausex02.ad.cirrus.com ([141.131.3.21]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 40x4mhmb5a-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 14 Aug 2024 03:40:00 -0500 (CDT) Received: from ausex01.ad.cirrus.com (141.131.37.95) by ausex02.ad.cirrus.com (141.131.37.96) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 14 Aug 2024 03:39:56 -0500 Received: from EDIN7BQBTG3.ad.cirrus.com (141.131.38.212) by anon-ausex01.ad.cirrus.com (141.131.37.95) with Microsoft SMTP Server id 15.2.1544.9 via Frontend Transport; Wed, 14 Aug 2024 03:39:55 -0500 From: Ian Brockbank To: , CC: Palmer Dabbelt , Alistair Francis , Bin Meng , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Ian Brockbank , LIU Zhiwei Subject: [PATCH 03/11] hw/intc: Add CLIC device Date: Wed, 14 Aug 2024 09:27:27 +0100 Message-ID: <20240814083836.12256-4-Ian.Brockbank@cirrus.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240814083836.12256-1-Ian.Brockbank@cirrus.com> References: <20240814083836.12256-1-Ian.Brockbank@cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: 1OJsQ6tGyOyf5n8ncYd1zwbBNK8t694W X-Proofpoint-GUID: 1OJsQ6tGyOyf5n8ncYd1zwbBNK8t694W X-Proofpoint-Spam-Reason: safe Received-SPF: pass client-ip=67.231.152.168; envelope-from=prvs=5956f96c7e=ian.brockbank@cirrus.com; helo=mx0b-001ae601.pphosted.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 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, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 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: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Ian Brockbank The Core-Local Interrupt Controller (CLIC) provides low-latency, vectored, pre-emptive interrupts for RISC-V systems. The CLIC also supports a new Selective Hardware Vectoring feature that allow users to optimize each interrupt for either faster response or smaller code size. Signed-off-by: LIU Zhiwei Signed-off-by: Ian Brockbank --- hw/intc/Kconfig | 3 + hw/intc/meson.build | 3 +- hw/intc/riscv_clic.c | 1037 ++++++++++++++++++++++++++++++++++ hw/riscv/Kconfig | 1 + include/hw/intc/riscv_clic.h | 213 +++++++ target/riscv/cpu.h | 2 + target/riscv/cpu_bits.h | 17 + 7 files changed, 1275 insertions(+), 1 deletion(-) create mode 100644 hw/intc/riscv_clic.c create mode 100644 include/hw/intc/riscv_clic.h -- 2.46.0.windows.1 This message and any attachments may contain privileged and confidential information that is intended solely for the person(s) to whom it is addressed. If you are not an intended recipient you must not: read; copy; distribute; discuss; take any action in or make any reliance upon the contents of this message; nor open or read any attachment. If you have received this message in error, please notify us as soon as possible on the following telephone number and destroy this message including any attachments. Thank you. Cirrus Logic International (UK) Ltd and Cirrus Logic International Semiconductor Ltd are companies registered in Scotland, with registered numbers SC089839 and SC495735 respectively. Our registered office is at 7B Nightingale Way, Quartermile, Edinburgh, EH3 9EG, UK. Tel: +44 (0)131 272 7000. www.cirrus.com diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig index dd405bdb5d..1cd4c2f58c 100644 --- a/hw/intc/Kconfig +++ b/hw/intc/Kconfig @@ -81,6 +81,9 @@ config SIFIVE_PLIC bool select MSI_NONBROKEN +config RISCV_CLIC + bool + config GOLDFISH_PIC bool diff --git a/hw/intc/meson.build b/hw/intc/meson.build index f4d81eb8e4..6e0df09265 100644 --- a/hw/intc/meson.build +++ b/hw/intc/meson.build @@ -61,7 +61,8 @@ specific_ss.add(when: 'CONFIG_RISCV_ACLINT', if_true: files('riscv_aclint.c')) specific_ss.add(when: 'CONFIG_RISCV_APLIC', if_true: files('riscv_aplic.c')) specific_ss.add(when: 'CONFIG_RISCV_IMSIC', if_true: files('riscv_imsic.c')) specific_ss.add(when: 'CONFIG_SIFIVE_PLIC', if_true: files('sifive_plic.c')) -specific_ss.add(when: 'CONFIG_XICS', if_true: files('xics.c', 'xive2.c')) +specific_ss.add(when: 'CONFIG_RISCV_CLIC', if_true: files('riscv_clic.c')) +specific_ss.add(when: 'CONFIG_XICS', if_true: files('xics.c')) specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XICS'], if_true: files('xics_kvm.c')) specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('xics_spapr.c', 'spapr_xive.c')) diff --git a/hw/intc/riscv_clic.c b/hw/intc/riscv_clic.c new file mode 100644 index 0000000000..1800e84dfd --- /dev/null +++ b/hw/intc/riscv_clic.c @@ -0,0 +1,1037 @@ +/* + * RISC-V CLIC(Core Local Interrupt Controller) for QEMU. + * + * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu + * Copyright (c) 2017-2018 SiFive, Inc. + * Copyright (c) 2021 T-Head Semiconductor Co., Ltd. All rights reserved. + * Copyright (c) 2024 Cirrus Logic, Inc and + * Cirrus Logic International Semiconductor Ltd. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * This implementation follows the CLIC 0.9-stable draft at 14 March 2024, + * with the following exceptions and implementation details: + * - the CLIC control registers are memory-mapped as per earlier drafts (in + * particular version 0.9-draft, 20 June 2023) + * - the indirect CSR control in 0.9-stable is not implemented + * - the vector table can be either handler addresses (as per the spec) + or a jump table where each entry is processed as an instruction, + selectable with version number v0.9-jmp + * - each hart is assigned its own CLIC block + * - support for PRV_S and PRV_M is selectable at CLIC instantiation by + * passing in a base address for the given modes; a base address of 0 is + * treated as not supported + * - PRV_S and PRV_U registers are mapped onto the PRV_M controls with + * appropriate filtering for the access mode + * + * The implementation has a RISCVCLICState per hart, with a RISCVCLICView + * for each mode subsidiary to that. Each view knows its access mode and base + * address, as well as the RISCVCLICState with which it is associated. + * + * MMIO accesses go through the view, allowing the appropriate permissions to + * be enforced when accessing the parent RISCVCLICState for the settings. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/log.h" +#include "qemu/main-loop.h" +#include "hw/sysbus.h" +#include "sysemu/qtest.h" +#include "target/riscv/cpu.h" +#include "hw/qdev-properties.h" +#include "hw/intc/riscv_clic.h" + +static const char *modeview_name[] = { + TYPE_RISCV_CLIC "_prv_u", /* PRV_U */ + TYPE_RISCV_CLIC "_prv_s", /* PRV_S */ + NULL, /* reserved */ + TYPE_RISCV_CLIC "_prv_m", /* PRV_M */ +}; + +/* + * The 2-bit trig WARL field specifies the trigger type and polarity for each + * interrupt input. Bit 1, trig[0], is defined as "edge-triggered" + * (0: level-triggered, 1: edge-triggered); while bit 2, trig[1], is defined as + * "negative-edge" (0: positive-edge, 1: negative-edge). (Section 3.6) + */ + +static inline TRIG_TYPE +riscv_clic_get_trigger_type(RISCVCLICState *clic, size_t irq) +{ + return get_field(clic->clicintattr[irq], CLIC_INTATTR_TRIG); +} + +static inline bool +riscv_clic_is_edge_triggered(RISCVCLICState *clic, size_t irq) +{ + TRIG_TYPE trig_type = riscv_clic_get_trigger_type(clic, irq); + return trig_type & CLIC_INTATTR_TRIG_EDGE; +} + +static inline bool +riscv_clic_is_shv_interrupt(RISCVCLICState *clic, size_t irq) +{ + uint32_t shv = get_field(clic->clicintattr[irq], CLIC_INTATTR_SHV); + return shv && clic->shv_enabled; +} + +static uint8_t +riscv_clic_get_interrupt_level(RISCVCLICState *clic, uint8_t intctl) +{ + int nlbits = min(clic->mnlbits, clic->clicintctlbits); + + uint8_t mask_il = ((1 << nlbits) - 1) << (8 - nlbits); + uint8_t mask_padding = (1 << (8 - nlbits)) - 1; + /* unused level bits are set to 1 */ + return (intctl & mask_il) | mask_padding; +} + +static uint8_t +riscv_clic_get_interrupt_priority(RISCVCLICState *clic, uint8_t intctl) +{ + int npbits = clic->clicintctlbits - clic->mnlbits; + uint8_t mask_priority = ((1 << npbits) - 1) << (8 - npbits); + uint8_t mask_padding = (1 << (8 - npbits)) - 1; + + if (npbits < 0) { + return UINT8_MAX; + } + /* unused priority bits are set to 1 */ + return (intctl & mask_priority) | mask_padding; +} + +static void +riscv_clic_intcfg_decode(RISCVCLICState *clic, uint16_t intcfg, + uint8_t *mode, uint8_t *level, + uint8_t *priority) +{ + *mode = intcfg >> 8; + *level = riscv_clic_get_interrupt_level(clic, intcfg & 0xff); + *priority = riscv_clic_get_interrupt_priority(clic, intcfg & 0xff); +} + +static void riscv_clic_next_interrupt(void *opaque) +{ + /* + * Scan active list for highest priority pending interrupts + * comparing against this harts mintstatus register and interrupt + * the core if we have a higher priority interrupt to deliver + */ + RISCVCLICState *clic = (RISCVCLICState *)opaque; + CPUState *cpu = cpu_by_arch_id(clic->hartid); + CPURISCVState *env = cpu ? cpu_env(cpu) : NULL; + + if (!env) { + qemu_log_mask(LOG_GUEST_ERROR, + "aclint-swi: invalid hartid: %u", clic->hartid); + return; + } + + BQL_LOCK_GUARD(); + + int il[4] = { + MAX(get_field(env->mintstatus, MINTSTATUS_UIL), + clic->uintthresh & 0xff), /* PRV_U */ + MAX(get_field(env->mintstatus, MINTSTATUS_SIL), + clic->sintthresh & 0xff), /* PRV_S */ + 0, /* reserved */ + MAX(get_field(env->mintstatus, MINTSTATUS_MIL), + clic->mintthresh & 0xff) /* PRV_M */ + }; + + /* Get sorted list of enabled interrupts for this hart */ + CLICActiveInterrupt *active = clic->active_list; + size_t active_count = clic->active_count; + uint8_t mode, level, priority; + + /* Loop through the enabled interrupts sorted by mode+priority+level */ + while (active_count) { + riscv_clic_intcfg_decode(clic, active->intcfg, &mode, &level, + &priority); + if (mode < env->priv || (mode == env->priv && level < il[mode])) { + /* + * No pending interrupts with high enough mode+priority+level + * break and clear pending interrupt for this hart + */ + break; + } + /* Check pending interrupt with high enough mode+priority+level */ + if (clic->clicintip[active->irq]) { + /* Clean vector edge-triggered pending */ + if (riscv_clic_is_edge_triggered(clic, active->irq) && + riscv_clic_is_shv_interrupt(clic, active->irq)) { + clic->clicintip[active->irq] = 0; + } + /* Post pending interrupt for this hart */ + clic->exccode = active->irq | + mode << RISCV_EXCP_CLIC_MODE_SHIFT | + level << RISCV_EXCP_CLIC_LEVEL_SHIFT; + qemu_set_irq(clic->cpu_irq, 1); + return; + } + /* Check next enabled interrupt */ + active_count--; + active++; + } +} + +/* + * Any interrupt i that is not accessible to S-mode or U-Mode + * appears as hard-wired zeros in clicintip[i], clicintie[i], + * clicintattr[i], and clicintctl[i].(Section 3.9)(Section 3.10) + */ +static bool +riscv_clic_check_visible(RISCVCLICState *clic, int mode, int irq) +{ + uint8_t intattr_mode = get_field(clic->clicintattr[irq], + CLIC_INTATTR_MODE); + + if (!clic->prv_s && !clic->prv_u) { /* M */ + return mode == PRV_M; + } else if (clic->prv_s && clic->prv_u) { /* M/S/U */ + switch (clic->nmbits) { + case 0: + return mode == PRV_M; + case 1: + return (mode == PRV_M) || (intattr_mode <= PRV_S); + case 2: + return mode >= intattr_mode; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "clic: nmbits can only be 0 or 1 or 2 for M/S/U hart"); + exit(1); + } + } else { /* M/S or M/U */ + switch (clic->nmbits) { + case 0: + return mode == PRV_M; + case 1: + return (mode == PRV_M) || (intattr_mode <= PRV_S); + default: + qemu_log_mask(LOG_GUEST_ERROR, + "clic: nmbits can only be 0 or 1 for M/S or M/U hart"); + exit(1); + } + } + return false; +} + +/* + * For level-triggered interrupts, software writes to pending bits are + * ignored completely. (Section 3.4) + */ +static bool +riscv_clic_validate_intip(RISCVCLICState *clic, int irq) +{ + return riscv_clic_is_edge_triggered(clic, irq); +} + +static void +riscv_clic_update_intip(RISCVCLICState *clic, int irq, uint64_t value) +{ + clic->clicintip[irq] = !!value; + riscv_clic_next_interrupt(clic); +} + +/* + * For security purpose, the field can only be set to a privilege + * level that is equal mode to or lower than the currently running + * privilege level.(Section 3.6) + */ +static bool riscv_clic_validate_intattr(RISCVCLICState *clic, uint8_t value) +{ + int mode = extract64(value, CLIC_INTATTR_MODE_SHIFT, + CLIC_INTATTR_MODE_WIDTH); + + if (!qtest_enabled()) { + CPURISCVState *env = cpu_env(current_cpu); + if (env->priv < mode) { + return false; + } + } + return true; +} + +/* + * Work out the effective requested mode based on the number of nmbits. + * + * priv-modes nmbits mode Interpretation + * M 0 xx M-mode interrupt + * + * M/U 0 xx M-mode interrupt + * M/U 1 0x U-mode interrupt + * M/U 1 1x M-mode interrupt + * + * M/S 0 xx M-mode interrupt + * M/S 1 0x S-mode interrupt + * M/S 1 1x M-mode interrupt + * + * M/S/U 0 xx M-mode interrupt + * M/S/U 1 0x S-mode interrupt + * M/S/U 1 1x M-mode interrupt + * M/S/U 2 00 U-mode interrupt + * M/S/U 2 01 S-mode interrupt + * M/S/U 2 10 Reserved + * M/S/U 2 11 M-mode interrupt + * + * M/S/U 3 xx Reserved + */ +static uint8_t riscv_clic_effective_mode(RISCVCLICState *clic, uint8_t intattr) +{ + uint8_t mode = get_field(intattr, CLIC_INTATTR_MODE); + + switch (clic->nmbits) { + case 0: + mode = PRV_M; + break; + + case 1: + if (mode <= PRV_S) { + if (clic->prv_s) { + mode = PRV_S; + } else { + assert(clic->prv_u); + mode = PRV_U; + } + } else { + mode = PRV_M; + } + break; + + case 2: + /* no modification required */ + break; + + default: + /* We validate nmbits so this shouldn't be possible */ + assert(clic->nmbits <= 2); + } + + return mode; +} + +/* Return target interrupt number */ +static int riscv_clic_get_irq(RISCVCLICState *clic, hwaddr addr) +{ + return addr / 4; +} + +/* Encode the priority and IRQ as a single sortable value */ +static inline int riscv_clic_encode_priority(const CLICActiveInterrupt *i) +{ + /* Highest mode+level+priority */ + int priority = (i->intcfg & CLIC_INTCFG_MASK) << CLIC_IRQ_BITS; + /* Highest irq number */ + int irq = i->irq & CLIC_IRQ_MASK; + /* Combined */ + return priority | irq; +} + +static int riscv_clic_active_compare(const void *a, const void *b) +{ + return riscv_clic_encode_priority(b) - riscv_clic_encode_priority(a); +} + +static void +riscv_clic_update_intie(RISCVCLICState *clic, int mode, + int irq, uint64_t new_intie) +{ + CLICActiveInterrupt *active_list = clic->active_list; + + uint8_t old_intie = clic->clicintie[irq]; + clic->clicintie[irq] = !!new_intie; + + /* Add to or remove from list of active interrupts */ + if (new_intie && !old_intie) { + uint16_t intcfg = (mode << CLIC_INTCFG_MODE_SHIFT) | + clic->clicintctl[irq]; + active_list[clic->active_count].intcfg = intcfg; + active_list[clic->active_count].irq = irq; + clic->active_count++; + } else if (!new_intie && old_intie) { + CLICActiveInterrupt key = { + (mode << 8) | clic->clicintctl[irq], irq + }; + CLICActiveInterrupt *result = bsearch(&key, + active_list, clic->active_count, + sizeof(CLICActiveInterrupt), + riscv_clic_active_compare); + assert(result); + size_t elem = result - active_list; + size_t sz = --clic->active_count - elem; + memmove(&result[0], &result[1], sz); + } + + /* Sort list of active interrupts */ + qsort(active_list, clic->active_count, + sizeof(CLICActiveInterrupt), + riscv_clic_active_compare); + + riscv_clic_next_interrupt(clic); +} + +static void +riscv_clic_hart_write(RISCVCLICState *clic, hwaddr addr, + uint64_t value, unsigned size, + int mode, int irq) +{ + int req = extract32(addr, 0, 2); + + /* visibility is checked in riscv_clic_write */ + + if (irq >= clic->num_sources) { + qemu_log_mask(LOG_GUEST_ERROR, + "clic: invalid irq %u: 0x%" HWADDR_PRIx "\n", irq, addr); + return; + } + + switch (req) { + case 0: /* clicintip[i] */ + if (riscv_clic_validate_intip(clic, irq)) { + /* + * The actual pending bit is located at bit 0 (i.e., the + * least significant bit). In case future extensions expand the bit + * field, from FW perspective clicintip[i]=zero means no interrupt + * pending, and clicintip[i]!=0 (not just 1) indicates an + * interrupt is pending. (Section 3.4) + */ + if (value != clic->clicintip[irq]) { + riscv_clic_update_intip(clic, irq, value); + } + } + /* Handle a 32-bit write */ + if (size > 1) { + unsigned width = min(size, 4); + unsigned i; + for (i = 1; i < width; i++) { + uint64_t local_value = (value >> (i * 8)) & 0xFF; + riscv_clic_hart_write(clic, addr + i, local_value, + 1, mode, irq); + } + } + break; + + case 1: /* clicintie[i] */ + if (clic->clicintie[irq] != value) { + riscv_clic_update_intie(clic, mode, irq, value); + } + break; + + case 2: /* clicintattr[i] */ + uint8_t field_mode = riscv_clic_effective_mode(clic, value); + if (PRV_RESERVED == field_mode) { + field_mode = get_field(clic->clicintattr[irq], + CLIC_INTATTR_MODE); + } + value = set_field(value, CLIC_INTATTR_MODE, field_mode); + if (riscv_clic_validate_intattr(clic, value)) { + if (clic->clicintattr[irq] != value) { + clic->clicintattr[irq] = value; + riscv_clic_next_interrupt(clic); + } + } + break; + + case 3: /* clicintctl[i] */ + if (value != clic->clicintctl[irq]) { + clic->clicintctl[irq] = value; + riscv_clic_next_interrupt(clic); + } + break; + } +} + +static uint64_t +riscv_clic_hart_read(RISCVCLICState *clic, hwaddr addr, unsigned size, + int mode, int irq) +{ + int req = extract32(addr, 0, 2); + int i; + + /* visibility is checked in riscv_clic_read */ + + if (irq >= clic->num_sources) { + qemu_log_mask(LOG_GUEST_ERROR, + "clic: invalid irq %u: 0x%" HWADDR_PRIx "\n", irq, addr); + return 0; + } + + switch (req) { + case 0: /* clicintip[i] */ + uint64_t retval = clic->clicintip[irq]; + if (size > 1) { + /* Handle a multi-part read */ + for (i = 1; i < size; ++i) { + uint64_t subval = + (riscv_clic_hart_read(clic, addr + i, 1, mode, irq) & 0xFF); + retval |= subval << (i * 8); + } + } + return retval; + + case 1: /* clicintie[i] */ + return clic->clicintie[irq]; + case 2: /* clicintattr[i] */ + /* + * clicintattr register layout + * Bits Field + * 7:6 mode + * 5:3 reserved (WPRI 0) + * 2:1 trig + * 0 shv + */ + uint8_t intattr = clic->clicintattr[irq] & CLIC_INTATTR_MASK; + int field_mode = riscv_clic_effective_mode(clic, intattr); + intattr = set_field(intattr, CLIC_INTATTR_MODE, field_mode); + return intattr; + + case 3: /* clicintctl[i] */ + /* + * The implemented bits are kept left-justified in the most-significant + * bits of each 8-bit clicintctl[i] register, with the lower + * unimplemented bits treated as hardwired to 1.(Section 3.7) + */ + return clic->clicintctl[irq] | + ((1 << (8 - clic->clicintctlbits)) - 1); + } + + return 0; +} + +static void +riscv_clic_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) +{ + RISCVCLICView *clicview = opaque; + RISCVCLICState *clic = clicview->clic; + CPUState *cpu = cpu_by_arch_id(clic->hartid); + CPURISCVState *env = cpu ? cpu_env(cpu) : NULL; + hwaddr clic_size = clic->clic_size; + int mode = clicview->mode, irq; + const char *current_mode_str = (PRV_M == env->priv) ? "PRV_M" : + (PRV_S == env->priv) ? "PRV_S" : + (PRV_U == env->priv) ? "PRV_U" : + "unknown"; + const char *access_mode_str = (PRV_M == mode) ? "PRV_M" : + (PRV_S == mode) ? "PRV_S" : + (PRV_U == mode) ? "PRV_U" : + "unknown"; + + assert(addr < clic_size); + + if (mode > env->priv) { + qemu_log_mask(LOG_GUEST_ERROR, + "clic: invalid write to %s CLIC registers in %s mode\n", + access_mode_str, current_mode_str); + return; + } + + if (addr < CLIC_INTCTL_BASE) { + assert(addr % 4 == 0); + int index = addr / 4; + switch (index) { + case 0: /* cliccfg */ + { + uint8_t mnlbits = extract32(value, 0, 4); + uint8_t nmbits = extract32(value, 4, 2); + uint8_t snlbits = extract32(value, 16, 4); + uint8_t unlbits = extract32(value, 24, 4); + + /* + * The 4-bit cliccfg.mnlbits WARL field. + * Valid values are 0—8. + */ + if (mnlbits <= 8 && PRV_M == mode) { + clic->mnlbits = mnlbits; + } + if (clic->prv_s && snlbits <= 8 && mode >= PRV_S) { + clic->snlbits = snlbits; + } + if (clic->prv_u && unlbits <= 8) { + clic->unlbits = unlbits; + } + + /* + * The nmbits field - the number of bits for the mode. + * Valid values are given by implemented privileges. + * This is only accessible in PRV_M. + */ + if (PRV_M == mode) { + if (clic->prv_s && clic->prv_u) { + if (nmbits <= 2) { + clic->nmbits = nmbits; + } + } else if (clic->prv_s || clic->prv_u) { + if (nmbits <= 1) { + clic->nmbits = nmbits; + } + } else { + if (nmbits == 0) { + clic->nmbits = 0; + } + } + } + + break; + } + case CLIC_INTTRIG_START ... CLIC_INTTRIG_END: /* clicinttrig */ + { + uint32_t interrupt_number = value & CLIC_INTTRIG_IRQN; + if (interrupt_number <= clic->num_sources) { + value &= CLIC_INTTRIG_MASK; + clic->clicinttrig[index - CLIC_INTTRIG_START] = value; + /* TODO: How does this cause the interrupt to trigger? */ + } + break; + } + case 2: /* mintthresh - only in CLIC spec v0.8 */ + if (0 == strcmp(clic->version, "v0.8")) { + clic->mintthresh = value; + break; + } + qemu_log_mask(LOG_GUEST_ERROR, + "clic: invalid write addr: 0x%" HWADDR_PRIx "\n", + addr); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "clic: invalid write addr: 0x%" HWADDR_PRIx "\n", + addr); + return; + } + } else { + addr -= CLIC_INTCTL_BASE; + irq = riscv_clic_get_irq(clic, addr); + + if (riscv_clic_check_visible(clic, mode, irq)) { + riscv_clic_hart_write(clic, addr, value, size, mode, irq); + } + } +} + +static uint64_t +riscv_clic_read(void *opaque, hwaddr addr, unsigned size) +{ + RISCVCLICView *clicview = opaque; + RISCVCLICState *clic = clicview->clic; + CPUState *cpu = cpu_by_arch_id(clic->hartid); + CPURISCVState *env = cpu ? cpu_env(cpu) : NULL; + hwaddr clic_size = clic->clic_size; + int mode = clicview->mode, irq; + + assert(addr < clic_size); + + if (mode > env->priv) { + const char *current_mode_str = (PRV_M == env->priv) ? "PRV_M" : + (PRV_S == env->priv) ? "PRV_S" : + (PRV_U == env->priv) ? "PRV_U" : + "unknown"; + const char *access_mode_str = (PRV_M == mode) ? "PRV_M" : + (PRV_S == mode) ? "PRV_S" : + (PRV_U == mode) ? "PRV_U" : + "unknown"; + qemu_log_mask(LOG_GUEST_ERROR, + "clic: invalid write to %s CLIC registers in %s mode\n", + access_mode_str, current_mode_str); + return 0; + } + + if (addr < CLIC_INTCTL_BASE) { + assert(addr % 4 == 0); + int index = addr / 4; + switch (index) { + case 0: + /* + * cliccfg register layout + * + * Bits Field + * 31:28 reserved (WPRI 0) + * 27:24 unlbits + * 23:20 reserved (WPRI 0) + * 19:16 snlbits + * 15:6 reserved (WPRI 0) + * 5:4 nmbits + * 3:0 mnlbits + */ + uint64_t cliccfg = 0; + if (PRV_M == mode) { + cliccfg = clic->mnlbits | (clic->nmbits << 4); + } + if (clic->prv_s && mode >= PRV_S) { + cliccfg |= clic->snlbits << 16; + } + if (clic->prv_u && mode >= PRV_U) { + cliccfg |= clic->unlbits << 24; + } + return cliccfg; + + case CLIC_INTTRIG_START ... CLIC_INTTRIG_END: /* clicinttrig */ + /* + * clicinttrig register layout + * + * Bits Field + * 31 enable + * 30:13 reserved (WARL 0) + * 12:0 interrupt_number + */ + uint64_t inttrig = clic->clicinttrig[index - CLIC_INTTRIG_START]; + return inttrig & CLIC_INTTRIG_MASK; + + case 2: /* mintthresh - only in CLIC spec v0.8 */ + if (0 == strcmp(clic->version, "v0.8")) { + return clic->mintthresh; + break; + } + qemu_log_mask(LOG_GUEST_ERROR, + "clic: invalid read : 0x%" HWADDR_PRIx "\n", + addr); + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "clic: invalid read : 0x%" HWADDR_PRIx "\n", + addr); + break; + } + } else { + addr -= CLIC_INTCTL_BASE; + irq = riscv_clic_get_irq(clic, addr); + + if (riscv_clic_check_visible(clic, mode, irq)) { + return riscv_clic_hart_read(clic, addr, size, mode, irq); + } + } + + return 0; +} + +static void riscv_clic_set_irq(void *opaque, int id, int level) +{ + RISCVCLICState *clic = opaque; + TRIG_TYPE type; + + type = riscv_clic_get_trigger_type(clic, id); + + /* + * In general, the edge-triggered interrupt state should be kept in pending + * bit, while the level-triggered interrupt should be kept in the level + * state of the incoming wire. + * + * For CLIC, model the level-triggered interrupt by read-only pending bit. + */ + if (level) { + switch (type) { + case POSITIVE_LEVEL: + case POSITIVE_EDGE: + riscv_clic_update_intip(clic, id, level); + break; + case NEG_LEVEL: + riscv_clic_update_intip(clic, id, !level); + break; + case NEG_EDGE: + break; + default: + /* It's a 2-bit field so this shouldn't be possible */ + assert(type <= 3); + } + } else { + switch (type) { + case POSITIVE_LEVEL: + riscv_clic_update_intip(clic, id, level); + break; + case POSITIVE_EDGE: + break; + case NEG_LEVEL: + case NEG_EDGE: + riscv_clic_update_intip(clic, id, !level); + break; + default: + /* It's a 2-bit field so this shouldn't be possible */ + assert(type <= 3); + } + } +} + +static void riscv_clic_cpu_irq_handler(void *opaque, int irq, int level) +{ + CPURISCVState *env = (CPURISCVState *)opaque; + RISCVCLICState *clic = env->clic; + + if (level) { + env->exccode = clic->exccode; + cpu_interrupt(env_cpu(env), CPU_INTERRUPT_CLIC); + } +} + +static const MemoryRegionOps riscv_clic_ops = { + .read = riscv_clic_read, + .write = riscv_clic_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 8 + } +}; + +static void riscv_clic_realize(DeviceState *dev, Error **errp) +{ + RISCVCLICState *clic = RISCV_CLIC(dev); + size_t irqs = clic->num_sources; + + if (clic->prv_s && clic->prv_u) { + clic->nmbits = 2; + } else if (clic->prv_s || clic->prv_u) { + clic->nmbits = 1; + } else { + clic->nmbits = 0; + } + + clic->clicintip = g_new0(uint8_t, irqs); + clic->clicintie = g_new0(uint8_t, irqs); + clic->clicintattr = g_new0(uint8_t, irqs); + clic->clicintctl = g_new0(uint8_t, irqs); + clic->active_list = g_new0(CLICActiveInterrupt, irqs); + + if (!clic->prv_s) { + clic->snlbits = 0; + } + if (!clic->prv_u) { + clic->unlbits = 0; + } + + /* Allocate irqs through gpio, so that we can use qtest */ + qdev_init_gpio_in(dev, riscv_clic_set_irq, irqs); + qdev_init_gpio_out(dev, &clic->cpu_irq, 1); + + assert(cpu_exists(clic->hartid)); + RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(clic->hartid)); + qemu_irq irq = qemu_allocate_irq(riscv_clic_cpu_irq_handler, &cpu->env, 1); + qdev_connect_gpio_out(dev, 0, irq); + cpu->env.clic = clic; +} + +static void riscv_clic_view_realize(DeviceState *dev, Error **errp) +{ + RISCVCLICView *clicview = RISCV_CLIC_VIEW(dev); + RISCVCLICState *clic = clicview->clic; + + memory_region_init_io(&clicview->mmio, OBJECT(clicview), &riscv_clic_ops, + clicview, TYPE_RISCV_CLIC_VIEW, clic->clic_size); + sysbus_init_mmio(SYS_BUS_DEVICE(clicview), &clicview->mmio); +} + +static Property riscv_clic_properties[] = { + DEFINE_PROP_BOOL("shv-enabled", RISCVCLICState, shv_enabled, true), + DEFINE_PROP_BOOL("jump-table", RISCVCLICState, jump_table, false), + DEFINE_PROP_UINT8("mnlbits", RISCVCLICState, mnlbits, 8), + DEFINE_PROP_UINT8("snlbits", RISCVCLICState, snlbits, 8), + DEFINE_PROP_UINT8("unlbits", RISCVCLICState, unlbits, 8), + DEFINE_PROP_INT32("hartid", RISCVCLICState, hartid, 0), + DEFINE_PROP_UINT32("num-sources", RISCVCLICState, num_sources, 0), + DEFINE_PROP_UINT32("clic-size", RISCVCLICState, clic_size, 0), + DEFINE_PROP_UINT32("clicintctlbits", RISCVCLICState, clicintctlbits, 0), + DEFINE_PROP_STRING("version", RISCVCLICState, version), + DEFINE_PROP_END_OF_LIST(), +}; + +static Property riscv_clic_view_properties[] = { + DEFINE_PROP_LINK("clic", RISCVCLICView, clic, + TYPE_RISCV_CLIC, RISCVCLICState *), + DEFINE_PROP_UINT8("mode", RISCVCLICView, mode, PRV_U), + DEFINE_PROP_UINT64("clicbase", RISCVCLICView, clicbase, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void riscv_clic_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = riscv_clic_realize; + device_class_set_props(dc, riscv_clic_properties); +} + +static void riscv_clic_view_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = riscv_clic_view_realize; + device_class_set_props(dc, riscv_clic_view_properties); +} + +static const TypeInfo riscv_clic_info = { + .name = TYPE_RISCV_CLIC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(RISCVCLICState), + .class_init = riscv_clic_class_init, +}; + +static const TypeInfo riscv_clic_view_info = { + .name = TYPE_RISCV_CLIC_VIEW, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(RISCVCLICView), + .class_init = riscv_clic_view_init, +}; + +static void riscv_clic_register_types(void) +{ + type_register_static(&riscv_clic_info); + type_register_static(&riscv_clic_view_info); +} + +type_init(riscv_clic_register_types) + +/* + * riscv_clic_view_create: + * + * @clic: machine-mode CLIC this is an view onto + * @clicbase: base address of this view CLIC memory-mapped registers + * @mode: the mode of the view - PRV_S or PRV_U + * + * Returns: the new view + */ +static RISCVCLICView *riscv_clic_view_create(RISCVCLICState *clic, + hwaddr clicbase, int mode) +{ + DeviceState *dev = qdev_new(TYPE_RISCV_CLIC_VIEW); + RISCVCLICView *clicview = RISCV_CLIC_VIEW(dev); + Object *obj = OBJECT(dev); + Object *clicobj = OBJECT(clic); + + assert(0 != clic); /* this should exist */ + assert(0 != clicbase); /* this should exist */ + assert(0 == (clicbase & 0xfff)); /* base should be 4KiB-aligned */ + assert(PRV_M == mode || PRV_S == mode || PRV_U == mode); + + object_property_add_child(clicobj, modeview_name[mode], obj); + clicview->clic = clic; + + qdev_prop_set_uint8(dev, "mode", mode); + qdev_prop_set_uint64(dev, "clicbase", clicbase); + + if (!sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal)) { + object_unparent(obj); + return NULL; + } + + memory_region_init_io(&clicview->mmio, OBJECT(dev), &riscv_clic_ops, + clicview, TYPE_RISCV_CLIC_VIEW, clic->clic_size); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, clicbase); + + return clicview; +} + +/* + * riscv_clic_create: + * + * @mclicbase: base address of PRV_M CLIC memory-mapped registers + * @sclicbase: base address of PRV_S CLIC memory-mapped registers + * @uclicbase: base address of PRV_U CLIC memory-mapped registers + * @hartid: the HART ID this CLIC is serving + * @num_sources: number of interrupts supporting by each aperture + * @clicintctlbits: bits are actually implemented in the clicintctl registers + * @version: clic version, such as "v0.9"; append "-jmp" for jump table instead + * of function pointers + * + * Returns: the device object + */ +DeviceState *riscv_clic_create(hwaddr mclicbase, hwaddr sclicbase, + hwaddr uclicbase, uint32_t hartid, + uint32_t num_sources, uint8_t clicintctlbits, + const char *version) +{ + DeviceState *dev = qdev_new(TYPE_RISCV_CLIC); + RISCVCLICState *s = RISCV_CLIC(dev); + g_autofree char **tokens = NULL; + char *base_version; + bool jump_table = false; + + assert(num_sources <= CLIC_MAX_IRQ_COUNT); + assert(cpu_exists(hartid)); + assert(clicintctlbits <= MAX_CLIC_INTCTLBITS); + assert(0 == (mclicbase & 0xfff)); /* base should be 4KiB-aligned */ + + /* Parse the version */ + tokens = g_strsplit(version, "-", 2); + base_version = g_strdup(tokens[0]); + assert(0 == strcmp(base_version, "v0.9")); + if (tokens[1]) { + assert(0 == strcmp(tokens[1], "jmp")); + jump_table = true; + } + + qdev_prop_set_uint32(dev, "hartid", hartid); + qdev_prop_set_uint32(dev, "num-sources", num_sources); + qdev_prop_set_uint32(dev, "clic-size", num_sources * 4 + CLIC_INTCTL_BASE); + qdev_prop_set_uint32(dev, "clicintctlbits", clicintctlbits); + qdev_prop_set_string(dev, "version", base_version); + qdev_prop_set_bit(dev, "jump-table", jump_table); + + s->prv_m = riscv_clic_view_create(s, mclicbase, PRV_M); + if (sclicbase) { + s->prv_s = riscv_clic_view_create(s, sclicbase, PRV_S); + } + if (uclicbase) { + s->prv_u = riscv_clic_view_create(s, uclicbase, PRV_U); + } + + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + return dev; +} + +void riscv_clic_get_next_interrupt(void *opaque) +{ + RISCVCLICState *clic = opaque; + riscv_clic_next_interrupt(clic); +} + +bool riscv_clic_shv_interrupt(void *opaque, int irq) +{ + RISCVCLICState *clic = opaque; + return riscv_clic_is_shv_interrupt(clic, irq); +} + +bool riscv_clic_edge_triggered(void *opaque, int irq) +{ + RISCVCLICState *clic = opaque; + return riscv_clic_is_edge_triggered(clic, irq); +} + +bool riscv_clic_use_jump_table(void *opaque) +{ + RISCVCLICState *clic = opaque; + return clic->jump_table; +} + +void riscv_clic_clean_pending(void *opaque, int irq) +{ + RISCVCLICState *clic = opaque; + clic->clicintip[irq] = 0; +} + +/* + * The new CLIC interrupt-handling mode is encoded as a new state in + * the existing WARL xtvec register, where the low two bits are 11. + */ +bool riscv_clic_is_clic_mode(CPURISCVState *env) +{ + target_ulong xtvec = (env->priv == PRV_M) ? env->mtvec : env->stvec; + return env->clic && ((xtvec & XTVEC_MODE) == XTVEC_CLIC); +} + +void riscv_clic_decode_exccode(uint32_t exccode, int *mode, + int *il, int *irq) +{ + *irq = get_field(exccode, RISCV_EXCP_CLIC_IRQ); + *mode = get_field(exccode, RISCV_EXCP_CLIC_MODE); + *il = get_field(exccode, RISCV_EXCP_CLIC_LEVEL); +} diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index a2030e3a6f..18454df8bd 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -47,6 +47,7 @@ config RISCV_VIRT select SERIAL select RISCV_ACLINT select RISCV_APLIC + select RISCV_CLIC select RISCV_IMSIC select SIFIVE_PLIC select SIFIVE_TEST diff --git a/include/hw/intc/riscv_clic.h b/include/hw/intc/riscv_clic.h new file mode 100644 index 0000000000..b38a576308 --- /dev/null +++ b/include/hw/intc/riscv_clic.h @@ -0,0 +1,213 @@ +/* + * RISC-V CLIC(Core Local Interrupt Controller) interface. + * + * Copyright (c) 2021 T-Head Semiconductor Co., Ltd. All rights reserved. + * Copyright (c) 2024 Cirrus Logic, Inc + * and Cirrus Logic International Semiconductor Ltd. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * This implementation follows the CLIC 0.9-stable draft at 14 March 2024, + * with the following exceptions and implementation details: + * - the CLIC control registers are memory-mapped as per earlier drafts (in + * particular version 0.9-draft, 20 June 2023) + * - the indirect CSR control in 0.9-stable is not implemented + * - the vector table can be either handler addresses (as per the spec) + or a jump table where each entry is processed as an instruction, + selectable with version number v0.9-jmp + * - each hart is assigned its own CLIC block + * - if PRV_S and/or PRV_M are supported, they are currently assumed to follow + * the PRV_M registers; a subsequent update will address this + * - support for PRV_S and PRV_M is selectable at CLIC instantiation + * - PRV_S and PRV_U registers are currently separate from PRV_M; a subsequent + * update will turn them into filtered views onto the PRV_M registers + * - each hart is assigned its own CLIC block + * - support for PRV_S and PRV_M is selectable at CLIC instantiation by + * passing in a base address for the given modes; a base address of 0 is + * treated as not supported + * - PRV_S and PRV_U registers are mapped onto the PRV_M controls with + * appropriate filtering for the access mode + * + * The implementation has a RISCVCLICState per hart, with a RISCVCLICView + * for each mode subsidiary to that. Each view knows its access mode and base + * address, as well as the RISCVCLICState with which it is associated. + * + * MMIO accesses go through the view, allowing the appropriate permissions to + * be enforced when accessing the parent RISCVCLICState for the settings. + */ + +#ifndef RISCV_CLIC_H +#define RISCV_CLIC_H + +#include "hw/irq.h" +#include "hw/sysbus.h" + +#define TYPE_RISCV_CLIC "riscv_clic" +#define TYPE_RISCV_CLIC_VIEW "riscv_clic_view" +#define RISCV_CLIC(obj) \ + OBJECT_CHECK(RISCVCLICState, (obj), TYPE_RISCV_CLIC) +#define RISCV_CLIC_VIEW(obj) \ + OBJECT_CHECK(RISCVCLICView, (obj), TYPE_RISCV_CLIC_VIEW) + +/* + * CLIC per hart active interrupts + * + * We maintain per hart lists of enabled interrupts sorted by + * mode+level+priority. The sorting is done on the configuration path + * so that the interrupt delivery fastpath can linear scan enabled + * interrupts in priority order. + */ +typedef struct CLICActiveInterrupt { + uint16_t intcfg; + uint16_t irq; +} CLICActiveInterrupt; + +typedef enum TRIG_TYPE { + POSITIVE_LEVEL, + POSITIVE_EDGE, + NEG_LEVEL, + NEG_EDGE, +} TRIG_TYPE; + +#define CLIC_INTCTL_BASE 0x1000 /* start offset of intctl registers */ +#define MAX_CLIC_INTCTLBITS 8 /* maximum value for intctlbits */ + +/* maximum of 4096 IRQs */ +#define CLIC_IRQ_BITS 12 +#define CLIC_MAX_IRQ_COUNT (1 << CLIC_IRQ_BITS) +#define CLIC_MAX_IRQ (CLIC_MAX_IRQ_COUNT - 1) +#define CLIC_IRQ_MASK CLIC_MAX_IRQ + +/* + * clicinttrig registers + * 31 interrupt_trap_enable + * 30 nxti_enable + * 29:13 reserved (WARL 0) + * 12:0 interrupt_number + */ +#define CLIC_INTTRIG_REGS 32 /* inttrig register count */ +#define CLIC_INTTRIG_START 0x10 /* first inttrig register */ +#define CLIC_INTTRIG_END (CLIC_INTTRIG_START + CLIC_INTTRIG_REGS - 1) +#define CLIC_INTTRIG_TRAP_ENA 0x80000000 +#define CLIC_INTTRIG_NXTI_ENA 0x40000000 +#define CLIC_INTTRIG_IRQN 0x00001fff +#define CLIC_INTTRIG_MASK (CLIC_INTTRIG_TRAP_ENA | \ + CLIC_INTTRIG_NXTI_ENA | CLIC_INTTRIG_IRQN) + +/* + * We combine the mode and intctl to a number so that higher modes come first. + * 9:8 machine mode + * 7:0 clicintctl + */ +#define CLIC_INTCFG_MODE_SHIFT 8 +#define CLIC_INTCFG_MODE 0x300 +#define CLIC_INTCFG_CTL 0xff +#define CLIC_INTCFG_MASK (CLIC_INTCFG_MODE | CLIC_INTCFG_CTL) + +/* + * clicintattr layout + * 7:6 mode + * 5:3 reserved (WPRI 0) + * 2:1 trig + * 0 shv + */ +#define CLIC_INTATTR_MODE_SHIFT 6 +#define CLIC_INTATTR_MODE_WIDTH 2 +#define CLIC_INTATTR_MODE 0xc0 +#define CLIC_INTATTR_TRIG_SHIFT 1 +#define CLIC_INTATTR_TRIG_WIDTH 2 +#define CLIC_INTATTR_TRIG 0x06 +#define CLIC_INTATTR_SHV 0x01 +#define CLIC_INTATTR_MASK (CLIC_INTATTR_MODE | CLIC_INTATTR_TRIG | \ + CLIC_INTATTR_SHV) +/* The clicintattr value */ +#define CLIC_INTATTR_TRIG_EDGE 0b01 /* trig decode edge-triggered */ +#define CLIC_INTATTR_TRIG_INV 0b10 /* trig decode negative polarity */ + +/* Forward declaration */ +typedef struct RISCVCLICView RISCVCLICView; + +/* + * The main CLIC state (PRV_M mode) for a hart. + */ +typedef struct RISCVCLICState { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + + /* Implementation parameters */ + bool shv_enabled; /* hardware-vectoring enabled */ + bool jump_table; /* vector with jump table, not handler addresses */ + int hartid; + uint32_t num_sources; + uint32_t clic_size; + uint32_t clic_mmode_base; + uint32_t clicintctlbits; + RISCVCLICView *prv_m; /* our PRV_M view */ + RISCVCLICView *prv_s; /* our PRV_S view */ + RISCVCLICView *prv_u; /* our PRV_U view */ + char *version; + + /* Global configuration */ + uint8_t nmbits; /* mode bits */ + uint8_t mnlbits; /* level bits for M-mode */ + uint8_t snlbits; /* level bits for S-mode, if present */ + uint8_t unlbits; /* level bits for U-mode, if present */ + uint32_t clicinttrig[CLIC_INTTRIG_REGS]; + + /* Aperture configuration */ + uint8_t *clicintip; + uint8_t *clicintie; + uint8_t *clicintattr; + uint8_t *clicintctl; + + /* Compatible with v0.8 */ + uint32_t mintthresh; + uint32_t sintthresh; + uint32_t uintthresh; + + /* QEMU implementation related fields */ + uint32_t exccode; + CLICActiveInterrupt *active_list; + size_t active_count; + qemu_irq cpu_irq; +} RISCVCLICState; + +/* + * A PRV_S or PRV_U overlay onto the main RISCVCLICState. + */ +typedef struct RISCVCLICView { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + RISCVCLICState *clic; /* the CLIC this is a view onto */ + MemoryRegion mmio; + uint64_t clicbase; + uint8_t mode; +} RISCVCLICView; + +DeviceState *riscv_clic_create(hwaddr mclicbase, hwaddr sclicbase, + hwaddr uclicbase, uint32_t hartid, + uint32_t num_sources, uint8_t clicintctlbits, + const char *version); + +void riscv_clic_decode_exccode(uint32_t exccode, int *mode, int *il, int *irq); +void riscv_clic_clean_pending(void *opaque, int irq); +bool riscv_clic_edge_triggered(void *opaque, int irq); +bool riscv_clic_shv_interrupt(void *opaque, int irq); +bool riscv_clic_use_jump_table(void *opaque); +void riscv_clic_get_next_interrupt(void *opaque); +bool riscv_clic_is_clic_mode(CPURISCVState *env); +#endif diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 9b5f36ad0a..12aa8cf6b1 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -36,6 +36,7 @@ typedef struct CPUArchState CPURISCVState; #define CPU_RESOLVING_TYPE TYPE_RISCV_CPU +#define CPU_INTERRUPT_CLIC CPU_INTERRUPT_TGT_EXT_0 #if defined(TARGET_RISCV32) # define TYPE_RISCV_CPU_BASE TYPE_RISCV_CPU_BASE32 @@ -465,6 +466,7 @@ struct CPUArchState { bool vstime_irq; void *clic; /* clic interrupt controller */ + uint32_t exccode; /* clic irq encode */ hwaddr kernel_addr; hwaddr fdt_addr; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index ad45402370..0ed44ec0a8 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -694,6 +694,12 @@ typedef enum RISCVException { } RISCVException; #define RISCV_EXCP_INT_FLAG 0x80000000 +#define RISCV_EXCP_CLIC 0x40000000 +#define RISCV_EXCP_CLIC_LEVEL_SHIFT 14 +#define RISCV_EXCP_CLIC_LEVEL (0xff << RISCV_EXCP_CLIC_LEVEL_SHIFT) +#define RISCV_EXCP_CLIC_MODE_SHIFT 12 +#define RISCV_EXCP_CLIC_MODE (3 << RISCV_EXCP_CLIC_MODE_SHIFT) +#define RISCV_EXCP_CLIC_IRQ 0x00000fff #define RISCV_EXCP_INT_MASK 0x7fffffff /* Interrupt causes */ @@ -746,6 +752,17 @@ typedef enum RISCVException { #define SINTSTATUS_SIL 0x0000ff00 /* sil[15:8] */ #define SINTSTATUS_UIL 0x000000ff /* uil[7:0] */ +/* mtvec & stvec */ +#define XTVEC_MODE 0x03 +#define XTVEC_SUBMODE 0x3c +#define XTVEC_FULL_MODE (XTVEC_MODE | XTVEC_SUBMODE) +#define XTVEC_OBASE (~XTVEC_MODE) +#define XTVEC_NBASE (~XTVEC_FULL_MODE) + +#define XTVEC_CLINT_DIRECT 0x0 +#define XTVEC_CLINT_VECTORED 0x1 +#define XTVEC_CLIC 0x3 + /* MIE masks */ #define MIE_SEIE (1 << IRQ_S_EXT) #define MIE_UEIE (1 << IRQ_U_EXT) From patchwork Wed Aug 14 08:27:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Brockbank X-Patchwork-Id: 13763090 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 5B8D1C52D7F for ; Wed, 14 Aug 2024 08:42:58 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1se9ab-0002e7-Lm; Wed, 14 Aug 2024 04:42:41 -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 1se9aX-0002Kr-96; Wed, 14 Aug 2024 04:42:37 -0400 Received: from mx0b-001ae601.pphosted.com ([67.231.152.168]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1se9aV-0005sO-Ex; Wed, 14 Aug 2024 04:42:37 -0400 Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 47E4fosN021737; Wed, 14 Aug 2024 03:42:29 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s= PODMain02222019; bh=KF6Y8IDy+yUTRo0bbLXGR0h6YqSstKq3GyAx9tu3L24=; b= NuN8QdecrHLnMn+Wucou0RL+Dse7NeLGbY9I+4Ubp6Wwp9ANY3GREF10r23d80d6 2htMdNszjem+zBrrIpGdfF/aAWLMxyc0ucdvO23CArEqyurToBqJMtPOrB5myaiD ERVwPkLLI/FIpp1+jHv9SB7DHtxq9DDO1lXGZn5/YchDo37OaRqweJ57ov2lrjHx sBBhl9Z7PeJ5uud4GzdrLORWJkhD0ycIks6whEj3ogkjA0ZsD17t6In4dHBTE0Ae lLiEURehxKedgYBSOkBTVcVd6/w0rXu1QiBO6pAw+z0OvWQ4VmIJ/+o58DSO94pj oTY4XKvP/UFNegrJf2+ABg== Received: from ausex01.ad.cirrus.com ([141.131.3.19]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 40x4mhmb7x-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 14 Aug 2024 03:42:29 -0500 (CDT) Received: from ausex01.ad.cirrus.com (141.131.37.95) by ausex01.ad.cirrus.com (141.131.37.95) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 14 Aug 2024 03:42:28 -0500 Received: from EDIN7BQBTG3.ad.cirrus.com (141.131.38.212) by anon-ausex01.ad.cirrus.com (141.131.37.95) with Microsoft SMTP Server id 15.2.1544.9 via Frontend Transport; Wed, 14 Aug 2024 03:42:26 -0500 From: Ian Brockbank To: , CC: Palmer Dabbelt , Alistair Francis , Bin Meng , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Ian Brockbank , LIU Zhiwei Subject: [PATCH 04/11] target/riscv: Update CSR xie in CLIC mode Date: Wed, 14 Aug 2024 09:27:33 +0100 Message-ID: <20240814083836.12256-10-Ian.Brockbank@cirrus.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240814083836.12256-1-Ian.Brockbank@cirrus.com> References: <20240814083836.12256-1-Ian.Brockbank@cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: 8UAYLPOfOVukU5Nt6in4KHdA2GpDOKXn X-Proofpoint-GUID: 8UAYLPOfOVukU5Nt6in4KHdA2GpDOKXn X-Proofpoint-Spam-Reason: orgsafe Received-SPF: pass client-ip=67.231.152.168; envelope-from=prvs=5956f96c7e=ian.brockbank@cirrus.com; helo=mx0b-001ae601.pphosted.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 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, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 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: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Ian Brockbank The xie CSR appears hardwired to zero in CLIC mode, replaced by separate memory-mapped interrupt enables (clicintie[i]). Writes to xie will be ignored and will not trap (i.e., no access faults). Signed-off-by: LIU Zhiwei Signed-off-by: Ian Brockbank --- target/riscv/csr.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) -- 2.46.0.windows.1 This message and any attachments may contain privileged and confidential information that is intended solely for the person(s) to whom it is addressed. If you are not an intended recipient you must not: read; copy; distribute; discuss; take any action in or make any reliance upon the contents of this message; nor open or read any attachment. If you have received this message in error, please notify us as soon as possible on the following telephone number and destroy this message including any attachments. Thank you. Cirrus Logic International (UK) Ltd and Cirrus Logic International Semiconductor Ltd are companies registered in Scotland, with registered numbers SC089839 and SC495735 respectively. Our registered office is at 7B Nightingale Way, Quartermile, Edinburgh, EH3 9EG, UK. Tel: +44 (0)131 272 7000. www.cirrus.com diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 9c824c0d8f..a5978e0929 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -30,6 +30,10 @@ #include "qemu/guest-random.h" #include "qapi/error.h" +#if !defined(CONFIG_USER_ONLY) +#include "hw/intc/riscv_clic.h" +#endif + /* CSR function table public API */ void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops) { @@ -1805,16 +1809,19 @@ static RISCVException rmw_mie64(CPURISCVState *env, int csrno, uint64_t *ret_val, uint64_t new_val, uint64_t wr_mask) { - uint64_t mask = wr_mask & all_ints; + /* Access to xie will be ignored in CLIC mode and will not trap. */ + if (!riscv_clic_is_clic_mode(env)) { + uint64_t mask = wr_mask & all_ints; - if (ret_val) { - *ret_val = env->mie; - } + if (ret_val) { + *ret_val = env->mie; + } - env->mie = (env->mie & ~mask) | (new_val & mask); + env->mie = (env->mie & ~mask) | (new_val & mask); - if (!riscv_has_ext(env, RVH)) { - env->mie &= ~((uint64_t)HS_MODE_INTERRUPTS); + if (!riscv_has_ext(env, RVH)) { + env->mie &= ~((uint64_t)HS_MODE_INTERRUPTS); + } } return RISCV_EXCP_NONE; @@ -2906,13 +2913,13 @@ static int read_mintstatus(CPURISCVState *env, int csrno, target_ulong *val) static int read_mintthresh(CPURISCVState *env, int csrno, target_ulong *val) { *val = env->mintthresh; - return 0; + return RISCV_EXCP_NONE; } static int write_mintthresh(CPURISCVState *env, int csrno, target_ulong val) { env->mintthresh = val; - return 0; + return RISCV_EXCP_NONE; } /* Supervisor Trap Setup */ @@ -3059,7 +3066,10 @@ static RISCVException rmw_sie64(CPURISCVState *env, int csrno, *ret_val |= env->sie & nalias_mask; } - env->sie = (env->sie & ~sie_mask) | (new_val & sie_mask); + /* Writes to xie will be ignored in CLIC mode and will not trap. */ + if (!riscv_clic_is_clic_mode(env)) { + env->sie = (env->sie & ~sie_mask) | (new_val & sie_mask); + } } return ret; @@ -3337,13 +3347,13 @@ static int read_sintstatus(CPURISCVState *env, int csrno, target_ulong *val) static int read_sintthresh(CPURISCVState *env, int csrno, target_ulong *val) { *val = env->sintthresh; - return 0; + return RISCV_EXCP_NONE; } static int write_sintthresh(CPURISCVState *env, int csrno, target_ulong val) { env->sintthresh = val; - return 0; + return RISCV_EXCP_NONE; } /* Supervisor Protection and Translation */ From patchwork Wed Aug 14 08:27:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Brockbank X-Patchwork-Id: 13763091 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4C86FC52D7F for ; Wed, 14 Aug 2024 08:43:18 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1se9az-0004vO-TQ; Wed, 14 Aug 2024 04:43: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 1se9ax-0004kY-Uu; Wed, 14 Aug 2024 04:43:03 -0400 Received: from mx0a-001ae601.pphosted.com ([67.231.149.25] helo=mx0b-001ae601.pphosted.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1se9aw-0005vH-81; Wed, 14 Aug 2024 04:43:03 -0400 Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 47E5j9TL020215; Wed, 14 Aug 2024 03:42:56 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s= PODMain02222019; bh=6kxBEvL1XX5A4t5MqUPj/4BY/7wipVF5zbUzogEKAoI=; b= QD5nkfHhea4CLqusHTdQl0EdYiu/cQMz2wIPhG02U37OtPMH9RMO33KUJbsTFuKN Hp8cZkMBOjlMzevNN+/526b5I6fc4pv4Dr1KxpyfqZN28LCdHN5NA7HxOxNtknS7 OjFCDuHhLd1TTleDHy5CznT7bLImRxO8e8u28IATQ+ZdgpzmqM3TWCuTUYkEMxqw o1LUO9TmInewECrSBmhOyFRjp1QsKO0dziNpNsN62iWsC34rCRpNOLvwnfeonqIv svctvdtaCMkL4IMO3uIKrbOk6UHIe51QAS6sbYvzWmfeaSSuPTKDZU2SMlWlbQld Pb/poNdPg4CtMyAitD77ng== Received: from ausex01.ad.cirrus.com ([141.131.3.19]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 40x5kwmae0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 14 Aug 2024 03:42:55 -0500 (CDT) Received: from ausex01.ad.cirrus.com (141.131.37.95) by ausex01.ad.cirrus.com (141.131.37.95) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 14 Aug 2024 03:42:52 -0500 Received: from EDIN7BQBTG3.ad.cirrus.com (141.131.38.212) by anon-ausex01.ad.cirrus.com (141.131.37.95) with Microsoft SMTP Server id 15.2.1544.9 via Frontend Transport; Wed, 14 Aug 2024 03:42:50 -0500 From: Ian Brockbank To: , CC: Palmer Dabbelt , Alistair Francis , Bin Meng , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Ian Brockbank , LIU Zhiwei Subject: [PATCH 05/11] target/riscv: Update CSR xip in CLIC mode Date: Wed, 14 Aug 2024 09:27:35 +0100 Message-ID: <20240814083836.12256-12-Ian.Brockbank@cirrus.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240814083836.12256-1-Ian.Brockbank@cirrus.com> References: <20240814083836.12256-1-Ian.Brockbank@cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: Yv9SvXIq-hFTf7e0IJKUq3wYC4HmjeR0 X-Proofpoint-GUID: Yv9SvXIq-hFTf7e0IJKUq3wYC4HmjeR0 X-Proofpoint-Spam-Reason: orgsafe Received-SPF: pass client-ip=67.231.149.25; envelope-from=prvs=5956f96c7e=ian.brockbank@cirrus.com; helo=mx0b-001ae601.pphosted.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 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, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 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: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Ian Brockbank The xip CSR appears hardwired to zero in CLIC mode, replaced by separate memory-mapped interrupt pendings (clicintip[i]). Writes to xip will be ignored and will not trap (i.e., no access faults). Signed-off-by: LIU Zhiwei Signed-off-by: Ian Brockbank --- target/riscv/csr.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) -- 2.46.0.windows.1 This message and any attachments may contain privileged and confidential information that is intended solely for the person(s) to whom it is addressed. If you are not an intended recipient you must not: read; copy; distribute; discuss; take any action in or make any reliance upon the contents of this message; nor open or read any attachment. If you have received this message in error, please notify us as soon as possible on the following telephone number and destroy this message including any attachments. Thank you. Cirrus Logic International (UK) Ltd and Cirrus Logic International Semiconductor Ltd are companies registered in Scotland, with registered numbers SC089839 and SC495735 respectively. Our registered office is at 7B Nightingale Way, Quartermile, Edinburgh, EH3 9EG, UK. Tel: +44 (0)131 272 7000. www.cirrus.com diff --git a/target/riscv/csr.c b/target/riscv/csr.c index a5978e0929..276ef7856e 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -2743,6 +2743,12 @@ static RISCVException rmw_mip(CPURISCVState *env, int csrno, uint64_t rval; RISCVException ret; + /* The xip CSR appears hardwired to zero in CLIC mode. */ + if (riscv_clic_is_clic_mode(env)) { + *ret_val = 0; + return RISCV_EXCP_NONE; + } + ret = rmw_mip64(env, csrno, &rval, new_val, wr_mask); if (ret_val) { *ret_val = rval; @@ -3294,6 +3300,12 @@ static RISCVException rmw_sip64(CPURISCVState *env, int csrno, } ret = rmw_vsip64(env, CSR_VSIP, ret_val, new_val, wr_mask); } else { + /* The xip CSR appears hardwired to zero in CLIC mode. */ + if (riscv_clic_is_clic_mode(env)) { + *ret_val = 0; + return RISCV_EXCP_NONE; + } + ret = rmw_mvip64(env, csrno, ret_val, new_val, wr_mask & mask); } From patchwork Wed Aug 14 08:27:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Brockbank X-Patchwork-Id: 13763093 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E4A8DC3DA4A for ; Wed, 14 Aug 2024 08:43:57 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1se9bk-0000ez-KI; Wed, 14 Aug 2024 04:43:52 -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 1se9bh-0000NT-6v; Wed, 14 Aug 2024 04:43:49 -0400 Received: from mx0b-001ae601.pphosted.com ([67.231.152.168]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1se9bf-0005zY-8F; Wed, 14 Aug 2024 04:43:48 -0400 Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 47E4gOKg023234; Wed, 14 Aug 2024 03:43:39 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s= PODMain02222019; bh=BpG6B539a4OdKFkJyo/rvorQIsMi6L/7XRdL6Y07Hh4=; b= KfGsboNnHwMBUlW2RBcDnbk+3M3rzVnrRe5zbJ60W+Vsbp5HLtbyoxwFU7MXJKc9 uPTxOkuCvW9O7s26vW4l8+hTloXV8r4IFdEr/lG+9DZBpsnMNnDHbn7q3XldRaR7 3TLT8fZerF2Vxl7a+Gft3R3Fk0hkwf/lh/yHAzFxNXUiABR0c5CuoRqx7JR6pVZU g9azXzRV/vGx85oWYNcfHcVCVWVP1jQAIq7zKlgysA7F8yKDO2tClUxIwWJf2dRX T4dm3R/4sqeATI7U7/o3CTOSdAynC0m8pJDmn0SaE+k2aoUfu71lGe0catFECT28 mZjCADTDGNal75l0CxQHZQ== Received: from ausex02.ad.cirrus.com ([141.131.3.21]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 40x4mhmb8r-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 14 Aug 2024 03:43:39 -0500 (CDT) Received: from ausex01.ad.cirrus.com (141.131.37.95) by ausex02.ad.cirrus.com (141.131.37.96) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 14 Aug 2024 03:43:38 -0500 Received: from EDIN7BQBTG3.ad.cirrus.com (141.131.38.212) by anon-ausex01.ad.cirrus.com (141.131.37.95) with Microsoft SMTP Server id 15.2.1544.9 via Frontend Transport; Wed, 14 Aug 2024 03:43:36 -0500 From: Ian Brockbank To: , CC: Palmer Dabbelt , Alistair Francis , Bin Meng , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Ian Brockbank , LIU Zhiwei Subject: [PATCH 06/11] target/riscv: Update CSR xtvec in CLIC mode Date: Wed, 14 Aug 2024 09:27:39 +0100 Message-ID: <20240814083836.12256-16-Ian.Brockbank@cirrus.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240814083836.12256-1-Ian.Brockbank@cirrus.com> References: <20240814083836.12256-1-Ian.Brockbank@cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: mc0j2OrmnRKsZRZFDUxxX5E83bhixuvI X-Proofpoint-GUID: mc0j2OrmnRKsZRZFDUxxX5E83bhixuvI X-Proofpoint-Spam-Reason: safe Received-SPF: pass client-ip=67.231.152.168; envelope-from=prvs=5956f96c7e=ian.brockbank@cirrus.com; helo=mx0b-001ae601.pphosted.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 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, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 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: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Ian Brockbank The new CLIC interrupt-handling mode is encoded as a new state in the existing WARL xtvec register, where the low two bits of are 11. Signed-off-by: LIU Zhiwei Signed-off-by: Ian Brockbank --- target/riscv/cpu.h | 2 ++ target/riscv/cpu_bits.h | 2 ++ target/riscv/csr.c | 63 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 63 insertions(+), 4 deletions(-) -- 2.46.0.windows.1 This message and any attachments may contain privileged and confidential information that is intended solely for the person(s) to whom it is addressed. If you are not an intended recipient you must not: read; copy; distribute; discuss; take any action in or make any reliance upon the contents of this message; nor open or read any attachment. If you have received this message in error, please notify us as soon as possible on the following telephone number and destroy this message including any attachments. Thank you. Cirrus Logic International (UK) Ltd and Cirrus Logic International Semiconductor Ltd are companies registered in Scotland, with registered numbers SC089839 and SC495735 respectively. Our registered office is at 7B Nightingale Way, Quartermile, Edinburgh, EH3 9EG, UK. Tel: +44 (0)131 272 7000. www.cirrus.com diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 12aa8cf6b1..05a014db03 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -283,11 +283,13 @@ struct CPUArchState { target_ulong medeleg; target_ulong stvec; + target_ulong stvt; /* clic-spec */ target_ulong sepc; target_ulong scause; target_ulong sintthresh; /* clic-spec */ target_ulong mtvec; + target_ulong mtvt; /* clic-spec */ target_ulong mepc; target_ulong mcause; target_ulong mtval; /* since: priv-1.10.0 */ diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 0ed44ec0a8..279a6f889b 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -153,6 +153,7 @@ #define CSR_MIE 0x304 #define CSR_MTVEC 0x305 #define CSR_MCOUNTEREN 0x306 +#define CSR_MTVT 0x307 /* clic-spec-draft */ /* 32-bit only */ #define CSR_MSTATUSH 0x310 @@ -192,6 +193,7 @@ #define CSR_SIE 0x104 #define CSR_STVEC 0x105 #define CSR_SCOUNTEREN 0x106 +#define CSR_STVT 0x107 /* clic-spec-draft */ /* Supervisor Configuration CSRs */ #define CSR_SENVCFG 0x10A diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 276ef7856e..be0071fd25 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -2170,9 +2170,23 @@ static RISCVException read_mtvec(CPURISCVState *env, int csrno, static RISCVException write_mtvec(CPURISCVState *env, int csrno, target_ulong val) { - /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */ - if ((val & 3) < 2) { + /* + * bits [1:0] encode mode; 0 = direct, 1 = vectored, 3 = CLIC, + * others reserved + */ + target_ulong mode = get_field(val, XTVEC_MODE); + target_ulong fullmode = val & XTVEC_FULL_MODE; + if (mode <= XTVEC_CLINT_VECTORED) { env->mtvec = val; + } else if (XTVEC_CLIC == fullmode && env->clic) { + /* + * CLIC mode hardwires xtvec bits 2-5 to zero. + * Layout: + * XLEN-1:6 base (WARL) + * 5:2 submode (WARL) - 0000 for CLIC + * 1:0 mode (WARL) - 11 for CLIC + */ + env->mtvec = (val & XTVEC_NBASE) | XTVEC_CLIC; } else { qemu_log_mask(LOG_UNIMP, "CSR_MTVEC: reserved mode not supported\n"); } @@ -2271,6 +2285,18 @@ static RISCVException write_mcounteren(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +static int read_mtvt(CPURISCVState *env, int csrno, target_ulong *val) +{ + *val = env->mtvt; + return RISCV_EXCP_NONE; +} + +static int write_mtvt(CPURISCVState *env, int csrno, target_ulong val) +{ + env->mtvt = val & XTVEC_NBASE; + return RISCV_EXCP_NONE; +} + /* Machine Trap Handling */ static RISCVException read_mscratch_i128(CPURISCVState *env, int csrno, Int128 *val) @@ -3122,9 +3148,24 @@ static RISCVException read_stvec(CPURISCVState *env, int csrno, static RISCVException write_stvec(CPURISCVState *env, int csrno, target_ulong val) { - /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */ - if ((val & 3) < 2) { + /* + * bits [1:0] encode mode; 0 = direct, 1 = vectored, 3 = CLIC, + * others reserved + */ + target_ulong mode = val & XTVEC_MODE; + target_ulong fullmode = val & XTVEC_FULL_MODE; + if (mode <= XTVEC_CLINT_VECTORED) { env->stvec = val; + } else if (XTVEC_CLIC == fullmode && env->clic) { + /* + * If only CLIC mode is supported, writes to bit 1 are also ignored and + * it is always set to one. CLIC mode hardwires xtvec bits 2-5 to zero. + * Layout: + * XLEN-1:6 base (WARL) + * 5:2 submode (WARL) - 0000 for CLIC + * 1:0 mode (WARL) - 11 for CLIC + */ + env->stvec = (val & XTVEC_NBASE) | XTVEC_CLIC; } else { qemu_log_mask(LOG_UNIMP, "CSR_STVEC: reserved mode not supported\n"); } @@ -3149,6 +3190,18 @@ static RISCVException write_scounteren(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +static int read_stvt(CPURISCVState *env, int csrno, target_ulong *val) +{ + *val = env->stvt; + return RISCV_EXCP_NONE; +} + +static int write_stvt(CPURISCVState *env, int csrno, target_ulong val) +{ + env->stvt = val & XTVEC_NBASE; + return RISCV_EXCP_NONE; +} + /* Supervisor Trap Handling */ static RISCVException read_sscratch_i128(CPURISCVState *env, int csrno, Int128 *val) @@ -5666,11 +5719,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { write_mhpmcounterh }, /* Machine Mode Core Level Interrupt Controller */ + [CSR_MTVT] = { "mtvt", clic, read_mtvt, write_mtvt }, [CSR_MINTSTATUS] = { "mintstatus", clic, read_mintstatus }, [CSR_MINTTHRESH] = { "mintthresh", clic, read_mintthresh, write_mintthresh }, /* Supervisor Mode Core Level Interrupt Controller */ + [CSR_STVT] = { "stvt", clic, read_stvt, write_stvt }, [CSR_SINTSTATUS] = { "sintstatus", clic, read_sintstatus }, [CSR_SINTTHRESH] = { "sintthresh", clic, read_sintthresh, write_sintthresh }, From patchwork Wed Aug 14 08:27:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Brockbank X-Patchwork-Id: 13763092 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id CF25EC3DA4A for ; Wed, 14 Aug 2024 08:43:33 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1se9bL-0006uM-RE; Wed, 14 Aug 2024 04:43: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 1se9bJ-0006g3-J8; Wed, 14 Aug 2024 04:43:25 -0400 Received: from mx0b-001ae601.pphosted.com ([67.231.152.168]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1se9bG-0005wd-99; Wed, 14 Aug 2024 04:43:25 -0400 Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 47E4gOKe023234; Wed, 14 Aug 2024 03:43:15 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s= PODMain02222019; bh=MaLEtMq/pIJzfGG6cS8WjmovSKbvm3aRu7TcVO7kh/A=; b= SIZ0g4eyI3tgBSGICKYgnnoLuPRgBXWc/q4BSZmBEzqhIjBEhLJX4qci5X//LxSQ aXIvHq3Jv3CVJadF9kJA3+oEfRjQJAobFjg3Q/kflp2j9LvzoBULu43kiExsy+DQ I0SFFApHKnIdeLe8QJZuJ73hlUq10aONpDPXlDf8Fxt0x6CYGYwheXoRM8bs+/KB cAhHZwJL5oCrppiIMIGtt4lUHn+4p5yJskr7dYyyGmA/HSqI+Ajm64JODUUyshvc ZWZuZpUxY3DErpFV0D5tqvDnu9mepHyyjXNE+ySHnboLXkxOUiEzfZU9iCSqVym3 ZomTLwpVkGgTjs5tAn+dDA== Received: from ausex01.ad.cirrus.com ([141.131.3.19]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 40x4mhmb8c-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 14 Aug 2024 03:43:14 -0500 (CDT) Received: from ausex01.ad.cirrus.com (141.131.37.95) by ausex01.ad.cirrus.com (141.131.37.95) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 14 Aug 2024 03:43:14 -0500 Received: from EDIN7BQBTG3.ad.cirrus.com (141.131.38.212) by anon-ausex01.ad.cirrus.com (141.131.37.95) with Microsoft SMTP Server id 15.2.1544.9 via Frontend Transport; Wed, 14 Aug 2024 03:43:12 -0500 From: Ian Brockbank To: , CC: Palmer Dabbelt , Alistair Francis , Bin Meng , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Ian Brockbank , LIU Zhiwei Subject: [PATCH 07/11] target/riscv: Update CSR xnxti in CLIC mode Date: Wed, 14 Aug 2024 09:27:37 +0100 Message-ID: <20240814083836.12256-14-Ian.Brockbank@cirrus.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240814083836.12256-1-Ian.Brockbank@cirrus.com> References: <20240814083836.12256-1-Ian.Brockbank@cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: EkTh0I53R6-dp5uI0VXoqDLJcRb3l1uk X-Proofpoint-GUID: EkTh0I53R6-dp5uI0VXoqDLJcRb3l1uk X-Proofpoint-Spam-Reason: orgsafe Received-SPF: pass client-ip=67.231.152.168; envelope-from=prvs=5956f96c7e=ian.brockbank@cirrus.com; helo=mx0b-001ae601.pphosted.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 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, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 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: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Ian Brockbank The CSR can be used by software to service the next horizontal interrupt when it has greater level than the saved interrupt context (held in xcause`.pil`) and greater level than the interrupt threshold of the corresponding privilege mode, Signed-off-by: LIU Zhiwei Signed-off-by: Ian Brockbank --- target/riscv/cpu_bits.h | 25 +++++++++ target/riscv/csr.c | 111 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) -- 2.46.0.windows.1 This message and any attachments may contain privileged and confidential information that is intended solely for the person(s) to whom it is addressed. If you are not an intended recipient you must not: read; copy; distribute; discuss; take any action in or make any reliance upon the contents of this message; nor open or read any attachment. If you have received this message in error, please notify us as soon as possible on the following telephone number and destroy this message including any attachments. Thank you. Cirrus Logic International (UK) Ltd and Cirrus Logic International Semiconductor Ltd are companies registered in Scotland, with registered numbers SC089839 and SC495735 respectively. Our registered office is at 7B Nightingale Way, Quartermile, Edinburgh, EH3 9EG, UK. Tel: +44 (0)131 272 7000. www.cirrus.com diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 279a6f889b..3744b34504 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -166,6 +166,7 @@ #define CSR_MCAUSE 0x342 #define CSR_MTVAL 0x343 #define CSR_MIP 0x344 +#define CSR_MNXTI 0x345 /* clic-spec-draft */ #define CSR_MINTSTATUS 0xfb1 /* clic-spec-draft */ #define CSR_MINTTHRESH 0x347 /* clic-spec-draft */ @@ -210,6 +211,7 @@ #define CSR_SCAUSE 0x142 #define CSR_STVAL 0x143 #define CSR_SIP 0x144 +#define CSR_SNXTI 0x145 /* clic-spec-draft */ #define CSR_SINTSTATUS 0xdb1 /* clic-spec-draft */ #define CSR_SINTTHRESH 0x147 /* clic-spec-draft */ @@ -561,6 +563,8 @@ #define MSTATUS_GVA 0x4000000000ULL #define MSTATUS_MPV 0x8000000000ULL +#define MSTATUS_WRITE_MASK 0x0000001f + #define MSTATUS64_UXL 0x0000000300000000ULL #define MSTATUS64_SXL 0x0000000C00000000ULL @@ -754,6 +758,27 @@ typedef enum RISCVException { #define SINTSTATUS_SIL 0x0000ff00 /* sil[15:8] */ #define SINTSTATUS_UIL 0x000000ff /* uil[7:0] */ +/* mcause */ +#define MCAUSE_INT (1 << (TARGET_LONG_BITS - 1)) +#define MCAUSE_MINHV 0x40000000 /* minhv */ +#define MCAUSE_MPP 0x30000000 /* mpp[1:0] */ +#define MCAUSE_MPIE 0x08000000 /* mpie */ +#define MCAUSE_MPIL 0x00ff0000 /* mpil[7:0] */ +#define MCAUSE_EXCCODE 0x00000fff /* exccode[11:0] */ + +/* scause */ +#define SCAUSE_INT (1 << (TARGET_LONG_BITS - 1)) +#define SCAUSE_SINHV 0x40000000 /* sinhv */ +#define SCAUSE_SPP 0x10000000 /* spp */ +#define SCAUSE_SPIE 0x08000000 /* spie */ +#define SCAUSE_SPIL 0x00ff0000 /* spil[7:0] */ +#define SCAUSE_EXCCODE 0x00000fff /* exccode[11:0] */ + +/* mcause & scause */ +#define XCAUSE_XPP_SHIFT 28 +#define XCAUSE_XPIE_SHIFT 27 +#define XCAUSE_XPIL_SHIFT 16 + /* mtvec & stvec */ #define XTVEC_MODE 0x03 #define XTVEC_SUBMODE 0x3c diff --git a/target/riscv/csr.c b/target/riscv/csr.c index be0071fd25..813a5b927f 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "qemu/log.h" +#include "qemu/main-loop.h" #include "qemu/timer.h" #include "cpu.h" #include "tcg/tcg-cpu.h" @@ -2936,6 +2937,77 @@ static RISCVException rmw_mviph(CPURISCVState *env, int csrno, return ret; } +static bool get_xnxti_status(CPURISCVState *env) +{ + int clic_irq, clic_priv, clic_il, pil; + + if (!env->exccode) { /* No interrupt */ + return false; + } + /* The system is not in a CLIC mode */ + if (!riscv_clic_is_clic_mode(env)) { + return false; + } else { + riscv_clic_decode_exccode(env->exccode, &clic_priv, &clic_il, + &clic_irq); + + if (env->priv == PRV_M) { + pil = MAX(get_field(env->mcause, MCAUSE_MPIL), env->mintthresh); + } else if (env->priv == PRV_S) { + pil = MAX(get_field(env->scause, SCAUSE_SPIL), env->sintthresh); + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "CSR: rmw xnxti with unsupported mode\n"); + exit(1); + } + + if ((clic_priv != env->priv) || /* No horizontal interrupt */ + (clic_il <= pil) || /* No higher level interrupt */ + (riscv_clic_shv_interrupt(env->clic, clic_irq))) { + /* CLIC vector mode */ + return false; + } else { + return true; + } + } +} + +static int rmw_mnxti(CPURISCVState *env, int csrno, target_ulong *ret_value, + target_ulong new_value, target_ulong write_mask) +{ + int clic_priv, clic_il, clic_irq; + bool ready; + if (write_mask) { + env->mstatus |= new_value & (write_mask & MSTATUS_WRITE_MASK); + } + + BQL_LOCK_GUARD(); + + ready = get_xnxti_status(env); + if (ready) { + riscv_clic_decode_exccode(env->exccode, &clic_priv, &clic_il, + &clic_irq); + if (write_mask) { + bool edge = riscv_clic_edge_triggered(env->clic, clic_irq); + if (edge) { + riscv_clic_clean_pending(env->clic, clic_irq); + } + env->mintstatus = set_field(env->mintstatus, + MINTSTATUS_MIL, clic_il); + env->mcause = set_field(env->mcause, MCAUSE_EXCCODE, clic_irq); + } + if (ret_value) { + *ret_value = (env->mtvt & ~0x3f) + sizeof(target_ulong) * clic_irq; + } + } else { + if (ret_value) { + *ret_value = 0; + } + } + + return RISCV_EXCP_NONE; +} + static int read_mintstatus(CPURISCVState *env, int csrno, target_ulong *val) { *val = env->mintstatus; @@ -3401,6 +3473,43 @@ static RISCVException rmw_siph(CPURISCVState *env, int csrno, return ret; } +static int rmw_snxti(CPURISCVState *env, int csrno, target_ulong *ret_value, + target_ulong new_value, target_ulong write_mask) +{ + int clic_priv, clic_il, clic_irq; + bool ready; + if (write_mask) { + env->mstatus |= new_value & (write_mask & MSTATUS_WRITE_MASK); + } + + BQL_LOCK_GUARD(); + + ready = get_xnxti_status(env); + if (ready) { + riscv_clic_decode_exccode(env->exccode, &clic_priv, &clic_il, + &clic_irq); + if (write_mask) { + bool edge = riscv_clic_edge_triggered(env->clic, clic_irq); + if (edge) { + riscv_clic_clean_pending(env->clic, clic_irq); + } + /* update the PRV_S parts of mintstatus */ + env->mintstatus = set_field(env->mintstatus, + MINTSTATUS_SIL, clic_il); + env->scause = set_field(env->scause, SCAUSE_EXCCODE, clic_irq); + } + if (ret_value) { + *ret_value = (env->stvt & ~0x3f) + sizeof(target_ulong) * clic_irq; + } + } else { + if (ret_value) { + *ret_value = 0; + } + } + + return RISCV_EXCP_NONE; +} + static int read_sintstatus(CPURISCVState *env, int csrno, target_ulong *val) { /* sintstatus is a filtered view of mintstatus with the PRV_M removed */ @@ -5720,12 +5829,14 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { /* Machine Mode Core Level Interrupt Controller */ [CSR_MTVT] = { "mtvt", clic, read_mtvt, write_mtvt }, + [CSR_MNXTI] = { "mnxti", clic, NULL, NULL, rmw_mnxti }, [CSR_MINTSTATUS] = { "mintstatus", clic, read_mintstatus }, [CSR_MINTTHRESH] = { "mintthresh", clic, read_mintthresh, write_mintthresh }, /* Supervisor Mode Core Level Interrupt Controller */ [CSR_STVT] = { "stvt", clic, read_stvt, write_stvt }, + [CSR_SNXTI] = { "snxti", clic, NULL, NULL, rmw_snxti }, [CSR_SINTSTATUS] = { "sintstatus", clic, read_sintstatus }, [CSR_SINTTHRESH] = { "sintthresh", clic, read_sintthresh, write_sintthresh },