xref: /onnv-gate/usr/src/uts/i86pc/os/mp_implfuncs.c (revision 5295:a21f2449e5f9)
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 /*
223446Smrj  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <sys/psm.h>
290Sstevel@tonic-gate #include <sys/vmem.h>
300Sstevel@tonic-gate #include <vm/hat.h>
310Sstevel@tonic-gate #include <sys/modctl.h>
320Sstevel@tonic-gate #include <vm/seg_kmem.h>
33*5295Srandyf #define	PSMI_1_6
340Sstevel@tonic-gate #include <sys/psm.h>
350Sstevel@tonic-gate #include <sys/psm_modctl.h>
360Sstevel@tonic-gate #include <sys/smp_impldefs.h>
370Sstevel@tonic-gate #include <sys/reboot.h>
385084Sjohnlev #if defined(__xpv)
395084Sjohnlev #include <sys/hypervisor.h>
405084Sjohnlev #include <vm/kboot_mmu.h>
415084Sjohnlev #include <vm/hat_pte.h>
425084Sjohnlev #endif
430Sstevel@tonic-gate 
440Sstevel@tonic-gate /*
450Sstevel@tonic-gate  *	External reference functions
460Sstevel@tonic-gate  */
470Sstevel@tonic-gate extern void *get_next_mach(void *, char *);
480Sstevel@tonic-gate extern void close_mach_list(void);
490Sstevel@tonic-gate extern void open_mach_list(void);
500Sstevel@tonic-gate 
510Sstevel@tonic-gate /*
520Sstevel@tonic-gate  * from startup.c - kernel VA range allocator for device mappings
530Sstevel@tonic-gate  */
540Sstevel@tonic-gate extern void *device_arena_alloc(size_t size, int vm_flag);
550Sstevel@tonic-gate extern void device_arena_free(void * vaddr, size_t size);
560Sstevel@tonic-gate 
570Sstevel@tonic-gate void psm_modloadonly(void);
580Sstevel@tonic-gate void psm_install(void);
590Sstevel@tonic-gate 
600Sstevel@tonic-gate /*
610Sstevel@tonic-gate  * Local Function Prototypes
620Sstevel@tonic-gate  */
630Sstevel@tonic-gate static struct modlinkage *psm_modlinkage_alloc(struct psm_info *infop);
640Sstevel@tonic-gate static void psm_modlinkage_free(struct modlinkage *mlinkp);
650Sstevel@tonic-gate 
660Sstevel@tonic-gate static char *psm_get_impl_module(int first);
670Sstevel@tonic-gate 
680Sstevel@tonic-gate static int mod_installpsm(struct modlpsm *modl, struct modlinkage *modlp);
690Sstevel@tonic-gate static int mod_removepsm(struct modlpsm *modl, struct modlinkage *modlp);
700Sstevel@tonic-gate static int mod_infopsm(struct modlpsm *modl, struct modlinkage *modlp, int *p0);
710Sstevel@tonic-gate struct mod_ops mod_psmops = {
720Sstevel@tonic-gate 	mod_installpsm, mod_removepsm, mod_infopsm
730Sstevel@tonic-gate };
740Sstevel@tonic-gate 
750Sstevel@tonic-gate static struct psm_sw psm_swtab = {
760Sstevel@tonic-gate 	&psm_swtab, &psm_swtab, NULL, NULL
770Sstevel@tonic-gate };
780Sstevel@tonic-gate 
790Sstevel@tonic-gate kmutex_t psmsw_lock;			/* lock accesses to psmsw 	*/
800Sstevel@tonic-gate struct psm_sw *psmsw = &psm_swtab; 	/* start of all psm_sw		*/
810Sstevel@tonic-gate 
820Sstevel@tonic-gate static struct modlinkage *
830Sstevel@tonic-gate psm_modlinkage_alloc(struct psm_info *infop)
840Sstevel@tonic-gate {
850Sstevel@tonic-gate 	int	memsz;
860Sstevel@tonic-gate 	struct modlinkage *mlinkp;
870Sstevel@tonic-gate 	struct modlpsm *mlpsmp;
880Sstevel@tonic-gate 	struct psm_sw *swp;
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 	memsz = sizeof (struct modlinkage) + sizeof (struct modlpsm) +
915084Sjohnlev 	    sizeof (struct psm_sw);
920Sstevel@tonic-gate 	mlinkp = (struct modlinkage *)kmem_zalloc(memsz, KM_NOSLEEP);
930Sstevel@tonic-gate 	if (!mlinkp) {
940Sstevel@tonic-gate 		cmn_err(CE_WARN, "!psm_mod_init: Cannot install %s",
955084Sjohnlev 		    infop->p_mach_idstring);
960Sstevel@tonic-gate 		return (NULL);
970Sstevel@tonic-gate 	}
980Sstevel@tonic-gate 	mlpsmp = (struct modlpsm *)(mlinkp + 1);
990Sstevel@tonic-gate 	swp = (struct psm_sw *)(mlpsmp + 1);
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate 	mlinkp->ml_rev = MODREV_1;
1020Sstevel@tonic-gate 	mlinkp->ml_linkage[0] = (void *)mlpsmp;
1030Sstevel@tonic-gate 	mlinkp->ml_linkage[1] = (void *)NULL;
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate 	mlpsmp->psm_modops = &mod_psmops;
1060Sstevel@tonic-gate 	mlpsmp->psm_linkinfo = infop->p_mach_desc;
1070Sstevel@tonic-gate 	mlpsmp->psm_swp = swp;
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 	swp->psw_infop = infop;
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate 	return (mlinkp);
1120Sstevel@tonic-gate }
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate static void
1150Sstevel@tonic-gate psm_modlinkage_free(struct modlinkage *mlinkp)
1160Sstevel@tonic-gate {
1170Sstevel@tonic-gate 	if (!mlinkp)
1180Sstevel@tonic-gate 		return;
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	(void) kmem_free(mlinkp, (sizeof (struct modlinkage) +
1215084Sjohnlev 	    sizeof (struct modlpsm) + sizeof (struct psm_sw)));
1220Sstevel@tonic-gate }
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate int
1250Sstevel@tonic-gate psm_mod_init(void **handlepp, struct psm_info *infop)
1260Sstevel@tonic-gate {
1270Sstevel@tonic-gate 	struct modlinkage **modlpp = (struct modlinkage **)handlepp;
1280Sstevel@tonic-gate 	int	status;
1290Sstevel@tonic-gate 	struct modlinkage *mlinkp;
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate 	if (!*modlpp) {
1320Sstevel@tonic-gate 		mlinkp = psm_modlinkage_alloc(infop);
1330Sstevel@tonic-gate 		if (!mlinkp)
1340Sstevel@tonic-gate 			return (ENOSPC);
1350Sstevel@tonic-gate 	} else
1360Sstevel@tonic-gate 		mlinkp = *modlpp;
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 	status = mod_install(mlinkp);
1390Sstevel@tonic-gate 	if (status) {
1400Sstevel@tonic-gate 		psm_modlinkage_free(mlinkp);
1410Sstevel@tonic-gate 		*modlpp = NULL;
1420Sstevel@tonic-gate 	} else
1430Sstevel@tonic-gate 		*modlpp = mlinkp;
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 	return (status);
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate /*ARGSUSED1*/
1490Sstevel@tonic-gate int
1500Sstevel@tonic-gate psm_mod_fini(void **handlepp, struct psm_info *infop)
1510Sstevel@tonic-gate {
1520Sstevel@tonic-gate 	struct modlinkage **modlpp = (struct modlinkage **)handlepp;
1530Sstevel@tonic-gate 	int	status;
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	status = mod_remove(*modlpp);
1560Sstevel@tonic-gate 	if (status == 0) {
1570Sstevel@tonic-gate 		psm_modlinkage_free(*modlpp);
1580Sstevel@tonic-gate 		*modlpp = NULL;
1590Sstevel@tonic-gate 	}
1600Sstevel@tonic-gate 	return (status);
1610Sstevel@tonic-gate }
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate int
1640Sstevel@tonic-gate psm_mod_info(void **handlepp, struct psm_info *infop, struct modinfo *modinfop)
1650Sstevel@tonic-gate {
1660Sstevel@tonic-gate 	struct modlinkage **modlpp = (struct modlinkage **)handlepp;
1670Sstevel@tonic-gate 	int status;
1680Sstevel@tonic-gate 	struct modlinkage *mlinkp;
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate 	if (!*modlpp) {
1710Sstevel@tonic-gate 		mlinkp = psm_modlinkage_alloc(infop);
1720Sstevel@tonic-gate 		if (!mlinkp)
1730Sstevel@tonic-gate 			return ((int)NULL);
1740Sstevel@tonic-gate 	} else
1750Sstevel@tonic-gate 		mlinkp = *modlpp;
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	status =  mod_info(mlinkp, modinfop);
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 	if (!status) {
1800Sstevel@tonic-gate 		psm_modlinkage_free(mlinkp);
1810Sstevel@tonic-gate 		*modlpp = NULL;
1820Sstevel@tonic-gate 	} else
1830Sstevel@tonic-gate 		*modlpp = mlinkp;
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate 	return (status);
1860Sstevel@tonic-gate }
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate int
1890Sstevel@tonic-gate psm_add_intr(int lvl, avfunc xxintr, char *name, int vect, caddr_t arg)
1900Sstevel@tonic-gate {
1910Sstevel@tonic-gate 	return (add_avintr((void *)NULL, lvl, xxintr, name, vect,
192916Sschwartz 	    arg, NULL, NULL, NULL));
1930Sstevel@tonic-gate }
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate int
1960Sstevel@tonic-gate psm_add_nmintr(int lvl, avfunc xxintr, char *name, caddr_t arg)
1970Sstevel@tonic-gate {
1980Sstevel@tonic-gate 	return (add_nmintr(lvl, xxintr, name, arg));
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate processorid_t
2020Sstevel@tonic-gate psm_get_cpu_id(void)
2030Sstevel@tonic-gate {
2040Sstevel@tonic-gate 	return (CPU->cpu_id);
2050Sstevel@tonic-gate }
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate caddr_t
2080Sstevel@tonic-gate psm_map_phys_new(paddr_t addr, size_t len, int prot)
2090Sstevel@tonic-gate {
2100Sstevel@tonic-gate 	uint_t pgoffset;
2110Sstevel@tonic-gate 	paddr_t base;
2120Sstevel@tonic-gate 	pgcnt_t npages;
2130Sstevel@tonic-gate 	caddr_t cvaddr;
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	if (len == 0)
2160Sstevel@tonic-gate 		return (0);
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	pgoffset = addr & MMU_PAGEOFFSET;
2195084Sjohnlev #ifdef __xpv
2205084Sjohnlev 	/*
2215084Sjohnlev 	 * If we're dom0, we're starting from a MA. translate that to a PA
2225084Sjohnlev 	 * XXPV - what about driver domains???
2235084Sjohnlev 	 */
2245084Sjohnlev 	if (DOMAIN_IS_INITDOMAIN(xen_info)) {
2255084Sjohnlev 		base = pfn_to_pa(xen_assign_pfn(mmu_btop(addr))) |
2265084Sjohnlev 		    (addr & MMU_PAGEOFFSET);
2275084Sjohnlev 	} else {
2285084Sjohnlev 		base = addr;
2295084Sjohnlev 	}
2305084Sjohnlev #else
2313446Smrj 	base = addr;
2325084Sjohnlev #endif
2330Sstevel@tonic-gate 	npages = mmu_btopr(len + pgoffset);
2340Sstevel@tonic-gate 	cvaddr = device_arena_alloc(ptob(npages), VM_NOSLEEP);
2350Sstevel@tonic-gate 	if (cvaddr == NULL)
2360Sstevel@tonic-gate 		return (0);
2370Sstevel@tonic-gate 	hat_devload(kas.a_hat, cvaddr, mmu_ptob(npages), mmu_btop(base),
2380Sstevel@tonic-gate 	    prot, HAT_LOAD_LOCK);
2390Sstevel@tonic-gate 	return (cvaddr + pgoffset);
2400Sstevel@tonic-gate }
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate void
2430Sstevel@tonic-gate psm_unmap_phys(caddr_t addr, size_t len)
2440Sstevel@tonic-gate {
2450Sstevel@tonic-gate 	uint_t pgoffset;
2460Sstevel@tonic-gate 	caddr_t base;
2470Sstevel@tonic-gate 	pgcnt_t npages;
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	if (len == 0)
2500Sstevel@tonic-gate 		return;
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate 	pgoffset = (uintptr_t)addr & MMU_PAGEOFFSET;
2530Sstevel@tonic-gate 	base = addr - pgoffset;
2540Sstevel@tonic-gate 	npages = mmu_btopr(len + pgoffset);
2550Sstevel@tonic-gate 	hat_unload(kas.a_hat, base, ptob(npages), HAT_UNLOAD_UNLOCK);
2560Sstevel@tonic-gate 	device_arena_free(base, ptob(npages));
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate caddr_t
2600Sstevel@tonic-gate psm_map_new(paddr_t addr, size_t len, int prot)
2610Sstevel@tonic-gate {
2620Sstevel@tonic-gate 	int phys_prot = PROT_READ;
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 	ASSERT(prot == (prot & (PSM_PROT_WRITE | PSM_PROT_READ)));
2650Sstevel@tonic-gate 	if (prot & PSM_PROT_WRITE)
2660Sstevel@tonic-gate 		phys_prot |= PROT_WRITE;
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 	return (psm_map_phys(addr, len, phys_prot));
2690Sstevel@tonic-gate }
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate #undef psm_map_phys
2720Sstevel@tonic-gate #undef psm_map
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate caddr_t
2750Sstevel@tonic-gate psm_map_phys(uint32_t addr, size_t len, int prot)
2760Sstevel@tonic-gate {
2770Sstevel@tonic-gate 	return (psm_map_phys_new((paddr_t)(addr & 0xffffffff), len, prot));
2780Sstevel@tonic-gate }
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate caddr_t
2810Sstevel@tonic-gate psm_map(uint32_t addr, size_t len, int prot)
2820Sstevel@tonic-gate {
2830Sstevel@tonic-gate 	return (psm_map_new((paddr_t)(addr & 0xffffffff), len, prot));
2840Sstevel@tonic-gate }
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate void
2870Sstevel@tonic-gate psm_unmap(caddr_t addr, size_t len)
2880Sstevel@tonic-gate {
2890Sstevel@tonic-gate 	uint_t pgoffset;
2900Sstevel@tonic-gate 	caddr_t base;
2910Sstevel@tonic-gate 	pgcnt_t npages;
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 	if (len == 0)
2940Sstevel@tonic-gate 		return;
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 	pgoffset = (uintptr_t)addr & MMU_PAGEOFFSET;
2970Sstevel@tonic-gate 	base = addr - pgoffset;
2980Sstevel@tonic-gate 	npages = mmu_btopr(len + pgoffset);
2990Sstevel@tonic-gate 	hat_unload(kas.a_hat, base, ptob(npages), HAT_UNLOAD_UNLOCK);
3000Sstevel@tonic-gate 	device_arena_free(base, ptob(npages));
3010Sstevel@tonic-gate }
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate /*ARGSUSED1*/
3040Sstevel@tonic-gate static int
3050Sstevel@tonic-gate mod_installpsm(struct modlpsm *modl, struct modlinkage *modlp)
3060Sstevel@tonic-gate {
3070Sstevel@tonic-gate 	struct psm_sw *swp;
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	swp = modl->psm_swp;
3100Sstevel@tonic-gate 	mutex_enter(&psmsw_lock);
3110Sstevel@tonic-gate 	psmsw->psw_back->psw_forw = swp;
3120Sstevel@tonic-gate 	swp->psw_back = psmsw->psw_back;
3130Sstevel@tonic-gate 	swp->psw_forw = psmsw;
3140Sstevel@tonic-gate 	psmsw->psw_back = swp;
3150Sstevel@tonic-gate 	swp->psw_flag |= PSM_MOD_INSTALL;
3160Sstevel@tonic-gate 	mutex_exit(&psmsw_lock);
3170Sstevel@tonic-gate 	return (0);
3180Sstevel@tonic-gate }
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate /*ARGSUSED1*/
3210Sstevel@tonic-gate static int
3220Sstevel@tonic-gate mod_removepsm(struct modlpsm *modl, struct modlinkage *modlp)
3230Sstevel@tonic-gate {
3240Sstevel@tonic-gate 	struct psm_sw *swp;
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 	swp = modl->psm_swp;
3270Sstevel@tonic-gate 	mutex_enter(&psmsw_lock);
3280Sstevel@tonic-gate 	if (swp->psw_flag & PSM_MOD_IDENTIFY) {
3290Sstevel@tonic-gate 		mutex_exit(&psmsw_lock);
3300Sstevel@tonic-gate 		return (EBUSY);
3310Sstevel@tonic-gate 	}
3320Sstevel@tonic-gate 	if (!(swp->psw_flag & PSM_MOD_INSTALL)) {
3330Sstevel@tonic-gate 		mutex_exit(&psmsw_lock);
3340Sstevel@tonic-gate 		return (0);
3350Sstevel@tonic-gate 	}
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 	swp->psw_back->psw_forw = swp->psw_forw;
3380Sstevel@tonic-gate 	swp->psw_forw->psw_back = swp->psw_back;
3390Sstevel@tonic-gate 	mutex_exit(&psmsw_lock);
3400Sstevel@tonic-gate 	return (0);
3410Sstevel@tonic-gate }
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate /*ARGSUSED1*/
3440Sstevel@tonic-gate static int
3450Sstevel@tonic-gate mod_infopsm(struct modlpsm *modl, struct modlinkage *modlp, int *p0)
3460Sstevel@tonic-gate {
3470Sstevel@tonic-gate 	*p0 = (int)modl->psm_swp->psw_infop->p_owner;
3480Sstevel@tonic-gate 	return (0);
3490Sstevel@tonic-gate }
3500Sstevel@tonic-gate 
3515084Sjohnlev #if defined(__xpv)
3525084Sjohnlev #define	DEFAULT_PSM_MODULE	"xpv_psm"
3535084Sjohnlev #else
3543446Smrj #define	DEFAULT_PSM_MODULE	"uppc"
3555084Sjohnlev #endif
3563446Smrj 
3570Sstevel@tonic-gate static char *
3580Sstevel@tonic-gate psm_get_impl_module(int first)
3590Sstevel@tonic-gate {
3600Sstevel@tonic-gate 	static char **pnamep;
3610Sstevel@tonic-gate 	static char *psm_impl_module_list[] = {
3623446Smrj 		DEFAULT_PSM_MODULE,
3630Sstevel@tonic-gate 		(char *)0
3640Sstevel@tonic-gate 	};
3650Sstevel@tonic-gate 	static void *mhdl = NULL;
3660Sstevel@tonic-gate 	static char machname[MAXNAMELEN];
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate 	if (first)
3690Sstevel@tonic-gate 		pnamep = psm_impl_module_list;
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate 	if (*pnamep != (char *)0)
3720Sstevel@tonic-gate 		return (*pnamep++);
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate 	mhdl = get_next_mach(mhdl, machname);
3750Sstevel@tonic-gate 	if (mhdl)
3760Sstevel@tonic-gate 		return (machname);
3770Sstevel@tonic-gate 	return ((char *)0);
3780Sstevel@tonic-gate }
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate void
3810Sstevel@tonic-gate psm_modload(void)
3820Sstevel@tonic-gate {
3830Sstevel@tonic-gate 	char *this;
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate 	mutex_init(&psmsw_lock, NULL, MUTEX_DEFAULT, NULL);
3860Sstevel@tonic-gate 	open_mach_list();
3870Sstevel@tonic-gate 
3885084Sjohnlev 	for (this = psm_get_impl_module(1); this != (char *)NULL;
3895084Sjohnlev 	    this = psm_get_impl_module(0)) {
3900Sstevel@tonic-gate 		if (modload("mach", this) == -1)
3910Sstevel@tonic-gate 			cmn_err(CE_WARN, "!Cannot load psm %s", this);
3920Sstevel@tonic-gate 	}
3930Sstevel@tonic-gate 	close_mach_list();
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate void
3970Sstevel@tonic-gate psm_install(void)
3980Sstevel@tonic-gate {
3990Sstevel@tonic-gate 	struct psm_sw *swp, *cswp;
4000Sstevel@tonic-gate 	struct psm_ops *opsp;
4010Sstevel@tonic-gate 	char machstring[15];
4020Sstevel@tonic-gate 	int err;
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate 	mutex_enter(&psmsw_lock);
4050Sstevel@tonic-gate 	for (swp = psmsw->psw_forw; swp != psmsw; ) {
4060Sstevel@tonic-gate 		opsp = swp->psw_infop->p_ops;
4070Sstevel@tonic-gate 		if (opsp->psm_probe) {
4080Sstevel@tonic-gate 			if ((*opsp->psm_probe)() == PSM_SUCCESS) {
4090Sstevel@tonic-gate 				swp->psw_flag |= PSM_MOD_IDENTIFY;
4100Sstevel@tonic-gate 				swp = swp->psw_forw;
4110Sstevel@tonic-gate 				continue;
4120Sstevel@tonic-gate 			}
4130Sstevel@tonic-gate 		}
4140Sstevel@tonic-gate 		/* remove the unsuccessful psm modules */
4150Sstevel@tonic-gate 		cswp = swp;
4160Sstevel@tonic-gate 		swp = swp->psw_forw;
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate 		mutex_exit(&psmsw_lock);
4190Sstevel@tonic-gate 		(void) strcpy(&machstring[0], cswp->psw_infop->p_mach_idstring);
4200Sstevel@tonic-gate 		err = mod_remove_by_name(cswp->psw_infop->p_mach_idstring);
4210Sstevel@tonic-gate 		if (err)
4220Sstevel@tonic-gate 			cmn_err(CE_WARN, "%s: mod_remove_by_name failed %d",
4235084Sjohnlev 			    &machstring[0], err);
4240Sstevel@tonic-gate 		mutex_enter(&psmsw_lock);
4250Sstevel@tonic-gate 	}
4260Sstevel@tonic-gate 	mutex_exit(&psmsw_lock);
4270Sstevel@tonic-gate 	(*psminitf)();
4280Sstevel@tonic-gate }
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate /*
4310Sstevel@tonic-gate  * Return 1 if kernel debugger is present, and 0 if not.
4320Sstevel@tonic-gate  */
4330Sstevel@tonic-gate int
4340Sstevel@tonic-gate psm_debugger(void)
4350Sstevel@tonic-gate {
4360Sstevel@tonic-gate 	return ((boothowto & RB_DEBUG) != 0);
4370Sstevel@tonic-gate }
438