From nobody Mon Apr 6 16:47:57 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1773863110; cv=none; d=zohomail.com; s=zohoarc; b=Fkq6KT9pJx2PQ87Z59MWg73oYkSHdVostB8C4/QDS4rXhth9SEGv+Ix38Qg6LU1gFHgQ6MZ9sQoYjcJmm47G+FvN8rlsUQoj7r4uhI0K1B+mwLCbTiwgTD6SekeGdd+quGEte3fbFOTNlrwsIJq247hGzwG5UxCjKcCKO+jXBjA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773863110; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=MyLex6OTnYvy/DWccP0n2Mw9tvmu2JJXYlF6lIdz31c=; b=T+rv5z/UmlCX/qQkpEk2sLaXYMpFS4xa1a8Xrm5mLMgzuYaEEcQ8WdlBovroDx9eNV2i/sMJnwSn7nPZ2Rimc6/ZJXvbhfADfxRXhHvQ3YvjIFRvACwSqxzgus8bm15D/TJLmbarCsRodN/4WZY3xOlyUh/YUqtojCMrA7mN/4M= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773863110085916.0350191993018; Wed, 18 Mar 2026 12:45:10 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w2woR-0005uI-Qk; Wed, 18 Mar 2026 15:44:15 -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 1w2w0s-0002Un-CN for qemu-devel@nongnu.org; Wed, 18 Mar 2026 14:53:02 -0400 Received: from mail-wm1-x330.google.com ([2a00:1450:4864:20::330]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w2w0p-00065G-Qr for qemu-devel@nongnu.org; Wed, 18 Mar 2026 14:53:02 -0400 Received: by mail-wm1-x330.google.com with SMTP id 5b1f17b1804b1-482f454be5bso12561085e9.0 for ; Wed, 18 Mar 2026 11:52:59 -0700 (PDT) Received: from luis-IdeaPad-Flex-5-14ALC05.. ([148.69.202.102]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-486f8b0bc58sm16135905e9.3.2026.03.18.11.52.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 Mar 2026 11:52:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773859978; x=1774464778; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=MyLex6OTnYvy/DWccP0n2Mw9tvmu2JJXYlF6lIdz31c=; b=HA8Z+eM0i233D6Jxws26wt/4pG6VFAYoyHO9jmnKd/XB/XY5KVINWyiGui+vMmoBIS U2jqGtuG7Vx6STq5KAyKA6ZpDwLzd4JEUuYB2Ow8nqM+ter1LJOa8HyDDargszio8gRk m4W9JUHT0zPkJb/ChZ7VrcX9N3Jvw66QKFUGws4XkKMiFLh2CvK2W1lbnf9/wiiSbwOU iRRhyRPPPy3Rr4GNjrkN4wdXNfZe1XqQLUIpmi3ZX+DBfjKHuV9OElwNadpKhHCmkDDr fjrdtYlBTAjJGo8G94ntRnn+hLLM5FriM4Xm1Y7N5WwSsJpnkoQm3CfF7xzxuRnuvDBO s3NA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773859978; x=1774464778; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=MyLex6OTnYvy/DWccP0n2Mw9tvmu2JJXYlF6lIdz31c=; b=pFv0ttLpH0RvxA3CVymodJ/rsXZAViCvbkYUB6v5C/lbm+RQZbYdWeHASjOfQyDjtH CMndRJQBbppA1k2ZyDJVFtWYOTOG48fd4M3a338n/ZrMONNomEGHUlY4oFZHJk2+MpF/ wurbhPXHcvywaeBE2LFlULnjL2yJKj8Qp5sb0fsWoi+2XUv5bVKcanuf5jz+UzAM3xqS LH8lmxyBBPhFsyFDTsykbisYp/zgOuR+yTXuBeiex4qLswQoXr5IMX3Ufhldt87iCxxd nffXsiaJrsxsXvtP9j1364P9F+eZl1p3CAcmiu+YErOrXbCBo6ueJop1U3D/nzh+S8zn jCfg== X-Gm-Message-State: AOJu0Yw16QfKy6o/nG0f5nK+2X4uWcL8+9cXvjzsEWLr+fQdsEs4sNSt PliHHyew/BbEvnJJWrPEFpGBavEc2zV/be3Cao25aKu0z+I5/Evp1VBU1WfYUq52fuU= X-Gm-Gg: ATEYQzwQgZvrercQchcYu8VJmf+9Z61RFzAE4qQN/JC2BBjy3PKgVtt0g4LPA58foSV DDHoCR+c8P2vdjoLBZtTuZxTyiFaP9qrMaAhrfb/eYAbSuF0d9YFpWJjbIMBEk25v42ZrC6I8+i aProFSfi0UIbtd6/EI23GQRyGJmIpPqlI6+Pjn4N8aDGz8/1j/OsIiDqzWaTp332EGHHIFC4950 OOXTps4Q3NzYi67C9uQDjdRQKN3v9C52XI52j+UtQzTg5jVhyvGk86ow8PDsDvMWbPGZEKnMQ5k 1MB9msEtCoyAd8vteVB9SShdI6Ds3DdWOq0c4YK+cOg+S8L79OMSM8vhREeio28WAfMNPKMRwEZ jd53oMvAYekOzVfD7hW0w9P4DNwge2dt8fA94ticp2vimf1PdXkzXHIn5VYkLYDuF6eLRKeGurV EM4wZmsOkJaRQ9bPk+te62FtPM/IKUlcFe+OMyVuae46CWVEZimuUJUS1iDkBceGuYhwhbws51b CNJTU4JfRth6J82zE1JymcwUBBKotG6EchtGfk= X-Received: by 2002:a05:600c:3544:b0:485:3e00:944a with SMTP id 5b1f17b1804b1-486f8b35605mr11473145e9.9.1773859977695; Wed, 18 Mar 2026 11:52:57 -0700 (PDT) From: luisccc To: qemu-devel@nongnu.org Cc: luisccc , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , qemu-riscv@nongnu.org (open list:RISC-V TCG CPUs) Subject: [RFC PATCH 1/6] target/riscv: Add SPMP infrastructure Date: Wed, 18 Mar 2026 18:52:31 +0000 Message-ID: <20260318185238.99143-2-luisccunha8@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260318185238.99143-1-luisccunha8@gmail.com> References: <20260318185238.99143-1-luisccunha8@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::330; envelope-from=luisccunha8@gmail.com; helo=mail-wm1-x330.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.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, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 18 Mar 2026 15:44:14 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1773863113757154100 Introduce the initial infrastructure required for the RISC-V S-mode Physica= l Memory Protection (SPMP) implementation. This patch adds the SPMP source files, integrates them into the build syste= m, and introduces the CPU state and configuration fields required by subseq= uent patches. No SPMP checks are enforced yet. Signed-off-by: Luis Cunha --- target/riscv/cpu.h | 6 + target/riscv/cpu_cfg_fields.h.inc | 1 + target/riscv/meson.build | 1 + target/riscv/spmp.c | 512 ++++++++++++++++++++++++++++++ target/riscv/spmp.h | 83 +++++ 5 files changed, 603 insertions(+) create mode 100644 target/riscv/spmp.c create mode 100644 target/riscv/spmp.h diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 35d1f6362c..c265098324 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -178,8 +178,11 @@ extern RISCVCPUImpliedExtsRule *riscv_multi_ext_implie= d_rules[]; #define OLD_MAX_RISCV_PMPS (16) #define MIN_RISCV_PMP_GRANULARITY 4 =20 +#define MAX_RISCV_SPMPS (64) + #if !defined(CONFIG_USER_ONLY) #include "pmp.h" +#include "spmp.h" #include "debug.h" #endif =20 @@ -442,6 +445,9 @@ struct CPUArchState { pmp_table_t pmp_state; target_ulong mseccfg; =20 + /* S-mode Physical Memory Protection */ + spmp_table_t spmp_state; + /* trigger module */ target_ulong trigger_cur; target_ulong tdata1[RV_MAX_TRIGGERS]; diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/cpu_cfg_field= s.h.inc index 70ec650abf..72d417c241 100644 --- a/target/riscv/cpu_cfg_fields.h.inc +++ b/target/riscv/cpu_cfg_fields.h.inc @@ -156,6 +156,7 @@ BOOL_FIELD(ext_xmipslsp) =20 BOOL_FIELD(mmu) BOOL_FIELD(pmp) +BOOL_FIELD(spmp) BOOL_FIELD(debug) BOOL_FIELD(misa_w) =20 diff --git a/target/riscv/meson.build b/target/riscv/meson.build index 3842c7c1a8..d03f3a7826 100644 --- a/target/riscv/meson.build +++ b/target/riscv/meson.build @@ -34,6 +34,7 @@ riscv_system_ss =3D ss.source_set() riscv_system_ss.add(files( 'arch_dump.c', 'pmp.c', + 'spmp.c', 'debug.c', 'monitor.c', 'machine.c', diff --git a/target/riscv/spmp.c b/target/riscv/spmp.c new file mode 100644 index 0000000000..85c5259b33 --- /dev/null +++ b/target/riscv/spmp.c @@ -0,0 +1,512 @@ +/* + * QEMU RISC-V SPMP (S-mode Physical Memory Protection) + * + * Author: + * Lu=C3=ADs Cunha + * + * Based on an earlier SPMP prototype by: + * Bicheng Yang + * Dong Du + * + * This provides a RISC-V S-mode Physical Memory Protection interface. + * + * 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 f= or + * more details. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "cpu.h" +#include "cpu_bits.h" +#include "trace.h" +#include "exec/target_page.h" + +/* + * Accessor method to extract address matching type 'a field' from cfg reg + */ +uint8_t spmp_get_a_field(uint8_t cfg) +{ + uint8_t a =3D cfg >> 3; + return a & 0x3; +} + +/* + * Check whether mstatus.sum is set. + */ +static inline int sum_is_set(CPURISCVState *env) +{ + if (env->mstatus & MSTATUS_SUM) { + return 1; + } + + return 0; +} + +void spmp_decode_napot(target_ulong a, target_ulong *sa, target_ulong *ea) +{ + /* + * aaaa...aaa0 8-byte NAPOT range + * aaaa...aa01 16-byte NAPOT range + * aaaa...a011 32-byte NAPOT range + * ... + * aa01...1111 2^XLEN-byte NAPOT range + * a011...1111 2^(XLEN+1)-byte NAPOT range + * 0111...1111 2^(XLEN+2)-byte NAPOT range + * 1111...1111 Reserved + */ + a =3D (a << 2) | 0x3; + *sa =3D a & (a + 1); + *ea =3D a | (a + 1); +} + +static void spmp_update_rule_addr(CPURISCVState *env, uint32_t spmp_index) +{ + uint8_t this_cfg =3D env->spmp_state.spmp[spmp_index].cfg_reg; + target_ulong this_addr =3D env->spmp_state.spmp[spmp_index].addr_reg; + target_ulong prev_addr =3D 0u; + target_ulong sa =3D 0u; + target_ulong ea =3D 0u; + + if (spmp_index >=3D 1u) { + prev_addr =3D env->spmp_state.spmp[spmp_index - 1].addr_reg; + } + + switch (spmp_get_a_field(this_cfg)) { + case SPMP_AMATCH_OFF: + sa =3D 0u; + ea =3D -1; + break; + + case SPMP_AMATCH_TOR: + sa =3D prev_addr << 2; /* shift up from [xx:0] to [xx+2:2] */ + ea =3D (this_addr << 2) - 1u; + break; + + case SPMP_AMATCH_NA4: + sa =3D this_addr << 2; /* shift up from [xx:0] to [xx+2:2] */ + ea =3D (sa + 4u) - 1u; + break; + + case SPMP_AMATCH_NAPOT: + spmp_decode_napot(this_addr, &sa, &ea); + break; + + default: + sa =3D 0u; + ea =3D 0u; + break; + } + + env->spmp_state.addr[spmp_index].sa =3D sa; + env->spmp_state.addr[spmp_index].ea =3D ea; +} + +static void spmp_update_rule_nums(CPURISCVState *env) +{ + int i; + + env->spmp_state.num_active_rules =3D 0; + for (i =3D 0; i < MAX_RISCV_SPMPS; i++) { + const uint8_t a_field =3D + spmp_get_a_field(env->spmp_state.spmp[i].cfg_reg); + if (SPMP_AMATCH_OFF !=3D a_field) { + env->spmp_state.num_active_rules++; + } + } +} + +/* + * Convert cfg/addr reg values here into simple 'sa' --> start address and= 'ea' + * end address values. + * This function is called relatively infrequently whereas the check that + * an address is within a spmp rule is called often, so optimise that one + */ +static void spmp_update_rule(CPURISCVState *env, uint32_t spmp_index) +{ + spmp_update_rule_addr(env, spmp_index); + spmp_update_rule_nums(env); +} + +static uint8_t spmp_is_in_range(CPURISCVState *env, int spmp_index, + target_ulong addr) +{ + if ((addr >=3D env->spmp_state.addr[spmp_index].sa) + && (addr <=3D env->spmp_state.addr[spmp_index].ea)) { + return 1; + } + + return 0; +} + +static bool spmp_get_spmpen_bit(CPURISCVState *env, int index) +{ + return true; +} + +/* + * Check if the address has required RWX privs when no SPMP entry is match= ed. + */ +static bool spmp_hart_has_privs_default(CPURISCVState *env, target_ulong a= ddr, + spmp_priv_t *allowed_privs, + target_ulong mode) +{ + bool ret; + mode =3D env->virt_enabled ? PRV_U : mode; + + if ((!riscv_cpu_cfg(env)->spmp) || !(mode =3D=3D PRV_U)) { + /* + * The SPMP proposal states three circumstances that the access + * is allowed: + * 1. The HW does not implement any SPMP entry. + * 2. If the effective privilege mode of the access is S and no SP= MP + * entry matches + * 3. The access mode is M. + */ + ret =3D true; + *allowed_privs =3D SPMP_READ | SPMP_WRITE | SPMP_EXEC; + } else { + /* + * U-mode is not allowed to succeed if they don't match a rule, + * but there are rules. We've checked for those rules earlier in t= his + * function. + */ + ret =3D false; + *allowed_privs =3D 0; + } + + return ret; +} + + +/* + * Public Interface + */ + +/* + * Check if the address has required RWX privs to complete desired operati= on + */ +bool spmp_hart_has_privs(CPURISCVState *env, target_ulong addr, + target_ulong size, spmp_priv_t privs, spmp_priv_t *allowed_privs, + target_ulong mode) +{ + int i =3D 0; + int ret =3D -1; + int spmp_size =3D 0; + target_ulong s =3D 0; + target_ulong e =3D 0; + bool spmpen_en =3D false; + + /* If it is either VS or VU mode, we treat it as U mode */ + mode =3D env->virt_enabled ? PRV_U : mode; + + /* Short cut for M-mode access */ + if (mode =3D=3D PRV_M) { + *allowed_privs =3D SPMP_READ | SPMP_WRITE | SPMP_EXEC; + return true; + } + + /* Short cut if no rules */ + if (env->spmp_state.num_active_rules =3D=3D 0) { + return spmp_hart_has_privs_default(env, addr, allowed_privs, mode); + } + + if (size =3D=3D 0) { + if (riscv_cpu_cfg(env)->mmu) { + /* + * If size is unknown (0), assume that all bytes + * from addr to the end of the page will be accessed. + */ + spmp_size =3D -(addr | TARGET_PAGE_MASK); + } else { + spmp_size =3D sizeof(target_ulong); + } + } else { + spmp_size =3D size; + } + + /* It depends on mpmpdeleg */ + for (i =3D 0; i < env->spmp_state.num_deleg_rules; i++) { + s =3D spmp_is_in_range(env, i, addr); + e =3D spmp_is_in_range(env, i, addr + spmp_size - 1); + spmpen_en =3D spmp_get_spmpen_bit(env, i); + + /* partially inside */ + if ((s + e) =3D=3D 1) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: spmp violation - access is partially inside= \n", + __func__); + ret =3D 0; + break; + } + + /* fully inside */ + const uint8_t a_field =3D + spmp_get_a_field(env->spmp_state.spmp[i].cfg_reg); + + /* + * Convert the SPMP permissions to match the truth table in the + * SPMP spec. + */ + const uint8_t spmp_operation =3D + (env->spmp_state.spmp[i].cfg_reg & SPMP_EX= EC) + | (env->spmp_state.spmp[i].cfg_reg & SPMP_= WRITE) + | (env->spmp_state.spmp[i].cfg_reg & SPMP_= READ); + + if (((s + e) =3D=3D 2) && (SPMP_AMATCH_OFF !=3D a_field) && spmpen= _en) { + /* + * If the SPMP entry is not off, spmpen bit is set, and the ad= dress + * is in range, do the priv check + */ + + /* Shared not set */ + if (!(env->spmp_state.spmp[i].cfg_reg & SPMP_SHARED)) { + /* + * Deny if: + * S mode access, with SUM not set, and UMODE set. + * U mode access, with UMODE not set. + */ + if ((mode =3D=3D PRV_S && !sum_is_set(env) && + (env->spmp_state.spmp[i].cfg_reg & SPMP_UMODE)) || + (mode =3D=3D PRV_U && + !(env->spmp_state.spmp[i].cfg_reg & SPMP_UMODE))) { + *allowed_privs =3D 0; + } + /* + * EnforceNoX if: + * S mode access, with SUM set, and UMODE set. + * Note: The specification has the table in RWX, the opo= site + * of the order in the cfg reg. + */ + else if (mode =3D=3D PRV_S && sum_is_set(env) && + (env->spmp_state.spmp[i].cfg_reg & SPMP_UMODE)) { + switch (spmp_operation) { + case 0: + case 2: + case 4: + case 6: + *allowed_privs =3D 0; + break; + case 1: + case 5: + *allowed_privs =3D SPMP_READ; + break; + case 3: + case 7: + *allowed_privs =3D SPMP_READ | SPMP_WRITE; + break; + default: + g_assert_not_reached(); + } + } else { + /* Check for reserved configs */ + if (spmp_operation =3D=3D 2 || spmp_operation =3D=3D 6= ) { + *allowed_privs =3D 0; + } else { + /* U mode falls here - Enforce */ + *allowed_privs =3D spmp_operation & 0x7; + } + } + } + /* Set Shared bit */ + else { + if (mode =3D=3D PRV_S) { + /* Check for reserved configs */ + if (spmp_operation =3D=3D 2 || spmp_operation =3D=3D 6= ) { + *allowed_privs =3D 0; + } else { + *allowed_privs =3D spmp_operation & 0x7; + } + } else { + switch (spmp_operation) { + case 0: + case 2: + case 6: + *allowed_privs =3D 0; + break; + case 1: + case 3: + *allowed_privs =3D SPMP_READ; + break; + case 4: + case 7: + *allowed_privs =3D SPMP_EXEC; + break; + case 5: + *allowed_privs =3D SPMP_READ | SPMP_EXEC; + break; + default: + g_assert_not_reached(); + } + } + } + + ret =3D ((privs & *allowed_privs) =3D=3D privs); + break; + } + } + + /* No rule matched */ + if (ret =3D=3D -1) { + return spmp_hart_has_privs_default(env, addr, allowed_privs, mode); + } + + return ret =3D=3D 1 ? true : false; +} + +static bool is_entry_locked(CPURISCVState *env, int index) +{ + uint8_t next_a_field =3D SPMP_AMATCH_TOR; + + /* + * Verify if it is the last entry. + * If not, check if the next entry is TOR type. + * If it is TOR, check if either this or next entry is locked. + */ + if (index < env->spmp_state.num_deleg_rules - 1) { + next_a_field =3D + spmp_get_a_field(env->spmp_state.spmp[index + 1].cfg_r= eg); + + if (next_a_field =3D=3D SPMP_AMATCH_TOR) { + return (env->spmp_state.locked_rules >> index) & 0x1 + || (env->spmp_state.locked_rules >> (index + 1)) & 0x1; + } + } + + /* Otherwise, just check this entry */ + return (env->spmp_state.locked_rules >> index) & 0x1; +} + +/* + * Accessor to set the cfg reg for a specific SPMP/HART + * Bounds checks. + */ +void spmpcfg_csr_write(CPURISCVState *env, uint32_t reg_index, + target_ulong val, bool m_mode_access) +{ + bool locked =3D m_mode_access ? false : is_entry_locked(env, reg_index= ); + + /* If within bounds and not locked */ + if (reg_index < env->spmp_state.num_deleg_rules && !locked) { + + env->spmp_state.spmp[reg_index].cfg_reg =3D val; + /* Storing this allows for faster switching with the sspmpen ext */ + env->spmp_state.locked_rules |=3D + ((val & SPMP_LOCK) >> 7 & 0x1) << reg_inde= x; + + spmp_update_rule(env, reg_index); + } else { + if (locked) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: ignoring spmpcfg write - locked entry\n", __func_= _); + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: ignoring spmpcfg write - out of bounds\n", __func= __); + } + } +} + +/* + * Handle a read from a spmpcfg CSR + */ +target_ulong spmpcfg_csr_read(CPURISCVState *env, uint32_t reg_index) +{ + if (reg_index < env->spmp_state.num_deleg_rules) { + return env->spmp_state.spmp[reg_index].cfg_reg; + } + + return 0; +} + +/* + * Handle a write to a spmpaddr CSR + */ +void spmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index, + target_ulong val, bool m_mode_access) +{ + bool locked =3D m_mode_access ? false : is_entry_locked(env, addr_inde= x); + + /* If within bounds and not locked */ + if (addr_index < env->spmp_state.num_deleg_rules && !locked) { + + env->spmp_state.spmp[addr_index].addr_reg =3D val; + spmp_update_rule(env, addr_index); + } else { + if (locked) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: ignoring spmpaddr write - locked entry\n", __func= __); + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: ignoring spmpaddr write - out of bounds\n", __fun= c__); + } + } +} + +/* + * Handle a read from a spmpaddr CSR + */ +target_ulong spmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index) +{ + target_ulong val =3D 0; + + if (addr_index < env->spmp_state.num_deleg_rules) { + val =3D env->spmp_state.spmp[addr_index].addr_reg; + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: ignoring spmpaddr read - out of bounds\n", __fu= nc__); + } + + return val; +} + +/* + * Handle a write to the sspmpen CSR + */ +void sspmpen_csr_write(CPURISCVState *env, uint64_t new_val) +{ + uint64_t mask =3D (env->spmp_state.num_deleg_rules =3D=3D MAX_RISCV_SP= MPS) ? + ~0ULL : ((1ULL << env->spmp_state.num_deleg_rules) - 1= ); + + /* If the rule is locked, the bit cannot be changed */ + env->spmp_state.spmpen =3D + (env->spmp_state.spmpen & env->spmp_state.locked_rules= ) | + (new_val & ~env->spmp_state.locked_rules); + env->spmp_state.spmpen &=3D mask; +} + +/* + * Convert SPMP privilege to TLB page privilege. + */ +int spmp_priv_to_page_prot(spmp_priv_t spmp_priv) +{ + int prot =3D 0; + + if (spmp_priv & SPMP_READ) { + prot |=3D PAGE_READ; + } + if (spmp_priv & SPMP_WRITE) { + prot |=3D PAGE_WRITE; + } + if (spmp_priv & SPMP_EXEC) { + prot |=3D PAGE_EXEC; + } + + return prot; +} + +void spmp_unlock_entries(CPURISCVState *env) +{ + /* Reset everything */ + for (int i =3D 0; i < MAX_RISCV_SPMPS; i++) { + env->spmp_state.spmp[i].cfg_reg &=3D ~(SPMP_LOCK | SPMP_AMATCH); + } + + env->spmp_state.locked_rules =3D 0; + env->spmp_state.num_active_rules =3D 0; +} diff --git a/target/riscv/spmp.h b/target/riscv/spmp.h new file mode 100644 index 0000000000..02a05acdf8 --- /dev/null +++ b/target/riscv/spmp.h @@ -0,0 +1,83 @@ +/* + * QEMU RISC-V SPMP (S-mode Physical Memory Protection) + * + * Author: + * Lu=C3=ADs Cunha + * + * Based on an earlier SPMP prototype by: + * Bicheng Yang + * Dong Du + * + * This provides a RISC-V S-mode Physical Memory Protection interface. + * + * 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 f= or + * more details. + */ + +#ifndef RISCV_SPMP_H +#define RISCV_SPMP_H + + +typedef enum { + SPMP_READ =3D (1 << 0), + SPMP_WRITE =3D (1 << 1), + SPMP_EXEC =3D (1 << 2), + SPMP_AMATCH =3D (3 << 3), + SPMP_LOCK =3D (1 << 7), + SPMP_UMODE =3D (1 << 8), + SPMP_SHARED =3D (1 << 9) +} spmp_priv_t; + +typedef enum { + SPMP_AMATCH_OFF, /* Null (off) */ + SPMP_AMATCH_TOR, /* Top of Range */ + SPMP_AMATCH_NA4, /* Naturally aligned four-byte region */ + SPMP_AMATCH_NAPOT /* Naturally aligned power-of-two region */ +} spmp_am_t; + +typedef struct { + target_ulong addr_reg; + uint16_t cfg_reg; +} spmp_entry_t; + +typedef struct { + target_ulong sa; + target_ulong ea; +} spmp_addr_t; + +typedef struct { + spmp_entry_t spmp[MAX_RISCV_SPMPS]; + spmp_addr_t addr[MAX_RISCV_SPMPS]; + + uint8_t num_active_rules; + uint8_t num_deleg_rules; + uint64_t spmpen; + uint64_t locked_rules; +} spmp_table_t; + +void spmpcfg_csr_write(CPURISCVState *env, uint32_t reg_index, + target_ulong val, bool m_mode_access); +target_ulong spmpcfg_csr_read(CPURISCVState *env, uint32_t reg_index); + +target_ulong spmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index); +void spmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index, + target_ulong val, bool m_mode_access); + +void sspmpen_csr_write(CPURISCVState *env, uint64_t new_val); + +bool spmp_hart_has_privs(CPURISCVState *env, target_ulong addr, + target_ulong size, spmp_priv_t privs, spmp_priv_t *allowed_privs, + target_ulong mode); +int spmp_priv_to_page_prot(spmp_priv_t spmp_priv); +void spmp_unlock_entries(CPURISCVState *env); + +void spmp_decode_napot(target_ulong a, target_ulong *sa, target_ulong *ea); +uint8_t spmp_get_a_field(uint8_t cfg); + +#endif --=20 2.43.0 From nobody Mon Apr 6 16:47:57 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1773863094; cv=none; d=zohomail.com; s=zohoarc; b=J/IUfr5ZpxMYGQ4H0k1r/yqc6aJyObtfYccMkRH+/cllhDAewXxcIiyHm5wYZ6EnKYDAXyn0q9k4sa5vuwrTTCaX1WHkDfVGjTHt1XvL8xBBI82mjkBNgTm8w+cvm0zhfo7DSzG4vBQ2eBMPdNcQ4NDIiqfvYM7oeaN2UCVvntQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773863094; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=jDtU3k6M3GiftyqmYDg1aRbMp4kh06I9uB7ga9EAvCk=; b=WlwBJPakh5nj3K4rIQV7SjAcs9cc+VrGJPH3c5EVbQ2zlg7ToSE/OkKkKIiCvvAsMHAC7GtxEOWp1dCcroCh2Df+NOCSOz9cb+WjZjNbbyGvj5cBKv5af3zeVJPFx+oW7gKWa6U0oqgVm9S8w67pcquuadW5C11j9g3YYyyyPdQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 177386309450015.309031214922356; Wed, 18 Mar 2026 12:44:54 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w2woU-0005un-FD; Wed, 18 Mar 2026 15:44:18 -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 1w2w10-0002Vz-64 for qemu-devel@nongnu.org; Wed, 18 Mar 2026 14:53:10 -0400 Received: from mail-wm1-x32d.google.com ([2a00:1450:4864:20::32d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w2w0x-00066j-3z for qemu-devel@nongnu.org; Wed, 18 Mar 2026 14:53:09 -0400 Received: by mail-wm1-x32d.google.com with SMTP id 5b1f17b1804b1-486507134e4so2017615e9.0 for ; Wed, 18 Mar 2026 11:53:06 -0700 (PDT) Received: from luis-IdeaPad-Flex-5-14ALC05.. ([148.69.202.102]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-486f8b0bc58sm16135905e9.3.2026.03.18.11.53.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 Mar 2026 11:53:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773859985; x=1774464785; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=jDtU3k6M3GiftyqmYDg1aRbMp4kh06I9uB7ga9EAvCk=; b=nrRFbKrsM3ghrCBwefMS1BEYh+UYgjz5VQiZvZZDjC5P/KzNdpAUcTUz3BVMP3lgW+ zdhImmsPyqHdNL5DdIkzmfjfTN6rmYOKpSlgVz9o1WcfqQ2FbBgSYiAwm/0Pl+9lXVm4 JmtioOMsjCIft78UVmNJSe65sXn0G8LQ1N5MDGh7ZdX07DfCZiyQdmyiFQQWDwnaAQ47 wW9c5Z3ozxjgW2CwxRxngwvo8cfEA2V8Bz94fHiDBcTIis72ix8/G/xhI+uOkkrUzl/2 dLMP2820x5MDeBQX+0ypDQrRwDehoy+1kwoCk74ScJfyG0C8c8BYZH8RI2v89nxri6/M r1jA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773859985; x=1774464785; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=jDtU3k6M3GiftyqmYDg1aRbMp4kh06I9uB7ga9EAvCk=; b=P7YZL4kPQUHMmptoqZGnqCA4ILKStESR2hA7h/zuKy+6yo80JUM4GVPqhGbHU5930b xhtOwaXQdiu+bX+blxfxvsRZJwjLxfce8qZTok9q/+I+DUOg+X88J2ANqegQZfcSFg1B xkEJywSQfVK7YWzaOeQqAVGl8CJoLXsHEwFlZJUvVM1ZQWOLheNaQO+qVFEeMEmABPzb jW203KrKl0Pv/jAVi0mwq54H/qUVwxBbMyiIgM6oqweTmQHbnofplwhMUUhKhLNU3ySx nZVEfCxbii0+Cqink0JPTbz8CBWJvYcMir96VLE/vgTJsSYdujZamhk0SNI1g0YaiDQG 3VeQ== X-Gm-Message-State: AOJu0YxgW+vyL1TxFQOCbYVLpX2ydxVH4VhngYqXasD+ecQXhHlfKpSg 8sMNoXpgY3+lQ3AkLkJ5JI1dvtJb2EeKN6e7aLEmxKy9yuuQ0WJKL7fKDbfFlDGtqbk= X-Gm-Gg: ATEYQzxqzPesX+t+O1lIvXX9j9E9JaebtHFvdqC/1MRHAvzndn+H2nfcYwXJ9OxolzH 5bvZC10duutqDixQeeB6fzUwjzdfuK0DC+/GqLo5yN6UnZBSfg986FrQl4Ys1yzHRvyww9SdJK9 N2Vr21hAIe1R/V/ybJMMB7j8gkSOV5K55j+QT6rFfOlTt5Ox2gZ3yic6Qqu8AOkr/E1zEWxqwSz FHJTT7Js5eFifCfgS0omDKnoRZllvFBU5jCzSHNktQiyklP5oMMVGqXGO8mTvHchrjo16p5czeG KW16HgmWUUjP9X8sZVhJRXKgvXwlB6c88HXZNBq4TN2m+6B82BXJxCwYS7teANEanfL2ZE2X2QY 71PzCMo5NmmSoZ9tiRBjik8DHYfU+dCkq1kA0OTMTHqpvKDHkko9qYYC5KL0XIZt0m+tdEJ2byx HI34FegFJ0qb/GtD+8BNgXUMBQOg4MirhJH6SOSWL8Rhp22dahqFGa5sbucgu2NULzvhJHdc4je v/NRR5q2IGgWej6ZmP5UCrOKBtQsgk1BHSKsXA= X-Received: by 2002:a05:600c:4a17:b0:485:3b34:2f62 with SMTP id 5b1f17b1804b1-486f44222d2mr51017495e9.14.1773859985208; Wed, 18 Mar 2026 11:53:05 -0700 (PDT) From: luisccc To: qemu-devel@nongnu.org Cc: luisccc , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , qemu-riscv@nongnu.org (open list:RISC-V TCG CPUs) Subject: [RFC PATCH 2/6] target/riscv: Add SPMP CSR configuration Date: Wed, 18 Mar 2026 18:52:32 +0000 Message-ID: <20260318185238.99143-3-luisccunha8@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260318185238.99143-1-luisccunha8@gmail.com> References: <20260318185238.99143-1-luisccunha8@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::32d; envelope-from=luisccunha8@gmail.com; helo=mail-wm1-x32d.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.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, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 18 Mar 2026 15:44:17 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1773863095752158500 Content-Type: text/plain; charset="utf-8" Introduce the CSR definitions and handlers to configure S-mode Physical Me= mory Protection (SPMP). This patch adds the SPMP CSR bit definitions. The implementation allows sof= tware to configure SPMP state but does not yet enforce memory access checks. Signed-off-by: Luis Cunha --- target/riscv/cpu_bits.h | 3 ++ target/riscv/csr.c | 73 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index b62dd82fe7..9b7ab28bba 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -1049,6 +1049,9 @@ typedef enum CTRType { #define ISELECT_CD_LAST 0x5f #define ISELECT_MASK_SXCSRIND 0xfff =20 +/* SPMP Values for Indirect CSR Access Extension */ +#define ISELECT_SPMP_BASE 0x100 + /* Dummy [M|S|VS]ISELECT value for emulating [M|S|VS]TOPEI CSRs */ #define ISELECT_IMSIC_TOPEI (ISELECT_MASK_AIA + 1) =20 diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 5064483917..167d84d92a 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -759,6 +759,16 @@ static RISCVException pmp(CPURISCVState *env, int csrn= o) return RISCV_EXCP_ILLEGAL_INST; } =20 +static RISCVException spmp(CPURISCVState *env, int csrno) +{ + if (!riscv_cpu_cfg(env)->spmp) { + return RISCV_EXCP_ILLEGAL_INST; + } + + /* SPMP can only exist, if smode exists */ + return smode(env, csrno); +} + static RISCVException have_mseccfg(CPURISCVState *env, int csrno) { if (riscv_cpu_cfg(env)->ext_smepmp) { @@ -2454,6 +2464,12 @@ static bool xiselect_ctr_range(int csrno, target_ulo= ng isel) csrno < CSR_MIREG; } =20 +static bool xiselect_spmp_range(target_ulong isel) +{ + return (ISELECT_SPMP_BASE <=3D isel && + isel <=3D ISELECT_SPMP_BASE + MAX_RISCV_SPMPS); +} + static int rmw_iprio(target_ulong xlen, target_ulong iselect, uint8_t *iprio, target_ulong *val, target_ulong new_val, @@ -2790,6 +2806,9 @@ static int rmw_xireg_ctr(CPURISCVState *env, int csrn= o, return 0; } =20 +static int rmw_xireg_spmp(CPURISCVState *env, int csrno, + target_ulong isel, target_ulong *val, + target_ulong new_val, target_ulong wr_mask); /* * rmw_xireg_csrind: Perform indirect access to xireg and xireg2-xireg6 * @@ -2808,6 +2827,14 @@ static int rmw_xireg_csrind(CPURISCVState *env, int = csrno, ret =3D rmw_xireg_cd(env, csrno, isel, val, new_val, wr_mask); } else if (xiselect_ctr_range(csrno, isel)) { ret =3D rmw_xireg_ctr(env, csrno, isel, val, new_val, wr_mask); + } else if (xiselect_spmp_range(isel)) { + /* Is SPMP enabled? */ + ret =3D spmp(env, csrno); + if (ret !=3D RISCV_EXCP_NONE) { + return ret; + } + + ret =3D rmw_xireg_spmp(env, csrno, isel, val, new_val, wr_mask); } else { /* * As per the specification, access to unimplented region is undef= ined @@ -5292,6 +5319,52 @@ static RISCVException write_pmpaddr(CPURISCVState *e= nv, int csrno, return RISCV_EXCP_NONE; } =20 +static int rmw_xireg_spmp(CPURISCVState *env, int csrno, + target_ulong isel, target_ulong *val, + target_ulong new_val, target_ulong wr_mask) +{ + int index =3D 0; + bool m_mode_access =3D false; + + /* Read 0 and write ignore if no rules are delegated */ + if (env->spmp_state.num_deleg_rules =3D=3D 0) { + *val =3D 0; + return 0; + } + + index =3D isel - ISELECT_SPMP_BASE; + + switch (csrno) { + case CSR_MIREG: + /* If M mode, signal it */ + m_mode_access =3D true; + [[fallthrough]]; + case CSR_SIREG: + if (val) { + *val =3D spmpaddr_csr_read(env, index); + } + + spmpaddr_csr_write(env, index, new_val & wr_mask, m_mode_access); + break; + case CSR_MIREG2: + /* If M mode, signal it */ + m_mode_access =3D true; + [[fallthrough]]; + case CSR_SIREG2: + index =3D isel - ISELECT_SPMP_BASE; + if (val) { + *val =3D spmpcfg_csr_read(env, index); + } + + spmpcfg_csr_write(env, index, new_val & wr_mask, m_mode_access); + break; + default: + return RISCV_EXCP_ILLEGAL_INST; + } + + return 0; +} + static RISCVException read_tselect(CPURISCVState *env, int csrno, target_ulong *val) { --=20 2.43.0 From nobody Mon Apr 6 16:47:57 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1773863180; cv=none; d=zohomail.com; s=zohoarc; b=k0ij+tfgjv7ZjQK8lfsfOyrEzBqR9DPHm42kDmTzGaHFjo9iU00EmiawQofFhWuR13EyZGQGllW7/ZOniEqHlYg5Ko7rfGC7Z4ow0mU3W/HMbbbpmF4JB1Iu8/VvIiW90+G6qYAraa1bKzfcDUDUhCHCQ/hV1rDCjFmXEdO2Lic= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773863180; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=MgUU3ESREZdS9sq4yVbWG85T8VnRxWZzI6/tT8ASiHg=; b=kGoozjFV7xFT60lGbsbVMmqQTTS6bImgUUxDq1JpDL3KVu2Oa5N0o0UExXhrZ/yLQflebsuC0rjrYGFshF5aLWaxeHd2wZb+9puoFnoBNISdruRY7FIOGoVk6ZGRld+hUq9Oy3B3/KR4+x211/X9FYRJfMVHycfseY9uqR/spM4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773863180173348.24359289194535; Wed, 18 Mar 2026 12:46:20 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w2woV-0005uq-1G; Wed, 18 Mar 2026 15:44:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w2w1C-0002Yh-BQ for qemu-devel@nongnu.org; Wed, 18 Mar 2026 14:53:22 -0400 Received: from mail-wm1-x336.google.com ([2a00:1450:4864:20::336]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w2w1A-00068A-HL for qemu-devel@nongnu.org; Wed, 18 Mar 2026 14:53:22 -0400 Received: by mail-wm1-x336.google.com with SMTP id 5b1f17b1804b1-4856cd3f1ffso1762615e9.3 for ; Wed, 18 Mar 2026 11:53:20 -0700 (PDT) Received: from luis-IdeaPad-Flex-5-14ALC05.. ([148.69.202.102]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-486f8b0bc58sm16135905e9.3.2026.03.18.11.53.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 Mar 2026 11:53:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773859999; x=1774464799; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=MgUU3ESREZdS9sq4yVbWG85T8VnRxWZzI6/tT8ASiHg=; b=coG49HqMrKmTA0jyUutXwe8paDbJFZ63ApvHlBJCaV9K1MINesm5pKngfDuJ3LXC7S sZhprDSVWOouK+JrCrfnlEhXUA0I53poT+i4S9N3fMVjhUgnr93Rjc3G5kvJiFegZCC4 5jv2+DPTVDpxuBWzKJx6p6qVmZFVMZllKPV9i/Eo429w1Mjh3QYKuGf7IamYRZ2bhyrZ 3FQaexRs6aW9ro0CjocBdK1V8f/WaFd44HG7U6dwvwP9JFopiGOaIxdNK366tQfwu13r 3kazQ9BTzRoZDtFBYlMHhARtXA9p34lhxOOfZ1rWtaNO/59PPEUsvxU9h74irDeZNE3F GTdw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773859999; x=1774464799; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=MgUU3ESREZdS9sq4yVbWG85T8VnRxWZzI6/tT8ASiHg=; b=iM8ugPS8srtJiSIS14Zcc1pRYIfcaHcAQpqLnC2JnuFtn4rPVb76CGRi37xCxsx+x3 Gg9PFH2RIfNI+anwIQOvxVeLj1rXUqDFbu+fzAC2XY7Mi8IYjDegOydu5CUj15ozCald /fMIDkxff0zFWZ+VDCNd4YACa3gj5aIGM1pT/TPzs47dnUjJ6U4Bf1IbRfKRp9W1j0BS kYUhmLGUqwzf0Glsstyo9mqiT8NMQtOuUYfS9k3i0OeasZnryJgQ36D+rfoJnNxL22xM MYSSTaCWb1kDGLixJAxTbQj2SYmWMgIAROnXsawLrycllTsmLiof8euhBxQBCFBEM2+i iUsg== X-Gm-Message-State: AOJu0YyZfkUr6nJxMgjDhMSee+4oSB4mR9KEZV7tR/HqcpFFhOH0OPZA fTRZotVowsC36SMSMG18m/xw+aM9XEtjMgdmjv9rHwaPgT3Q1cgZg81BUQaJi9kFPGY= X-Gm-Gg: ATEYQzyrl+kjLEEJJG6Hb4q1Gg/J4aNch8KBFtvJADfDEbDtzOLoXg9Ym3jOfNiiaXe zYOe0qnCOeXT0cvY4xO4P3EX2Fcnia/h8I8KNXr6TlLJp5USXY4Sc4tsZFXaXseYkEUcUuZDdKl 6oacoz91iTCR9iTpNsp0NeUO7I3MJY1sgaXlze6B1YpXWJ0XgEolE9J6jc5dlTo41Cus1pM9KAI PvOnhBDw8VN4rPWJu/UeSMQtf5wmZHQ/qXJNLHIIGiXhud3GoNDEcWPBOn+qMUt82EuxkCwcaow 4Yrf1sdVbtKgoVj1OXy1YBMAK8zXyGDyx+gwtFdxThH47r+QE6yelFlvXXtrZo2JaMfVV+GQ6oB qEuJ7uQq99k8iMgfSA7CUJ4Js73iy1RSABXdtFU3J3ni5OdkyipvjOSdYKpsm4ooqqVT3bEG2Hk Is62CJHq58Dli3zJ5IzYJ4xazgvNlA3tm/xklnreG6750CMKiy8sChK+dLMl6lzi1JqstZNJ0Cb FcXkhlEYM3L3t/3/8mrLompxZGpZNOPVdcXsYI= X-Received: by 2002:a05:600c:1d10:b0:485:3eba:ab96 with SMTP id 5b1f17b1804b1-486f4421c4cmr79350895e9.3.1773859998687; Wed, 18 Mar 2026 11:53:18 -0700 (PDT) From: luisccc To: qemu-devel@nongnu.org Cc: luisccc , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , qemu-riscv@nongnu.org (open list:RISC-V TCG CPUs) Subject: [RFC PATCH 3/6] target/riscv: Implement extension for Sharing Hardware Resources (Smpmpdeleg) Date: Wed, 18 Mar 2026 18:52:33 +0000 Message-ID: <20260318185238.99143-4-luisccunha8@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260318185238.99143-1-luisccunha8@gmail.com> References: <20260318185238.99143-1-luisccunha8@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::336; envelope-from=luisccunha8@gmail.com; helo=mail-wm1-x336.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.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, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 18 Mar 2026 15:44:18 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1773863181855158500 Content-Type: text/plain; charset="utf-8" Signed-off-by: Luis Cunha --- target/riscv/cpu.c | 8 ++++++++ target/riscv/cpu.h | 2 ++ target/riscv/cpu_bits.h | 2 ++ target/riscv/cpu_cfg_fields.h.inc | 1 + target/riscv/csr.c | 27 +++++++++++++++++++++++++++ target/riscv/pmp.c | 14 +++++++++++++- target/riscv/pmp.h | 1 + 7 files changed, 54 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index e56470a374..5383e07dbd 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -760,6 +760,14 @@ static void riscv_cpu_reset_hold(Object *obj, ResetTyp= e type) } =20 pmp_unlock_entries(env); + + /* Is SPMP enabled? */ + if (riscv_cpu_cfg(env)->spmp) { + env->mpmpdeleg =3D MPMP_DELEG_DEFAULT; + env->spmp_state.num_deleg_rules =3D 64 - MPMP_DELEG_DEFAULT; + + spmp_unlock_entries(env); + } #else env->priv =3D PRV_U; env->senvcfg =3D 0; diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index c265098324..e19c1216ea 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -179,6 +179,7 @@ extern RISCVCPUImpliedExtsRule *riscv_multi_ext_implied= _rules[]; #define MIN_RISCV_PMP_GRANULARITY 4 =20 #define MAX_RISCV_SPMPS (64) +#define MPMP_DELEG_DEFAULT (64) =20 #if !defined(CONFIG_USER_ONLY) #include "pmp.h" @@ -447,6 +448,7 @@ struct CPUArchState { =20 /* S-mode Physical Memory Protection */ spmp_table_t spmp_state; + uint16_t mpmpdeleg; =20 /* trigger module */ target_ulong trigger_cur; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 9b7ab28bba..36f7c1e873 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -449,6 +449,8 @@ #define CSR_PMPADDR62 0x3ee #define CSR_PMPADDR63 0x3ef =20 +#define CSR_MPMPDELEG 0x316 + /* RNMI */ #define CSR_MNSCRATCH 0x740 #define CSR_MNEPC 0x741 diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/cpu_cfg_field= s.h.inc index 72d417c241..772cc176d0 100644 --- a/target/riscv/cpu_cfg_fields.h.inc +++ b/target/riscv/cpu_cfg_fields.h.inc @@ -119,6 +119,7 @@ BOOL_FIELD(rvv_ta_all_1s) BOOL_FIELD(rvv_ma_all_1s) BOOL_FIELD(rvv_vl_half_avl) BOOL_FIELD(rvv_vsetvl_x0_vill) +BOOL_FIELD(ext_smpmpdeleg) /* Named features */ BOOL_FIELD(ext_svade) BOOL_FIELD(ext_zic64b) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 167d84d92a..4b9fa11540 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -5365,6 +5365,30 @@ static int rmw_xireg_spmp(CPURISCVState *env, int cs= rno, return 0; } =20 +/* S-mode Physical Memory Protection */ +static RISCVException rmw_mpmpdeleg(CPURISCVState *env, int csrno, + target_ulong *ret_val, + target_ulong new_val, target_ulong wr_= mask) +{ + uint16_t new_mpmpdeleg =3D (env->mpmpdeleg & ~wr_mask) | (new_val & wr= _mask); + + if (ret_val) { + *ret_val =3D env->mpmpdeleg; + } + + /* + * pmpnum is locked if MSECCFG_MML is set + * and if new_mpmpdeleg is higher than last locked rule + */ + if (!(env->mseccfg & MSECCFG_MML) && + (new_mpmpdeleg & 0x7F) > env->pmp_state.last_locked_rule) { + env->mpmpdeleg =3D new_mpmpdeleg & 0x7F; + } + + env->spmp_state.num_deleg_rules =3D MPMP_DELEG_DEFAULT - env->mpmpdele= g; + return RISCV_EXCP_NONE; +} + static RISCVException read_tselect(CPURISCVState *env, int csrno, target_ulong *val) { @@ -6362,6 +6386,9 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] =3D { [CSR_PMPADDR63] =3D { "pmpaddr63", pmp, read_pmpaddr, write_pmpaddr, .min_priv_ver =3D PRIV_VERSION_1_12_0 }, =20 + /* S-mode Physical Memory Protection */ + [CSR_MPMPDELEG] =3D { "mpmpdeleg", spmp, NULL, NULL, rmw_mpmpdeleg }, + /* Debug CSRs */ [CSR_TSELECT] =3D { "tselect", debug, read_tselect, write_tselect= }, [CSR_TDATA1] =3D { "tdata1", debug, read_tdata, write_tdata = }, diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c index 3ef62d26ad..22d6f1f5b3 100644 --- a/target/riscv/pmp.c +++ b/target/riscv/pmp.c @@ -174,6 +174,12 @@ static bool pmp_write_cfg(CPURISCVState *env, uint32_t= pmp_index, uint8_t val) return false; } env->pmp_state.pmp[pmp_index].cfg_reg =3D val; + + if ((val & PMP_LOCK) && + env->pmp_state.last_locked_rule < (signed int)pmp_index) { + env->pmp_state.last_locked_rule =3D pmp_index; + } + pmp_update_rule_addr(env, pmp_index); return true; } @@ -193,6 +199,8 @@ void pmp_unlock_entries(CPURISCVState *env) for (i =3D 0; i < pmp_num; i++) { env->pmp_state.pmp[i].cfg_reg &=3D ~(PMP_LOCK | PMP_AMATCH); } + + env->pmp_state.last_locked_rule =3D -1; } =20 static void pmp_decode_napot(hwaddr a, hwaddr *sa, hwaddr *ea) @@ -385,11 +393,15 @@ bool pmp_hart_has_privs(CPURISCVState *env, hwaddr ad= dr, pmp_size =3D size; } =20 + /* If SPMP is enabled, use the MPMP delegation */ + uint8_t max_pmp_index =3D + (riscv_cpu_cfg(env)->spmp) ? (env->mpmpdeleg & 0x7F) : pmp_regions; + /* * 1.10 draft priv spec states there is an implicit order * from low to high */ - for (i =3D 0; i < pmp_regions; i++) { + for (i =3D 0; i < max_pmp_index; i++) { s =3D pmp_is_in_range(env, i, addr); e =3D pmp_is_in_range(env, i, addr + pmp_size - 1); =20 diff --git a/target/riscv/pmp.h b/target/riscv/pmp.h index 271cf24169..3194c6b531 100644 --- a/target/riscv/pmp.h +++ b/target/riscv/pmp.h @@ -63,6 +63,7 @@ typedef struct { pmp_entry_t pmp[MAX_RISCV_PMPS]; pmp_addr_t addr[MAX_RISCV_PMPS]; uint32_t num_rules; + signed char last_locked_rule; } pmp_table_t; =20 void pmpcfg_csr_write(CPURISCVState *env, uint32_t reg_index, --=20 2.43.0 From nobody Mon Apr 6 16:47:57 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1773863131; cv=none; d=zohomail.com; s=zohoarc; b=jX5VpyvEsB6fWYjtgblrA+cmGwZTv7RbbTCku7jywU7YgPbTxgwp5A6z/OOap3TLpzodcRAFxmDMkTeSCv4WzB8xThjl6CiXFN9QkfqZmb4nY7Y18l7B/B0szgF9dnwddI1jnYv0iOw2w3HX15lbyv0FNKLXw+ZHQXT0aIG7Iwo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773863131; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=vqGv6FVLTonOExL81okKQ24PXUVEVEL0h321keC4CZ8=; b=F0A//6ex7Ie+Ih4M4dwxp9PGrU8HA8j8dbVX8lKH0nTw7v3No2ZSHAMd7CEgDP/N0fpwpGQaoyXAGaDrXbr12vW7l776Fnr7k3NFLYj0aN6qFFzuYftyrlmxcwPa9Qd2/VdP02ifNi67U/FMuSs/5xXYyHg/USMEVEn0VW5q6UU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773863131842310.5121253590745; Wed, 18 Mar 2026 12:45:31 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w2woY-0005vu-Hy; Wed, 18 Mar 2026 15:44:22 -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 1w2w1J-0002Zd-R2 for qemu-devel@nongnu.org; Wed, 18 Mar 2026 14:53:31 -0400 Received: from mail-wm1-x333.google.com ([2a00:1450:4864:20::333]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w2w1H-0006B1-VG for qemu-devel@nongnu.org; Wed, 18 Mar 2026 14:53:29 -0400 Received: by mail-wm1-x333.google.com with SMTP id 5b1f17b1804b1-4856cd3f1ffso1763495e9.3 for ; Wed, 18 Mar 2026 11:53:27 -0700 (PDT) Received: from luis-IdeaPad-Flex-5-14ALC05.. ([148.69.202.102]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-486f8b0bc58sm16135905e9.3.2026.03.18.11.53.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 Mar 2026 11:53:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773860006; x=1774464806; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=vqGv6FVLTonOExL81okKQ24PXUVEVEL0h321keC4CZ8=; b=O0eWkqFp2ZHbl4AoLGXk/neo0uX28hUgTdXDwJpmDoBbqZCiaw4y0mukMCOqM3DwHQ +0BFPHqL9iekURaCmhu9Y9kV+1lOgSBcGKTqYlanz8ruPEK8OJGuB981jkBdykKRm+b+ lDM4NEFzhzteNVjnB+eOVYCiGtEGaZL3yJYPuVaFPDXRyIHQqgz9kesThOgs9QvVzkQ9 KAOF9wuOXfYpbu90Pk1lWC1nZi7lBMfvmMppvjm9HFEkK1jPVvwO8bdyVJQ0w15pdlrC 8oVUGmcOockt/ym9Svz4Z73uLf2KUfjaO12j+rxiGZUznm2mBfeIQ6+UxDwFb3VrP7bT ZwiQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773860006; x=1774464806; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=vqGv6FVLTonOExL81okKQ24PXUVEVEL0h321keC4CZ8=; b=OnMqJMvJJmBWHloDJt2x0HDmos9tVbuviFC0p5ALcoPX4/8hJeldE13U/XS44DIK/y XSci7XcfMK21xJGeU9nyRp6dG1DPWW/T1YPXcISHxdOMZvjcJcJSDedksn4yEDCUrFZs 5GnJha+9zt3/KpjyXXK8jCi4vtHVt+x29JjkrAY9b1w2G/+YCFnfbtE8G0jYH9Mw7Yy/ DDwzd45oAj7W6OIOWucQU9Pq8z7fkwYGvbwxGEFCHDKseKOj+ofqS588o1yDDlKZYR2+ JnmhZKEa0qVD2AJnM3YKZ6ayf+e1YS0mYtzoL5aUPsDibSdZziM5j8aFeO1yRFpC7onD tCWA== X-Gm-Message-State: AOJu0YxE48EPUd+WeYD2Gmw6EhSki4LK8c5WUAULlOezO28R9ypEITMv MpxvC5iu4zM1NOEkwZo/wWDXrinNkFJU/3hLQKcOcYfLqi7N1uy2h3AivVXBai3zxdc= X-Gm-Gg: ATEYQzyyCDoImRAZJw6/JZEqMEU3tVhqz0v3IkZmkdErcnWoL1ySOwolaCfMkaRNVu5 HFq+wY57Ox/Z7BsBwtH7dGJJi8x0QrWaZ8y87ZWo/4XR1czHeRv9J+7FflHp09LzEHIbxwmGYg+ YO30zM0KpSlmnLWqxm9Ob63D8zwAdExt47K0ywygLG93uKTcnG73PFwAqGkQ3O125K3lHJULjoz /LeN+9HD5EtCmd/JP3N4na7WFukdTvHdsWqF+sXhybG4M9krf2KUPqCSp2IceKpfmussHUPWQRM k/ZG8sJ6UeCzl6VKOt4kLj6HB8YZZwBen/EB7g3vQva57NXWTsxfSVjZnaR/BZPA+QgxZ6NRhYg xKDUREEsOkmtUDW/IhLfhKSPX5+tg/+t/rzuvRwCZS30sjZ0VL2pvm0xV1/FpPzVVHKDwgVgzRH LTjSavMC+3Lg4ugcYMNK/C1UhRatgTP6GFpICRIPAOeO2HUAaIie1LBBkjkSCQp1dgj0uXtYT3B FU4prIy6RAehGngYv0Jnea2VMNT/NGOj+Uzk/c= X-Received: by 2002:a05:600c:3f14:b0:486:f8d6:5dea with SMTP id 5b1f17b1804b1-486f8d65df5mr7046805e9.19.1773860006159; Wed, 18 Mar 2026 11:53:26 -0700 (PDT) From: luisccc To: qemu-devel@nongnu.org Cc: luisccc , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , qemu-riscv@nongnu.org (open list:RISC-V TCG CPUs) Subject: [RFC PATCH 4/6] target/riscv: Implement extension for Optimizing Context Switching (Sspmpen) Date: Wed, 18 Mar 2026 18:52:34 +0000 Message-ID: <20260318185238.99143-5-luisccunha8@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260318185238.99143-1-luisccunha8@gmail.com> References: <20260318185238.99143-1-luisccunha8@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::333; envelope-from=luisccunha8@gmail.com; helo=mail-wm1-x333.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.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, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 18 Mar 2026 15:44:18 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1773863133904154100 Content-Type: text/plain; charset="utf-8" Signed-off-by: Luis Cunha --- target/riscv/cpu_bits.h | 4 ++ target/riscv/cpu_cfg_fields.h.inc | 1 + target/riscv/csr.c | 67 +++++++++++++++++++++++++++++++ target/riscv/spmp.c | 6 ++- 4 files changed, 77 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 36f7c1e873..0a8cfedc5d 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -255,6 +255,10 @@ #define CSR_SCTRSTATUS 0x14f #define CSR_SCTRDEPTH 0x15f =20 +/* S-mode Physical Memory Protection (SPMP) */ +#define CSR_SPMPEN 0x183 +#define CSR_SPMPENH 0x193 + /* VS-Level Control transfer records CSRs */ #define CSR_VSCTRCTL 0x24e =20 diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/cpu_cfg_field= s.h.inc index 772cc176d0..88edac21ca 100644 --- a/target/riscv/cpu_cfg_fields.h.inc +++ b/target/riscv/cpu_cfg_fields.h.inc @@ -120,6 +120,7 @@ BOOL_FIELD(rvv_ma_all_1s) BOOL_FIELD(rvv_vl_half_avl) BOOL_FIELD(rvv_vsetvl_x0_vill) BOOL_FIELD(ext_smpmpdeleg) +BOOL_FIELD(ext_sspmpen) /* Named features */ BOOL_FIELD(ext_svade) BOOL_FIELD(ext_zic64b) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 4b9fa11540..a11d7e6704 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -769,6 +769,16 @@ static RISCVException spmp(CPURISCVState *env, int csr= no) return smode(env, csrno); } =20 +static RISCVException sspmpen(CPURISCVState *env, int csrno) +{ + if (!riscv_cpu_cfg(env)->ext_sspmpen) { + return RISCV_EXCP_ILLEGAL_INST; + } + + /* SSPMPEN can only exist, if spmp exists */ + return spmp(env, csrno); +} + static RISCVException have_mseccfg(CPURISCVState *env, int csrno) { if (riscv_cpu_cfg(env)->ext_smepmp) { @@ -5389,6 +5399,61 @@ static RISCVException rmw_mpmpdeleg(CPURISCVState *e= nv, int csrno, return RISCV_EXCP_NONE; } =20 +static RISCVException rmw_spmpen64(CPURISCVState *env, int csrno, + uint64_t *ret_val, + uint64_t new_val, uint64_t wr_mask) +{ + uint64_t new_spmpen =3D (env->spmp_state.spmpen & ~wr_mask) | + (new_val & wr_mask); + + if (env->spmp_state.num_deleg_rules =3D=3D 0) { + if (ret_val) { + *ret_val =3D 0; + } + + return RISCV_EXCP_NONE; + } + + if (ret_val) { + *ret_val =3D env->spmp_state.spmpen; + } + + sspmpen_csr_write(env, new_spmpen); + + return RISCV_EXCP_NONE; +} + +static RISCVException rmw_spmpen(CPURISCVState *env, int csrno, + target_ulong *ret_val, + target_ulong new_val, target_ulong wr_ma= sk) +{ + uint64_t rval =3D 0; + RISCVException ret; + ret =3D rmw_spmpen64(env, csrno, &rval, new_val, wr_mask); + if (ret_val) { + *ret_val =3D rval; + } + + return ret; +} + +static RISCVException rmw_spmpenh(CPURISCVState *env, int csrno, + target_ulong *ret_val, + target_ulong new_val, + target_ulong wr_mask) +{ + uint64_t rval =3D 0; + RISCVException ret; + + ret =3D rmw_spmpen64(env, csrno, &rval, + ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32); + if (ret_val) { + *ret_val =3D rval >> 32; + } + + return ret; +} + static RISCVException read_tselect(CPURISCVState *env, int csrno, target_ulong *val) { @@ -6388,6 +6453,8 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] =3D { =20 /* S-mode Physical Memory Protection */ [CSR_MPMPDELEG] =3D { "mpmpdeleg", spmp, NULL, NULL, rmw_mpmpdeleg }, + [CSR_SPMPEN] =3D { "spmpen", sspmpen, NULL, NULL, rmw_spmpen }, + [CSR_SPMPENH] =3D { "spmpenh", sspmpen, NULL, NULL, rmw_spmpenh }, =20 /* Debug CSRs */ [CSR_TSELECT] =3D { "tselect", debug, read_tselect, write_tselect= }, diff --git a/target/riscv/spmp.c b/target/riscv/spmp.c index 85c5259b33..1615c207df 100644 --- a/target/riscv/spmp.c +++ b/target/riscv/spmp.c @@ -147,7 +147,11 @@ static uint8_t spmp_is_in_range(CPURISCVState *env, in= t spmp_index, =20 static bool spmp_get_spmpen_bit(CPURISCVState *env, int index) { - return true; + if (!riscv_cpu_cfg(env)->ext_sspmpen) { + return true; + } + + return (env->spmp_state.spmpen >> index) & 0x1; } =20 /* --=20 2.43.0 From nobody Mon Apr 6 16:47:57 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1773863182; cv=none; d=zohomail.com; s=zohoarc; b=dMoZWnHPDHa3OtZABk0WeuQfhkcmQitxXEmirio7eTxVe1mZhUFiF4zGGuvUvZZI0CyULJ0wvxkUR2sNnnbI2jk30B598ZzWU/JHfLq3sxTtS5wp6cifcpax21FbaR7SMnLqJQtzJyWUO7f1AMHeY7CtidD1uOd++eSq0MhsHw4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773863182; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=M2E9dkyclMm1Bw8RNQiNxi3vU1BzLiWqIgGZE5zUnoY=; b=CLrPYnoPgtkqPQgEEUPrfnN1rgDEorEMzknvDUfEHqCsfxAsIG4WfADwZXSaxAcwGKnveZCIQBivDNOPutA4AIhNOJwpadcYhLkrOUmgKKmtXphW0QFTjIEhNEZW9LxUSU6uIEHBa1IyRCB0SCpOuLGYQu4AdwWZR5Nfvj+ZGuM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773863182173602.1638233041431; Wed, 18 Mar 2026 12:46:22 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w2woY-0005ve-Fb; Wed, 18 Mar 2026 15:44:22 -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 1w2w1Y-0002cy-It for qemu-devel@nongnu.org; Wed, 18 Mar 2026 14:53:44 -0400 Received: from mail-wm1-x335.google.com ([2a00:1450:4864:20::335]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w2w1S-0006Qw-Mc for qemu-devel@nongnu.org; Wed, 18 Mar 2026 14:53:43 -0400 Received: by mail-wm1-x335.google.com with SMTP id 5b1f17b1804b1-4853aec185aso1407965e9.1 for ; Wed, 18 Mar 2026 11:53:38 -0700 (PDT) Received: from luis-IdeaPad-Flex-5-14ALC05.. ([148.69.202.102]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-486f8b0bc58sm16135905e9.3.2026.03.18.11.53.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 Mar 2026 11:53:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773860017; x=1774464817; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=M2E9dkyclMm1Bw8RNQiNxi3vU1BzLiWqIgGZE5zUnoY=; b=DCKmZZm/mIyzTGMvFeD4+7+S2eB5qPDbo14BMUrB4UYo26WXWmgutLU/dmbR/OmXKJ Gjk5ilySMeK6IGnEBAe1Y4ytPmR7lgb3vzyB2U8ImyxzULeQktTFbWLYbs97+ECmIRfK CZLfM/jwHL65kJwQTb9XrcUXQ+q3Q0S0kQ65rF3sUVzs+8Z1QaJG+3mOob6XNxw+3jcm S1+agYwIef475l/vBMwodj/os7HwfXvIcJ1hx1LJufugEEgGbCxySegJ6TEYB77HsQ8K A/8mU8CJZY4QmkhdEIsuUCFOJaoy52nzsnIH5LqCKwGQzfCzc6ngK/KQP7UlfxBoSxUs j6og== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773860017; x=1774464817; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=M2E9dkyclMm1Bw8RNQiNxi3vU1BzLiWqIgGZE5zUnoY=; b=TnMyb2UIAn6td/MO9F2xKghVdWJEnXYddXOIVXCYr4acXWXbhuZffwiUfaPeUM7LkT lhq+SlrUTmy8XccX+YBfn49QP9enlRxsoYJ+9pfTay6hFg9CP+bFiEfOPpWScX4PcxbQ W70kfc7levDzsZjAI2MBt+jAZEElgY4L/53Bc+GWoVgjyrk5NRBkhUEnWbwmWNbt0dE6 YP7E1q3fITf2BoUXRoxLIVWXbNZi4qsMWUxuP9ow2BRoi1gXGAtQMZijMj3qMscnKwE4 89eeERzhRvKymYWra3QD44eVRnvk9KHf4599ctR8TKKQl0IcTS+aJuxGIiWiitA4POcd mSpQ== X-Gm-Message-State: AOJu0YzEuI1c4Gox8auCOBVvbZuzVysM3p7DavsjOLjLH90ViHHuGxI4 Bx8UHZQouI3RmDnyzab4kYBosLLFNns1ikWKDY4xbNBfc0Rd7nwoMUxQlL3c+i59bpQ= X-Gm-Gg: ATEYQzzisxXAvkdZ3DxBIzhBN29utPc/jZ75FXYfI6ACjQnMvohrJJxS4VL+PU+Scpk BNn3Ma6l6fAdmvrSCv1YdC43e4jW/vSd8ZQtcwOA2GuMqkDopkr5EmqAUL8yJWp1fRXOoDTCCw2 WIAdfLb4eIXr1Cd/fV+XZE5mQRrzQhHCFpTDAJ6L1fdWMyT6rO3w/SHMxKuCNRZf0E9u/Zm8Ckb 8DRu9R3d1FQaT5aPKGLS+ETU0nX34LE8Dh7ZdJalLPmkJxf4ZB7h5BHjky8tC/bf6FJgAE3tNW5 e3ArUsrO7l0UyeT8ZuGISBMQluNKD++6e8qGuJ8foFCDq7AVqZQlWJvtEV1a7r1zIchyNAbdyQc EKmseHQP/rXW7f3JvpWpt5ke60G3UxB1znq4ayxmrkavNBqbTu49mhDtz6yCi/OMCS3iN44TElU k2vb3pGVl8QOtUVz8BRMxaXTvn9aJahan6nlMYcSO9E3BKwp+Y2ts2b85kT16+JmL5nqIvQjaY3 KFBWaMBjfXLT3UansSo6AKbH2rV282htiq9SeI= X-Received: by 2002:a05:600c:1f93:b0:485:2fc5:3a5 with SMTP id 5b1f17b1804b1-486f445e26dmr74478575e9.26.1773860016738; Wed, 18 Mar 2026 11:53:36 -0700 (PDT) From: luisccc To: qemu-devel@nongnu.org Cc: luisccc , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , qemu-riscv@nongnu.org (open list:RISC-V TCG CPUs) Subject: [RFC PATCH 5/6] target/riscv: Enable SPMP support in CPU Date: Wed, 18 Mar 2026 18:52:35 +0000 Message-ID: <20260318185238.99143-6-luisccunha8@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260318185238.99143-1-luisccunha8@gmail.com> References: <20260318185238.99143-1-luisccunha8@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::335; envelope-from=luisccunha8@gmail.com; helo=mail-wm1-x335.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.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, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 18 Mar 2026 15:44:19 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1773863183934158500 Content-Type: text/plain; charset="utf-8" Integrate the SPMP implementation into the RISC-V CPU model.Memory access c= hecks are updated to take SPMP configuration into account when the extensio= n is active. Signed-off-by: Luis Cunha --- target/riscv/cpu.h | 1 + target/riscv/cpu_helper.c | 139 +++++++++++++++++++++++++++++++------- 2 files changed, 116 insertions(+), 24 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index e19c1216ea..bf05ab66ce 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -130,6 +130,7 @@ enum { TRANSLATE_SUCCESS, TRANSLATE_FAIL, TRANSLATE_PMP_FAIL, + TRANSLATE_SPMP_FAIL, TRANSLATE_G_STAGE_FAIL }; =20 diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index dd6c861a90..de20f6c9f4 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -36,6 +36,7 @@ #include "cpu_bits.h" #include "debug.h" #include "pmp.h" +#include "spmp.h" #include "qemu/plugin.h" =20 int riscv_env_mmu_index(CPURISCVState *env, bool ifetch) @@ -1113,6 +1114,42 @@ static int get_physical_address_pmp(CPURISCVState *e= nv, int *prot, hwaddr addr, return TRANSLATE_SUCCESS; } =20 +/* + * get_physical_address_spmp - check SPMP permission for this physical add= ress + * + * Match the SPMP region and check permission for this physical address. + * Returns 0 if the permission checking was successful. + * The SPMP check is happened before the PMP check. + * + * @env: CPURISCVState + * @prot: The returned protection attributes + * @addr: The physical address to be checked permission + * @access_type: The type of access + * @mode: Indicates current privilege level. + */ +static int get_physical_address_spmp(CPURISCVState *env, int *prot, hwaddr= addr, + int size, int access_type, + int mode) +{ + spmp_priv_t spmp_priv; + + if (!riscv_cpu_cfg(env)->spmp) { + *prot =3D PAGE_READ | PAGE_WRITE | PAGE_EXEC; + return TRANSLATE_SUCCESS; + } + + if (!spmp_hart_has_privs(env, addr, size, 1 << access_type, &spmp_priv, + mode)) { + *prot =3D 0; + return TRANSLATE_SPMP_FAIL; + } + + *prot =3D spmp_priv_to_page_prot(spmp_priv); + + return TRANSLATE_SUCCESS; +} + + /* Returns 'true' if a svukte address check is needed */ static bool do_svukte_check(CPURISCVState *env, bool first_stage, int mode, bool virt) @@ -1616,8 +1653,8 @@ static int get_physical_address(CPURISCVState *env, h= waddr *physical, =20 static void raise_mmu_exception(CPURISCVState *env, target_ulong address, MMUAccessType access_type, bool pmp_violat= ion, - bool first_stage, bool two_stage, - bool two_stage_indirect) + bool spmp_violation, bool first_stage, + bool two_stage, bool two_stage_indirect) { CPUState *cs =3D env_cpu(env); =20 @@ -1625,7 +1662,7 @@ static void raise_mmu_exception(CPURISCVState *env, t= arget_ulong address, case MMU_INST_FETCH: if (pmp_violation) { cs->exception_index =3D RISCV_EXCP_INST_ACCESS_FAULT; - } else if (env->virt_enabled && !first_stage) { + } else if (env->virt_enabled && (!first_stage || spmp_violation)) { cs->exception_index =3D RISCV_EXCP_INST_GUEST_PAGE_FAULT; } else { cs->exception_index =3D RISCV_EXCP_INST_PAGE_FAULT; @@ -1634,7 +1671,8 @@ static void raise_mmu_exception(CPURISCVState *env, t= arget_ulong address, case MMU_DATA_LOAD: if (pmp_violation) { cs->exception_index =3D RISCV_EXCP_LOAD_ACCESS_FAULT; - } else if (two_stage && !first_stage) { + } else if ((two_stage && !first_stage) || + (env->virt_enabled && spmp_violation)) { cs->exception_index =3D RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT; } else { cs->exception_index =3D RISCV_EXCP_LOAD_PAGE_FAULT; @@ -1643,7 +1681,8 @@ static void raise_mmu_exception(CPURISCVState *env, t= arget_ulong address, case MMU_DATA_STORE: if (pmp_violation) { cs->exception_index =3D RISCV_EXCP_STORE_AMO_ACCESS_FAULT; - } else if (two_stage && !first_stage) { + } else if ((two_stage && !first_stage) || + (env->virt_enabled && spmp_violation)) { cs->exception_index =3D RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAUL= T; } else { cs->exception_index =3D RISCV_EXCP_STORE_PAGE_FAULT; @@ -1766,8 +1805,9 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, = int size, CPURISCVState *env =3D &cpu->env; vaddr im_address; hwaddr pa =3D 0; - int prot, prot2, prot_pmp; + int prot, prot2, prot_pmp, prot_spmp; bool pmp_violation =3D false; + bool spmp_violation =3D false; bool first_stage_error =3D true; bool two_stage_lookup =3D mmuidx_2stage(mmu_idx); bool two_stage_indirect_error =3D false; @@ -1820,16 +1860,38 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address= , int size, prot &=3D prot2; =20 if (ret =3D=3D TRANSLATE_SUCCESS) { - ret =3D get_physical_address_pmp(env, &prot_pmp, pa, - size, access_type, mode); - tlb_size =3D pmp_get_tlb_size(env, pa); + int vm; + if (riscv_cpu_mxl(env) =3D=3D MXL_RV32) { + vm =3D get_field(env->hgatp, SATP32_MODE); + } else { + vm =3D get_field(env->hgatp, SATP64_MODE); + } =20 - qemu_log_mask(CPU_LOG_MMU, - "%s PMP address=3D" HWADDR_FMT_plx " ret %d = prot" - " %d tlb_size %" HWADDR_PRIu "\n", - __func__, pa, ret, prot_pmp, tlb_size); + if (vm =3D=3D VM_1_10_MBARE && riscv_cpu_cfg(env)->spmp) { + /* S-mode Physical Memory Protection check */ + ret =3D get_physical_address_spmp(env, &prot_spmp, pa, + size, access_type, mod= e); =20 - prot &=3D prot_pmp; + prot &=3D prot_spmp; + + if (ret =3D=3D TRANSLATE_SPMP_FAIL) { + spmp_violation =3D true; + } + } + + /* Only apply checks when the SPMP passed */ + if (ret !=3D TRANSLATE_SPMP_FAIL) { + ret =3D get_physical_address_pmp(env, &prot_pmp, pa, + size, access_type, mode); + tlb_size =3D pmp_get_tlb_size(env, pa); + + qemu_log_mask(CPU_LOG_MMU, + "%s PMP address=3D" HWADDR_FMT_plx " ret %= d prot" + " %d tlb_size %" HWADDR_PRIu "\n", + __func__, pa, ret, prot_pmp, tlb_size); + + prot &=3D prot_pmp; + } } else { /* * Guest physical address translation failed, this is a HS @@ -1855,16 +1917,45 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address= , int size, __func__, address, ret, pa, prot); =20 if (ret =3D=3D TRANSLATE_SUCCESS) { - ret =3D get_physical_address_pmp(env, &prot_pmp, pa, - size, access_type, mode); - tlb_size =3D pmp_get_tlb_size(env, pa); + /* + * Check both SPMP and PMP if the core is running in bare mode. + */ + int vm; + if (riscv_cpu_mxl(env) =3D=3D MXL_RV32) { + vm =3D get_field(env->satp, SATP32_MODE); + } else { + vm =3D get_field(env->satp, SATP64_MODE); + } =20 - qemu_log_mask(CPU_LOG_MMU, - "%s PMP address=3D" HWADDR_FMT_plx " ret %d prot" - " %d tlb_size %" HWADDR_PRIu "\n", - __func__, pa, ret, prot_pmp, tlb_size); + if (vm =3D=3D VM_1_10_MBARE && riscv_cpu_cfg(env)->spmp) { + /* S-mode Physical Memory Protection check */ + ret =3D get_physical_address_spmp(env, &prot_spmp, pa, + size, access_type, mode); + + qemu_log_mask(CPU_LOG_MMU, + "%s SPMP address=3D" HWADDR_FMT_plx " ret %d" + " prot %d\n", __func__, pa, ret, prot_spmp); + + prot &=3D prot_spmp; + + if (ret =3D=3D TRANSLATE_SPMP_FAIL) { + spmp_violation =3D true; + } + } =20 - prot &=3D prot_pmp; + /* Only apply checks when the SPMP passed */ + if (ret !=3D TRANSLATE_SPMP_FAIL) { + ret =3D get_physical_address_pmp(env, &prot_pmp, pa, + size, access_type, mode); + tlb_size =3D pmp_get_tlb_size(env, pa); + + qemu_log_mask(CPU_LOG_MMU, + "%s PMP address=3D" HWADDR_FMT_plx " ret %d pr= ot" + " %d tlb_size %" HWADDR_PRIu "\n", + __func__, pa, ret, prot_pmp, tlb_size); + + prot &=3D prot_pmp; + } } } =20 @@ -1897,8 +1988,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, = int size, wp_access, retaddr); =20 raise_mmu_exception(env, address, access_type, pmp_violation, - first_stage_error, two_stage_lookup, - two_stage_indirect_error); + spmp_violation, first_stage_error, + two_stage_lookup, two_stage_indirect_error); cpu_loop_exit_restore(cs, retaddr); } =20 --=20 2.43.0 From nobody Mon Apr 6 16:47:57 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1773863200; cv=none; d=zohomail.com; s=zohoarc; b=cBN6WR/dtNJWOyk2Z/ydaiPR4lGXCcJeWX1F27D+oF0lyLNRcjRXUGpt6oNDfTduYp96zm0AFBABQ2OyuVFaT6MQcBItLAAPi4JozdhmvK9weZeWAAZ0L4tnUDlaS23aGNFeabJ5/y3GXrFArEGUAEgEawua5NggtsFiPzVDcIU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773863200; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=XxLT5THnGV2VliLFwB1i1UVfc5yvR4zYfU/4uELoqVA=; b=kMUZHUcBvyCXs0/gIQRfW3C71eoZ5O3lA22DVqvvZJgoq5M97T5+RnZQjvNs5BtVqFF+PfNken08qOfTaFACy6UDq8PW3jjrqXqgDYqzAY9KJFQmaKskneLefrOAtU11WmQzs374K4GLVOGJ5Q6IKY29pfB33JYAA50DkxCsReM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773863200664186.66897186958363; Wed, 18 Mar 2026 12:46:40 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w2woa-0005wG-4R; Wed, 18 Mar 2026 15:44:24 -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 1w2w1e-0002dm-JA for qemu-devel@nongnu.org; Wed, 18 Mar 2026 14:53:50 -0400 Received: from mail-wm1-x32e.google.com ([2a00:1450:4864:20::32e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w2w1d-0006cx-1p for qemu-devel@nongnu.org; Wed, 18 Mar 2026 14:53:50 -0400 Received: by mail-wm1-x32e.google.com with SMTP id 5b1f17b1804b1-4853c1ca73aso1183725e9.2 for ; Wed, 18 Mar 2026 11:53:48 -0700 (PDT) Received: from luis-IdeaPad-Flex-5-14ALC05.. ([148.69.202.102]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-486f8b0bc58sm16135905e9.3.2026.03.18.11.53.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 Mar 2026 11:53:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773860027; x=1774464827; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=XxLT5THnGV2VliLFwB1i1UVfc5yvR4zYfU/4uELoqVA=; b=K3e7HEF7mDQy5evcNwMjrv6+8V/ebKPryk+D5yaqSv+LoIik/xFwcUxAn5iEdGb6z/ onv9Soq8zf3szjif1fXy+Ecea0roVkHAkYW8yRPKOIqARmPApr6FUyZvDb9Jpdp91VoF HGvGhw/tfvuxRFtIOHnqbWWfSHcgjHXvQ0vilfj77jOxlOtV6U+vxajcrxE/7GzEvepu bFaMWq5KfPI9GeW5QlHw33L7YGuI0sAx/CQFYv+Lv1TqrQ6ABr3uUkLeFpEhc9/k5g3+ tDb2pLW8RtdkUfEhL9HbCjpjccJAtldU933GeerpzkR0Xht+1D88HnyLqBV5bux+wAKM gjXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773860027; x=1774464827; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=XxLT5THnGV2VliLFwB1i1UVfc5yvR4zYfU/4uELoqVA=; b=NXu2wWcWgMtlEEDqX1w95NFBGrD5WK4m6x91LBCOA8xDnqA0FayxuLS7DRYb+Ed39+ fNy73fdKpM5C76BVNLsvSo1ehtrDtjroPXi/4vNOm3SMdbZ8fbQ8RiSrRlI6eLNmFjFw tABmEbX3yh6nOOpBEXtpjMAmkMLc/97n6/g4MXADXHsS74GMZrxTdVctvbkdW5Upw+kH e/OQd+B9nOlD6Q+DlX5BeVsBPLVgf4J7p6lxL814wmeJijcMVmkfJ0qtTSobG9TQ3bsj hoYgf1x0/7R95SaDg4G1MenHqC0hlf6KSlN4PlaNmNk+9U+IX0t4cnXcmCqLA6f8oEQh 0N7w== X-Gm-Message-State: AOJu0Yz5IJ3iJTOotYpNy8yIdkD/A2k0Hc981Q8tm4dAN4h2yZao2Rcs cB8no1E3l6mrhYGWHsqQ1GKpx7v8C/Bdlhw5+/I5chG3xhc3gh4pzVw1163gf5CGVdo= X-Gm-Gg: ATEYQzwkLXxvL5WmNUn8T9KtfL1r4FqQXE2nR9HKmAFLJQBr1zubKf2b+fQO29z+RUT O6V64FCEgAfsaP/mbV9sqs7d8UuJ3uRJ7xgAWdQDuoc5Nr3HIqlKPkAlX/FXvfNlbm2caOPiIh3 Q4hnqYhzhz6trQOjjzHcxQVUblTBiLSq7Fhq9FN9Pq/o34kcFcrdtmnpLyO4LliwfnspeLqEkD4 C7az2yCIWKPmHdwd/U1ZLBEDI/S2DnNxnV3bQl3kr3A4Mwpo9QgK+9KaIbheNw5NMNZiG3lL6bU 4DJpK6MM0xULB9M3GPNRwWrbOvnuh728vjrHFfv8ZJvPktrRQ7wI+1p7p7tNdgGEPsW4B1vjUdh TP4FRm4kqHcGs4SBL/5SR0TN+0W9wKjPbeUxXeL71Ezw32rIFieXhawaynu/TeTNt/oAWJNDWdx x21Md+lnLs3i3uYqsF6Orhr4zvP/MwDDmtF+uqYjETfvGcSC8GolH5YNS0I2nbWMFF401x0buKz M38raYOLQ1jtrHenWyPH/s9qtP9Y3OdHARD5go= X-Received: by 2002:a05:600c:4fc6:b0:480:690e:f14a with SMTP id 5b1f17b1804b1-486f4460743mr71345165e9.14.1773860026956; Wed, 18 Mar 2026 11:53:46 -0700 (PDT) From: luisccc To: qemu-devel@nongnu.org Cc: luisccc , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , qemu-riscv@nongnu.org (open list:RISC-V TCG CPUs) Subject: [RFC PATCH 6/6] target/riscv: Add CPU properties for SPMP and sspmpen Date: Wed, 18 Mar 2026 18:52:36 +0000 Message-ID: <20260318185238.99143-7-luisccunha8@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260318185238.99143-1-luisccunha8@gmail.com> References: <20260318185238.99143-1-luisccunha8@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::32e; envelope-from=luisccunha8@gmail.com; helo=mail-wm1-x32e.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.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, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 18 Mar 2026 15:44:23 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1773863202764154100 Content-Type: text/plain; charset="utf-8" Add CPU properties to control the SPMP and sspmpen extensions from the QEMU= command line. SPMP can be enabled with: -cpu ,spmp=3Dtrue Note: This automatically enables smpmpdeleg, sscsrind, and smcsrind. The sspmpen extension can be enabled with: -cpu ,sspmpen=3Dtrue Note: This automatically enables SPMP and its depedencies. Signed-off-by: Luis Cunha --- target/riscv/cpu.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 5383e07dbd..29bfce6581 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1656,6 +1656,84 @@ static const PropertyInfo prop_pmp_granularity =3D { .set =3D prop_pmp_granularity_set, }; =20 +static void prop_spmp_set(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + RISCVCPU *cpu =3D RISCV_CPU(obj); + bool value; + + visit_type_bool(v, name, &value, errp); + + if (cpu->cfg.spmp !=3D value && riscv_cpu_is_vendor(obj)) { + cpu_set_prop_err(cpu, name, errp); + return; + } + + cpu_option_add_user_setting(name, value); + cpu->cfg.spmp =3D value; + cpu->cfg.ext_smpmpdeleg =3D value; + + /* Enable necessary extensions */ + if (value) { + cpu->cfg.ext_sscsrind =3D true; + cpu->cfg.ext_smcsrind =3D true; + } +} + +static void prop_spmp_get(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + bool value =3D RISCV_CPU(obj)->cfg.spmp; + + visit_type_bool(v, name, &value, errp); +} + +static const PropertyInfo prop_spmp =3D { + .type =3D "bool", + .description =3D "spmp", + .get =3D prop_spmp_get, + .set =3D prop_spmp_set, +}; + +static void prop_sspmpen_set(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + RISCVCPU *cpu =3D RISCV_CPU(obj); + bool value; + + visit_type_bool(v, name, &value, errp); + + if (cpu->cfg.spmp !=3D value && riscv_cpu_is_vendor(obj)) { + cpu_set_prop_err(cpu, name, errp); + return; + } + + cpu_option_add_user_setting(name, value); + cpu->cfg.ext_sspmpen =3D value; + + /* Enable necessary extensions */ + if (value) { + cpu->cfg.spmp =3D true; + cpu->cfg.ext_sscsrind =3D true; + cpu->cfg.ext_smcsrind =3D true; + } +} + +static void prop_sspmpen_get(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + bool value =3D RISCV_CPU(obj)->cfg.ext_sspmpen; + + visit_type_bool(v, name, &value, errp); +} + +static const PropertyInfo prop_ext_sspmpen =3D { + .type =3D "bool", + .description =3D "ext_sspmpen", + .get =3D prop_sspmpen_get, + .set =3D prop_sspmpen_set, +}; + static int priv_spec_from_str(const char *priv_spec_str) { int priv_version =3D -1; @@ -2657,6 +2735,8 @@ static const Property riscv_cpu_properties[] =3D { {.name =3D "pmp", .info =3D &prop_pmp}, {.name =3D "num-pmp-regions", .info =3D &prop_num_pmp_regions}, {.name =3D "pmp-granularity", .info =3D &prop_pmp_granularity}, + {.name =3D "spmp", .info =3D &prop_spmp}, + {.name =3D "sspmpen", .info =3D &prop_ext_sspmpen}, =20 {.name =3D "priv_spec", .info =3D &prop_priv_spec}, {.name =3D "vext_spec", .info =3D &prop_vext_spec}, --=20 2.43.0