17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5ae115bc7Smrj * Common Development and Distribution License (the "License"). 6ae115bc7Smrj * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22cc7a88b5Smrj * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 25*a3114836SGerry Liu #define PSMI_1_7 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <sys/vmem.h> 287c478bd9Sstevel@tonic-gate #include <vm/hat.h> 297c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 307c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h> 317c478bd9Sstevel@tonic-gate #include <sys/psm.h> 327c478bd9Sstevel@tonic-gate #include <sys/psm_modctl.h> 337c478bd9Sstevel@tonic-gate #include <sys/smp_impldefs.h> 347c478bd9Sstevel@tonic-gate #include <sys/reboot.h> 35843e1988Sjohnlev #if defined(__xpv) 36843e1988Sjohnlev #include <sys/hypervisor.h> 37843e1988Sjohnlev #include <vm/kboot_mmu.h> 38843e1988Sjohnlev #include <vm/hat_pte.h> 39843e1988Sjohnlev #endif 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate /* 427c478bd9Sstevel@tonic-gate * External reference functions 437c478bd9Sstevel@tonic-gate */ 447c478bd9Sstevel@tonic-gate extern void *get_next_mach(void *, char *); 457c478bd9Sstevel@tonic-gate extern void close_mach_list(void); 467c478bd9Sstevel@tonic-gate extern void open_mach_list(void); 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate /* 497c478bd9Sstevel@tonic-gate * from startup.c - kernel VA range allocator for device mappings 507c478bd9Sstevel@tonic-gate */ 517c478bd9Sstevel@tonic-gate extern void *device_arena_alloc(size_t size, int vm_flag); 527c478bd9Sstevel@tonic-gate extern void device_arena_free(void * vaddr, size_t size); 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate void psm_modloadonly(void); 557c478bd9Sstevel@tonic-gate void psm_install(void); 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate /* 587c478bd9Sstevel@tonic-gate * Local Function Prototypes 597c478bd9Sstevel@tonic-gate */ 607c478bd9Sstevel@tonic-gate static struct modlinkage *psm_modlinkage_alloc(struct psm_info *infop); 617c478bd9Sstevel@tonic-gate static void psm_modlinkage_free(struct modlinkage *mlinkp); 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate static char *psm_get_impl_module(int first); 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate static int mod_installpsm(struct modlpsm *modl, struct modlinkage *modlp); 667c478bd9Sstevel@tonic-gate static int mod_removepsm(struct modlpsm *modl, struct modlinkage *modlp); 677c478bd9Sstevel@tonic-gate static int mod_infopsm(struct modlpsm *modl, struct modlinkage *modlp, int *p0); 687c478bd9Sstevel@tonic-gate struct mod_ops mod_psmops = { 697c478bd9Sstevel@tonic-gate mod_installpsm, mod_removepsm, mod_infopsm 707c478bd9Sstevel@tonic-gate }; 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate static struct psm_sw psm_swtab = { 737c478bd9Sstevel@tonic-gate &psm_swtab, &psm_swtab, NULL, NULL 747c478bd9Sstevel@tonic-gate }; 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate kmutex_t psmsw_lock; /* lock accesses to psmsw */ 777c478bd9Sstevel@tonic-gate struct psm_sw *psmsw = &psm_swtab; /* start of all psm_sw */ 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate static struct modlinkage * 807c478bd9Sstevel@tonic-gate psm_modlinkage_alloc(struct psm_info *infop) 817c478bd9Sstevel@tonic-gate { 827c478bd9Sstevel@tonic-gate int memsz; 837c478bd9Sstevel@tonic-gate struct modlinkage *mlinkp; 847c478bd9Sstevel@tonic-gate struct modlpsm *mlpsmp; 857c478bd9Sstevel@tonic-gate struct psm_sw *swp; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate memsz = sizeof (struct modlinkage) + sizeof (struct modlpsm) + 887c478bd9Sstevel@tonic-gate sizeof (struct psm_sw); 897c478bd9Sstevel@tonic-gate mlinkp = (struct modlinkage *)kmem_zalloc(memsz, KM_NOSLEEP); 907c478bd9Sstevel@tonic-gate if (!mlinkp) { 917c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "!psm_mod_init: Cannot install %s", 927c478bd9Sstevel@tonic-gate infop->p_mach_idstring); 937c478bd9Sstevel@tonic-gate return (NULL); 947c478bd9Sstevel@tonic-gate } 957c478bd9Sstevel@tonic-gate mlpsmp = (struct modlpsm *)(mlinkp + 1); 967c478bd9Sstevel@tonic-gate swp = (struct psm_sw *)(mlpsmp + 1); 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate mlinkp->ml_rev = MODREV_1; 997c478bd9Sstevel@tonic-gate mlinkp->ml_linkage[0] = (void *)mlpsmp; 1007c478bd9Sstevel@tonic-gate mlinkp->ml_linkage[1] = (void *)NULL; 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate mlpsmp->psm_modops = &mod_psmops; 1037c478bd9Sstevel@tonic-gate mlpsmp->psm_linkinfo = infop->p_mach_desc; 1047c478bd9Sstevel@tonic-gate mlpsmp->psm_swp = swp; 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate swp->psw_infop = infop; 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate return (mlinkp); 1097c478bd9Sstevel@tonic-gate } 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate static void 1127c478bd9Sstevel@tonic-gate psm_modlinkage_free(struct modlinkage *mlinkp) 1137c478bd9Sstevel@tonic-gate { 1147c478bd9Sstevel@tonic-gate if (!mlinkp) 1157c478bd9Sstevel@tonic-gate return; 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate (void) kmem_free(mlinkp, (sizeof (struct modlinkage) + 1187c478bd9Sstevel@tonic-gate sizeof (struct modlpsm) + sizeof (struct psm_sw))); 1197c478bd9Sstevel@tonic-gate } 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate int 1227c478bd9Sstevel@tonic-gate psm_mod_init(void **handlepp, struct psm_info *infop) 1237c478bd9Sstevel@tonic-gate { 1247c478bd9Sstevel@tonic-gate struct modlinkage **modlpp = (struct modlinkage **)handlepp; 1257c478bd9Sstevel@tonic-gate int status; 1267c478bd9Sstevel@tonic-gate struct modlinkage *mlinkp; 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate if (!*modlpp) { 1297c478bd9Sstevel@tonic-gate mlinkp = psm_modlinkage_alloc(infop); 1307c478bd9Sstevel@tonic-gate if (!mlinkp) 1317c478bd9Sstevel@tonic-gate return (ENOSPC); 1327c478bd9Sstevel@tonic-gate } else 1337c478bd9Sstevel@tonic-gate mlinkp = *modlpp; 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate status = mod_install(mlinkp); 1367c478bd9Sstevel@tonic-gate if (status) { 1377c478bd9Sstevel@tonic-gate psm_modlinkage_free(mlinkp); 1387c478bd9Sstevel@tonic-gate *modlpp = NULL; 1397c478bd9Sstevel@tonic-gate } else 1407c478bd9Sstevel@tonic-gate *modlpp = mlinkp; 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate return (status); 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 1467c478bd9Sstevel@tonic-gate int 1477c478bd9Sstevel@tonic-gate psm_mod_fini(void **handlepp, struct psm_info *infop) 1487c478bd9Sstevel@tonic-gate { 1497c478bd9Sstevel@tonic-gate struct modlinkage **modlpp = (struct modlinkage **)handlepp; 1507c478bd9Sstevel@tonic-gate int status; 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate status = mod_remove(*modlpp); 1537c478bd9Sstevel@tonic-gate if (status == 0) { 1547c478bd9Sstevel@tonic-gate psm_modlinkage_free(*modlpp); 1557c478bd9Sstevel@tonic-gate *modlpp = NULL; 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate return (status); 1587c478bd9Sstevel@tonic-gate } 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate int 1617c478bd9Sstevel@tonic-gate psm_mod_info(void **handlepp, struct psm_info *infop, struct modinfo *modinfop) 1627c478bd9Sstevel@tonic-gate { 1637c478bd9Sstevel@tonic-gate struct modlinkage **modlpp = (struct modlinkage **)handlepp; 1647c478bd9Sstevel@tonic-gate int status; 1657c478bd9Sstevel@tonic-gate struct modlinkage *mlinkp; 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate if (!*modlpp) { 1687c478bd9Sstevel@tonic-gate mlinkp = psm_modlinkage_alloc(infop); 1697c478bd9Sstevel@tonic-gate if (!mlinkp) 1707c478bd9Sstevel@tonic-gate return ((int)NULL); 1717c478bd9Sstevel@tonic-gate } else 1727c478bd9Sstevel@tonic-gate mlinkp = *modlpp; 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate status = mod_info(mlinkp, modinfop); 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate if (!status) { 1777c478bd9Sstevel@tonic-gate psm_modlinkage_free(mlinkp); 1787c478bd9Sstevel@tonic-gate *modlpp = NULL; 1797c478bd9Sstevel@tonic-gate } else 1807c478bd9Sstevel@tonic-gate *modlpp = mlinkp; 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate return (status); 1837c478bd9Sstevel@tonic-gate } 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate int 1867c478bd9Sstevel@tonic-gate psm_add_intr(int lvl, avfunc xxintr, char *name, int vect, caddr_t arg) 1877c478bd9Sstevel@tonic-gate { 1887c478bd9Sstevel@tonic-gate return (add_avintr((void *)NULL, lvl, xxintr, name, vect, 1897a364d25Sschwartz arg, NULL, NULL, NULL)); 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate int 1937c478bd9Sstevel@tonic-gate psm_add_nmintr(int lvl, avfunc xxintr, char *name, caddr_t arg) 1947c478bd9Sstevel@tonic-gate { 1957c478bd9Sstevel@tonic-gate return (add_nmintr(lvl, xxintr, name, arg)); 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate processorid_t 1997c478bd9Sstevel@tonic-gate psm_get_cpu_id(void) 2007c478bd9Sstevel@tonic-gate { 2017c478bd9Sstevel@tonic-gate return (CPU->cpu_id); 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate caddr_t 2057c478bd9Sstevel@tonic-gate psm_map_phys_new(paddr_t addr, size_t len, int prot) 2067c478bd9Sstevel@tonic-gate { 2077c478bd9Sstevel@tonic-gate uint_t pgoffset; 2087c478bd9Sstevel@tonic-gate paddr_t base; 2097c478bd9Sstevel@tonic-gate pgcnt_t npages; 2107c478bd9Sstevel@tonic-gate caddr_t cvaddr; 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate if (len == 0) 2137c478bd9Sstevel@tonic-gate return (0); 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate pgoffset = addr & MMU_PAGEOFFSET; 216843e1988Sjohnlev #ifdef __xpv 217843e1988Sjohnlev /* 218843e1988Sjohnlev * If we're dom0, we're starting from a MA. translate that to a PA 219843e1988Sjohnlev * XXPV - what about driver domains??? 220843e1988Sjohnlev */ 221843e1988Sjohnlev if (DOMAIN_IS_INITDOMAIN(xen_info)) { 222843e1988Sjohnlev base = pfn_to_pa(xen_assign_pfn(mmu_btop(addr))) | 223843e1988Sjohnlev (addr & MMU_PAGEOFFSET); 224843e1988Sjohnlev } else { 225ae115bc7Smrj base = addr; 226843e1988Sjohnlev } 227843e1988Sjohnlev #else 228843e1988Sjohnlev base = addr; 229843e1988Sjohnlev #endif 2307c478bd9Sstevel@tonic-gate npages = mmu_btopr(len + pgoffset); 2317c478bd9Sstevel@tonic-gate cvaddr = device_arena_alloc(ptob(npages), VM_NOSLEEP); 2327c478bd9Sstevel@tonic-gate if (cvaddr == NULL) 2337c478bd9Sstevel@tonic-gate return (0); 2347c478bd9Sstevel@tonic-gate hat_devload(kas.a_hat, cvaddr, mmu_ptob(npages), mmu_btop(base), 2357c478bd9Sstevel@tonic-gate prot, HAT_LOAD_LOCK); 2367c478bd9Sstevel@tonic-gate return (cvaddr + pgoffset); 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate void 2407c478bd9Sstevel@tonic-gate psm_unmap_phys(caddr_t addr, size_t len) 2417c478bd9Sstevel@tonic-gate { 2427c478bd9Sstevel@tonic-gate uint_t pgoffset; 2437c478bd9Sstevel@tonic-gate caddr_t base; 2447c478bd9Sstevel@tonic-gate pgcnt_t npages; 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate if (len == 0) 2477c478bd9Sstevel@tonic-gate return; 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate pgoffset = (uintptr_t)addr & MMU_PAGEOFFSET; 2507c478bd9Sstevel@tonic-gate base = addr - pgoffset; 2517c478bd9Sstevel@tonic-gate npages = mmu_btopr(len + pgoffset); 2527c478bd9Sstevel@tonic-gate hat_unload(kas.a_hat, base, ptob(npages), HAT_UNLOAD_UNLOCK); 2537c478bd9Sstevel@tonic-gate device_arena_free(base, ptob(npages)); 2547c478bd9Sstevel@tonic-gate } 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate caddr_t 2577c478bd9Sstevel@tonic-gate psm_map_new(paddr_t addr, size_t len, int prot) 2587c478bd9Sstevel@tonic-gate { 2597c478bd9Sstevel@tonic-gate int phys_prot = PROT_READ; 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate ASSERT(prot == (prot & (PSM_PROT_WRITE | PSM_PROT_READ))); 2627c478bd9Sstevel@tonic-gate if (prot & PSM_PROT_WRITE) 2637c478bd9Sstevel@tonic-gate phys_prot |= PROT_WRITE; 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate return (psm_map_phys(addr, len, phys_prot)); 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate #undef psm_map_phys 2697c478bd9Sstevel@tonic-gate #undef psm_map 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate caddr_t 2727c478bd9Sstevel@tonic-gate psm_map_phys(uint32_t addr, size_t len, int prot) 2737c478bd9Sstevel@tonic-gate { 2747c478bd9Sstevel@tonic-gate return (psm_map_phys_new((paddr_t)(addr & 0xffffffff), len, prot)); 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate caddr_t 2787c478bd9Sstevel@tonic-gate psm_map(uint32_t addr, size_t len, int prot) 2797c478bd9Sstevel@tonic-gate { 2807c478bd9Sstevel@tonic-gate return (psm_map_new((paddr_t)(addr & 0xffffffff), len, prot)); 2817c478bd9Sstevel@tonic-gate } 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate void 2847c478bd9Sstevel@tonic-gate psm_unmap(caddr_t addr, size_t len) 2857c478bd9Sstevel@tonic-gate { 2867c478bd9Sstevel@tonic-gate uint_t pgoffset; 2877c478bd9Sstevel@tonic-gate caddr_t base; 2887c478bd9Sstevel@tonic-gate pgcnt_t npages; 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate if (len == 0) 2917c478bd9Sstevel@tonic-gate return; 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate pgoffset = (uintptr_t)addr & MMU_PAGEOFFSET; 2947c478bd9Sstevel@tonic-gate base = addr - pgoffset; 2957c478bd9Sstevel@tonic-gate npages = mmu_btopr(len + pgoffset); 2967c478bd9Sstevel@tonic-gate hat_unload(kas.a_hat, base, ptob(npages), HAT_UNLOAD_UNLOCK); 2977c478bd9Sstevel@tonic-gate device_arena_free(base, ptob(npages)); 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 3017c478bd9Sstevel@tonic-gate static int 3027c478bd9Sstevel@tonic-gate mod_installpsm(struct modlpsm *modl, struct modlinkage *modlp) 3037c478bd9Sstevel@tonic-gate { 3047c478bd9Sstevel@tonic-gate struct psm_sw *swp; 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate swp = modl->psm_swp; 3077c478bd9Sstevel@tonic-gate mutex_enter(&psmsw_lock); 3087c478bd9Sstevel@tonic-gate psmsw->psw_back->psw_forw = swp; 3097c478bd9Sstevel@tonic-gate swp->psw_back = psmsw->psw_back; 3107c478bd9Sstevel@tonic-gate swp->psw_forw = psmsw; 3117c478bd9Sstevel@tonic-gate psmsw->psw_back = swp; 3127c478bd9Sstevel@tonic-gate swp->psw_flag |= PSM_MOD_INSTALL; 3137c478bd9Sstevel@tonic-gate mutex_exit(&psmsw_lock); 3147c478bd9Sstevel@tonic-gate return (0); 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 3187c478bd9Sstevel@tonic-gate static int 3197c478bd9Sstevel@tonic-gate mod_removepsm(struct modlpsm *modl, struct modlinkage *modlp) 3207c478bd9Sstevel@tonic-gate { 3217c478bd9Sstevel@tonic-gate struct psm_sw *swp; 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate swp = modl->psm_swp; 3247c478bd9Sstevel@tonic-gate mutex_enter(&psmsw_lock); 3257c478bd9Sstevel@tonic-gate if (swp->psw_flag & PSM_MOD_IDENTIFY) { 3267c478bd9Sstevel@tonic-gate mutex_exit(&psmsw_lock); 3277c478bd9Sstevel@tonic-gate return (EBUSY); 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate if (!(swp->psw_flag & PSM_MOD_INSTALL)) { 3307c478bd9Sstevel@tonic-gate mutex_exit(&psmsw_lock); 3317c478bd9Sstevel@tonic-gate return (0); 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate swp->psw_back->psw_forw = swp->psw_forw; 3357c478bd9Sstevel@tonic-gate swp->psw_forw->psw_back = swp->psw_back; 3367c478bd9Sstevel@tonic-gate mutex_exit(&psmsw_lock); 3377c478bd9Sstevel@tonic-gate return (0); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 3417c478bd9Sstevel@tonic-gate static int 3427c478bd9Sstevel@tonic-gate mod_infopsm(struct modlpsm *modl, struct modlinkage *modlp, int *p0) 3437c478bd9Sstevel@tonic-gate { 3447c478bd9Sstevel@tonic-gate *p0 = (int)modl->psm_swp->psw_infop->p_owner; 3457c478bd9Sstevel@tonic-gate return (0); 3467c478bd9Sstevel@tonic-gate } 3477c478bd9Sstevel@tonic-gate 348843e1988Sjohnlev #if defined(__xpv) 349cc7a88b5Smrj #define DEFAULT_PSM_MODULE "xpv_uppc" 350843e1988Sjohnlev #else 351ae115bc7Smrj #define DEFAULT_PSM_MODULE "uppc" 352843e1988Sjohnlev #endif 353ae115bc7Smrj 3547c478bd9Sstevel@tonic-gate static char * 3557c478bd9Sstevel@tonic-gate psm_get_impl_module(int first) 3567c478bd9Sstevel@tonic-gate { 3577c478bd9Sstevel@tonic-gate static char **pnamep; 3587c478bd9Sstevel@tonic-gate static char *psm_impl_module_list[] = { 359ae115bc7Smrj DEFAULT_PSM_MODULE, 3607c478bd9Sstevel@tonic-gate (char *)0 3617c478bd9Sstevel@tonic-gate }; 3627c478bd9Sstevel@tonic-gate static void *mhdl = NULL; 3637c478bd9Sstevel@tonic-gate static char machname[MAXNAMELEN]; 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate if (first) 3667c478bd9Sstevel@tonic-gate pnamep = psm_impl_module_list; 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate if (*pnamep != (char *)0) 3697c478bd9Sstevel@tonic-gate return (*pnamep++); 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate mhdl = get_next_mach(mhdl, machname); 3727c478bd9Sstevel@tonic-gate if (mhdl) 3737c478bd9Sstevel@tonic-gate return (machname); 3747c478bd9Sstevel@tonic-gate return ((char *)0); 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate void 3787c478bd9Sstevel@tonic-gate psm_modload(void) 3797c478bd9Sstevel@tonic-gate { 3807c478bd9Sstevel@tonic-gate char *this; 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate mutex_init(&psmsw_lock, NULL, MUTEX_DEFAULT, NULL); 3837c478bd9Sstevel@tonic-gate open_mach_list(); 3847c478bd9Sstevel@tonic-gate 385843e1988Sjohnlev for (this = psm_get_impl_module(1); this != (char *)NULL; 3867c478bd9Sstevel@tonic-gate this = psm_get_impl_module(0)) { 3877c478bd9Sstevel@tonic-gate if (modload("mach", this) == -1) 3885f890c5eSMark Johnson cmn_err(CE_CONT, "!Skipping psm: %s\n", this); 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate close_mach_list(); 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate 393b9bc7f78Ssmaybe #if defined(__xpv) 394b9bc7f78Ssmaybe #define NOTSUP_MSG "This version of Solaris xVM does not support this hardware" 395b9bc7f78Ssmaybe #else 396b9bc7f78Ssmaybe #define NOTSUP_MSG "This version of Solaris does not support this hardware" 397b9bc7f78Ssmaybe #endif /* __xpv */ 398b9bc7f78Ssmaybe 3997c478bd9Sstevel@tonic-gate void 4007c478bd9Sstevel@tonic-gate psm_install(void) 4017c478bd9Sstevel@tonic-gate { 4027c478bd9Sstevel@tonic-gate struct psm_sw *swp, *cswp; 4037c478bd9Sstevel@tonic-gate struct psm_ops *opsp; 4047c478bd9Sstevel@tonic-gate char machstring[15]; 405b9bc7f78Ssmaybe int err, psmcnt = 0; 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate mutex_enter(&psmsw_lock); 4087c478bd9Sstevel@tonic-gate for (swp = psmsw->psw_forw; swp != psmsw; ) { 4097c478bd9Sstevel@tonic-gate opsp = swp->psw_infop->p_ops; 4107c478bd9Sstevel@tonic-gate if (opsp->psm_probe) { 4117c478bd9Sstevel@tonic-gate if ((*opsp->psm_probe)() == PSM_SUCCESS) { 412b9bc7f78Ssmaybe psmcnt++; 4137c478bd9Sstevel@tonic-gate swp->psw_flag |= PSM_MOD_IDENTIFY; 4147c478bd9Sstevel@tonic-gate swp = swp->psw_forw; 4157c478bd9Sstevel@tonic-gate continue; 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate /* remove the unsuccessful psm modules */ 4197c478bd9Sstevel@tonic-gate cswp = swp; 4207c478bd9Sstevel@tonic-gate swp = swp->psw_forw; 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate mutex_exit(&psmsw_lock); 4237c478bd9Sstevel@tonic-gate (void) strcpy(&machstring[0], cswp->psw_infop->p_mach_idstring); 4247c478bd9Sstevel@tonic-gate err = mod_remove_by_name(cswp->psw_infop->p_mach_idstring); 4257c478bd9Sstevel@tonic-gate if (err) 426408a1f8eSVikram Hegde cmn_err(CE_WARN, "!%s: mod_remove_by_name failed %d", 4277c478bd9Sstevel@tonic-gate &machstring[0], err); 4287c478bd9Sstevel@tonic-gate mutex_enter(&psmsw_lock); 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate mutex_exit(&psmsw_lock); 431b9bc7f78Ssmaybe if (psmcnt == 0) 432b9bc7f78Ssmaybe halt(NOTSUP_MSG); 4337c478bd9Sstevel@tonic-gate (*psminitf)(); 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate /* 4377c478bd9Sstevel@tonic-gate * Return 1 if kernel debugger is present, and 0 if not. 4387c478bd9Sstevel@tonic-gate */ 4397c478bd9Sstevel@tonic-gate int 4407c478bd9Sstevel@tonic-gate psm_debugger(void) 4417c478bd9Sstevel@tonic-gate { 4427c478bd9Sstevel@tonic-gate return ((boothowto & RB_DEBUG) != 0); 4437c478bd9Sstevel@tonic-gate } 444