1/*	$NetBSD: booke_cache.c,v 1.5 2020/07/06 09:34:16 rin Exp $	*/
2/*-
3 * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Raytheon BBN Technologies Corp and Defense Advanced Research Projects
8 * Agency and which was developed by Matt Thomas of 3am Software Foundry.
9 *
10 * This material is based upon work supported by the Defense Advanced Research
11 * Projects Agency and Space and Naval Warfare Systems Center, Pacific, under
12 * Contract No. N66001-09-C-2073.
13 * Approved for Public Release, Distribution Unlimited
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
28 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include <sys/cdefs.h>
38__KERNEL_RCSID(0, "$NetBSD: booke_cache.c,v 1.5 2020/07/06 09:34:16 rin Exp $");
39
40#include <sys/param.h>
41#include <sys/cpu.h>
42#include <sys/atomic.h>
43
44enum cache_op { OP_DCBF, OP_DCBST, OP_DCBI, OP_DCBZ, OP_DCBA, OP_ICBI };
45
46static void inline
47dcbf(vaddr_t va, vsize_t off)
48{
49	__asm volatile("dcbf\t%0,%1" : : "b" (va), "r" (off));
50}
51
52static void inline
53dcbst(vaddr_t va, vsize_t off)
54{
55	__asm volatile("dcbst\t%0,%1" : : "b" (va), "r" (off));
56}
57
58static void inline
59dcbi(vaddr_t va, vsize_t off)
60{
61	__asm volatile("dcbi\t%0,%1" : : "b" (va), "r" (off));
62}
63
64static void inline
65dcbz(vaddr_t va, vsize_t off)
66{
67	__asm volatile("dcbz\t%0,%1" : : "b" (va), "r" (off));
68}
69
70static void inline
71dcba(vaddr_t va, vsize_t off)
72{
73	__asm volatile("dcba\t%0,%1" : : "b" (va), "r" (off));
74}
75
76static void inline
77icbi(vaddr_t va, vsize_t off)
78{
79	__asm volatile("icbi\t%0,%1" : : "b" (va), "r" (off));
80}
81
82static inline void
83cache_op(vaddr_t va, vsize_t len, vsize_t line_size, enum cache_op op)
84{
85	KASSERT(line_size > 0);
86
87	if (len == 0)
88		return;
89
90	/* Make sure we flush all cache lines */
91	len += va & (line_size - 1);
92	va &= -line_size;
93
94	for (vsize_t i = 0; i < len; i += line_size) {
95		switch (op) {
96		case OP_DCBF: dcbf(va, i); break;
97		case OP_DCBST: dcbst(va, i); break;
98		case OP_DCBI: dcbi(va, i); break;
99		case OP_DCBZ: dcbz(va, i); break;
100		case OP_DCBA: dcba(va, i); break;
101		case OP_ICBI: icbi(va, i); break;
102		}
103	}
104	if (op != OP_ICBI)
105		membar_producer();
106}
107
108void
109dcache_wb_page(vaddr_t va)
110{
111	cache_op(va, PAGE_SIZE, curcpu()->ci_ci.dcache_line_size, OP_DCBST);
112}
113
114void
115dcache_wbinv_page(vaddr_t va)
116{
117	cache_op(va, PAGE_SIZE, curcpu()->ci_ci.dcache_line_size, OP_DCBF);
118}
119
120void
121dcache_inv_page(vaddr_t va)
122{
123	cache_op(va, PAGE_SIZE, curcpu()->ci_ci.dcache_line_size, OP_DCBI);
124}
125
126void
127dcache_zero_page(vaddr_t va)
128{
129	cache_op(va, PAGE_SIZE, curcpu()->ci_ci.dcache_line_size, OP_DCBZ);
130}
131
132void
133icache_inv_page(vaddr_t va)
134{
135	membar_sync();
136	cache_op(va, PAGE_SIZE, curcpu()->ci_ci.icache_line_size, OP_ICBI);
137	membar_sync();
138	/* synchronizing instruction will be the rfi to user mode */
139}
140
141void
142dcache_wb(vaddr_t va, vsize_t len)
143{
144	cache_op(va, len, curcpu()->ci_ci.dcache_line_size, OP_DCBST);
145}
146
147void
148dcache_wbinv(vaddr_t va, vsize_t len)
149{
150	cache_op(va, len, curcpu()->ci_ci.dcache_line_size, OP_DCBF);
151}
152
153void
154dcache_inv(vaddr_t va, vsize_t len)
155{
156	cache_op(va, len, curcpu()->ci_ci.dcache_line_size, OP_DCBI);
157}
158
159void
160icache_inv(vaddr_t va, vsize_t len)
161{
162	membar_sync();
163	cache_op(va, len, curcpu()->ci_ci.icache_line_size, OP_ICBI);
164	membar_sync();
165}
166