1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 1998 Doug Rabson 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #ifndef _MACHINE_CPUFUNC_H_ 32 #define _MACHINE_CPUFUNC_H_ 33 34 #ifdef _KERNEL 35 36 #include <sys/types.h> 37 38 #include <machine/psl.h> 39 #include <machine/spr.h> 40 41 struct thread; 42 43 #ifdef KDB 44 void breakpoint(void); 45 #else 46 static __inline void 47 breakpoint(void) 48 { 49 50 return; 51 } 52 #endif 53 54 /* CPU register mangling inlines */ 55 56 static __inline void 57 mtmsr(register_t value) 58 { 59 60 __asm __volatile ("mtmsr %0; isync" :: "r"(value)); 61 } 62 63 #ifdef __powerpc64__ 64 static __inline void 65 mtmsrd(register_t value) 66 { 67 68 __asm __volatile ("mtmsrd %0; isync" :: "r"(value)); 69 } 70 #endif 71 72 static __inline register_t 73 mfmsr(void) 74 { 75 register_t value; 76 77 __asm __volatile ("mfmsr %0" : "=r"(value)); 78 79 return (value); 80 } 81 82 #ifndef __powerpc64__ 83 static __inline void 84 mtsrin(vm_offset_t va, register_t value) 85 { 86 87 __asm __volatile ("mtsrin %0,%1; isync" :: "r"(value), "r"(va)); 88 } 89 90 static __inline register_t 91 mfsrin(vm_offset_t va) 92 { 93 register_t value; 94 95 __asm __volatile ("mfsrin %0,%1" : "=r"(value) : "r"(va)); 96 97 return (value); 98 } 99 #endif 100 101 static __inline register_t 102 mfctrl(void) 103 { 104 register_t value; 105 106 __asm __volatile ("mfspr %0,136" : "=r"(value)); 107 108 return (value); 109 } 110 111 112 static __inline void 113 mtdec(register_t value) 114 { 115 116 __asm __volatile ("mtdec %0" :: "r"(value)); 117 } 118 119 static __inline register_t 120 mfdec(void) 121 { 122 register_t value; 123 124 __asm __volatile ("mfdec %0" : "=r"(value)); 125 126 return (value); 127 } 128 129 static __inline register_t 130 mfpvr(void) 131 { 132 register_t value; 133 134 __asm __volatile ("mfpvr %0" : "=r"(value)); 135 136 return (value); 137 } 138 139 static __inline u_quad_t 140 mftb(void) 141 { 142 u_quad_t tb; 143 #ifdef __powerpc64__ 144 __asm __volatile ("mftb %0" : "=r"(tb)); 145 #else 146 uint32_t *tbup = (uint32_t *)&tb; 147 uint32_t *tblp = tbup + 1; 148 149 do { 150 *tbup = mfspr(TBR_TBU); 151 *tblp = mfspr(TBR_TBL); 152 } while (*tbup != mfspr(TBR_TBU)); 153 #endif 154 155 return (tb); 156 } 157 158 static __inline void 159 mttb(u_quad_t time) 160 { 161 162 mtspr(TBR_TBWL, 0); 163 mtspr(TBR_TBWU, (uint32_t)(time >> 32)); 164 mtspr(TBR_TBWL, (uint32_t)(time & 0xffffffff)); 165 } 166 167 static __inline void 168 eieio(void) 169 { 170 171 __asm __volatile ("eieio" : : : "memory"); 172 } 173 174 static __inline void 175 isync(void) 176 { 177 178 __asm __volatile ("isync" : : : "memory"); 179 } 180 181 static __inline void 182 powerpc_sync(void) 183 { 184 185 __asm __volatile ("sync" : : : "memory"); 186 } 187 188 static __inline int 189 cntlzd(uint64_t word) 190 { 191 uint64_t result; 192 /* cntlzd %0, %1 */ 193 __asm __volatile(".long 0x7c000074 | (%1 << 21) | (%0 << 16)" : 194 "=r"(result) : "r"(word)); 195 196 return (int)result; 197 } 198 199 static __inline int 200 cnttzd(uint64_t word) 201 { 202 uint64_t result; 203 /* cnttzd %0, %1 */ 204 __asm __volatile(".long 0x7c000474 | (%1 << 21) | (%0 << 16)" : 205 "=r"(result) : "r"(word)); 206 207 return (int)result; 208 } 209 210 static __inline void 211 ptesync(void) 212 { 213 __asm __volatile("ptesync"); 214 } 215 216 static __inline register_t 217 intr_disable(void) 218 { 219 register_t msr; 220 221 msr = mfmsr(); 222 mtmsr(msr & ~PSL_EE); 223 return (msr); 224 } 225 226 static __inline void 227 intr_restore(register_t msr) 228 { 229 230 mtmsr(msr); 231 } 232 233 static __inline struct pcpu * 234 get_pcpu(void) 235 { 236 struct pcpu *ret; 237 238 __asm __volatile("mfsprg %0, 0" : "=r"(ret)); 239 240 return (ret); 241 } 242 243 #define HAVE_INLINE_FLS 244 static __inline __pure2 int 245 fls(int mask) 246 { 247 return (mask ? 32 - __builtin_clz(mask) : 0); 248 } 249 250 #define HAVE_INLINE_FLSL 251 static __inline __pure2 int 252 flsl(long mask) 253 { 254 return (mask ? (8 * sizeof(long) - __builtin_clzl(mask)) : 0); 255 } 256 257 /* "NOP" operations to signify priorities to the kernel. */ 258 static __inline void 259 nop_prio_vlow(void) 260 { 261 __asm __volatile("or 31,31,31"); 262 } 263 264 static __inline void 265 nop_prio_low(void) 266 { 267 __asm __volatile("or 1,1,1"); 268 } 269 270 static __inline void 271 nop_prio_mlow(void) 272 { 273 __asm __volatile("or 6,6,6"); 274 } 275 276 static __inline void 277 nop_prio_medium(void) 278 { 279 __asm __volatile("or 2,2,2"); 280 } 281 282 static __inline void 283 nop_prio_mhigh(void) 284 { 285 __asm __volatile("or 5,5,5"); 286 } 287 288 static __inline void 289 nop_prio_high(void) 290 { 291 __asm __volatile("or 3,3,3"); 292 } 293 294 #endif /* _KERNEL */ 295 296 #endif /* !_MACHINE_CPUFUNC_H_ */ 297