xref: /netbsd-src/sys/arch/powerpc/booke/booke_cache.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: booke_cache.c,v 1.4 2011/06/29 21:53:10 dholland 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  *
38  */
39 #include <sys/cdefs.h>
40 
41 __KERNEL_RCSID(0, "$NetBSD: booke_cache.c,v 1.4 2011/06/29 21:53:10 dholland Exp $");
42 
43 #include <sys/param.h>
44 #include <sys/cpu.h>
45 #include <sys/atomic.h>
46 
47 enum cache_op { OP_DCBF, OP_DCBST, OP_DCBI, OP_DCBZ, OP_DCBA, OP_ICBI };
48 
49 static void inline
50 dcbf(vaddr_t va, vsize_t off)
51 {
52 	__asm volatile("dcbf\t%0,%1" : : "b" (va), "r" (off));
53 }
54 
55 static void inline
56 dcbst(vaddr_t va, vsize_t off)
57 {
58 	__asm volatile("dcbst\t%0,%1" : : "b" (va), "r" (off));
59 }
60 
61 static void inline
62 dcbi(vaddr_t va, vsize_t off)
63 {
64 	__asm volatile("dcbi\t%0,%1" : : "b" (va), "r" (off));
65 }
66 
67 static void inline
68 dcbz(vaddr_t va, vsize_t off)
69 {
70 	__asm volatile("dcbz\t%0,%1" : : "b" (va), "r" (off));
71 }
72 
73 static void inline
74 dcba(vaddr_t va, vsize_t off)
75 {
76 	__asm volatile("dcba\t%0,%1" : : "b" (va), "r" (off));
77 }
78 
79 static void inline
80 icbi(vaddr_t va, vsize_t off)
81 {
82 	__asm volatile("icbi\t%0,%1" : : "b" (va), "r" (off));
83 }
84 
85 static inline void
86 cache_op(vaddr_t va, vsize_t len, vsize_t line_size, enum cache_op op)
87 {
88 	KASSERT(line_size > 0);
89 
90 	if (len == 0)
91 		return;
92 
93 	/* Make sure we flush all cache lines */
94 	len += va & (line_size - 1);
95 	va &= -line_size;
96 
97 	for (vsize_t i = 0; i < len; i += line_size) {
98 		switch (op) {
99 		case OP_DCBF: dcbf(va, i); break;
100 		case OP_DCBST: dcbst(va, i); break;
101 		case OP_DCBI: dcbi(va, i); break;
102 		case OP_DCBZ: dcbz(va, i); break;
103 		case OP_DCBA: dcba(va, i); break;
104 		case OP_ICBI: icbi(va, i); break;
105 		}
106 	}
107 	if (op != OP_ICBI)
108 		membar_producer();
109 }
110 
111 void
112 dcache_wb_page(vaddr_t va)
113 {
114 	cache_op(va, PAGE_SIZE, curcpu()->ci_ci.dcache_line_size, OP_DCBST);
115 }
116 
117 void
118 dcache_wbinv_page(vaddr_t va)
119 {
120 	cache_op(va, PAGE_SIZE, curcpu()->ci_ci.dcache_line_size, OP_DCBF);
121 }
122 
123 void
124 dcache_inv_page(vaddr_t va)
125 {
126 	cache_op(va, PAGE_SIZE, curcpu()->ci_ci.dcache_line_size, OP_DCBI);
127 }
128 
129 void
130 dcache_zero_page(vaddr_t va)
131 {
132 	cache_op(va, PAGE_SIZE, curcpu()->ci_ci.dcache_line_size, OP_DCBZ);
133 }
134 
135 void
136 icache_inv_page(vaddr_t va)
137 {
138 	membar_sync();
139 	cache_op(va, PAGE_SIZE, curcpu()->ci_ci.icache_line_size, OP_ICBI);
140 	membar_sync();
141 	/* synchronizing instruction will be the rfi to user mode */
142 }
143 
144 void
145 dcache_wb(vaddr_t va, vsize_t len)
146 {
147 	cache_op(va, len, curcpu()->ci_ci.dcache_line_size, OP_DCBST);
148 }
149 
150 void
151 dcache_wbinv(vaddr_t va, vsize_t len)
152 {
153 	cache_op(va, len, curcpu()->ci_ci.dcache_line_size, OP_DCBF);
154 }
155 
156 void
157 dcache_inv(vaddr_t va, vsize_t len)
158 {
159 	cache_op(va, len, curcpu()->ci_ci.dcache_line_size, OP_DCBI);
160 }
161 
162 void
163 icache_inv(vaddr_t va, vsize_t len)
164 {
165 	membar_sync();
166 	cache_op(va, len, curcpu()->ci_ci.icache_line_size, OP_ICBI);
167 	membar_sync();
168 }
169