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