1 1.111 jmcneill /* $NetBSD: cpu_subr.c,v 1.111 2025/02/17 11:56:56 jmcneill Exp $ */ 2 1.1 matt 3 1.1 matt /*- 4 1.1 matt * Copyright (c) 2001 Matt Thomas. 5 1.1 matt * Copyright (c) 2001 Tsubai Masanari. 6 1.1 matt * Copyright (c) 1998, 1999, 2001 Internet Research Institute, Inc. 7 1.1 matt * All rights reserved. 8 1.1 matt * 9 1.1 matt * Redistribution and use in source and binary forms, with or without 10 1.1 matt * modification, are permitted provided that the following conditions 11 1.1 matt * are met: 12 1.1 matt * 1. Redistributions of source code must retain the above copyright 13 1.1 matt * notice, this list of conditions and the following disclaimer. 14 1.1 matt * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 matt * notice, this list of conditions and the following disclaimer in the 16 1.1 matt * documentation and/or other materials provided with the distribution. 17 1.1 matt * 3. All advertising materials mentioning features or use of this software 18 1.1 matt * must display the following acknowledgement: 19 1.1 matt * This product includes software developed by 20 1.1 matt * Internet Research Institute, Inc. 21 1.1 matt * 4. The name of the author may not be used to endorse or promote products 22 1.1 matt * derived from this software without specific prior written permission. 23 1.1 matt * 24 1.1 matt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 25 1.1 matt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26 1.1 matt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 1.1 matt * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 28 1.1 matt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29 1.1 matt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 1.1 matt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 1.1 matt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 1.1 matt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 1.1 matt * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 1.1 matt */ 35 1.9 lukem 36 1.9 lukem #include <sys/cdefs.h> 37 1.111 jmcneill __KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v 1.111 2025/02/17 11:56:56 jmcneill Exp $"); 38 1.1 matt 39 1.103 rin #include "sysmon_envsys.h" 40 1.103 rin 41 1.103 rin #ifdef _KERNEL_OPT 42 1.103 rin #include "opt_altivec.h" 43 1.103 rin #include "opt_multiprocessor.h" 44 1.104 rin #include "opt_ppcarch.h" 45 1.103 rin #include "opt_ppccache.h" 46 1.1 matt #include "opt_ppcparam.h" 47 1.103 rin #endif 48 1.1 matt 49 1.1 matt #include <sys/param.h> 50 1.1 matt #include <sys/systm.h> 51 1.1 matt #include <sys/device.h> 52 1.33 garbled #include <sys/types.h> 53 1.33 garbled #include <sys/lwp.h> 54 1.56 phx #include <sys/xcall.h> 55 1.1 matt 56 1.59 uebayasi #include <uvm/uvm.h> 57 1.1 matt 58 1.61 matt #include <powerpc/pcb.h> 59 1.67 matt #include <powerpc/psl.h> 60 1.55 matt #include <powerpc/spr.h> 61 1.1 matt #include <powerpc/oea/hid.h> 62 1.1 matt #include <powerpc/oea/hid_601.h> 63 1.55 matt #include <powerpc/oea/spr.h> 64 1.42 garbled #include <powerpc/oea/cpufeat.h> 65 1.1 matt 66 1.1 matt #include <dev/sysmon/sysmonvar.h> 67 1.1 matt 68 1.7 matt static void cpu_enable_l2cr(register_t); 69 1.7 matt static void cpu_enable_l3cr(register_t); 70 1.1 matt static void cpu_config_l2cr(int); 71 1.7 matt static void cpu_config_l3cr(int); 72 1.23 briggs static void cpu_probe_speed(struct cpu_info *); 73 1.20 matt static void cpu_idlespin(void); 74 1.56 phx static void cpu_set_dfs_xcall(void *, void *); 75 1.1 matt #if NSYSMON_ENVSYS > 0 76 1.1 matt static void cpu_tau_setup(struct cpu_info *); 77 1.34 xtraeme static void cpu_tau_refresh(struct sysmon_envsys *, envsys_data_t *); 78 1.1 matt #endif 79 1.1 matt 80 1.95 macallan extern void init_scom_speedctl(void); 81 1.95 macallan 82 1.82 christos int cpu = -1; 83 1.1 matt int ncpus; 84 1.1 matt 85 1.7 matt struct fmttab { 86 1.7 matt register_t fmt_mask; 87 1.7 matt register_t fmt_value; 88 1.7 matt const char *fmt_string; 89 1.7 matt }; 90 1.7 matt 91 1.50 macallan /* 92 1.50 macallan * This should be one per CPU but since we only support it on 750 variants it 93 1.87 snj * doesn't really matter since none of them support SMP 94 1.50 macallan */ 95 1.50 macallan envsys_data_t sensor; 96 1.50 macallan 97 1.7 matt static const struct fmttab cpu_7450_l2cr_formats[] = { 98 1.7 matt { L2CR_L2E, 0, " disabled" }, 99 1.7 matt { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO, " data-only" }, 100 1.7 matt { L2CR_L2DO|L2CR_L2IO, L2CR_L2IO, " instruction-only" }, 101 1.7 matt { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO|L2CR_L2IO, " locked" }, 102 1.7 matt { L2CR_L2E, ~0, " 256KB L2 cache" }, 103 1.36 garbled { L2CR_L2PE, 0, " no parity" }, 104 1.97 uwe { L2CR_L2PE, L2CR_L2PE, " parity enabled" }, 105 1.28 garbled { 0, 0, NULL } 106 1.7 matt }; 107 1.7 matt 108 1.22 matt static const struct fmttab cpu_7448_l2cr_formats[] = { 109 1.22 matt { L2CR_L2E, 0, " disabled" }, 110 1.22 matt { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO, " data-only" }, 111 1.22 matt { L2CR_L2DO|L2CR_L2IO, L2CR_L2IO, " instruction-only" }, 112 1.22 matt { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO|L2CR_L2IO, " locked" }, 113 1.22 matt { L2CR_L2E, ~0, " 1MB L2 cache" }, 114 1.36 garbled { L2CR_L2PE, 0, " no parity" }, 115 1.97 uwe { L2CR_L2PE, L2CR_L2PE, " parity enabled" }, 116 1.28 garbled { 0, 0, NULL } 117 1.22 matt }; 118 1.22 matt 119 1.11 matt static const struct fmttab cpu_7457_l2cr_formats[] = { 120 1.11 matt { L2CR_L2E, 0, " disabled" }, 121 1.11 matt { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO, " data-only" }, 122 1.11 matt { L2CR_L2DO|L2CR_L2IO, L2CR_L2IO, " instruction-only" }, 123 1.11 matt { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO|L2CR_L2IO, " locked" }, 124 1.11 matt { L2CR_L2E, ~0, " 512KB L2 cache" }, 125 1.36 garbled { L2CR_L2PE, 0, " no parity" }, 126 1.97 uwe { L2CR_L2PE, L2CR_L2PE, " parity enabled" }, 127 1.28 garbled { 0, 0, NULL } 128 1.11 matt }; 129 1.11 matt 130 1.7 matt static const struct fmttab cpu_7450_l3cr_formats[] = { 131 1.7 matt { L3CR_L3DO|L3CR_L3IO, L3CR_L3DO, " data-only" }, 132 1.7 matt { L3CR_L3DO|L3CR_L3IO, L3CR_L3IO, " instruction-only" }, 133 1.7 matt { L3CR_L3DO|L3CR_L3IO, L3CR_L3DO|L3CR_L3IO, " locked" }, 134 1.7 matt { L3CR_L3SIZ, L3SIZ_2M, " 2MB" }, 135 1.7 matt { L3CR_L3SIZ, L3SIZ_1M, " 1MB" }, 136 1.7 matt { L3CR_L3PE|L3CR_L3APE, L3CR_L3PE|L3CR_L3APE, " parity" }, 137 1.7 matt { L3CR_L3PE|L3CR_L3APE, L3CR_L3PE, " data-parity" }, 138 1.7 matt { L3CR_L3PE|L3CR_L3APE, L3CR_L3APE, " address-parity" }, 139 1.7 matt { L3CR_L3PE|L3CR_L3APE, 0, " no-parity" }, 140 1.7 matt { L3CR_L3SIZ, ~0, " L3 cache" }, 141 1.7 matt { L3CR_L3RT, L3RT_MSUG2_DDR, " (DDR SRAM)" }, 142 1.7 matt { L3CR_L3RT, L3RT_PIPELINE_LATE, " (LW SRAM)" }, 143 1.7 matt { L3CR_L3RT, L3RT_PB2_SRAM, " (PB2 SRAM)" }, 144 1.7 matt { L3CR_L3CLK, ~0, " at" }, 145 1.7 matt { L3CR_L3CLK, L3CLK_20, " 2:1" }, 146 1.7 matt { L3CR_L3CLK, L3CLK_25, " 2.5:1" }, 147 1.7 matt { L3CR_L3CLK, L3CLK_30, " 3:1" }, 148 1.7 matt { L3CR_L3CLK, L3CLK_35, " 3.5:1" }, 149 1.7 matt { L3CR_L3CLK, L3CLK_40, " 4:1" }, 150 1.7 matt { L3CR_L3CLK, L3CLK_50, " 5:1" }, 151 1.7 matt { L3CR_L3CLK, L3CLK_60, " 6:1" }, 152 1.7 matt { L3CR_L3CLK, ~0, " ratio" }, 153 1.28 garbled { 0, 0, NULL }, 154 1.7 matt }; 155 1.7 matt 156 1.109 jmcneill static const struct fmttab cpu_ibm750cl_l2cr_formats[] = { 157 1.109 jmcneill { L2CR_L2E, 0, " disabled" }, 158 1.109 jmcneill { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO, " data-only" }, 159 1.109 jmcneill { L2CR_L2DO|L2CR_L2IO, L2CR_L2IO, " instruction-only" }, 160 1.109 jmcneill { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO|L2CR_L2IO, " locked" }, 161 1.109 jmcneill { 0, ~0, " 256KB" }, 162 1.109 jmcneill { L2CR_L2WT, L2CR_L2WT, " WT" }, 163 1.109 jmcneill { L2CR_L2WT, 0, " WB" }, 164 1.109 jmcneill { L2CR_L2PE, L2CR_L2PE, " with ECC" }, 165 1.109 jmcneill { 0, ~0, " L2 cache" }, 166 1.109 jmcneill { 0, 0, NULL } 167 1.109 jmcneill }; 168 1.109 jmcneill 169 1.7 matt static const struct fmttab cpu_ibm750_l2cr_formats[] = { 170 1.7 matt { L2CR_L2E, 0, " disabled" }, 171 1.7 matt { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO, " data-only" }, 172 1.7 matt { L2CR_L2DO|L2CR_L2IO, L2CR_L2IO, " instruction-only" }, 173 1.7 matt { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO|L2CR_L2IO, " locked" }, 174 1.7 matt { 0, ~0, " 512KB" }, 175 1.7 matt { L2CR_L2WT, L2CR_L2WT, " WT" }, 176 1.7 matt { L2CR_L2WT, 0, " WB" }, 177 1.7 matt { L2CR_L2PE, L2CR_L2PE, " with ECC" }, 178 1.7 matt { 0, ~0, " L2 cache" }, 179 1.28 garbled { 0, 0, NULL } 180 1.7 matt }; 181 1.7 matt 182 1.7 matt static const struct fmttab cpu_l2cr_formats[] = { 183 1.7 matt { L2CR_L2E, 0, " disabled" }, 184 1.7 matt { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO, " data-only" }, 185 1.7 matt { L2CR_L2DO|L2CR_L2IO, L2CR_L2IO, " instruction-only" }, 186 1.7 matt { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO|L2CR_L2IO, " locked" }, 187 1.7 matt { L2CR_L2PE, L2CR_L2PE, " parity" }, 188 1.7 matt { L2CR_L2PE, 0, " no-parity" }, 189 1.7 matt { L2CR_L2SIZ, L2SIZ_2M, " 2MB" }, 190 1.7 matt { L2CR_L2SIZ, L2SIZ_1M, " 1MB" }, 191 1.7 matt { L2CR_L2SIZ, L2SIZ_512K, " 512KB" }, 192 1.7 matt { L2CR_L2SIZ, L2SIZ_256K, " 256KB" }, 193 1.7 matt { L2CR_L2WT, L2CR_L2WT, " WT" }, 194 1.7 matt { L2CR_L2WT, 0, " WB" }, 195 1.7 matt { L2CR_L2E, ~0, " L2 cache" }, 196 1.7 matt { L2CR_L2RAM, L2RAM_FLOWTHRU_BURST, " (FB SRAM)" }, 197 1.7 matt { L2CR_L2RAM, L2RAM_PIPELINE_LATE, " (LW SRAM)" }, 198 1.7 matt { L2CR_L2RAM, L2RAM_PIPELINE_BURST, " (PB SRAM)" }, 199 1.7 matt { L2CR_L2CLK, ~0, " at" }, 200 1.7 matt { L2CR_L2CLK, L2CLK_10, " 1:1" }, 201 1.7 matt { L2CR_L2CLK, L2CLK_15, " 1.5:1" }, 202 1.7 matt { L2CR_L2CLK, L2CLK_20, " 2:1" }, 203 1.7 matt { L2CR_L2CLK, L2CLK_25, " 2.5:1" }, 204 1.7 matt { L2CR_L2CLK, L2CLK_30, " 3:1" }, 205 1.7 matt { L2CR_L2CLK, L2CLK_35, " 3.5:1" }, 206 1.7 matt { L2CR_L2CLK, L2CLK_40, " 4:1" }, 207 1.7 matt { L2CR_L2CLK, ~0, " ratio" }, 208 1.28 garbled { 0, 0, NULL } 209 1.7 matt }; 210 1.7 matt 211 1.7 matt static void cpu_fmttab_print(const struct fmttab *, register_t); 212 1.7 matt 213 1.7 matt struct cputab { 214 1.7 matt const char name[8]; 215 1.7 matt uint16_t version; 216 1.7 matt uint16_t revfmt; 217 1.7 matt }; 218 1.7 matt #define REVFMT_MAJMIN 1 /* %u.%u */ 219 1.7 matt #define REVFMT_HEX 2 /* 0x%04x */ 220 1.7 matt #define REVFMT_DEC 3 /* %u */ 221 1.7 matt static const struct cputab models[] = { 222 1.7 matt { "601", MPC601, REVFMT_DEC }, 223 1.7 matt { "602", MPC602, REVFMT_DEC }, 224 1.7 matt { "603", MPC603, REVFMT_MAJMIN }, 225 1.7 matt { "603e", MPC603e, REVFMT_MAJMIN }, 226 1.7 matt { "603ev", MPC603ev, REVFMT_MAJMIN }, 227 1.31 aymeric { "G2", MPCG2, REVFMT_MAJMIN }, 228 1.7 matt { "604", MPC604, REVFMT_MAJMIN }, 229 1.15 briggs { "604e", MPC604e, REVFMT_MAJMIN }, 230 1.7 matt { "604ev", MPC604ev, REVFMT_MAJMIN }, 231 1.7 matt { "620", MPC620, REVFMT_HEX }, 232 1.7 matt { "750", MPC750, REVFMT_MAJMIN }, 233 1.7 matt { "750FX", IBM750FX, REVFMT_MAJMIN }, 234 1.62 matt { "750GX", IBM750GX, REVFMT_MAJMIN }, 235 1.7 matt { "7400", MPC7400, REVFMT_MAJMIN }, 236 1.7 matt { "7410", MPC7410, REVFMT_MAJMIN }, 237 1.7 matt { "7450", MPC7450, REVFMT_MAJMIN }, 238 1.7 matt { "7455", MPC7455, REVFMT_MAJMIN }, 239 1.11 matt { "7457", MPC7457, REVFMT_MAJMIN }, 240 1.21 matt { "7447A", MPC7447A, REVFMT_MAJMIN }, 241 1.22 matt { "7448", MPC7448, REVFMT_MAJMIN }, 242 1.7 matt { "8240", MPC8240, REVFMT_MAJMIN }, 243 1.30 nisimura { "8245", MPC8245, REVFMT_MAJMIN }, 244 1.27 sanjayl { "970", IBM970, REVFMT_MAJMIN }, 245 1.27 sanjayl { "970FX", IBM970FX, REVFMT_MAJMIN }, 246 1.47 chs { "970MP", IBM970MP, REVFMT_MAJMIN }, 247 1.41 garbled { "POWER3II", IBMPOWER3II, REVFMT_MAJMIN }, 248 1.7 matt { "", 0, REVFMT_HEX } 249 1.7 matt }; 250 1.7 matt 251 1.105 thorpej #include <powerpc/oea/bat.h> 252 1.105 thorpej extern struct bat battable[]; 253 1.105 thorpej 254 1.1 matt #ifdef MULTIPROCESSOR 255 1.60 matt struct cpu_info cpu_info[CPU_MAXNUM] = { 256 1.60 matt [0] = { 257 1.60 matt .ci_curlwp = &lwp0, 258 1.105 thorpej .ci_battable = battable, 259 1.60 matt }, 260 1.60 matt }; 261 1.33 garbled volatile struct cpu_hatch_data *cpu_hatch_data; 262 1.33 garbled volatile int cpu_hatch_stack; 263 1.75 kiyohara #define HATCH_STACK_SIZE 0x1000 264 1.33 garbled extern int ticks_per_intr; 265 1.67 matt #include <powerpc/pic/picvar.h> 266 1.67 matt #include <powerpc/pic/ipivar.h> 267 1.1 matt #else 268 1.60 matt struct cpu_info cpu_info[1] = { 269 1.60 matt [0] = { 270 1.60 matt .ci_curlwp = &lwp0, 271 1.105 thorpej .ci_battable = battable, 272 1.60 matt }, 273 1.60 matt }; 274 1.33 garbled #endif /*MULTIPROCESSOR*/ 275 1.1 matt 276 1.1 matt int cpu_altivec; 277 1.67 matt register_t cpu_psluserset; 278 1.67 matt register_t cpu_pslusermod; 279 1.67 matt register_t cpu_pslusermask = 0xffff; 280 1.1 matt 281 1.106 thorpej unsigned long oeacpufeat; 282 1.106 thorpej 283 1.42 garbled void 284 1.107 thorpej cpu_features_probe(void) 285 1.42 garbled { 286 1.107 thorpej static bool feature_probe_done; 287 1.107 thorpej 288 1.42 garbled u_int pvr, vers; 289 1.42 garbled 290 1.107 thorpej if (feature_probe_done) { 291 1.107 thorpej return; 292 1.107 thorpej } 293 1.107 thorpej 294 1.42 garbled pvr = mfpvr(); 295 1.42 garbled vers = pvr >> 16; 296 1.42 garbled 297 1.42 garbled if ((vers >= IBMRS64II && vers <= IBM970GX) || vers == MPC620 || 298 1.107 thorpej vers == IBMCELL || vers == IBMPOWER6P5) { 299 1.72 matt oeacpufeat |= OEACPU_64; 300 1.72 matt oeacpufeat |= OEACPU_64_BRIDGE; 301 1.72 matt oeacpufeat |= OEACPU_NOBAT; 302 1.74 kiyohara 303 1.72 matt } else if (vers == MPC601) { 304 1.42 garbled oeacpufeat |= OEACPU_601; 305 1.45 matt 306 1.77 matt } else if (MPC745X_P(vers)) { 307 1.77 matt if (vers != MPC7450) { 308 1.77 matt /* Enable more SPRG registers */ 309 1.77 matt oeacpufeat |= OEACPU_HIGHSPRG; 310 1.77 matt 311 1.77 matt /* Enable more BAT registers */ 312 1.77 matt oeacpufeat |= OEACPU_HIGHBAT; 313 1.78 matt 314 1.78 matt /* Enable larger BAT registers */ 315 1.78 matt oeacpufeat |= OEACPU_XBSEN; 316 1.107 thorpej } 317 1.107 thorpej 318 1.107 thorpej } else if (vers == IBM750FX || vers == IBM750GX) { 319 1.107 thorpej oeacpufeat |= OEACPU_HIGHBAT; 320 1.107 thorpej } 321 1.107 thorpej 322 1.107 thorpej feature_probe_done = true; 323 1.107 thorpej } 324 1.107 thorpej 325 1.107 thorpej void 326 1.107 thorpej cpu_features_enable(void) 327 1.107 thorpej { 328 1.107 thorpej static bool feature_enable_done; 329 1.107 thorpej 330 1.107 thorpej if (feature_enable_done) { 331 1.107 thorpej return; 332 1.107 thorpej } 333 1.107 thorpej 334 1.107 thorpej u_int pvr, vers; 335 1.107 thorpej 336 1.107 thorpej pvr = mfpvr(); 337 1.107 thorpej vers = pvr >> 16; 338 1.107 thorpej 339 1.107 thorpej if (MPC745X_P(vers)) { 340 1.107 thorpej register_t hid0 = mfspr(SPR_HID0); 341 1.107 thorpej register_t hid1 = mfspr(SPR_HID1); 342 1.107 thorpej 343 1.107 thorpej const register_t ohid0 = hid0; 344 1.107 thorpej 345 1.107 thorpej if (oeacpufeat & OEACPU_HIGHBAT) { 346 1.107 thorpej hid0 |= HID0_HIGH_BAT_EN; 347 1.107 thorpej } 348 1.107 thorpej 349 1.107 thorpej if (oeacpufeat & OEACPU_XBSEN) { 350 1.78 matt hid0 |= HID0_XBSEN; 351 1.107 thorpej } 352 1.78 matt 353 1.107 thorpej if (hid0 != ohid0) { 354 1.78 matt mtspr(SPR_HID0, hid0); 355 1.78 matt __asm volatile("sync;isync"); 356 1.77 matt } 357 1.77 matt 358 1.77 matt /* Enable address broadcasting for MP systems */ 359 1.77 matt hid1 |= HID1_SYNCBE | HID1_ABE; 360 1.77 matt 361 1.79 matt mtspr(SPR_HID1, hid1); 362 1.77 matt __asm volatile("sync;isync"); 363 1.107 thorpej } 364 1.107 thorpej 365 1.107 thorpej feature_enable_done = true; 366 1.107 thorpej } 367 1.62 matt 368 1.107 thorpej /* This is to be called from locore.S, and nowhere else. */ 369 1.107 thorpej 370 1.107 thorpej void 371 1.107 thorpej cpu_model_init(void) 372 1.107 thorpej { 373 1.107 thorpej /* 374 1.107 thorpej * This is just a wrapper for backwards-compatibility, and will 375 1.107 thorpej * probably be garbage-collected in the near future. 376 1.107 thorpej */ 377 1.107 thorpej cpu_features_probe(); 378 1.107 thorpej cpu_features_enable(); 379 1.42 garbled } 380 1.42 garbled 381 1.1 matt void 382 1.7 matt cpu_fmttab_print(const struct fmttab *fmt, register_t data) 383 1.7 matt { 384 1.7 matt for (; fmt->fmt_mask != 0 || fmt->fmt_value != 0; fmt++) { 385 1.7 matt if ((~fmt->fmt_mask & fmt->fmt_value) != 0 || 386 1.7 matt (data & fmt->fmt_mask) == fmt->fmt_value) 387 1.7 matt aprint_normal("%s", fmt->fmt_string); 388 1.7 matt } 389 1.7 matt } 390 1.7 matt 391 1.7 matt void 392 1.20 matt cpu_idlespin(void) 393 1.20 matt { 394 1.20 matt register_t msr; 395 1.20 matt 396 1.20 matt if (powersave <= 0) 397 1.20 matt return; 398 1.20 matt 399 1.83 macallan #if defined(_ARCH_PPC64) || defined (PPC_OEA64_BRIDGE) 400 1.98 phx if (cpu_altivec) 401 1.98 phx __asm volatile("dssall"); 402 1.83 macallan #endif 403 1.98 phx 404 1.98 phx __asm volatile( 405 1.20 matt "sync;" 406 1.20 matt "mfmsr %0;" 407 1.20 matt "oris %0,%0,%1@h;" /* enter power saving mode */ 408 1.20 matt "mtmsr %0;" 409 1.20 matt "isync;" 410 1.20 matt : "=r"(msr) 411 1.20 matt : "J"(PSL_POW)); 412 1.20 matt } 413 1.20 matt 414 1.20 matt void 415 1.1 matt cpu_probe_cache(void) 416 1.1 matt { 417 1.1 matt u_int assoc, pvr, vers; 418 1.1 matt 419 1.1 matt pvr = mfpvr(); 420 1.1 matt vers = pvr >> 16; 421 1.1 matt 422 1.27 sanjayl 423 1.27 sanjayl /* Presently common across almost all implementations. */ 424 1.43 garbled curcpu()->ci_ci.dcache_line_size = 32; 425 1.43 garbled curcpu()->ci_ci.icache_line_size = 32; 426 1.27 sanjayl 427 1.27 sanjayl 428 1.1 matt switch (vers) { 429 1.1 matt #define K *1024 430 1.1 matt case IBM750FX: 431 1.62 matt case IBM750GX: 432 1.1 matt case MPC601: 433 1.1 matt case MPC750: 434 1.48 macallan case MPC7400: 435 1.22 matt case MPC7447A: 436 1.22 matt case MPC7448: 437 1.1 matt case MPC7450: 438 1.1 matt case MPC7455: 439 1.11 matt case MPC7457: 440 1.1 matt curcpu()->ci_ci.dcache_size = 32 K; 441 1.1 matt curcpu()->ci_ci.icache_size = 32 K; 442 1.1 matt assoc = 8; 443 1.1 matt break; 444 1.1 matt case MPC603: 445 1.1 matt curcpu()->ci_ci.dcache_size = 8 K; 446 1.1 matt curcpu()->ci_ci.icache_size = 8 K; 447 1.1 matt assoc = 2; 448 1.1 matt break; 449 1.1 matt case MPC603e: 450 1.1 matt case MPC603ev: 451 1.1 matt case MPC604: 452 1.1 matt case MPC8240: 453 1.1 matt case MPC8245: 454 1.31 aymeric case MPCG2: 455 1.1 matt curcpu()->ci_ci.dcache_size = 16 K; 456 1.1 matt curcpu()->ci_ci.icache_size = 16 K; 457 1.1 matt assoc = 4; 458 1.1 matt break; 459 1.15 briggs case MPC604e: 460 1.1 matt case MPC604ev: 461 1.1 matt curcpu()->ci_ci.dcache_size = 32 K; 462 1.1 matt curcpu()->ci_ci.icache_size = 32 K; 463 1.1 matt assoc = 4; 464 1.1 matt break; 465 1.41 garbled case IBMPOWER3II: 466 1.41 garbled curcpu()->ci_ci.dcache_size = 64 K; 467 1.41 garbled curcpu()->ci_ci.icache_size = 32 K; 468 1.41 garbled curcpu()->ci_ci.dcache_line_size = 128; 469 1.41 garbled curcpu()->ci_ci.icache_line_size = 128; 470 1.41 garbled assoc = 128; /* not a typo */ 471 1.41 garbled break; 472 1.27 sanjayl case IBM970: 473 1.27 sanjayl case IBM970FX: 474 1.47 chs case IBM970MP: 475 1.27 sanjayl curcpu()->ci_ci.dcache_size = 32 K; 476 1.27 sanjayl curcpu()->ci_ci.icache_size = 64 K; 477 1.27 sanjayl curcpu()->ci_ci.dcache_line_size = 128; 478 1.27 sanjayl curcpu()->ci_ci.icache_line_size = 128; 479 1.27 sanjayl assoc = 2; 480 1.27 sanjayl break; 481 1.27 sanjayl 482 1.1 matt default: 483 1.6 thorpej curcpu()->ci_ci.dcache_size = PAGE_SIZE; 484 1.6 thorpej curcpu()->ci_ci.icache_size = PAGE_SIZE; 485 1.1 matt assoc = 1; 486 1.1 matt #undef K 487 1.1 matt } 488 1.1 matt 489 1.1 matt /* 490 1.1 matt * Possibly recolor. 491 1.1 matt */ 492 1.1 matt uvm_page_recolor(atop(curcpu()->ci_ci.dcache_size / assoc)); 493 1.1 matt } 494 1.1 matt 495 1.1 matt struct cpu_info * 496 1.60 matt cpu_attach_common(device_t self, int id) 497 1.1 matt { 498 1.1 matt struct cpu_info *ci; 499 1.1 matt u_int pvr, vers; 500 1.1 matt 501 1.1 matt ci = &cpu_info[id]; 502 1.1 matt #ifndef MULTIPROCESSOR 503 1.1 matt /* 504 1.1 matt * If this isn't the primary CPU, print an error message 505 1.1 matt * and just bail out. 506 1.1 matt */ 507 1.1 matt if (id != 0) { 508 1.71 phx aprint_naive("\n"); 509 1.3 matt aprint_normal(": ID %d\n", id); 510 1.66 matt aprint_normal_dev(self, 511 1.66 matt "processor off-line; " 512 1.66 matt "multiprocessor support not present in kernel\n"); 513 1.1 matt return (NULL); 514 1.1 matt } 515 1.1 matt #endif 516 1.1 matt 517 1.1 matt ci->ci_cpuid = id; 518 1.60 matt ci->ci_idepth = -1; 519 1.1 matt ci->ci_dev = self; 520 1.20 matt ci->ci_idlespin = cpu_idlespin; 521 1.1 matt 522 1.102 macallan #ifdef MULTIPROCESSOR 523 1.102 macallan /* Register IPI Interrupt */ 524 1.102 macallan if ((ipiops.ppc_establish_ipi) && (id == 0)) 525 1.102 macallan ipiops.ppc_establish_ipi(IST_LEVEL, IPL_HIGH, NULL); 526 1.102 macallan #endif 527 1.102 macallan 528 1.1 matt pvr = mfpvr(); 529 1.1 matt vers = (pvr >> 16) & 0xffff; 530 1.1 matt 531 1.1 matt switch (id) { 532 1.1 matt case 0: 533 1.1 matt /* load my cpu_number to PIR */ 534 1.1 matt switch (vers) { 535 1.1 matt case MPC601: 536 1.1 matt case MPC604: 537 1.15 briggs case MPC604e: 538 1.1 matt case MPC604ev: 539 1.1 matt case MPC7400: 540 1.1 matt case MPC7410: 541 1.22 matt case MPC7447A: 542 1.22 matt case MPC7448: 543 1.1 matt case MPC7450: 544 1.1 matt case MPC7455: 545 1.11 matt case MPC7457: 546 1.1 matt mtspr(SPR_PIR, id); 547 1.1 matt } 548 1.1 matt cpu_setup(self, ci); 549 1.1 matt break; 550 1.1 matt default: 551 1.71 phx aprint_naive("\n"); 552 1.1 matt if (id >= CPU_MAXNUM) { 553 1.3 matt aprint_normal(": more than %d cpus?\n", CPU_MAXNUM); 554 1.1 matt panic("cpuattach"); 555 1.1 matt } 556 1.1 matt #ifndef MULTIPROCESSOR 557 1.3 matt aprint_normal(" not configured\n"); 558 1.1 matt return NULL; 559 1.29 yamt #else 560 1.29 yamt mi_cpu_attach(ci); 561 1.29 yamt break; 562 1.1 matt #endif 563 1.1 matt } 564 1.1 matt return (ci); 565 1.1 matt } 566 1.1 matt 567 1.1 matt void 568 1.60 matt cpu_setup(device_t self, struct cpu_info *ci) 569 1.1 matt { 570 1.83 macallan u_int pvr, vers; 571 1.66 matt const char * const xname = device_xname(self); 572 1.24 he const char *bitmask; 573 1.24 he char hidbuf[128]; 574 1.1 matt char model[80]; 575 1.85 maya #if defined(PPC_OEA64_BRIDGE) || defined(_ARCH_PPC64) 576 1.83 macallan char hidbuf_u[128]; 577 1.83 macallan const char *bitmasku = NULL; 578 1.88 mrg volatile uint64_t hid64_0, hid64_0_save; 579 1.83 macallan #endif 580 1.88 mrg #if !defined(_ARCH_PPC64) 581 1.88 mrg register_t hid0 = 0, hid0_save = 0; 582 1.83 macallan #endif 583 1.1 matt 584 1.1 matt pvr = mfpvr(); 585 1.1 matt vers = (pvr >> 16) & 0xffff; 586 1.1 matt 587 1.1 matt cpu_identify(model, sizeof(model)); 588 1.71 phx aprint_naive("\n"); 589 1.3 matt aprint_normal(": %s, ID %d%s\n", model, cpu_number(), 590 1.1 matt cpu_number() == 0 ? " (primary)" : ""); 591 1.1 matt 592 1.46 garbled /* set the cpu number */ 593 1.46 garbled ci->ci_cpuid = cpu_number(); 594 1.83 macallan #if defined(_ARCH_PPC64) 595 1.88 mrg __asm volatile("mfspr %0,%1" : "=r"(hid64_0) : "K"(SPR_HID0)); 596 1.88 mrg hid64_0_save = hid64_0; 597 1.83 macallan #else 598 1.88 mrg #if defined(PPC_OEA64_BRIDGE) 599 1.88 mrg if ((oeacpufeat & OEACPU_64_BRIDGE) != 0) 600 1.88 mrg hid64_0_save = hid64_0 = mfspr(SPR_HID0); 601 1.88 mrg else 602 1.88 mrg #endif 603 1.88 mrg hid0_save = hid0 = mfspr(SPR_HID0); 604 1.83 macallan #endif 605 1.27 sanjayl 606 1.88 mrg 607 1.1 matt cpu_probe_cache(); 608 1.1 matt 609 1.1 matt /* 610 1.1 matt * Configure power-saving mode. 611 1.1 matt */ 612 1.1 matt switch (vers) { 613 1.90 mrg #if !defined(_ARCH_PPC64) 614 1.18 briggs case MPC604: 615 1.18 briggs case MPC604e: 616 1.18 briggs case MPC604ev: 617 1.18 briggs /* 618 1.18 briggs * Do not have HID0 support settings, but can support 619 1.18 briggs * MSR[POW] off 620 1.18 briggs */ 621 1.18 briggs powersave = 1; 622 1.18 briggs break; 623 1.18 briggs 624 1.1 matt case MPC603: 625 1.1 matt case MPC603e: 626 1.1 matt case MPC603ev: 627 1.1 matt case MPC7400: 628 1.1 matt case MPC7410: 629 1.1 matt case MPC8240: 630 1.1 matt case MPC8245: 631 1.31 aymeric case MPCG2: 632 1.1 matt /* Select DOZE mode. */ 633 1.1 matt hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); 634 1.1 matt hid0 |= HID0_DOZE | HID0_DPM; 635 1.1 matt powersave = 1; 636 1.1 matt break; 637 1.1 matt 638 1.57 macallan case MPC750: 639 1.57 macallan case IBM750FX: 640 1.62 matt case IBM750GX: 641 1.57 macallan /* Select NAP mode. */ 642 1.57 macallan hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); 643 1.57 macallan hid0 |= HID0_NAP | HID0_DPM; 644 1.57 macallan powersave = 1; 645 1.57 macallan break; 646 1.57 macallan 647 1.22 matt case MPC7447A: 648 1.22 matt case MPC7448: 649 1.11 matt case MPC7457: 650 1.1 matt case MPC7455: 651 1.1 matt case MPC7450: 652 1.5 matt /* Enable the 7450 branch caches */ 653 1.5 matt hid0 |= HID0_SGE | HID0_BTIC; 654 1.5 matt hid0 |= HID0_LRSTK | HID0_FOLD | HID0_BHT; 655 1.1 matt /* Disable BTIC on 7450 Rev 2.0 or earlier */ 656 1.5 matt if (vers == MPC7450 && (pvr & 0xFFFF) <= 0x0200) 657 1.1 matt hid0 &= ~HID0_BTIC; 658 1.1 matt /* Select NAP mode. */ 659 1.45 matt hid0 &= ~HID0_SLEEP; 660 1.101 macallan /* XXX my quicksilver hangs if nap is enabled */ 661 1.101 macallan if (vers != MPC7450) { 662 1.101 macallan hid0 |= HID0_NAP | HID0_DPM; 663 1.101 macallan powersave = 1; 664 1.101 macallan } 665 1.1 matt break; 666 1.90 mrg #endif 667 1.1 matt 668 1.27 sanjayl case IBM970: 669 1.27 sanjayl case IBM970FX: 670 1.47 chs case IBM970MP: 671 1.83 macallan #if defined(_ARCH_PPC64) || defined (PPC_OEA64_BRIDGE) 672 1.88 mrg #if !defined(_ARCH_PPC64) 673 1.88 mrg KASSERT((oeacpufeat & OEACPU_64_BRIDGE) != 0); 674 1.88 mrg #endif 675 1.88 mrg hid64_0 &= ~(HID0_64_DOZE | HID0_64_NAP | HID0_64_DEEPNAP); 676 1.91 macallan hid64_0 |= HID0_64_NAP | HID0_64_DPM | HID0_64_EX_TBEN | 677 1.88 mrg HID0_64_TB_CTRL | HID0_64_EN_MCHK; 678 1.83 macallan powersave = 1; 679 1.83 macallan break; 680 1.83 macallan #endif 681 1.41 garbled case IBMPOWER3II: 682 1.1 matt default: 683 1.1 matt /* No power-saving mode is available. */ ; 684 1.1 matt } 685 1.1 matt 686 1.1 matt #ifdef NAPMODE 687 1.1 matt switch (vers) { 688 1.1 matt case IBM750FX: 689 1.62 matt case IBM750GX: 690 1.1 matt case MPC750: 691 1.1 matt case MPC7400: 692 1.1 matt /* Select NAP mode. */ 693 1.1 matt hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); 694 1.1 matt hid0 |= HID0_NAP; 695 1.1 matt break; 696 1.1 matt } 697 1.1 matt #endif 698 1.1 matt 699 1.1 matt switch (vers) { 700 1.1 matt case IBM750FX: 701 1.62 matt case IBM750GX: 702 1.1 matt case MPC750: 703 1.1 matt hid0 &= ~HID0_DBP; /* XXX correct? */ 704 1.1 matt hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT; 705 1.1 matt break; 706 1.1 matt 707 1.1 matt case MPC7400: 708 1.1 matt case MPC7410: 709 1.1 matt hid0 &= ~HID0_SPD; 710 1.1 matt hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT; 711 1.1 matt hid0 |= HID0_EIEC; 712 1.1 matt break; 713 1.1 matt } 714 1.1 matt 715 1.83 macallan /* 716 1.83 macallan * according to the 603e manual this is necessary for an external L2 717 1.83 macallan * cache to work properly 718 1.83 macallan */ 719 1.76 kiyohara switch (vers) { 720 1.76 kiyohara case MPC603e: 721 1.76 kiyohara hid0 |= HID0_ABE; 722 1.76 kiyohara } 723 1.83 macallan 724 1.88 mrg #if defined(_ARCH_PPC64) || defined(PPC_OEA64_BRIDGE) 725 1.88 mrg #if defined(PPC_OEA64_BRIDGE) 726 1.88 mrg if ((oeacpufeat & OEACPU_64_BRIDGE) != 0) { 727 1.88 mrg #endif 728 1.88 mrg if (hid64_0 != hid64_0_save) { 729 1.89 macallan mtspr64(SPR_HID0, hid64_0); 730 1.88 mrg } 731 1.88 mrg #if defined(PPC_OEA64_BRIDGE) 732 1.88 mrg } else { 733 1.88 mrg #endif 734 1.76 kiyohara #endif 735 1.41 garbled 736 1.88 mrg #if !defined(_ARCH_PPC64) 737 1.88 mrg if (hid0 != hid0_save) { 738 1.88 mrg mtspr(SPR_HID0, hid0); 739 1.88 mrg __asm volatile("sync;isync"); 740 1.88 mrg } 741 1.88 mrg #endif 742 1.88 mrg #if defined(PPC_OEA64_BRIDGE) 743 1.88 mrg } 744 1.88 mrg #endif 745 1.1 matt 746 1.1 matt switch (vers) { 747 1.1 matt case MPC601: 748 1.1 matt bitmask = HID0_601_BITMASK; 749 1.1 matt break; 750 1.86 macallan case MPC7447A: 751 1.86 macallan case MPC7448: 752 1.1 matt case MPC7450: 753 1.1 matt case MPC7455: 754 1.11 matt case MPC7457: 755 1.1 matt bitmask = HID0_7450_BITMASK; 756 1.1 matt break; 757 1.27 sanjayl case IBM970: 758 1.27 sanjayl case IBM970FX: 759 1.47 chs case IBM970MP: 760 1.83 macallan bitmask = HID0_970_BITMASK; 761 1.85 maya #if defined(PPC_OEA64_BRIDGE) || defined(_ARCH_PPC64) 762 1.83 macallan bitmasku = HID0_970_BITMASK_U; 763 1.83 macallan #endif 764 1.27 sanjayl break; 765 1.1 matt default: 766 1.1 matt bitmask = HID0_BITMASK; 767 1.1 matt break; 768 1.1 matt } 769 1.83 macallan 770 1.85 maya #if defined(PPC_OEA64_BRIDGE) || defined(_ARCH_PPC64) 771 1.83 macallan if (bitmasku != NULL) { 772 1.88 mrg snprintb(hidbuf, sizeof hidbuf, bitmask, hid64_0 & 0xffffffff); 773 1.88 mrg snprintb(hidbuf_u, sizeof hidbuf_u, bitmasku, hid64_0 >> 32); 774 1.83 macallan aprint_normal_dev(self, "HID0 %s %s, powersave: %d\n", 775 1.83 macallan hidbuf_u, hidbuf, powersave); 776 1.83 macallan } else 777 1.83 macallan #endif 778 1.83 macallan { 779 1.83 macallan snprintb(hidbuf, sizeof hidbuf, bitmask, hid0); 780 1.83 macallan aprint_normal_dev(self, "HID0 %s, powersave: %d\n", 781 1.83 macallan hidbuf, powersave); 782 1.83 macallan } 783 1.1 matt 784 1.23 briggs ci->ci_khz = 0; 785 1.23 briggs 786 1.1 matt /* 787 1.1 matt * Display speed and cache configuration. 788 1.1 matt */ 789 1.15 briggs switch (vers) { 790 1.15 briggs case MPC604: 791 1.15 briggs case MPC604e: 792 1.15 briggs case MPC604ev: 793 1.15 briggs case MPC750: 794 1.15 briggs case IBM750FX: 795 1.62 matt case IBM750GX: 796 1.16 briggs case MPC7400: 797 1.15 briggs case MPC7410: 798 1.22 matt case MPC7447A: 799 1.22 matt case MPC7448: 800 1.16 briggs case MPC7450: 801 1.16 briggs case MPC7455: 802 1.16 briggs case MPC7457: 803 1.66 matt aprint_normal_dev(self, ""); 804 1.23 briggs cpu_probe_speed(ci); 805 1.23 briggs aprint_normal("%u.%02u MHz", 806 1.23 briggs ci->ci_khz / 1000, (ci->ci_khz / 10) % 100); 807 1.36 garbled switch (vers) { 808 1.37 macallan case MPC7450: /* 7441 does not have L3! */ 809 1.37 macallan case MPC7455: /* 7445 does not have L3! */ 810 1.37 macallan case MPC7457: /* 7447 does not have L3! */ 811 1.37 macallan cpu_config_l3cr(vers); 812 1.38 macallan break; 813 1.36 garbled case IBM750FX: 814 1.62 matt case IBM750GX: 815 1.36 garbled case MPC750: 816 1.36 garbled case MPC7400: 817 1.36 garbled case MPC7410: 818 1.36 garbled case MPC7447A: 819 1.36 garbled case MPC7448: 820 1.36 garbled cpu_config_l2cr(pvr); 821 1.36 garbled break; 822 1.36 garbled default: 823 1.36 garbled break; 824 1.7 matt } 825 1.7 matt aprint_normal("\n"); 826 1.15 briggs break; 827 1.1 matt } 828 1.1 matt 829 1.1 matt #if NSYSMON_ENVSYS > 0 830 1.1 matt /* 831 1.1 matt * Attach MPC750 temperature sensor to the envsys subsystem. 832 1.1 matt * XXX the 74xx series also has this sensor, but it is not 833 1.74 kiyohara * XXX supported by Motorola and may return values that are off by 834 1.1 matt * XXX 35-55 degrees C. 835 1.1 matt */ 836 1.62 matt if (vers == MPC750 || vers == IBM750FX || vers == IBM750GX) 837 1.1 matt cpu_tau_setup(ci); 838 1.1 matt #endif 839 1.1 matt 840 1.95 macallan #if defined(PPC_OEA64) || defined(PPC_OEA64_BRIDGE) 841 1.95 macallan if (vers == IBM970MP) 842 1.95 macallan init_scom_speedctl(); 843 1.95 macallan #endif 844 1.95 macallan 845 1.1 matt evcnt_attach_dynamic(&ci->ci_ev_clock, EVCNT_TYPE_INTR, 846 1.66 matt NULL, xname, "clock"); 847 1.1 matt evcnt_attach_dynamic(&ci->ci_ev_traps, EVCNT_TYPE_TRAP, 848 1.66 matt NULL, xname, "traps"); 849 1.1 matt evcnt_attach_dynamic(&ci->ci_ev_kdsi, EVCNT_TYPE_TRAP, 850 1.66 matt &ci->ci_ev_traps, xname, "kernel DSI traps"); 851 1.1 matt evcnt_attach_dynamic(&ci->ci_ev_udsi, EVCNT_TYPE_TRAP, 852 1.66 matt &ci->ci_ev_traps, xname, "user DSI traps"); 853 1.1 matt evcnt_attach_dynamic(&ci->ci_ev_udsi_fatal, EVCNT_TYPE_TRAP, 854 1.66 matt &ci->ci_ev_udsi, xname, "user DSI failures"); 855 1.10 matt evcnt_attach_dynamic(&ci->ci_ev_kisi, EVCNT_TYPE_TRAP, 856 1.66 matt &ci->ci_ev_traps, xname, "kernel ISI traps"); 857 1.1 matt evcnt_attach_dynamic(&ci->ci_ev_isi, EVCNT_TYPE_TRAP, 858 1.66 matt &ci->ci_ev_traps, xname, "user ISI traps"); 859 1.1 matt evcnt_attach_dynamic(&ci->ci_ev_isi_fatal, EVCNT_TYPE_TRAP, 860 1.66 matt &ci->ci_ev_isi, xname, "user ISI failures"); 861 1.1 matt evcnt_attach_dynamic(&ci->ci_ev_scalls, EVCNT_TYPE_TRAP, 862 1.66 matt &ci->ci_ev_traps, xname, "system call traps"); 863 1.1 matt evcnt_attach_dynamic(&ci->ci_ev_pgm, EVCNT_TYPE_TRAP, 864 1.66 matt &ci->ci_ev_traps, xname, "PGM traps"); 865 1.1 matt evcnt_attach_dynamic(&ci->ci_ev_fpu, EVCNT_TYPE_TRAP, 866 1.66 matt &ci->ci_ev_traps, xname, "FPU unavailable traps"); 867 1.1 matt evcnt_attach_dynamic(&ci->ci_ev_fpusw, EVCNT_TYPE_TRAP, 868 1.66 matt &ci->ci_ev_fpu, xname, "FPU context switches"); 869 1.1 matt evcnt_attach_dynamic(&ci->ci_ev_ali, EVCNT_TYPE_TRAP, 870 1.66 matt &ci->ci_ev_traps, xname, "user alignment traps"); 871 1.1 matt evcnt_attach_dynamic(&ci->ci_ev_ali_fatal, EVCNT_TYPE_TRAP, 872 1.108 rin &ci->ci_ev_ali, xname, "user alignment failures"); 873 1.1 matt evcnt_attach_dynamic(&ci->ci_ev_umchk, EVCNT_TYPE_TRAP, 874 1.66 matt &ci->ci_ev_umchk, xname, "user MCHK failures"); 875 1.1 matt evcnt_attach_dynamic(&ci->ci_ev_vec, EVCNT_TYPE_TRAP, 876 1.66 matt &ci->ci_ev_traps, xname, "AltiVec unavailable"); 877 1.1 matt #ifdef ALTIVEC 878 1.1 matt if (cpu_altivec) { 879 1.1 matt evcnt_attach_dynamic(&ci->ci_ev_vecsw, EVCNT_TYPE_TRAP, 880 1.66 matt &ci->ci_ev_vec, xname, "AltiVec context switches"); 881 1.1 matt } 882 1.1 matt #endif 883 1.33 garbled evcnt_attach_dynamic(&ci->ci_ev_ipi, EVCNT_TYPE_INTR, 884 1.66 matt NULL, xname, "IPIs"); 885 1.1 matt } 886 1.1 matt 887 1.36 garbled /* 888 1.36 garbled * According to a document labeled "PVR Register Settings": 889 1.36 garbled ** For integrated microprocessors the PVR register inside the device 890 1.36 garbled ** will identify the version of the microprocessor core. You must also 891 1.36 garbled ** read the Device ID, PCI register 02, to identify the part and the 892 1.36 garbled ** Revision ID, PCI register 08, to identify the revision of the 893 1.36 garbled ** integrated microprocessor. 894 1.36 garbled * This apparently applies to 8240/8245/8241, PVR 00810101 and 80811014 895 1.36 garbled */ 896 1.36 garbled 897 1.1 matt void 898 1.1 matt cpu_identify(char *str, size_t len) 899 1.1 matt { 900 1.24 he u_int pvr, major, minor; 901 1.1 matt uint16_t vers, rev, revfmt; 902 1.1 matt const struct cputab *cp; 903 1.1 matt size_t n; 904 1.1 matt 905 1.1 matt pvr = mfpvr(); 906 1.1 matt vers = pvr >> 16; 907 1.1 matt rev = pvr; 908 1.27 sanjayl 909 1.1 matt switch (vers) { 910 1.1 matt case MPC7410: 911 1.24 he minor = (pvr >> 0) & 0xff; 912 1.24 he major = minor <= 4 ? 1 : 2; 913 1.1 matt break; 914 1.36 garbled case MPCG2: /*XXX see note above */ 915 1.36 garbled major = (pvr >> 4) & 0xf; 916 1.36 garbled minor = (pvr >> 0) & 0xf; 917 1.36 garbled break; 918 1.1 matt default: 919 1.36 garbled major = (pvr >> 8) & 0xf; 920 1.24 he minor = (pvr >> 0) & 0xf; 921 1.1 matt } 922 1.1 matt 923 1.1 matt for (cp = models; cp->name[0] != '\0'; cp++) { 924 1.1 matt if (cp->version == vers) 925 1.1 matt break; 926 1.1 matt } 927 1.1 matt 928 1.82 christos if (cpu == -1) 929 1.1 matt cpu = vers; 930 1.1 matt 931 1.1 matt revfmt = cp->revfmt; 932 1.1 matt if (rev == MPC750 && pvr == 15) { 933 1.1 matt revfmt = REVFMT_HEX; 934 1.1 matt } 935 1.111 jmcneill if (vers == MPC750 && (pvr & 0xf000) == 0x7000 && 936 1.111 jmcneill (pvr & 0x0f00) >= 0x0100) { 937 1.111 jmcneill /* IBM Broadway */ 938 1.111 jmcneill revfmt = REVFMT_HEX; 939 1.111 jmcneill } 940 1.1 matt 941 1.1 matt if (cp->name[0] != '\0') { 942 1.1 matt n = snprintf(str, len, "%s (Revision ", cp->name); 943 1.1 matt } else { 944 1.1 matt n = snprintf(str, len, "Version %#x (Revision ", vers); 945 1.1 matt } 946 1.1 matt if (len > n) { 947 1.1 matt switch (revfmt) { 948 1.1 matt case REVFMT_MAJMIN: 949 1.24 he snprintf(str + n, len - n, "%u.%u)", major, minor); 950 1.1 matt break; 951 1.1 matt case REVFMT_HEX: 952 1.1 matt snprintf(str + n, len - n, "0x%04x)", rev); 953 1.1 matt break; 954 1.1 matt case REVFMT_DEC: 955 1.1 matt snprintf(str + n, len - n, "%u)", rev); 956 1.1 matt break; 957 1.1 matt } 958 1.1 matt } 959 1.1 matt } 960 1.1 matt 961 1.1 matt #ifdef L2CR_CONFIG 962 1.1 matt u_int l2cr_config = L2CR_CONFIG; 963 1.1 matt #else 964 1.1 matt u_int l2cr_config = 0; 965 1.1 matt #endif 966 1.1 matt 967 1.2 jklos #ifdef L3CR_CONFIG 968 1.2 jklos u_int l3cr_config = L3CR_CONFIG; 969 1.2 jklos #else 970 1.2 jklos u_int l3cr_config = 0; 971 1.2 jklos #endif 972 1.2 jklos 973 1.1 matt void 974 1.7 matt cpu_enable_l2cr(register_t l2cr) 975 1.7 matt { 976 1.7 matt register_t msr, x; 977 1.40 garbled uint16_t vers; 978 1.7 matt 979 1.40 garbled vers = mfpvr() >> 16; 980 1.74 kiyohara 981 1.7 matt /* Disable interrupts and set the cache config bits. */ 982 1.7 matt msr = mfmsr(); 983 1.7 matt mtmsr(msr & ~PSL_EE); 984 1.7 matt #ifdef ALTIVEC 985 1.7 matt if (cpu_altivec) 986 1.26 perry __asm volatile("dssall"); 987 1.7 matt #endif 988 1.26 perry __asm volatile("sync"); 989 1.7 matt mtspr(SPR_L2CR, l2cr & ~L2CR_L2E); 990 1.26 perry __asm volatile("sync"); 991 1.7 matt 992 1.7 matt /* Wait for L2 clock to be stable (640 L2 clocks). */ 993 1.7 matt delay(100); 994 1.7 matt 995 1.7 matt /* Invalidate all L2 contents. */ 996 1.40 garbled if (MPC745X_P(vers)) { 997 1.40 garbled mtspr(SPR_L2CR, l2cr | L2CR_L2I); 998 1.40 garbled do { 999 1.40 garbled x = mfspr(SPR_L2CR); 1000 1.40 garbled } while (x & L2CR_L2I); 1001 1.40 garbled } else { 1002 1.40 garbled mtspr(SPR_L2CR, l2cr | L2CR_L2I); 1003 1.40 garbled do { 1004 1.40 garbled x = mfspr(SPR_L2CR); 1005 1.40 garbled } while (x & L2CR_L2IP); 1006 1.40 garbled } 1007 1.7 matt /* Enable L2 cache. */ 1008 1.7 matt l2cr |= L2CR_L2E; 1009 1.7 matt mtspr(SPR_L2CR, l2cr); 1010 1.7 matt mtmsr(msr); 1011 1.7 matt } 1012 1.7 matt 1013 1.7 matt void 1014 1.7 matt cpu_enable_l3cr(register_t l3cr) 1015 1.1 matt { 1016 1.7 matt register_t x; 1017 1.7 matt 1018 1.7 matt /* By The Book (numbered steps from section 3.7.1.3 of MPC7450UM) */ 1019 1.74 kiyohara 1020 1.7 matt /* 1021 1.7 matt * 1: Set all L3CR bits for final config except L3E, L3I, L3PE, and 1022 1.7 matt * L3CLKEN. (also mask off reserved bits in case they were included 1023 1.7 matt * in L3CR_CONFIG) 1024 1.7 matt */ 1025 1.7 matt l3cr &= ~(L3CR_L3E|L3CR_L3I|L3CR_L3PE|L3CR_L3CLKEN|L3CR_RESERVED); 1026 1.7 matt mtspr(SPR_L3CR, l3cr); 1027 1.7 matt 1028 1.7 matt /* 2: Set L3CR[5] (otherwise reserved bit) to 1 */ 1029 1.7 matt l3cr |= 0x04000000; 1030 1.7 matt mtspr(SPR_L3CR, l3cr); 1031 1.7 matt 1032 1.7 matt /* 3: Set L3CLKEN to 1*/ 1033 1.7 matt l3cr |= L3CR_L3CLKEN; 1034 1.7 matt mtspr(SPR_L3CR, l3cr); 1035 1.7 matt 1036 1.7 matt /* 4/5: Perform a global cache invalidate (ref section 3.7.3.6) */ 1037 1.26 perry __asm volatile("dssall;sync"); 1038 1.7 matt /* L3 cache is already disabled, no need to clear L3E */ 1039 1.7 matt mtspr(SPR_L3CR, l3cr|L3CR_L3I); 1040 1.7 matt do { 1041 1.7 matt x = mfspr(SPR_L3CR); 1042 1.7 matt } while (x & L3CR_L3I); 1043 1.74 kiyohara 1044 1.7 matt /* 6: Clear L3CLKEN to 0 */ 1045 1.7 matt l3cr &= ~L3CR_L3CLKEN; 1046 1.7 matt mtspr(SPR_L3CR, l3cr); 1047 1.7 matt 1048 1.7 matt /* 7: Perform a 'sync' and wait at least 100 CPU cycles */ 1049 1.26 perry __asm volatile("sync"); 1050 1.7 matt delay(100); 1051 1.7 matt 1052 1.7 matt /* 8: Set L3E and L3CLKEN */ 1053 1.7 matt l3cr |= (L3CR_L3E|L3CR_L3CLKEN); 1054 1.7 matt mtspr(SPR_L3CR, l3cr); 1055 1.7 matt 1056 1.7 matt /* 9: Perform a 'sync' and wait at least 100 CPU cycles */ 1057 1.26 perry __asm volatile("sync"); 1058 1.7 matt delay(100); 1059 1.7 matt } 1060 1.7 matt 1061 1.7 matt void 1062 1.7 matt cpu_config_l2cr(int pvr) 1063 1.7 matt { 1064 1.7 matt register_t l2cr; 1065 1.36 garbled u_int vers = (pvr >> 16) & 0xffff; 1066 1.1 matt 1067 1.1 matt l2cr = mfspr(SPR_L2CR); 1068 1.1 matt 1069 1.1 matt /* 1070 1.1 matt * For MP systems, the firmware may only configure the L2 cache 1071 1.1 matt * on the first CPU. In this case, assume that the other CPUs 1072 1.1 matt * should use the same value for L2CR. 1073 1.1 matt */ 1074 1.1 matt if ((l2cr & L2CR_L2E) != 0 && l2cr_config == 0) { 1075 1.1 matt l2cr_config = l2cr; 1076 1.1 matt } 1077 1.1 matt 1078 1.1 matt /* 1079 1.1 matt * Configure L2 cache if not enabled. 1080 1.1 matt */ 1081 1.8 scw if ((l2cr & L2CR_L2E) == 0 && l2cr_config != 0) { 1082 1.7 matt cpu_enable_l2cr(l2cr_config); 1083 1.8 scw l2cr = mfspr(SPR_L2CR); 1084 1.8 scw } 1085 1.7 matt 1086 1.15 briggs if ((l2cr & L2CR_L2E) == 0) { 1087 1.15 briggs aprint_normal(" L2 cache present but not enabled "); 1088 1.7 matt return; 1089 1.15 briggs } 1090 1.36 garbled aprint_normal(","); 1091 1.1 matt 1092 1.36 garbled switch (vers) { 1093 1.36 garbled case IBM750FX: 1094 1.62 matt case IBM750GX: 1095 1.7 matt cpu_fmttab_print(cpu_ibm750_l2cr_formats, l2cr); 1096 1.36 garbled break; 1097 1.36 garbled case MPC750: 1098 1.36 garbled if ((pvr & 0xffffff00) == 0x00082200 /* IBM750CX */ || 1099 1.109 jmcneill (pvr & 0xffffef00) == 0x00082300 /* IBM750CXe */) { 1100 1.36 garbled cpu_fmttab_print(cpu_ibm750_l2cr_formats, l2cr); 1101 1.109 jmcneill } else if ((pvr & 0xfffff0e0) == 0x00087000 /* IBM750CL */) { 1102 1.109 jmcneill cpu_fmttab_print(cpu_ibm750cl_l2cr_formats, l2cr); 1103 1.109 jmcneill } else { 1104 1.36 garbled cpu_fmttab_print(cpu_l2cr_formats, l2cr); 1105 1.109 jmcneill } 1106 1.36 garbled break; 1107 1.36 garbled case MPC7447A: 1108 1.36 garbled case MPC7457: 1109 1.36 garbled cpu_fmttab_print(cpu_7457_l2cr_formats, l2cr); 1110 1.36 garbled return; 1111 1.36 garbled case MPC7448: 1112 1.36 garbled cpu_fmttab_print(cpu_7448_l2cr_formats, l2cr); 1113 1.36 garbled return; 1114 1.36 garbled case MPC7450: 1115 1.36 garbled case MPC7455: 1116 1.36 garbled cpu_fmttab_print(cpu_7450_l2cr_formats, l2cr); 1117 1.36 garbled break; 1118 1.36 garbled default: 1119 1.7 matt cpu_fmttab_print(cpu_l2cr_formats, l2cr); 1120 1.36 garbled break; 1121 1.1 matt } 1122 1.7 matt } 1123 1.1 matt 1124 1.7 matt void 1125 1.7 matt cpu_config_l3cr(int vers) 1126 1.7 matt { 1127 1.7 matt register_t l2cr; 1128 1.7 matt register_t l3cr; 1129 1.7 matt 1130 1.7 matt l2cr = mfspr(SPR_L2CR); 1131 1.1 matt 1132 1.7 matt /* 1133 1.7 matt * For MP systems, the firmware may only configure the L2 cache 1134 1.7 matt * on the first CPU. In this case, assume that the other CPUs 1135 1.7 matt * should use the same value for L2CR. 1136 1.7 matt */ 1137 1.7 matt if ((l2cr & L2CR_L2E) != 0 && l2cr_config == 0) { 1138 1.7 matt l2cr_config = l2cr; 1139 1.7 matt } 1140 1.1 matt 1141 1.7 matt /* 1142 1.7 matt * Configure L2 cache if not enabled. 1143 1.7 matt */ 1144 1.7 matt if ((l2cr & L2CR_L2E) == 0 && l2cr_config != 0) { 1145 1.7 matt cpu_enable_l2cr(l2cr_config); 1146 1.7 matt l2cr = mfspr(SPR_L2CR); 1147 1.7 matt } 1148 1.74 kiyohara 1149 1.7 matt aprint_normal(","); 1150 1.22 matt switch (vers) { 1151 1.22 matt case MPC7447A: 1152 1.22 matt case MPC7457: 1153 1.22 matt cpu_fmttab_print(cpu_7457_l2cr_formats, l2cr); 1154 1.22 matt return; 1155 1.22 matt case MPC7448: 1156 1.22 matt cpu_fmttab_print(cpu_7448_l2cr_formats, l2cr); 1157 1.22 matt return; 1158 1.22 matt default: 1159 1.22 matt cpu_fmttab_print(cpu_7450_l2cr_formats, l2cr); 1160 1.22 matt break; 1161 1.22 matt } 1162 1.2 jklos 1163 1.7 matt l3cr = mfspr(SPR_L3CR); 1164 1.1 matt 1165 1.7 matt /* 1166 1.7 matt * For MP systems, the firmware may only configure the L3 cache 1167 1.7 matt * on the first CPU. In this case, assume that the other CPUs 1168 1.7 matt * should use the same value for L3CR. 1169 1.7 matt */ 1170 1.7 matt if ((l3cr & L3CR_L3E) != 0 && l3cr_config == 0) { 1171 1.7 matt l3cr_config = l3cr; 1172 1.7 matt } 1173 1.1 matt 1174 1.7 matt /* 1175 1.7 matt * Configure L3 cache if not enabled. 1176 1.7 matt */ 1177 1.7 matt if ((l3cr & L3CR_L3E) == 0 && l3cr_config != 0) { 1178 1.7 matt cpu_enable_l3cr(l3cr_config); 1179 1.7 matt l3cr = mfspr(SPR_L3CR); 1180 1.7 matt } 1181 1.74 kiyohara 1182 1.7 matt if (l3cr & L3CR_L3E) { 1183 1.7 matt aprint_normal(","); 1184 1.7 matt cpu_fmttab_print(cpu_7450_l3cr_formats, l3cr); 1185 1.7 matt } 1186 1.1 matt } 1187 1.1 matt 1188 1.1 matt void 1189 1.23 briggs cpu_probe_speed(struct cpu_info *ci) 1190 1.1 matt { 1191 1.1 matt uint64_t cps; 1192 1.1 matt 1193 1.7 matt mtspr(SPR_MMCR0, MMCR0_FC); 1194 1.1 matt mtspr(SPR_PMC1, 0); 1195 1.7 matt mtspr(SPR_MMCR0, MMCR0_PMC1SEL(PMCN_CYCLES)); 1196 1.1 matt delay(100000); 1197 1.1 matt cps = (mfspr(SPR_PMC1) * 10) + 4999; 1198 1.1 matt 1199 1.15 briggs mtspr(SPR_MMCR0, MMCR0_FC); 1200 1.15 briggs 1201 1.56 phx ci->ci_khz = (cps * cpu_get_dfs()) / 1000; 1202 1.56 phx } 1203 1.56 phx 1204 1.56 phx /* 1205 1.56 phx * Read the Dynamic Frequency Switching state and return a divisor for 1206 1.56 phx * the maximum frequency. 1207 1.56 phx */ 1208 1.56 phx int 1209 1.56 phx cpu_get_dfs(void) 1210 1.56 phx { 1211 1.58 phx u_int pvr, vers; 1212 1.56 phx 1213 1.56 phx pvr = mfpvr(); 1214 1.56 phx vers = pvr >> 16; 1215 1.56 phx 1216 1.56 phx switch (vers) { 1217 1.56 phx case MPC7448: 1218 1.58 phx if (mfspr(SPR_HID1) & HID1_DFS4) 1219 1.56 phx return 4; 1220 1.99 mrg /* FALLTHROUGH */ 1221 1.56 phx case MPC7447A: 1222 1.58 phx if (mfspr(SPR_HID1) & HID1_DFS2) 1223 1.56 phx return 2; 1224 1.56 phx } 1225 1.56 phx return 1; 1226 1.56 phx } 1227 1.56 phx 1228 1.56 phx /* 1229 1.56 phx * Set the Dynamic Frequency Switching divisor the same for all cpus. 1230 1.56 phx */ 1231 1.56 phx void 1232 1.56 phx cpu_set_dfs(int div) 1233 1.56 phx { 1234 1.56 phx u_int dfs_mask, pvr, vers; 1235 1.56 phx 1236 1.56 phx pvr = mfpvr(); 1237 1.56 phx vers = pvr >> 16; 1238 1.56 phx dfs_mask = 0; 1239 1.56 phx 1240 1.56 phx switch (vers) { 1241 1.56 phx case MPC7448: 1242 1.56 phx dfs_mask |= HID1_DFS4; 1243 1.99 mrg /* FALLTHROUGH */ 1244 1.56 phx case MPC7447A: 1245 1.56 phx dfs_mask |= HID1_DFS2; 1246 1.56 phx break; 1247 1.56 phx default: 1248 1.56 phx printf("cpu_set_dfs: DFS not supported\n"); 1249 1.56 phx return; 1250 1.56 phx 1251 1.56 phx } 1252 1.96 macallan #ifdef MULTIPROCESSOR 1253 1.96 macallan uint64_t where; 1254 1.56 phx where = xc_broadcast(0, (xcfunc_t)cpu_set_dfs_xcall, &div, &dfs_mask); 1255 1.56 phx xc_wait(where); 1256 1.96 macallan #else 1257 1.96 macallan cpu_set_dfs_xcall(&div, &dfs_mask); 1258 1.96 macallan #endif 1259 1.56 phx } 1260 1.56 phx 1261 1.56 phx static void 1262 1.56 phx cpu_set_dfs_xcall(void *arg1, void *arg2) 1263 1.56 phx { 1264 1.56 phx u_int dfs_mask, hid1, old_hid1; 1265 1.56 phx int *divisor, s; 1266 1.56 phx 1267 1.56 phx divisor = arg1; 1268 1.56 phx dfs_mask = *(u_int *)arg2; 1269 1.56 phx 1270 1.56 phx s = splhigh(); 1271 1.56 phx hid1 = old_hid1 = mfspr(SPR_HID1); 1272 1.56 phx 1273 1.56 phx switch (*divisor) { 1274 1.56 phx case 1: 1275 1.56 phx hid1 &= ~dfs_mask; 1276 1.56 phx break; 1277 1.56 phx case 2: 1278 1.56 phx hid1 &= ~(dfs_mask & HID1_DFS4); 1279 1.56 phx hid1 |= dfs_mask & HID1_DFS2; 1280 1.56 phx break; 1281 1.56 phx case 4: 1282 1.56 phx hid1 &= ~(dfs_mask & HID1_DFS2); 1283 1.56 phx hid1 |= dfs_mask & HID1_DFS4; 1284 1.56 phx break; 1285 1.56 phx } 1286 1.56 phx 1287 1.56 phx if (hid1 != old_hid1) { 1288 1.56 phx __asm volatile("sync"); 1289 1.56 phx mtspr(SPR_HID1, hid1); 1290 1.56 phx __asm volatile("sync;isync"); 1291 1.56 phx } 1292 1.56 phx 1293 1.56 phx splx(s); 1294 1.1 matt } 1295 1.1 matt 1296 1.1 matt #if NSYSMON_ENVSYS > 0 1297 1.1 matt void 1298 1.1 matt cpu_tau_setup(struct cpu_info *ci) 1299 1.1 matt { 1300 1.34 xtraeme struct sysmon_envsys *sme; 1301 1.50 macallan int error, therm_delay; 1302 1.111 jmcneill u_int pvr, vers; 1303 1.111 jmcneill 1304 1.111 jmcneill pvr = mfpvr(); 1305 1.111 jmcneill vers = pvr >> 16; 1306 1.111 jmcneill 1307 1.111 jmcneill if (vers == MPC750 && (pvr & 0xf000) == 0x7000 && 1308 1.111 jmcneill (pvr & 0x0f00) >= 0x0100) { 1309 1.111 jmcneill /* Broadway has dummy TAU registers, just ignore it. */ 1310 1.111 jmcneill return; 1311 1.111 jmcneill } 1312 1.50 macallan 1313 1.50 macallan mtspr(SPR_THRM1, SPR_THRM_VALID); 1314 1.50 macallan mtspr(SPR_THRM2, 0); 1315 1.50 macallan 1316 1.50 macallan /* 1317 1.50 macallan * we need to figure out how much 20+us in units of CPU clock cycles 1318 1.50 macallan * are 1319 1.50 macallan */ 1320 1.50 macallan 1321 1.50 macallan therm_delay = ci->ci_khz / 40; /* 25us just to be safe */ 1322 1.74 kiyohara 1323 1.74 kiyohara mtspr(SPR_THRM3, SPR_THRM_TIMER(therm_delay) | SPR_THRM_ENABLE); 1324 1.1 matt 1325 1.34 xtraeme sme = sysmon_envsys_create(); 1326 1.12 matt 1327 1.34 xtraeme sensor.units = ENVSYS_STEMP; 1328 1.68 pgoyette sensor.state = ENVSYS_SINVALID; 1329 1.34 xtraeme (void)strlcpy(sensor.desc, "CPU Temp", sizeof(sensor.desc)); 1330 1.34 xtraeme if (sysmon_envsys_sensor_attach(sme, &sensor)) { 1331 1.34 xtraeme sysmon_envsys_destroy(sme); 1332 1.34 xtraeme return; 1333 1.34 xtraeme } 1334 1.34 xtraeme 1335 1.74 kiyohara sme->sme_name = device_xname(ci->ci_dev); 1336 1.34 xtraeme sme->sme_cookie = ci; 1337 1.34 xtraeme sme->sme_refresh = cpu_tau_refresh; 1338 1.1 matt 1339 1.34 xtraeme if ((error = sysmon_envsys_register(sme)) != 0) { 1340 1.66 matt aprint_error_dev(ci->ci_dev, 1341 1.66 matt " unable to register with sysmon (%d)\n", error); 1342 1.34 xtraeme sysmon_envsys_destroy(sme); 1343 1.34 xtraeme } 1344 1.1 matt } 1345 1.1 matt 1346 1.1 matt /* Find the temperature of the CPU. */ 1347 1.34 xtraeme void 1348 1.34 xtraeme cpu_tau_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 1349 1.1 matt { 1350 1.1 matt int i, threshold, count; 1351 1.1 matt 1352 1.1 matt threshold = 64; /* Half of the 7-bit sensor range */ 1353 1.1 matt 1354 1.1 matt /* Successive-approximation code adapted from Motorola 1355 1.1 matt * application note AN1800/D, "Programming the Thermal Assist 1356 1.1 matt * Unit in the MPC750 Microprocessor". 1357 1.1 matt */ 1358 1.50 macallan for (i = 5; i >= 0 ; i--) { 1359 1.74 kiyohara mtspr(SPR_THRM1, 1360 1.1 matt SPR_THRM_THRESHOLD(threshold) | SPR_THRM_VALID); 1361 1.1 matt count = 0; 1362 1.74 kiyohara while ((count < 100000) && 1363 1.1 matt ((mfspr(SPR_THRM1) & SPR_THRM_TIV) == 0)) { 1364 1.1 matt count++; 1365 1.1 matt delay(1); 1366 1.1 matt } 1367 1.1 matt if (mfspr(SPR_THRM1) & SPR_THRM_TIN) { 1368 1.74 kiyohara /* The interrupt bit was set, meaning the 1369 1.74 kiyohara * temperature was above the threshold 1370 1.1 matt */ 1371 1.50 macallan threshold += 1 << i; 1372 1.1 matt } else { 1373 1.1 matt /* Temperature was below the threshold */ 1374 1.50 macallan threshold -= 1 << i; 1375 1.1 matt } 1376 1.1 matt } 1377 1.1 matt threshold += 2; 1378 1.1 matt 1379 1.1 matt /* Convert the temperature in degrees C to microkelvin */ 1380 1.34 xtraeme edata->value_cur = (threshold * 1000000) + 273150000; 1381 1.50 macallan edata->state = ENVSYS_SVALID; 1382 1.1 matt } 1383 1.1 matt #endif /* NSYSMON_ENVSYS > 0 */ 1384 1.33 garbled 1385 1.33 garbled #ifdef MULTIPROCESSOR 1386 1.76 kiyohara volatile u_int cpu_spinstart_ack, cpu_spinstart_cpunum; 1387 1.46 garbled 1388 1.33 garbled int 1389 1.60 matt cpu_spinup(device_t self, struct cpu_info *ci) 1390 1.33 garbled { 1391 1.33 garbled volatile struct cpu_hatch_data hatch_data, *h = &hatch_data; 1392 1.33 garbled struct pglist mlist; 1393 1.81 mrg int i, error; 1394 1.61 matt char *hp; 1395 1.33 garbled 1396 1.33 garbled KASSERT(ci != curcpu()); 1397 1.33 garbled 1398 1.46 garbled /* Now allocate a hatch stack */ 1399 1.75 kiyohara error = uvm_pglistalloc(HATCH_STACK_SIZE, 0x10000, 0x10000000, 16, 0, 1400 1.46 garbled &mlist, 1, 1); 1401 1.46 garbled if (error) { 1402 1.46 garbled aprint_error(": unable to allocate hatch stack\n"); 1403 1.46 garbled return -1; 1404 1.46 garbled } 1405 1.46 garbled 1406 1.46 garbled hp = (void *)VM_PAGE_TO_PHYS(TAILQ_FIRST(&mlist)); 1407 1.75 kiyohara memset(hp, 0, HATCH_STACK_SIZE); 1408 1.46 garbled 1409 1.33 garbled /* Initialize secondary cpu's initial lwp to its idlelwp. */ 1410 1.33 garbled ci->ci_curlwp = ci->ci_data.cpu_idlelwp; 1411 1.54 rmind ci->ci_curpcb = lwp_getpcb(ci->ci_curlwp); 1412 1.33 garbled ci->ci_curpm = ci->ci_curpcb->pcb_pm; 1413 1.105 thorpej ci->ci_battable = battable; 1414 1.33 garbled 1415 1.33 garbled cpu_hatch_data = h; 1416 1.70 matt h->hatch_running = 0; 1417 1.70 matt h->hatch_self = self; 1418 1.70 matt h->hatch_ci = ci; 1419 1.70 matt h->hatch_pir = ci->ci_cpuid; 1420 1.46 garbled 1421 1.75 kiyohara cpu_hatch_stack = (uint32_t)hp + HATCH_STACK_SIZE - CALLFRAMELEN; 1422 1.33 garbled ci->ci_lasttb = cpu_info[0].ci_lasttb; 1423 1.33 garbled 1424 1.33 garbled /* copy special registers */ 1425 1.46 garbled 1426 1.70 matt h->hatch_hid0 = mfspr(SPR_HID0); 1427 1.93 macallan #if defined(PPC_OEA64_BRIDGE) || defined (_ARCH_PPC64) 1428 1.94 macallan h->hatch_hid1 = mfspr(SPR_HID1); 1429 1.93 macallan h->hatch_hid4 = mfspr(SPR_HID4); 1430 1.93 macallan h->hatch_hid5 = mfspr(SPR_HID5); 1431 1.93 macallan #endif 1432 1.74 kiyohara 1433 1.70 matt __asm volatile ("mfsdr1 %0" : "=r"(h->hatch_sdr1)); 1434 1.46 garbled for (i = 0; i < 16; i++) { 1435 1.70 matt __asm ("mfsrin %0,%1" : "=r"(h->hatch_sr[i]) : 1436 1.33 garbled "r"(i << ADDR_SR_SHFT)); 1437 1.46 garbled } 1438 1.46 garbled if (oeacpufeat & OEACPU_64) 1439 1.70 matt h->hatch_asr = mfspr(SPR_ASR); 1440 1.46 garbled else 1441 1.70 matt h->hatch_asr = 0; 1442 1.46 garbled 1443 1.91 macallan if ((oeacpufeat & OEACPU_NOBAT) == 0) { 1444 1.91 macallan /* copy the bat regs */ 1445 1.91 macallan __asm volatile ("mfibatu %0,0" : "=r"(h->hatch_ibatu[0])); 1446 1.91 macallan __asm volatile ("mfibatl %0,0" : "=r"(h->hatch_ibatl[0])); 1447 1.91 macallan __asm volatile ("mfibatu %0,1" : "=r"(h->hatch_ibatu[1])); 1448 1.91 macallan __asm volatile ("mfibatl %0,1" : "=r"(h->hatch_ibatl[1])); 1449 1.91 macallan __asm volatile ("mfibatu %0,2" : "=r"(h->hatch_ibatu[2])); 1450 1.91 macallan __asm volatile ("mfibatl %0,2" : "=r"(h->hatch_ibatl[2])); 1451 1.91 macallan __asm volatile ("mfibatu %0,3" : "=r"(h->hatch_ibatu[3])); 1452 1.91 macallan __asm volatile ("mfibatl %0,3" : "=r"(h->hatch_ibatl[3])); 1453 1.91 macallan __asm volatile ("mfdbatu %0,0" : "=r"(h->hatch_dbatu[0])); 1454 1.91 macallan __asm volatile ("mfdbatl %0,0" : "=r"(h->hatch_dbatl[0])); 1455 1.91 macallan __asm volatile ("mfdbatu %0,1" : "=r"(h->hatch_dbatu[1])); 1456 1.91 macallan __asm volatile ("mfdbatl %0,1" : "=r"(h->hatch_dbatl[1])); 1457 1.91 macallan __asm volatile ("mfdbatu %0,2" : "=r"(h->hatch_dbatu[2])); 1458 1.91 macallan __asm volatile ("mfdbatl %0,2" : "=r"(h->hatch_dbatl[2])); 1459 1.91 macallan __asm volatile ("mfdbatu %0,3" : "=r"(h->hatch_dbatu[3])); 1460 1.91 macallan __asm volatile ("mfdbatl %0,3" : "=r"(h->hatch_dbatl[3])); 1461 1.91 macallan __asm volatile ("sync; isync"); 1462 1.91 macallan } 1463 1.33 garbled 1464 1.33 garbled if (md_setup_trampoline(h, ci) == -1) 1465 1.33 garbled return -1; 1466 1.33 garbled md_presync_timebase(h); 1467 1.33 garbled md_start_timebase(h); 1468 1.33 garbled 1469 1.33 garbled /* wait for secondary printf */ 1470 1.46 garbled 1471 1.33 garbled delay(200000); 1472 1.33 garbled 1473 1.76 kiyohara #ifdef CACHE_PROTO_MEI 1474 1.76 kiyohara __asm volatile ("dcbi 0,%0"::"r"(&h->hatch_running):"memory"); 1475 1.76 kiyohara __asm volatile ("sync; isync"); 1476 1.76 kiyohara __asm volatile ("dcbst 0,%0"::"r"(&h->hatch_running):"memory"); 1477 1.76 kiyohara __asm volatile ("sync; isync"); 1478 1.76 kiyohara #endif 1479 1.100 macallan int hatch_bail = 0; 1480 1.100 macallan while ((h->hatch_running < 1) && (hatch_bail < 100000)) { 1481 1.100 macallan delay(1); 1482 1.100 macallan hatch_bail++; 1483 1.100 macallan #ifdef CACHE_PROTO_MEI 1484 1.100 macallan __asm volatile ("dcbi 0,%0"::"r"(&h->hatch_running):"memory"); 1485 1.100 macallan __asm volatile ("sync; isync"); 1486 1.100 macallan __asm volatile ("dcbst 0,%0"::"r"(&h->hatch_running):"memory"); 1487 1.100 macallan __asm volatile ("sync; isync"); 1488 1.100 macallan #endif 1489 1.100 macallan } 1490 1.70 matt if (h->hatch_running < 1) { 1491 1.76 kiyohara #ifdef CACHE_PROTO_MEI 1492 1.76 kiyohara __asm volatile ("dcbi 0,%0"::"r"(&cpu_spinstart_ack):"memory"); 1493 1.76 kiyohara __asm volatile ("sync; isync"); 1494 1.76 kiyohara __asm volatile ("dcbst 0,%0"::"r"(&cpu_spinstart_ack):"memory"); 1495 1.76 kiyohara __asm volatile ("sync; isync"); 1496 1.76 kiyohara #endif 1497 1.46 garbled aprint_error("%d:CPU %d didn't start %d\n", cpu_spinstart_ack, 1498 1.46 garbled ci->ci_cpuid, cpu_spinstart_ack); 1499 1.110 andvar console_debugger(); 1500 1.33 garbled return -1; 1501 1.33 garbled } 1502 1.33 garbled 1503 1.33 garbled return 0; 1504 1.33 garbled } 1505 1.33 garbled 1506 1.33 garbled static volatile int start_secondary_cpu; 1507 1.33 garbled 1508 1.46 garbled register_t 1509 1.46 garbled cpu_hatch(void) 1510 1.33 garbled { 1511 1.33 garbled volatile struct cpu_hatch_data *h = cpu_hatch_data; 1512 1.70 matt struct cpu_info * const ci = h->hatch_ci; 1513 1.54 rmind struct pcb *pcb; 1514 1.33 garbled u_int msr; 1515 1.33 garbled int i; 1516 1.33 garbled 1517 1.33 garbled /* Initialize timebase. */ 1518 1.33 garbled __asm ("mttbl %0; mttbu %0; mttbl %0" :: "r"(0)); 1519 1.33 garbled 1520 1.46 garbled /* 1521 1.46 garbled * Set PIR (Processor Identification Register). i.e. whoami 1522 1.49 chs * Note that PIR is read-only on some CPU versions, so we write to it 1523 1.49 chs * only if it has a different value than we need. 1524 1.46 garbled */ 1525 1.46 garbled 1526 1.46 garbled msr = mfspr(SPR_PIR); 1527 1.70 matt if (msr != h->hatch_pir) 1528 1.70 matt mtspr(SPR_PIR, h->hatch_pir); 1529 1.74 kiyohara 1530 1.64 matt __asm volatile ("mtsprg0 %0" :: "r"(ci)); 1531 1.65 matt curlwp = ci->ci_curlwp; 1532 1.46 garbled cpu_spinstart_ack = 0; 1533 1.33 garbled 1534 1.91 macallan if ((oeacpufeat & OEACPU_NOBAT) == 0) { 1535 1.91 macallan /* Initialize MMU. */ 1536 1.91 macallan __asm ("mtibatu 0,%0" :: "r"(h->hatch_ibatu[0])); 1537 1.91 macallan __asm ("mtibatl 0,%0" :: "r"(h->hatch_ibatl[0])); 1538 1.91 macallan __asm ("mtibatu 1,%0" :: "r"(h->hatch_ibatu[1])); 1539 1.91 macallan __asm ("mtibatl 1,%0" :: "r"(h->hatch_ibatl[1])); 1540 1.91 macallan __asm ("mtibatu 2,%0" :: "r"(h->hatch_ibatu[2])); 1541 1.91 macallan __asm ("mtibatl 2,%0" :: "r"(h->hatch_ibatl[2])); 1542 1.91 macallan __asm ("mtibatu 3,%0" :: "r"(h->hatch_ibatu[3])); 1543 1.91 macallan __asm ("mtibatl 3,%0" :: "r"(h->hatch_ibatl[3])); 1544 1.91 macallan __asm ("mtdbatu 0,%0" :: "r"(h->hatch_dbatu[0])); 1545 1.91 macallan __asm ("mtdbatl 0,%0" :: "r"(h->hatch_dbatl[0])); 1546 1.91 macallan __asm ("mtdbatu 1,%0" :: "r"(h->hatch_dbatu[1])); 1547 1.91 macallan __asm ("mtdbatl 1,%0" :: "r"(h->hatch_dbatl[1])); 1548 1.91 macallan __asm ("mtdbatu 2,%0" :: "r"(h->hatch_dbatu[2])); 1549 1.91 macallan __asm ("mtdbatl 2,%0" :: "r"(h->hatch_dbatl[2])); 1550 1.91 macallan __asm ("mtdbatu 3,%0" :: "r"(h->hatch_dbatu[3])); 1551 1.91 macallan __asm ("mtdbatl 3,%0" :: "r"(h->hatch_dbatl[3])); 1552 1.91 macallan } 1553 1.33 garbled 1554 1.92 macallan #ifdef PPC_OEA64_BRIDGE 1555 1.91 macallan if ((oeacpufeat & OEACPU_64_BRIDGE) != 0) { 1556 1.93 macallan 1557 1.91 macallan mtspr64(SPR_HID0, h->hatch_hid0); 1558 1.94 macallan mtspr64(SPR_HID1, h->hatch_hid1); 1559 1.93 macallan mtspr64(SPR_HID4, h->hatch_hid4); 1560 1.93 macallan mtspr64(SPR_HID5, h->hatch_hid5); 1561 1.93 macallan mtspr64(SPR_HIOR, 0); 1562 1.91 macallan } else 1563 1.92 macallan #endif 1564 1.91 macallan mtspr(SPR_HID0, h->hatch_hid0); 1565 1.33 garbled 1566 1.91 macallan if ((oeacpufeat & OEACPU_NOBAT) == 0) { 1567 1.91 macallan __asm ("mtibatl 0,%0; mtibatu 0,%1; mtdbatl 0,%0; mtdbatu 0,%1;" 1568 1.91 macallan :: "r"(battable[0].batl), "r"(battable[0].batu)); 1569 1.91 macallan } 1570 1.33 garbled 1571 1.46 garbled __asm volatile ("sync"); 1572 1.33 garbled for (i = 0; i < 16; i++) 1573 1.70 matt __asm ("mtsrin %0,%1" :: "r"(h->hatch_sr[i]), "r"(i << ADDR_SR_SHFT)); 1574 1.46 garbled __asm volatile ("sync; isync"); 1575 1.46 garbled 1576 1.46 garbled if (oeacpufeat & OEACPU_64) 1577 1.70 matt mtspr(SPR_ASR, h->hatch_asr); 1578 1.33 garbled 1579 1.46 garbled cpu_spinstart_ack = 1; 1580 1.46 garbled __asm ("ptesync"); 1581 1.70 matt __asm ("mtsdr1 %0" :: "r"(h->hatch_sdr1)); 1582 1.46 garbled __asm volatile ("sync; isync"); 1583 1.46 garbled 1584 1.46 garbled cpu_spinstart_ack = 5; 1585 1.46 garbled for (i = 0; i < 16; i++) 1586 1.70 matt __asm ("mfsrin %0,%1" : "=r"(h->hatch_sr[i]) : 1587 1.46 garbled "r"(i << ADDR_SR_SHFT)); 1588 1.33 garbled 1589 1.33 garbled /* Enable I/D address translations. */ 1590 1.46 garbled msr = mfmsr(); 1591 1.33 garbled msr |= PSL_IR|PSL_DR|PSL_ME|PSL_RI; 1592 1.46 garbled mtmsr(msr); 1593 1.33 garbled __asm volatile ("sync; isync"); 1594 1.46 garbled cpu_spinstart_ack = 2; 1595 1.33 garbled 1596 1.33 garbled md_sync_timebase(h); 1597 1.33 garbled 1598 1.70 matt cpu_setup(h->hatch_self, ci); 1599 1.33 garbled 1600 1.70 matt h->hatch_running = 1; 1601 1.33 garbled __asm volatile ("sync; isync"); 1602 1.33 garbled 1603 1.33 garbled while (start_secondary_cpu == 0) 1604 1.33 garbled ; 1605 1.33 garbled 1606 1.33 garbled __asm volatile ("sync; isync"); 1607 1.33 garbled 1608 1.46 garbled aprint_normal("cpu%d started\n", curcpu()->ci_index); 1609 1.33 garbled __asm volatile ("mtdec %0" :: "r"(ticks_per_intr)); 1610 1.33 garbled 1611 1.33 garbled md_setup_interrupts(); 1612 1.33 garbled 1613 1.33 garbled ci->ci_ipending = 0; 1614 1.33 garbled ci->ci_cpl = 0; 1615 1.33 garbled 1616 1.33 garbled mtmsr(mfmsr() | PSL_EE); 1617 1.54 rmind pcb = lwp_getpcb(ci->ci_data.cpu_idlelwp); 1618 1.54 rmind return pcb->pcb_sp; 1619 1.33 garbled } 1620 1.33 garbled 1621 1.33 garbled void 1622 1.53 cegger cpu_boot_secondary_processors(void) 1623 1.33 garbled { 1624 1.33 garbled start_secondary_cpu = 1; 1625 1.33 garbled __asm volatile ("sync"); 1626 1.33 garbled } 1627 1.33 garbled 1628 1.33 garbled #endif /*MULTIPROCESSOR*/ 1629