1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2024 The FreeBSD Foundation
5 *
6 * This software was developed by Mitchell Horne <mhorne@FreeBSD.org> under
7 * sponsorship from the FreeBSD Foundation.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30 #include <sys/param.h>
31 #include <sys/systm.h>
32
33 #include <machine/thead.h>
34
35 bool has_errata_thead_pbmt = false;
36
37 /* ----------------- dcache ops --------------------- */
38
39
40 /* th.dcache.civa: clean & invalidate at VA stored in t0. */
41 #define THEAD_DCACHE_CIVA ".long 0x0272800b\n"
42
43 /* th.dcache.iva: invalidate at VA stored in t0. */
44 #define THEAD_DCACHE_IVA ".long 0x0262800b\n"
45
46 /* th.dcache.cva: clean at VA stored in t0. */
47 #define THEAD_DCACHE_CVA ".long 0x0252800b\n"
48
49 /* th.sync.s: two-way instruction barrier */
50 #define THEAD_SYNC_S ".long 0x0190000b\n"
51
52 /* MHTODO: we could parse this information from the device tree. */
53 #define THEAD_DCACHE_SIZE 64
54
55 static void
thead_cpu_dcache_wbinv_range(vm_offset_t va,vm_size_t len)56 thead_cpu_dcache_wbinv_range(vm_offset_t va, vm_size_t len)
57 {
58 register vm_offset_t t0 __asm("t0") = rounddown(va, dcache_line_size);
59
60 for (; t0 < va + len; t0 += dcache_line_size) {
61 __asm __volatile(THEAD_DCACHE_CIVA
62 :: "r" (t0) : "memory");
63 }
64 __asm __volatile(THEAD_SYNC_S ::: "memory");
65 }
66
67 static void
thead_cpu_dcache_inv_range(vm_offset_t va,vm_size_t len)68 thead_cpu_dcache_inv_range(vm_offset_t va, vm_size_t len)
69 {
70 register vm_offset_t t0 __asm("t0") = rounddown(va, dcache_line_size);
71
72 for (; t0 < va + len; t0 += dcache_line_size) {
73 __asm __volatile(THEAD_DCACHE_IVA
74 :: "r" (t0) : "memory");
75 }
76 __asm __volatile(THEAD_SYNC_S ::: "memory");
77 }
78
79 static void
thead_cpu_dcache_wb_range(vm_offset_t va,vm_size_t len)80 thead_cpu_dcache_wb_range(vm_offset_t va, vm_size_t len)
81 {
82 register vm_offset_t t0 __asm("t0") = rounddown(va, dcache_line_size);
83
84 for (; t0 < va + len; t0 += dcache_line_size) {
85 __asm __volatile(THEAD_DCACHE_CVA
86 :: "r" (t0) : "memory");
87 }
88 __asm __volatile(THEAD_SYNC_S ::: "memory");
89 }
90
91 void
thead_setup_cache(void)92 thead_setup_cache(void)
93 {
94 struct riscv_cache_ops thead_ops;
95
96 thead_ops.dcache_wbinv_range = thead_cpu_dcache_wbinv_range;
97 thead_ops.dcache_inv_range = thead_cpu_dcache_inv_range;
98 thead_ops.dcache_wb_range = thead_cpu_dcache_wb_range;
99
100 riscv_cache_install_hooks(&thead_ops, THEAD_DCACHE_SIZE);
101 }
102