From patchwork Wed Mar 6 02:35:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bo Gan X-Patchwork-Id: 1908519 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=ms9VpiX6; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=VQajiwnd; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org; envelope-from=opensbi-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=patchwork.ozlabs.org) Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4TqGlW1MjKz23qm for ; Wed, 6 Mar 2024 13:36:23 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:List-Subscribe:List-Help: List-Post:List-Archive:List-Unsubscribe:List-Id:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=4algO4F0tg6nJ5ZL4vZpC7TlW4QDUNOOyVSq3sVKZf8=; b=ms9VpiX6VUb95b a7tCtqQwZK3MsgfX7Ps27KJLc5ZVEFDJveipq45nzi5SFS2k1LzvCE5O3Kf22nvSPR3OK6m+4+Ri0 STyBm3FUYj1SRnM+dU4+kz/zi3rbjUPmLewXQW1OK988T3V9QEByP+Ot9fXeDxX4yPQIEiLLb3qn4 /678EwiCM57fgM1yrqetFyhy1/0qehnNtpVOp1anJXjfpRVVFY0InSlPaxuZF/52LmhDos6lTnKxD FHPFO5B/kSsskdhHzl7M/3+KfLgUgNtJ7e7Jd1XK2a3DHN5rkPhYBQZ9NVU6pwtIJ6ZtvPT7dOK40 mM7wNRgGQca+lg7IVUZg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rhh8i-0000000G0MI-0Or0; Wed, 06 Mar 2024 02:36:16 +0000 Received: from mail-pf1-x436.google.com ([2607:f8b0:4864:20::436]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rhh8d-0000000G0Iy-1hy5 for opensbi@lists.infradead.org; Wed, 06 Mar 2024 02:36:13 +0000 Received: by mail-pf1-x436.google.com with SMTP id d2e1a72fcca58-6e622b46f45so2400574b3a.1 for ; Tue, 05 Mar 2024 18:36:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1709692570; x=1710297370; darn=lists.infradead.org; h=references:in-reply-to:message-id:date:subject:cc:to:from:from:to :cc:subject:date:message-id:reply-to; bh=CMkVtWmTUWos8JnjZmuHx82VD/GZFURCXwcQVvybDvI=; b=VQajiwndbYetzeb1QFNJj5qEeKLLwmASsbzT5AHaX+cImYDbL4pgXayA54rZziYoio IfhTcAeHakk9Ee2BoFpEHm7+o+KNo4Jodqqs4QCS+m/A2hjddWzVa5epNLglrFM3htJm Zhk6i3FuWth1rfC329JNfqAwCfxONilnAavAPEymCMjBarAH0kwt0WEsAyyLm/0Y2d+J ZnpUQ9S4A7S/SkK5oQAbGSBviGxJgA92SMQ13XFOOsbyHkryZ3QVq2yZtK6vTTRKPNxW GlsFGbDArHIT+PZALc/PF7otaUxK1A5sZKMhRcYWbN2HUySh2PlW6pUP6nt7ZTtTPT93 FVLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709692570; x=1710297370; h=references:in-reply-to:message-id:date:subject:cc:to:from :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=CMkVtWmTUWos8JnjZmuHx82VD/GZFURCXwcQVvybDvI=; b=Ux5BDtT4o9MzDK5sd42WaJ09s4sx7Zw5Gq13YHvFS4CNs052hQ/3ce2R3yeGiv0aK9 l+n0N5ZBo1G/7WBlFSy8ZdrzrnFtSfwClTc9uomS3zCzly4ZuNL9flnUPsVKJbl6Dqg9 Kh6iNh5r6npUXsTPAu0p+GM50FYZU6FFmuSMwNu5ohSGZEL4aQ0H18NuYtC2v1xIPUtZ 92EurU381DsXSklqNMYcJvJ9mKIy9qQ6MQ2EjjOJfTVxCJZgdP4MNl5Z17WIn/VOOzTh L9TH8RZ/D80aJkYFk+C+yWCf8Sa7Ex/5hpYVEC6aZUFl87YRt9gcNdOwkRWrmZDYWpXY JmHA== X-Gm-Message-State: AOJu0YwQip8NmA68IWj7fqt2PoqOmnlpcTrSyv4xKFrXDVoVxntmj8oC 6pDrGgcMt+mUJHDAvA9LZkIEgZZhum0R/ByYpH6Pvasnkp+dsC3tzd2VzlutMiY= X-Google-Smtp-Source: AGHT+IGWaNg0j4ntDb1nxeJ+IXhVrii2Ag9MfK9wGiExSzcIFi9T2S2me0CHO33kWoQoKzK8nG35Rg== X-Received: by 2002:a05:6a20:1e5e:b0:1a1:4ca8:da1e with SMTP id cy30-20020a056a201e5e00b001a14ca8da1emr2668947pzb.52.1709692569666; Tue, 05 Mar 2024 18:36:09 -0800 (PST) Received: from m91p.airy.home ([172.92.174.232]) by smtp.gmail.com with ESMTPSA id v27-20020aa799db000000b006e5a0abb167sm9005653pfi.1.2024.03.05.18.36.08 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 05 Mar 2024 18:36:08 -0800 (PST) From: Bo Gan To: opensbi@lists.infradead.org Cc: wxjstz@126.com, anup@brainfault.org Subject: [PATCH v4 5/7] lib: sbi: abstract out insn decoding to unify mem fault handlers Date: Tue, 5 Mar 2024 18:35:38 -0800 Message-Id: <1709692540-77803-6-git-send-email-ganboing@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1709692540-77803-1-git-send-email-ganboing@gmail.com> References: <1709692540-77803-1-git-send-email-ganboing@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240305_183611_651273_A8C562B5 X-CRM114-Status: GOOD ( 19.26 ) X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: This patch abstracts out the instruction decoding part of misaligned ld/st fault handlers, so it can be reused by ld/st access fault handlers. Also Added lb/lbu/sb decoding. (previously unreachable by [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:436 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [ganboing(at)gmail.com] -0.0 T_SCC_BODY_TEXT_LINE No description available. X-BeenThere: opensbi@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "opensbi" Errors-To: opensbi-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org This patch abstracts out the instruction decoding part of misaligned ld/st fault handlers, so it can be reused by ld/st access fault handlers. Also Added lb/lbu/sb decoding. (previously unreachable by misaligned fault) sbi_trap_emulate_load/store is now the common handler which takes a `emu` parameter that is responsible for emulating the misaligned or access fault. The `emu` callback is expected to fixup the fault, and based on the return code of `emu`, sbi_trap_emulate_load/store will: r/wlen => the fixup is successful and regs/mepc needs to be updated. 0 => the fixup is successful, but regs/mepc should be left untouched (this is usually used if `emu` does `sbi_trap_redirect`) -err => failed, sbi_trap_error will be called For now, load/store access faults are blindly redirected. It will be enhanced in the following patches. Signed-off-by: Bo Gan Reviewed-by: Anup Patel --- include/sbi/sbi_trap_ldst.h | 13 +++- lib/sbi/sbi_trap.c | 13 +++- lib/sbi/sbi_trap_ldst.c | 150 ++++++++++++++++++++++++++++++++------------ 3 files changed, 132 insertions(+), 44 deletions(-) diff --git a/include/sbi/sbi_trap_ldst.h b/include/sbi/sbi_trap_ldst.h index 5f0ed92..9cab4e4 100644 --- a/include/sbi/sbi_trap_ldst.h +++ b/include/sbi/sbi_trap_ldst.h @@ -13,7 +13,12 @@ #include #include -struct sbi_trap_regs; +union sbi_ldst_data { + u64 data_u64; + u32 data_u32; + u8 data_bytes[8]; + ulong data_ulong; +}; int sbi_misaligned_load_handler(struct sbi_trap_regs *regs, const struct sbi_trap_info *orig_trap); @@ -21,4 +26,10 @@ int sbi_misaligned_load_handler(struct sbi_trap_regs *regs, int sbi_misaligned_store_handler(struct sbi_trap_regs *regs, const struct sbi_trap_info *orig_trap); +int sbi_load_access_handler(struct sbi_trap_regs *regs, + const struct sbi_trap_info *orig_trap); + +int sbi_store_access_handler(struct sbi_trap_regs *regs, + const struct sbi_trap_info *orig_trap); + #endif diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c index e379984..c665013 100644 --- a/lib/sbi/sbi_trap.c +++ b/lib/sbi/sbi_trap.c @@ -299,10 +299,12 @@ struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs) msg = "illegal instruction handler failed"; break; case CAUSE_MISALIGNED_LOAD: + sbi_pmu_ctr_incr_fw(SBI_PMU_FW_MISALIGNED_LOAD); rc = sbi_misaligned_load_handler(regs, &trap); msg = "misaligned load handler failed"; break; case CAUSE_MISALIGNED_STORE: + sbi_pmu_ctr_incr_fw(SBI_PMU_FW_MISALIGNED_STORE); rc = sbi_misaligned_store_handler(regs, &trap); msg = "misaligned store handler failed"; break; @@ -312,10 +314,15 @@ struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs) msg = "ecall handler failed"; break; case CAUSE_LOAD_ACCESS: + sbi_pmu_ctr_incr_fw(SBI_PMU_FW_ACCESS_LOAD); + rc = sbi_load_access_handler(regs, &trap); + msg = "load fault handler failed"; + break; case CAUSE_STORE_ACCESS: - sbi_pmu_ctr_incr_fw(mcause == CAUSE_LOAD_ACCESS ? - SBI_PMU_FW_ACCESS_LOAD : SBI_PMU_FW_ACCESS_STORE); - /* fallthrough */ + sbi_pmu_ctr_incr_fw(SBI_PMU_FW_ACCESS_STORE); + rc = sbi_store_access_handler(regs, &trap); + msg = "store fault handler failed"; + break; default: /* If the trap came from S or U mode, redirect it there */ msg = "trap redirect failed"; diff --git a/lib/sbi/sbi_trap_ldst.c b/lib/sbi/sbi_trap_ldst.c index 1fb0ed6..7e4a007 100644 --- a/lib/sbi/sbi_trap_ldst.c +++ b/lib/sbi/sbi_trap_ldst.c @@ -16,11 +16,23 @@ #include #include -union reg_data { - u8 data_bytes[8]; - ulong data_ulong; - u64 data_u64; -}; +/** + * Load emulator callback: + * + * @return rlen=success, 0=success w/o regs modification, or negative error + */ +typedef int (*sbi_trap_ld_emulator)(int rlen, union sbi_ldst_data *out_val, + struct sbi_trap_regs *regs, + const struct sbi_trap_info *orig_trap); + +/** + * Store emulator callback: + * + * @return wlen=success, 0=success w/o regs modification, or negative error + */ +typedef int (*sbi_trap_st_emulator)(int wlen, union sbi_ldst_data in_val, + struct sbi_trap_regs *regs, + const struct sbi_trap_info *orig_trap); static ulong sbi_misaligned_tinst_fixup(ulong orig_tinst, ulong new_tinst, ulong addr_offset) @@ -34,15 +46,14 @@ static ulong sbi_misaligned_tinst_fixup(ulong orig_tinst, ulong new_tinst, return orig_tinst | (addr_offset << SH_RS1); } -int sbi_misaligned_load_handler(struct sbi_trap_regs *regs, - const struct sbi_trap_info *orig_trap) +static int sbi_trap_emulate_load(struct sbi_trap_regs *regs, + const struct sbi_trap_info *orig_trap, + sbi_trap_ld_emulator emu) { ulong insn, insn_len; - union reg_data val; + union sbi_ldst_data val = { 0 }; struct sbi_trap_info uptrap; - int i, fp = 0, shift = 0, len = 0; - - sbi_pmu_ctr_incr_fw(SBI_PMU_FW_MISALIGNED_LOAD); + int rc, fp = 0, shift = 0, len = 0; if (orig_trap->tinst & 0x1) { /* @@ -64,7 +75,12 @@ int sbi_misaligned_load_handler(struct sbi_trap_regs *regs, insn_len = INSN_LEN(insn); } - if ((insn & INSN_MASK_LW) == INSN_MATCH_LW) { + if ((insn & INSN_MASK_LB) == INSN_MATCH_LB) { + len = 1; + shift = 8 * (sizeof(ulong) - len); + } else if ((insn & INSN_MASK_LBU) == INSN_MATCH_LBU) { + len = 1; + } else if ((insn & INSN_MASK_LW) == INSN_MATCH_LW) { len = 4; shift = 8 * (sizeof(ulong) - len); #if __riscv_xlen == 64 @@ -127,17 +143,10 @@ int sbi_misaligned_load_handler(struct sbi_trap_regs *regs, return sbi_trap_redirect(regs, orig_trap); } - val.data_u64 = 0; - for (i = 0; i < len; i++) { - val.data_bytes[i] = - sbi_load_u8((void *)(orig_trap->tval + i), &uptrap); - if (uptrap.cause) { - uptrap.epc = regs->mepc; - uptrap.tinst = sbi_misaligned_tinst_fixup( - orig_trap->tinst, uptrap.tinst, i); - return sbi_trap_redirect(regs, &uptrap); - } - } + rc = emu(len, &val, regs, orig_trap); + + if (rc <= 0) + return rc; if (!fp) SET_RD(insn, regs, ((long)(val.data_ulong << shift)) >> shift); @@ -153,15 +162,14 @@ int sbi_misaligned_load_handler(struct sbi_trap_regs *regs, return 0; } -int sbi_misaligned_store_handler(struct sbi_trap_regs *regs, - const struct sbi_trap_info *orig_trap) +static int sbi_trap_emulate_store(struct sbi_trap_regs *regs, + const struct sbi_trap_info *orig_trap, + sbi_trap_st_emulator emu) { ulong insn, insn_len; - union reg_data val; + union sbi_ldst_data val; struct sbi_trap_info uptrap; - int i, len = 0; - - sbi_pmu_ctr_incr_fw(SBI_PMU_FW_MISALIGNED_STORE); + int rc, len = 0; if (orig_trap->tinst & 0x1) { /* @@ -185,7 +193,9 @@ int sbi_misaligned_store_handler(struct sbi_trap_regs *regs, val.data_ulong = GET_RS2(insn, regs); - if ((insn & INSN_MASK_SW) == INSN_MATCH_SW) { + if ((insn & INSN_MASK_SB) == INSN_MATCH_SB) { + len = 1; + } else if ((insn & INSN_MASK_SW) == INSN_MATCH_SW) { len = 4; #if __riscv_xlen == 64 } else if ((insn & INSN_MASK_SD) == INSN_MATCH_SD) { @@ -235,18 +245,78 @@ int sbi_misaligned_store_handler(struct sbi_trap_regs *regs, return sbi_trap_redirect(regs, orig_trap); } - for (i = 0; i < len; i++) { - sbi_store_u8((void *)(orig_trap->tval + i), val.data_bytes[i], - &uptrap); - if (uptrap.cause) { - uptrap.epc = regs->mepc; - uptrap.tinst = sbi_misaligned_tinst_fixup( - orig_trap->tinst, uptrap.tinst, i); - return sbi_trap_redirect(regs, &uptrap); - } - } + rc = emu(len, val, regs, orig_trap); + + if (rc <= 0) + return rc; regs->mepc += insn_len; return 0; } + +static int sbi_misaligned_ld_emulator(int rlen, union sbi_ldst_data *out_val, + struct sbi_trap_regs *regs, + const struct sbi_trap_info *orig_trap) +{ + struct sbi_trap_info uptrap; + int i; + + for (i = 0; i < rlen; i++) { + out_val->data_bytes[i] = + sbi_load_u8((void *)(orig_trap->tval + i), &uptrap); + if (uptrap.cause) { + uptrap.epc = regs->mepc; + uptrap.tinst = sbi_misaligned_tinst_fixup( + orig_trap->tinst, uptrap.tinst, i); + return sbi_trap_redirect(regs, &uptrap); + } + } + return rlen; +} + +int sbi_misaligned_load_handler(struct sbi_trap_regs *regs, + const struct sbi_trap_info *orig_trap) +{ + return sbi_trap_emulate_load(regs, orig_trap, + sbi_misaligned_ld_emulator); +} + +static int sbi_misaligned_st_emulator(int wlen, union sbi_ldst_data in_val, + struct sbi_trap_regs *regs, + const struct sbi_trap_info *orig_trap) +{ + struct sbi_trap_info uptrap; + int i; + + for (i = 0; i < wlen; i++) { + sbi_store_u8((void *)(orig_trap->tval + i), + in_val.data_bytes[i], &uptrap); + if (uptrap.cause) { + uptrap.epc = regs->mepc; + uptrap.tinst = sbi_misaligned_tinst_fixup( + orig_trap->tinst, uptrap.tinst, i); + return sbi_trap_redirect(regs, &uptrap); + } + } + return wlen; +} + +int sbi_misaligned_store_handler(struct sbi_trap_regs *regs, + const struct sbi_trap_info *orig_trap) +{ + return sbi_trap_emulate_store(regs, orig_trap, + sbi_misaligned_st_emulator); +} + +int sbi_load_access_handler(struct sbi_trap_regs *regs, + const struct sbi_trap_info *orig_trap) +{ + return sbi_trap_redirect(regs, orig_trap); +} + +int sbi_store_access_handler(struct sbi_trap_regs *regs, + const struct sbi_trap_info *orig_trap) +{ + return sbi_trap_redirect(regs, orig_trap); +}