From patchwork Wed Jun 26 17:48:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiang W X-Patchwork-Id: 1952740 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=t75YBDW+; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=126.com header.i=@126.com header.a=rsa-sha256 header.s=s110527 header.b=SAKiuKav; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org; envelope-from=opensbi-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=patchwork.ozlabs.org) Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4W8Tjb2wkNz20Xf for ; Thu, 27 Jun 2024 03:49:38 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=dDq53X9J2rc1EmMVK+sV9Jsj3OS/cZJ6YYLSRLnNm+Q=; b=t75YBDW+9hnnQL 8CZAFqc209DiFPIn2U9Hu8twke19z67Ovbl/I71StqmtzjZdYNW/4e/0xbX9c9sILZKURILn9mTWy wjRoFCsrFOV3TwiZfNnotUa1HJ8wD14sdn33B70J3gBo3+ZLmaNOwMAX1NSRoDvBcnEWIMNkGI1b4 3wAhBi6Nvebw+ENsKPWKyBJdm/Lw4pPFt2quIjVH8pNKmG3pL0Z+128SQCx+yxSdVXr0HnVCwOvGM cVwEGmVEOs/EB1gq5ckRn4RjI2IizUkgDK8vFft+FIwDDB2loHHdZoUjEEejCEgEzmPa00VdEKVby 6o3vLixxfXZsRj2Lru0Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sMWlp-00000007oZ4-3RXo; Wed, 26 Jun 2024 17:49:25 +0000 Received: from m16.mail.126.com ([117.135.210.9]) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sMWli-00000007oWy-0qbg for opensbi@lists.infradead.org; Wed, 26 Jun 2024 17:49:23 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=126.com; s=s110527; h=From:Subject:Date:Message-ID:MIME-Version; bh=POTCx r+QOnqqZzOw1YezxpDvxwvB3WTAczHJIs3iqq8=; b=SAKiuKavgLvzexhMBCwoV 6T+PYg3kdTF6tk+TXb1WPNEYNl4ZWfCW6whLf4bZe8q6PqJdQtvUFlrvht/cKJfZ 8Z+gAZ95Ai9d8+RnEwPdGF15mw64YqGnfsiym8bsYOwA2vbJtyLfgaLj9ZnaIqbW q4DDg/svpNOadLS98tX9Ao= Received: from T490.lan (unknown [112.83.183.192]) by gzga-smtp-mta-g0-1 (Coremail) with SMTP id _____wD3Hz5iVHxmnCGXAA--.57783S3; Thu, 27 Jun 2024 01:48:19 +0800 (CST) From: Xiang W To: opensbi@lists.infradead.org Cc: Xiang W , anup@brainfault.org Subject: [PATCH 1/3] lib: sbi: Add tor type PMP support Date: Thu, 27 Jun 2024 01:48:12 +0800 Message-ID: <20240626174816.2837278-2-wxjstz@126.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240626174816.2837278-1-wxjstz@126.com> References: <20240626174816.2837278-1-wxjstz@126.com> MIME-Version: 1.0 X-CM-TRANSID: _____wD3Hz5iVHxmnCGXAA--.57783S3 X-Coremail-Antispam: 1Uf129KBjvJXoW3tr43XrWkJr15AF1DKF15Jwb_yoWkJw45pF WxKa4Dtr48tryvqasxAr48WFy5tw1UK3ZxtFW2kry093W5WF1rZFy3C3s0qr1UXFykXFW7 A3yftr18uFs8XFJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x0pimZXrUUUUU= X-Originating-IP: [112.83.183.192] X-CM-SenderInfo: pz0m23b26rjloofrz/1tbiFwYKOmW-P5RYDwAAsH X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240626_104919_437075_2647F023 X-CRM114-Status: GOOD ( 19.60 ) X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: tor type PMP can save the number of PMP configuration registers in certain scenarios. This patch add support Signed-off-by: Xiang W --- include/sbi/riscv_asm.h | 6 +- lib/sbi/riscv_asm.c | 190 +++++++++++++++++++++++ lib/sbi/sbi_hart.c | 29 +++--- 3 files changed, 132 insertions(+), 93 del [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [wxjstz(at)126.com] -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [117.135.210.9 listed in list.dnswl.org] X-BeenThere: opensbi@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "opensbi" Errors-To: opensbi-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org tor type PMP can save the number of PMP configuration registers in certain scenarios. This patch add support Signed-off-by: Xiang W --- include/sbi/riscv_asm.h | 6 +- lib/sbi/riscv_asm.c | 190 +++++++++++++++++++++++----------------- lib/sbi/sbi_hart.c | 29 +++--- 3 files changed, 132 insertions(+), 93 deletions(-) diff --git a/include/sbi/riscv_asm.h b/include/sbi/riscv_asm.h index 2c34635..60036fa 100644 --- a/include/sbi/riscv_asm.h +++ b/include/sbi/riscv_asm.h @@ -187,11 +187,11 @@ int pmp_disable(unsigned int n); /* Check if the matching field is set */ int is_pmp_entry_mapped(unsigned long entry); -int pmp_set(unsigned int n, unsigned long prot, unsigned long addr, - unsigned long log2len); +int pmp_set(unsigned int *n, unsigned long prot, unsigned long addr, + unsigned long end); int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out, - unsigned long *log2len); + unsigned long *end_out); #endif /* !__ASSEMBLER__ */ diff --git a/lib/sbi/riscv_asm.c b/lib/sbi/riscv_asm.c index 05b8c7c..b763ec5 100644 --- a/lib/sbi/riscv_asm.c +++ b/lib/sbi/riscv_asm.c @@ -8,8 +8,10 @@ */ #include +#include #include #include +#include #include #include @@ -258,29 +260,52 @@ static unsigned long ctz(unsigned long x) return ret; } -int pmp_disable(unsigned int n) +static void pmp_rw(unsigned int n, + unsigned long *cfg_in, unsigned long *addr_in, + unsigned long *cfg_out, unsigned long *addr_out) { - int pmpcfg_csr, pmpcfg_shift; unsigned long cfgmask, pmpcfg; + int pmpcfg_csr, pmpcfg_shift, pmpaddr_csr; - if (n >= PMP_COUNT) - return SBI_EINVAL; - + if (cfg_in || cfg_out) { #if __riscv_xlen == 32 - pmpcfg_csr = CSR_PMPCFG0 + (n >> 2); - pmpcfg_shift = (n & 3) << 3; + pmpcfg_csr = CSR_PMPCFG0 + (n >> 2); + pmpcfg_shift = (n & 3) << 3; #elif __riscv_xlen == 64 - pmpcfg_csr = (CSR_PMPCFG0 + (n >> 2)) & ~1; - pmpcfg_shift = (n & 7) << 3; + pmpcfg_csr = (CSR_PMPCFG0 + (n >> 2)) & ~1; + pmpcfg_shift = (n & 7) << 3; #else # error "Unexpected __riscv_xlen" #endif - /* Clear the address matching bits to disable the pmp entry */ - cfgmask = ~(0xffUL << pmpcfg_shift); - pmpcfg = (csr_read_num(pmpcfg_csr) & cfgmask); + cfgmask = ~(0xffUL << pmpcfg_shift); + pmpcfg = (csr_read_num(pmpcfg_csr) & cfgmask); + if (cfg_out) + *cfg_out = pmpcfg >> pmpcfg_shift; + if (cfg_in) { + pmpcfg |= ((*cfg_in << pmpcfg_shift) & ~cfgmask); + csr_write_num(pmpcfg_csr, pmpcfg); + } + } + + if (addr_in || addr_out) { + pmpaddr_csr = CSR_PMPADDR0 + n; + if (addr_out) + *addr_out = csr_read_num(pmpaddr_csr); + if (addr_in) + csr_write_num(pmpaddr_csr, *addr_in); + } +} + +int pmp_disable(unsigned int n) +{ + unsigned long pmpcfg; + + if (n >= PMP_COUNT) + return SBI_EINVAL; - csr_write_num(pmpcfg_csr, pmpcfg); + pmpcfg = 0; + pmp_rw(n, &pmpcfg, NULL, NULL, NULL); return SBI_OK; } @@ -289,99 +314,94 @@ int is_pmp_entry_mapped(unsigned long entry) { unsigned long prot; unsigned long addr; - unsigned long log2len; + unsigned long end; - pmp_get(entry, &prot, &addr, &log2len); + pmp_get(entry, &prot, &addr, &end); /* If address matching bits are non-zero, the entry is enable */ if (prot & PMP_A) return true; + pmp_get(entry + 1, &prot, &addr, &end); + if ((prot & PMP_A) == PMP_A_TOR) + return true; + return false; } -int pmp_set(unsigned int n, unsigned long prot, unsigned long addr, - unsigned long log2len) +int pmp_set(unsigned int *idx, unsigned long prot, unsigned long addr, unsigned long end) { - int pmpcfg_csr, pmpcfg_shift, pmpaddr_csr; - unsigned long cfgmask, pmpcfg; + unsigned int n = *idx; + unsigned long log2len, size; unsigned long addrmask, pmpaddr; - /* check parameters */ - if (n >= PMP_COUNT || log2len > __riscv_xlen || log2len < PMP_SHIFT) + if (end <= addr) return SBI_EINVAL; - /* calculate PMP register and offset */ -#if __riscv_xlen == 32 - pmpcfg_csr = CSR_PMPCFG0 + (n >> 2); - pmpcfg_shift = (n & 3) << 3; -#elif __riscv_xlen == 64 - pmpcfg_csr = (CSR_PMPCFG0 + (n >> 2)) & ~1; - pmpcfg_shift = (n & 7) << 3; -#else -# error "Unexpected __riscv_xlen" -#endif - pmpaddr_csr = CSR_PMPADDR0 + n; - - /* encode PMP config */ - prot &= ~PMP_A; - prot |= (log2len == PMP_SHIFT) ? PMP_A_NA4 : PMP_A_NAPOT; - cfgmask = ~(0xffUL << pmpcfg_shift); - pmpcfg = (csr_read_num(pmpcfg_csr) & cfgmask); - pmpcfg |= ((prot << pmpcfg_shift) & ~cfgmask); - - /* encode PMP address */ - if (log2len == PMP_SHIFT) { - pmpaddr = (addr >> PMP_SHIFT); - } else { - if (log2len == __riscv_xlen) { - pmpaddr = -1UL; + size = end - addr + 1; + if ((end - addr == -1UL) || (sbi_popcount(size) == 1)) { + log2len = log2roundup(size); + if (end - addr == -1UL) + log2len = __riscv_xlen; + if (n >= PMP_COUNT || log2len < PMP_SHIFT) + return SBI_EINVAL; + + /* encode PMP config */ + prot &= ~PMP_A; + prot |= (log2len == PMP_SHIFT) ? PMP_A_NA4 : PMP_A_NAPOT; + + /* encode PMP address */ + if (log2len == PMP_SHIFT) { + pmpaddr = (addr >> PMP_SHIFT); } else { - addrmask = (1UL << (log2len - PMP_SHIFT)) - 1; - pmpaddr = ((addr >> PMP_SHIFT) & ~addrmask); - pmpaddr |= (addrmask >> 1); + if (log2len == __riscv_xlen) { + pmpaddr = -1UL; + } else { + addrmask = (1UL << (log2len - PMP_SHIFT)) - 1; + pmpaddr = ((addr >> PMP_SHIFT) & ~addrmask); + pmpaddr |= (addrmask >> 1); + } } + pmp_rw(n, &prot, &pmpaddr, NULL, NULL); + n++; + *idx = n; + return 0; } - /* write csrs */ - csr_write_num(pmpaddr_csr, pmpaddr); - csr_write_num(pmpcfg_csr, pmpcfg); + if (n + 1 >= PMP_COUNT) + return SBI_EINVAL; + + addr = addr >> PMP_SHIFT; + end = (end + 1) >> PMP_SHIFT; + + prot &= ~PMP_A; + pmp_rw(n, &prot, &addr, NULL, NULL); + n++; + prot |= PMP_A_TOR; + pmp_rw(n, &prot, &end, NULL, NULL); + n++; + + *idx = n; return 0; } int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out, - unsigned long *log2len) + unsigned long *end_out) { - int pmpcfg_csr, pmpcfg_shift, pmpaddr_csr; - unsigned long cfgmask, pmpcfg, prot; - unsigned long t1, addr, len; + unsigned long prot, prot_a; + unsigned long t1, addr, len, end; /* check parameters */ - if (n >= PMP_COUNT || !prot_out || !addr_out || !log2len) + if (n >= PMP_COUNT || !prot_out || !addr_out || !end_out) return SBI_EINVAL; - *prot_out = *addr_out = *log2len = 0; - - /* calculate PMP register and offset */ -#if __riscv_xlen == 32 - pmpcfg_csr = CSR_PMPCFG0 + (n >> 2); - pmpcfg_shift = (n & 3) << 3; -#elif __riscv_xlen == 64 - pmpcfg_csr = (CSR_PMPCFG0 + (n >> 2)) & ~1; - pmpcfg_shift = (n & 7) << 3; -#else -# error "Unexpected __riscv_xlen" -#endif - pmpaddr_csr = CSR_PMPADDR0 + n; - /* decode PMP config */ - cfgmask = (0xffUL << pmpcfg_shift); - pmpcfg = csr_read_num(pmpcfg_csr) & cfgmask; - prot = pmpcfg >> pmpcfg_shift; + end = 0; + pmp_rw(n, NULL, NULL, &prot, &addr); /* decode PMP address */ - if ((prot & PMP_A) == PMP_A_NAPOT) { - addr = csr_read_num(pmpaddr_csr); + prot_a = prot & PMP_A; + if (prot_a == PMP_A_NAPOT) { if (addr == -1UL) { addr = 0; len = __riscv_xlen; @@ -390,15 +410,27 @@ int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out, addr = (addr & ~((1UL << t1) - 1)) << PMP_SHIFT; len = (t1 + PMP_SHIFT + 1); } - } else { - addr = csr_read_num(pmpaddr_csr) << PMP_SHIFT; + end = addr + (1UL << len) - 1; + } + if (prot_a == PMP_A_NA4) { + addr = addr << PMP_SHIFT; len = PMP_SHIFT; + end = addr + (1UL << len) - 1; + } + if(prot_a == PMP_A_TOR) { + end = addr; + if (n > 0) + pmp_rw(n - 1, NULL, NULL, NULL, &addr); + else + addr = 0; + addr = addr << PMP_SHIFT; + end = (end << PMP_SHIFT) - 1; } /* return details */ *prot_out = prot; *addr_out = addr; - *log2len = len; + *end_out = end; return 0; } diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c index c366701..acf0926 100644 --- a/lib/sbi/sbi_hart.c +++ b/lib/sbi/sbi_hart.c @@ -349,16 +349,18 @@ static unsigned int sbi_hart_get_smepmp_flags(struct sbi_scratch *scratch, static void sbi_hart_smepmp_set(struct sbi_scratch *scratch, struct sbi_domain *dom, struct sbi_domain_memregion *reg, - unsigned int pmp_idx, + unsigned int *pmp_idx, unsigned int pmp_flags, unsigned int pmp_log2gran, unsigned long pmp_addr_max) { unsigned long pmp_addr = reg->base >> PMP_SHIFT; - - if (pmp_log2gran <= reg->order && pmp_addr < pmp_addr_max) { - pmp_set(pmp_idx, pmp_flags, reg->base, reg->order); - } else { + unsigned long start = reg->base; + unsigned long end = reg->order < __riscv_xlen ? + start + BIT(reg->order) - 1: -1UL; + if (pmp_log2gran <= reg->order && pmp_addr < pmp_addr_max) + pmp_set(pmp_idx, pmp_flags, start, end); + else { sbi_printf("Can not configure pmp for domain %s because" " memory region address 0x%lx or size 0x%lx " "is not in range.\n", dom->name, reg->base, @@ -403,7 +405,7 @@ static int sbi_hart_smepmp_configure(struct sbi_scratch *scratch, if (!pmp_flags) return 0; - sbi_hart_smepmp_set(scratch, dom, reg, pmp_idx++, pmp_flags, + sbi_hart_smepmp_set(scratch, dom, reg, &pmp_idx, pmp_flags, pmp_log2gran, pmp_addr_max); } @@ -429,7 +431,7 @@ static int sbi_hart_smepmp_configure(struct sbi_scratch *scratch, if (!pmp_flags) return 0; - sbi_hart_smepmp_set(scratch, dom, reg, pmp_idx++, pmp_flags, + sbi_hart_smepmp_set(scratch, dom, reg, &pmp_idx, pmp_flags, pmp_log2gran, pmp_addr_max); } @@ -450,7 +452,7 @@ static int sbi_hart_oldpmp_configure(struct sbi_scratch *scratch, struct sbi_domain *dom = sbi_domain_thishart_ptr(); unsigned int pmp_idx = 0; unsigned int pmp_flags; - unsigned long pmp_addr; + unsigned long pmp_addr, start, end; sbi_domain_for_each_memregion(dom, reg) { if (pmp_count <= pmp_idx) @@ -473,8 +475,11 @@ static int sbi_hart_oldpmp_configure(struct sbi_scratch *scratch, pmp_flags |= PMP_X; pmp_addr = reg->base >> PMP_SHIFT; + start = reg->base; + end = reg->order < __riscv_xlen ? + start + BIT(reg->order) - 1 : -1UL; if (pmp_log2gran <= reg->order && pmp_addr < pmp_addr_max) { - pmp_set(pmp_idx++, pmp_flags, reg->base, reg->order); + pmp_set(&pmp_idx, pmp_flags, start, end); } else { sbi_printf("Can not configure pmp for domain %s because" " memory region address 0x%lx or size 0x%lx " @@ -489,8 +494,9 @@ static int sbi_hart_oldpmp_configure(struct sbi_scratch *scratch, int sbi_hart_map_saddr(unsigned long addr, unsigned long size) { /* shared R/W access for M and S/U mode */ + unsigned int n = SBI_SMEPMP_RESV_ENTRY; unsigned int pmp_flags = (PMP_W | PMP_X); - unsigned long order, base = 0; + unsigned long order, base = 0, end; struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); /* If Smepmp is not supported no special mapping is required */ @@ -514,7 +520,8 @@ int sbi_hart_map_saddr(unsigned long addr, unsigned long size) } } - pmp_set(SBI_SMEPMP_RESV_ENTRY, pmp_flags, base, order); + end = base + (1UL << order) - 1; + pmp_set(&n, pmp_flags, base, end); return SBI_OK; } From patchwork Wed Jun 26 17:48:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiang W X-Patchwork-Id: 1952743 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=JDkbVNGb; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=126.com header.i=@126.com header.a=rsa-sha256 header.s=s110527 header.b=iqvNfcJS; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org; envelope-from=opensbi-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=patchwork.ozlabs.org) Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4W8Tjb3Db0z214l for ; Thu, 27 Jun 2024 03:49:37 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=pb3OAc9NwyKv8BmFfoDn1kUQPo8pvqa633GKUsF91oE=; b=JDkbVNGbosNntM ucXpWnMhE1N62z+dP7DeYymO8oNSpAng56hkyswx7Z1tqcCCkwiyn7rEDMgTqa3Ytaz5ccvNBcQTC FqOUkx/e72PzzKus5A9xTcfJTYZl7q/m94QMCfk15BkuXciySwA3egyxRNOTxpL1zqErT+EBeLxhB qqSh4IxMzXVCI8nuKyiBPGccD91y9t+I4szc3r75bH/lbsSlSceJcQKzJYJweI1QbFb1r9hQutRz+ Vr7EJxb2ejCbB8KT0d0UYkziymt38/aHBzOcRAcV6pj3YGeySKWr7QqjgZfkbhJqxOCkgSg8WWsqQ odpXg3pIl6sIKZobE0fg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sMWlq-00000007oZK-24Km; Wed, 26 Jun 2024 17:49:26 +0000 Received: from m16.mail.126.com ([117.135.210.8]) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sMWlk-00000007oX4-2Dyp for opensbi@lists.infradead.org; Wed, 26 Jun 2024 17:49:23 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=126.com; s=s110527; h=From:Subject:Date:Message-ID:MIME-Version; bh=6Z9XT JciO6WfMg20V/YiEgONhr6SIDF3hGyMnNDLDmA=; b=iqvNfcJSOfxXk8tbTMv5T hGTPlax4zdD9N2Bb02DtOfKQ6iBFnksZ0qFjSDVnyuH2TKfLljMxTGG8Z1OkomYC 5ADO/1OIqkCGvKSVAh0NqiT1jFYZhjq7QKfr9vn4amcS504PCzeasvV3T/dX7127 hdyHlmqwAOd8kMHdMWaPY8= Received: from T490.lan (unknown [112.83.183.192]) by gzga-smtp-mta-g0-1 (Coremail) with SMTP id _____wD3Hz5iVHxmnCGXAA--.57783S4; Thu, 27 Jun 2024 01:48:19 +0800 (CST) From: Xiang W To: opensbi@lists.infradead.org Cc: Xiang W , anup@brainfault.org Subject: [PATCH 2/3] lib: sbi: Introduce size to sbi_domain_memregion Date: Thu, 27 Jun 2024 01:48:13 +0800 Message-ID: <20240626174816.2837278-3-wxjstz@126.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240626174816.2837278-1-wxjstz@126.com> References: <20240626174816.2837278-1-wxjstz@126.com> MIME-Version: 1.0 X-CM-TRANSID: _____wD3Hz5iVHxmnCGXAA--.57783S4 X-Coremail-Antispam: 1Uf129KBjvJXoW3AFyfXw18GryDCF4xKFWDXFb_yoWfCr1fp3 W8tFy3Gr4Iqr4FqwnrGa1UW390kry0yF4Ykay2kw10kw18Arn8CF48Zwn09r13AFyxZa1U ur4jvrsruFsxtaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x0ziHUDJUUUUU= X-Originating-IP: [112.83.183.192] X-CM-SenderInfo: pz0m23b26rjloofrz/1tbi5BUKOmVLaGIaoAAAsf X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240626_104920_943171_B548CDED X-CRM114-Status: GOOD ( 20.36 ) X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: In order to support tor type pmp, introduce size to sbi_domain_memregion. Signed-off-by: Xiang W --- include/sbi/sbi_domain.h | 37 ++++++++++++++++++ lib/sbi/sbi_domain.c | 82 ++++++++++++++++++++ lib/sbi/sbi_hart.c | 15 ++++---- 3 files changed, 85 in [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [wxjstz(at)126.com] -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [117.135.210.8 listed in list.dnswl.org] 0.0 RCVD_IN_MSPIKE_L3 RBL: Low reputation (-3) [117.135.210.8 listed in bl.mailspike.net] 0.0 RCVD_IN_MSPIKE_BL Mailspike blocklisted X-BeenThere: opensbi@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "opensbi" Errors-To: opensbi-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org In order to support tor type pmp, introduce size to sbi_domain_memregion. Signed-off-by: Xiang W --- include/sbi/sbi_domain.h | 37 ++++++++++++++++++ lib/sbi/sbi_domain.c | 82 ++++++++++++++++++++-------------------- lib/sbi/sbi_hart.c | 15 ++++---- 3 files changed, 85 insertions(+), 49 deletions(-) diff --git a/include/sbi/sbi_domain.h b/include/sbi/sbi_domain.h index a6e99c6..f97f62e 100644 --- a/include/sbi/sbi_domain.h +++ b/include/sbi/sbi_domain.h @@ -32,6 +32,14 @@ struct sbi_domain_memregion { * It has to be minimum 3 and maximum __riscv_xlen */ unsigned long order; + + /** + * when size is not equal to 0, order is invalid + * When the size of the memory region is not a power of 2, + * it is represented by size. + */ + unsigned long size; + /** * Base address of memory region * It must be 2^order aligned address @@ -227,6 +235,35 @@ extern struct sbi_domain *domidx_to_domain_table[]; /** Iterate over each memory region of a domain */ #define sbi_domain_for_each_memregion(__d, __r) \ for ((__r) = (__d)->regions; (__r)->order; (__r)++) +/** + * Calculate the start address of the memory region + * @param r pointer to memory region + * @return start address of the memory region + */ +static inline unsigned long memregion_start(const struct sbi_domain_memregion *r) +{ + if (r->size) + return r->base; + if (r->order < __riscv_xlen) + return r->base; + else + return 0; +} + +/** + * Calculate the end addresses of the memory region + * @param r pointer to memory region + * @return end addresses of the memory region + */ +static inline unsigned long memregion_end(const struct sbi_domain_memregion *r) +{ + if (r->size) + return r->base + r->size - 1; + if (r->order < __riscv_xlen) + return r->base + BIT(r->order) - 1; + else + return -1UL; +} /** * Check whether given HART is assigned to specified domain diff --git a/lib/sbi/sbi_domain.c b/lib/sbi/sbi_domain.c index 374ac36..9a9fce1 100644 --- a/lib/sbi/sbi_domain.c +++ b/lib/sbi/sbi_domain.c @@ -40,6 +40,10 @@ struct sbi_domain root = { static unsigned long domain_hart_ptr_offset; +static const struct sbi_domain_memregion *find_region( + const struct sbi_domain *dom, + unsigned long addr); + struct sbi_domain *sbi_hartindex_to_domain(u32 hartindex) { struct sbi_scratch *scratch; @@ -96,6 +100,12 @@ ulong sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom, return ret; } +static inline bool +in_memregion(const struct sbi_domain_memregion *r, unsigned long addr) +{ + return memregion_start(r) <= addr && addr <= memregion_end(r); +} + void sbi_domain_memregion_init(unsigned long addr, unsigned long size, unsigned long flags, @@ -120,6 +130,7 @@ void sbi_domain_memregion_init(unsigned long addr, if (reg) { reg->base = base; + reg->size = 0; reg->order = order; reg->flags = flags; } @@ -130,8 +141,8 @@ bool sbi_domain_check_addr(const struct sbi_domain *dom, unsigned long access_flags) { bool rmmio, mmio = false; - struct sbi_domain_memregion *reg; - unsigned long rstart, rend, rflags, rwx = 0, rrwx = 0; + const struct sbi_domain_memregion *reg; + unsigned long rflags, rwx = 0, rrwx = 0; if (!dom) return false; @@ -153,22 +164,18 @@ bool sbi_domain_check_addr(const struct sbi_domain *dom, if (access_flags & SBI_DOMAIN_MMIO) mmio = true; - sbi_domain_for_each_memregion(dom, reg) { + reg = find_region(dom, addr); + if (reg) { rflags = reg->flags; rrwx = (mode == PRV_M ? (rflags & SBI_DOMAIN_MEMREGION_M_ACCESS_MASK) : (rflags & SBI_DOMAIN_MEMREGION_SU_ACCESS_MASK) >> SBI_DOMAIN_MEMREGION_SU_ACCESS_SHIFT); - rstart = reg->base; - rend = (reg->order < __riscv_xlen) ? - rstart + ((1UL << reg->order) - 1) : -1UL; - if (rstart <= addr && addr <= rend) { - rmmio = (rflags & SBI_DOMAIN_MEMREGION_MMIO) ? true : false; - if (mmio != rmmio) - return false; - return ((rrwx & rwx) == rwx) ? true : false; - } + rmmio = (rflags & SBI_DOMAIN_MEMREGION_MMIO) ? true : false; + if (mmio != rmmio) + return false; + return ((rrwx & rwx) == rwx) ? true : false; } return (mode == PRV_M) ? true : false; @@ -177,6 +184,9 @@ bool sbi_domain_check_addr(const struct sbi_domain *dom, /* Check if region complies with constraints */ static bool is_region_valid(const struct sbi_domain_memregion *reg) { + if (reg->size) + return sbi_popcount(reg->size) > 2 ? true : false; + if (reg->order < 3 || __riscv_xlen < reg->order) return false; @@ -193,18 +203,9 @@ static bool is_region_valid(const struct sbi_domain_memregion *reg) static bool is_region_subset(const struct sbi_domain_memregion *regA, const struct sbi_domain_memregion *regB) { - ulong regA_start = regA->base; - ulong regA_end = regA->base + (BIT(regA->order) - 1); - ulong regB_start = regB->base; - ulong regB_end = regB->base + (BIT(regB->order) - 1); - - if ((regB_start <= regA_start) && - (regA_start < regB_end) && - (regB_start < regA_end) && - (regA_end <= regB_end)) - return true; - - return false; + ulong regA_start = memregion_start(regA); + ulong regA_end = memregion_end(regA); + return in_memregion(regB, regA_start) && in_memregion(regB, regA_end); } /** Check if regionA can be replaced by regionB */ @@ -221,10 +222,12 @@ static bool is_region_compatible(const struct sbi_domain_memregion *regA, static bool is_region_before(const struct sbi_domain_memregion *regA, const struct sbi_domain_memregion *regB) { - if (regA->order < regB->order) + unsigned long regA_s = memregion_end(regA) - memregion_start(regA); + unsigned long regB_s = memregion_end(regB) - memregion_start(regB); + if (regA_s < regB_s) return true; - if ((regA->order == regB->order) && + if ((regA_s == regB_s) && (regA->base < regB->base)) return true; @@ -235,14 +238,10 @@ static const struct sbi_domain_memregion *find_region( const struct sbi_domain *dom, unsigned long addr) { - unsigned long rstart, rend; struct sbi_domain_memregion *reg; sbi_domain_for_each_memregion(dom, reg) { - rstart = reg->base; - rend = (reg->order < __riscv_xlen) ? - rstart + ((1UL << reg->order) - 1) : -1UL; - if (rstart <= addr && addr <= rend) + if (in_memregion(reg, addr)) return reg; } @@ -262,7 +261,8 @@ static const struct sbi_domain_memregion *find_next_subset_region( continue; if (!ret || (sreg->base < ret->base) || - ((sreg->base == ret->base) && (sreg->order < ret->order))) + ((sreg->base == ret->base) && + (memregion_end(sreg) < memregion_end(ret)))) ret = sreg; } @@ -314,8 +314,8 @@ static int sanitize_domain(struct sbi_domain *dom) sbi_domain_for_each_memregion(dom, reg) { if (!is_region_valid(reg)) { sbi_printf("%s: %s has invalid region base=0x%lx " - "order=%lu flags=0x%lx\n", __func__, - dom->name, reg->base, reg->order, + "order=%lu size=%lu flags=0x%lx\n", __func__, + dom->name, reg->base, reg->order, reg->size, reg->flags); return SBI_EINVAL; } @@ -423,10 +423,11 @@ bool sbi_domain_check_addr_range(const struct sbi_domain *dom, sreg = find_next_subset_region(dom, reg, addr); if (sreg) addr = sreg->base; - else if (reg->order < __riscv_xlen) - addr = reg->base + (1UL << reg->order); - else - break; + else { + addr = memregion_end(reg) + 1; + if (addr == 0) + break; + } } return true; @@ -455,9 +456,8 @@ void sbi_domain_dump(const struct sbi_domain *dom, const char *suffix) i = 0; sbi_domain_for_each_memregion(dom, reg) { - rstart = reg->base; - rend = (reg->order < __riscv_xlen) ? - rstart + ((1UL << reg->order) - 1) : -1UL; + rstart = memregion_start(reg); + rend = memregion_end(reg); sbi_printf("Domain%d Region%02d %s: 0x%" PRILX "-0x%" PRILX " ", dom->index, i, suffix, rstart, rend); diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c index acf0926..982e77a 100644 --- a/lib/sbi/sbi_hart.c +++ b/lib/sbi/sbi_hart.c @@ -355,10 +355,9 @@ static void sbi_hart_smepmp_set(struct sbi_scratch *scratch, unsigned long pmp_addr_max) { unsigned long pmp_addr = reg->base >> PMP_SHIFT; - unsigned long start = reg->base; - unsigned long end = reg->order < __riscv_xlen ? - start + BIT(reg->order) - 1: -1UL; - if (pmp_log2gran <= reg->order && pmp_addr < pmp_addr_max) + unsigned long start = memregion_start(reg); + unsigned long end = memregion_end(reg); + if ((1 << pmp_log2gran) - 1 <= end - start && pmp_addr < pmp_addr_max) pmp_set(pmp_idx, pmp_flags, start, end); else { sbi_printf("Can not configure pmp for domain %s because" @@ -475,10 +474,10 @@ static int sbi_hart_oldpmp_configure(struct sbi_scratch *scratch, pmp_flags |= PMP_X; pmp_addr = reg->base >> PMP_SHIFT; - start = reg->base; - end = reg->order < __riscv_xlen ? - start + BIT(reg->order) - 1 : -1UL; - if (pmp_log2gran <= reg->order && pmp_addr < pmp_addr_max) { + start = memregion_start(reg); + end = memregion_end(reg); + if ((1 << pmp_log2gran) - 1 <= end - start && + pmp_addr < pmp_addr_max) { pmp_set(&pmp_idx, pmp_flags, start, end); } else { sbi_printf("Can not configure pmp for domain %s because" From patchwork Wed Jun 26 17:48:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiang W X-Patchwork-Id: 1952741 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=BmUaU2NG; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=126.com header.i=@126.com header.a=rsa-sha256 header.s=s110527 header.b=TEg3/bRr; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org; envelope-from=opensbi-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=patchwork.ozlabs.org) Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4W8Tjb2yj3z20Z9 for ; Thu, 27 Jun 2024 03:49:38 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=spJvnQiWBib5YvHTf9rDklxr9qMEKFfHiBOBbfG/aA0=; b=BmUaU2NG86T6pd NvAmw2H0fL3BzRitPxHwvKARcgzXmSxYEicDq87EZohKm7iosGMu65Hx4nCBcRI9lBoES4orVTm5p v7QxUq9OT8xbrQarphJH2DE9Z3PWTSb3pqJOLB8u0Qtjyz5D2CtVsWFM2y5K7TmhSDF+zIk+tMGDp PwwCZj7S3HZWAOm4AZSuSo5lXhwULLH/HC6M/YT72y+PWIF14B/uxPZ8bxBFrlCveOXVVFrG7JEzd 7bbO0CSvKea+KVmnkYimLBayxJelgzhzKTmcQOEZ8QhUy65HMjr+Z8iFfj0Glx4oQwpJDsbcrbGXa +99xeltPZ/PXQyxpXFDw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sMWlo-00000007oYf-0eBw; Wed, 26 Jun 2024 17:49:24 +0000 Received: from m16.mail.126.com ([220.197.31.9]) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sMWlh-00000007oWv-1hSV for opensbi@lists.infradead.org; Wed, 26 Jun 2024 17:49:22 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=126.com; s=s110527; h=From:Subject:Date:Message-ID:MIME-Version; bh=gWy0f am+hy9G1CAek+fuWWgszDw9/vbaDEH2K7OcsAY=; b=TEg3/bRr3NTmeEcKVel7w mvgPzmz2luWrUDEfgEcU7pJ6ZFK2DWMAVj0BL4IH4T+8exAE2JXYstOgRCUDV3U/ JxjU2C7iX90QrXbVlh4RIlMu4ppcN0rNPQ6Z0gsdO6dbWsy+gyzo8eiegt2Y26DB rZVzshJD1w5kSXlhG7fauk= Received: from T490.lan (unknown [112.83.183.192]) by gzga-smtp-mta-g0-1 (Coremail) with SMTP id _____wD3Hz5iVHxmnCGXAA--.57783S5; Thu, 27 Jun 2024 01:48:20 +0800 (CST) From: Xiang W To: opensbi@lists.infradead.org Cc: Xiang W , anup@brainfault.org Subject: [PATCH 3/3] lib: sbi: Improve memory region merging Date: Thu, 27 Jun 2024 01:48:14 +0800 Message-ID: <20240626174816.2837278-4-wxjstz@126.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240626174816.2837278-1-wxjstz@126.com> References: <20240626174816.2837278-1-wxjstz@126.com> MIME-Version: 1.0 X-CM-TRANSID: _____wD3Hz5iVHxmnCGXAA--.57783S5 X-Coremail-Antispam: 1Uf129KBjvJXoW3Xw4fCw4rCryfXFyUWw1UGFg_yoW3Gry8pa 15KF9rKr4Iqr4jqws7Ga1UX390yr1IyF4a939rAw18A3WxJr9xCFWrZw1jvF1YvFyxXa1j 9Fy5WrsrCrsxtaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRQzVbUUUUU= X-Originating-IP: [112.83.183.192] X-CM-SenderInfo: pz0m23b26rjloofrz/1tbi5BQKOmVLaGIakgAAss X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240626_104919_419054_C367651A X-CRM114-Status: GOOD ( 18.90 ) X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: The previous merging method can only merge blocks of the same order. The current merging method can merge blocks of different orders. The tor type of pmp can be used to save pmp configuration register [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [220.197.31.9 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [wxjstz(at)126.com] X-BeenThere: opensbi@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "opensbi" Errors-To: opensbi-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org The previous merging method can only merge blocks of the same order. The current merging method can merge blocks of different orders. The tor type of pmp can be used to save pmp configuration registers. Signed-off-by: Xiang W --- lib/sbi/sbi_domain.c | 254 +++++++++++++++++++++++++++++-------------- 1 file changed, 172 insertions(+), 82 deletions(-) diff --git a/lib/sbi/sbi_domain.c b/lib/sbi/sbi_domain.c index 9a9fce1..4d8d995 100644 --- a/lib/sbi/sbi_domain.c +++ b/lib/sbi/sbi_domain.c @@ -279,17 +279,175 @@ static void swap_region(struct sbi_domain_memregion* reg1, sbi_memcpy(reg2, &treg, sizeof(treg)); } -static void clear_region(struct sbi_domain_memregion* reg) +static bool merge_find_near(struct sbi_domain *dom, + unsigned long flags, + unsigned long *start, + unsigned long *end, + unsigned long *bmap) { - sbi_memset(reg, 0x0, sizeof(*reg)); + bool found, ret = false; + int i; + unsigned long s, e, s1, e1; + struct sbi_domain_memregion *reg; + s = *start; + e = *end; + do { + found = false; + i = 0; + sbi_domain_for_each_memregion(dom, reg) { + i++; + if (__test_bit(i- 1, bmap)) + continue; + if (flags != reg->flags) + continue; + s1 = memregion_start(reg); + e1 = memregion_end(reg); + if (e1 < s - 1 || s1 > e + 1) + continue; + found = true; + __set_bit(i - 1, bmap); + s = MIN(s, s1); + e = MAX(e, e1); + } + ret = ret || found; + } while (found); + *start = s; + *end = e; + + return ret; } -static int sanitize_domain(struct sbi_domain *dom) +static void merge_del_helper(struct sbi_domain *dom, + unsigned long *regions_count, unsigned long *bmap) +{ + int i, s = 0, count = *regions_count; + for (i = count - 1; i >= 0; i--) { + if (!__test_bit(i, bmap)) + s += sizeof(struct sbi_domain_memregion); + else { + sbi_memmove(dom->regions + i, dom->regions + i + 1, s); + count--; + } + } + + dom->regions[count].order = 0; + *regions_count = count; +} + +static bool merge_add_helper(struct sbi_domain *dom, + unsigned long *regions_count, + unsigned long *bmap, unsigned long start, + unsigned long end, unsigned long flags) { - u32 i, j, count; - bool is_covered; + int cnt = 0; + unsigned long pos, order, size, s; + end = end + 1; + size = end - start; + if (sbi_popcount(size) > 2) { + merge_del_helper(dom, regions_count, bmap); + + dom->regions[*regions_count].base = start; + dom->regions[*regions_count].size = size; + dom->regions[*regions_count].order = 1; + dom->regions[*regions_count].flags = flags; + (*regions_count)++; + dom->regions[*regions_count].order = 0; + return true; + } + + + pos = start; + while (pos < end) { + s = end - pos; + order = sbi_ffs(pos); + if (BIT(order) > s) + order = sbi_fls(s); + pos = pos + BIT(order); + cnt++; + } + if (cnt >= sbi_popcount(*bmap)) + return false; + + merge_del_helper(dom, regions_count, bmap); + + pos = start; + while (pos < end) { + s = end - pos; + order = sbi_ffs(pos); + if (BIT(order) > s) + order = sbi_fls(s); + dom->regions[*regions_count].base = pos; + dom->regions[*regions_count].size = 0; + dom->regions[*regions_count].order = order; + dom->regions[*regions_count].flags = flags; + (*regions_count)++; + pos = pos + BIT(order); + } + dom->regions[*regions_count].order = 0; + + return true; +} + +static int merge_region(struct sbi_domain *dom) +{ + int i, j; + bool found; + unsigned long bmap, start, end, regions_count; struct sbi_domain_memregion *reg, *reg1; + /* Count memory regions */ + regions_count = root_memregs_count; + if (dom != &root) { + regions_count = 0; + sbi_domain_for_each_memregion(dom, reg) + regions_count++; + } + + /* + * bmap is used to record near regions that may be merged. The number of + * regions cannot exceed the number of bits in bmap. + */ + if (regions_count > BITS_PER_LONG) + return SBI_EINVAL; + + i = 0; + while(i < regions_count) { + reg = dom->regions + i; + bmap = 1UL << i; + start = memregion_start(reg); + end = memregion_end(reg); + found = merge_find_near(dom, reg->flags, &start, &end, &bmap); + if (found) { + if (merge_add_helper(dom, ®ions_count, &bmap, + start, end, reg->flags)) + continue; + } + i++; + } + + /* Sort the memory regions */ + for (i = 0; i < (regions_count - 1); i++) { + reg = &dom->regions[i]; + for (j = i + 1; j < regions_count; j++) { + reg1 = &dom->regions[j]; + + if (!is_region_before(reg1, reg)) + continue; + + swap_region(reg, reg1); + } + } + + if (dom == &root) + root_memregs_count = regions_count; + return SBI_OK; +} + +static int sanitize_domain(struct sbi_domain *dom) +{ + u32 i; + struct sbi_domain_memregion *reg; + /* Check possible HARTs */ if (!dom->possible_harts) { sbi_printf("%s: %s possible HART mask is NULL\n", @@ -321,11 +479,6 @@ static int sanitize_domain(struct sbi_domain *dom) } } - /* Count memory regions */ - count = 0; - sbi_domain_for_each_memregion(dom, reg) - count++; - /* Check presence of firmware regions */ if (!dom->fw_region_inited) { sbi_printf("%s: %s does not have firmware region\n", @@ -333,43 +486,7 @@ static int sanitize_domain(struct sbi_domain *dom) return SBI_EINVAL; } - /* Sort the memory regions */ - for (i = 0; i < (count - 1); i++) { - reg = &dom->regions[i]; - for (j = i + 1; j < count; j++) { - reg1 = &dom->regions[j]; - - if (!is_region_before(reg1, reg)) - continue; - - swap_region(reg, reg1); - } - } - - /* Remove covered regions */ - while(i < (count - 1)) { - is_covered = false; - reg = &dom->regions[i]; - - for (j = i + 1; j < count; j++) { - reg1 = &dom->regions[j]; - - if (is_region_compatible(reg, reg1)) { - is_covered = true; - break; - } - } - - /* find a region is superset of reg, remove reg */ - if (is_covered) { - for (j = i; j < (count - 1); j++) - swap_region(&dom->regions[j], - &dom->regions[j + 1]); - clear_region(&dom->regions[count - 1]); - count--; - } else - i++; - } + merge_region(dom); /* * We don't need to check boot HART id of domain because if boot @@ -605,8 +722,7 @@ int sbi_domain_register(struct sbi_domain *dom, int sbi_domain_root_add_memregion(const struct sbi_domain_memregion *reg) { int rc; - bool reg_merged; - struct sbi_domain_memregion *nreg, *nreg1, *nreg2; + struct sbi_domain_memregion *nreg; /* Sanity checks */ if (!reg || domain_finalized || !root.regions || @@ -625,39 +741,13 @@ int sbi_domain_root_add_memregion(const struct sbi_domain_memregion *reg) root_memregs_count++; root.regions[root_memregs_count].order = 0; - /* Sort and optimize root regions */ - do { - /* Sanitize the root domain so that memregions are sorted */ - rc = sanitize_domain(&root); - if (rc) { - sbi_printf("%s: sanity checks failed for" - " %s (error %d)\n", __func__, - root.name, rc); - return rc; - } - - /* Merge consecutive memregions with same order and flags */ - reg_merged = false; - sbi_domain_for_each_memregion(&root, nreg) { - nreg1 = nreg + 1; - if (!nreg1->order) - continue; - - if (!(nreg->base & (BIT(nreg->order + 1) - 1)) && - (nreg->base + BIT(nreg->order)) == nreg1->base && - nreg->order == nreg1->order && - nreg->flags == nreg1->flags) { - nreg->order++; - while (nreg1->order) { - nreg2 = nreg1 + 1; - sbi_memcpy(nreg1, nreg2, sizeof(*nreg1)); - nreg1++; - } - reg_merged = true; - root_memregs_count--; - } - } - } while (reg_merged); + rc = sanitize_domain(&root); + if (rc) { + sbi_printf("%s: sanity checks failed for" + " %s (error %d)\n", __func__, + root.name, rc); + return rc; + } return 0; }