From: Andrew Jones <ajones@ventanamicro.com>
To: linux-riscv@lists.infradead.org, kvm-riscv@lists.infradead.org,
devicetree@vger.kernel.org
Cc: 'Conor Dooley ' <conor.dooley@microchip.com>,
'Paul Walmsley ' <paul.walmsley@sifive.com>,
'Palmer Dabbelt ' <palmer@dabbelt.com>,
'Sudip Mukherjee ' <sudip.mukherjee@codethink.co.uk>,
'Ben Dooks ' <ben.dooks@codethink.co.uk>,
'Atish Patra ' <atishp@rivosinc.com>,
'Albert Ou ' <aou@eecs.berkeley.edu>,
'Anup Patel ' <apatel@ventanamicro.com>,
'Krzysztof Kozlowski ' <krzysztof.kozlowski+dt@linaro.org>,
'Rob Herring ' <robh@kernel.org>,
'Jisheng Zhang ' <jszhang@kernel.org>,
'Heiko Stuebner ' <heiko@sntech.de>
Subject: [PATCH v6 6/8] RISC-V: Use Zicboz in clear_page when available
Date: Fri, 24 Feb 2023 17:26:29 +0100 [thread overview]
Message-ID: <20230224162631.405473-7-ajones@ventanamicro.com> (raw)
In-Reply-To: <20230224162631.405473-1-ajones@ventanamicro.com>
Using memset() to zero a 4K page takes 563 total instructions, where
20 are branches. clear_page(), with Zicboz and a 64 byte block size,
takes 169 total instructions, where 4 are branches and 33 are nops.
Even though the block size is a variable, thanks to alternatives, we
can still implement a Duff device without having to do any preliminary
calculations. This is achieved by using the alternatives' cpufeature
value (the upper 16 bits of patch_id). The value used is the maximum
zicboz block size order accepted at the patch site. This enables us
to stop patching / unrolling when 4K bytes have been zeroed (we would
loop and continue after 4K if the page size would be larger)
For 4K pages, unrolling 16 times allows block sizes of 64 and 128 to
only loop a few times and larger block sizes to not loop at all. Since
cbo.zero doesn't take an offset, we also need an 'add' after each
instruction, making the loop body 112 to 160 bytes. Hopefully this
is small enough to not cause icache misses.
Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
arch/riscv/Kconfig | 13 ++++++
arch/riscv/include/asm/insn-def.h | 4 ++
arch/riscv/include/asm/page.h | 6 ++-
arch/riscv/kernel/cpufeature.c | 11 +++++
arch/riscv/lib/Makefile | 1 +
arch/riscv/lib/clear_page.S | 74 +++++++++++++++++++++++++++++++
6 files changed, 108 insertions(+), 1 deletion(-)
create mode 100644 arch/riscv/lib/clear_page.S
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index aa951fe2bc56..f715aa39c465 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -458,6 +458,19 @@ config RISCV_ISA_ZICBOM
If you don't know what to do here, say Y.
+config RISCV_ISA_ZICBOZ
+ bool "Zicboz extension support for faster zeroing of memory"
+ depends on !XIP_KERNEL && MMU
+ select RISCV_ALTERNATIVE
+ default y
+ help
+ Enable the use of the ZICBOZ extension (cbo.zero instruction)
+ when available.
+
+ The Zicboz extension is used for faster zeroing of memory.
+
+ If you don't know what to do here, say Y.
+
config TOOLCHAIN_HAS_ZIHINTPAUSE
bool
default y
diff --git a/arch/riscv/include/asm/insn-def.h b/arch/riscv/include/asm/insn-def.h
index e01ab51f50d2..6960beb75f32 100644
--- a/arch/riscv/include/asm/insn-def.h
+++ b/arch/riscv/include/asm/insn-def.h
@@ -192,4 +192,8 @@
INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \
RS1(base), SIMM12(2))
+#define CBO_zero(base) \
+ INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \
+ RS1(base), SIMM12(4))
+
#endif /* __ASM_INSN_DEF_H */
diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h
index 9f432c1b5289..ccd168fe29d2 100644
--- a/arch/riscv/include/asm/page.h
+++ b/arch/riscv/include/asm/page.h
@@ -49,10 +49,14 @@
#ifndef __ASSEMBLY__
+#ifdef CONFIG_RISCV_ISA_ZICBOZ
+void clear_page(void *page);
+#else
#define clear_page(pgaddr) memset((pgaddr), 0, PAGE_SIZE)
+#endif
#define copy_page(to, from) memcpy((to), (from), PAGE_SIZE)
-#define clear_user_page(pgaddr, vaddr, page) memset((pgaddr), 0, PAGE_SIZE)
+#define clear_user_page(pgaddr, vaddr, page) clear_page(pgaddr)
#define copy_user_page(vto, vfrom, vaddr, topg) \
memcpy((vto), (vfrom), PAGE_SIZE)
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index d424cd76beb1..8e7b0d703841 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -293,6 +293,17 @@ static bool riscv_cpufeature_patch_check(u16 id, u16 value)
if (!value)
return true;
+ switch (id) {
+ case RISCV_ISA_EXT_ZICBOZ:
+ /*
+ * Zicboz alternative applications provide the maximum
+ * supported block size order, or zero when it doesn't
+ * matter. If the current block size exceeds the maximum,
+ * then the alternative cannot be applied.
+ */
+ return riscv_cboz_block_size <= (1U << value);
+ }
+
return false;
}
diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
index 6c74b0bedd60..26cb2502ecf8 100644
--- a/arch/riscv/lib/Makefile
+++ b/arch/riscv/lib/Makefile
@@ -8,5 +8,6 @@ lib-y += strlen.o
lib-y += strncmp.o
lib-$(CONFIG_MMU) += uaccess.o
lib-$(CONFIG_64BIT) += tishift.o
+lib-$(CONFIG_RISCV_ISA_ZICBOZ) += clear_page.o
obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o
diff --git a/arch/riscv/lib/clear_page.S b/arch/riscv/lib/clear_page.S
new file mode 100644
index 000000000000..d7a256eb53f4
--- /dev/null
+++ b/arch/riscv/lib/clear_page.S
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2023 Ventana Micro Systems Inc.
+ */
+
+#include <linux/linkage.h>
+#include <asm/asm.h>
+#include <asm/alternative-macros.h>
+#include <asm-generic/export.h>
+#include <asm/hwcap.h>
+#include <asm/insn-def.h>
+#include <asm/page.h>
+
+#define CBOZ_ALT(order, old, new) \
+ ALTERNATIVE(old, new, 0, \
+ ((order) << 16) | RISCV_ISA_EXT_ZICBOZ, \
+ CONFIG_RISCV_ISA_ZICBOZ)
+
+/* void clear_page(void *page) */
+SYM_FUNC_START(clear_page)
+ li a2, PAGE_SIZE
+
+ /*
+ * If Zicboz isn't present, or somehow has a block
+ * size larger than 4K, then fallback to memset.
+ */
+ CBOZ_ALT(12, "j .Lno_zicboz", "nop")
+
+ lw a1, riscv_cboz_block_size
+ add a2, a0, a2
+.Lzero_loop:
+ CBO_zero(a0)
+ add a0, a0, a1
+ CBOZ_ALT(11, "bltu a0, a2, .Lzero_loop; ret", "nop; nop")
+ CBO_zero(a0)
+ add a0, a0, a1
+ CBOZ_ALT(10, "bltu a0, a2, .Lzero_loop; ret", "nop; nop")
+ CBO_zero(a0)
+ add a0, a0, a1
+ CBO_zero(a0)
+ add a0, a0, a1
+ CBOZ_ALT(9, "bltu a0, a2, .Lzero_loop; ret", "nop; nop")
+ CBO_zero(a0)
+ add a0, a0, a1
+ CBO_zero(a0)
+ add a0, a0, a1
+ CBO_zero(a0)
+ add a0, a0, a1
+ CBO_zero(a0)
+ add a0, a0, a1
+ CBOZ_ALT(8, "bltu a0, a2, .Lzero_loop; ret", "nop; nop")
+ CBO_zero(a0)
+ add a0, a0, a1
+ CBO_zero(a0)
+ add a0, a0, a1
+ CBO_zero(a0)
+ add a0, a0, a1
+ CBO_zero(a0)
+ add a0, a0, a1
+ CBO_zero(a0)
+ add a0, a0, a1
+ CBO_zero(a0)
+ add a0, a0, a1
+ CBO_zero(a0)
+ add a0, a0, a1
+ CBO_zero(a0)
+ add a0, a0, a1
+ bltu a0, a2, .Lzero_loop
+ ret
+.Lno_zicboz:
+ li a1, 0
+ tail __memset
+SYM_FUNC_END(clear_page)
+EXPORT_SYMBOL(clear_page)
--
2.39.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
next prev parent reply other threads:[~2023-02-24 17:31 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-02-24 16:26 [PATCH v6 0/8] RISC-V: Apply Zicboz to clear_page Andrew Jones
2023-02-24 16:26 ` [PATCH v6 1/8] RISC-V: alternatives: Support patching multiple insns in assembly Andrew Jones
2023-02-24 16:26 ` [PATCH v6 2/8] RISC-V: Factor out body of riscv_init_cbom_blocksize loop Andrew Jones
2023-02-24 16:26 ` [PATCH v6 3/8] dt-bindings: riscv: Document cboz-block-size Andrew Jones
2023-02-24 16:26 ` [PATCH v6 4/8] RISC-V: Add Zicboz detection and block size parsing Andrew Jones
2023-02-24 16:26 ` [PATCH v6 5/8] RISC-V: cpufeatures: Put the upper 16 bits of patch ID to work Andrew Jones
2023-02-24 16:26 ` Andrew Jones [this message]
2023-02-24 16:26 ` [PATCH v6 7/8] RISC-V: KVM: Provide UAPI for Zicboz block size Andrew Jones
2023-02-24 16:26 ` [PATCH v6 8/8] RISC-V: KVM: Expose Zicboz to the guest Andrew Jones
2023-03-15 4:38 ` Palmer Dabbelt
2023-03-15 4:54 ` Anup Patel
2023-03-15 4:35 ` [PATCH v6 0/8] RISC-V: Apply Zicboz to clear_page Palmer Dabbelt
2023-03-15 8:53 ` Andrew Jones
2023-03-18 1:00 ` patchwork-bot+linux-riscv
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230224162631.405473-7-ajones@ventanamicro.com \
--to=ajones@ventanamicro.com \
--cc=aou@eecs.berkeley.edu \
--cc=apatel@ventanamicro.com \
--cc=atishp@rivosinc.com \
--cc=ben.dooks@codethink.co.uk \
--cc=conor.dooley@microchip.com \
--cc=devicetree@vger.kernel.org \
--cc=heiko@sntech.de \
--cc=jszhang@kernel.org \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=kvm-riscv@lists.infradead.org \
--cc=linux-riscv@lists.infradead.org \
--cc=palmer@dabbelt.com \
--cc=paul.walmsley@sifive.com \
--cc=robh@kernel.org \
--cc=sudip.mukherjee@codethink.co.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox