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, nskipped_io; 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 nskipped_io = 0; 260 261 for (i = 0, promt = transroot; i < ntransroot; i++, promt++) { 262 ASSERT(promt->tte_hi != 0); 263 ASSERT32(promt->virt_hi == 0 && promt->size_hi == 0); 264 265 vaddr = COMBINE(promt->virt_hi, promt->virt_lo); 266 267 if (!PROM_ADDR(vaddr)) { 268 nskipped++; 269 continue; 270 } 271 272 npgs = mmu_btopr(COMBINE(promt->size_hi, promt->size_lo)); 273 274 if (npgs > 1) { 275 PMFREE_DEBUG("large trans vaddr=0x%lx, npgs=%d\n", 276 vaddr, npgs); 277 } 278 for (j = 0; j < npgs; j++) { 279 280 pfn = sfmmu_vatopfn((caddr_t)vaddr, KHATID, &tte); 281 282 if (pfn == PFN_INVALID) { 283 tte.tte_inthi = promt->tte_hi; 284 tte.tte_intlo = promt->tte_lo; 285 pfn = TTE_TO_PFN((caddr_t)COMBINE( 286 promt->virt_hi, promt->virt_lo), &tte); 287 PMFREE_DEBUG( 288 "no mapping for vaddr=0x%lx (opfn=0x%lx)\n", 289 vaddr, pfn); 290 break; 291 } 292 ASSERT(!TTE_IS_LOCKED(&tte)); 293 ASSERT(TTE_IS_8K(&tte)); 294 295 /* 296 * Unload the current mapping for the pfn and 297 * if it is the last mapping for a memory page, 298 * free the page. 299 */ 300 PMFREE_DEBUG("unmap vaddr=0x%lx pfn=0x%lx", vaddr, pfn); 301 302 hat_unload(kas.a_hat, (caddr_t)vaddr, PAGESIZE, 303 HAT_UNLOAD_UNLOCK); 304 305 if (pf_is_memory(pfn)) { 306 pp = page_numtopp_nolock(pfn); 307 PMFREE_DEBUG(" pp=0x%p", (void *)pp); 308 ASSERT(pp); 309 ASSERT(PAGE_EXCL(pp)); 310 ASSERT(PP_ISNORELOC(pp)); 311 ASSERT(!PP_ISFREE(pp)); 312 ASSERT(page_find(&prom_ppages, pfn)); 313 ASSERT(page_get_pagecnt(pp->p_szc) == 1); 314 315 if (pp->p_mapping) { 316 PMFREE_DEBUG(" skip\n"); 317 } else { 318 PP_CLRNORELOC(pp); 319 page_destroy(pp, 0); 320 memlist_write_lock(); 321 rv = memlist_add_span(pfn << PAGESHIFT, 322 PAGESIZE, &phys_avail); 323 ASSERT(rv == MEML_SPANOP_OK); 324 memlist_write_unlock(); 325 PMFREE_DEBUG(" free\n"); 326 nfreed++; 327 } 328 } else { 329 nskipped_io++; 330 PMFREE_DEBUG(" skip IO\n"); 331 } 332 nunmapped++; 333 vaddr += PAGESIZE; 334 } 335 } 336 337 if (transroot) { 338 PMFREE_DEBUG( 339 "nunmapped=%d nfreed=%d nskipped=%d nskipped_io=%d\n", 340 nunmapped, nfreed, nskipped, nskipped_io); 341 kmem_free(transroot, ntransroot * sizeof (*transroot)); 342 } 343 344 /* 345 * Unload OBP permanent mappings. 346 */ 347 kdi_tlb_page_unlock((caddr_t)OFW_START_ADDR, 1); 348 kpreempt_disable(); 349 other_cpus = cpu_ready_set; 350 CPUSET_DEL(other_cpus, CPU->cpu_id); 351 xt_some(other_cpus, vtag_unmap_perm_tl1, (uint64_t)OFW_START_ADDR, 352 KCONTEXT); 353 kpreempt_enable(); 354 } 355 356 static void cache_prom_data(void); 357 358 /* 359 * This function returns 1 if the current thread is executing in 360 * the CIF and 0 otherwise. This is useful information to know 361 * since code that implements CIF handlers can assume that it has 362 * gone through the kern_preprom() entry point, implying it is 363 * running single threaded, has preemption disabled, etc. 364 */ 365 int 366 promif_in_cif(void) 367 { 368 int mycpuid = getprocessorid(); 369 370 return ((cif_cpu == mycpuid) ? 1 : 0); 371 } 372 373 /* 374 * Check that all cpus in the MD are within range (< NCPU). Attempt 375 * to stop any that aren't. 376 */ 377 static void 378 cif_check_cpus(void) 379 { 380 md_t *mdp; 381 mde_cookie_t rootnode; 382 size_t listsz; 383 int i; 384 mde_cookie_t *listp = NULL; 385 int num_nodes; 386 uint64_t cpuid; 387 int status; 388 389 mdp = md_get_handle(); 390 ASSERT(mdp); 391 392 rootnode = md_root_node(mdp); 393 ASSERT(rootnode != MDE_INVAL_ELEM_COOKIE); 394 395 num_nodes = md_node_count(mdp); 396 ASSERT(num_nodes > 0); 397 398 listsz = num_nodes * sizeof (mde_cookie_t); 399 listp = kmem_zalloc(listsz, KM_SLEEP); 400 401 num_nodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, "cpu"), 402 md_find_name(mdp, "fwd"), listp); 403 404 if (num_nodes <= 0) 405 goto done; 406 407 for (i = 0; i < num_nodes; i++) { 408 if (md_get_prop_val(mdp, listp[i], "id", &cpuid)) { 409 cmn_err(CE_WARN, "cif_check_cpus: " 410 "CPU instance %d has no 'id' property", i); 411 continue; 412 } 413 414 mutex_enter(&cpu_lock); 415 416 if (cpuid >= NCPU) { 417 status = stopcpu_bycpuid(cpuid); 418 if (status != 0 && status != ENOTSUP) 419 cmn_err(CE_PANIC, "failed to stop cpu %lu (%d)", 420 cpuid, status); 421 } 422 423 mutex_exit(&cpu_lock); 424 } 425 426 done: 427 kmem_free(listp, listsz); 428 (void) md_fini_handle(mdp); 429 } 430 431 void 432 cif_init(void) 433 { 434 void (*kmdb_cb)(void); 435 uint64_t rtba; 436 uint64_t rv; 437 size_t ntransroot; 438 struct translation *transroot; 439 440 /* 441 * Check if domaining is enabled. If not, do not 442 * initialize the kernel CIF handler. 443 */ 444 if (!domaining_enabled()) 445 return; 446 447 transroot = read_prom_mappings(&ntransroot); 448 449 /* 450 * Cache PROM data that is needed later, e.g. a shadow 451 * copy of the device tree, IO mappings, etc. 452 */ 453 cache_prom_data(); 454 455 /* 456 * Prepare to take over the get/set of environmental variables. 457 */ 458 promif_prop_init(); 459 460 /* 461 * Switch CIF handler to the kernel. 462 */ 463 prom_cif_handler = cif_handler; 464 465 promif_preprom(); 466 cif_handler = kern_cif_handler; 467 468 /* 469 * Take over rtba for the boot CPU. The rtba for 470 * all other CPUs are set as they enter the system. 471 */ 472 rtba = va_to_pa(&trap_table); 473 if ((rv = hv_cpu_set_rtba(&rtba)) != H_EOK) 474 panic("hv_cpu_set_rtba failed: %ld\n", rv); 475 476 promif_postprom(); 477 478 /* 479 * If the system has been booted with kmdb we need kmdb to 480 * use the kernel cif handler instead of the PROM cif handler. 481 */ 482 if (boothowto & RB_KMDB) { 483 kmdb_cb = (void (*)(void))modlookup("misc/kmdbmod", 484 "kctl_switch_promif"); 485 ASSERT(kmdb_cb != NULL); 486 (*kmdb_cb)(); 487 } 488 489 cif_check_cpus(); 490 491 if (transroot != NULL) 492 unmap_prom_mappings(transroot, ntransroot); 493 } 494 495 static void 496 cache_prom_data(void) 497 { 498 /* initialize copy of OBP device tree */ 499 promif_stree_init(); 500 501 /* initialize io parameters */ 502 promif_io_init(); 503 } 504 505 #endif /* _KMDB */ 506