Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2194956/?format=api
{ "id": 2194956, "url": "http://patchwork.ozlabs.org/api/patches/2194956/?format=api", "web_url": "http://patchwork.ozlabs.org/project/opensbi/patch/20260210094044.72591-7-ganboing@gmail.com/", "project": { "id": 67, "url": "http://patchwork.ozlabs.org/api/projects/67/?format=api", "name": "OpenSBI development", "link_name": "opensbi", "list_id": "opensbi.lists.infradead.org", "list_email": "opensbi@lists.infradead.org", "web_url": "https://github.com/riscv/opensbi", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "https://github.com/riscv/opensbi/commit/{}" }, "msgid": "<20260210094044.72591-7-ganboing@gmail.com>", "list_archive_url": null, "date": "2026-02-10T09:40:43", "name": "[6/7] lib: sbi: Rework load/store emulator instruction decoding", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "61616e995221247f770be9b5b0c81bf3a47cffe4", "submitter": { "id": 86401, "url": "http://patchwork.ozlabs.org/api/people/86401/?format=api", "name": "Bo Gan", "email": "ganboing@gmail.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/opensbi/patch/20260210094044.72591-7-ganboing@gmail.com/mbox/", "series": [ { "id": 491635, "url": "http://patchwork.ozlabs.org/api/series/491635/?format=api", "web_url": "http://patchwork.ozlabs.org/project/opensbi/list/?series=491635", "date": "2026-02-10T09:40:41", "name": "Fixes for load/store misaligned and access faults", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/491635/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2194956/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2194956/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "\n <opensbi-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n secure) header.d=lists.infradead.org header.i=@lists.infradead.org\n header.a=rsa-sha256 header.s=bombadil.20210309 header.b=O+29B9qH;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20230601 header.b=XG88fVMq;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=none (no SPF record) smtp.mailfrom=lists.infradead.org\n (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org;\n envelope-from=opensbi-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org;\n receiver=patchwork.ozlabs.org)" ], "Received": [ "from bombadil.infradead.org (bombadil.infradead.org\n [IPv6:2607:7c80:54:3::133])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4f9Gp22wcTz1xwH\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 10 Feb 2026 20:43:06 +1100 (AEDT)", "from localhost ([::1] helo=bombadil.infradead.org)\n\tby bombadil.infradead.org with esmtp (Exim 4.98.2 #2 (Red Hat Linux))\n\tid 1vpkGn-0000000Glc3-44Vv;\n\tTue, 10 Feb 2026 09:42:57 +0000", "from mail-pl1-x635.google.com ([2607:f8b0:4864:20::635])\n\tby bombadil.infradead.org with esmtps (Exim 4.98.2 #2 (Red Hat Linux))\n\tid 1vpkGl-0000000GlZa-1gmH\n\tfor opensbi@lists.infradead.org;\n\tTue, 10 Feb 2026 09:42:56 +0000", "by mail-pl1-x635.google.com with SMTP id\n d9443c01a7336-2a962230847so4937825ad.3\n for <opensbi@lists.infradead.org>;\n Tue, 10 Feb 2026 01:42:55 -0800 (PST)", "from m91p.airy.home ([172.92.174.155])\n by smtp.gmail.com with ESMTPSA id\n d9443c01a7336-2a9521b8d79sm133219215ad.61.2026.02.10.01.42.52\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 10 Feb 2026 01:42:53 -0800 (PST)" ], "DKIM-Signature": [ "v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=lists.infradead.org; s=bombadil.20210309; h=Sender:\n\tContent-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post:\n\tList-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:\n\tMessage-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description:\n\tResent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:\n\tList-Owner; bh=xMdHGpFAFZz/4/nQ/SA/9L0S6i4tDrRGyucv0XUgiO0=; b=O+29B9qHGRVw2F\n\tOQYuxlmhpaugXoquP19o49byi7S6C2xEwa2chUOzsl1ZQgHriF66qv1IwzRjwDHlPixqjgYN6WBuC\n\tXoApd7QDkyKwq7Hh1sTwsaZeOXswX9WDPa2ANjWOzyTs1JNDoMl47ERNn/MSkgn0Ps2E+PfZwgr9N\n\t2bgvFN3gfPzyc35CVP2zNBdGLAxpq8W20wWp7F1kQ+MLMZ0KbL1v1k6ERSNAsR7A1be78XZqOGChn\n\tOB55KpN9jqqVaYZxt38RpPBOYbCSZeTiNFcNuqhXQbJl18B2/F6cGV9EdhovvYGoT36VxM0JpentN\n\tAtTWFU0fC9+PjUz6EflQ==;", "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20230601; t=1770716574; x=1771321374;\n darn=lists.infradead.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=CiNt2dmvYGdVThQp0w5G/tQSM37csAffuKbYDOQOz1c=;\n b=XG88fVMqRsvYqKC5vc88jsXhe9zZPCyONa4S1ObVgcvjEYuRNxnix4bEoM2RojAXfv\n tESvztNA/umESkA2ZK21BYmFF42PAqykOreEnMLGn6OMp8LRRdl9gwyG8KQnwPqKMZbZ\n FGYb275MljnbObSr8s67hGFsOdx33CG81kCptHsT0h5LvXL+NkXNAWEYwrsZuC2H6dVw\n 81r6c3KcpEmenofWfIU5jdic+i5m6Q+XCM11ne7wEKB9m5n6n5Ycwqm6aAzVRIAnMv8D\n W1+hcE2Gl0unVDd6lGBjR8Yd0aLV7xGuuv2YvEpL6j2i91V0gWNPKSTB7D2UoB+K8+kH\n hgvA==" ], "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1770716574; x=1771321374;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=CiNt2dmvYGdVThQp0w5G/tQSM37csAffuKbYDOQOz1c=;\n b=CCknN3oppbYciAcXKG2+l0rO8gK1aeGxc0t5WsW2xbRpKWFjFVpubi8lhN5/G0FHX7\n 3+ttrVPYPal+vHEukvbwRIormUbhogrdT2qlfnc2p0wziBRFe2ff7CPNAEoWqF3n8ZRP\n xABMmmXgiT85wxozCH2Zhaiis2sgu6a1UsO3OQ1Vwy4Li6OH4fGO4WTHdLXbObBEPgMk\n IkbfLFyVNqXN87IwE8OxQ3VJgBHybc93+jVs8KyHJwiP+0xEt6nPw9cuc+/BzGiJxDdH\n EKzfCgb44l2F2Gp2jKu5lVaF+ylbW3mpv6sr1HGhjHKBnRWeIUgpFngKag2aNB/AM+JI\n SsMQ==", "X-Gm-Message-State": "AOJu0Yy2EKeCSslXwra984MpQph69EE3thBRM+TonkqOjoBJmaTxFBkl\n\tUfbojO8VmF47cn5Ae0n913JcHX69aBRjpVmbeoYxn0i2EVqLTnYGScQA/XpS+g==", "X-Gm-Gg": "AZuq6aL6MzOsv+juce2gOBKq4YapMo2Bd31DTMgoioEx7oJoho/PLSm6NVwE+lTqz/N\n\tDRsL5cLfZFNxcqXRAazQl7oiCDWh1Fp4h4osTXzqsBovPHf8Yp6ogFd9Q9WT7vlJXz9VQtL0Kwm\n\t5jlDHkB6wi7upr//8lizcWZc6MQ0ee7i1ly6d9hovXdr1yp0y70Bc9edA11wmNE0iW5r1luSJRO\n\tptmAj+dnewowN2bi3rXhG+gLllhlNBensr35kWmtuqb1fmMeUy61jd18xVzXpJR7CC48CwRvqxc\n\t1jcvvKOgUcVW1i6d+HW5WsRHR4uyMQDITwQYrT+BWeOhoCQTFAuHVTt9CekMzSQgs1jmhe1xaGO\n\tFE4H/A4g4+mJBHRk7iO1dmx7kyHVYAS00jPey/+/5M8TY2JSNlvdZ9kb3P89n2ZQMrKRO5NGtrT\n\twnOs6n4sXR5WzqKHQzYPrWae4S", "X-Received": "by 2002:a17:903:2289:b0:2aa:d1e1:29d5 with SMTP id\n d9443c01a7336-2aad1e12c0dmr92405015ad.50.1770716573869;\n Tue, 10 Feb 2026 01:42:53 -0800 (PST)", "From": "Bo Gan <ganboing@gmail.com>", "To": "opensbi@lists.infradead.org,\n\tdramforever@live.com,\n\tanup.patel@oss.qualcomm.com", "Cc": "anup@brainfault.org,\n\tcleger@rivosinc.com,\n\tsamuel.holland@sifive.com", "Subject": "[PATCH 6/7] lib: sbi: Rework load/store emulator instruction decoding", "Date": "Tue, 10 Feb 2026 01:40:43 -0800", "Message-Id": "<20260210094044.72591-7-ganboing@gmail.com>", "X-Mailer": "git-send-email 2.34.1", "In-Reply-To": "<20260210094044.72591-1-ganboing@gmail.com>", "References": "<20260210094044.72591-1-ganboing@gmail.com>", "MIME-Version": "1.0", "X-CRM114-Version": "20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 ", "X-CRM114-CacheID": "sfid-20260210_014255_470743_F9C1647F ", "X-CRM114-Status": "GOOD ( 29.64 )", "X-Spam-Score": "-2.1 (--)", "X-Spam-Report": "Spam detection software,\n running on the system \"bombadil.infradead.org\",\n has NOT identified this incoming email as spam. The original\n message has been attached to this so you can view it or label\n similar future email. If you have any questions, see\n the administrator of that system for details.\n Content preview: Rehaul instruction decoding to fix the following issues: -\n We assume the XLEN of previous mode is the same as MXLEN. However,\n RVC instructions\n decodes differently in RV32 and RV64, so shouldn't have assumed that. - We\n assume it's a misaligned fault and the [...]\n Content analysis details: (-2.1 points, 5.0 required)\n pts rule name description\n ---- ----------------------\n --------------------------------------------------\n -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no\n trust\n [2607:f8b0:4864:20:0:0:0:635 listed in]\n [list.dnswl.org]\n 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record\n -0.0 SPF_PASS SPF: sender matches SPF record\n -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from\n author's\n domain\n -0.1 DKIM_VALID Message has at least one valid DKIM or DK\n signature\n 0.1 DKIM_SIGNED Message has a DKIM or DK signature,\n not necessarily valid\n -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from\n envelope-from domain\n -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1%\n [score: 0.0000]\n 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail\n provider\n [ganboing(at)gmail.com]", "X-BeenThere": "opensbi@lists.infradead.org", "X-Mailman-Version": "2.1.34", "Precedence": "list", "List-Id": "<opensbi.lists.infradead.org>", "List-Unsubscribe": "<http://lists.infradead.org/mailman/options/opensbi>,\n <mailto:opensbi-request@lists.infradead.org?subject=unsubscribe>", "List-Archive": "<http://lists.infradead.org/pipermail/opensbi/>", "List-Post": "<mailto:opensbi@lists.infradead.org>", "List-Help": "<mailto:opensbi-request@lists.infradead.org?subject=help>", "List-Subscribe": "<http://lists.infradead.org/mailman/listinfo/opensbi>,\n <mailto:opensbi-request@lists.infradead.org?subject=subscribe>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Sender": "\"opensbi\" <opensbi-bounces@lists.infradead.org>", "Errors-To": "opensbi-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org" }, "content": "Rehaul instruction decoding to fix the following issues:\n\n- We assume the XLEN of previous mode is the same as MXLEN. However,\n RVC instructions decodes differently in RV32 and RV64, so shouldn't\n have assumed that.\n- We assume it's a misaligned fault and the load/store offset is 0,\n i.e., base address == fault address, but access faults can have\n non-0 offset (on HW supporting misaligned accesses), so platform\n specific load/store fault handler gets the wrong base address.\n- No checking of [63:32] of tinst in RV64, which is explicitly\n required by Privileged ISA 19.6.3. Must reject tinst with non-0\n high 32 bits.\n\nThus, fix all the above. For misaligned load/store fault, the address\noffset is always 0, thus we kill the use of base address, and use trap\naddress instead (same as before), which lets the compiler optimize out\nimm parsing and other calculations.\n\nI also analyzed the behavior of misaligned fault handler before fix.\nWith the following conditions met, it can trigger data corruption:\n\n- HW doesn't transform instruction into tinst.\n- HW doesn't support misaligned load/store, and OS doesn't enable\n misaligned delegation, thus OpenSBI handler is in effect\n- HW supports mixed XLEN, and M mode is running RV64, and the trapping\n mode (U/VS/VU) is running RV32.\n- The trapping instruction is c.f{l|s}w(sp).\n\nDue to the incorrect insn decoding, the trapping instruction would\nmistakenly be decoded as c.{l|s}d(sp). With this fix, c.f{l|s}w(sp)\nin RV32 is now emulated correctly.\n\nValidation:\nThe patch is validated to have fixed the issue with test cases running\non a modified version of QEMU that exposes misaligned faults [1], and\na further modified version that removes tinst transformation [2]. The\nS-mode OS is a local build of Debian Trixie 6.12 kernel that enables\nCOMPAT (RV32), and the U-mode test application exercises all integer\nand floating-point load/store (RVIFD64/32+RVC64/32) instructions with\nall possible imm values. The patch is also tested on real HW (Sifive\nP550/ESWIN EIC7700), which only supports RV64. On P550, the same test\nwas validated both in U mode and VU mode, where the host runs a 6.12\nESWIN vendor kernel that has some ESWIN SoC device driver patches [3]\napplied, and the guest runs the exact same Debian Trixie 6.12 kernel\nmentioned above.\n\n[1] https://github.com/ganboing/qemu/tree/ganboing-misalign\n[2] https://github.com/ganboing/qemu/tree/ganboing-misalign-no-tinst\n[3] https://github.com/sifiveinc/riscv-linux/tree/rel/kernel-6.12/hifive-premier-p550\n\nFixes: 7219477f7b40 (\"lib: Use MTINST CSR in misaligned load/store emulation\")\nFixes: b5ae8e8a650d (\"lib: Add misaligned load/store trap handling\")\nFixes: 4c112650bbb0 (\"lib: sbi: abstract out insn decoding to unify mem fault handlers\")\nSigned-off-by: Bo Gan <ganboing@gmail.com>\n---\n lib/sbi/sbi_trap_ldst.c | 427 +++++++++++++++++++++++++++-------------\n 1 file changed, 295 insertions(+), 132 deletions(-)", "diff": "diff --git a/lib/sbi/sbi_trap_ldst.c b/lib/sbi/sbi_trap_ldst.c\nindex 22c4d5a7..2371abca 100644\n--- a/lib/sbi/sbi_trap_ldst.c\n+++ b/lib/sbi/sbi_trap_ldst.c\n@@ -44,30 +44,34 @@ ulong sbi_misaligned_tinst_fixup(ulong orig_tinst, ulong new_tinst,\n \t\treturn orig_tinst | (addr_offset << SH_RS1);\n }\n \n+static inline bool sbi_trap_tinst_valid(ulong tinst)\n+{\n+\t/*\n+\t * Bit[0] == 1 implies trapped instruction value is\n+\t * transformed instruction or custom instruction.\n+\t * Also do proper checking per Privileged ISA 19.6.3,\n+\t * and make sure high 32 bits of tinst is 0\n+\t */\n+\treturn tinst == (uint32_t)tinst && (tinst & 0x1);\n+}\n+\n static int sbi_trap_emulate_load(struct sbi_trap_context *tcntx,\n \t\t\t\t sbi_trap_ld_emulator emu)\n {\n \tconst struct sbi_trap_info *orig_trap = &tcntx->trap;\n \tstruct sbi_trap_regs *regs = &tcntx->regs;\n-\tulong insn, insn_len;\n+\tulong insn, insn_len, imm = 0, shift = 0, off = 0;\n \tunion sbi_ldst_data val = { 0 };\n \tstruct sbi_trap_info uptrap;\n-\tint rc, fp = 0, shift = 0, len = 0;\n-\tbool xform = false;\n-\n-\tif (orig_trap->tinst & 0x1) {\n-\t\t/*\n-\t\t * Bit[0] == 1 implies trapped instruction value is\n-\t\t * transformed instruction or custom instruction.\n-\t\t */\n+\tbool xform = false, fp = false, c_load = false, c_ldsp = false;\n+\tint rc, len = 0, prev_xlen = 0;\n+\n+\tif (sbi_trap_tinst_valid(orig_trap->tinst)) {\n \t\txform\t = true;\n \t\tinsn\t = orig_trap->tinst | INSN_16BIT_MASK;\n \t\tinsn_len = (orig_trap->tinst & 0x2) ? INSN_LEN(insn) : 2;\n \t} else {\n-\t\t/*\n-\t\t * Bit[0] == 0 implies trapped instruction value is\n-\t\t * zero or special value.\n-\t\t */\n+\t\t/* trapped instruction value is zero or special value */\n \t\tinsn = sbi_get_insn(regs->mepc, &uptrap);\n \t\tif (uptrap.cause) {\n \t\t\treturn sbi_trap_redirect(regs, &uptrap);\n@@ -75,92 +79,170 @@ static int sbi_trap_emulate_load(struct sbi_trap_context *tcntx,\n \t\tinsn_len = INSN_LEN(insn);\n \t}\n \n+\t/**\n+\t * Common for RV32/RV64:\n+\t * lb, lbu, lh, lhu, lw, flw, flw\n+\t * c.lbu, c.lh, c.lhu, c.lw, c.lwsp, c.fld, c.fldsp\n+\t */\n \tif ((insn & INSN_MASK_LB) == INSN_MATCH_LB) {\n-\t\tlen = 1;\n-\t\tshift = 8 * (sizeof(ulong) - len);\n+\t\tlen = -1;\n \t} else if ((insn & INSN_MASK_LBU) == INSN_MATCH_LBU) {\n \t\tlen = 1;\n-\t} else if ((insn & INSN_MASK_LW) == INSN_MATCH_LW) {\n-\t\tlen = 4;\n-\t\tshift = 8 * (sizeof(ulong) - len);\n-#if __riscv_xlen == 64\n-\t} else if ((insn & INSN_MASK_LD) == INSN_MATCH_LD) {\n-\t\tlen = 8;\n-\t\tshift = 8 * (sizeof(ulong) - len);\n-\t} else if ((insn & INSN_MASK_LWU) == INSN_MATCH_LWU) {\n-\t\tlen = 4;\n-#endif\n-#ifdef __riscv_flen\n-\t} else if ((insn & INSN_MASK_FLD) == INSN_MATCH_FLD) {\n-\t\tfp = 1;\n-\t\tlen = 8;\n-\t} else if ((insn & INSN_MASK_FLW) == INSN_MATCH_FLW) {\n-\t\tfp = 1;\n-\t\tlen = 4;\n-#endif\n+\t} else if ((insn & INSN_MASK_C_LBU) == INSN_MATCH_C_LBU) {\n+\t\t/* Zcb */\n+\t\tlen = 1;\n+\t\timm = RVC_LB_IMM(insn);\n+\t\tc_load = true;\n \t} else if ((insn & INSN_MASK_LH) == INSN_MATCH_LH) {\n-\t\tlen = 2;\n-\t\tshift = 8 * (sizeof(ulong) - len);\n+\t\tlen = -2;\n+\t} else if ((insn & INSN_MASK_C_LH) == INSN_MATCH_C_LH) {\n+\t\t/* Zcb */\n+\t\tlen = -2;\n+\t\timm = RVC_LH_IMM(insn);\n+\t\tc_load = true;\n \t} else if ((insn & INSN_MASK_LHU) == INSN_MATCH_LHU) {\n \t\tlen = 2;\n-#if __riscv_xlen >= 64\n-\t} else if ((insn & INSN_MASK_C_LD) == INSN_MATCH_C_LD) {\n-\t\tlen = 8;\n-\t\tshift = 8 * (sizeof(ulong) - len);\n-\t\tinsn = RVC_RS2S(insn) << SH_RD;\n-\t} else if ((insn & INSN_MASK_C_LDSP) == INSN_MATCH_C_LDSP &&\n-\t\t ((insn >> SH_RD) & 0x1f)) {\n-\t\tlen = 8;\n-\t\tshift = 8 * (sizeof(ulong) - len);\n-#endif\n+\t} else if ((insn & INSN_MASK_C_LHU) == INSN_MATCH_C_LHU) {\n+\t\t/* Zcb */\n+\t\tlen = 2;\n+\t\timm = RVC_LH_IMM(insn);\n+\t\tc_load = true;\n+\t} else if ((insn & INSN_MASK_LW) == INSN_MATCH_LW) {\n+\t\tlen = -4;\n \t} else if ((insn & INSN_MASK_C_LW) == INSN_MATCH_C_LW) {\n-\t\tlen = 4;\n-\t\tshift = 8 * (sizeof(ulong) - len);\n-\t\tinsn = RVC_RS2S(insn) << SH_RD;\n+\t\t/* Zca */\n+\t\tlen = -4;\n+\t\timm = RVC_LW_IMM(insn);\n+\t\tc_load = true;\n \t} else if ((insn & INSN_MASK_C_LWSP) == INSN_MATCH_C_LWSP &&\n-\t\t ((insn >> SH_RD) & 0x1f)) {\n-\t\tlen = 4;\n-\t\tshift = 8 * (sizeof(ulong) - len);\n+\t\tGET_RD_NUM(insn)) {\n+\t\t/* Zca */\n+\t\tlen = -4;\n+\t\timm = RVC_LWSP_IMM(insn);\n+\t\tc_ldsp = true;\n #ifdef __riscv_flen\n+\t} else if ((insn & INSN_MASK_FLW) == INSN_MATCH_FLW) {\n+\t\tlen = 4;\n+\t\tfp = true;\n+\t} else if ((insn & INSN_MASK_FLD) == INSN_MATCH_FLD) {\n+\t\tlen = 8;\n+\t\tfp = true;\n \t} else if ((insn & INSN_MASK_C_FLD) == INSN_MATCH_C_FLD) {\n-\t\tfp = 1;\n-\t\tlen = 8;\n-\t\tinsn = RVC_RS2S(insn) << SH_RD;\n+\t\t/* Zcd */\n+\t\tlen = 8;\n+\t\timm = RVC_LD_IMM(insn);\n+\t\tc_load = true;\n+\t\tfp = true;\n \t} else if ((insn & INSN_MASK_C_FLDSP) == INSN_MATCH_C_FLDSP) {\n-\t\tfp = 1;\n+\t\t/* Zcd */\n \t\tlen = 8;\n-#if __riscv_xlen == 32\n-\t} else if ((insn & INSN_MASK_C_FLW) == INSN_MATCH_C_FLW) {\n-\t\tfp = 1;\n-\t\tlen = 4;\n-\t\tinsn = RVC_RS2S(insn) << SH_RD;\n-\t} else if ((insn & INSN_MASK_C_FLWSP) == INSN_MATCH_C_FLWSP) {\n-\t\tfp = 1;\n-\t\tlen = 4;\n+\t\timm = RVC_LDSP_IMM(insn);\n+\t\tc_ldsp = true;\n+\t\tfp = true;\n #endif\n+\t} else {\n+\t\tprev_xlen = sbi_regs_prev_xlen(regs);\n+\t}\n+\n+\t/**\n+\t * Must distinguish between rv64 and rv32, RVC instructions have\n+\t * overlapping encoding:\n+\t * c.ld in rv64 == c.flw in rv32\n+\t * c.ldsp in rv64 == c.flwsp in rv32\n+\t */\n+\tif (prev_xlen == 64) {\n+\t\t/* RV64 Only: lwu, ld, c.ld, c.ldsp */\n+\t\tif ((insn & INSN_MASK_LWU) == INSN_MATCH_LWU) {\n+\t\t\tlen = 4;\n+\t\t} else if ((insn & INSN_MASK_LD) == INSN_MATCH_LD) {\n+\t\t\tlen = 8;\n+\t\t} else if ((insn & INSN_MASK_C_LD) == INSN_MATCH_C_LD) {\n+\t\t\t/* Zca */\n+\t\t\tlen = 8;\n+\t\t\timm = RVC_LD_IMM(insn);\n+\t\t\tc_load = true;\n+\t\t} else if ((insn & INSN_MASK_C_LDSP) == INSN_MATCH_C_LDSP &&\n+\t\t\tGET_RD_NUM(insn)) {\n+\t\t\t/* Zca */\n+\t\t\tlen = 8;\n+\t\t\timm = RVC_LDSP_IMM(insn);\n+\t\t\tc_ldsp = true;\n+\t\t}\n+#ifdef __riscv_flen\n+\t} else if (prev_xlen == 32) {\n+\t\t/* RV32 Only: c.flw, c.flwsp */\n+\t\tif ((insn & INSN_MASK_C_FLW) == INSN_MATCH_C_FLW) {\n+\t\t\t/* Zcf */\n+\t\t\tlen = 4;\n+\t\t\timm = RVC_LW_IMM(insn);\n+\t\t\tc_load = true;\n+\t\t\tfp = true;\n+\t\t} else if ((insn & INSN_MASK_C_FLWSP) == INSN_MATCH_C_FLWSP) {\n+\t\t\t/* Zcf */\n+\t\t\tlen = 4;\n+\t\t\timm = RVC_LWSP_IMM(insn);\n+\t\t\tc_ldsp = true;\n+\t\t\tfp = true;\n+\t\t}\n #endif\n-\t} else if ((insn & INSN_MASK_C_LHU) == INSN_MATCH_C_LHU) {\n-\t\tlen = 2;\n-\t\tinsn = RVC_RS2S(insn) << SH_RD;\n-\t} else if ((insn & INSN_MASK_C_LH) == INSN_MATCH_C_LH) {\n-\t\tlen = 2;\n+\t}\n+\n+\tif (len < 0) {\n+\t\tlen = -len;\n \t\tshift = 8 * (sizeof(ulong) - len);\n-\t\tinsn = RVC_RS2S(insn) << SH_RD;\n \t}\n \n-\trc = emu(xform ? 0 : insn, len, orig_trap->tval, &val, tcntx);\n+\tif (!len || orig_trap->cause == CAUSE_MISALIGNED_LOAD)\n+\t\t/* Unknown instruction or no need to calculate offset */\n+\t\tgoto do_emu;\n+\n+\tif (xform)\n+\t\t/* Transformed insn */\n+\t\toff = GET_RS1_NUM(insn);\n+\telse if (c_load)\n+\t\t/* non SP-based compressed load */\n+\t\toff = orig_trap->tval - GET_RS1S(insn, regs) - imm;\n+\telse if (c_ldsp)\n+\t\t/* SP-based compressed load */\n+\t\toff = orig_trap->tval - REG_VAL(2, regs) - imm;\n+\telse\n+\t\t/* I-type non-compressed load */\n+\t\toff = orig_trap->tval - GET_RS1(insn, regs) - (ulong)IMM_I(insn);\n+\t/**\n+\t * Normalize offset, in case the XLEN of unpriv mode is smaller,\n+\t * and/or pointer masking is in effect\n+\t */\n+\toff &= (len - 1);\n+\n+do_emu:\n+\trc = emu(xform ? 0 : insn, len, orig_trap->tval - off, &val, tcntx);\n \tif (rc <= 0)\n \t\treturn rc;\n+\tif (!len)\n+\t\tgoto epc_fixup;\n+\n+\tif (!fp) {\n+\t\tulong v = ((long)(val.data_ulong << shift)) >> shift;\n \n-\tif (!fp)\n-\t\tSET_RD(insn, regs, ((long)(val.data_ulong << shift)) >> shift);\n+\t\tif (c_load)\n+\t\t\tSET_RDS(insn, regs, v);\n+\t\telse\n+\t\t\tSET_RD(insn, regs, v);\n #ifdef __riscv_flen\n-\telse if (len == 8)\n-\t\tSET_F64_RD(insn, regs, val.data_u64);\n-\telse\n-\t\tSET_F32_RD(insn, regs, val.data_ulong);\n+\t} else if (len == 8) {\n+\t\tif (c_load)\n+\t\t\tSET_F64_RDS(insn, regs, val.data_u64);\n+\t\telse\n+\t\t\tSET_F64_RD(insn, regs, val.data_u64);\n+\t} else {\n+\t\tif (c_load)\n+\t\t\tSET_F32_RDS(insn, regs, val.data_ulong);\n+\t\telse\n+\t\t\tSET_F32_RD(insn, regs, val.data_ulong);\n #endif\n+\t}\n \n+epc_fixup:\n \tregs->mepc += insn_len;\n \n \treturn 0;\n@@ -171,25 +253,18 @@ static int sbi_trap_emulate_store(struct sbi_trap_context *tcntx,\n {\n \tconst struct sbi_trap_info *orig_trap = &tcntx->trap;\n \tstruct sbi_trap_regs *regs = &tcntx->regs;\n-\tulong insn, insn_len;\n+\tulong insn, insn_len, imm = 0, off = 0;\n \tunion sbi_ldst_data val;\n \tstruct sbi_trap_info uptrap;\n-\tint rc, len = 0;\n-\tbool xform = false;\n-\n-\tif (orig_trap->tinst & 0x1) {\n-\t\t/*\n-\t\t * Bit[0] == 1 implies trapped instruction value is\n-\t\t * transformed instruction or custom instruction.\n-\t\t */\n+\tbool xform = false, fp = false, c_store = false, c_stsp = false;\n+\tint rc, len = 0, prev_xlen = 0;\n+\n+\tif (sbi_trap_tinst_valid(orig_trap->tinst)) {\n \t\txform\t = true;\n \t\tinsn\t = orig_trap->tinst | INSN_16BIT_MASK;\n \t\tinsn_len = (orig_trap->tinst & 0x2) ? INSN_LEN(insn) : 2;\n \t} else {\n-\t\t/*\n-\t\t * Bit[0] == 0 implies trapped instruction value is\n-\t\t * zero or special value.\n-\t\t */\n+\t\t/* trapped instruction value is zero or special value */\n \t\tinsn = sbi_get_insn(regs->mepc, &uptrap);\n \t\tif (uptrap.cause) {\n \t\t\treturn sbi_trap_redirect(regs, &uptrap);\n@@ -197,62 +272,150 @@ static int sbi_trap_emulate_store(struct sbi_trap_context *tcntx,\n \t\tinsn_len = INSN_LEN(insn);\n \t}\n \n-\tval.data_ulong = GET_RS2(insn, regs);\n-\n+\t/**\n+\t * Common for RV32/RV64:\n+\t * sb, sh, sw, fsw, fsd\n+\t * c.sb, c.sh, c.sw, c.swsp, c.fsd, c.fsdsp\n+\t */\n \tif ((insn & INSN_MASK_SB) == INSN_MATCH_SB) {\n \t\tlen = 1;\n-\t} else if ((insn & INSN_MASK_SW) == INSN_MATCH_SW) {\n-\t\tlen = 4;\n-#if __riscv_xlen == 64\n-\t} else if ((insn & INSN_MASK_SD) == INSN_MATCH_SD) {\n-\t\tlen = 8;\n-#endif\n-#ifdef __riscv_flen\n-\t} else if ((insn & INSN_MASK_FSD) == INSN_MATCH_FSD) {\n-\t\tlen\t = 8;\n-\t\tval.data_u64 = GET_F64_RS2(insn, regs);\n-\t} else if ((insn & INSN_MASK_FSW) == INSN_MATCH_FSW) {\n-\t\tlen\t = 4;\n-\t\tval.data_ulong = GET_F32_RS2(insn, regs);\n-#endif\n+\t} else if ((insn & INSN_MASK_C_SB) == INSN_MATCH_C_SB) {\n+\t\t/* Zcb */\n+\t\tlen = 1;\n+\t\timm = RVC_SB_IMM(insn);\n+\t\tc_store = true;\n \t} else if ((insn & INSN_MASK_SH) == INSN_MATCH_SH) {\n \t\tlen = 2;\n-#if __riscv_xlen >= 64\n-\t} else if ((insn & INSN_MASK_C_SD) == INSN_MATCH_C_SD) {\n-\t\tlen\t = 8;\n-\t\tval.data_ulong = GET_RS2S(insn, regs);\n-\t} else if ((insn & INSN_MASK_C_SDSP) == INSN_MATCH_C_SDSP) {\n-\t\tlen\t = 8;\n-\t\tval.data_ulong = GET_RS2C(insn, regs);\n-#endif\n+\t} else if ((insn & INSN_MASK_C_SH) == INSN_MATCH_C_SH) {\n+\t\t/* Zcb */\n+\t\tlen = 2;\n+\t\timm = RVC_SH_IMM(insn);\n+\t\tc_store = true;\n+\t} else if ((insn & INSN_MASK_SW) == INSN_MATCH_SW) {\n+\t\tlen = 4;\n \t} else if ((insn & INSN_MASK_C_SW) == INSN_MATCH_C_SW) {\n-\t\tlen\t = 4;\n-\t\tval.data_ulong = GET_RS2S(insn, regs);\n+\t\t/* Zca */\n+\t\tlen = 4;\n+\t\timm = RVC_SW_IMM(insn);\n+\t\tc_store = true;\n \t} else if ((insn & INSN_MASK_C_SWSP) == INSN_MATCH_C_SWSP) {\n-\t\tlen\t = 4;\n-\t\tval.data_ulong = GET_RS2C(insn, regs);\n+\t\t/* Zca */\n+\t\tlen = 4;\n+\t\timm = RVC_SWSP_IMM(insn);\n+\t\tc_stsp = true;\n #ifdef __riscv_flen\n+\t} else if ((insn & INSN_MASK_FSW) == INSN_MATCH_FSW) {\n+\t\tlen = 4;\n+\t\tfp = true;\n+\t} else if ((insn & INSN_MASK_FSD) == INSN_MATCH_FSD) {\n+\t\tlen = 8;\n+\t\tfp = true;\n \t} else if ((insn & INSN_MASK_C_FSD) == INSN_MATCH_C_FSD) {\n-\t\tlen\t = 8;\n-\t\tval.data_u64 = GET_F64_RS2S(insn, regs);\n+\t\t/* Zcd */\n+\t\tlen = 8;\n+\t\timm = RVC_SD_IMM(insn);\n+\t\tc_store = true;\n+\t\tfp = true;\n \t} else if ((insn & INSN_MASK_C_FSDSP) == INSN_MATCH_C_FSDSP) {\n-\t\tlen\t = 8;\n-\t\tval.data_u64 = GET_F64_RS2C(insn, regs);\n-#if __riscv_xlen == 32\n-\t} else if ((insn & INSN_MASK_C_FSW) == INSN_MATCH_C_FSW) {\n-\t\tlen\t = 4;\n-\t\tval.data_ulong = GET_F32_RS2S(insn, regs);\n-\t} else if ((insn & INSN_MASK_C_FSWSP) == INSN_MATCH_C_FSWSP) {\n-\t\tlen\t = 4;\n-\t\tval.data_ulong = GET_F32_RS2C(insn, regs);\n+\t\t/* Zcd */\n+\t\tlen = 8;\n+\t\timm = RVC_SDSP_IMM(insn);\n+\t\tc_stsp = true;\n+\t\tfp = true;\n #endif\n+\t} else {\n+\t\tprev_xlen = sbi_regs_prev_xlen(regs);\n+\t}\n+\n+\t/**\n+\t * Must distinguish between rv64 and rv32, RVC instructions have\n+\t * overlapping encoding:\n+\t * c.sd in rv64 == c.fsw in rv32\n+\t * c.sdsp in rv64 == c.fswsp in rv32\n+\t */\n+\tif (prev_xlen == 64) {\n+\t\t/* RV64 Only: sd, c.sd, c.sdsp */\n+\t\tif ((insn & INSN_MASK_SD) == INSN_MATCH_SD) {\n+\t\t\tlen = 8;\n+\t\t} else if ((insn & INSN_MASK_C_SD) == INSN_MATCH_C_SD) {\n+\t\t\t/* Zca */\n+\t\t\tlen = 8;\n+\t\t\timm = RVC_SD_IMM(insn);\n+\t\t\tc_store = true;\n+\t\t} else if ((insn & INSN_MASK_C_SDSP) == INSN_MATCH_C_SDSP) {\n+\t\t\t/* Zca */\n+\t\t\tlen = 8;\n+\t\t\timm = RVC_SDSP_IMM(insn);\n+\t\t\tc_stsp = true;\n+\t\t}\n+#ifdef __riscv_flen\n+\t} else if (prev_xlen == 32) {\n+\t\t/* RV32 Only: c.fsw, c.fswsp */\n+\t\tif ((insn & INSN_MASK_C_FSW) == INSN_MATCH_C_FSW) {\n+\t\t\t/* Zcf */\n+\t\t\tlen = 4;\n+\t\t\timm = RVC_SW_IMM(insn);\n+\t\t\tc_store = true;\n+\t\t\tfp = true;\n+\t\t} else if ((insn & INSN_MASK_C_FSWSP) == INSN_MATCH_C_FSWSP) {\n+\t\t\t/* Zcf */\n+\t\t\tlen = 4;\n+\t\t\timm = RVC_SWSP_IMM(insn);\n+\t\t\tc_stsp = true;\n+\t\t\tfp = true;\n+\t\t}\n #endif\n-\t} else if ((insn & INSN_MASK_C_SH) == INSN_MATCH_C_SH) {\n-\t\tlen\t\t= 2;\n-\t\tval.data_ulong = GET_RS2S(insn, regs);\n \t}\n \n-\trc = emu(xform ? 0 : insn, len, orig_trap->tval, val, tcntx);\n+\tif (!fp) {\n+\t\tif (c_store)\n+\t\t\tval.data_ulong = GET_RS2S(insn, regs);\n+\t\telse if (c_stsp)\n+\t\t\tval.data_ulong = GET_RS2C(insn, regs);\n+\t\telse\n+\t\t\tval.data_ulong = GET_RS2(insn, regs);\n+#ifdef __riscv_flen\n+\t} else if (len == 8) {\n+\t\tif (c_store)\n+\t\t\tval.data_u64 = GET_F64_RS2S(insn, regs);\n+\t\telse if (c_stsp)\n+\t\t\tval.data_u64 = GET_F64_RS2C(insn, regs);\n+\t\telse\n+\t\t\tval.data_u64 = GET_F64_RS2(insn, regs);\n+\t} else {\n+\t\tif (c_store)\n+\t\t\tval.data_ulong = GET_F32_RS2S(insn, regs);\n+\t\telse if (c_stsp)\n+\t\t\tval.data_ulong = GET_F32_RS2C(insn, regs);\n+\t\telse\n+\t\t\tval.data_ulong = GET_F32_RS2(insn, regs);\n+#endif\n+\t}\n+\n+\tif (!len || orig_trap->cause == CAUSE_MISALIGNED_STORE)\n+\t\t/* Unknown instruction or no need to calculate offset */\n+\t\tgoto do_emu;\n+\n+\tif (xform)\n+\t\t/* Transformed insn */\n+\t\toff = GET_RS1_NUM(insn);\n+\telse if (c_store)\n+\t\t/* non SP-based compressed store */\n+\t\toff = orig_trap->tval - GET_RS1S(insn, regs) - imm;\n+\telse if (c_stsp)\n+\t\t/* SP-based compressed store */\n+\t\toff = orig_trap->tval - REG_VAL(2, regs) - imm;\n+\telse\n+\t\t/* S-type non-compressed store */\n+\t\toff = orig_trap->tval - GET_RS1(insn, regs) - (ulong)IMM_S(insn);\n+\t/**\n+\t * Normalize offset, in case the XLEN of unpriv mode is smaller,\n+\t * and/or pointer masking is in effect\n+\t */\n+\toff &= (len - 1);\n+\n+do_emu:\n+\trc = emu(xform ? 0 : insn, len, orig_trap->tval - off, val, tcntx);\n \tif (rc <= 0)\n \t\treturn rc;\n \n", "prefixes": [ "6/7" ] }