1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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 29 #ifndef _MACHINE_CPUFUNC_H_ 30 #define _MACHINE_CPUFUNC_H_ 31 32 #ifdef _KERNEL 33 34 #include <sys/types.h> 35 36 #include <machine/psl.h> 37 #include <machine/spr.h> 38 39 struct thread; 40 41 #ifdef KDB 42 void breakpoint(void); 43 #else 44 static __inline void 45 breakpoint(void) 46 { 47 48 return; 49 } 50 #endif 51 52 /* CPU register mangling inlines */ 53 54 static __inline void 55 mtmsr(register_t value) 56 { 57 58 __asm __volatile ("mtmsr %0; isync" :: "r"(value)); 59 } 60 61 #ifdef __powerpc64__ 62 static __inline void 63 mtmsrd(register_t value) 64 { 65 66 __asm __volatile ("mtmsrd %0; isync" :: "r"(value)); 67 } 68 #endif 69 70 static __inline register_t 71 mfmsr(void) 72 { 73 register_t value; 74 75 __asm __volatile ("mfmsr %0" : "=r"(value)); 76 77 return (value); 78 } 79 80 #ifndef __powerpc64__ 81 static __inline void 82 mtsrin(vm_offset_t va, register_t value) 83 { 84 85 __asm __volatile ("mtsrin %0,%1; isync" :: "r"(value), "r"(va)); 86 } 87 88 static __inline register_t 89 mfsrin(vm_offset_t va) 90 { 91 register_t value; 92 93 __asm __volatile ("mfsrin %0,%1" : "=r"(value) : "r"(va)); 94 95 return (value); 96 } 97 #endif 98 99 static __inline register_t 100 mfctrl(void) 101 { 102 register_t value; 103 104 __asm __volatile ("mfspr %0,136" : "=r"(value)); 105 106 return (value); 107 } 108 109 static __inline void 110 mtdec(register_t value) 111 { 112 113 __asm __volatile ("mtdec %0" :: "r"(value)); 114 } 115 116 static __inline register_t 117 mfdec(void) 118 { 119 register_t value; 120 121 __asm __volatile ("mfdec %0" : "=r"(value)); 122 123 return (value); 124 } 125 126 static __inline uint32_t 127 mfpvr(void) 128 { 129 uint32_t value; 130 131 __asm __volatile ("mfpvr %0" : "=r"(value)); 132 133 return (value); 134 } 135 136 static __inline u_quad_t 137 mftb(void) 138 { 139 u_quad_t tb; 140 #ifdef __powerpc64__ 141 __asm __volatile ("mftb %0" : "=r"(tb)); 142 #else 143 uint32_t *tbup = (uint32_t *)&tb; 144 uint32_t *tblp = tbup + 1; 145 146 do { 147 *tbup = mfspr(TBR_TBU); 148 *tblp = mfspr(TBR_TBL); 149 } while (*tbup != mfspr(TBR_TBU)); 150 #endif 151 152 return (tb); 153 } 154 155 static __inline void 156 mttb(u_quad_t time) 157 { 158 159 mtspr(TBR_TBWL, 0); 160 mtspr(TBR_TBWU, (uint32_t)(time >> 32)); 161 mtspr(TBR_TBWL, (uint32_t)(time & 0xffffffff)); 162 } 163 164 static __inline register_t 165 mffs(void) 166 { 167 uint64_t value; 168 169 __asm __volatile ("mffs 0; stfd 0,0(%0)" 170 :: "b"(&value)); 171 172 return ((register_t)value); 173 } 174 175 static __inline void 176 mtfsf(uint64_t value) 177 { 178 179 __asm __volatile ("lfd 0,0(%0); mtfsf 0xff,0" 180 :: "b"(&value)); 181 } 182 183 static __inline void 184 eieio(void) 185 { 186 187 __asm __volatile ("eieio" : : : "memory"); 188 } 189 190 static __inline void 191 isync(void) 192 { 193 194 __asm __volatile ("isync" : : : "memory"); 195 } 196 197 static __inline void 198 powerpc_sync(void) 199 { 200 201 __asm __volatile ("sync" : : : "memory"); 202 } 203 204 static __inline int 205 cntlzd(uint64_t word) 206 { 207 uint64_t result; 208 /* cntlzd %0, %1 */ 209 __asm __volatile(".long 0x7c000074 | (%1 << 21) | (%0 << 16)" : 210 "=r"(result) : "r"(word)); 211 212 return (int)result; 213 } 214 215 static __inline int 216 cnttzd(uint64_t word) 217 { 218 uint64_t result; 219 /* cnttzd %0, %1 */ 220 __asm __volatile(".long 0x7c000474 | (%1 << 21) | (%0 << 16)" : 221 "=r"(result) : "r"(word)); 222 223 return (int)result; 224 } 225 226 static __inline void 227 ptesync(void) 228 { 229 __asm __volatile("ptesync"); 230 } 231 232 static __inline register_t 233 intr_disable(void) 234 { 235 register_t msr; 236 237 msr = mfmsr(); 238 mtmsr(msr & ~PSL_EE); 239 return (msr); 240 } 241 242 static __inline void 243 intr_restore(register_t msr) 244 { 245 246 mtmsr(msr); 247 } 248 249 static __inline struct pcpu * 250 get_pcpu(void) 251 { 252 struct pcpu *ret; 253 254 __asm __volatile("mfsprg %0, 0" : "=r"(ret)); 255 256 return (ret); 257 } 258 259 /* "NOP" operations to signify priorities to the kernel. */ 260 static __inline void 261 nop_prio_vlow(void) 262 { 263 __asm __volatile("or 31,31,31"); 264 } 265 266 static __inline void 267 nop_prio_low(void) 268 { 269 __asm __volatile("or 1,1,1"); 270 } 271 272 static __inline void 273 nop_prio_mlow(void) 274 { 275 __asm __volatile("or 6,6,6"); 276 } 277 278 static __inline void 279 nop_prio_medium(void) 280 { 281 __asm __volatile("or 2,2,2"); 282 } 283 284 static __inline void 285 nop_prio_mhigh(void) 286 { 287 __asm __volatile("or 5,5,5"); 288 } 289 290 static __inline void 291 nop_prio_high(void) 292 { 293 __asm __volatile("or 3,3,3"); 294 } 295 296 #endif /* _KERNEL */ 297 298 #endif /* !_MACHINE_CPUFUNC_H_ */ 299