git: dfe57951f061 - main - riscv: add custom T-HEAD dcache ops
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 25 Nov 2024 21:08:46 UTC
The branch main has been updated by mhorne: URL: https://cgit.FreeBSD.org/src/commit/?id=dfe57951f0610c6de42190b32c7ed844a97ee593 commit dfe57951f0610c6de42190b32c7ed844a97ee593 Author: Mitchell Horne <mhorne@FreeBSD.org> AuthorDate: 2024-11-21 18:11:51 +0000 Commit: Mitchell Horne <mhorne@FreeBSD.org> CommitDate: 2024-11-25 21:08:04 +0000 riscv: add custom T-HEAD dcache ops This is the first major quirk we need to support in order to run on current T-HEAD/XuanTie CPUs, e.g. the C906 or C910, found in several existing RISC-V SBCs. With these custom dcache routines installed, busdma can reliably communicate with devices which are not coherent w.r.t. the CPU's data caches. This patch introduces the first quirk/errata handling functions to identcpu.c, and thus is forced to make some decisions about how this code is structured. It will be amended with the changes that follow in the series, yet I feel the final result is (unavoidably) somewhat clumsy. I expect the CPU identification code will continue to evolve as more CPUs and their quirks are eventually supported. Discussed with: jrtc27 Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D47455 --- sys/conf/files.riscv | 2 + sys/riscv/include/thead.h | 35 ++++++++++++++++ sys/riscv/riscv/identcpu.c | 21 ++++++++++ sys/riscv/thead/thead.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 157 insertions(+) diff --git a/sys/conf/files.riscv b/sys/conf/files.riscv index 915bce34603d..6186ae9b3371 100644 --- a/sys/conf/files.riscv +++ b/sys/conf/files.riscv @@ -84,5 +84,7 @@ riscv/vmm/vmm_riscv.c optional vmm 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 index 000000000000..e11d5c37374c --- /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 <mhorne@FreeBSD.org> 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 index 7823830c3136..f85aed88d3b9 100644 --- a/sys/riscv/riscv/identcpu.c +++ b/sys/riscv/riscv/identcpu.c @@ -52,6 +52,7 @@ #include <machine/cpufunc.h> #include <machine/elf.h> #include <machine/md_var.h> +#include <machine/thead.h> #ifdef FDT #include <dev/fdt/fdt_common.h> @@ -463,6 +464,25 @@ identify_cpu_ids(struct cpu_desc *desc) } } +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(u_int cpu) 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 index 000000000000..f959d32cfed8 --- /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 <mhorne@FreeBSD.org> 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 <sys/param.h> +#include <sys/systm.h> + +#include <machine/thead.h> + +/* ----------------- 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); +}