xref: /freebsd/sys/riscv/thead/thead.c (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
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
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
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
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
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