From patchwork Thu Feb 9 06:23:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deepak Gupta X-Patchwork-Id: 13134028 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D2B82C05027 for ; Thu, 9 Feb 2023 06:25:41 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pQ0Lw-0000sm-5c; Thu, 09 Feb 2023 01:24:16 -0500 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 1pQ0Lu-0000s9-3c for qemu-devel@nongnu.org; Thu, 09 Feb 2023 01:24:14 -0500 Received: from mail-pg1-x530.google.com ([2607:f8b0:4864:20::530]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pQ0Ls-0007vq-5X for qemu-devel@nongnu.org; Thu, 09 Feb 2023 01:24:13 -0500 Received: by mail-pg1-x530.google.com with SMTP id r18so912727pgr.12 for ; Wed, 08 Feb 2023 22:24:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rivosinc-com.20210112.gappssmtp.com; s=20210112; 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=7CUYidC2PYJ4aSSo65h6OAHrCirLGNVfJL1zZ8fOzVI=; b=ZiI62LHWMC7KlKecQDIy1C3+ekw76I6k4j1WyE6ErWJ8Fv2Pl17SA34CvnfjBOFSj+ ZlQOKDdVgroh/eRt6cLdUoqdTvFaltt4V1FW7KtuTO+1GVhKS5JT7yOCZg0FBhYIFFt3 xrcVOiNARQGlSMsNoW6g+YhAf+//Gex2Imns6s2tMxrUB5Pv4hnnqcnwvexfZzjKkaB0 jYAznpXYkJFA/ydBmfRGx2IFa+TSXShJ8NJ/iWjWKKYOzG0xjQCNyBx2GzrB87WEX9pu dqYPhJHuSN+JDWPH3KPkG+tgPY7g1PDaMYvp6wbhfNJCvohomp39ZfrdFqEqHPeC/fb4 BCEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version: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=7CUYidC2PYJ4aSSo65h6OAHrCirLGNVfJL1zZ8fOzVI=; b=bXW/Optznz+KQKn9T75MP6BYHU8f7DAmz4zYvnm892t1VK02XwNQ8RGuLVxebBwZH0 4Zsn2NVHlpw0Q9ejQHqrkJx45UVLQJ8QRGYeGEq1jbnRDEpuh+7UEkyflNFI3q0LC6b6 GZyXCdJCkUK72Tm24XHdZJDr2+TbYiCzPlvj5WU6aYMg5HSo79kH2oUDDUcrqnyr8uX9 qIBymJHD3Oq85xd29pXH0oiPwOFP1ZFqY0atsXOP6DsRX6IN2fBZPqKZgcE7K8rWCLN2 xWIYETG4bvD49Pnbaiu9hIKzoEkQt11FlwHO+15xpMnXzWo7WES/nDI3tTAntDzufd69 8VYQ== X-Gm-Message-State: AO0yUKWezOjDlLYaqRzNNpNRdHXEadhels1QBJwwsDyiZYq3UO+Zhlhx jlMJ75XikkLSukmKVRKMUme9BQ== X-Google-Smtp-Source: AK7set9f5ri3wD2OEEyMPyCqVcZGtrOhgEtsPIj7qAs7gAeNw5XGMcIHaPzeIxfY7NaBz7abj+jTFw== X-Received: by 2002:a62:150a:0:b0:59c:8937:435e with SMTP id 10-20020a62150a000000b0059c8937435emr9399084pfv.28.1675923849835; Wed, 08 Feb 2023 22:24:09 -0800 (PST) Received: from debug.ba.rivosinc.com ([66.220.2.162]) by smtp.gmail.com with ESMTPSA id j14-20020aa7800e000000b00571cdbd0771sm521919pfi.102.2023.02.08.22.24.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Feb 2023 22:24:09 -0800 (PST) From: Deepak Gupta To: Palmer Dabbelt , Alistair Francis , Bin Meng Cc: Deepak Gupta , Kip Walker , qemu-riscv@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH v1 RFC Zisslpcfi 1/9] target/riscv: adding zimops and zisslpcfi extension to RISCV cpu config Date: Wed, 8 Feb 2023 22:23:56 -0800 Message-Id: <20230209062404.3582018-2-debug@rivosinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230209062404.3582018-1-debug@rivosinc.com> References: <20230209062404.3582018-1-debug@rivosinc.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::530; envelope-from=debug@rivosinc.com; helo=mail-pg1-x530.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Introducing riscv `zisslpcfi` extension to riscv target. `zisslpcfi` extension provides hardware assistance to riscv hart to enable control flow integrity (CFI) for software. `zisslpcfi` extension expects hart to implement `zimops`. `zimops` stands for "unprivileged integer maybe operations". `zimops` carve out certain reserved opcodes encodings from integer spec to "may be operations" encodings. `zimops` opcode encodings simply move 0 to rd. `zisslpcfi` claims some of the `zimops` encodings and use them for shadow stack management or indirect branch tracking. Any future extension can also claim `zimops` encodings. This patch also adds a dependency check for `zimops` to be enabled if `zisslpcfi` is enabled on the hart. Signed-off-by: Deepak Gupta Signed-off-by: Kip Walker --- target/riscv/cpu.c | 13 +++++++++++++ target/riscv/cpu.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index cc75ca7667..6b4e90eb91 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -110,6 +110,8 @@ static const struct isa_ext_data isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot), ISA_EXT_DATA_ENTRY(svpbmt, true, PRIV_VERSION_1_12_0, ext_svpbmt), ISA_EXT_DATA_ENTRY(xventanacondops, true, PRIV_VERSION_1_12_0, ext_XVentanaCondOps), + ISA_EXT_DATA_ENTRY(zimops, true, PRIV_VERSION_1_12_0, ext_zimops), + ISA_EXT_DATA_ENTRY(zisslpcfi, true, PRIV_VERSION_1_12_0, ext_cfi), }; static bool isa_ext_is_enabled(RISCVCPU *cpu, @@ -792,6 +794,11 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) return; } + if (cpu->cfg.ext_cfi && !cpu->cfg.ext_zimops) { + error_setg(errp, "Zisslpcfi extension requires Zimops extension"); + return; + } + /* Set the ISA extensions, checks should have happened above */ if (cpu->cfg.ext_zdinx || cpu->cfg.ext_zhinx || cpu->cfg.ext_zhinxmin) { @@ -1102,6 +1109,12 @@ static Property riscv_cpu_properties[] = { #ifndef CONFIG_USER_ONLY DEFINE_PROP_UINT64("resetvec", RISCVCPU, env.resetvec, DEFAULT_RSTVEC), #endif + /* + * Zisslpcfi CFI extension, Zisslpcfi implicitly means Zimops is + * implemented + */ + DEFINE_PROP_BOOL("zisslpcfi", RISCVCPU, cfg.ext_cfi, true), + DEFINE_PROP_BOOL("zimops", RISCVCPU, cfg.ext_zimops, true), DEFINE_PROP_BOOL("short-isa-string", RISCVCPU, cfg.short_isa_string, false), diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index f5609b62a2..9a923760b2 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -471,6 +471,8 @@ struct RISCVCPUConfig { uint32_t mvendorid; uint64_t marchid; uint64_t mimpid; + bool ext_zimops; + bool ext_cfi; /* Vendor-specific custom extensions */ bool ext_XVentanaCondOps; From patchwork Thu Feb 9 06:23:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deepak Gupta X-Patchwork-Id: 13134031 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6BB5FC61DA4 for ; Thu, 9 Feb 2023 06:26:31 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pQ0Lw-0000t6-Ja; Thu, 09 Feb 2023 01:24:16 -0500 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 1pQ0Lv-0000sS-JX for qemu-devel@nongnu.org; Thu, 09 Feb 2023 01:24:15 -0500 Received: from mail-pg1-x52a.google.com ([2607:f8b0:4864:20::52a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pQ0Lt-0007w9-30 for qemu-devel@nongnu.org; Thu, 09 Feb 2023 01:24:15 -0500 Received: by mail-pg1-x52a.google.com with SMTP id 78so927457pgb.8 for ; Wed, 08 Feb 2023 22:24:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rivosinc-com.20210112.gappssmtp.com; s=20210112; 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=qlPh49wlbxVVcOm0Ok3pVswLtoV2NRPuPBXAw/YmxdU=; b=soLrCqWLZow/sp1tWvVcJV8qtGoTHNC/x+PuDY0LOt1Y8+NE8ekfQKLWz35beos5tx /f5SrGKzoTQ4kUoJ7p7Ne2xmEpFBeWdWEZR8hFx3iR89UIfyascsqqdvMOyvZdqokd+G xCYyhHmX4ZJQtxlWOg+5z6ACjRlFPKKmB9uB5Pt7tbm3MW3UW3RBg6Ui5Gu3yDNPRaoz y7Jj6RKXHEWF49sQCQBj6ssOGtbfsNuVqVsoQB/kuj60/kgjOESKHFgN8+um7XadKlaK CDKUkcgWhsQgkr2NEeA0Ava+k3FfSN1pGIU8ULtvWgPJx5HXSJdZejazU7wyccrZd2dv 281g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version: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=qlPh49wlbxVVcOm0Ok3pVswLtoV2NRPuPBXAw/YmxdU=; b=J0lbIBekD/LEg3t5mGvOGVBSlT4g6hHawvJn00Yn+rvg7VnF8S647ygnELX0Sx3YZd JJPjuFSFX56qd89rMbbuxMHrsz7S0SB8zTXAot/ycUG6eWT48cGLHWF/BNqGW7SCpLEv CvAkGON372jPkdT4qn+5vyoyMDSi2oXiUO8ex/cd24H8Rd0qF7S7GaKj8alsYYbxnuTc IkLH9g22NOpsD6XAs3kYq9WovxrX4mKDDt3iXs56vXcyosarb/kMdAR4+CIXAwS31yL0 3X02WNpx+NnnDbIQA4OFQ7DZrbPoKEJo5bsBJY320exKnZAmyerySwq7szuLtQrHpWYd VIxA== X-Gm-Message-State: AO0yUKXhG8OvV5tsY/gr4RLDVNkuX8M5KxeRqz6QZv3znYcZSbsaiZQF x0gawtF3Wm6UPO3OfxjhetsyhhITcmqecpMh X-Google-Smtp-Source: AK7set8kNRYpwuG9p2IpokvYGz5GF6McvSaho78kGz/ueIsJp5bSeWX9pKnKE8gVPsrWZXBKa7UZJw== X-Received: by 2002:a62:520a:0:b0:5a8:44b1:7396 with SMTP id g10-20020a62520a000000b005a844b17396mr4400777pfb.15.1675923851727; Wed, 08 Feb 2023 22:24:11 -0800 (PST) Received: from debug.ba.rivosinc.com ([66.220.2.162]) by smtp.gmail.com with ESMTPSA id j14-20020aa7800e000000b00571cdbd0771sm521919pfi.102.2023.02.08.22.24.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Feb 2023 22:24:11 -0800 (PST) From: Deepak Gupta To: Palmer Dabbelt , Alistair Francis , Bin Meng Cc: Deepak Gupta , Kip Walker , qemu-riscv@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH v1 RFC Zisslpcfi 2/9] target/riscv: zisslpcfi CSR, bit positions and other definitions Date: Wed, 8 Feb 2023 22:23:57 -0800 Message-Id: <20230209062404.3582018-3-debug@rivosinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230209062404.3582018-1-debug@rivosinc.com> References: <20230209062404.3582018-1-debug@rivosinc.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::52a; envelope-from=debug@rivosinc.com; helo=mail-pg1-x52a.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org `zisslpcfi` extension adds two new CSRs. CSR_SSP and CSR_LPLR. - CSR_SSP: This CSR holds shadow stack pointer for current privilege mode CSR_SSP is accessible in all modes. Each mode must establish it's own CSR_SSP. - CSR_LPLR: This CSR holds label value set at the callsite by compiler. On call target label check instructions are emitted by compiler which check label value against value present in CSR_LPRL. Enabling of `zisslpcfi` is controlled via menvcfg (for S/HS/VS/U/VU) and henvcfg (for VS/VU) at bit position 60. Each mode has enable/disable bits for forward cfi. Backward cfi doesn't have separate enable/disable bits for S and M mode. User forward cfi and user backward cfi enable/disable bits are in mstatus/sstatus CSR. Supervisor forward cfi enable/disable bit are in menvcfg and henvcfg CSR. Machine mode forward cfi enable/disable bit is in mseccfg CSR. If forward cfi enabled, all indirect branches must land on a landing pad instruction (`lpcll`, introduced in later commits). CPU/hart tracks this internally using a landing pad tracker called `elp` short for `expecting landing pad`. An interrupt can occur between an indirect branch and target. If such an event occurs `elp` is saved away in mstatus/sstatus CSR Signed-off-by: Deepak Gupta Signed-off-by: Kip Walker --- target/riscv/cpu.h | 5 +++++ target/riscv/cpu_bits.h | 25 +++++++++++++++++++++++++ target/riscv/pmp.h | 3 ++- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 9a923760b2..18db61a06a 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -181,6 +181,11 @@ struct CPUArchState { uint32_t features; + /* CFI Extension user mode registers and state */ + uint32_t lplr; + target_ulong ssp; + cfi_elp elp; + #ifdef CONFIG_USER_ONLY uint32_t elf_flags; #endif diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 8b0d7e20ea..1663ba5775 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -39,6 +39,10 @@ /* Control and Status Registers */ +/* CFI CSRs */ +#define CSR_LPLR 0x006 +#define CSR_SSP 0x020 + /* User Trap Setup */ #define CSR_USTATUS 0x000 #define CSR_UIE 0x004 @@ -542,6 +546,10 @@ #define MSTATUS_TVM 0x00100000 /* since: priv-1.10 */ #define MSTATUS_TW 0x00200000 /* since: priv-1.10 */ #define MSTATUS_TSR 0x00400000 /* since: priv-1.10 */ +#define MSTATUS_UFCFIEN 0x00800000 /* Zisslpcfi-0.1 */ +#define MSTATUS_UBCFIEN 0x01000000 /* Zisslpcfi-0.1 */ +#define MSTATUS_SPELP 0x02000000 /* Zisslpcfi-0.1 */ +#define MSTATUS_MPELP 0x04000000 /* Zisslpcfi-0.1 */ #define MSTATUS_GVA 0x4000000000ULL #define MSTATUS_MPV 0x8000000000ULL @@ -572,12 +580,21 @@ typedef enum { #define SSTATUS_XS 0x00018000 #define SSTATUS_SUM 0x00040000 /* since: priv-1.10 */ #define SSTATUS_MXR 0x00080000 +#define SSTATUS_UFCFIEN MSTATUS_UFCFIEN /* Zisslpcfi-0.1 */ +#define SSTATUS_UBCFIEN MSTATUS_UBCFIEN /* Zisslpcfi-0.1 */ +#define SSTATUS_SPELP MSTATUS_SPELP /* Zisslpcfi-0.1 */ #define SSTATUS64_UXL 0x0000000300000000ULL #define SSTATUS32_SD 0x80000000 #define SSTATUS64_SD 0x8000000000000000ULL +#define CFISTATUS_M_MASK (MSTATUS_UFCFIEN | MSTATUS_UBCFIEN | \ + MSTATUS_MPELP | MSTATUS_SPELP) + +#define CFISTATUS_S_MASK (SSTATUS_UFCFIEN | SSTATUS_UBCFIEN | \ + SSTATUS_SPELP) + /* hstatus CSR bits */ #define HSTATUS_VSBE 0x00000020 #define HSTATUS_GVA 0x00000040 @@ -747,10 +764,14 @@ typedef enum RISCVException { #define MENVCFG_CBIE (3UL << 4) #define MENVCFG_CBCFE BIT(6) #define MENVCFG_CBZE BIT(7) +#define MENVCFG_SFCFIEN BIT(59) +#define MENVCFG_CFI BIT(60) #define MENVCFG_PBMTE (1ULL << 62) #define MENVCFG_STCE (1ULL << 63) /* For RV32 */ +#define MENVCFGH_SFCFIEN BIT(27) +#define MENVCFGH_CFI BIT(28) #define MENVCFGH_PBMTE BIT(30) #define MENVCFGH_STCE BIT(31) @@ -763,10 +784,14 @@ typedef enum RISCVException { #define HENVCFG_CBIE MENVCFG_CBIE #define HENVCFG_CBCFE MENVCFG_CBCFE #define HENVCFG_CBZE MENVCFG_CBZE +#define HENVCFG_SFCFIEN MENVCFG_SFCFIEN +#define HENVCFG_CFI MENVCFG_CFI #define HENVCFG_PBMTE MENVCFG_PBMTE #define HENVCFG_STCE MENVCFG_STCE /* For RV32 */ +#define HENVCFGH_SFCFIEN MENVCFGH_SFCFIEN +#define HENVCFGH_CFI MENVCFGH_CFI #define HENVCFGH_PBMTE MENVCFGH_PBMTE #define HENVCFGH_STCE MENVCFGH_STCE diff --git a/target/riscv/pmp.h b/target/riscv/pmp.h index da32c61c85..f5bfc4955b 100644 --- a/target/riscv/pmp.h +++ b/target/riscv/pmp.h @@ -43,7 +43,8 @@ typedef enum { MSECCFG_MMWP = 1 << 1, MSECCFG_RLB = 1 << 2, MSECCFG_USEED = 1 << 8, - MSECCFG_SSEED = 1 << 9 + MSECCFG_SSEED = 1 << 9, + MSECCFG_MFCFIEN = 1 << 10 } mseccfg_field_t; typedef struct { From patchwork Thu Feb 9 06:23:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deepak Gupta X-Patchwork-Id: 13134034 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 47A17C636D6 for ; Thu, 9 Feb 2023 06:27:58 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pQ0Ly-0000uC-Mm; Thu, 09 Feb 2023 01:24:18 -0500 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 1pQ0Lx-0000ta-B4 for qemu-devel@nongnu.org; Thu, 09 Feb 2023 01:24:17 -0500 Received: from mail-pf1-x42e.google.com ([2607:f8b0:4864:20::42e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pQ0Lv-0007wV-0k for qemu-devel@nongnu.org; Thu, 09 Feb 2023 01:24:17 -0500 Received: by mail-pf1-x42e.google.com with SMTP id v3so673304pfn.6 for ; Wed, 08 Feb 2023 22:24:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rivosinc-com.20210112.gappssmtp.com; s=20210112; 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=OjYZ/J+fuGuBPvfefUWdX1uo98embzdFhANJFdid3iE=; b=D1m2PIZdQFxaK4YL89yJbVRbRoXJlZb+A71KZo1rm32oTXp5QK0nC/VC2EBMp3b2UD b1dhdYZaOIIeGPghyxnCpYDw+mW7V7xTt6bnmnapOz8QkCVPgNFfJRkc/Z6TT5BnHx6Y sXBTtG7BTpY62q4BCPmKcqe6TYsIspxn7iGlC4oGGn3c2SUOXpmkIVM9eZSHcLvKyLec 7IcIU0mqoyTBBYctjitsPYlx/VwhUvyat40GnMkNjZWw/GqpFGrrf33bp8PbKPxggunE zGFEAnQyAwX5Ey3VZDZVPD02Cf5Ofa4FWlp7dFxioKyPZXroLbFKC3WA/DwQr2u/YLSi bdjQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version: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=OjYZ/J+fuGuBPvfefUWdX1uo98embzdFhANJFdid3iE=; b=MyUl17riOIYJCwxo+DUoAEAyhpvUTGxqA6rVR5uL2wApNg+q75DR6bbwVBJlQG0g/z Hj6/wzG77hDMugR9Fnh40SBFTou/55+mWFCdh6hfs7oNcReEsFQ4zlQrIm8/BTVQ3qQ/ I1BEVz7YmX0KE/oVUlId6Li+jIQtYtONIaXJGBYCLsSKUcqL3xJ2nNoT1miWVfLK8ihu OJsr98Kw5xzVQsMc2MC20X2dY+56I1hRkyLDjeRwK5cjl6FdDaTKA8/vyOMmJX08e1o9 Y6Zhc/U/fMKF+UhV4XpmtNNKvMllKN2ZL5mFMah03ICr0MgKPWzWuk2sirUGl/I+KmT6 48cQ== X-Gm-Message-State: AO0yUKVJhRKS5Z5tgXCW/F2kwkU5fcg2EJx7stFolrB3bc9xj+uvTRH8 BbLnbH7r7i0DQ0t+mJ07KeTDJA== X-Google-Smtp-Source: AK7set8M+6oK86xHcbT+lPZin/xaEJYr7J6xRHwKPQwVG32h7agvsvlmihBwYzB+2m1NmjoKsXloiQ== X-Received: by 2002:a62:1d44:0:b0:5a8:4c9d:6237 with SMTP id d65-20020a621d44000000b005a84c9d6237mr2937462pfd.21.1675923853549; Wed, 08 Feb 2023 22:24:13 -0800 (PST) Received: from debug.ba.rivosinc.com ([66.220.2.162]) by smtp.gmail.com with ESMTPSA id j14-20020aa7800e000000b00571cdbd0771sm521919pfi.102.2023.02.08.22.24.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Feb 2023 22:24:13 -0800 (PST) From: Deepak Gupta To: Palmer Dabbelt , Alistair Francis , Bin Meng Cc: Deepak Gupta , Kip Walker , qemu-riscv@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH v1 RFC Zisslpcfi 3/9] target/riscv: implements CSRs and new bits in existing CSRs in zisslpcfi Date: Wed, 8 Feb 2023 22:23:58 -0800 Message-Id: <20230209062404.3582018-4-debug@rivosinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230209062404.3582018-1-debug@rivosinc.com> References: <20230209062404.3582018-1-debug@rivosinc.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::42e; envelope-from=debug@rivosinc.com; helo=mail-pf1-x42e.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org CSR_SSP and CSR_LPLR are new CSR additions to cpu/hart. This patch allows access to these CSRs. A predicate routine handles access to these CSR as per specification. This patch also implments new bit definitions in menvcfg/henvcfg/mstatus/ sstatus CSRs to master enabled cfi and enable forward cfi in S and M mode. mstatus CSR holds forward and backward cfi enabling for U mode. There is no enabling bit for backward cfi in S and M mode. It is always enabled if extension is implemented by CPU. Signed-off-by: Deepak Gupta Signed-off-by: Kip Walker --- target/riscv/csr.c | 137 ++++++++++++++++++++++++++++++++++++++++++++- target/riscv/pmp.c | 9 +++ 2 files changed, 145 insertions(+), 1 deletion(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 0db2c233e5..24e208ebed 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -163,6 +163,50 @@ static RISCVException ctr32(CPURISCVState *env, int csrno) return ctr(env, csrno); } +static RISCVException cfi(CPURISCVState *env, int csrno) +{ + /* no cfi extension */ + if (!env_archcpu(env)->cfg.ext_cfi) { + return RISCV_EXCP_ILLEGAL_INST; + } + /* + * CONFIG_USER_MODE always allow access for now. Better for user mode only + * functionality + */ +#if !defined(CONFIG_USER_ONLY) + /* current priv not M */ + if (env->priv != PRV_M) { + /* menvcfg says no CFI */ + if (!get_field(env->menvcfg, MENVCFG_CFI)) { + return RISCV_EXCP_ILLEGAL_INST; + } + + /* V = 1 and henvcfg says no CFI. raise virtual instr fault */ + if (riscv_cpu_virt_enabled(env) && + !get_field(env->henvcfg, HENVCFG_CFI)) { + return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; + } + + /* + * LPLR and SSP are not accessible to U mode if disabled via status + * CSR + */ + if (env->priv == PRV_U) { + if (csrno == CSR_LPLR && + !get_field(env->mstatus, MSTATUS_UFCFIEN)) { + return RISCV_EXCP_ILLEGAL_INST; + } + if (csrno == CSR_SSP && + !get_field(env->mstatus, MSTATUS_UBCFIEN)) { + return RISCV_EXCP_ILLEGAL_INST; + } + } + } +#endif + + return RISCV_EXCP_NONE; +} + #if !defined(CONFIG_USER_ONLY) static RISCVException mctr(CPURISCVState *env, int csrno) { @@ -485,6 +529,32 @@ static RISCVException seed(CPURISCVState *env, int csrno) #endif } +/* Zisslpcfi CSR_LPLR read/write */ +static int read_lplr(CPURISCVState *env, int csrno, target_ulong *val) +{ + *val = env->lplr; + return RISCV_EXCP_NONE; +} + +static int write_lplr(CPURISCVState *env, int csrno, target_ulong val) +{ + env->lplr = val & (LPLR_UL | LPLR_ML | LPLR_LL); + return RISCV_EXCP_NONE; +} + +/* Zisslpcfi CSR_SSP read/write */ +static int read_ssp(CPURISCVState *env, int csrno, target_ulong *val) +{ + *val = env->ssp; + return RISCV_EXCP_NONE; +} + +static int write_ssp(CPURISCVState *env, int csrno, target_ulong val) +{ + env->ssp = val; + return RISCV_EXCP_NONE; +} + /* User Floating-Point CSRs */ static RISCVException read_fflags(CPURISCVState *env, int csrno, target_ulong *val) @@ -1227,7 +1297,7 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, /* flush tlb on mstatus fields that affect VM */ if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV | - MSTATUS_MPRV | MSTATUS_SUM)) { + MSTATUS_MPRV | MSTATUS_SUM | MSTATUS_UFCFIEN | MSTATUS_UBCFIEN)) { tlb_flush(env_cpu(env)); } mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE | @@ -1250,6 +1320,11 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, } } + /* If cfi extension is available, then apply cfi status mask */ + if (env_archcpu(env)->cfg.ext_cfi) { + mask |= CFISTATUS_M_MASK; + } + mstatus = (mstatus & ~mask) | (val & mask); if (xl > MXL_RV32) { @@ -1880,9 +1955,17 @@ static RISCVException write_menvcfg(CPURISCVState *env, int csrno, target_ulong val) { uint64_t mask = MENVCFG_FIOM | MENVCFG_CBIE | MENVCFG_CBCFE | MENVCFG_CBZE; + uint64_t cfi_mask = MENVCFG_CFI | MENVCFG_SFCFIEN; if (riscv_cpu_mxl(env) == MXL_RV64) { mask |= MENVCFG_PBMTE | MENVCFG_STCE; + if (env_archcpu(env)->cfg.ext_cfi) { + mask |= cfi_mask; + /* If any cfi enabling bit changes in menvcfg, flush tlb */ + if ((val ^ env->menvcfg) & cfi_mask) { + tlb_flush(env_cpu(env)); + } + } } env->menvcfg = (env->menvcfg & ~mask) | (val & mask); @@ -1900,8 +1983,17 @@ static RISCVException write_menvcfgh(CPURISCVState *env, int csrno, target_ulong val) { uint64_t mask = MENVCFG_PBMTE | MENVCFG_STCE; + uint64_t cfi_mask = MENVCFG_CFI | MENVCFG_SFCFIEN; uint64_t valh = (uint64_t)val << 32; + if (env_archcpu(env)->cfg.ext_cfi) { + mask |= cfi_mask; + /* If any cfi enabling bit changes in menvcfg, flush tlb */ + if ((val ^ env->menvcfg) & cfi_mask) { + tlb_flush(env_cpu(env)); + } + } + env->menvcfg = (env->menvcfg & ~mask) | (valh & mask); return RISCV_EXCP_NONE; @@ -1954,6 +2046,7 @@ static RISCVException write_henvcfg(CPURISCVState *env, int csrno, target_ulong val) { uint64_t mask = HENVCFG_FIOM | HENVCFG_CBIE | HENVCFG_CBCFE | HENVCFG_CBZE; + uint64_t cfi_mask = HENVCFG_CFI | HENVCFG_SFCFIEN; RISCVException ret; ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG); @@ -1963,6 +2056,18 @@ static RISCVException write_henvcfg(CPURISCVState *env, int csrno, if (riscv_cpu_mxl(env) == MXL_RV64) { mask |= HENVCFG_PBMTE | HENVCFG_STCE; + /* + * If cfi available and menvcfg.CFI = 1, then apply cfi mask for + * henvcfg + */ + if (env_archcpu(env)->cfg.ext_cfi && + get_field(env->menvcfg, MENVCFG_CFI)) { + mask |= cfi_mask; + /* If any cfi enabling bit changes in henvcfg, flush tlb */ + if ((val ^ env->henvcfg) & cfi_mask) { + tlb_flush(env_cpu(env)); + } + } } env->henvcfg = (env->henvcfg & ~mask) | (val & mask); @@ -1988,9 +2093,19 @@ static RISCVException write_henvcfgh(CPURISCVState *env, int csrno, target_ulong val) { uint64_t mask = HENVCFG_PBMTE | HENVCFG_STCE; + uint64_t cfi_mask = HENVCFG_CFI | HENVCFG_SFCFIEN; uint64_t valh = (uint64_t)val << 32; RISCVException ret; + if (env_archcpu(env)->cfg.ext_cfi && + get_field(env->menvcfg, MENVCFG_CFI)) { + mask |= cfi_mask; + /* If any cfi enabling bit changes in henvcfg, flush tlb */ + if ((val ^ env->henvcfg) & cfi_mask) { + tlb_flush(env_cpu(env)); + } + } + ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG); if (ret != RISCV_EXCP_NONE) { return ret; @@ -2270,6 +2385,11 @@ static RISCVException read_sstatus_i128(CPURISCVState *env, int csrno, mask |= SSTATUS64_UXL; } + if ((env_archcpu(env)->cfg.ext_cfi) && + get_field(env->menvcfg, MENVCFG_CFI)) { + mask |= CFISTATUS_S_MASK; + } + *val = int128_make128(sstatus, add_status_sd(MXL_RV128, sstatus)); return RISCV_EXCP_NONE; } @@ -2281,6 +2401,11 @@ static RISCVException read_sstatus(CPURISCVState *env, int csrno, if (env->xl != MXL_RV32 || env->debugger) { mask |= SSTATUS64_UXL; } + + if ((env_archcpu(env)->cfg.ext_cfi) && + get_field(env->menvcfg, MENVCFG_CFI)) { + mask |= CFISTATUS_S_MASK; + } /* TODO: Use SXL not MXL. */ *val = add_status_sd(riscv_cpu_mxl(env), env->mstatus & mask); return RISCV_EXCP_NONE; @@ -2296,6 +2421,12 @@ static RISCVException write_sstatus(CPURISCVState *env, int csrno, mask |= SSTATUS64_UXL; } } + + /* If cfi available and menvcfg.CFI = 1, apply CFI mask for sstatus */ + if ((env_archcpu(env)->cfg.ext_cfi) && + get_field(env->menvcfg, MENVCFG_CFI)) { + mask |= CFISTATUS_S_MASK; + } target_ulong newval = (env->mstatus & ~mask) | (val & mask); return write_mstatus(env, CSR_MSTATUS, newval); } @@ -4001,6 +4132,10 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { /* Crypto Extension */ [CSR_SEED] = { "seed", seed, NULL, NULL, rmw_seed }, + /* User mode CFI CSR */ + [CSR_LPLR] = { "lplr", cfi, read_lplr, write_lplr }, + [CSR_SSP] = { "ssp", cfi, read_ssp, write_ssp }, + #if !defined(CONFIG_USER_ONLY) /* Machine Timers and Counters */ [CSR_MCYCLE] = { "mcycle", any, read_hpmcounter, diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c index d1126a6066..89745d46cd 100644 --- a/target/riscv/pmp.c +++ b/target/riscv/pmp.c @@ -579,6 +579,15 @@ void mseccfg_csr_write(CPURISCVState *env, target_ulong val) /* Sticky bits */ val |= (env->mseccfg & (MSECCFG_MMWP | MSECCFG_MML)); + /* M-mode forward cfi to be enabled if cfi extension is implemented */ + if (env_archcpu(env)->cfg.ext_cfi) { + val |= (val & MSECCFG_MFCFIEN); + /* If forward cfi in mseccfg is being toggled, flush tlb */ + if ((env->mseccfg ^ val) & MSECCFG_MFCFIEN) { + tlb_flush(env_cpu(env)); + } + } + env->mseccfg = val; } From patchwork Thu Feb 9 06:23:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deepak Gupta X-Patchwork-Id: 13134030 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 29BADC05027 for ; Thu, 9 Feb 2023 06:25:50 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pQ0M0-0000v3-Mx; Thu, 09 Feb 2023 01:24:20 -0500 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 1pQ0Lz-0000ug-En for qemu-devel@nongnu.org; Thu, 09 Feb 2023 01:24:19 -0500 Received: from mail-pf1-x435.google.com ([2607:f8b0:4864:20::435]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pQ0Lx-0007x1-Kn for qemu-devel@nongnu.org; Thu, 09 Feb 2023 01:24:19 -0500 Received: by mail-pf1-x435.google.com with SMTP id a5so658588pfv.10 for ; Wed, 08 Feb 2023 22:24:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rivosinc-com.20210112.gappssmtp.com; s=20210112; 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=slc2qEJKHDUPCqJbT+o4fG/GNXtlIN4HHpf/pKqJaTw=; b=6vhXlP9BP1PzczhlUyDT/OgkPtpmJzCqM6MrN31zX6E1qPKEDx7pfXjYohz+zhN5mz 6AMTj7l077D+2RNbrhC7EO2DiU+KtXYLwRNo+Sj5usbuKZAuweV9ugy+pAYP4o0SJcgs G3oEjtKxSGn0b7KAAHtlO7x5jEISt/9Lq1xAm1Yr2+yNJ0GrvHIw51Ul5NQXy4jYlO6C 6s5wrFURniSx2mohhRJ7sLiGYA1RkrWgxQFyvgZ2QsKRnKWrTfnaI4k5CKKwRnkwu1nN 5kq71mPh7VltiJN5ocQFa+U30cjjQr13QtKyDdVhTL70kE2OqZYV7bCXiLlYLqqxG4S/ EvpQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version: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=slc2qEJKHDUPCqJbT+o4fG/GNXtlIN4HHpf/pKqJaTw=; b=cvgXvFGQrNWCLkc+ETu9GnpsFV/XRKFWtFH4sPukNkNDvXJGlrLvgF/Zuhiq+ckSqx 1nxh27Gr7WklmlMQNYT/MyoI2aiGPPPpzhGzmeRKYtIu6v7Qf9wqEw/PyuD/5nLh8ew5 XtbbJpZUFunlIh1xgNyn9wqOoRpy1sY7uRvDmaVZUR3Khers9V6etavFiDhTJtUOR4GU CFGwC0O9barig9D8sSIgEKkQE7GyoKqMGKWtU+Df9shlMQ1a1ohfbeby5JjlqaQ9sKmM BJ/zYAKN1rRR3lTtIc7f0P8NiscNnfdr2+6h4k8fFzA/lvk/FQ/X2zPEgvy5/flzGXFK t2Nw== X-Gm-Message-State: AO0yUKWIzQzX7qojtQXHTqhLl0f6b69cgnzPA/JFlaEPTID7KILkC6VU OYV72/9i/gl6L4Ig/UFUbD2ktoHPuYYIHhpE X-Google-Smtp-Source: AK7set8PCojduiIoCfj0XC1QNwu1p0TsGXFJxs/bNWDcx/YtIzgBqwJVVy3w0llApiYpKH6J/sZMuA== X-Received: by 2002:a62:8493:0:b0:5a8:492f:c074 with SMTP id k141-20020a628493000000b005a8492fc074mr3869240pfd.29.1675923856265; Wed, 08 Feb 2023 22:24:16 -0800 (PST) Received: from debug.ba.rivosinc.com ([66.220.2.162]) by smtp.gmail.com with ESMTPSA id j14-20020aa7800e000000b00571cdbd0771sm521919pfi.102.2023.02.08.22.24.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Feb 2023 22:24:15 -0800 (PST) From: Deepak Gupta To: Palmer Dabbelt , Alistair Francis , Bin Meng Cc: Deepak Gupta , Kip Walker , qemu-riscv@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH v1 RFC Zisslpcfi 4/9] target/riscv: helper functions for forward and backward cfi Date: Wed, 8 Feb 2023 22:23:59 -0800 Message-Id: <20230209062404.3582018-5-debug@rivosinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230209062404.3582018-1-debug@rivosinc.com> References: <20230209062404.3582018-1-debug@rivosinc.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::435; envelope-from=debug@rivosinc.com; helo=mail-pf1-x435.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Implementation for forward cfi and backward cfi needs helper function to determine if currently fcfi and bcfi are enabled. Enable depends on privilege mode and settings in sstatus/menvcfg/henvcfg/mseccfg CSRs. Signed-off-by: Deepak Gupta Signed-off-by: Kip Walker --- target/riscv/cpu.h | 2 ++ target/riscv/cpu_helper.c | 51 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 18db61a06a..d14ea4f91d 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -568,6 +568,8 @@ bool riscv_cpu_virt_enabled(CPURISCVState *env); void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable); bool riscv_cpu_two_stage_lookup(int mmu_idx); int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch); +bool cpu_get_fcfien(CPURISCVState *env); +bool cpu_get_bcfien(CPURISCVState *env); hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); G_NORETURN void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, MMUAccessType access_type, int mmu_idx, diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 9a28816521..a397023840 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -30,6 +30,7 @@ #include "sysemu/cpu-timers.h" #include "cpu_bits.h" #include "debug.h" +#include "pmp.h" int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch) { @@ -40,6 +41,56 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch) #endif } +bool cpu_get_fcfien(CPURISCVState *env) +{ +#ifdef CONFIG_USER_ONLY + return false; +#else + /* no cfi extension, return false */ + if (!env_archcpu(env)->cfg.ext_cfi) { + return false; + } + + switch (env->priv) { + case PRV_U: + return (env->mstatus & MSTATUS_UFCFIEN) ? true : false; + case PRV_S: + return (env->menvcfg & MENVCFG_SFCFIEN) ? true : false; + case PRV_M: + return (env->mseccfg & MSECCFG_MFCFIEN) ? true : false; + default: + g_assert_not_reached(); + } +#endif +} + +bool cpu_get_bcfien(CPURISCVState *env) +{ +#ifdef CONFIG_USER_ONLY + return false; +#else + /* no cfi extension, return false */ + if (!env_archcpu(env)->cfg.ext_cfi) { + return false; + } + + switch (env->priv) { + case PRV_U: + return (env->mstatus & MSTATUS_UBCFIEN) ? true : false; + + /* + * no gating for back cfi in M/S mode. back cfi is always on for + * M/S mode + */ + case PRV_S: + case PRV_M: + return true; + default: + g_assert_not_reached(); + } +#endif +} + void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *pflags) { From patchwork Thu Feb 9 06:24:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deepak Gupta X-Patchwork-Id: 13134029 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3207CC61DA4 for ; Thu, 9 Feb 2023 06:25:43 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pQ0M3-0000vu-Bc; Thu, 09 Feb 2023 01:24:23 -0500 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 1pQ0M1-0000vc-IG for qemu-devel@nongnu.org; Thu, 09 Feb 2023 01:24:21 -0500 Received: from mail-pf1-x430.google.com ([2607:f8b0:4864:20::430]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pQ0Lz-0007xR-Ko for qemu-devel@nongnu.org; Thu, 09 Feb 2023 01:24:21 -0500 Received: by mail-pf1-x430.google.com with SMTP id o75so652493pfg.12 for ; Wed, 08 Feb 2023 22:24:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rivosinc-com.20210112.gappssmtp.com; s=20210112; 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=MgwkEef7vxsb/V1HXgcHLlMSEMyA02TSLlxvE3Cow40=; b=TAzYRBy9c1J42h7yIEL90qCBrFU8nQShxiiBHhZsyawDqRrel7tvHqYcD1TqC4+h7u /GmaUlmDbBFXUQq8csI3/IZuSy+dMgZ9CBMIoBpOBcnmWt5OVUsFFKcaCtGdEmA4E6My Z0bE/tgy86QedUce0ofoTvqHYFFmHRYRiXKtDa/RV3MRQQ7apdrItnKvJOfL4LrNh8MC Rs7Rppyw3QcL3HQTo1U3xgVD4iqxkrOBHdUyv8D8fu1AaSC4cgQhaXeSMuMg9t+lmwHF MxDyzeXHTc/Cp0xJVE0jssgQJQyr742iPEO2FJR5BfOkwQiaIeSpFzLChtGjyau/PhFJ qeZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version: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=MgwkEef7vxsb/V1HXgcHLlMSEMyA02TSLlxvE3Cow40=; b=hS3cRbjYISs9Yv7wo+HhUud1/Joy2bZwigwRmTnPe2RLPfhjly1TPYu7DLgAS/l9YX rMfu4fPxodCeDtfrppQbWJkglLwdJpVETVKEp5Zr+FOMHNbOkZobh+WBiJAW6DmN5Y0h n5m3Jj/Vcb7E3eGlvx9ndIwXqi/6GQd5fpXcAUzHO+sHPfdNYwqQRLx1I/K3kSUp3Wa2 OU2IpgR98RfWwcv/CoNtQCKJwgzmcw+JKxs5VqiE39oa7bPLcbmN/EOjGMyhD263KDyU dAeB9GydJoOWpnbZjWoYa/4OjS43QzP/P9sgnWCN2580BLLCezxx9aExaznUl4L+mOtE J+Yw== X-Gm-Message-State: AO0yUKVua6NfpWJ/gvui6V1tlodY7w1ZLQgE6hPuhiNYHHziXZChPJ3d YAxezy3KmRPgDAlLF0JHmFWtOg== X-Google-Smtp-Source: AK7set/kfSscXUqLk72DMNJ5tN6W0nYpof+hQ6/dyWYuxntBCi+m2MM5vFHb5xQ21Y1fURBkmkmtvw== X-Received: by 2002:a62:524d:0:b0:590:7678:27c9 with SMTP id g74-20020a62524d000000b00590767827c9mr9645061pfb.7.1675923858326; Wed, 08 Feb 2023 22:24:18 -0800 (PST) Received: from debug.ba.rivosinc.com ([66.220.2.162]) by smtp.gmail.com with ESMTPSA id j14-20020aa7800e000000b00571cdbd0771sm521919pfi.102.2023.02.08.22.24.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Feb 2023 22:24:17 -0800 (PST) From: Deepak Gupta To: Palmer Dabbelt , Alistair Francis , Bin Meng Cc: Deepak Gupta , Kip Walker , qemu-riscv@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH v1 RFC Zisslpcfi 5/9] target/riscv: state save and restore of zisslppcfi state Date: Wed, 8 Feb 2023 22:24:00 -0800 Message-Id: <20230209062404.3582018-6-debug@rivosinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230209062404.3582018-1-debug@rivosinc.com> References: <20230209062404.3582018-1-debug@rivosinc.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::430; envelope-from=debug@rivosinc.com; helo=mail-pf1-x430.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org zisslpcfi's forward cfi if enabled on a hart, enables tracking of indirect branches. CPU/hart internally keeps a state `elp` short for expecting landing pad instruction. This state goes into LP_EXPECTED on an indirect branch. But an interrupt/exception can occur before target instruction is executed. In such a case this state must be preserved so that it can be restored later. zisslpcfi saves elp state in `sstatus` CSR. This patch saves elp state in sstatus CSR on trap delivery while restores from sstatus CSR on trap return. Additionally state in sstatus CSR must have save and restore zisslpcfi state on exiting from hypervisor and entering into hypervisor. Signed-off-by: Deepak Gupta Signed-off-by: Kip Walker Reviewed-by: LIU Zhiwei --- target/riscv/cpu_bits.h | 5 +++++ target/riscv/cpu_helper.c | 26 ++++++++++++++++++++++++++ target/riscv/op_helper.c | 12 ++++++++++++ 3 files changed, 43 insertions(+) diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 1663ba5775..37100ec8f6 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -594,6 +594,11 @@ typedef enum { #define CFISTATUS_S_MASK (SSTATUS_UFCFIEN | SSTATUS_UBCFIEN | \ SSTATUS_SPELP) +/* enum for branch tracking state in cpu/hart */ +typedef enum { + NO_LP_EXPECTED = 0, + LP_EXPECTED = 1, +} cfi_elp; /* hstatus CSR bits */ #define HSTATUS_VSBE 0x00000020 diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index a397023840..fc188683c9 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -534,6 +534,16 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env) if (riscv_has_ext(env, RVF)) { mstatus_mask |= MSTATUS_FS; } + + /* + * If cfi extension available, menvcfg.CFI = 1 and henvcfg.CFI = 1, + * then apply CFI mask on mstatus + */ + if (env_archcpu(env)->cfg.ext_cfi && + get_field(env->menvcfg, MENVCFG_CFI) && + get_field(env->henvcfg, HENVCFG_CFI)) { + mstatus_mask |= CFISTATUS_S_MASK; + } bool current_virt = riscv_cpu_virt_enabled(env); g_assert(riscv_has_ext(env, RVH)); @@ -1723,6 +1733,10 @@ void riscv_cpu_do_interrupt(CPUState *cs) if (env->priv <= PRV_S && cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) { /* handle the trap in S-mode */ + /* save elp status */ + if (cpu_get_fcfien(env)) { + env->mstatus = set_field(env->mstatus, MSTATUS_SPELP, env->elp); + } if (riscv_has_ext(env, RVH)) { uint64_t hdeleg = async ? env->hideleg : env->hedeleg; @@ -1772,6 +1786,10 @@ void riscv_cpu_do_interrupt(CPUState *cs) riscv_cpu_set_mode(env, PRV_S); } else { /* handle the trap in M-mode */ + /* save elp status */ + if (cpu_get_fcfien(env)) { + env->mstatus = set_field(env->mstatus, MSTATUS_MPELP, env->elp); + } if (riscv_has_ext(env, RVH)) { if (riscv_cpu_virt_enabled(env)) { riscv_cpu_swap_hypervisor_regs(env); @@ -1803,6 +1821,14 @@ void riscv_cpu_do_interrupt(CPUState *cs) riscv_cpu_set_mode(env, PRV_M); } + /* + * Interrupt/exception/trap delivery is asynchronous event and as per + * Zisslpcfi spec CPU should clear up the ELP state. If cfi extension is + * available, clear ELP state. + */ + if (cpu->cfg.ext_cfi) { + env->elp = NO_LP_EXPECTED; + } /* NOTE: it is not necessary to yield load reservations here. It is only * necessary for an SC from "another hart" to cause a load reservation * to be yielded. Refer to the memory consistency model section of the diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 878bcb03b8..d15893aa82 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -176,6 +176,12 @@ target_ulong helper_sret(CPURISCVState *env) riscv_cpu_set_virt_enabled(env, prev_virt); } + /* If forward cfi enabled for target, restore elp status */ + if (cpu_get_fcfien(env)) { + env->elp = get_field(env->mstatus, MSTATUS_SPELP); + env->mstatus = set_field(env->mstatus, MSTATUS_SPELP, 0); + } + riscv_cpu_set_mode(env, prev_priv); return retpc; @@ -220,6 +226,12 @@ target_ulong helper_mret(CPURISCVState *env) riscv_cpu_set_virt_enabled(env, prev_virt); } + /* If forward cfi enabled for target, restore elp status */ + if (cpu_get_fcfien(env)) { + env->elp = get_field(env->mstatus, MSTATUS_MPELP); + env->mstatus = set_field(env->mstatus, MSTATUS_MPELP, 0); + } + return retpc; } From patchwork Thu Feb 9 06:24:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deepak Gupta X-Patchwork-Id: 13134033 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 0BB29C61DA4 for ; Thu, 9 Feb 2023 06:27:58 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pQ0M6-0000x9-3c; Thu, 09 Feb 2023 01:24:26 -0500 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 1pQ0M4-0000wZ-Nc for qemu-devel@nongnu.org; Thu, 09 Feb 2023 01:24:24 -0500 Received: from mail-pf1-x42a.google.com ([2607:f8b0:4864:20::42a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pQ0M2-0007xr-BX for qemu-devel@nongnu.org; Thu, 09 Feb 2023 01:24:24 -0500 Received: by mail-pf1-x42a.google.com with SMTP id r17so663792pff.9 for ; Wed, 08 Feb 2023 22:24:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rivosinc-com.20210112.gappssmtp.com; s=20210112; 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=jRqJiEOrxr+Lg5i/nVzezfWn+WGoCCcHshuxculEll8=; b=cP2N5c3xoSFf8jJxN4Vu9hsVvGEegahPN+9wAkh7gAh5O/p0CJA5XgEd2BbAasmNjF 4dgsjxUGi3ZqzM9B1IaefC2xLRfYO3gJW7ZwMQUMy3EGyJGXopUDzdC1a3u/lqARF47y zmixsJCOdfzE/2+Rqma3pMr02UaPvn1zbDa5ZFd/dUDehFTBEJw2uHTAsqFq0QZrZbOg ub7Oqi2dUVWUYPXzs/XIwURrsHO1JSQIusN+A/NYwH4Q9t0I1fUXmW5d7Fzmo1Xf24L8 bOnaFLn09s6c/dnPDn6DzLUdt8rgy3t0mh5b1SmNJ2E8gykTW9UT9Vtsy23A5Mb18NLL 73TA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version: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=jRqJiEOrxr+Lg5i/nVzezfWn+WGoCCcHshuxculEll8=; b=CwVpKhjKr43kVwmUmDb9WT+Y2814wZJWGnmc1LyYylw9LL6qBIRVD8zKn3pbsEVZbi 3wNs4bD3+TTwaWcHSBYHLdsy+xR8FvOw6usXHFX8Aa0k56ijwlmr51ZYQHgP39knNq+Z 0yMz3Qh17bY+/xM57Mo/N5zF8nwb9rU0H40kZgSQq9jtN2C96/O7h1LJsW+6pOIORL5r O6hfu/rBC0CSa6XpY8Rn2ONZ7CTo5YyXduUgaoVxfqBPT4ugShrhAkv0fmjiFFRJFKpS 7Yq8NJzyFdhLCPnM8Vfe/msNHPcQMEUIVJgUjeMS98AQnGM4UKCtNZDHZKvRo2cygyRJ JmWw== X-Gm-Message-State: AO0yUKVllzf0s1FOzI4XAWliJnvzm2WdaX+YB6b/0hhTzFRLqYqoxAKq UL9eC4I6GhzgjgpdGsla4WVY6w== X-Google-Smtp-Source: AK7set8Qgt/E1nnf1poSgtwsc0U48dP9tdqaBBIuvPQAcC0m6MPirbc4Lp/iEl0h1nLo1/5BSk1GMw== X-Received: by 2002:aa7:9a1a:0:b0:592:5276:95df with SMTP id w26-20020aa79a1a000000b00592527695dfmr2577537pfj.2.1675923860649; Wed, 08 Feb 2023 22:24:20 -0800 (PST) Received: from debug.ba.rivosinc.com ([66.220.2.162]) by smtp.gmail.com with ESMTPSA id j14-20020aa7800e000000b00571cdbd0771sm521919pfi.102.2023.02.08.22.24.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Feb 2023 22:24:20 -0800 (PST) From: Deepak Gupta To: Palmer Dabbelt , Alistair Francis , Bin Meng Cc: Deepak Gupta , Kip Walker , qemu-riscv@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH v1 RFC Zisslpcfi 6/9] target/riscv: MMU changes for back cfi's shadow stack Date: Wed, 8 Feb 2023 22:24:01 -0800 Message-Id: <20230209062404.3582018-7-debug@rivosinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230209062404.3582018-1-debug@rivosinc.com> References: <20230209062404.3582018-1-debug@rivosinc.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::42a; envelope-from=debug@rivosinc.com; helo=mail-pf1-x42a.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org zisslpcfi protects returns(back cfi) using shadow stack. If compiled with enabled compiler, function prologs will have `sspush ra` instruction to push return address on shadow stack and function epilogs will have `sspop t0; sschckra` instruction sequences. `sspop t0` will pop the value from top of the shadow stack in t0. `sschckra` will compare `t0` and `x1` and if they don't match then hart will raise an illegal instruction exception. Shadow stack is read-only memory except stores can be performed via `sspush` and `ssamoswap` instructions. This requires new PTE encoding for shadow stack. zisslpcfi uses R=0, W=1, X=0 (an existing reserved encoding ) to encode a shadow stack. If backward cfi is not enabled for current mode, shadow stack PTE encodings remain reserved. Regular stores to shadow stack raise AMO/store access fault. Shadow stack loads/stores on regular memory raise load access/store access fault. This patch creates a new MMU TLB index for shadow stack and flushes TLB for shadow stack on privileges changes. This patch doesn't implement `Smepmp` related enforcement on shadow stack pmp entry. Reason being qemu doesn't have `Smepmp` implementation yet. `Smepmp` enforcement should come whenever it is implemented. Signed-off-by: Deepak Gupta Signed-off-by: Kip Walker --- target/riscv/cpu-param.h | 1 + target/riscv/cpu.c | 2 + target/riscv/cpu.h | 3 ++ target/riscv/cpu_helper.c | 107 +++++++++++++++++++++++++++++++------- 4 files changed, 94 insertions(+), 19 deletions(-) diff --git a/target/riscv/cpu-param.h b/target/riscv/cpu-param.h index ebaf26d26d..a1e379beb7 100644 --- a/target/riscv/cpu-param.h +++ b/target/riscv/cpu-param.h @@ -25,6 +25,7 @@ * - M mode 0b011 * - U mode HLV/HLVX/HSV 0b100 * - S mode HLV/HLVX/HSV 0b101 + * - BCFI shadow stack 0b110 * - M mode HLV/HLVX/HSV 0b111 */ #define NB_MMU_MODES 8 diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 6b4e90eb91..14cfb93288 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -584,6 +584,8 @@ static void riscv_cpu_reset_hold(Object *obj) } /* mmte is supposed to have pm.current hardwired to 1 */ env->mmte |= (PM_EXT_INITIAL | MMTE_M_PM_CURRENT); + /* Initialize ss_priv to current priv. */ + env->ss_priv = env->priv; #endif env->xl = riscv_cpu_mxl(env); riscv_cpu_update_mask(env); diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index d14ea4f91d..8803ea6426 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -379,6 +379,7 @@ struct CPUArchState { uint64_t sstateen[SMSTATEEN_MAX_COUNT]; target_ulong senvcfg; uint64_t henvcfg; + target_ulong ss_priv; #endif target_ulong cur_pmmask; target_ulong cur_pmbase; @@ -617,6 +618,8 @@ void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong); #define TB_FLAGS_PRIV_HYP_ACCESS_MASK (1 << 2) #define TB_FLAGS_MSTATUS_FS MSTATUS_FS #define TB_FLAGS_MSTATUS_VS MSTATUS_VS +/* TLB MMU index for shadow stack accesses */ +#define MMU_IDX_SS_ACCESS 6 #include "exec/cpu-all.h" diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index fc188683c9..63377abc2f 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -657,7 +657,8 @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable) bool riscv_cpu_two_stage_lookup(int mmu_idx) { - return mmu_idx & TB_FLAGS_PRIV_HYP_ACCESS_MASK; + return (mmu_idx & TB_FLAGS_PRIV_HYP_ACCESS_MASK) && + (mmu_idx != MMU_IDX_SS_ACCESS); } int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts) @@ -745,6 +746,38 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv) * preemptive context switch. As a result, do both. */ env->load_res = -1; + + if (cpu_get_bcfien(env) && (env->priv != env->ss_priv)) { + /* + * If backward CFI is enabled in the new privilege state, the + * shadow stack TLB needs to be flushed - unless the most recent + * use of the SS TLB was for the same privilege mode. + */ + tlb_flush_by_mmuidx(env_cpu(env), 1 << MMU_IDX_SS_ACCESS); + /* + * Ignoring env->virt here since currently every time it flips, + * all TLBs are flushed anyway. + */ + env->ss_priv = env->priv; + } +} + +typedef enum { + SSTACK_NO, /* Access is not for a shadow stack instruction */ + SSTACK_YES, /* Access is for a shadow stack instruction */ + SSTACK_DC /* Don't care about SS attribute in PMP */ +} SStackPmpMode; + +static bool legal_sstack_access(int access_type, bool sstack_inst, + bool sstack_attribute) +{ + /* + * Read/write/execution permissions are checked as usual. Shadow + * stack enforcement is just that (1) instruction type must match + * the attribute unless (2) a non-SS load to an SS region. + */ + return (sstack_inst == sstack_attribute) || + ((access_type == MMU_DATA_LOAD) && sstack_attribute); } /* @@ -764,7 +797,7 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv) static int get_physical_address_pmp(CPURISCVState *env, int *prot, target_ulong *tlb_size, hwaddr addr, int size, MMUAccessType access_type, - int mode) + int mode, SStackPmpMode sstack) { pmp_priv_t pmp_priv; int pmp_index = -1; @@ -812,13 +845,16 @@ static int get_physical_address_pmp(CPURISCVState *env, int *prot, * Second stage is used for hypervisor guest translation * @two_stage: Are we going to perform two stage translation * @is_debug: Is this access from a debugger or the monitor? + * @sstack: Is this access for a shadow stack? Passed by reference so + it can be forced to SSTACK_DC when the SS check is completed + based on a PTE - so the PMP SS attribute will be ignored. */ static int get_physical_address(CPURISCVState *env, hwaddr *physical, int *prot, target_ulong addr, target_ulong *fault_pte_addr, int access_type, int mmu_idx, bool first_stage, bool two_stage, - bool is_debug) + bool is_debug, SStackPmpMode *sstack) { /* NOTE: the env->pc value visible here will not be * correct, but the value visible to the exception handler @@ -830,6 +866,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical, hwaddr ppn; RISCVCPU *cpu = env_archcpu(env); int napot_bits = 0; + bool is_sstack = (sstack != NULL) && (*sstack == SSTACK_YES); target_ulong napot_mask; /* @@ -851,6 +888,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical, if (get_field(env->mstatus, MSTATUS_MPRV)) { mode = get_field(env->mstatus, MSTATUS_MPP); } + } else if (mmu_idx == MMU_IDX_SS_ACCESS) { + mode = env->priv; } if (first_stage == false) { @@ -966,7 +1005,7 @@ restart: int vbase_ret = get_physical_address(env, &vbase, &vbase_prot, base, NULL, MMU_DATA_LOAD, mmu_idx, false, true, - is_debug); + is_debug, NULL); if (vbase_ret != TRANSLATE_SUCCESS) { if (fault_pte_addr) { @@ -983,7 +1022,7 @@ restart: int pmp_prot; int pmp_ret = get_physical_address_pmp(env, &pmp_prot, NULL, pte_addr, sizeof(target_ulong), - MMU_DATA_LOAD, PRV_S); + MMU_DATA_LOAD, PRV_S, SSTACK_NO); if (pmp_ret != TRANSLATE_SUCCESS) { return TRANSLATE_PMP_FAIL; } @@ -1010,6 +1049,18 @@ restart: } } + /* + * When backward CFI is enabled, the R=0, W=1, X=0 reserved encoding + * is used to mark Shadow Stack (SS) pages. If back CFI enabled, allow + * normal loads on SS pages, regular stores raise store access fault + * and avoid hitting the reserved-encoding case. Only shadow stack + * stores are allowed on SS pages. Shadow stack loads and stores on + * regular memory (non-SS) raise load and store/AMO access fault. + * Second stage translations don't participate in Shadow Stack. + */ + bool sstack_page = (cpu_get_bcfien(env) && first_stage && + ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W)); + if (!(pte & PTE_V)) { /* Invalid PTE */ return TRANSLATE_FAIL; @@ -1021,7 +1072,7 @@ restart: return TRANSLATE_FAIL; } base = ppn << PGSHIFT; - } else if ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) { + } else if (((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) && !sstack_page) { /* Reserved leaf PTE flags: PTE_W */ return TRANSLATE_FAIL; } else if ((pte & (PTE_R | PTE_W | PTE_X)) == (PTE_W | PTE_X)) { @@ -1038,16 +1089,21 @@ restart: } else if (ppn & ((1ULL << ptshift) - 1)) { /* Misaligned PPN */ return TRANSLATE_FAIL; - } else if (access_type == MMU_DATA_LOAD && !((pte & PTE_R) || - ((pte & PTE_X) && mxr))) { + } else if (access_type == MMU_DATA_LOAD && !(((pte & PTE_R) || + sstack_page) || ((pte & PTE_X) && mxr))) { /* Read access check failed */ return TRANSLATE_FAIL; - } else if (access_type == MMU_DATA_STORE && !(pte & PTE_W)) { + } else if ((access_type == MMU_DATA_STORE && !is_sstack) && + !(pte & PTE_W)) { /* Write access check failed */ return TRANSLATE_FAIL; } else if (access_type == MMU_INST_FETCH && !(pte & PTE_X)) { /* Fetch access check failed */ return TRANSLATE_FAIL; + } else if (!legal_sstack_access(access_type, is_sstack, + sstack_page)) { + /* Illegal combo of instruction type and page attribute */ + return TRANSLATE_PMP_FAIL; } else { /* if necessary, set accessed and dirty bits. */ target_ulong updated_pte = pte | PTE_A | @@ -1107,18 +1163,27 @@ restart: ) << PGSHIFT) | (addr & ~TARGET_PAGE_MASK); /* set permissions on the TLB entry */ - if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) { + if ((pte & PTE_R) || ((pte & PTE_X) && mxr) || sstack_page) { *prot |= PAGE_READ; } if ((pte & PTE_X)) { *prot |= PAGE_EXEC; } - /* add write permission on stores or if the page is already dirty, - so that we TLB miss on later writes to update the dirty bit */ + /* + * add write permission on stores or if the page is already dirty, + * so that we TLB miss on later writes to update the dirty bit + */ if ((pte & PTE_W) && (access_type == MMU_DATA_STORE || (pte & PTE_D))) { *prot |= PAGE_WRITE; } + if (sstack) { + /* + * Tell the caller to skip the SS bit in the PMP since we + * resolved the attributes via the page table. + */ + *sstack = SSTACK_DC; + } return TRANSLATE_SUCCESS; } } @@ -1190,13 +1255,13 @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) int mmu_idx = cpu_mmu_index(&cpu->env, false); if (get_physical_address(env, &phys_addr, &prot, addr, NULL, 0, mmu_idx, - true, riscv_cpu_virt_enabled(env), true)) { + true, riscv_cpu_virt_enabled(env), true, NULL)) { return -1; } if (riscv_cpu_virt_enabled(env)) { if (get_physical_address(env, &phys_addr, &prot, phys_addr, NULL, - 0, mmu_idx, false, true, true)) { + 0, mmu_idx, false, true, true, NULL)) { return -1; } } @@ -1291,6 +1356,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, bool two_stage_indirect_error = false; int ret = TRANSLATE_FAIL; int mode = mmu_idx; + bool sstack = (mmu_idx == MMU_IDX_SS_ACCESS); + SStackPmpMode ssmode = sstack ? SSTACK_YES : SSTACK_NO; /* default TLB page size */ target_ulong tlb_size = TARGET_PAGE_SIZE; @@ -1318,7 +1385,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, /* Two stage lookup */ ret = get_physical_address(env, &pa, &prot, address, &env->guest_phys_fault_addr, access_type, - mmu_idx, true, true, false); + mmu_idx, true, true, false, &ssmode); /* * A G-stage exception may be triggered during two state lookup. @@ -1342,7 +1409,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, ret = get_physical_address(env, &pa, &prot2, im_address, NULL, access_type, mmu_idx, false, true, - false); + false, NULL); qemu_log_mask(CPU_LOG_MMU, "%s 2nd-stage address=%" VADDR_PRIx " ret %d physical " @@ -1353,7 +1420,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, if (ret == TRANSLATE_SUCCESS) { ret = get_physical_address_pmp(env, &prot_pmp, &tlb_size, pa, - size, access_type, mode); + size, access_type, mode, + SSTACK_NO); qemu_log_mask(CPU_LOG_MMU, "%s PMP address=" HWADDR_FMT_plx " ret %d prot" @@ -1377,7 +1445,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, } else { /* Single stage lookup */ ret = get_physical_address(env, &pa, &prot, address, NULL, - access_type, mmu_idx, true, false, false); + access_type, mmu_idx, true, false, + false, &ssmode); qemu_log_mask(CPU_LOG_MMU, "%s address=%" VADDR_PRIx " ret %d physical " @@ -1386,7 +1455,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, if (ret == TRANSLATE_SUCCESS) { ret = get_physical_address_pmp(env, &prot_pmp, &tlb_size, pa, - size, access_type, mode); + size, access_type, mode, ssmode); qemu_log_mask(CPU_LOG_MMU, "%s PMP address=" HWADDR_FMT_plx " ret %d prot" From patchwork Thu Feb 9 06:24:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deepak Gupta X-Patchwork-Id: 13134032 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B8194C05027 for ; Thu, 9 Feb 2023 06:27:57 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pQ0M7-0000xg-Nh; Thu, 09 Feb 2023 01:24:27 -0500 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 1pQ0M6-0000xD-5m for qemu-devel@nongnu.org; Thu, 09 Feb 2023 01:24:26 -0500 Received: from mail-pl1-x632.google.com ([2607:f8b0:4864:20::632]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pQ0M4-0007yC-8U for qemu-devel@nongnu.org; Thu, 09 Feb 2023 01:24:25 -0500 Received: by mail-pl1-x632.google.com with SMTP id iz19so440677plb.13 for ; Wed, 08 Feb 2023 22:24:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rivosinc-com.20210112.gappssmtp.com; s=20210112; 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=TofwhUrqur+nfz+vYUg5s7uS+g1axympVTaiH26ziSo=; b=WV0Yt6wdmrqWodN7vbRW+HPm9uh0fz0KSzT832srkfpLSdUHyuO0/+VTrgG6qUWMc3 2Pj5GsMMEOY7VawBl/1zXs6znAeGGSK9sHUZ9SH9DuMWXudXWVif85UvZyTb5LuMFgZa yZYs3EjNSOCT8BszvohuA3RDv/cCNjFThcgrol/Isx9j+jUxC5+/7gVAroAjTUoNmiwF KxXMOJuSxV+0TIJeiv3hTwTRMHBA8U3+bn5yZud2rkE1YIipoUUFMdtHwPqv0j2BAbO1 hmKLKwi7TES4kXEcIGqogMOij1yEUJY+vjJ+yV2zoOEmakrhWxOeTZxqrvVWGZFxjh1h D8xQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version: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=TofwhUrqur+nfz+vYUg5s7uS+g1axympVTaiH26ziSo=; b=vKi+Dmm4uMl43B1wMWItjAZmFdYDZCZ/bcUYXl3eqXorsiwaJ33HUCVOvgjBMB57g+ OAsknNUp+7OjSZ8/4fmZkrlayHsypcdCLxjTmhN/w6nxE04zxYCpyqilrzIilItnripr oi+4uomQjXMJSG7oRuC+fTfORyFEFMz7y715qt7qV+ZNZsttodd+NzWl6KNG++C2flBK On+PfDusktZStrNHj/qWQI6o7Qhiggqt0SqpbOCw1ZwoXNwR+bS5RzRohBYISX575b6p pt2vvTxgjPd92rYKTiN8+30+IRC1fTDVN0q37kxrTwVTQGGwU7S3HZSYXdO+KPxoxzj9 qpXg== X-Gm-Message-State: AO0yUKUei6sfzLqXnQZg3jBePd9kqAWU3X+bnTCbsp/UquxVZs5JHfh2 rbkeyhLDcagZu8cTeNsAS1EGow== X-Google-Smtp-Source: AK7set9C10grrd179fFqlTXzN324Ox6RGtoPfKNW1oTMeK49OXjNuGAwmVD0ykk8pMnx0wYWV1dp0w== X-Received: by 2002:a05:6a20:3d8d:b0:bc:f189:5064 with SMTP id s13-20020a056a203d8d00b000bcf1895064mr12998894pzi.52.1675923862920; Wed, 08 Feb 2023 22:24:22 -0800 (PST) Received: from debug.ba.rivosinc.com ([66.220.2.162]) by smtp.gmail.com with ESMTPSA id j14-20020aa7800e000000b00571cdbd0771sm521919pfi.102.2023.02.08.22.24.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Feb 2023 22:24:22 -0800 (PST) From: Deepak Gupta To: Palmer Dabbelt , Alistair Francis , Bin Meng Cc: Deepak Gupta , Kip Walker , qemu-riscv@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH v1 RFC Zisslpcfi 7/9] target/riscv: Tracking indirect branches (fcfi) using TCG Date: Wed, 8 Feb 2023 22:24:02 -0800 Message-Id: <20230209062404.3582018-8-debug@rivosinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230209062404.3582018-1-debug@rivosinc.com> References: <20230209062404.3582018-1-debug@rivosinc.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::632; envelope-from=debug@rivosinc.com; helo=mail-pl1-x632.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org zisslpcfi protects forward control flow (if enabled) by enforcing all indirect call and jmp must land on a landing pad instruction `lpcll` short for landing pad and check lower label value. If target of an indirect call or jmp is not `lpcll` then cpu/hart must raise an illegal instruction exception. This patch implements the mechanism using TCG. Target architecture branch instruction must define the end of a TB. Using this property, during translation of branch instruction, TB flag = FCFI_LP_EXPECTED can be set. Translation of target TB can check if FCFI_LP_EXPECTED flag is set and a flag (fcfi_lp_expected) can be set in DisasContext. If `lpcll` gets translated, fcfi_lp_expected flag in DisasContext can be cleared. Else it'll fault. This patch also also adds flag for forward and backward cfi in DisasContext. Signed-off-by: Deepak Gupta Signed-off-by: Kip Walker --- target/riscv/cpu.h | 3 +++ target/riscv/cpu_helper.c | 12 +++++++++ target/riscv/translate.c | 52 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 8803ea6426..98b272bcad 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -644,6 +644,9 @@ FIELD(TB_FLAGS, VMA, 25, 1) /* Native debug itrigger */ FIELD(TB_FLAGS, ITRIGGER, 26, 1) +/* Zisslpcfi needs a TB flag to track indirect branches */ +FIELD(TB_FLAGS, FCFI_LP_EXPECTED, 27, 1) + #ifdef TARGET_RISCV32 #define riscv_cpu_mxl(env) ((void)(env), MXL_RV32) #else diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 63377abc2f..d15918f534 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -129,6 +129,18 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1); } + if (cpu->cfg.ext_cfi) { + /* + * For Forward CFI, only the expectation of a lpcll at + * the start of the block is tracked (which can only happen + * when FCFI is enabled for the current processor mode). A jump + * or call at the end of the previous TB will have updated + * env->elp to indicate the expectation. + */ + flags = FIELD_DP32(flags, TB_FLAGS, FCFI_LP_EXPECTED, + env->elp != NO_LP_EXPECTED); + } + #ifdef CONFIG_USER_ONLY flags |= TB_FLAGS_MSTATUS_FS; flags |= TB_FLAGS_MSTATUS_VS; diff --git a/target/riscv/translate.c b/target/riscv/translate.c index df38db7553..7d43d20fc3 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -41,6 +41,7 @@ static TCGv load_val; /* globals for PM CSRs */ static TCGv pm_mask; static TCGv pm_base; +static TCGOp *cfi_lp_check; #include "exec/gen-icount.h" @@ -116,6 +117,10 @@ typedef struct DisasContext { bool itrigger; /* TCG of the current insn_start */ TCGOp *insn_start; + /* CFI extension */ + bool bcfi_enabled; + bool fcfi_enabled; + bool fcfi_lp_expected; } DisasContext; static inline bool has_ext(DisasContext *ctx, uint32_t ext) @@ -1166,11 +1171,44 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->pm_mask_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_MASK_ENABLED); ctx->pm_base_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_BASE_ENABLED); ctx->itrigger = FIELD_EX32(tb_flags, TB_FLAGS, ITRIGGER); + ctx->bcfi_enabled = cpu_get_bcfien(env); + ctx->fcfi_enabled = cpu_get_fcfien(env); + ctx->fcfi_lp_expected = FIELD_EX32(tb_flags, TB_FLAGS, FCFI_LP_EXPECTED); ctx->zero = tcg_constant_tl(0); } static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu) { + DisasContext *ctx = container_of(db, DisasContext, base); + + if (ctx->fcfi_lp_expected) { + /* + * Since we can't look ahead to confirm that the first + * instruction is a legal landing pad instruction, emit + * compare-and-branch sequence that will be fixed-up in + * riscv_tr_tb_stop() to either statically hit or skip an + * illegal instruction exception depending on whether the + * flag was lowered by translation of a CJLP or JLP as + * the first instruction in the block. + */ + TCGv_i32 immediate; + TCGLabel *l; + l = gen_new_label(); + immediate = tcg_temp_local_new_i32(); + tcg_gen_movi_i32(immediate, 0); + cfi_lp_check = tcg_last_op(); + tcg_gen_brcondi_i32(TCG_COND_EQ, immediate, 0, l); + tcg_temp_free_i32(immediate); + gen_exception_illegal(ctx); + gen_set_label(l); + /* + * Despite the use of gen_exception_illegal(), the rest of + * the TB needs to be generated. The TCG optimizer will + * clean things up depending on which path ends up being + * active. + */ + ctx->base.is_jmp = DISAS_NEXT; + } } static void riscv_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) @@ -1225,6 +1263,7 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) static void riscv_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) { DisasContext *ctx = container_of(dcbase, DisasContext, base); + CPURISCVState *env = cpu->env_ptr; switch (ctx->base.is_jmp) { case DISAS_TOO_MANY: @@ -1235,6 +1274,19 @@ static void riscv_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) default: g_assert_not_reached(); } + + if (ctx->fcfi_lp_expected) { + /* + * If the "lp expected" flag is still up, the block needs to take an + * illegal instruction exception. + */ + tcg_set_insn_param(cfi_lp_check, 1, tcgv_i32_arg(tcg_constant_i32(1))); + } else { + /* + * LP instruction requirement was met, clear up LP expected + */ + env->elp = NO_LP_EXPECTED; + } } static void riscv_tr_disas_log(const DisasContextBase *dcbase, From patchwork Thu Feb 9 06:24:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deepak Gupta X-Patchwork-Id: 13134027 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 33ED9C05027 for ; Thu, 9 Feb 2023 06:25:16 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pQ0MB-0000yc-Vl; Thu, 09 Feb 2023 01:24:32 -0500 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 1pQ0MB-0000yL-25 for qemu-devel@nongnu.org; Thu, 09 Feb 2023 01:24:31 -0500 Received: from mail-pg1-x52a.google.com ([2607:f8b0:4864:20::52a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pQ0M7-0007yx-LJ for qemu-devel@nongnu.org; Thu, 09 Feb 2023 01:24:30 -0500 Received: by mail-pg1-x52a.google.com with SMTP id 7so951082pga.1 for ; Wed, 08 Feb 2023 22:24:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rivosinc-com.20210112.gappssmtp.com; s=20210112; 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=9Jpx55XSl5ZxIppesj8mRIonMpJl9Kp5E0HS//vv/Ps=; b=CJVkXhOLgYgzGFyL5IfUUgpDwEeAmesCZ/oOPz7PpUuykh2iMfqubcl+9cZiCVjdHF X1HUy98yVFY4CYqb9KUo770P7H9ypT9Yy62ID2TAxYgkAg27iJWUWIxoFWfvFC0237Gr 39wXYWR1gs+0yHS3FHdJVYevz79LdUGcaX2bki35cJ0pqcXspCrHK/ZjJ/kA7NKDv/Pm KKipBGuxC5HmytODtGlqpUeCXLHRuIFbP5kx37cq1RppaX9opqRxdG7lQkEbIKfHWaVv Iq3bQjYGuqvi+hLQNmQYqA6opXaCy6z6iamuc+zMygPR7LKi3QLFaIb52nLU0bpKKLyz PiUg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version: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=9Jpx55XSl5ZxIppesj8mRIonMpJl9Kp5E0HS//vv/Ps=; b=pRIcyXdPr8NAon5ZmpZGdi2hcGqWV8zhSxYLBO/7+zSkpD5n5lEunaDR82Y7yS49Us nlrpLbhMV11N98PRi7X0y6ZOQnd2GZzxen7Ygj4yF4syo27HwPt7BME8Be5c77whzVzR 538FtdK0l4Dvr7za9A8rvFYh99scdpr5/1FyHUW2Qn372+4PII8F+bCvfMZTjJrcYd9R 0+e/2+/nAHHOtyjFbfBiHWaXUWX12XrnUcEOz0h4JTW7UHwVSt/VdfPqibunO+azSLO4 E61tHtnJG7obGHadQgRdE4nvJUzZjK8OZLlGEYME0yBwLxOa1hGmwDwj9PQ9Cmi+ZsZy nmmw== X-Gm-Message-State: AO0yUKUBgfwCr/788Tav12GP2JCPADPKSrzx89cE5XbROyFrygx3MaOU Z1P5hwDcwjY7NwXvKjKqw2Lv9Q== X-Google-Smtp-Source: AK7set/5zeNrv4L3yx/k4jfB7Xcf9MxbK2H2kZiXzgjS/+wKi39ZkBJcy0JpdeCsmtrISF/KgBo4gg== X-Received: by 2002:a62:1c58:0:b0:5a8:5101:d667 with SMTP id c85-20020a621c58000000b005a85101d667mr2141542pfc.22.1675923866000; Wed, 08 Feb 2023 22:24:26 -0800 (PST) Received: from debug.ba.rivosinc.com ([66.220.2.162]) by smtp.gmail.com with ESMTPSA id j14-20020aa7800e000000b00571cdbd0771sm521919pfi.102.2023.02.08.22.24.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Feb 2023 22:24:25 -0800 (PST) From: Deepak Gupta To: Palmer Dabbelt , Alistair Francis , Bin Meng Cc: Deepak Gupta , Kip Walker , qemu-riscv@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH v1 RFC Zisslpcfi 8/9] target/riscv: Instructions encodings, implementation and handlers Date: Wed, 8 Feb 2023 22:24:03 -0800 Message-Id: <20230209062404.3582018-9-debug@rivosinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230209062404.3582018-1-debug@rivosinc.com> References: <20230209062404.3582018-1-debug@rivosinc.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::52a; envelope-from=debug@rivosinc.com; helo=mail-pg1-x52a.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This patch implements instruction encodings for zisslpcfi instructions. Additionally this patch implements zimops encodings as well. If Zisslpcfi is supported by CPU but not enabled then all Zisslpcfi instructions default to Zimops instuction behavior i.e. mov 0 to rd. zisslpcfi defines following instructions. - Backward control flow - sspush x1/x5 : Decrement shadow stack pointer and pushes x1 or x5 on shadow stack. - sspop x1/x5 : Pops from shadow stack into x1 or x5. Increments shadow stack pointer. - ssprr : Reads current shadow stack pointer into a destination register. - sscheckra : Compares x1 with x5. Raises illegal instr fault if x1 != x5 - ssamoswap : Atomically swaps value on top of shadow stack - Forward control flow - lpsll, lpsml, lpsul : sets lower (9bit), mid (8bit) and upper (8bit) label values in CSR_ULLP respectively. - lpcll, lpcml, lpcul : checks lower (9bit), mid (8bit) and upper (8bit) label values with CSR_ULLP respectively. Check label instructions raise illegal instruction fault when labels mismatch. Signed-off-by: Deepak Gupta Signed-off-by: Kip Walker --- target/riscv/cpu_bits.h | 10 + target/riscv/helper.h | 7 + target/riscv/insn32.decode | 29 ++ target/riscv/insn_trans/trans_rvi.c.inc | 14 + target/riscv/insn_trans/trans_zimops.c.inc | 53 +++ target/riscv/insn_trans/trans_zisslpcfi.c.inc | 310 ++++++++++++++++++ target/riscv/op_helper.c | 67 ++++ target/riscv/translate.c | 2 + 8 files changed, 492 insertions(+) create mode 100644 target/riscv/insn_trans/trans_zimops.c.inc create mode 100644 target/riscv/insn_trans/trans_zisslpcfi.c.inc diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 37100ec8f6..b2d527c626 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -600,6 +600,16 @@ typedef enum { LP_EXPECTED = 1, } cfi_elp; +#define LPLR_UL (((1 << 8) - 1) << 17) +#define LPLR_ML (((1 << 8) - 1) << 9) +#define LPLR_LL ((1 << 9) - 1) + +typedef enum { + FCFI_LPLL = 0, + FCFI_ML = 1, + FCFI_UL = 2, +} cfi_label_inst; + /* hstatus CSR bits */ #define HSTATUS_VSBE 0x00000020 #define HSTATUS_GVA 0x00000040 diff --git a/target/riscv/helper.h b/target/riscv/helper.h index 227c7122ef..6484415612 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -97,6 +97,11 @@ DEF_HELPER_FLAGS_2(fcvt_h_l, TCG_CALL_NO_RWG, i64, env, tl) DEF_HELPER_FLAGS_2(fcvt_h_lu, TCG_CALL_NO_RWG, i64, env, tl) DEF_HELPER_FLAGS_2(fclass_h, TCG_CALL_NO_RWG_SE, tl, env, i64) +/* Forward CFI label checking */ +DEF_HELPER_2(cfi_jalr, void, env, int) +DEF_HELPER_3(cfi_check_landing_pad, void, env, int, int) +DEF_HELPER_3(cfi_set_landing_pad, void, env, int, int) + /* Special functions */ DEF_HELPER_2(csrr, tl, env, int) DEF_HELPER_3(csrw, void, env, int, tl) @@ -112,6 +117,8 @@ DEF_HELPER_1(tlb_flush, void, env) /* Native Debug */ DEF_HELPER_1(itrigger_match, void, env) #endif +/* helper for back cfi mismatch */ +DEF_HELPER_1(sschkra_mismatch, void, env) /* Hypervisor functions */ #ifndef CONFIG_USER_ONLY diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index b7e7613ea2..cd734f03ae 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -37,6 +37,8 @@ %imm_u 12:s20 !function=ex_shift_12 %imm_bs 30:2 !function=ex_shift_3 %imm_rnum 20:4 +%imm_cfi9 15:9 +%imm_cfi8 15:8 # Argument sets: &empty @@ -163,6 +165,33 @@ csrrwi ............ ..... 101 ..... 1110011 @csr csrrsi ............ ..... 110 ..... 1110011 @csr csrrci ............ ..... 111 ..... 1110011 @csr +# zimops (unpriv integer may be operations) instructions with system opcode +# These're superset of for cfi encodings. zimops_r and zimops_rr should be last +# entry in below overlapping patterns so that it acts as final sink for overlapping patterns. +# Any new encoding that can be used should be placed above mop.r and mop.rr + +# cfi instructions carved out of mop.r +{ + sspush 100000 0 11100 ..... 100 00000 1110011 %rs1 + sspop 100000 0 11100 00000 100 ..... 1110011 %rd + ssprr 100000 0 11101 00000 100 ..... 1110011 %rd + zimops_r 1-00-- 0 111-- ----- 100 ..... 1110011 %rd +} + +# cfi instructions carved out of mop.rr +{ + sschckra 100010 1 00001 00101 100 00000 1110011 + ssamoswap 100000 1 ..... ..... 100 ..... 1110011 @r + + lpsll 100000 1 0 ......... 100 00000 1110011 %imm_cfi9 + lpcll 100000 1 1 ......... 100 00000 1110011 %imm_cfi9 + lpsml 100001 1 0 0........ 100 00000 1110011 %imm_cfi8 + lpcml 100001 1 0 1........ 100 00000 1110011 %imm_cfi8 + lpsul 100010 1 1 0........ 100 00000 1110011 %imm_cfi8 + lpcul 100010 1 1 1........ 100 00000 1110011 %imm_cfi8 + zimops_rr 1-00-- 1 - --------- 100 ..... 1110011 %rd +} + # *** RV64I Base Instruction Set (in addition to RV32I) *** lwu ............ ..... 110 ..... 0000011 @i ld ............ ..... 011 ..... 0000011 @i diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index 5c69b88d1e..4a4f1ca778 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -66,6 +66,20 @@ static bool trans_jalr(DisasContext *ctx, arg_jalr *a) } gen_set_gpri(ctx, a->rd, ctx->pc_succ_insn); + + if (ctx->cfg_ptr->ext_cfi) { + /* + * Rely on a helper to check the forward CFI enable for the + * current process mode. The alternatives would be (1) include + * "fcfi enabled" in the cflags or (2) maintain a "fcfi + * currently enabled" in cpu_env and emit TCG code to access + * and test it. + */ + if (a->rd == xRA || a->rd == xT0 || (a->rs1 != xRA && a->rs1 != xT0)) { + gen_helper_cfi_jalr(cpu_env, tcg_constant_i32(LP_EXPECTED)); + } + } + lookup_and_goto_ptr(ctx); if (misaligned) { diff --git a/target/riscv/insn_trans/trans_zimops.c.inc b/target/riscv/insn_trans/trans_zimops.c.inc new file mode 100644 index 0000000000..51748637b9 --- /dev/null +++ b/target/riscv/insn_trans/trans_zimops.c.inc @@ -0,0 +1,53 @@ +/* + * RISC-V translation routines for the Control-Flow Integrity Extension + * + * Copyright (c) 2022-2023 Rivos Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + + static bool trans_zimops_r(DisasContext *ctx, arg_zimops_r * a) + { + /* zimops not implemented, raise illegal instruction & return true */ + if (!ctx->cfg_ptr->ext_zimops) { + gen_exception_illegal(ctx); + return true; + } + + /* + * zimops implemented, simply grab destination and mov zero. + * return true + */ + TCGv dest = dest_gpr(ctx, a->rd); + dest = tcg_const_tl(0); + gen_set_gpr(ctx, a->rd, dest); + return true; + } + + static bool trans_zimops_rr(DisasContext *ctx, arg_zimops_rr * a) + { + /* zimops not implemented, raise illegal instruction & return true */ + if (!ctx->cfg_ptr->ext_zimops) { + gen_exception_illegal(ctx); + return true; + } + + /* + * zimops implemented, simply grab destination and mov zero. + * return true + */ + TCGv dest = dest_gpr(ctx, a->rd); + dest = tcg_const_tl(0); + gen_set_gpr(ctx, a->rd, dest); + return true; + } diff --git a/target/riscv/insn_trans/trans_zisslpcfi.c.inc b/target/riscv/insn_trans/trans_zisslpcfi.c.inc new file mode 100644 index 0000000000..fe27bb73f6 --- /dev/null +++ b/target/riscv/insn_trans/trans_zisslpcfi.c.inc @@ -0,0 +1,310 @@ +/* + * RISC-V translation routines for the Control-Flow Integrity Extension + * + * Copyright (c) 2022-2023 Rivos Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +static MemOp mxl_memop(DisasContext *ctx) +{ + switch (get_xl(ctx)) { + case MXL_RV32: + return MO_TEUL; + + case MXL_RV64: + return MO_TEUQ; + + case MXL_RV128: + return MO_TEUO; + + default: + g_assert_not_reached(); + } +} + +static bool trans_sspop(DisasContext *ctx, arg_sspop *a) +{ + /* cfi only supported on 32bit and 64bit */ + if (get_xl(ctx) != MXL_RV32 && get_xl(ctx) != MXL_RV64) { + return false; + } + + /* back cfi not enabled, should go to trans_zimops. return false */ + if (!ctx->bcfi_enabled) { + return false; + } + + /* sspop can only load into x1 or x5. Everything else defaults to zimops */ + if (a->rd != 1 && a->rd != 5) { + return false; + } + + /* + * get data in TCGv using get_gpr + * get addr in TCGv using gen_helper_csrr on CSR_SSP + * use some tcg subtract arithmetic (subtract by XLEN) on addr + * perform ss store on computed address + */ + + TCGv addr = tcg_temp_new(); + int tmp = (get_xl(ctx) == MXL_RV64) ? 8 : 4; + TCGv_i32 ssp_csr = tcg_constant_i32(CSR_SSP); + TCGv data = get_gpr(ctx, a->rd, EXT_NONE); + gen_helper_csrr(addr, cpu_env, ssp_csr); + tcg_gen_qemu_ld_tl(data, addr, MMU_IDX_SS_ACCESS, + mxl_memop(ctx) | MO_ALIGN); + + /* + * add XLEN/bitwidth to addr, align to XLEN . How do i do that? Is below + * the right way + */ + tcg_gen_addi_tl(addr, addr, tmp); + gen_set_gpr(ctx, a->rd, data); + gen_helper_csrw(cpu_env, ssp_csr, addr); + + return true; +} + +static bool trans_sspush(DisasContext *ctx, arg_sspush *a) +{ + /* cfi only supported on 32bit and 64bit */ + if (get_xl(ctx) != MXL_RV32 && get_xl(ctx) != MXL_RV64) { + return false; + } + + /* back cfi not enabled, should go to trans_zimops. return false */ + if (!ctx->bcfi_enabled) { + return false; + } + + /* + * sspush can only push from x1 or x5. Everything else defaults to zimops + */ + if (a->rs1 != 1 && a->rs1 != 5) { + return false; + } + + /* + * get data in TCGv using get_gpr + * get addr in TCGv using gen_helper_csrr on CSR_SSP + * use some tcg subtract arithmetic (subtract by XLEN) on addr + * perform ss store on computed address + */ + + TCGv addr = tcg_temp_new(); + int tmp = (get_xl(ctx) == MXL_RV64) ? -8 : -4; + TCGv_i32 ssp_csr = tcg_constant_i32(CSR_SSP); + TCGv data = get_gpr(ctx, a->rs1, EXT_NONE); + gen_helper_csrr(addr, cpu_env, ssp_csr); + + /* + * subtract XLEN from addr, align to XLEN . How do i do that? Is below the + * right way + */ + tcg_gen_addi_tl(addr, addr, tmp); + tcg_gen_qemu_st_tl(data, addr, MMU_IDX_SS_ACCESS, + mxl_memop(ctx) | MO_ALIGN); + + gen_helper_csrw(cpu_env, ssp_csr, addr); + + return true; +} + +static bool trans_sschckra(DisasContext *ctx, arg_sschckra *a) +{ + /* cfi only supported on 32bit and 64bit */ + if (get_xl(ctx) != MXL_RV32 && get_xl(ctx) != MXL_RV64) { + return false; + } + + /* back cfi not enabled, should go to trans_zimops. return false */ + if (!ctx->bcfi_enabled) { + return false; + } + + gen_helper_sschkra_mismatch(cpu_env); + + return true; +} + +static bool trans_ssprr(DisasContext *ctx, arg_ssprr *a) +{ + /* cfi only supported on 32bit and 64bit */ + if (get_xl(ctx) != MXL_RV32 && get_xl(ctx) != MXL_RV64) { + return false; + } + + /* back cfi not enabled, should go to trans_zimops. return false */ + if (!ctx->bcfi_enabled) { + return false; + } + + TCGv dest = get_gpr(ctx, a->rd, EXT_NONE); + TCGv_i32 ssp_csr = tcg_constant_i32(CSR_SSP); + gen_helper_csrr(dest, cpu_env, ssp_csr); + gen_set_gpr(ctx, a->rd, dest); + + return true; +} + +static bool trans_ssamoswap(DisasContext *ctx, arg_ssamoswap *a) +{ + /* cfi only supported on 32bit and 64bit */ + if (get_xl(ctx) != MXL_RV32 && get_xl(ctx) != MXL_RV64) { + return false; + } + + /* back cfi not enabled, should go to trans_zimops. return false */ + if (!ctx->bcfi_enabled) { + return false; + } + + /* If cfi is enabled then, then rd must be != 0 */ + + if (a->rd == 0) { + return false; + } + + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_address(ctx, a->rs1, 0); + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); + MemOp mop = (MO_ALIGN | ((get_xl(ctx) == MXL_RV32) ? MO_TESL : MO_TESQ)); + + tcg_gen_atomic_xchg_tl(dest, src1, src2, MMU_IDX_SS_ACCESS, mop); + gen_set_gpr(ctx, a->rd, dest); + return true; +} + +static bool trans_lpcll(DisasContext *ctx, arg_lpcll *a) +{ + /* cfi only supported on 32bit and 64bit */ + if (get_xl(ctx) != MXL_RV32 && get_xl(ctx) != MXL_RV64) { + return false; + } + + /* + * If this is the first instruction of the TB, let the translator + * know the landing pad requirement was satisfied. No need to bother + * checking for CFI feature or enablement. + */ + + if (ctx->base.pc_next == ctx->base.pc_first) { + ctx->fcfi_lp_expected = false; + /* PC must be 4 byte aligned */ + if (ctx->fcfi_enabled && ((ctx->base.pc_next) & 0x3)) { + /* + * misaligned, according to spec we should raise illegal instead + * of mis-aligned + */ + gen_exception_illegal(ctx); + } + } + + /* forward cfi not enabled, should go to trans_zimops. return false */ + if (!ctx->fcfi_enabled) { + return false; + } + + gen_helper_cfi_check_landing_pad(cpu_env, tcg_constant_i32(a->imm_cfi9), + tcg_constant_i32(FCFI_LPLL)); + return true; +} + +static bool trans_lpcml(DisasContext *ctx, arg_lpcml *a) +{ + /* cfi only supported on 32bit and 64bit */ + if (get_xl(ctx) != MXL_RV32 && get_xl(ctx) != MXL_RV64) { + return false; + } + + /* forward cfi not enabled, should go to trans_zimops. return false */ + if (!ctx->fcfi_enabled) { + return false; + } + + gen_helper_cfi_check_landing_pad(cpu_env, tcg_constant_i32(a->imm_cfi8), + tcg_constant_i32(FCFI_ML)); + return true; +} + +static bool trans_lpcul(DisasContext *ctx, arg_lpcul *a) +{ + /* cfi only supported on 32bit and 64bit */ + if (get_xl(ctx) != MXL_RV32 && get_xl(ctx) != MXL_RV64) { + return false; + } + + /* forward cfi not enabled, should go to trans_zimops. return false */ + if (!ctx->fcfi_enabled) { + return false; + } + + gen_helper_cfi_check_landing_pad(cpu_env, tcg_constant_i32(a->imm_cfi8), + tcg_constant_i32(FCFI_UL)); + return true; +} + +static bool trans_lpsll(DisasContext *ctx, arg_lpsll *a) +{ + /* cfi only supported on 32bit and 64bit */ + if (get_xl(ctx) != MXL_RV32 && get_xl(ctx) != MXL_RV64) { + return false; + } + + /* forward cfi not enabled, should go to trans_zimops. return false */ + if (!ctx->fcfi_enabled) { + return false; + } + + gen_helper_cfi_set_landing_pad(cpu_env, tcg_constant_i32(a->imm_cfi9), + tcg_constant_i32(FCFI_LPLL)); + + return true; +} + +static bool trans_lpsml(DisasContext *ctx, arg_lpsml *a) +{ + /* cfi only supported on 32bit and 64bit */ + if (get_xl(ctx) != MXL_RV32 && get_xl(ctx) != MXL_RV64) { + return false; + } + + /* forward cfi not enabled, should go to trans_zimops. return false */ + if (!ctx->fcfi_enabled) { + return false; + } + + gen_helper_cfi_set_landing_pad(cpu_env, tcg_constant_i32(a->imm_cfi8), + tcg_constant_i32(FCFI_ML)); + + return true; +} + +static bool trans_lpsul(DisasContext *ctx, arg_lpsul *a) +{ + /* cfi only supported on 32bit and 64bit */ + if (get_xl(ctx) != MXL_RV32 && get_xl(ctx) != MXL_RV64) { + return false; + } + + /* forward cfi not enabled, should go to trans_zimops. return false */ + if (!ctx->fcfi_enabled) { + return false; + } + + gen_helper_cfi_set_landing_pad(cpu_env, tcg_constant_i32(a->imm_cfi8), + tcg_constant_i32(FCFI_UL)); + + return true; +} diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index d15893aa82..c14b76aabb 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -123,6 +123,73 @@ target_ulong helper_csrrw_i128(CPURISCVState *env, int csr, return int128_getlo(rv); } +void helper_sschkra_mismatch(CPURISCVState *env) +{ + if (env->gpr[xRA] != env->gpr[xT0]) { + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + } +} + +void helper_cfi_jalr(CPURISCVState *env, int elp) +{ + /* + * The translation routine doesn't know if forward CFI is enabled + * in the current processor mode or not. It's not worth burning a + * cflags bit to encode this, or tracking the current-mode-fcfi + * enable in a dedicated member of 'env'. Just come out to a helper + * for jump/call on a core with CFI. + */ + if (cpu_get_fcfien(env)) { + env->elp = elp; + } +} + +void helper_cfi_check_landing_pad(CPURISCVState *env, int lbl, int inst_type) +{ + if (cpu_get_fcfien(env)) { + switch (inst_type) { + case FCFI_LPLL: + /* + * Check for a lower label match. We already checked 4 byte + * alignment in tcg + */ + if (lbl != get_field(env->lplr, LPLR_LL)) { + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + } + env->elp = NO_LP_EXPECTED; + break; + case FCFI_ML: + if (lbl != get_field(env->lplr, LPLR_ML)) { + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + } + break; + case FCFI_UL: + if (lbl != get_field(env->lplr, LPLR_UL)) { + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + } + } + } +} + +void helper_cfi_set_landing_pad(CPURISCVState *env, int lbl, int inst_type) +{ + if (cpu_get_fcfien(env)) { + switch (inst_type) { + case FCFI_LPLL: + /* setting lower label always clears up entire field */ + env->lplr = 0; + env->lplr = set_field(env->lplr, LPLR_LL, lbl); + break; + case FCFI_ML: + env->lplr = set_field(env->lplr, LPLR_ML, lbl); + break; + case FCFI_UL: + env->lplr = set_field(env->lplr, LPLR_UL, lbl); + break; + } + } +} + #ifndef CONFIG_USER_ONLY target_ulong helper_sret(CPURISCVState *env) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 7d43d20fc3..b1a965d192 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -1071,6 +1071,8 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc) #include "insn_trans/trans_privileged.c.inc" #include "insn_trans/trans_svinval.c.inc" #include "insn_trans/trans_xventanacondops.c.inc" +#include "insn_trans/trans_zisslpcfi.c.inc" +#include "insn_trans/trans_zimops.c.inc" /* Include the auto-generated decoder for 16 bit insn */ #include "decode-insn16.c.inc" From patchwork Thu Feb 9 06:24:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deepak Gupta X-Patchwork-Id: 13134035 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id AC682C05027 for ; Thu, 9 Feb 2023 06:28:07 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pQ0ME-0000zw-QX; Thu, 09 Feb 2023 01:24:34 -0500 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 1pQ0MC-0000yd-F8 for qemu-devel@nongnu.org; Thu, 09 Feb 2023 01:24:32 -0500 Received: from mail-pf1-x435.google.com ([2607:f8b0:4864:20::435]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pQ0M9-0007x0-R5 for qemu-devel@nongnu.org; Thu, 09 Feb 2023 01:24:32 -0500 Received: by mail-pf1-x435.google.com with SMTP id y4so680730pfe.4 for ; Wed, 08 Feb 2023 22:24:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rivosinc-com.20210112.gappssmtp.com; s=20210112; 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=rfCWSS9jG8oH/r1HKi/uvLvwEOlj2iUYuI+0QRVQEBI=; b=JX9AUpxnix8Mmj0KQMXg0OEVqeFJNIpZhExeW9R8Uzf6i7/nIVe3C3v9Kv+nYiLz4K fAxmnpJjbqt2YWL2SmJOweUYxVNvYlmeizR82/1LHEaLslx7I/cQA5R6e2zavM/fr/V+ Lmoro6mVpJDBu14D/ICrtWEEfpmCzuIZLytUbPtv2S95/TlZMvFRRhoXmNll/xAfXhtM bcducoIsLGo1DQgo338SOaKfXXrzLX7hPZVbrTVHLGEsTCODA1V8msGs+ZhSFUMVlKQo MhK7euCfztQhLi6oxztcDnvE3Aafg8LNmpvSz1iStzs/MUaWeDtDhg/Js9sNUWYrS92O u/sA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version: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=rfCWSS9jG8oH/r1HKi/uvLvwEOlj2iUYuI+0QRVQEBI=; b=AYnJSClFI94h+yM+4qYxudySYAg+FhEPKk9+CaukcK6p6ouBWC6ovgkpWWyzmEDwep LqkfaZr0c+8i9QR7tfPfPl4BmuUGedl5lfVpY8xhSe3yo+oKek5plnWSxv3VPTqDl9Tw jiltYwguyHGHp8WQDp1IkynCrZpHMPrfAg34/ESsbFxZSqWaoRf3qMilJB/gWtPQBhDB 8AdkWFS7V36GPVAHt/7ZBX9aEMVaPyXv9YVs/qAQEUkm7quVm5EVJAInribNwX4qGfpF IZY6J+zgHKro7EiwLaFUiIgziQzDZeiiZpOFiKD7qC/jOI0/nybbHcSJk7a5D7pr0j4k 6pBA== X-Gm-Message-State: AO0yUKUrpuV/m9fLCQ+hLhSCegJLh0m99jUeV2H1iD782aP+BgGt74pe M/I0dohFO/Ybqtf6xiQhVzsHGQ== X-Google-Smtp-Source: AK7set839n6ikNwAbkrWdYqvM1B4a65Iw/g5D22S8UasZYGNb8RhDcMemUJpc8aG2TscgYPqCDipRw== X-Received: by 2002:a62:16c7:0:b0:5a8:5424:d139 with SMTP id 190-20020a6216c7000000b005a85424d139mr1194347pfw.20.1675923869059; Wed, 08 Feb 2023 22:24:29 -0800 (PST) Received: from debug.ba.rivosinc.com ([66.220.2.162]) by smtp.gmail.com with ESMTPSA id j14-20020aa7800e000000b00571cdbd0771sm521919pfi.102.2023.02.08.22.24.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Feb 2023 22:24:28 -0800 (PST) From: Deepak Gupta To: Palmer Dabbelt , Alistair Francis Cc: Deepak Gupta , Kip Walker , qemu-riscv@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH v1 RFC Zisslpcfi 9/9] target/riscv: diassembly support for zisslpcfi instructions Date: Wed, 8 Feb 2023 22:24:04 -0800 Message-Id: <20230209062404.3582018-10-debug@rivosinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230209062404.3582018-1-debug@rivosinc.com> References: <20230209062404.3582018-1-debug@rivosinc.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::435; envelope-from=debug@rivosinc.com; helo=mail-pf1-x435.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This patch adds support to disassemble Zisslpcfi instructions. Signed-off-by: Deepak Gupta Signed-off-by: Kip Walker --- disas/riscv.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 1 deletion(-) diff --git a/disas/riscv.c b/disas/riscv.c index d216b9c39b..d16ee617b0 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -163,6 +163,7 @@ typedef enum { rv_codec_v_i, rv_codec_vsetvli, rv_codec_vsetivli, + rv_codec_lp, } rv_codec; typedef enum { @@ -935,6 +936,19 @@ typedef enum { rv_op_vsetvli = 766, rv_op_vsetivli = 767, rv_op_vsetvl = 768, + rv_op_lpsll = 769, + rv_op_lpcll = 770, + rv_op_lpsml = 771, + rv_op_lpcml = 772, + rv_op_lpsul = 773, + rv_op_lpcul = 774, + rv_op_sspush = 775, + rv_op_sspop = 776, + rv_op_ssprr = 777, + rv_op_ssamoswap = 778, + rv_op_sschkra = 779, + rv_op_zimops_r = 780, + rv_op_zimops_rr = 781, } rv_op; /* structures */ @@ -1011,6 +1025,7 @@ static const char rv_vreg_name_sym[32][4] = { #define rv_fmt_pred_succ "O\tp,s" #define rv_fmt_rs1_rs2 "O\t1,2" #define rv_fmt_rd_imm "O\t0,i" +#define rv_fmt_imm "O\ti" #define rv_fmt_rd_offset "O\t0,o" #define rv_fmt_rd_rs1_rs2 "O\t0,1,2" #define rv_fmt_frd_rs1 "O\t3,1" @@ -2065,7 +2080,20 @@ const rv_opcode_data opcode_data[] = { { "vsext.vf8", rv_codec_v_r, rv_fmt_vd_vs2_vm, NULL, rv_op_vsext_vf8, rv_op_vsext_vf8, 0 }, { "vsetvli", rv_codec_vsetvli, rv_fmt_vsetvli, NULL, rv_op_vsetvli, rv_op_vsetvli, 0 }, { "vsetivli", rv_codec_vsetivli, rv_fmt_vsetivli, NULL, rv_op_vsetivli, rv_op_vsetivli, 0 }, - { "vsetvl", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, rv_op_vsetvl, rv_op_vsetvl, 0 } + { "vsetvl", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, rv_op_vsetvl, rv_op_vsetvl, 0 }, + { "lpsll", rv_codec_lp, rv_fmt_imm, NULL, 0, 0, 0 }, + { "lpcll", rv_codec_lp, rv_fmt_imm, NULL, 0, 0, 0 }, + { "lpsml", rv_codec_lp, rv_fmt_imm, NULL, 0, 0, 0 }, + { "lpcml", rv_codec_lp, rv_fmt_imm, NULL, 0, 0, 0 }, + { "lpsul", rv_codec_lp, rv_fmt_imm, NULL, 0, 0, 0 }, + { "lpcul", rv_codec_lp, rv_fmt_imm, NULL, 0, 0, 0 }, + { "sspush", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 }, + { "sspop", rv_codec_r, rv_fmt_rd, NULL, 0, 0, 0 }, + { "ssprr", rv_codec_r, rv_fmt_rd, NULL, 0, 0, 0 }, + { "ssamoswap", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "sschkra", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 }, + { "zimops_r", rv_codec_r, rv_fmt_rd, NULL, 0, 0, 0 }, + { "zimops_rr", rv_codec_r, rv_fmt_rd, NULL, 0, 0, 0 } }; /* CSR names */ @@ -2084,6 +2112,8 @@ static const char *csr_name(int csrno) case 0x000a: return "vxrm"; case 0x000f: return "vcsr"; case 0x0015: return "seed"; + case 0x0006: return "lplr"; + case 0x0020: return "ssp"; case 0x0040: return "uscratch"; case 0x0041: return "uepc"; case 0x0042: return "ucause"; @@ -3554,6 +3584,87 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 1: op = rv_op_csrrw; break; case 2: op = rv_op_csrrs; break; case 3: op = rv_op_csrrc; break; + case 4: + /* if matches mop_r mask */ + if ((((inst >> 15) & 0b10110011110000000) == + 0b10000001110000000)) { + if ((inst >> 25) == 0b1000000) { + switch ((inst >> 20) & 0b11) { + case 0: /* sspush and sspop */ + if (((inst >> 15) & 0b11111) && + !((inst >> 7) & 0b11111)) + op = rv_op_sspush; + if (!((inst >> 15) & 0b11111) && + ((inst >> 7) & 0b11111)) + op = rv_op_sspop; + break; + + case 1: /* ssprr */ + if (!((inst >> 15) & 0b11111) && + ((inst >> 7) & 0b11111)) + op = rv_op_ssprr; + break; + + default: + op = rv_op_zimops_r; + break; + } + } else { + op = rv_op_zimops_r; + } + } else if (((inst >> 15) & 0b10110010000000000) == + 0b10000010000000000) { /* if matches mop_rr mask */ + switch (inst >> 28) { + case 0b1000: + switch ((inst >> 7) & 0b11111) { + case 0b00000: + /* collect 5 bits */ + switch (((inst >> 23) & 0b11111)) { + case 23: + op = rv_op_lpcul; + break; + case 22: + op = rv_op_lpsul; + break; + case 13: + op = rv_op_lpcml; + break; + case 12: + op = rv_op_lpsml; + break; + case 6: + case 7: + op = rv_op_lpcll; + break; + case 4: + case 5: + op = rv_op_lpsll; + break; + default: + if (inst == + 0b10001010000100101100000001110011) { + op = rv_op_sschkra; + } else { + op = rv_op_zimops_rr; + } + break; + } + break; + default: + if ((inst >> 26) == 0b100000) { + op = rv_op_ssamoswap; + } else { + op = rv_op_zimops_rr; + } + break; + } + break; + default: + op = rv_op_zimops_rr; + break; + } + } + break; case 5: op = rv_op_csrrwi; break; case 6: op = rv_op_csrrsi; break; case 7: op = rv_op_csrrci; break; @@ -3883,6 +3994,17 @@ static uint32_t operand_vm(rv_inst inst) return (inst << 38) >> 63; } +static uint32_t operand_lpl(rv_inst inst) +{ + uint32_t label_width = 9; + + if ((inst >> 26) & 0b11) { + label_width = 8; + } + + return (inst >> 15) & ((1 << label_width) - 1); +} + /* decode operands */ static void decode_inst_operands(rv_decode *dec, rv_isa isa) @@ -4199,6 +4321,9 @@ static void decode_inst_operands(rv_decode *dec, rv_isa isa) dec->imm = operand_vimm(inst); dec->vzimm = operand_vzimm10(inst); break; + case rv_codec_lp: + dec->imm = operand_lpl(inst); + break; }; }