diff --git a/sys/conf/files.riscv b/sys/conf/files.riscv --- a/sys/conf/files.riscv +++ b/sys/conf/files.riscv @@ -84,5 +84,7 @@ riscv/vmm/vmm_sbi.c optional vmm riscv/vmm/vmm_switch.S optional vmm +riscv/thead/thead.c standard + # Zstd contrib/zstd/lib/freebsd/zstd_kfreebsd.c optional zstdio compile-with ${ZSTD_C} diff --git a/sys/riscv/include/thead.h b/sys/riscv/include/thead.h new file mode 100644 --- /dev/null +++ b/sys/riscv/include/thead.h @@ -0,0 +1,35 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 The FreeBSD Foundation + * + * This software was developed by Mitchell Horne under + * sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _RISCV_THEAD_H_ +#define _RISCV_THEAD_H_ + +void thead_setup_cache(void); + +#endif /* _RISCV_THEAD_H_ */ diff --git a/sys/riscv/riscv/identcpu.c b/sys/riscv/riscv/identcpu.c --- a/sys/riscv/riscv/identcpu.c +++ b/sys/riscv/riscv/identcpu.c @@ -52,6 +52,7 @@ #include #include #include +#include #ifdef FDT #include @@ -463,6 +464,25 @@ } } +static void +handle_thead_quirks(u_int cpu, struct cpu_desc *desc) +{ + if (cpu != 0) + return; + + thead_setup_cache(); +} + +static void +handle_cpu_quirks(u_int cpu, struct cpu_desc *desc) +{ + switch (mvendorid) { + case MVENDORID_THEAD: + handle_thead_quirks(cpu, desc); + break; + } +} + void identify_cpu(u_int cpu) { @@ -472,6 +492,7 @@ identify_cpu_features(cpu, desc); update_global_capabilities(cpu, desc); + handle_cpu_quirks(cpu, desc); } void diff --git a/sys/riscv/thead/thead.c b/sys/riscv/thead/thead.c new file mode 100644 --- /dev/null +++ b/sys/riscv/thead/thead.c @@ -0,0 +1,99 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 The FreeBSD Foundation + * + * This software was developed by Mitchell Horne under + * sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include +#include + +#include + +/* ----------------- dcache ops --------------------- */ + + +/* th.dcache.civa: clean & invalidate at VA stored in t0. */ +#define THEAD_DCACHE_CIVA ".long 0x0272800b\n" + +/* th.dcache.iva: invalidate at VA stored in t0. */ +#define THEAD_DCACHE_IVA ".long 0x0262800b\n" + +/* th.dcache.cva: clean at VA stored in t0. */ +#define THEAD_DCACHE_CVA ".long 0x0252800b\n" + +/* th.sync.s: two-way instruction barrier */ +#define THEAD_SYNC_S ".long 0x0190000b\n" + +/* MHTODO: we could parse this information from the device tree. */ +#define THEAD_DCACHE_SIZE 64 + +static void +thead_cpu_dcache_wbinv_range(vm_offset_t va, vm_size_t len) +{ + register vm_offset_t t0 __asm("t0") = rounddown(va, dcache_line_size); + + for (; t0 < va + len; t0 += dcache_line_size) { + __asm __volatile(THEAD_DCACHE_CIVA + :: "r" (t0) : "memory"); + } + __asm __volatile(THEAD_SYNC_S ::: "memory"); +} + +static void +thead_cpu_dcache_inv_range(vm_offset_t va, vm_size_t len) +{ + register vm_offset_t t0 __asm("t0") = rounddown(va, dcache_line_size); + + for (; t0 < va + len; t0 += dcache_line_size) { + __asm __volatile(THEAD_DCACHE_IVA + :: "r" (t0) : "memory"); + } + __asm __volatile(THEAD_SYNC_S ::: "memory"); +} + +static void +thead_cpu_dcache_wb_range(vm_offset_t va, vm_size_t len) +{ + register vm_offset_t t0 __asm("t0") = rounddown(va, dcache_line_size); + + for (; t0 < va + len; t0 += dcache_line_size) { + __asm __volatile(THEAD_DCACHE_CVA + :: "r" (t0) : "memory"); + } + __asm __volatile(THEAD_SYNC_S ::: "memory"); +} + +void +thead_setup_cache(void) +{ + struct riscv_cache_ops thead_ops; + + thead_ops.dcache_wbinv_range = thead_cpu_dcache_wbinv_range; + thead_ops.dcache_inv_range = thead_cpu_dcache_inv_range; + thead_ops.dcache_wb_range = thead_cpu_dcache_wb_range; + + riscv_cache_install_hooks(&thead_ops, THEAD_DCACHE_SIZE); +}