xref: /freebsd/sys/riscv/thead/thead.c (revision dfe57951f0610c6de42190b32c7ed844a97ee593)
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 /* ----------------- dcache ops --------------------- */
36 
37 
38 /* th.dcache.civa: clean & invalidate at VA stored in t0. */
39 #define	THEAD_DCACHE_CIVA	".long 0x0272800b\n"
40 
41 /* th.dcache.iva: invalidate at VA stored in t0. */
42 #define	THEAD_DCACHE_IVA	".long 0x0262800b\n"
43 
44 /* th.dcache.cva: clean at VA stored in t0. */
45 #define	THEAD_DCACHE_CVA	".long 0x0252800b\n"
46 
47 /* th.sync.s: two-way instruction barrier */
48 #define	THEAD_SYNC_S		".long 0x0190000b\n"
49 
50 /* MHTODO: we could parse this information from the device tree. */
51 #define	THEAD_DCACHE_SIZE	64
52 
53 static void
54 thead_cpu_dcache_wbinv_range(vm_offset_t va, vm_size_t len)
55 {
56 	register vm_offset_t t0 __asm("t0") = rounddown(va, dcache_line_size);
57 
58 	for (; t0 < va + len; t0 += dcache_line_size) {
59 		__asm __volatile(THEAD_DCACHE_CIVA
60 		                 :: "r" (t0) : "memory");
61 	}
62 	__asm __volatile(THEAD_SYNC_S ::: "memory");
63 }
64 
65 static void
66 thead_cpu_dcache_inv_range(vm_offset_t va, vm_size_t len)
67 {
68 	register vm_offset_t t0 __asm("t0") = rounddown(va, dcache_line_size);
69 
70 	for (; t0 < va + len; t0 += dcache_line_size) {
71 		__asm __volatile(THEAD_DCACHE_IVA
72 				 :: "r" (t0) : "memory");
73 	}
74 	__asm __volatile(THEAD_SYNC_S ::: "memory");
75 }
76 
77 static void
78 thead_cpu_dcache_wb_range(vm_offset_t va, vm_size_t len)
79 {
80 	register vm_offset_t t0 __asm("t0") = rounddown(va, dcache_line_size);
81 
82 	for (; t0 < va + len; t0 += dcache_line_size) {
83 		__asm __volatile(THEAD_DCACHE_CVA
84 				 :: "r" (t0) : "memory");
85 	}
86 	__asm __volatile(THEAD_SYNC_S ::: "memory");
87 }
88 
89 void
90 thead_setup_cache(void)
91 {
92 	struct riscv_cache_ops thead_ops;
93 
94 	thead_ops.dcache_wbinv_range = thead_cpu_dcache_wbinv_range;
95 	thead_ops.dcache_inv_range = thead_cpu_dcache_inv_range;
96 	thead_ops.dcache_wb_range = thead_cpu_dcache_wb_range;
97 
98 	riscv_cache_install_hooks(&thead_ops, THEAD_DCACHE_SIZE);
99 }
100