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