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 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/promif_impl.h> 28 #include <sys/machsystm.h> 29 #include <sys/lpad.h> 30 #include <sys/vmsystm.h> 31 #include <sys/prom_plat.h> 32 #include <sys/ldoms.h> 33 #include <sys/kobj.h> 34 #include <sys/reboot.h> 35 #include <sys/hypervisor_api.h> 36 #include <sys/mdesc.h> 37 #include <sys/mach_descrip.h> 38 #include <sys/cpu_module.h> 39 40 #ifndef _KMDB 41 #include <sys/pte.h> 42 #include <vm/hat_sfmmu.h> 43 #include <sys/memlist_impl.h> 44 45 static processorid_t cif_cpu; 46 static struct translation *cif_prom_trans; 47 static size_t cif_prom_ntrans; 48 49 int cif_cpu_mp_ready; 50 int (*prom_cif_handler)(void *) = NULL; 51 52 extern struct memlist *phys_avail; 53 extern struct vnode prom_ppages; 54 extern void kdi_tlb_page_unlock(caddr_t, int); 55 56 #define COMBINE(hi, lo) (((uint64_t)(uint32_t)(hi) << 32) | (uint32_t)(lo)) 57 #define OFW_PT_START_ADDR 0xfffffffc00000000 /* OBP PT start */ 58 #define OFW_PT_END_ADDR 0xffffffffffffffff /* OBP PT end */ 59 60 #define PROM_ADDR(a) (((a) >= OFW_START_ADDR && (a) <= OFW_END_ADDR) || \ 61 ((a) >= OFW_PT_START_ADDR && (a) <= OFW_PT_END_ADDR)) 62 #endif 63 64 #ifdef DEBUG 65 uint_t cif_debug; 66 int prom_free_debug; 67 #define PMFREE_DEBUG(args...) if (prom_free_debug) printf(args) 68 #else 69 #define PMFREE_DEBUG(args...) 70 #endif 71 72 extern int (*cif_handler)(void *); 73 74 typedef struct { 75 char *name; 76 cif_func_t func; 77 } cif_callback_t; 78 79 static cif_callback_t cb_table[] = { 80 { "getprop", promif_getprop }, 81 { "getproplen", promif_getproplen }, 82 { "nextprop", promif_nextprop }, 83 { "peer", promif_nextnode }, 84 { "child", promif_childnode }, 85 { "parent", promif_parentnode }, 86 { "enter", promif_enter_mon }, 87 { "exit", promif_exit_to_mon }, 88 { "boot", promif_reboot }, 89 { "write", promif_write }, 90 { "read", promif_read }, 91 { "interpret", promif_interpret }, 92 { "finddevice", promif_finddevice }, 93 { "instance-to-package", promif_instance_to_package }, 94 #ifndef _KMDB 95 { "setprop", promif_setprop }, 96 { "test", promif_test }, 97 { "instance-to-path", promif_instance_to_path }, 98 { "SUNW,power-off", promif_power_off }, 99 { "SUNW,asr-list-keys-len", promif_asr_list_keys_len }, 100 { "SUNW,asr-list-keys", promif_asr_list_keys }, 101 { "SUNW,asr-export-len", promif_asr_export_len }, 102 { "SUNW,asr-export", promif_asr_export }, 103 { "SUNW,set-security-key", promif_set_security_key }, 104 { "SUNW,get-security-key", promif_get_security_key }, 105 { "SUNW,start-cpu-by-cpuid", promif_start_cpu }, 106 { "SUNW,set-trap-table", promif_set_mmfsa_traptable }, 107 { "SUNW,set-sun4v-api-version", promif_set_sun4v_api_version }, 108 { "SUNW,get-sun4v-api-version", promif_get_sun4v_api_version }, 109 #endif 110 { NULL, NULL } 111 }; 112 113 cif_func_t 114 promif_find_cif_callback(char *opname) 115 { 116 cif_callback_t *cb; 117 118 if (opname == NULL) 119 return (NULL); 120 121 for (cb = cb_table; cb->name; cb++) { 122 if (prom_strcmp(cb->name, opname) == 0) 123 break; 124 } 125 126 return (cb->func); 127 } 128 129 static int 130 kern_cif_handler(void *p) 131 { 132 cell_t *ci = (cell_t *)p; 133 char *opname; 134 cif_func_t func; 135 int rv; 136 137 ASSERT(cif_handler == kern_cif_handler); 138 139 #ifndef _KMDB 140 cif_cpu = getprocessorid(); 141 #endif 142 143 opname = p1275_cell2ptr(ci[0]); 144 145 /* lookup the callback for the desired operation */ 146 func = promif_find_cif_callback(opname); 147 148 if (func == NULL) { 149 #ifdef _KMDB 150 prom_fatal_error("sun4v unsupported CIFs\n"); 151 #else 152 cmn_err(CE_CONT, "!sun4v unsupported CIF: %s\n", opname); 153 return (-1); 154 #endif 155 } 156 157 /* callback found, execute it */ 158 rv = func(p); 159 160 #ifndef _KMDB 161 cif_cpu = -1; 162 #endif 163 164 return (rv); 165 } 166 167 #ifdef _KMDB 168 169 void 170 cif_init(char *pgmname, caddr_t root, ihandle_t in, ihandle_t out, 171 phandle_t pin, phandle_t pout, pnode_t chosen, pnode_t options) 172 { 173 /* initialize pointer to a copy of OBP device tree */ 174 promif_stree_setroot(root); 175 176 promif_set_nodes(chosen, options); 177 178 /* initialize io parameters */ 179 promif_io_init(in, out, pin, pout); 180 181 /* 182 * Switch CIF handler to the kernel. 183 */ 184 if (pgmname != NULL) 185 prom_init(pgmname, (void *)kern_cif_handler); 186 else 187 cif_handler = kern_cif_handler; 188 } 189 190 #else 191 192 static struct translation * 193 read_prom_mappings(size_t *ntransp) 194 { 195 char *prop = "translations"; 196 pnode_t node; 197 size_t translen; 198 ihandle_t immu; 199 struct translation *transroot; 200 201 *ntransp = 0; 202 203 /* 204 * the "translations" property is associated with the mmu node 205 */ 206 if ((immu = prom_mmu_ihandle()) == (ihandle_t)-1) { 207 PMFREE_DEBUG("no mmu ihandle"); 208 return (NULL); 209 } 210 node = (pnode_t)prom_getphandle(immu); 211 if (node == OBP_NONODE || node == OBP_BADNODE) { 212 PMFREE_DEBUG("no mmu node"); 213 return (NULL); 214 } 215 216 if ((translen = prom_getproplen(node, prop)) == -1) { 217 PMFREE_DEBUG("no translations property"); 218 return (NULL); 219 } 220 transroot = (struct translation *)kmem_zalloc(translen, KM_SLEEP); 221 222 if (prom_getprop(node, prop, (caddr_t)transroot) == -1) { 223 PMFREE_DEBUG("translations getprop failed"); 224 kmem_free(transroot, translen); 225 return (NULL); 226 } 227 *ntransp = translen / sizeof (*transroot); 228 229 return (transroot); 230 } 231 232 static void 233 unmap_prom_mappings(struct translation *transroot, size_t ntransroot) 234 { 235 int i, j, rv; 236 int npgs, nunmapped, nfreed, nskipped; 237 char *p; 238 tte_t tte; 239 pfn_t pfn; 240 page_t *pp; 241 uint64_t vaddr; 242 struct translation *promt; 243 cpuset_t other_cpus; 244 245 /* 246 * During startup isa_list is allocated in OBP address space 247 * so it needs to be re-allocated in kernel address space 248 * before OBP memory is unmapped. 249 * 250 * see cpu_setup_common(). 251 */ 252 p = kmem_zalloc(strlen(isa_list) + 1, KM_SLEEP); 253 (void) strcpy(p, isa_list); 254 isa_list = p; 255 256 nfreed = 0; 257 nunmapped = 0; 258 nskipped = 0; 259 260 for (i = 0, promt = transroot; i < ntransroot; i++, promt++) { 261 ASSERT(promt->tte_hi != 0); 262 ASSERT32(promt->virt_hi == 0 && promt->size_hi == 0); 263 264 vaddr = COMBINE(promt->virt_hi, promt->virt_lo); 265 266 if (!PROM_ADDR(vaddr)) { 267 nskipped++; 268 continue; 269 } 270 271 npgs = mmu_btopr(COMBINE(promt->size_hi, promt->size_lo)); 272 273 if (npgs > 1) { 274 PMFREE_DEBUG("large trans vaddr=0x%lx, npgs=%d\n", 275 vaddr, npgs); 276 } 277 for (j = 0; j < npgs; j++) { 278 279 pfn = sfmmu_vatopfn((caddr_t)vaddr, KHATID, &tte); 280 281 if (pfn == PFN_INVALID) { 282 tte.tte_inthi = promt->tte_hi; 283 tte.tte_intlo = promt->tte_lo; 284 pfn = TTE_TO_PFN((caddr_t)COMBINE( 285 promt->virt_hi, promt->virt_lo), &tte); 286 PMFREE_DEBUG( 287 "no mapping for vaddr=0x%lx (opfn=0x%lx)\n", 288 vaddr, pfn); 289 break; 290 } 291 ASSERT(!TTE_IS_LOCKED(&tte)); 292 ASSERT(TTE_IS_8K(&tte)); 293 294 /* 295 * Unload the current mapping for the page and 296 * if it is the last mapping, free the page. 297 */ 298 pp = page_numtopp_nolock(pfn); 299 PMFREE_DEBUG("unmap vaddr=0x%lx pfn=0x%lx pp=0x%p", 300 vaddr, pfn, (void *)pp); 301 ASSERT(pp); 302 ASSERT(PAGE_EXCL(pp)); 303 ASSERT(PP_ISNORELOC(pp)); 304 ASSERT(!PP_ISFREE(pp)); 305 ASSERT(page_find(&prom_ppages, pfn)); 306 ASSERT(page_get_pagecnt(pp->p_szc) == 1); 307 308 hat_unload(kas.a_hat, (caddr_t)vaddr, PAGESIZE, 309 HAT_UNLOAD_UNLOCK); 310 311 if (pp->p_mapping) { 312 PMFREE_DEBUG(" skip\n"); 313 } else { 314 PP_CLRNORELOC(pp); 315 page_destroy(pp, 0); 316 memlist_write_lock(); 317 rv = memlist_add_span(pfn << PAGESHIFT, 318 PAGESIZE, &phys_avail); 319 ASSERT(rv == MEML_SPANOP_OK); 320 memlist_write_unlock(); 321 PMFREE_DEBUG(" free\n"); 322 nfreed++; 323 } 324 nunmapped++; 325 vaddr += PAGESIZE; 326 } 327 } 328 329 if (transroot) { 330 PMFREE_DEBUG("nunmapped=%d nfreed=%d nskipped=%d\n", 331 nunmapped, nfreed, nskipped); 332 kmem_free(transroot, ntransroot * sizeof (*transroot)); 333 } 334 335 /* 336 * Unload OBP permanent mappings. 337 */ 338 kdi_tlb_page_unlock((caddr_t)OFW_START_ADDR, 1); 339 kpreempt_disable(); 340 other_cpus = cpu_ready_set; 341 CPUSET_DEL(other_cpus, CPU->cpu_id); 342 xt_some(other_cpus, vtag_unmap_perm_tl1, (uint64_t)OFW_START_ADDR, 343 KCONTEXT); 344 kpreempt_enable(); 345 } 346 347 static void cache_prom_data(void); 348 349 /* 350 * This function returns 1 if the current thread is executing in 351 * the CIF and 0 otherwise. This is useful information to know 352 * since code that implements CIF handlers can assume that it has 353 * gone through the kern_preprom() entry point, implying it is 354 * running single threaded, has preemption disabled, etc. 355 */ 356 int 357 promif_in_cif(void) 358 { 359 int mycpuid = getprocessorid(); 360 361 return ((cif_cpu == mycpuid) ? 1 : 0); 362 } 363 364 /* 365 * Check that all cpus in the MD are within range (< NCPU). Attempt 366 * to stop any that aren't. 367 */ 368 static void 369 cif_check_cpus(void) 370 { 371 md_t *mdp; 372 mde_cookie_t rootnode; 373 size_t listsz; 374 int i; 375 mde_cookie_t *listp = NULL; 376 int num_nodes; 377 uint64_t cpuid; 378 int status; 379 380 mdp = md_get_handle(); 381 ASSERT(mdp); 382 383 rootnode = md_root_node(mdp); 384 ASSERT(rootnode != MDE_INVAL_ELEM_COOKIE); 385 386 num_nodes = md_node_count(mdp); 387 ASSERT(num_nodes > 0); 388 389 listsz = num_nodes * sizeof (mde_cookie_t); 390 listp = kmem_zalloc(listsz, KM_SLEEP); 391 392 num_nodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, "cpu"), 393 md_find_name(mdp, "fwd"), listp); 394 395 if (num_nodes <= 0) 396 goto done; 397 398 for (i = 0; i < num_nodes; i++) { 399 if (md_get_prop_val(mdp, listp[i], "id", &cpuid)) { 400 cmn_err(CE_WARN, "cif_check_cpus: " 401 "CPU instance %d has no 'id' property", i); 402 continue; 403 } 404 405 mutex_enter(&cpu_lock); 406 407 if (cpuid >= NCPU) { 408 status = stopcpu_bycpuid(cpuid); 409 if (status != 0 && status != ENOTSUP) 410 cmn_err(CE_PANIC, "failed to stop cpu %lu (%d)", 411 cpuid, status); 412 } 413 414 mutex_exit(&cpu_lock); 415 } 416 417 done: 418 kmem_free(listp, listsz); 419 (void) md_fini_handle(mdp); 420 } 421 422 void 423 cif_init(void) 424 { 425 void (*kmdb_cb)(void); 426 uint64_t rtba; 427 uint64_t rv; 428 size_t ntransroot; 429 struct translation *transroot; 430 431 /* 432 * Check if domaining is enabled. If not, do not 433 * initialize the kernel CIF handler. 434 */ 435 if (!domaining_enabled()) 436 return; 437 438 transroot = read_prom_mappings(&ntransroot); 439 440 /* 441 * Cache PROM data that is needed later, e.g. a shadow 442 * copy of the device tree, IO mappings, etc. 443 */ 444 cache_prom_data(); 445 446 /* 447 * Prepare to take over the get/set of environmental variables. 448 */ 449 promif_prop_init(); 450 451 /* 452 * Switch CIF handler to the kernel. 453 */ 454 prom_cif_handler = cif_handler; 455 456 promif_preprom(); 457 cif_handler = kern_cif_handler; 458 459 /* 460 * Take over rtba for the boot CPU. The rtba for 461 * all other CPUs are set as they enter the system. 462 */ 463 rtba = va_to_pa(&trap_table); 464 if ((rv = hv_cpu_set_rtba(&rtba)) != H_EOK) 465 panic("hv_cpu_set_rtba failed: %ld\n", rv); 466 467 promif_postprom(); 468 469 /* 470 * If the system has been booted with kmdb we need kmdb to 471 * use the kernel cif handler instead of the PROM cif handler. 472 */ 473 if (boothowto & RB_KMDB) { 474 kmdb_cb = (void (*)(void))modlookup("misc/kmdbmod", 475 "kctl_switch_promif"); 476 ASSERT(kmdb_cb != NULL); 477 (*kmdb_cb)(); 478 } 479 480 cif_check_cpus(); 481 482 if (transroot != NULL) 483 unmap_prom_mappings(transroot, ntransroot); 484 } 485 486 static void 487 cache_prom_data(void) 488 { 489 /* initialize copy of OBP device tree */ 490 promif_stree_init(); 491 492 /* initialize io parameters */ 493 promif_io_init(); 494 } 495 496 #endif /* _KMDB */ 497