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