1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/machsystm.h> 29 #include <sys/archsystm.h> 30 #include <sys/vm.h> 31 #include <sys/cpu.h> 32 #include <sys/atomic.h> 33 #include <sys/reboot.h> 34 #include <sys/kdi.h> 35 #include <sys/bootconf.h> 36 #include <sys/memlist_plat.h> 37 #include <sys/memlist_impl.h> 38 #include <sys/prom_plat.h> 39 #include <sys/prom_isa.h> 40 #include <sys/autoconf.h> 41 #include <sys/intreg.h> 42 #include <sys/ivintr.h> 43 #include <sys/fpu/fpusystm.h> 44 #include <sys/iommutsb.h> 45 #include <vm/vm_dep.h> 46 #include <vm/seg_kmem.h> 47 #include <vm/seg_kpm.h> 48 #include <vm/seg_map.h> 49 #include <vm/seg_kp.h> 50 #include <sys/sysconf.h> 51 #include <vm/hat_sfmmu.h> 52 #include <sys/kobj.h> 53 #include <sys/sun4asi.h> 54 #include <sys/clconf.h> 55 #include <sys/platform_module.h> 56 #include <sys/panic.h> 57 #include <sys/cpu_sgnblk_defs.h> 58 #include <sys/clock.h> 59 #include <sys/fpras_impl.h> 60 #include <sys/prom_debug.h> 61 #include <sys/traptrace.h> 62 #include <sys/memnode.h> 63 #include <sys/mem_cage.h> 64 65 /* 66 * fpRAS implementation structures. 67 */ 68 struct fpras_chkfn *fpras_chkfnaddrs[FPRAS_NCOPYOPS]; 69 struct fpras_chkfngrp *fpras_chkfngrps; 70 struct fpras_chkfngrp *fpras_chkfngrps_base; 71 int fpras_frequency = -1; 72 int64_t fpras_interval = -1; 73 74 void 75 setup_trap_table(void) 76 { 77 intr_init(CPU); /* init interrupt request free list */ 78 setwstate(WSTATE_KERN); 79 prom_set_traptable(&trap_table); 80 } 81 82 void 83 mach_fpras() 84 { 85 if (fpras_implemented && !fpras_disable) { 86 int i; 87 struct fpras_chkfngrp *fcgp; 88 size_t chkfngrpsallocsz; 89 90 /* 91 * Note that we size off of NCPU and setup for 92 * all those possibilities regardless of whether 93 * the cpu id is present or not. We do this so that 94 * we don't have any construction or destruction 95 * activity to perform at DR time, and it's not 96 * costly in memory. We require block alignment. 97 */ 98 chkfngrpsallocsz = NCPU * sizeof (struct fpras_chkfngrp); 99 fpras_chkfngrps_base = kmem_alloc(chkfngrpsallocsz, KM_SLEEP); 100 if (IS_P2ALIGNED((uintptr_t)fpras_chkfngrps_base, 64)) { 101 fpras_chkfngrps = fpras_chkfngrps_base; 102 } else { 103 kmem_free(fpras_chkfngrps_base, chkfngrpsallocsz); 104 chkfngrpsallocsz += 64; 105 fpras_chkfngrps_base = kmem_alloc(chkfngrpsallocsz, 106 KM_SLEEP); 107 fpras_chkfngrps = (struct fpras_chkfngrp *) 108 P2ROUNDUP((uintptr_t)fpras_chkfngrps_base, 64); 109 } 110 111 /* 112 * Copy our check function into place for each copy operation 113 * and each cpu id. 114 */ 115 fcgp = &fpras_chkfngrps[0]; 116 for (i = 0; i < FPRAS_NCOPYOPS; ++i) 117 bcopy((void *)fpras_chkfn_type1, &fcgp->fpras_fn[i], 118 sizeof (struct fpras_chkfn)); 119 for (i = 1; i < NCPU; ++i) 120 *(&fpras_chkfngrps[i]) = *fcgp; 121 122 /* 123 * At definition fpras_frequency is set to -1, and it will 124 * still have that value unless changed in /etc/system (not 125 * strictly supported, but not preventable). The following 126 * both sets the default and sanity checks anything from 127 * /etc/system. 128 */ 129 if (fpras_frequency < 0) 130 fpras_frequency = FPRAS_DEFAULT_FREQUENCY; 131 132 /* 133 * Now calculate fpras_interval. When fpras_interval 134 * becomes non-negative fpras checks will commence 135 * (copies before this point in boot will bypass fpras). 136 * Our stores of instructions must be visible; no need 137 * to flush as they're never been executed before. 138 */ 139 membar_producer(); 140 fpras_interval = (fpras_frequency == 0) ? 141 0 : sys_tick_freq / fpras_frequency; 142 } 143 } 144 145 void 146 mach_hw_copy_limit(void) 147 { 148 if (!fpu_exists) { 149 use_hw_bcopy = 0; 150 hw_copy_limit_1 = 0; 151 hw_copy_limit_2 = 0; 152 hw_copy_limit_4 = 0; 153 hw_copy_limit_8 = 0; 154 use_hw_bzero = 0; 155 } 156 } 157 158 void 159 load_tod_module() 160 { 161 /* 162 * Load tod driver module for the tod part found on this system. 163 * Recompute the cpu frequency/delays based on tod as tod part 164 * tends to keep time more accurately. 165 */ 166 if (tod_module_name == NULL || modload("tod", tod_module_name) == -1) 167 halt("Can't load tod module"); 168 } 169 170 void 171 mach_memscrub(void) 172 { 173 /* 174 * Startup memory scrubber, if not running fpu emulation code. 175 */ 176 177 if (fpu_exists) { 178 if (memscrub_init()) { 179 cmn_err(CE_WARN, 180 "Memory scrubber failed to initialize"); 181 } 182 } 183 } 184 185 void 186 mach_cpu_halt_idle() 187 { 188 /* no suport for halting idle CPU */ 189 } 190 191 /*ARGSUSED*/ 192 void 193 cpu_intrq_setup(struct cpu *cp) 194 { 195 /* Interrupt mondo queues not applicable to sun4u */ 196 } 197 198 /*ARGSUSED*/ 199 void 200 cpu_intrq_register(struct cpu *cp) 201 { 202 /* Interrupt/error queues not applicable to sun4u */ 203 } 204 205 /*ARGSUSED*/ 206 void 207 mach_htraptrace_setup(int cpuid) 208 { 209 /* Setup hypervisor traptrace buffer, not applicable to sun4u */ 210 } 211 212 /*ARGSUSED*/ 213 void 214 mach_htraptrace_configure(int cpuid) 215 { 216 /* enable/ disable hypervisor traptracing, not applicable to sun4u */ 217 } 218 219 /*ARGSUSED*/ 220 void 221 mach_htraptrace_init(void) 222 { 223 /* allocate hypervisor traptrace buffer, not applicable to sun4u */ 224 } 225 226 /*ARGSUSED*/ 227 void 228 mach_htraptrace_cleanup(int cpuid) 229 { 230 /* cleanup hypervisor traptrace buffer, not applicable to sun4u */ 231 } 232 233 void 234 mach_descrip_init(void) 235 { 236 /* Obtain Machine description - only for sun4v */ 237 } 238 239 void 240 hsvc_setup(void) 241 { 242 /* Setup hypervisor services, not applicable to sun4u */ 243 } 244 245 /* 246 * Return true if the machine we're running on is a Positron. 247 * (Positron is an unsupported developers platform.) 248 */ 249 int 250 iam_positron(void) 251 { 252 char model[32]; 253 const char proto_model[] = "SUNW,501-2732"; 254 pnode_t root = prom_rootnode(); 255 256 if (prom_getproplen(root, "model") != sizeof (proto_model)) 257 return (0); 258 259 (void) prom_getprop(root, "model", model); 260 if (strcmp(model, proto_model) == 0) 261 return (1); 262 return (0); 263 } 264 265 /* 266 * Find a physically contiguous area of twice the largest ecache size 267 * to be used while doing displacement flush of ecaches. 268 */ 269 uint64_t 270 ecache_flush_address(void) 271 { 272 struct memlist *pmem; 273 uint64_t flush_size; 274 uint64_t ret_val; 275 276 flush_size = ecache_size * 2; 277 for (pmem = phys_install; pmem; pmem = pmem->next) { 278 ret_val = P2ROUNDUP(pmem->address, ecache_size); 279 if (ret_val + flush_size <= pmem->address + pmem->size) 280 return (ret_val); 281 } 282 return ((uint64_t)-1); 283 } 284 285 /* 286 * Called with the memlist lock held to say that phys_install has 287 * changed. 288 */ 289 void 290 phys_install_has_changed(void) 291 { 292 /* 293 * Get the new address into a temporary just in case panicking 294 * involves use of ecache_flushaddr. 295 */ 296 uint64_t new_addr; 297 298 new_addr = ecache_flush_address(); 299 if (new_addr == (uint64_t)-1) { 300 cmn_err(CE_PANIC, 301 "ecache_flush_address(): failed, ecache_size=%x", 302 ecache_size); 303 /*NOTREACHED*/ 304 } 305 ecache_flushaddr = new_addr; 306 membar_producer(); 307 } 308