10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53446Smrj * Common Development and Distribution License (the "License").
63446Smrj * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
226356Smrj * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
25*12004Sjiang.liu@intel.com #define PSMI_1_7
260Sstevel@tonic-gate
270Sstevel@tonic-gate #include <sys/vmem.h>
280Sstevel@tonic-gate #include <vm/hat.h>
290Sstevel@tonic-gate #include <sys/modctl.h>
300Sstevel@tonic-gate #include <vm/seg_kmem.h>
310Sstevel@tonic-gate #include <sys/psm.h>
320Sstevel@tonic-gate #include <sys/psm_modctl.h>
330Sstevel@tonic-gate #include <sys/smp_impldefs.h>
340Sstevel@tonic-gate #include <sys/reboot.h>
355084Sjohnlev #if defined(__xpv)
365084Sjohnlev #include <sys/hypervisor.h>
375084Sjohnlev #include <vm/kboot_mmu.h>
385084Sjohnlev #include <vm/hat_pte.h>
395084Sjohnlev #endif
400Sstevel@tonic-gate
410Sstevel@tonic-gate /*
420Sstevel@tonic-gate * External reference functions
430Sstevel@tonic-gate */
440Sstevel@tonic-gate extern void *get_next_mach(void *, char *);
450Sstevel@tonic-gate extern void close_mach_list(void);
460Sstevel@tonic-gate extern void open_mach_list(void);
470Sstevel@tonic-gate
480Sstevel@tonic-gate /*
490Sstevel@tonic-gate * from startup.c - kernel VA range allocator for device mappings
500Sstevel@tonic-gate */
510Sstevel@tonic-gate extern void *device_arena_alloc(size_t size, int vm_flag);
520Sstevel@tonic-gate extern void device_arena_free(void * vaddr, size_t size);
530Sstevel@tonic-gate
540Sstevel@tonic-gate void psm_modloadonly(void);
550Sstevel@tonic-gate void psm_install(void);
560Sstevel@tonic-gate
570Sstevel@tonic-gate /*
580Sstevel@tonic-gate * Local Function Prototypes
590Sstevel@tonic-gate */
600Sstevel@tonic-gate static struct modlinkage *psm_modlinkage_alloc(struct psm_info *infop);
610Sstevel@tonic-gate static void psm_modlinkage_free(struct modlinkage *mlinkp);
620Sstevel@tonic-gate
630Sstevel@tonic-gate static char *psm_get_impl_module(int first);
640Sstevel@tonic-gate
650Sstevel@tonic-gate static int mod_installpsm(struct modlpsm *modl, struct modlinkage *modlp);
660Sstevel@tonic-gate static int mod_removepsm(struct modlpsm *modl, struct modlinkage *modlp);
670Sstevel@tonic-gate static int mod_infopsm(struct modlpsm *modl, struct modlinkage *modlp, int *p0);
680Sstevel@tonic-gate struct mod_ops mod_psmops = {
690Sstevel@tonic-gate mod_installpsm, mod_removepsm, mod_infopsm
700Sstevel@tonic-gate };
710Sstevel@tonic-gate
720Sstevel@tonic-gate static struct psm_sw psm_swtab = {
730Sstevel@tonic-gate &psm_swtab, &psm_swtab, NULL, NULL
740Sstevel@tonic-gate };
750Sstevel@tonic-gate
760Sstevel@tonic-gate kmutex_t psmsw_lock; /* lock accesses to psmsw */
770Sstevel@tonic-gate struct psm_sw *psmsw = &psm_swtab; /* start of all psm_sw */
780Sstevel@tonic-gate
790Sstevel@tonic-gate static struct modlinkage *
psm_modlinkage_alloc(struct psm_info * infop)800Sstevel@tonic-gate psm_modlinkage_alloc(struct psm_info *infop)
810Sstevel@tonic-gate {
820Sstevel@tonic-gate int memsz;
830Sstevel@tonic-gate struct modlinkage *mlinkp;
840Sstevel@tonic-gate struct modlpsm *mlpsmp;
850Sstevel@tonic-gate struct psm_sw *swp;
860Sstevel@tonic-gate
870Sstevel@tonic-gate memsz = sizeof (struct modlinkage) + sizeof (struct modlpsm) +
885084Sjohnlev sizeof (struct psm_sw);
890Sstevel@tonic-gate mlinkp = (struct modlinkage *)kmem_zalloc(memsz, KM_NOSLEEP);
900Sstevel@tonic-gate if (!mlinkp) {
910Sstevel@tonic-gate cmn_err(CE_WARN, "!psm_mod_init: Cannot install %s",
925084Sjohnlev infop->p_mach_idstring);
930Sstevel@tonic-gate return (NULL);
940Sstevel@tonic-gate }
950Sstevel@tonic-gate mlpsmp = (struct modlpsm *)(mlinkp + 1);
960Sstevel@tonic-gate swp = (struct psm_sw *)(mlpsmp + 1);
970Sstevel@tonic-gate
980Sstevel@tonic-gate mlinkp->ml_rev = MODREV_1;
990Sstevel@tonic-gate mlinkp->ml_linkage[0] = (void *)mlpsmp;
1000Sstevel@tonic-gate mlinkp->ml_linkage[1] = (void *)NULL;
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate mlpsmp->psm_modops = &mod_psmops;
1030Sstevel@tonic-gate mlpsmp->psm_linkinfo = infop->p_mach_desc;
1040Sstevel@tonic-gate mlpsmp->psm_swp = swp;
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate swp->psw_infop = infop;
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate return (mlinkp);
1090Sstevel@tonic-gate }
1100Sstevel@tonic-gate
1110Sstevel@tonic-gate static void
psm_modlinkage_free(struct modlinkage * mlinkp)1120Sstevel@tonic-gate psm_modlinkage_free(struct modlinkage *mlinkp)
1130Sstevel@tonic-gate {
1140Sstevel@tonic-gate if (!mlinkp)
1150Sstevel@tonic-gate return;
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate (void) kmem_free(mlinkp, (sizeof (struct modlinkage) +
1185084Sjohnlev sizeof (struct modlpsm) + sizeof (struct psm_sw)));
1190Sstevel@tonic-gate }
1200Sstevel@tonic-gate
1210Sstevel@tonic-gate int
psm_mod_init(void ** handlepp,struct psm_info * infop)1220Sstevel@tonic-gate psm_mod_init(void **handlepp, struct psm_info *infop)
1230Sstevel@tonic-gate {
1240Sstevel@tonic-gate struct modlinkage **modlpp = (struct modlinkage **)handlepp;
1250Sstevel@tonic-gate int status;
1260Sstevel@tonic-gate struct modlinkage *mlinkp;
1270Sstevel@tonic-gate
1280Sstevel@tonic-gate if (!*modlpp) {
1290Sstevel@tonic-gate mlinkp = psm_modlinkage_alloc(infop);
1300Sstevel@tonic-gate if (!mlinkp)
1310Sstevel@tonic-gate return (ENOSPC);
1320Sstevel@tonic-gate } else
1330Sstevel@tonic-gate mlinkp = *modlpp;
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate status = mod_install(mlinkp);
1360Sstevel@tonic-gate if (status) {
1370Sstevel@tonic-gate psm_modlinkage_free(mlinkp);
1380Sstevel@tonic-gate *modlpp = NULL;
1390Sstevel@tonic-gate } else
1400Sstevel@tonic-gate *modlpp = mlinkp;
1410Sstevel@tonic-gate
1420Sstevel@tonic-gate return (status);
1430Sstevel@tonic-gate }
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate /*ARGSUSED1*/
1460Sstevel@tonic-gate int
psm_mod_fini(void ** handlepp,struct psm_info * infop)1470Sstevel@tonic-gate psm_mod_fini(void **handlepp, struct psm_info *infop)
1480Sstevel@tonic-gate {
1490Sstevel@tonic-gate struct modlinkage **modlpp = (struct modlinkage **)handlepp;
1500Sstevel@tonic-gate int status;
1510Sstevel@tonic-gate
1520Sstevel@tonic-gate status = mod_remove(*modlpp);
1530Sstevel@tonic-gate if (status == 0) {
1540Sstevel@tonic-gate psm_modlinkage_free(*modlpp);
1550Sstevel@tonic-gate *modlpp = NULL;
1560Sstevel@tonic-gate }
1570Sstevel@tonic-gate return (status);
1580Sstevel@tonic-gate }
1590Sstevel@tonic-gate
1600Sstevel@tonic-gate int
psm_mod_info(void ** handlepp,struct psm_info * infop,struct modinfo * modinfop)1610Sstevel@tonic-gate psm_mod_info(void **handlepp, struct psm_info *infop, struct modinfo *modinfop)
1620Sstevel@tonic-gate {
1630Sstevel@tonic-gate struct modlinkage **modlpp = (struct modlinkage **)handlepp;
1640Sstevel@tonic-gate int status;
1650Sstevel@tonic-gate struct modlinkage *mlinkp;
1660Sstevel@tonic-gate
1670Sstevel@tonic-gate if (!*modlpp) {
1680Sstevel@tonic-gate mlinkp = psm_modlinkage_alloc(infop);
1690Sstevel@tonic-gate if (!mlinkp)
1700Sstevel@tonic-gate return ((int)NULL);
1710Sstevel@tonic-gate } else
1720Sstevel@tonic-gate mlinkp = *modlpp;
1730Sstevel@tonic-gate
1740Sstevel@tonic-gate status = mod_info(mlinkp, modinfop);
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate if (!status) {
1770Sstevel@tonic-gate psm_modlinkage_free(mlinkp);
1780Sstevel@tonic-gate *modlpp = NULL;
1790Sstevel@tonic-gate } else
1800Sstevel@tonic-gate *modlpp = mlinkp;
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate return (status);
1830Sstevel@tonic-gate }
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate int
psm_add_intr(int lvl,avfunc xxintr,char * name,int vect,caddr_t arg)1860Sstevel@tonic-gate psm_add_intr(int lvl, avfunc xxintr, char *name, int vect, caddr_t arg)
1870Sstevel@tonic-gate {
1880Sstevel@tonic-gate return (add_avintr((void *)NULL, lvl, xxintr, name, vect,
189916Sschwartz arg, NULL, NULL, NULL));
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate int
psm_add_nmintr(int lvl,avfunc xxintr,char * name,caddr_t arg)1930Sstevel@tonic-gate psm_add_nmintr(int lvl, avfunc xxintr, char *name, caddr_t arg)
1940Sstevel@tonic-gate {
1950Sstevel@tonic-gate return (add_nmintr(lvl, xxintr, name, arg));
1960Sstevel@tonic-gate }
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate processorid_t
psm_get_cpu_id(void)1990Sstevel@tonic-gate psm_get_cpu_id(void)
2000Sstevel@tonic-gate {
2010Sstevel@tonic-gate return (CPU->cpu_id);
2020Sstevel@tonic-gate }
2030Sstevel@tonic-gate
2040Sstevel@tonic-gate caddr_t
psm_map_phys_new(paddr_t addr,size_t len,int prot)2050Sstevel@tonic-gate psm_map_phys_new(paddr_t addr, size_t len, int prot)
2060Sstevel@tonic-gate {
2070Sstevel@tonic-gate uint_t pgoffset;
2080Sstevel@tonic-gate paddr_t base;
2090Sstevel@tonic-gate pgcnt_t npages;
2100Sstevel@tonic-gate caddr_t cvaddr;
2110Sstevel@tonic-gate
2120Sstevel@tonic-gate if (len == 0)
2130Sstevel@tonic-gate return (0);
2140Sstevel@tonic-gate
2150Sstevel@tonic-gate pgoffset = addr & MMU_PAGEOFFSET;
2165084Sjohnlev #ifdef __xpv
2175084Sjohnlev /*
2185084Sjohnlev * If we're dom0, we're starting from a MA. translate that to a PA
2195084Sjohnlev * XXPV - what about driver domains???
2205084Sjohnlev */
2215084Sjohnlev if (DOMAIN_IS_INITDOMAIN(xen_info)) {
2225084Sjohnlev base = pfn_to_pa(xen_assign_pfn(mmu_btop(addr))) |
2235084Sjohnlev (addr & MMU_PAGEOFFSET);
2245084Sjohnlev } else {
2255084Sjohnlev base = addr;
2265084Sjohnlev }
2275084Sjohnlev #else
2283446Smrj base = addr;
2295084Sjohnlev #endif
2300Sstevel@tonic-gate npages = mmu_btopr(len + pgoffset);
2310Sstevel@tonic-gate cvaddr = device_arena_alloc(ptob(npages), VM_NOSLEEP);
2320Sstevel@tonic-gate if (cvaddr == NULL)
2330Sstevel@tonic-gate return (0);
2340Sstevel@tonic-gate hat_devload(kas.a_hat, cvaddr, mmu_ptob(npages), mmu_btop(base),
2350Sstevel@tonic-gate prot, HAT_LOAD_LOCK);
2360Sstevel@tonic-gate return (cvaddr + pgoffset);
2370Sstevel@tonic-gate }
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate void
psm_unmap_phys(caddr_t addr,size_t len)2400Sstevel@tonic-gate psm_unmap_phys(caddr_t addr, size_t len)
2410Sstevel@tonic-gate {
2420Sstevel@tonic-gate uint_t pgoffset;
2430Sstevel@tonic-gate caddr_t base;
2440Sstevel@tonic-gate pgcnt_t npages;
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate if (len == 0)
2470Sstevel@tonic-gate return;
2480Sstevel@tonic-gate
2490Sstevel@tonic-gate pgoffset = (uintptr_t)addr & MMU_PAGEOFFSET;
2500Sstevel@tonic-gate base = addr - pgoffset;
2510Sstevel@tonic-gate npages = mmu_btopr(len + pgoffset);
2520Sstevel@tonic-gate hat_unload(kas.a_hat, base, ptob(npages), HAT_UNLOAD_UNLOCK);
2530Sstevel@tonic-gate device_arena_free(base, ptob(npages));
2540Sstevel@tonic-gate }
2550Sstevel@tonic-gate
2560Sstevel@tonic-gate caddr_t
psm_map_new(paddr_t addr,size_t len,int prot)2570Sstevel@tonic-gate psm_map_new(paddr_t addr, size_t len, int prot)
2580Sstevel@tonic-gate {
2590Sstevel@tonic-gate int phys_prot = PROT_READ;
2600Sstevel@tonic-gate
2610Sstevel@tonic-gate ASSERT(prot == (prot & (PSM_PROT_WRITE | PSM_PROT_READ)));
2620Sstevel@tonic-gate if (prot & PSM_PROT_WRITE)
2630Sstevel@tonic-gate phys_prot |= PROT_WRITE;
2640Sstevel@tonic-gate
2650Sstevel@tonic-gate return (psm_map_phys(addr, len, phys_prot));
2660Sstevel@tonic-gate }
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate #undef psm_map_phys
2690Sstevel@tonic-gate #undef psm_map
2700Sstevel@tonic-gate
2710Sstevel@tonic-gate caddr_t
psm_map_phys(uint32_t addr,size_t len,int prot)2720Sstevel@tonic-gate psm_map_phys(uint32_t addr, size_t len, int prot)
2730Sstevel@tonic-gate {
2740Sstevel@tonic-gate return (psm_map_phys_new((paddr_t)(addr & 0xffffffff), len, prot));
2750Sstevel@tonic-gate }
2760Sstevel@tonic-gate
2770Sstevel@tonic-gate caddr_t
psm_map(uint32_t addr,size_t len,int prot)2780Sstevel@tonic-gate psm_map(uint32_t addr, size_t len, int prot)
2790Sstevel@tonic-gate {
2800Sstevel@tonic-gate return (psm_map_new((paddr_t)(addr & 0xffffffff), len, prot));
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate
2830Sstevel@tonic-gate void
psm_unmap(caddr_t addr,size_t len)2840Sstevel@tonic-gate psm_unmap(caddr_t addr, size_t len)
2850Sstevel@tonic-gate {
2860Sstevel@tonic-gate uint_t pgoffset;
2870Sstevel@tonic-gate caddr_t base;
2880Sstevel@tonic-gate pgcnt_t npages;
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate if (len == 0)
2910Sstevel@tonic-gate return;
2920Sstevel@tonic-gate
2930Sstevel@tonic-gate pgoffset = (uintptr_t)addr & MMU_PAGEOFFSET;
2940Sstevel@tonic-gate base = addr - pgoffset;
2950Sstevel@tonic-gate npages = mmu_btopr(len + pgoffset);
2960Sstevel@tonic-gate hat_unload(kas.a_hat, base, ptob(npages), HAT_UNLOAD_UNLOCK);
2970Sstevel@tonic-gate device_arena_free(base, ptob(npages));
2980Sstevel@tonic-gate }
2990Sstevel@tonic-gate
3000Sstevel@tonic-gate /*ARGSUSED1*/
3010Sstevel@tonic-gate static int
mod_installpsm(struct modlpsm * modl,struct modlinkage * modlp)3020Sstevel@tonic-gate mod_installpsm(struct modlpsm *modl, struct modlinkage *modlp)
3030Sstevel@tonic-gate {
3040Sstevel@tonic-gate struct psm_sw *swp;
3050Sstevel@tonic-gate
3060Sstevel@tonic-gate swp = modl->psm_swp;
3070Sstevel@tonic-gate mutex_enter(&psmsw_lock);
3080Sstevel@tonic-gate psmsw->psw_back->psw_forw = swp;
3090Sstevel@tonic-gate swp->psw_back = psmsw->psw_back;
3100Sstevel@tonic-gate swp->psw_forw = psmsw;
3110Sstevel@tonic-gate psmsw->psw_back = swp;
3120Sstevel@tonic-gate swp->psw_flag |= PSM_MOD_INSTALL;
3130Sstevel@tonic-gate mutex_exit(&psmsw_lock);
3140Sstevel@tonic-gate return (0);
3150Sstevel@tonic-gate }
3160Sstevel@tonic-gate
3170Sstevel@tonic-gate /*ARGSUSED1*/
3180Sstevel@tonic-gate static int
mod_removepsm(struct modlpsm * modl,struct modlinkage * modlp)3190Sstevel@tonic-gate mod_removepsm(struct modlpsm *modl, struct modlinkage *modlp)
3200Sstevel@tonic-gate {
3210Sstevel@tonic-gate struct psm_sw *swp;
3220Sstevel@tonic-gate
3230Sstevel@tonic-gate swp = modl->psm_swp;
3240Sstevel@tonic-gate mutex_enter(&psmsw_lock);
3250Sstevel@tonic-gate if (swp->psw_flag & PSM_MOD_IDENTIFY) {
3260Sstevel@tonic-gate mutex_exit(&psmsw_lock);
3270Sstevel@tonic-gate return (EBUSY);
3280Sstevel@tonic-gate }
3290Sstevel@tonic-gate if (!(swp->psw_flag & PSM_MOD_INSTALL)) {
3300Sstevel@tonic-gate mutex_exit(&psmsw_lock);
3310Sstevel@tonic-gate return (0);
3320Sstevel@tonic-gate }
3330Sstevel@tonic-gate
3340Sstevel@tonic-gate swp->psw_back->psw_forw = swp->psw_forw;
3350Sstevel@tonic-gate swp->psw_forw->psw_back = swp->psw_back;
3360Sstevel@tonic-gate mutex_exit(&psmsw_lock);
3370Sstevel@tonic-gate return (0);
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate
3400Sstevel@tonic-gate /*ARGSUSED1*/
3410Sstevel@tonic-gate static int
mod_infopsm(struct modlpsm * modl,struct modlinkage * modlp,int * p0)3420Sstevel@tonic-gate mod_infopsm(struct modlpsm *modl, struct modlinkage *modlp, int *p0)
3430Sstevel@tonic-gate {
3440Sstevel@tonic-gate *p0 = (int)modl->psm_swp->psw_infop->p_owner;
3450Sstevel@tonic-gate return (0);
3460Sstevel@tonic-gate }
3470Sstevel@tonic-gate
3485084Sjohnlev #if defined(__xpv)
3496356Smrj #define DEFAULT_PSM_MODULE "xpv_uppc"
3505084Sjohnlev #else
3513446Smrj #define DEFAULT_PSM_MODULE "uppc"
3525084Sjohnlev #endif
3533446Smrj
3540Sstevel@tonic-gate static char *
psm_get_impl_module(int first)3550Sstevel@tonic-gate psm_get_impl_module(int first)
3560Sstevel@tonic-gate {
3570Sstevel@tonic-gate static char **pnamep;
3580Sstevel@tonic-gate static char *psm_impl_module_list[] = {
3593446Smrj DEFAULT_PSM_MODULE,
3600Sstevel@tonic-gate (char *)0
3610Sstevel@tonic-gate };
3620Sstevel@tonic-gate static void *mhdl = NULL;
3630Sstevel@tonic-gate static char machname[MAXNAMELEN];
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate if (first)
3660Sstevel@tonic-gate pnamep = psm_impl_module_list;
3670Sstevel@tonic-gate
3680Sstevel@tonic-gate if (*pnamep != (char *)0)
3690Sstevel@tonic-gate return (*pnamep++);
3700Sstevel@tonic-gate
3710Sstevel@tonic-gate mhdl = get_next_mach(mhdl, machname);
3720Sstevel@tonic-gate if (mhdl)
3730Sstevel@tonic-gate return (machname);
3740Sstevel@tonic-gate return ((char *)0);
3750Sstevel@tonic-gate }
3760Sstevel@tonic-gate
3770Sstevel@tonic-gate void
psm_modload(void)3780Sstevel@tonic-gate psm_modload(void)
3790Sstevel@tonic-gate {
3800Sstevel@tonic-gate char *this;
3810Sstevel@tonic-gate
3820Sstevel@tonic-gate mutex_init(&psmsw_lock, NULL, MUTEX_DEFAULT, NULL);
3830Sstevel@tonic-gate open_mach_list();
3840Sstevel@tonic-gate
3855084Sjohnlev for (this = psm_get_impl_module(1); this != (char *)NULL;
3865084Sjohnlev this = psm_get_impl_module(0)) {
3870Sstevel@tonic-gate if (modload("mach", this) == -1)
3887772SMark.Johnson@Sun.COM cmn_err(CE_CONT, "!Skipping psm: %s\n", this);
3890Sstevel@tonic-gate }
3900Sstevel@tonic-gate close_mach_list();
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate
3935529Ssmaybe #if defined(__xpv)
3945529Ssmaybe #define NOTSUP_MSG "This version of Solaris xVM does not support this hardware"
3955529Ssmaybe #else
3965529Ssmaybe #define NOTSUP_MSG "This version of Solaris does not support this hardware"
3975529Ssmaybe #endif /* __xpv */
3985529Ssmaybe
3990Sstevel@tonic-gate void
psm_install(void)4000Sstevel@tonic-gate psm_install(void)
4010Sstevel@tonic-gate {
4020Sstevel@tonic-gate struct psm_sw *swp, *cswp;
4030Sstevel@tonic-gate struct psm_ops *opsp;
4040Sstevel@tonic-gate char machstring[15];
4055529Ssmaybe int err, psmcnt = 0;
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate mutex_enter(&psmsw_lock);
4080Sstevel@tonic-gate for (swp = psmsw->psw_forw; swp != psmsw; ) {
4090Sstevel@tonic-gate opsp = swp->psw_infop->p_ops;
4100Sstevel@tonic-gate if (opsp->psm_probe) {
4110Sstevel@tonic-gate if ((*opsp->psm_probe)() == PSM_SUCCESS) {
4125529Ssmaybe psmcnt++;
4130Sstevel@tonic-gate swp->psw_flag |= PSM_MOD_IDENTIFY;
4140Sstevel@tonic-gate swp = swp->psw_forw;
4150Sstevel@tonic-gate continue;
4160Sstevel@tonic-gate }
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate /* remove the unsuccessful psm modules */
4190Sstevel@tonic-gate cswp = swp;
4200Sstevel@tonic-gate swp = swp->psw_forw;
4210Sstevel@tonic-gate
4220Sstevel@tonic-gate mutex_exit(&psmsw_lock);
4230Sstevel@tonic-gate (void) strcpy(&machstring[0], cswp->psw_infop->p_mach_idstring);
4240Sstevel@tonic-gate err = mod_remove_by_name(cswp->psw_infop->p_mach_idstring);
4250Sstevel@tonic-gate if (err)
4268198SVikram.Hegde@Sun.COM cmn_err(CE_WARN, "!%s: mod_remove_by_name failed %d",
4275084Sjohnlev &machstring[0], err);
4280Sstevel@tonic-gate mutex_enter(&psmsw_lock);
4290Sstevel@tonic-gate }
4300Sstevel@tonic-gate mutex_exit(&psmsw_lock);
4315529Ssmaybe if (psmcnt == 0)
4325529Ssmaybe halt(NOTSUP_MSG);
4330Sstevel@tonic-gate (*psminitf)();
4340Sstevel@tonic-gate }
4350Sstevel@tonic-gate
4360Sstevel@tonic-gate /*
4370Sstevel@tonic-gate * Return 1 if kernel debugger is present, and 0 if not.
4380Sstevel@tonic-gate */
4390Sstevel@tonic-gate int
psm_debugger(void)4400Sstevel@tonic-gate psm_debugger(void)
4410Sstevel@tonic-gate {
4420Sstevel@tonic-gate return ((boothowto & RB_DEBUG) != 0);
4430Sstevel@tonic-gate }
444