Received: by 2002:a05:6a10:af89:0:0:0:0 with SMTP id iu9csp1407834pxb; Fri, 21 Jan 2022 17:58:29 -0800 (PST) X-Google-Smtp-Source: ABdhPJzQeBVBy/h2LCCFjA1dUQEpwXX60Ii5fzUg9CzHScnxctrH7ZbN5+YySH9gqs3+GW4qC7S9 X-Received: by 2002:a17:902:e845:b0:14a:4ef1:dd0b with SMTP id t5-20020a170902e84500b0014a4ef1dd0bmr5930551plg.21.1642816709426; Fri, 21 Jan 2022 17:58:29 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1642816709; cv=none; d=google.com; s=arc-20160816; b=xTRjskQIoq8+lW6HcKkIRFvIdGX9G4e5eOzKBsndVvcpYd1FJaaXdNQ1RFtTjhULfK aciMNg87K1dLWwfrZJeSQEA/FWtQfGN10KaMzFAZPUUIHmJ1y9xL1qcrzXnKvmavDT7W Rrls+OMwSKFcsr7zPdSjLxnlc+v2pycjWH0TfeCIxTSAuL3dNaH+qa59rxGMfxxiOxBZ L2+CwTlkNvw78Q9Mj2JWKDtWrMT5ITBsY8uZd+QK8ZprSMVHvjS3YKHiCz7Mj3jV9M+d BN4vSJD+IvIpziIjxz90QkCKWdHrRQnxn41hRAIqgjeu3JGeQBL+CE1Bm6bzFNDGXLmc kGPg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=YTXEQ5fpq/JB35cb4n+YaDIobEI4g413oAIHLYyDAAE=; b=We4Dz+X4GG7XMiVzUZfzH/GVt10dk/3PBPFdI6fTxqg9P0mCvB5evBfUeRCYgskg0v bwAR3HOFPzU/x2p2pYMAAEHwZXsSOoQJSICxJ/nNUONf5CBa/i21duogD+2WDHky57a6 6oHpCaUXa7mFXu1qCZ9h3eUNdGMycR2ug7pWAE6zhR1VuUfAjThlThO2gP2zDkiH5y20 AwMhjQJcGQ1F9JW87MFqU2PND/4t6ZNaF9YMGZXsRBSeIlvuHE9foedd7/pKL9ttKIG9 pdP0tutIRq9O6oo3nS/rpIPIW23GgRC13rgcj5rLAW/MAXzjPg0MFDSZLAIW4zrLAUIz PwrQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id d184si7983300pgc.100.2022.01.21.17.58.17; Fri, 21 Jan 2022 17:58:29 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1378673AbiAUQkV (ORCPT + 99 others); Fri, 21 Jan 2022 11:40:21 -0500 Received: from gloria.sntech.de ([185.11.138.130]:36292 "EHLO gloria.sntech.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351481AbiAUQkS (ORCPT ); Fri, 21 Jan 2022 11:40:18 -0500 Received: from p508fcef5.dip0.t-ipconnect.de ([80.143.206.245] helo=phil.fritz.box) by gloria.sntech.de with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nAwuR-0008GA-95; Fri, 21 Jan 2022 17:37:07 +0100 From: Heiko Stuebner To: palmer@dabbelt.com, paul.walmsley@sifive.com, aou@eecs.berkeley.edu Cc: linux-riscv@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, robh+dt@kernel.org, wefu@redhat.com, liush@allwinnertech.com, guoren@kernel.org, atishp@atishpatra.org, anup@brainfault.org, drew@beagleboard.org, hch@lst.de, arnd@arndb.de, wens@csie.org, maxime@cerno.tech, dlustig@nvidia.com, gfavor@ventanamicro.com, andrea.mondelli@huawei.com, behrensj@mit.edu, xinhaoqu@huawei.com, huffman@cadence.com, mick@ics.forth.gr, allen.baum@esperantotech.com, jscheid@ventanamicro.com, rtrauben@gmail.com, samuel@sholland.org, cmuellner@linux.com, philipp.tomsich@vrull.eu, Heiko Stuebner , Palmer Dabbelt , Anup Patel , Atish Patra , Wei Wu Subject: [PATCH v5 12/14] riscv: add RISC-V Svpbmt extension supports Date: Fri, 21 Jan 2022 17:36:16 +0100 Message-Id: <20220121163618.351934-13-heiko@sntech.de> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220121163618.351934-1-heiko@sntech.de> References: <20220121163618.351934-1-heiko@sntech.de> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Wei Fu This patch follows the standard pure RISC-V Svpbmt extension in privilege spec to solve the non-coherent SOC dma synchronization issues. Here is the svpbmt PTE format: | 63 | 62-61 | 60-8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 N MT RSW D A G U X W R V ^ Of the Reserved bits [63:54] in a leaf PTE, the high bit is already allocated (as the N bit), so bits [62:61] are used as the MT (aka MemType) field. This field specifies one of three memory types that are close equivalents (or equivalent in effect) to the three main x86 and ARMv8 memory types - as shown in the following table. RISC-V Encoding & MemType RISC-V Description ---------- ------------------------------------------------ 00 - PMA Normal Cacheable, No change to implied PMA memory type 01 - NC Non-cacheable, idempotent, weakly-ordered Main Memory 10 - IO Non-cacheable, non-idempotent, strongly-ordered I/O memory 11 - Rsvd Reserved for future standard use The standard protection_map[] needn't be modified because the "PMA" type keeps the highest bits zero. The implementation is limited to arch/riscv/* as it uses an inline function and the alternatives mechanism to generate the _PAGE_MTMASK/IO/NOCACHE values for pgprot_noncached (& writecombine) in pgtable.h on both svpbmt and non-svpbmt-capable chips. Signed-off-by: Wei Fu Co-developed-by: Liu Shaohua Signed-off-by: Liu Shaohua Co-developed-by: Guo Ren Signed-off-by: Guo Ren [moved to use the alternatives mechanism] Co-developed-by: Heiko Stuebner Signed-off-by: Heiko Stuebner Cc: Palmer Dabbelt Cc: Christoph Hellwig Cc: Anup Patel Cc: Arnd Bergmann Cc: Atish Patra Cc: Drew Fustini Cc: Wei Fu Cc: Wei Wu Cc: Chen-Yu Tsai Cc: Maxime Ripard Cc: Daniel Lustig Cc: Greg Favor Cc: Andrea Mondelli Cc: Jonathan Behrens Cc: Xinhaoqu (Freddie) Cc: Bill Huffman Cc: Nick Kossifidis Cc: Allen Baum Cc: Josh Scheid Cc: Richard Trauben --- arch/riscv/include/asm/errata_list.h | 13 ++++- arch/riscv/include/asm/pgtable-32.h | 9 +++ arch/riscv/include/asm/pgtable-64.h | 47 ++++++++++++++++ arch/riscv/include/asm/pgtable-bits.h | 4 -- arch/riscv/include/asm/pgtable.h | 29 ++++++++-- arch/riscv/kernel/cpufeature.c | 79 +++++++++++++++++++++++++++ 6 files changed, 171 insertions(+), 10 deletions(-) diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h index 6b95bd9aee82..a4a9b0842922 100644 --- a/arch/riscv/include/asm/errata_list.h +++ b/arch/riscv/include/asm/errata_list.h @@ -14,7 +14,8 @@ #define ERRATA_SIFIVE_NUMBER 2 #endif -#define CPUFEATURE_NUMBER 0 +#define CPUFEATURE_SVPBMT 0 +#define CPUFEATURE_NUMBER 1 #ifdef __ASSEMBLY__ @@ -36,6 +37,16 @@ asm(ALTERNATIVE("sfence.vma %0", "sfence.vma", SIFIVE_VENDOR_ID, \ ERRATA_SIFIVE_CIP_1200, CONFIG_ERRATA_SIFIVE_CIP_1200) \ : : "r" (addr) : "memory") +/* + * _val is marked as "will be overwritten", so need to set it to 0 + * in the default case. + */ +#define ALT_SVPBMT_SHIFT 61 +#define ALT_SVPBMT(_val, prot) \ +asm(ALTERNATIVE("li %0, 0\t\nnop", "li %0, %1\t\nslli %0,%0,%2", 0, \ + CPUFEATURE_SVPBMT, CONFIG_64BIT) \ + : "=r"(_val) : "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT), "I"(ALT_SVPBMT_SHIFT)) + #endif /* __ASSEMBLY__ */ #endif diff --git a/arch/riscv/include/asm/pgtable-32.h b/arch/riscv/include/asm/pgtable-32.h index e266a4fe7f43..59ba1fbaf784 100644 --- a/arch/riscv/include/asm/pgtable-32.h +++ b/arch/riscv/include/asm/pgtable-32.h @@ -24,4 +24,13 @@ */ #define _PAGE_PFN_MASK GENMASK(31, 10) +#define _PAGE_NOCACHE 0 +#define _PAGE_IO 0 +#define _PAGE_MTMASK 0 + +/* Set of bits to preserve across pte_modify() */ +#define _PAGE_CHG_MASK (~(unsigned long)(_PAGE_PRESENT | _PAGE_READ | \ + _PAGE_WRITE | _PAGE_EXEC | \ + _PAGE_USER | _PAGE_GLOBAL)) + #endif /* _ASM_RISCV_PGTABLE_32_H */ diff --git a/arch/riscv/include/asm/pgtable-64.h b/arch/riscv/include/asm/pgtable-64.h index 706f0897437d..58b34ef74acb 100644 --- a/arch/riscv/include/asm/pgtable-64.h +++ b/arch/riscv/include/asm/pgtable-64.h @@ -8,6 +8,7 @@ #include #include +#include #define PGDIR_SHIFT 30 /* Size of region mapped by a page global directory */ @@ -36,6 +37,52 @@ typedef struct { */ #define _PAGE_PFN_MASK GENMASK(53, 10) +/* + * [62:61] Svpbmt Memory Type definitions: + * + * 00 - PMA Normal Cacheable, No change to implied PMA memory type + * 01 - NC Non-cacheable, idempotent, weakly-ordered Main Memory + * 10 - IO Non-cacheable, non-idempotent, strongly-ordered I/O memory + * 11 - Rsvd Reserved for future standard use + */ +#define _PAGE_NOCACHE_SVPBMT (1UL << 61) +#define _PAGE_IO_SVPBMT (1UL << 62) +#define _PAGE_MTMASK_SVPBMT (_PAGE_NOCACHE_SVPBMT | _PAGE_IO_SVPBMT) + +static inline u64 riscv_page_mtmask(void) +{ + u64 val; + + ALT_SVPBMT(val, _PAGE_MTMASK); + return val; +} + +static inline u64 riscv_page_nocache(void) +{ + u64 val; + + ALT_SVPBMT(val, _PAGE_NOCACHE); + return val; +} + +static inline u64 riscv_page_io(void) +{ + u64 val; + + ALT_SVPBMT(val, _PAGE_IO); + return val; +} + +#define _PAGE_NOCACHE riscv_page_nocache() +#define _PAGE_IO riscv_page_io() +#define _PAGE_MTMASK riscv_page_mtmask() + +/* Set of bits to preserve across pte_modify() */ +#define _PAGE_CHG_MASK (~(unsigned long)(_PAGE_PRESENT | _PAGE_READ | \ + _PAGE_WRITE | _PAGE_EXEC | \ + _PAGE_USER | _PAGE_GLOBAL | \ + _PAGE_MTMASK)) + static inline int pud_present(pud_t pud) { return (pud_val(pud) & _PAGE_PRESENT); diff --git a/arch/riscv/include/asm/pgtable-bits.h b/arch/riscv/include/asm/pgtable-bits.h index 4831122d559d..ee908a142f3c 100644 --- a/arch/riscv/include/asm/pgtable-bits.h +++ b/arch/riscv/include/asm/pgtable-bits.h @@ -29,10 +29,6 @@ #define _PAGE_PFN_SHIFT 10 -/* Set of bits to preserve across pte_modify() */ -#define _PAGE_CHG_MASK (~(unsigned long)(_PAGE_PRESENT | _PAGE_READ | \ - _PAGE_WRITE | _PAGE_EXEC | \ - _PAGE_USER | _PAGE_GLOBAL)) /* * when all of R/W/X are zero, the PTE is a pointer to the next level * of the page table; otherwise, it is a leaf PTE. diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index 5cf7465a96c5..a189a21a7c8a 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h @@ -148,11 +148,8 @@ #define PAGE_TABLE __pgprot(_PAGE_TABLE) -/* - * The RISC-V ISA doesn't yet specify how to query or modify PMAs, so we can't - * change the properties of memory regions. - */ -#define _PAGE_IOREMAP _PAGE_KERNEL +#define _PAGE_IOREMAP ((_PAGE_KERNEL & ~_PAGE_MTMASK) | _PAGE_IO) +#define PAGE_KERNEL_IO __pgprot(_PAGE_IOREMAP) extern pgd_t swapper_pg_dir[]; @@ -492,6 +489,28 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma, return ptep_test_and_clear_young(vma, address, ptep); } +#define pgprot_noncached pgprot_noncached +static inline pgprot_t pgprot_noncached(pgprot_t _prot) +{ + unsigned long prot = pgprot_val(_prot); + + prot &= ~_PAGE_MTMASK; + prot |= _PAGE_IO; + + return __pgprot(prot); +} + +#define pgprot_writecombine pgprot_writecombine +static inline pgprot_t pgprot_writecombine(pgprot_t _prot) +{ + unsigned long prot = pgprot_val(_prot); + + prot &= ~_PAGE_MTMASK; + prot |= _PAGE_NOCACHE; + + return __pgprot(prot); +} + /* * THP functions */ diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index fef804346d75..d14289fba055 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -159,7 +160,85 @@ struct cpufeature_info { bool (*check_func)(unsigned int stage); }; +#if defined(CONFIG_MMU) && defined(CONFIG_64BIT) +static bool cpufeature_svpbmt_check_fdt(void) +{ + const void *fdt = dtb_early_va; + const char *str; + int offset; + + offset = fdt_path_offset(fdt, "/cpus"); + if (offset < 0) + return false; + + for (offset = fdt_next_node(fdt, offset, NULL); offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + str = fdt_getprop(fdt, offset, "device_type", NULL); + if (!str || strcmp(str, "cpu")) + break; + + str = fdt_getprop(fdt, offset, "mmu-type", NULL); + if (!str) + continue; + + if (!strncmp(str + 6, "none", 4)) + continue; + + str = fdt_getprop(fdt, offset, "mmu", NULL); + if (!str) + continue; + + if (!strncmp(str + 6, "svpbmt", 6)) + return true; + } + + return false; +} + +static bool cpufeature_svpbmt_check_of(void) +{ + struct device_node *node; + const char *str; + + for_each_of_cpu_node(node) { + if (of_property_read_string(node, "mmu-type", &str)) + continue; + + if (!strncmp(str + 6, "none", 4)) + continue; + + if (of_property_read_string(node, "mmu", &str)) + continue; + + if (!strncmp(str + 6, "svpbmt", 6)) + return true; + } + + return false; +} +#endif + +static bool cpufeature_svpbmt_check_func(unsigned int stage) +{ + bool ret = false; + +#if defined(CONFIG_MMU) && defined(CONFIG_64BIT) + switch (stage) { + case RISCV_ALTERNATIVES_BOOT: + return cpufeature_svpbmt_check_fdt(); + default: + return cpufeature_svpbmt_check_of(); + } +#endif + + return ret; +} + static const struct cpufeature_info cpufeature_list[CPUFEATURE_NUMBER] = { + { + .name = "svpbmt", + .check_func = cpufeature_svpbmt_check_func + }, }; static u32 __init cpufeature_probe(unsigned int stage) -- 2.30.2