summaryrefslogtreecommitdiffstats
path: root/sys/arm64
diff options
context:
space:
mode:
authorwma <wma@FreeBSD.org>2016-04-04 07:06:20 +0000
committerwma <wma@FreeBSD.org>2016-04-04 07:06:20 +0000
commit4ba80483c09bada259d55bd321495c2af37bd702 (patch)
treedad55237167913057688cc56eefbc929fbbd34f8 /sys/arm64
parent725da9cdbc9e08a7b74413f6700d80c296358e81 (diff)
downloadFreeBSD-src-4ba80483c09bada259d55bd321495c2af37bd702.zip
FreeBSD-src-4ba80483c09bada259d55bd321495c2af37bd702.tar.gz
arm64: bzero optimization
This optimization attempts to utylize as wide as possible register store instructions to zero large buffers. The implementation, if possible, will use 'dc zva' to zero buffer by cache lines. Speedup: 60x faster memory zeroing Submitted by: Dominik Ermel <der@semihalf.com> Obtained from: Semihalf Sponsored by: Cavium Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D5726
Diffstat (limited to 'sys/arm64')
-rw-r--r--sys/arm64/arm64/machdep.c25
-rw-r--r--sys/arm64/include/armreg.h6
2 files changed, 20 insertions, 11 deletions
diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c
index 768d223..0ab4498 100644
--- a/sys/arm64/arm64/machdep.c
+++ b/sys/arm64/arm64/machdep.c
@@ -108,6 +108,7 @@ struct kva_md_info kmi;
int64_t dcache_line_size; /* The minimum D cache line size */
int64_t icache_line_size; /* The minimum I cache line size */
int64_t idcache_line_size; /* The minimum cache line size */
+int64_t dczva_line_size; /* The size of cache line the dc zva zeroes */
static void
cpu_startup(void *dummy)
@@ -129,16 +130,6 @@ cpu_idle_wakeup(int cpu)
return (0);
}
-void
-bzero(void *buf, size_t len)
-{
- uint8_t *p;
-
- p = buf;
- while(len-- > 0)
- *p++ = 0;
-}
-
int
fill_regs(struct thread *td, struct reg *regs)
{
@@ -800,8 +791,9 @@ try_load_dtb(caddr_t kmdp)
static void
cache_setup(void)
{
- int dcache_line_shift, icache_line_shift;
+ int dcache_line_shift, icache_line_shift, dczva_line_shift;
uint32_t ctr_el0;
+ uint32_t dczid_el0;
ctr_el0 = READ_SPECIALREG(ctr_el0);
@@ -815,6 +807,17 @@ cache_setup(void)
icache_line_size = sizeof(int) << icache_line_shift;
idcache_line_size = MIN(dcache_line_size, icache_line_size);
+
+ dczid_el0 = READ_SPECIALREG(dczid_el0);
+
+ /* Check if dc zva is not prohibited */
+ if (dczid_el0 & DCZID_DZP)
+ dczva_line_size = 0;
+ else {
+ /* Same as with above calculations */
+ dczva_line_shift = DCZID_BS_SIZE(dczid_el0);
+ dczva_line_size = sizeof(int) << dczva_line_shift;
+ }
}
void
diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h
index 8b2bc92..40d07f0 100644
--- a/sys/arm64/include/armreg.h
+++ b/sys/arm64/include/armreg.h
@@ -66,6 +66,12 @@
#define CTR_ILINE_MASK (0xf << CTR_ILINE_SHIFT)
#define CTR_ILINE_SIZE(reg) (((reg) & CTR_ILINE_MASK) >> CTR_ILINE_SHIFT)
+/* DCZID_EL0 - Data Cache Zero ID register */
+#define DCZID_DZP (1 << 4) /* DC ZVA prohibited if non-0 */
+#define DCZID_BS_SHIFT 0
+#define DCZID_BS_MASK (0xf << DCZID_BS_SHIFT)
+#define DCZID_BS_SIZE(reg) (((reg) & DCZID_BS_MASK) >> DCZID_BS_SHIFT)
+
/* ESR_ELx */
#define ESR_ELx_ISS_MASK 0x00ffffff
#define ISS_INSN_FnV (0x01 << 10)
OpenPOWER on IntegriCloud