1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * zuluvm module 31*0Sstevel@tonic-gate * 32*0Sstevel@tonic-gate * Provides services required by the XVR-4000 graphics accelerator (zulu) 33*0Sstevel@tonic-gate * that are not provided by the ddi. See PSARC 2002/231. 34*0Sstevel@tonic-gate * 35*0Sstevel@tonic-gate * Zulu has 2 dma engines with built in MMUs. zuluvm provides TLB miss 36*0Sstevel@tonic-gate * interrupt support obtaining virtual to physical address translations 37*0Sstevel@tonic-gate * using the XHAT interface PSARC/2003/517. 38*0Sstevel@tonic-gate * 39*0Sstevel@tonic-gate * The module has 3 components. This file, sun4u/vm/zulu_hat.c, and the 40*0Sstevel@tonic-gate * assembly language routines in sun4u/ml/zulu_asm.s and 41*0Sstevel@tonic-gate * sun4u/ml/zulu_hat_asm.s. 42*0Sstevel@tonic-gate * 43*0Sstevel@tonic-gate * The interrupt handler is a data bearing mondo interrupt handled at TL=1 44*0Sstevel@tonic-gate * If no translation is found in the zulu hat's tsb, or if the tsb is locked by 45*0Sstevel@tonic-gate * C code, the handler posts a soft interrupt which wakes up a parked 46*0Sstevel@tonic-gate * thread belonging to zuludaemon(1M). 47*0Sstevel@tonic-gate */ 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate #include <sys/conf.h> 50*0Sstevel@tonic-gate #include <sys/types.h> 51*0Sstevel@tonic-gate #include <sys/kmem.h> 52*0Sstevel@tonic-gate #include <sys/debug.h> 53*0Sstevel@tonic-gate #include <sys/modctl.h> 54*0Sstevel@tonic-gate #include <sys/autoconf.h> 55*0Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 56*0Sstevel@tonic-gate #include <sys/ddi_subrdefs.h> 57*0Sstevel@tonic-gate #include <sys/intr.h> 58*0Sstevel@tonic-gate #include <sys/ddi.h> 59*0Sstevel@tonic-gate #include <sys/sunndi.h> 60*0Sstevel@tonic-gate #include <sys/proc.h> 61*0Sstevel@tonic-gate #include <sys/thread.h> 62*0Sstevel@tonic-gate #include <sys/machsystm.h> 63*0Sstevel@tonic-gate #include <sys/ivintr.h> 64*0Sstevel@tonic-gate #include <sys/tnf_probe.h> 65*0Sstevel@tonic-gate #include <sys/intreg.h> 66*0Sstevel@tonic-gate #include <sys/atomic.h> 67*0Sstevel@tonic-gate #include <vm/as.h> 68*0Sstevel@tonic-gate #include <vm/seg_enum.h> 69*0Sstevel@tonic-gate #include <vm/faultcode.h> 70*0Sstevel@tonic-gate #include <sys/dmv.h> 71*0Sstevel@tonic-gate #include <sys/zulumod.h> 72*0Sstevel@tonic-gate #include <sys/zulu_hat.h> 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate #define ZULUVM_GET_PAGE(val) \ 75*0Sstevel@tonic-gate (caddr_t)((uintptr_t)(val) & PAGEMASK) 76*0Sstevel@tonic-gate #define ZULUVM_GET_AS curthread->t_procp->p_as 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate #define ZULUVM_LOCK mutex_enter(&(zdev->dev_lck)) 79*0Sstevel@tonic-gate #define ZULUVM_UNLOCK mutex_exit(&(zdev->dev_lck)) 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate #define ZULUVM_SET_STATE(_z, b, c) \ 82*0Sstevel@tonic-gate cas32((uint32_t *)&((_z)->zvm.state), c, b) 83*0Sstevel@tonic-gate #define ZULUVM_GET_STATE(_z) \ 84*0Sstevel@tonic-gate (_z)->zvm.state 85*0Sstevel@tonic-gate #define ZULUVM_SET_IDLE(_z) \ 86*0Sstevel@tonic-gate (_z)->zvm.state = ZULUVM_STATE_IDLE; 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate #define ZULUVM_INO_MASK ((1<<INO_SIZE)-1) 89*0Sstevel@tonic-gate #define ZULUVM_IGN_MASK ((1<<IGN_SIZE)-1) 90*0Sstevel@tonic-gate #define ZULUVM_MONDO(_zdev, _n) \ 91*0Sstevel@tonic-gate ((ZULUVM_IGN_MASK & _zdev->agentid) << INO_SIZE) | \ 92*0Sstevel@tonic-gate (ZULUVM_INO_MASK & (_n)) 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate static void zuluvm_stop(zuluvm_state_t *, int, char *); 95*0Sstevel@tonic-gate static zuluvm_proc_t *zuluvm_find_proc(zuluvm_state_t *, struct as *); 96*0Sstevel@tonic-gate static int zuluvm_proc_release(zuluvm_state_t *zdev, zuluvm_proc_t *proc); 97*0Sstevel@tonic-gate static int zuluvm_get_intr_props(zuluvm_state_t *zdev, dev_info_t *devi); 98*0Sstevel@tonic-gate static int zuluvm_driver_attach(zuluvm_state_t *); 99*0Sstevel@tonic-gate static int zuluvm_driver_detach(zuluvm_state_t *); 100*0Sstevel@tonic-gate static void zuluvm_retarget_intr(void *arg); 101*0Sstevel@tonic-gate static void zuluvm_do_retarget(zuluvm_state_t *zdev); 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate extern const unsigned int _mmu_pageshift; 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate extern int zuluvm_base_pgsize; 106*0Sstevel@tonic-gate static int zuluvm_pagesizes[ZULUM_MAX_PG_SIZES + 1]; 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate int zuluvm_fast_tlb = 1; 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate zuluvm_state_t *zuluvm_devtab[ZULUVM_MAX_DEV]; 111*0Sstevel@tonic-gate kmutex_t zuluvm_lck; 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate #ifdef DEBUG 114*0Sstevel@tonic-gate int zuluvm_debug_state = 0; 115*0Sstevel@tonic-gate #endif 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate unsigned long zuluvm_ctx_locked = 0; 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate /* 120*0Sstevel@tonic-gate * Module linkage information for the kernel. 121*0Sstevel@tonic-gate */ 122*0Sstevel@tonic-gate extern struct mod_ops mod_miscops; 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate static struct modlmisc modlmisc = { 125*0Sstevel@tonic-gate &mod_miscops, 126*0Sstevel@tonic-gate "sun4u support " ZULUVM_MOD_VERSION 127*0Sstevel@tonic-gate }; 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate static struct modlinkage modlinkage = { 130*0Sstevel@tonic-gate MODREV_1, 131*0Sstevel@tonic-gate (void *)&modlmisc, 132*0Sstevel@tonic-gate NULL 133*0Sstevel@tonic-gate }; 134*0Sstevel@tonic-gate 135*0Sstevel@tonic-gate int 136*0Sstevel@tonic-gate _init(void) 137*0Sstevel@tonic-gate { 138*0Sstevel@tonic-gate zuluvm_base_pgsize = (_mmu_pageshift - 13) / 3; 139*0Sstevel@tonic-gate if (zulu_hat_init() != 0) { 140*0Sstevel@tonic-gate return (ZULUVM_ERROR); 141*0Sstevel@tonic-gate } 142*0Sstevel@tonic-gate mutex_init(&zuluvm_lck, NULL, MUTEX_DEFAULT, NULL); 143*0Sstevel@tonic-gate return (mod_install(&modlinkage)); 144*0Sstevel@tonic-gate } 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate int 147*0Sstevel@tonic-gate _fini(void) 148*0Sstevel@tonic-gate { 149*0Sstevel@tonic-gate mutex_destroy(&zuluvm_lck); 150*0Sstevel@tonic-gate (void) zulu_hat_destroy(); 151*0Sstevel@tonic-gate return (mod_remove(&modlinkage)); 152*0Sstevel@tonic-gate } 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate int 155*0Sstevel@tonic-gate _info(struct modinfo *modinfop) 156*0Sstevel@tonic-gate { 157*0Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate /* 161*0Sstevel@tonic-gate * currently the kernel driver makes the following assumptions: 162*0Sstevel@tonic-gate * - there is only one TLB miss per zulu device handled at 163*0Sstevel@tonic-gate * any given time 164*0Sstevel@tonic-gate * ==> we only need local data storage per device, not per DMA 165*0Sstevel@tonic-gate * ==> a page fault will block the DMA engine until the fault 166*0Sstevel@tonic-gate * is resolved 167*0Sstevel@tonic-gate * ==> a pagefault will not trigger a zulu DMA context switch 168*0Sstevel@tonic-gate * 169*0Sstevel@tonic-gate * If we want to implement asynnchronous zulu page fault, then we 170*0Sstevel@tonic-gate * need to keep track of outstanding faults while zulu DMA runs 171*0Sstevel@tonic-gate * in a different context. 172*0Sstevel@tonic-gate */ 173*0Sstevel@tonic-gate static int 174*0Sstevel@tonic-gate zuluvm_write_tte(zuluvm_state_t *zdev, void *arg, caddr_t addr, 175*0Sstevel@tonic-gate int t_pfn, int t_perm, int t_size, uint64_t tag, 176*0Sstevel@tonic-gate int tlbtype, int *size) 177*0Sstevel@tonic-gate { 178*0Sstevel@tonic-gate int error; 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate (void) addr; 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gate ZULUVM_STATS_MISS(zdev, t_size); 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate if (tag == 0) { /* not coming from preload */ 185*0Sstevel@tonic-gate int state = ZULUVM_SET_STATE(zdev, ZULUVM_STATE_WRITE_TTE, 186*0Sstevel@tonic-gate ZULUVM_STATE_INTR_PENDING); 187*0Sstevel@tonic-gate if (state != ZULUVM_STATE_INTR_PENDING) { 188*0Sstevel@tonic-gate zuluvm_stop(zdev, state, "zuluvm_write_tte"); 189*0Sstevel@tonic-gate return (ZULUVM_MISS_CANCELED); 190*0Sstevel@tonic-gate } 191*0Sstevel@tonic-gate } 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate if (!(tlbtype & ZULUVM_ITLB_FLAG) && 194*0Sstevel@tonic-gate t_size != zuluvm_base_pgsize && 195*0Sstevel@tonic-gate t_size != ZULU_TTE4M) { 196*0Sstevel@tonic-gate t_size = zuluvm_base_pgsize; 197*0Sstevel@tonic-gate TNF_PROBE_2(zuluvm_write_tte_new_pfn, "zuluvm", /* */, 198*0Sstevel@tonic-gate tnf_opaque, t_pfn, t_pfn, tnf_int, pagesize, t_size); 199*0Sstevel@tonic-gate } 200*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_write_tte, "zuluvm", /* */, 201*0Sstevel@tonic-gate tnf_opaque, t_pfn, t_pfn); 202*0Sstevel@tonic-gate /* 203*0Sstevel@tonic-gate * if the caller is zuluvm_preload, then we need to pass 204*0Sstevel@tonic-gate * back the page size so it can add the right offset. 205*0Sstevel@tonic-gate */ 206*0Sstevel@tonic-gate if (size) 207*0Sstevel@tonic-gate *size = t_size; 208*0Sstevel@tonic-gate 209*0Sstevel@tonic-gate error = zulud_write_tte(zdev, arg, t_size, tag, t_pfn, 210*0Sstevel@tonic-gate t_perm, tlbtype); 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate return (error); 213*0Sstevel@tonic-gate } 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate static void 216*0Sstevel@tonic-gate zuluvm_stop(zuluvm_state_t *zdev, int state, char *tag) 217*0Sstevel@tonic-gate { 218*0Sstevel@tonic-gate int ostate = state; 219*0Sstevel@tonic-gate while (state != ZULUVM_STATE_STOPPED) { 220*0Sstevel@tonic-gate state = ZULUVM_SET_STATE(zdev, 221*0Sstevel@tonic-gate ZULUVM_STATE_STOPPED, state); 222*0Sstevel@tonic-gate #ifdef DEBUG 223*0Sstevel@tonic-gate if (zuluvm_debug_state) 224*0Sstevel@tonic-gate cmn_err(CE_NOTE, "zuluvm_stop(%s): (loop) state %d\n", 225*0Sstevel@tonic-gate tag, state); 226*0Sstevel@tonic-gate #endif 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate TNF_PROBE_2(zuluvm_stop, "zuluvm", /* */, 229*0Sstevel@tonic-gate tnf_string, tag, tag, 230*0Sstevel@tonic-gate tnf_int, state, ostate); 231*0Sstevel@tonic-gate ZULUVM_STATS_CANCEL(zdev); 232*0Sstevel@tonic-gate } 233*0Sstevel@tonic-gate 234*0Sstevel@tonic-gate /* 235*0Sstevel@tonic-gate * Executed with the context of the parked zulu deamon thread, 236*0Sstevel@tonic-gate * uses zulu_hat_load to resolve the miss. 237*0Sstevel@tonic-gate * The tte is loaded and miss done called by the function zuluvm_load_tte 238*0Sstevel@tonic-gate * which is called from zulu_hat 239*0Sstevel@tonic-gate * 240*0Sstevel@tonic-gate * This function is synchronized with the zuluvm_as_free. 241*0Sstevel@tonic-gate * zuluvm_as_free will block until miss servicing is complete. 242*0Sstevel@tonic-gate * 243*0Sstevel@tonic-gate * There is a race condition between as_free and the zulu tlb miss 244*0Sstevel@tonic-gate * soft interrupt: 245*0Sstevel@tonic-gate * - queue zulu interrupt 246*0Sstevel@tonic-gate * - process dies, as_free runs 247*0Sstevel@tonic-gate * - interrupt gets scheduled and runs as_fault on the 248*0Sstevel@tonic-gate * already freed as. 249*0Sstevel@tonic-gate * This is solved by keeping track of current zulu dma processes 250*0Sstevel@tonic-gate * and invalidating them in zuluvm_as_free. 251*0Sstevel@tonic-gate */ 252*0Sstevel@tonic-gate uint_t 253*0Sstevel@tonic-gate zuluvm_tlb_handler(caddr_t data) 254*0Sstevel@tonic-gate { 255*0Sstevel@tonic-gate zuluvm_state_t *zdev = (zuluvm_state_t *)data; 256*0Sstevel@tonic-gate int error; 257*0Sstevel@tonic-gate int flag = 0; 258*0Sstevel@tonic-gate int wait = 0; 259*0Sstevel@tonic-gate zuluvm_proc_t *proc = NULL; 260*0Sstevel@tonic-gate struct zulu_hat *zhat = NULL; 261*0Sstevel@tonic-gate caddr_t addr; 262*0Sstevel@tonic-gate int tlbtype; 263*0Sstevel@tonic-gate void *arg; 264*0Sstevel@tonic-gate int state, newstate; 265*0Sstevel@tonic-gate 266*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_tlb_handler_lwp, "zuluvm", /* */, 267*0Sstevel@tonic-gate tnf_opaque, lwp, ttolwp(curthread)); 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate ZULUVM_LOCK; 270*0Sstevel@tonic-gate error = ZULUVM_GET_TLB_ERRCODE(zdev); 271*0Sstevel@tonic-gate addr = (caddr_t)ZULUVM_GET_TLB_ADDR(zdev); 272*0Sstevel@tonic-gate tlbtype = ZULUVM_GET_TLB_TYPE(zdev); 273*0Sstevel@tonic-gate arg = zdev->zvm.arg; 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate /* 276*0Sstevel@tonic-gate * select the correct dma engine and remember the 277*0Sstevel@tonic-gate * the as_free synchronization flags. 278*0Sstevel@tonic-gate */ 279*0Sstevel@tonic-gate switch (tlbtype) { 280*0Sstevel@tonic-gate case ZULUVM_ITLB1: 281*0Sstevel@tonic-gate case ZULUVM_DMA1: 282*0Sstevel@tonic-gate proc = zdev->zvm.proc1; 283*0Sstevel@tonic-gate flag |= ZULUVM_DO_INTR1; 284*0Sstevel@tonic-gate wait |= ZULUVM_WAIT_INTR1; 285*0Sstevel@tonic-gate break; 286*0Sstevel@tonic-gate case ZULUVM_ITLB2: 287*0Sstevel@tonic-gate case ZULUVM_DMA2: 288*0Sstevel@tonic-gate proc = zdev->zvm.proc2; 289*0Sstevel@tonic-gate flag |= ZULUVM_DO_INTR2; 290*0Sstevel@tonic-gate wait |= ZULUVM_WAIT_INTR2; 291*0Sstevel@tonic-gate break; 292*0Sstevel@tonic-gate } 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate state = ZULUVM_SET_STATE(zdev, ZULUVM_STATE_INTR_PENDING, 295*0Sstevel@tonic-gate ZULUVM_STATE_INTR_QUEUED); 296*0Sstevel@tonic-gate newstate = ZULUVM_GET_STATE(zdev); 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate TNF_PROBE_2(zuluvm_tlb_handler_state, "zuluvm", /* */, 299*0Sstevel@tonic-gate tnf_int, oldstate, state, 300*0Sstevel@tonic-gate tnf_int, newstate, newstate); 301*0Sstevel@tonic-gate #ifdef DEBUG 302*0Sstevel@tonic-gate if (zuluvm_debug_state) 303*0Sstevel@tonic-gate cmn_err(CE_NOTE, "zuluvm_tlb_handler: state %d\n", state); 304*0Sstevel@tonic-gate #endif 305*0Sstevel@tonic-gate if (state != ZULUVM_STATE_INTR_PENDING && 306*0Sstevel@tonic-gate state != ZULUVM_STATE_INTR_QUEUED) { 307*0Sstevel@tonic-gate ZULUVM_UNLOCK; 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate zuluvm_stop(zdev, state, "softintr1"); 310*0Sstevel@tonic-gate zulud_tlb_done(zdev, arg, tlbtype, ZULUVM_MISS_CANCELED); 311*0Sstevel@tonic-gate return (1); 312*0Sstevel@tonic-gate } 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate /* 315*0Sstevel@tonic-gate * block the as_free callback in case it comes in 316*0Sstevel@tonic-gate */ 317*0Sstevel@tonic-gate zdev->intr_flags |= flag; 318*0Sstevel@tonic-gate ZULUVM_UNLOCK; 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate mutex_enter(&zdev->proc_lck); 321*0Sstevel@tonic-gate /* 322*0Sstevel@tonic-gate * check if this as is still valid 323*0Sstevel@tonic-gate */ 324*0Sstevel@tonic-gate if (proc == NULL || proc->valid == 0 || proc->zhat == NULL) { 325*0Sstevel@tonic-gate mutex_exit(&zdev->proc_lck); 326*0Sstevel@tonic-gate /* 327*0Sstevel@tonic-gate * we are on our way out, wake up the as_free 328*0Sstevel@tonic-gate * callback if it is waiting for us 329*0Sstevel@tonic-gate */ 330*0Sstevel@tonic-gate ZULUVM_LOCK; 331*0Sstevel@tonic-gate zdev->intr_flags &= ~flag; 332*0Sstevel@tonic-gate if (zdev->intr_flags | wait) 333*0Sstevel@tonic-gate cv_broadcast(&zdev->intr_wait); 334*0Sstevel@tonic-gate ZULUVM_UNLOCK; 335*0Sstevel@tonic-gate state = ZULUVM_SET_STATE(zdev, ZULUVM_STATE_IDLE, 336*0Sstevel@tonic-gate ZULUVM_STATE_INTR_PENDING); 337*0Sstevel@tonic-gate if (state != ZULUVM_STATE_INTR_PENDING) { 338*0Sstevel@tonic-gate zuluvm_stop(zdev, state, "softintr3"); 339*0Sstevel@tonic-gate } 340*0Sstevel@tonic-gate zulud_tlb_done(zdev, arg, tlbtype, ZULUVM_NO_HAT); 341*0Sstevel@tonic-gate return (1); 342*0Sstevel@tonic-gate } 343*0Sstevel@tonic-gate zhat = proc->zhat; 344*0Sstevel@tonic-gate mutex_exit(&zdev->proc_lck); 345*0Sstevel@tonic-gate 346*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_tlb_handler, "zuluvm", /* */, 347*0Sstevel@tonic-gate tnf_opaque, addr, addr); 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate switch (error) { 350*0Sstevel@tonic-gate case ZULUVM_CTX_LOCKED: 351*0Sstevel@tonic-gate /* 352*0Sstevel@tonic-gate * trap handler found that zulu_hat had the lock bit set 353*0Sstevel@tonic-gate * rather than block in the fast trap handler, it punts 354*0Sstevel@tonic-gate * in this rare instance 355*0Sstevel@tonic-gate */ 356*0Sstevel@tonic-gate ++zuluvm_ctx_locked; 357*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_ctx_locked, "zuluvm", /* CSTYLED */, 358*0Sstevel@tonic-gate tnf_ulong, zuluvm_ctx_locked, zuluvm_ctx_locked); 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gate /*FALLTHROUGH*/ 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate case ZULUVM_TTE_DELAY: 363*0Sstevel@tonic-gate /* 364*0Sstevel@tonic-gate * fast tlb handler was skipped, see zuluvm_fast_tlb flag 365*0Sstevel@tonic-gate */ 366*0Sstevel@tonic-gate /*FALLTHROUGH*/ 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate case ZULUVM_NO_TTE: 369*0Sstevel@tonic-gate /* 370*0Sstevel@tonic-gate * no TSB entry and TTE in the hash 371*0Sstevel@tonic-gate */ 372*0Sstevel@tonic-gate mutex_enter(&zdev->load_lck); 373*0Sstevel@tonic-gate zdev->in_intr = 1; 374*0Sstevel@tonic-gate error = zulu_hat_load(zhat, addr, 375*0Sstevel@tonic-gate (tlbtype == ZULUVM_DMA2) ? S_WRITE : S_READ, NULL); 376*0Sstevel@tonic-gate zdev->in_intr = 0; 377*0Sstevel@tonic-gate mutex_exit(&zdev->load_lck); 378*0Sstevel@tonic-gate if (error) { 379*0Sstevel@tonic-gate 380*0Sstevel@tonic-gate error = ZULUVM_NO_MAP; 381*0Sstevel@tonic-gate } else { 382*0Sstevel@tonic-gate error = ZULUVM_SUCCESS; 383*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_tlb_handler_done, "zuluvm", /* */, 384*0Sstevel@tonic-gate tnf_int, error, error); 385*0Sstevel@tonic-gate return (1); 386*0Sstevel@tonic-gate } 387*0Sstevel@tonic-gate 388*0Sstevel@tonic-gate default: 389*0Sstevel@tonic-gate /* 390*0Sstevel@tonic-gate * error case, fall through and tell zulu driver to abort DMA 391*0Sstevel@tonic-gate */ 392*0Sstevel@tonic-gate break; 393*0Sstevel@tonic-gate } 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate if (error != ZULUVM_MISS_CANCELED) { 396*0Sstevel@tonic-gate state = ZULUVM_SET_STATE(zdev, ZULUVM_STATE_IDLE, 397*0Sstevel@tonic-gate ZULUVM_STATE_WRITE_TTE); 398*0Sstevel@tonic-gate newstate = ZULUVM_GET_STATE(zdev); 399*0Sstevel@tonic-gate TNF_PROBE_2(zuluvm_tlb_handler_state_done, "zuluvm", /* */, 400*0Sstevel@tonic-gate tnf_int, oldstate, state, 401*0Sstevel@tonic-gate tnf_int, newstate, newstate); 402*0Sstevel@tonic-gate if (state != ZULUVM_STATE_WRITE_TTE) { 403*0Sstevel@tonic-gate zuluvm_stop(zdev, state, "softintr4"); 404*0Sstevel@tonic-gate } 405*0Sstevel@tonic-gate } 406*0Sstevel@tonic-gate /* 407*0Sstevel@tonic-gate * synchronize with as_free callback 408*0Sstevel@tonic-gate * It will set the wait flag, in that case we send 409*0Sstevel@tonic-gate * a wake up. 410*0Sstevel@tonic-gate */ 411*0Sstevel@tonic-gate ZULUVM_LOCK; 412*0Sstevel@tonic-gate zdev->intr_flags &= ~flag; 413*0Sstevel@tonic-gate if (zdev->intr_flags | wait) 414*0Sstevel@tonic-gate cv_broadcast(&zdev->intr_wait); 415*0Sstevel@tonic-gate ZULUVM_UNLOCK; 416*0Sstevel@tonic-gate 417*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_tlb_handler_done, "zuluvm", /* */, 418*0Sstevel@tonic-gate tnf_int, error, error); 419*0Sstevel@tonic-gate 420*0Sstevel@tonic-gate zulud_tlb_done(zdev, arg, tlbtype, error); 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate return (1); 423*0Sstevel@tonic-gate } 424*0Sstevel@tonic-gate 425*0Sstevel@tonic-gate 426*0Sstevel@tonic-gate void 427*0Sstevel@tonic-gate zuluvm_load_tte(struct zulu_hat *zhat, caddr_t addr, uint64_t pfn, 428*0Sstevel@tonic-gate int perm, int size) 429*0Sstevel@tonic-gate { 430*0Sstevel@tonic-gate zuluvm_state_t *zdev = zhat->zdev; 431*0Sstevel@tonic-gate int tlbtype = ZULUVM_GET_TLB_TYPE(zdev); 432*0Sstevel@tonic-gate 433*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&zdev->load_lck)); 434*0Sstevel@tonic-gate ASSERT(pfn != 0); 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate if (zdev->in_intr) { 437*0Sstevel@tonic-gate int error; 438*0Sstevel@tonic-gate int flag = 0; 439*0Sstevel@tonic-gate int wait = 0; 440*0Sstevel@tonic-gate 441*0Sstevel@tonic-gate error = zuluvm_write_tte(zdev, zdev->zvm.arg, addr, pfn, 442*0Sstevel@tonic-gate perm, size, 0, tlbtype, NULL); 443*0Sstevel@tonic-gate 444*0Sstevel@tonic-gate if (error != ZULUVM_MISS_CANCELED) { 445*0Sstevel@tonic-gate int state, newstate; 446*0Sstevel@tonic-gate 447*0Sstevel@tonic-gate state = ZULUVM_SET_STATE(zdev, ZULUVM_STATE_IDLE, 448*0Sstevel@tonic-gate ZULUVM_STATE_WRITE_TTE); 449*0Sstevel@tonic-gate newstate = ZULUVM_GET_STATE(zdev); 450*0Sstevel@tonic-gate TNF_PROBE_2(zuluvm_tlb_handler_state_done, "zuluvm", 451*0Sstevel@tonic-gate /* */, tnf_int, oldstate, state, 452*0Sstevel@tonic-gate tnf_int, newstate, newstate); 453*0Sstevel@tonic-gate if (state != ZULUVM_STATE_WRITE_TTE) { 454*0Sstevel@tonic-gate zuluvm_stop(zdev, state, "softintr4"); 455*0Sstevel@tonic-gate } 456*0Sstevel@tonic-gate } 457*0Sstevel@tonic-gate /* 458*0Sstevel@tonic-gate * synchronize with as_free callback 459*0Sstevel@tonic-gate * It will set the wait flag, in that case we send 460*0Sstevel@tonic-gate * a wake up. 461*0Sstevel@tonic-gate */ 462*0Sstevel@tonic-gate switch (tlbtype) { 463*0Sstevel@tonic-gate case ZULUVM_ITLB1: 464*0Sstevel@tonic-gate case ZULUVM_DMA1: 465*0Sstevel@tonic-gate flag = ZULUVM_DO_INTR1; 466*0Sstevel@tonic-gate wait = ZULUVM_WAIT_INTR1; 467*0Sstevel@tonic-gate break; 468*0Sstevel@tonic-gate case ZULUVM_ITLB2: 469*0Sstevel@tonic-gate case ZULUVM_DMA2: 470*0Sstevel@tonic-gate flag = ZULUVM_DO_INTR2; 471*0Sstevel@tonic-gate wait = ZULUVM_WAIT_INTR2; 472*0Sstevel@tonic-gate break; 473*0Sstevel@tonic-gate } 474*0Sstevel@tonic-gate 475*0Sstevel@tonic-gate ZULUVM_LOCK; 476*0Sstevel@tonic-gate zdev->intr_flags &= ~flag; 477*0Sstevel@tonic-gate if (zdev->intr_flags | wait) 478*0Sstevel@tonic-gate cv_broadcast(&zdev->intr_wait); 479*0Sstevel@tonic-gate ZULUVM_UNLOCK; 480*0Sstevel@tonic-gate 481*0Sstevel@tonic-gate zulud_tlb_done(zdev, zdev->zvm.arg, tlbtype, error); 482*0Sstevel@tonic-gate } else { 483*0Sstevel@tonic-gate (void) zuluvm_write_tte(zdev, zdev->zvm.arg, addr, pfn, 484*0Sstevel@tonic-gate perm, size, (uint64_t)addr | 485*0Sstevel@tonic-gate zhat->zulu_ctx, tlbtype, NULL); 486*0Sstevel@tonic-gate } 487*0Sstevel@tonic-gate } 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gate 490*0Sstevel@tonic-gate 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate /* 493*0Sstevel@tonic-gate * This function provides the faulting thread for zulu page faults 494*0Sstevel@tonic-gate * It is call from the device driver in response to an ioctl issued 495*0Sstevel@tonic-gate * by a zuludaemon thread. 496*0Sstevel@tonic-gate * It sits in cv_wait_sig until it gets woken up by a signal or 497*0Sstevel@tonic-gate * zulu tlb miss soft interrupt. 498*0Sstevel@tonic-gate */ 499*0Sstevel@tonic-gate int 500*0Sstevel@tonic-gate zuluvm_park(zuluvm_info_t devp) 501*0Sstevel@tonic-gate { 502*0Sstevel@tonic-gate int rval; 503*0Sstevel@tonic-gate zuluvm_state_t *zdev = (zuluvm_state_t *)devp; 504*0Sstevel@tonic-gate mutex_enter(&zdev->park_lck); 505*0Sstevel@tonic-gate zdev->parking = 1; 506*0Sstevel@tonic-gate for (;;) { 507*0Sstevel@tonic-gate rval = cv_wait_sig(&zdev->park_cv, &zdev->park_lck); 508*0Sstevel@tonic-gate if (rval == 0) 509*0Sstevel@tonic-gate break; 510*0Sstevel@tonic-gate rval = zuluvm_tlb_handler(devp); 511*0Sstevel@tonic-gate } 512*0Sstevel@tonic-gate zdev->parking = 0; 513*0Sstevel@tonic-gate mutex_exit(&zdev->park_lck); 514*0Sstevel@tonic-gate return (rval); 515*0Sstevel@tonic-gate } 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate /* 518*0Sstevel@tonic-gate * zulu soft interrupt handler, just triggers the parked zulu fault 519*0Sstevel@tonic-gate * thread 520*0Sstevel@tonic-gate */ 521*0Sstevel@tonic-gate /*ARGSUSED*/ 522*0Sstevel@tonic-gate uint_t 523*0Sstevel@tonic-gate zuluvm_softintr(caddr_t devp, caddr_t arg2) 524*0Sstevel@tonic-gate { 525*0Sstevel@tonic-gate int tlbtype; 526*0Sstevel@tonic-gate void *arg; 527*0Sstevel@tonic-gate zuluvm_state_t *zdev = (zuluvm_state_t *)devp; 528*0Sstevel@tonic-gate mutex_enter(&zdev->park_lck); 529*0Sstevel@tonic-gate if (zdev->parking) { 530*0Sstevel@tonic-gate cv_signal(&zdev->park_cv); 531*0Sstevel@tonic-gate mutex_exit(&zdev->park_lck); 532*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_fast_intr, "zuluvm", /* */, 533*0Sstevel@tonic-gate tnf_opaque, devp, devp); 534*0Sstevel@tonic-gate } else { 535*0Sstevel@tonic-gate mutex_exit(&zdev->park_lck); 536*0Sstevel@tonic-gate cmn_err(CE_NOTE, "zuluvm: no page fault thread\n"); 537*0Sstevel@tonic-gate ZULUVM_LOCK; 538*0Sstevel@tonic-gate tlbtype = ZULUVM_GET_TLB_TYPE(zdev); 539*0Sstevel@tonic-gate arg = zdev->zvm.arg; 540*0Sstevel@tonic-gate ZULUVM_UNLOCK; 541*0Sstevel@tonic-gate TNF_PROBE_0(zuluvm_fast_intr, "zuluvm", /* */); 542*0Sstevel@tonic-gate zuluvm_stop(zdev, ZULUVM_STATE_INTR_QUEUED, "fast_intr"); 543*0Sstevel@tonic-gate zulud_tlb_done(zdev, arg, tlbtype, ZULUVM_NO_TTE); 544*0Sstevel@tonic-gate } 545*0Sstevel@tonic-gate return (1); 546*0Sstevel@tonic-gate } 547*0Sstevel@tonic-gate 548*0Sstevel@tonic-gate /* ***** public interface for process mapping events (hat layer) ***** */ 549*0Sstevel@tonic-gate 550*0Sstevel@tonic-gate /* 551*0Sstevel@tonic-gate * If the page size matches the Zulu page sizes then just pass 552*0Sstevel@tonic-gate * it thru. If not then emulate the page demap with demaps of 553*0Sstevel@tonic-gate * smaller page size. 554*0Sstevel@tonic-gate */ 555*0Sstevel@tonic-gate /* ARGSUSED */ 556*0Sstevel@tonic-gate void 557*0Sstevel@tonic-gate zuluvm_demap_page(void *arg, struct hat *hat_ptr, short ctx, 558*0Sstevel@tonic-gate caddr_t vaddr, uint_t size) 559*0Sstevel@tonic-gate { 560*0Sstevel@tonic-gate void *ddarg; 561*0Sstevel@tonic-gate zuluvm_state_t *zdev = (zuluvm_state_t *)arg; 562*0Sstevel@tonic-gate 563*0Sstevel@tonic-gate if (arg == NULL) 564*0Sstevel@tonic-gate return; 565*0Sstevel@tonic-gate 566*0Sstevel@tonic-gate ZULUVM_STATS_DEMAP_PAGE(zdev); 567*0Sstevel@tonic-gate 568*0Sstevel@tonic-gate ddarg = zdev->zvm.arg; 569*0Sstevel@tonic-gate 570*0Sstevel@tonic-gate TNF_PROBE_3(zuluvm_demap_page, "zuluvm", /* */, 571*0Sstevel@tonic-gate tnf_opaque, addr, vaddr, 572*0Sstevel@tonic-gate tnf_int, size, size, 573*0Sstevel@tonic-gate tnf_int, ctx, ctx); 574*0Sstevel@tonic-gate 575*0Sstevel@tonic-gate if (ddarg != NULL) { 576*0Sstevel@tonic-gate if (size != zuluvm_base_pgsize && 577*0Sstevel@tonic-gate size != ZULU_TTE4M) { 578*0Sstevel@tonic-gate int i; 579*0Sstevel@tonic-gate int cnt = size - zuluvm_base_pgsize; 580*0Sstevel@tonic-gate cnt = ZULU_HAT_SZ_SHIFT(cnt); 581*0Sstevel@tonic-gate for (i = 0; i < cnt; i++) { 582*0Sstevel@tonic-gate uintptr_t addr = (uintptr_t)vaddr | 583*0Sstevel@tonic-gate i << ZULU_HAT_BP_SHIFT; 584*0Sstevel@tonic-gate zulud_demap_page(zdev, ddarg, 585*0Sstevel@tonic-gate (caddr_t)addr, ctx); 586*0Sstevel@tonic-gate } 587*0Sstevel@tonic-gate } else { 588*0Sstevel@tonic-gate zulud_demap_page(zdev, ddarg, vaddr, ctx); 589*0Sstevel@tonic-gate } 590*0Sstevel@tonic-gate TNF_PROBE_0(zuluvm_demap_page_done, "zuluvm", /* */); 591*0Sstevel@tonic-gate } else { 592*0Sstevel@tonic-gate TNF_PROBE_0(zuluvm_demap_page_null_ddarg, "zuluvm", /* */); 593*0Sstevel@tonic-gate } 594*0Sstevel@tonic-gate } 595*0Sstevel@tonic-gate 596*0Sstevel@tonic-gate /* 597*0Sstevel@tonic-gate * An entire context has gone away, just pass it thru 598*0Sstevel@tonic-gate */ 599*0Sstevel@tonic-gate void 600*0Sstevel@tonic-gate zuluvm_demap_ctx(void *arg, short ctx) 601*0Sstevel@tonic-gate { 602*0Sstevel@tonic-gate void *ddarg; 603*0Sstevel@tonic-gate zuluvm_state_t *zdev = (zuluvm_state_t *)arg; 604*0Sstevel@tonic-gate 605*0Sstevel@tonic-gate if (arg == NULL) 606*0Sstevel@tonic-gate return; 607*0Sstevel@tonic-gate 608*0Sstevel@tonic-gate ZULUVM_STATS_DEMAP_CTX(zdev); 609*0Sstevel@tonic-gate 610*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_demap_ctx, "zuluvm", /* */, 611*0Sstevel@tonic-gate tnf_int, ctx, ctx); 612*0Sstevel@tonic-gate ddarg = zdev->zvm.arg; 613*0Sstevel@tonic-gate 614*0Sstevel@tonic-gate if (ddarg != NULL) 615*0Sstevel@tonic-gate zulud_demap_ctx(zdev, ddarg, ctx); 616*0Sstevel@tonic-gate } 617*0Sstevel@tonic-gate 618*0Sstevel@tonic-gate static int 619*0Sstevel@tonic-gate zuluvm_driver_attach(zuluvm_state_t *zdev) 620*0Sstevel@tonic-gate { 621*0Sstevel@tonic-gate int i; 622*0Sstevel@tonic-gate mutex_enter(&zuluvm_lck); 623*0Sstevel@tonic-gate for (i = 0; i < ZULUVM_MAX_DEV; i++) { 624*0Sstevel@tonic-gate if (zuluvm_devtab[i] == NULL) { 625*0Sstevel@tonic-gate zuluvm_devtab[i] = zdev; 626*0Sstevel@tonic-gate ZULUVM_SET_IDLE(zdev); 627*0Sstevel@tonic-gate break; 628*0Sstevel@tonic-gate } 629*0Sstevel@tonic-gate } 630*0Sstevel@tonic-gate mutex_exit(&zuluvm_lck); 631*0Sstevel@tonic-gate if (i >= ZULUVM_MAX_DEV) 632*0Sstevel@tonic-gate return (ZULUVM_ERROR); 633*0Sstevel@tonic-gate 634*0Sstevel@tonic-gate if (zulu_hat_attach((void *)zdev) != 0) { 635*0Sstevel@tonic-gate return (ZULUVM_ERROR); 636*0Sstevel@tonic-gate } 637*0Sstevel@tonic-gate 638*0Sstevel@tonic-gate mutex_init(&zdev->dev_lck, NULL, MUTEX_DEFAULT, NULL); 639*0Sstevel@tonic-gate mutex_init(&zdev->load_lck, NULL, MUTEX_DEFAULT, NULL); 640*0Sstevel@tonic-gate mutex_init(&zdev->proc_lck, NULL, MUTEX_DEFAULT, NULL); 641*0Sstevel@tonic-gate mutex_init(&zdev->park_lck, NULL, MUTEX_DEFAULT, NULL); 642*0Sstevel@tonic-gate cv_init(&zdev->park_cv, NULL, CV_DEFAULT, NULL); 643*0Sstevel@tonic-gate cv_init(&zdev->intr_wait, NULL, CV_DEFAULT, NULL); 644*0Sstevel@tonic-gate zdev->parking = 0; 645*0Sstevel@tonic-gate 646*0Sstevel@tonic-gate #ifdef ZULUVM_STATS 647*0Sstevel@tonic-gate zdev->zvm.cancel = 0; 648*0Sstevel@tonic-gate zdev->zvm.pagefault = 0; 649*0Sstevel@tonic-gate zdev->zvm.no_mapping = 0; 650*0Sstevel@tonic-gate zdev->zvm.preload = 0; 651*0Sstevel@tonic-gate zdev->zvm.migrate = 0; 652*0Sstevel@tonic-gate zdev->zvm.pagesize = 0; 653*0Sstevel@tonic-gate zdev->zvm.tlb_miss[0] = 0; 654*0Sstevel@tonic-gate zdev->zvm.tlb_miss[1] = 0; 655*0Sstevel@tonic-gate zdev->zvm.tlb_miss[2] = 0; 656*0Sstevel@tonic-gate zdev->zvm.tlb_miss[3] = 0; 657*0Sstevel@tonic-gate zdev->zvm.itlb1miss = 0; 658*0Sstevel@tonic-gate zdev->zvm.dtlb1miss = 0; 659*0Sstevel@tonic-gate zdev->zvm.itlb2miss = 0; 660*0Sstevel@tonic-gate zdev->zvm.dtlb2miss = 0; 661*0Sstevel@tonic-gate #endif 662*0Sstevel@tonic-gate zdev->zvm.pfncnt = 0; 663*0Sstevel@tonic-gate for (i = 0; i < 50; i++) 664*0Sstevel@tonic-gate zdev->zvm.pfnbuf[i] = 0; 665*0Sstevel@tonic-gate 666*0Sstevel@tonic-gate zdev->zvm.mmu_pa = NULL; 667*0Sstevel@tonic-gate zdev->zvm.proc1 = NULL; 668*0Sstevel@tonic-gate zdev->zvm.proc2 = NULL; 669*0Sstevel@tonic-gate zdev->procs = NULL; 670*0Sstevel@tonic-gate return (ZULUVM_SUCCESS); 671*0Sstevel@tonic-gate } 672*0Sstevel@tonic-gate 673*0Sstevel@tonic-gate static int 674*0Sstevel@tonic-gate zuluvm_driver_detach(zuluvm_state_t *zdev) 675*0Sstevel@tonic-gate { 676*0Sstevel@tonic-gate int i; 677*0Sstevel@tonic-gate cv_destroy(&zdev->intr_wait); 678*0Sstevel@tonic-gate cv_destroy(&zdev->park_cv); 679*0Sstevel@tonic-gate mutex_destroy(&zdev->park_lck); 680*0Sstevel@tonic-gate mutex_destroy(&zdev->proc_lck); 681*0Sstevel@tonic-gate mutex_destroy(&zdev->dev_lck); 682*0Sstevel@tonic-gate mutex_destroy(&zdev->load_lck); 683*0Sstevel@tonic-gate zdev->dops = NULL; 684*0Sstevel@tonic-gate 685*0Sstevel@tonic-gate mutex_enter(&zuluvm_lck); 686*0Sstevel@tonic-gate for (i = 0; i < ZULUVM_MAX_DEV; i++) { 687*0Sstevel@tonic-gate if (zuluvm_devtab[i] == zdev) { 688*0Sstevel@tonic-gate zuluvm_devtab[i] = NULL; 689*0Sstevel@tonic-gate break; 690*0Sstevel@tonic-gate } 691*0Sstevel@tonic-gate } 692*0Sstevel@tonic-gate mutex_exit(&zuluvm_lck); 693*0Sstevel@tonic-gate 694*0Sstevel@tonic-gate if (zulu_hat_detach((void *)zdev) == 0) { 695*0Sstevel@tonic-gate return (ZULUVM_SUCCESS); 696*0Sstevel@tonic-gate } else { 697*0Sstevel@tonic-gate return (ZULUVM_ERROR); 698*0Sstevel@tonic-gate } 699*0Sstevel@tonic-gate } 700*0Sstevel@tonic-gate 701*0Sstevel@tonic-gate zulud_ops_t *zuluvm_dops = NULL; 702*0Sstevel@tonic-gate 703*0Sstevel@tonic-gate /* 704*0Sstevel@tonic-gate * init the zulu kernel driver (variables, locks, etc) 705*0Sstevel@tonic-gate */ 706*0Sstevel@tonic-gate int 707*0Sstevel@tonic-gate zuluvm_init(zulud_ops_t *ops, int **pagesizes) 708*0Sstevel@tonic-gate { 709*0Sstevel@tonic-gate int error = ZULUVM_SUCCESS; 710*0Sstevel@tonic-gate int i; 711*0Sstevel@tonic-gate int size = zuluvm_base_pgsize; /* MMU_PAGESIZE; */ 712*0Sstevel@tonic-gate 713*0Sstevel@tonic-gate if (ops->version != ZULUVM_INTERFACE_VERSION) 714*0Sstevel@tonic-gate return (ZULUVM_VERSION_MISMATCH); 715*0Sstevel@tonic-gate 716*0Sstevel@tonic-gate zuluvm_dops = ops; 717*0Sstevel@tonic-gate for (i = 0; i < ZULUM_MAX_PG_SIZES && size <= ZULU_TTE4M; i++) { 718*0Sstevel@tonic-gate zuluvm_pagesizes[i] = size++; 719*0Sstevel@tonic-gate } 720*0Sstevel@tonic-gate zuluvm_pagesizes[i] = -1; 721*0Sstevel@tonic-gate *pagesizes = zuluvm_pagesizes; 722*0Sstevel@tonic-gate 723*0Sstevel@tonic-gate return (error); 724*0Sstevel@tonic-gate } 725*0Sstevel@tonic-gate 726*0Sstevel@tonic-gate /* 727*0Sstevel@tonic-gate * cleanup afterwards 728*0Sstevel@tonic-gate */ 729*0Sstevel@tonic-gate int 730*0Sstevel@tonic-gate zuluvm_fini(void) 731*0Sstevel@tonic-gate { 732*0Sstevel@tonic-gate zuluvm_dops = NULL; 733*0Sstevel@tonic-gate return (ZULUVM_SUCCESS); 734*0Sstevel@tonic-gate } 735*0Sstevel@tonic-gate 736*0Sstevel@tonic-gate /* 737*0Sstevel@tonic-gate * allocate a zulu kernel driver instance for this zulu device 738*0Sstevel@tonic-gate */ 739*0Sstevel@tonic-gate int 740*0Sstevel@tonic-gate zuluvm_alloc_device(dev_info_t *devi, void *arg, zuluvm_info_t *devp, 741*0Sstevel@tonic-gate caddr_t mmu, caddr_t imr) 742*0Sstevel@tonic-gate { 743*0Sstevel@tonic-gate uint_t intr_num; 744*0Sstevel@tonic-gate zuluvm_state_t *zdev; 745*0Sstevel@tonic-gate int error = ZULUVM_SUCCESS; 746*0Sstevel@tonic-gate 747*0Sstevel@tonic-gate TNF_PROBE_3(zuluvm_alloc_device, "zuluvm", /* */, 748*0Sstevel@tonic-gate tnf_opaque, arg, arg, 749*0Sstevel@tonic-gate tnf_opaque, mmu, mmu, 750*0Sstevel@tonic-gate tnf_opaque, imr, imr); 751*0Sstevel@tonic-gate 752*0Sstevel@tonic-gate zdev = kmem_zalloc(sizeof (zuluvm_state_t), KM_SLEEP); 753*0Sstevel@tonic-gate zdev->dip = devi; 754*0Sstevel@tonic-gate zdev->dops = zuluvm_dops; 755*0Sstevel@tonic-gate error = zuluvm_driver_attach(zdev); 756*0Sstevel@tonic-gate if (error != ZULUVM_SUCCESS) { 757*0Sstevel@tonic-gate kmem_free(zdev, sizeof (zuluvm_state_t)); 758*0Sstevel@tonic-gate return (ZULUVM_NO_DEV); 759*0Sstevel@tonic-gate } 760*0Sstevel@tonic-gate 761*0Sstevel@tonic-gate ZULUVM_LOCK; 762*0Sstevel@tonic-gate error = zuluvm_get_intr_props(zdev, devi); 763*0Sstevel@tonic-gate if (error != ZULUVM_SUCCESS) { 764*0Sstevel@tonic-gate ZULUVM_UNLOCK; 765*0Sstevel@tonic-gate error = zuluvm_driver_detach(zdev); 766*0Sstevel@tonic-gate if (error != ZULUVM_SUCCESS) 767*0Sstevel@tonic-gate return (error); 768*0Sstevel@tonic-gate kmem_free(zdev, sizeof (zuluvm_state_t)); 769*0Sstevel@tonic-gate return (ZULUVM_NO_DEV); 770*0Sstevel@tonic-gate } 771*0Sstevel@tonic-gate zdev->zvm.arg = arg; 772*0Sstevel@tonic-gate zdev->zvm.mmu_pa = (uint64_t)va_to_pa((void *)mmu); 773*0Sstevel@tonic-gate zdev->imr = (uint64_t *)imr; 774*0Sstevel@tonic-gate zdev->zvm.dmv_intr = dmv_add_softintr(zuluvm_dmv_tlbmiss_tl1, 775*0Sstevel@tonic-gate (void *)zdev); 776*0Sstevel@tonic-gate zulud_set_itlb_pc(zdev, arg, DMV_MAKE_DMV(zdev->zvm.dmv_intr, 777*0Sstevel@tonic-gate (void *)zdev)); 778*0Sstevel@tonic-gate zulud_set_dtlb_pc(zdev, arg, DMV_MAKE_DMV(zdev->zvm.dmv_intr, 779*0Sstevel@tonic-gate (void *)zdev)); 780*0Sstevel@tonic-gate intr_dist_add(zuluvm_retarget_intr, (void *)zdev); 781*0Sstevel@tonic-gate zuluvm_do_retarget(zdev); 782*0Sstevel@tonic-gate intr_num = add_softintr(ZULUVM_PIL, zuluvm_softintr, (caddr_t)zdev); 783*0Sstevel@tonic-gate zdev->zvm.intr_num = intr_num; 784*0Sstevel@tonic-gate *devp = (caddr_t)zdev; 785*0Sstevel@tonic-gate ZULUVM_UNLOCK; 786*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_alloc_device_done, "zuluvm", /* */, 787*0Sstevel@tonic-gate tnf_opaque, devp, *devp); 788*0Sstevel@tonic-gate return (ZULUVM_SUCCESS); 789*0Sstevel@tonic-gate } 790*0Sstevel@tonic-gate 791*0Sstevel@tonic-gate /* 792*0Sstevel@tonic-gate * free a zulu kernel driver instance 793*0Sstevel@tonic-gate */ 794*0Sstevel@tonic-gate int 795*0Sstevel@tonic-gate zuluvm_free_device(zuluvm_info_t devp) 796*0Sstevel@tonic-gate { 797*0Sstevel@tonic-gate int error; 798*0Sstevel@tonic-gate zuluvm_state_t *zdev = (zuluvm_state_t *)devp; 799*0Sstevel@tonic-gate 800*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_free_device, "zuluvm", /* */, 801*0Sstevel@tonic-gate tnf_opaque, zdev, zdev); 802*0Sstevel@tonic-gate 803*0Sstevel@tonic-gate if (zdev == NULL) 804*0Sstevel@tonic-gate return (ZULUVM_NO_DEV); 805*0Sstevel@tonic-gate ZULUVM_LOCK; 806*0Sstevel@tonic-gate if (zdev->zvm.arg == NULL) { 807*0Sstevel@tonic-gate ZULUVM_UNLOCK; 808*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_free_device_done, "zuluvm", /* */, 809*0Sstevel@tonic-gate tnf_int, error, ZULUVM_NO_DEV); 810*0Sstevel@tonic-gate return (ZULUVM_NO_DEV); 811*0Sstevel@tonic-gate } 812*0Sstevel@tonic-gate (void) dmv_rem_intr(zdev->zvm.dmv_intr); 813*0Sstevel@tonic-gate rem_softintr(zdev->zvm.intr_num); 814*0Sstevel@tonic-gate intr_dist_rem(zuluvm_retarget_intr, (void *)zdev); 815*0Sstevel@tonic-gate zdev->zvm.arg = NULL; 816*0Sstevel@tonic-gate ZULUVM_UNLOCK; 817*0Sstevel@tonic-gate error = zuluvm_driver_detach(zdev); 818*0Sstevel@tonic-gate if (error != ZULUVM_SUCCESS) 819*0Sstevel@tonic-gate return (error); 820*0Sstevel@tonic-gate zdev->dops = NULL; 821*0Sstevel@tonic-gate kmem_free(zdev, sizeof (zuluvm_state_t)); 822*0Sstevel@tonic-gate 823*0Sstevel@tonic-gate TNF_PROBE_0(zuluvm_free_device_done, "zuluvm", /* */); 824*0Sstevel@tonic-gate return (ZULUVM_SUCCESS); 825*0Sstevel@tonic-gate } 826*0Sstevel@tonic-gate 827*0Sstevel@tonic-gate /* 828*0Sstevel@tonic-gate * find the as in the list of active zulu processes 829*0Sstevel@tonic-gate * The caller has to hold zdev->proc_lck 830*0Sstevel@tonic-gate */ 831*0Sstevel@tonic-gate static zuluvm_proc_t * 832*0Sstevel@tonic-gate zuluvm_find_proc(zuluvm_state_t *zdev, struct as *asp) 833*0Sstevel@tonic-gate { 834*0Sstevel@tonic-gate zuluvm_proc_t *p; 835*0Sstevel@tonic-gate TNF_PROBE_2(zuluvm_find_proc, "zuluvm", /* */, 836*0Sstevel@tonic-gate tnf_opaque, zdev, zdev, 837*0Sstevel@tonic-gate tnf_opaque, asp, asp); 838*0Sstevel@tonic-gate for (p = zdev->procs; p != NULL; p = p->next) { 839*0Sstevel@tonic-gate if (ZULU_HAT2AS(p->zhat) == asp) { 840*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_find_proc_done, 841*0Sstevel@tonic-gate "zuluvm", /* */, tnf_opaque, proc, p); 842*0Sstevel@tonic-gate return (p); 843*0Sstevel@tonic-gate } 844*0Sstevel@tonic-gate } 845*0Sstevel@tonic-gate TNF_PROBE_0(zuluvm_find_proc_fail, "zuluvm", /* */); 846*0Sstevel@tonic-gate return (NULL); 847*0Sstevel@tonic-gate } 848*0Sstevel@tonic-gate 849*0Sstevel@tonic-gate void 850*0Sstevel@tonic-gate zuluvm_as_free(struct as *as, void *arg, uint_t events) 851*0Sstevel@tonic-gate { 852*0Sstevel@tonic-gate zuluvm_proc_t *proc = (zuluvm_proc_t *)arg; 853*0Sstevel@tonic-gate zuluvm_state_t *zdev = proc->zdev; 854*0Sstevel@tonic-gate int wait = 0; 855*0Sstevel@tonic-gate int flag = 0; 856*0Sstevel@tonic-gate int valid; 857*0Sstevel@tonic-gate 858*0Sstevel@tonic-gate (void) events; 859*0Sstevel@tonic-gate 860*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_as_free, "zuluvm", /* */, 861*0Sstevel@tonic-gate tnf_opaque, arg, arg); 862*0Sstevel@tonic-gate 863*0Sstevel@tonic-gate (void) as_delete_callback(as, arg); 864*0Sstevel@tonic-gate /* 865*0Sstevel@tonic-gate * if this entry is still valid, then we need to sync 866*0Sstevel@tonic-gate * with zuluvm_tlb_handler rountine. 867*0Sstevel@tonic-gate */ 868*0Sstevel@tonic-gate mutex_enter(&zdev->proc_lck); 869*0Sstevel@tonic-gate valid = proc->valid; 870*0Sstevel@tonic-gate proc->valid = 0; 871*0Sstevel@tonic-gate mutex_exit(&zdev->proc_lck); 872*0Sstevel@tonic-gate 873*0Sstevel@tonic-gate if (valid) { 874*0Sstevel@tonic-gate ZULUVM_LOCK; 875*0Sstevel@tonic-gate if (proc == zdev->zvm.proc1) { 876*0Sstevel@tonic-gate flag |= ZULUVM_WAIT_INTR1; 877*0Sstevel@tonic-gate wait |= ZULUVM_DO_INTR1; 878*0Sstevel@tonic-gate } 879*0Sstevel@tonic-gate if (proc == zdev->zvm.proc2) { 880*0Sstevel@tonic-gate flag |= ZULUVM_WAIT_INTR2; 881*0Sstevel@tonic-gate wait |= ZULUVM_DO_INTR2; 882*0Sstevel@tonic-gate } 883*0Sstevel@tonic-gate if (flag) { 884*0Sstevel@tonic-gate zdev->intr_flags |= flag; 885*0Sstevel@tonic-gate /* 886*0Sstevel@tonic-gate * wait until the tlb miss is resloved 887*0Sstevel@tonic-gate */ 888*0Sstevel@tonic-gate while (zdev->intr_flags & wait) { 889*0Sstevel@tonic-gate cv_wait(&zdev->intr_wait, &zdev->dev_lck); 890*0Sstevel@tonic-gate } 891*0Sstevel@tonic-gate zdev->intr_flags &= ~flag; 892*0Sstevel@tonic-gate } 893*0Sstevel@tonic-gate ZULUVM_UNLOCK; 894*0Sstevel@tonic-gate } 895*0Sstevel@tonic-gate 896*0Sstevel@tonic-gate if (proc->zhat != NULL) { 897*0Sstevel@tonic-gate /* 898*0Sstevel@tonic-gate * prevent any further tlb miss processing for this hat 899*0Sstevel@tonic-gate */ 900*0Sstevel@tonic-gate zulu_hat_terminate(proc->zhat); 901*0Sstevel@tonic-gate } 902*0Sstevel@tonic-gate 903*0Sstevel@tonic-gate /* 904*0Sstevel@tonic-gate * decrement the ref count and do the appropriate 905*0Sstevel@tonic-gate * if it drops to zero. 906*0Sstevel@tonic-gate */ 907*0Sstevel@tonic-gate mutex_enter(&zdev->proc_lck); 908*0Sstevel@tonic-gate (void) zuluvm_proc_release(zdev, proc); 909*0Sstevel@tonic-gate mutex_exit(&zdev->proc_lck); 910*0Sstevel@tonic-gate } 911*0Sstevel@tonic-gate 912*0Sstevel@tonic-gate /* 913*0Sstevel@tonic-gate * notify zulu vm driver about a new process going to 914*0Sstevel@tonic-gate * use zulu DMA. Create a zulu_hat. 915*0Sstevel@tonic-gate */ 916*0Sstevel@tonic-gate int 917*0Sstevel@tonic-gate zuluvm_dma_add_proc(zuluvm_info_t devp, uint64_t *cookie) 918*0Sstevel@tonic-gate { 919*0Sstevel@tonic-gate zuluvm_proc_t *proc; 920*0Sstevel@tonic-gate int refcnt; 921*0Sstevel@tonic-gate struct as *asp = ZULUVM_GET_AS; 922*0Sstevel@tonic-gate zuluvm_state_t *zdev = (zuluvm_state_t *)devp; 923*0Sstevel@tonic-gate 924*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_dma_add_proc, "zuluvm", /* */, 925*0Sstevel@tonic-gate tnf_opaque, zdev, zdev); 926*0Sstevel@tonic-gate mutex_enter(&zdev->proc_lck); 927*0Sstevel@tonic-gate proc = zuluvm_find_proc(zdev, asp); 928*0Sstevel@tonic-gate if (proc == NULL) { 929*0Sstevel@tonic-gate proc = kmem_zalloc(sizeof (zuluvm_proc_t), KM_SLEEP); 930*0Sstevel@tonic-gate proc->zhat = zulu_hat_proc_attach(asp, zdev); 931*0Sstevel@tonic-gate if (proc->zhat == NULL) { 932*0Sstevel@tonic-gate mutex_exit(&zdev->proc_lck); 933*0Sstevel@tonic-gate kmem_free(proc, sizeof (zuluvm_proc_t)); 934*0Sstevel@tonic-gate TNF_PROBE_2(zuluvm_dma_add_proc_done, "zuluvm", /* */, 935*0Sstevel@tonic-gate tnf_int, valid, 0, 936*0Sstevel@tonic-gate tnf_int, error, ZULUVM_ERROR); 937*0Sstevel@tonic-gate return (ZULUVM_ERROR); 938*0Sstevel@tonic-gate } 939*0Sstevel@tonic-gate proc->zdev = zdev; 940*0Sstevel@tonic-gate proc->valid = 1; 941*0Sstevel@tonic-gate proc->refcnt = 1; 942*0Sstevel@tonic-gate proc->next = zdev->procs; 943*0Sstevel@tonic-gate if (zdev->procs) 944*0Sstevel@tonic-gate zdev->procs->prev = proc; 945*0Sstevel@tonic-gate proc->prev = NULL; 946*0Sstevel@tonic-gate zdev->procs = proc; 947*0Sstevel@tonic-gate proc->refcnt++; 948*0Sstevel@tonic-gate (void) as_add_callback(asp, zuluvm_as_free, proc, 949*0Sstevel@tonic-gate AS_FREE_EVENT, 0, -1, KM_SLEEP); 950*0Sstevel@tonic-gate } else { 951*0Sstevel@tonic-gate if (proc->valid == 0) { 952*0Sstevel@tonic-gate mutex_exit(&zdev->proc_lck); 953*0Sstevel@tonic-gate TNF_PROBE_2(zuluvm_dma_add_proc_done, "zuluvm", /* */, 954*0Sstevel@tonic-gate tnf_int, valid, 0, 955*0Sstevel@tonic-gate tnf_int, error, ZULUVM_ERROR); 956*0Sstevel@tonic-gate return (ZULUVM_ERROR); 957*0Sstevel@tonic-gate } 958*0Sstevel@tonic-gate proc->refcnt++; 959*0Sstevel@tonic-gate } 960*0Sstevel@tonic-gate refcnt = proc->refcnt; 961*0Sstevel@tonic-gate mutex_exit(&zdev->proc_lck); 962*0Sstevel@tonic-gate *cookie = (uint64_t)proc; 963*0Sstevel@tonic-gate TNF_PROBE_2(zuluvm_dma_add_proc_done, "zuluvm", /* */, 964*0Sstevel@tonic-gate tnf_int, refcnt, refcnt, 965*0Sstevel@tonic-gate tnf_int, error, ZULUVM_SUCCESS); 966*0Sstevel@tonic-gate return (ZULUVM_SUCCESS); 967*0Sstevel@tonic-gate } 968*0Sstevel@tonic-gate 969*0Sstevel@tonic-gate void 970*0Sstevel@tonic-gate zuluvm_proc_hold(zuluvm_state_t *zdev, zuluvm_proc_t *proc) 971*0Sstevel@tonic-gate { 972*0Sstevel@tonic-gate mutex_enter(&zdev->proc_lck); 973*0Sstevel@tonic-gate proc->refcnt++; 974*0Sstevel@tonic-gate mutex_exit(&zdev->proc_lck); 975*0Sstevel@tonic-gate } 976*0Sstevel@tonic-gate 977*0Sstevel@tonic-gate /* 978*0Sstevel@tonic-gate * decrement ref count and free data if it drops to zero 979*0Sstevel@tonic-gate */ 980*0Sstevel@tonic-gate static int 981*0Sstevel@tonic-gate zuluvm_proc_release(zuluvm_state_t *zdev, zuluvm_proc_t *proc) 982*0Sstevel@tonic-gate { 983*0Sstevel@tonic-gate int refcnt; 984*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&zdev->proc_lck)); 985*0Sstevel@tonic-gate refcnt = --proc->refcnt; 986*0Sstevel@tonic-gate TNF_PROBE_3(zuluvm_proc_release, "zuluvm", /* */, 987*0Sstevel@tonic-gate tnf_opaque, zdev, zdev, 988*0Sstevel@tonic-gate tnf_opaque, proc, proc, 989*0Sstevel@tonic-gate tnf_int, refcnt, refcnt); 990*0Sstevel@tonic-gate if (refcnt == 0) { 991*0Sstevel@tonic-gate if (proc->next) 992*0Sstevel@tonic-gate proc->next->prev = proc->prev; 993*0Sstevel@tonic-gate if (proc->prev) 994*0Sstevel@tonic-gate proc->prev->next = proc->next; 995*0Sstevel@tonic-gate else 996*0Sstevel@tonic-gate zdev->procs = proc->next; 997*0Sstevel@tonic-gate kmem_free(proc, sizeof (zuluvm_proc_t)); 998*0Sstevel@tonic-gate } 999*0Sstevel@tonic-gate return (refcnt); 1000*0Sstevel@tonic-gate } 1001*0Sstevel@tonic-gate 1002*0Sstevel@tonic-gate /* 1003*0Sstevel@tonic-gate * this process is not longer using DMA, all entries 1004*0Sstevel@tonic-gate * have been removed from the TLB. 1005*0Sstevel@tonic-gate */ 1006*0Sstevel@tonic-gate int 1007*0Sstevel@tonic-gate zuluvm_dma_delete_proc(zuluvm_info_t devp, uint64_t cookie) 1008*0Sstevel@tonic-gate { 1009*0Sstevel@tonic-gate int refcnt; 1010*0Sstevel@tonic-gate zuluvm_proc_t *proc = (zuluvm_proc_t *)cookie; 1011*0Sstevel@tonic-gate zuluvm_state_t *zdev = (zuluvm_state_t *)devp; 1012*0Sstevel@tonic-gate 1013*0Sstevel@tonic-gate TNF_PROBE_2(zuluvm_dma_delete_proc, "zuluvm", /* */, 1014*0Sstevel@tonic-gate tnf_opaque, zdev, zdev, 1015*0Sstevel@tonic-gate tnf_opaque, cookie, cookie); 1016*0Sstevel@tonic-gate mutex_enter(&zdev->proc_lck); 1017*0Sstevel@tonic-gate if (proc != NULL) { 1018*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_dma_delete_proc, "zuluvm", /* */, 1019*0Sstevel@tonic-gate tnf_opaque, proc, proc); 1020*0Sstevel@tonic-gate if (proc->zhat != NULL) { 1021*0Sstevel@tonic-gate zulu_hat_proc_detach(proc->zhat); 1022*0Sstevel@tonic-gate proc->zhat = NULL; 1023*0Sstevel@tonic-gate } 1024*0Sstevel@tonic-gate refcnt = zuluvm_proc_release(zdev, proc); 1025*0Sstevel@tonic-gate } 1026*0Sstevel@tonic-gate mutex_exit(&zdev->proc_lck); 1027*0Sstevel@tonic-gate 1028*0Sstevel@tonic-gate TNF_PROBE_2(zuluvm_dma_delete_proc_done, "zuluvm", /* */, 1029*0Sstevel@tonic-gate tnf_int, refcnt, refcnt, 1030*0Sstevel@tonic-gate tnf_int, error, ZULUVM_SUCCESS); 1031*0Sstevel@tonic-gate return (ZULUVM_SUCCESS); 1032*0Sstevel@tonic-gate } 1033*0Sstevel@tonic-gate 1034*0Sstevel@tonic-gate /* 1035*0Sstevel@tonic-gate * barrier sync for device driver 1036*0Sstevel@tonic-gate * blocks until zuluvm_tlbmiss_tl1 function is done 1037*0Sstevel@tonic-gate */ 1038*0Sstevel@tonic-gate void 1039*0Sstevel@tonic-gate zuluvm_fast_tlb_wait(caddr_t devp) 1040*0Sstevel@tonic-gate { 1041*0Sstevel@tonic-gate int state; 1042*0Sstevel@tonic-gate zuluvm_state_t *zdev = (zuluvm_state_t *)devp; 1043*0Sstevel@tonic-gate int cnt = 0; 1044*0Sstevel@tonic-gate 1045*0Sstevel@tonic-gate do { 1046*0Sstevel@tonic-gate state = ZULUVM_GET_STATE(zdev); 1047*0Sstevel@tonic-gate cnt++; 1048*0Sstevel@tonic-gate } while (state == ZULUVM_STATE_TLB_PENDING); 1049*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_fast_tlb_wait, "zuluvm", /* */, 1050*0Sstevel@tonic-gate tnf_int, loop_cnt, cnt); 1051*0Sstevel@tonic-gate } 1052*0Sstevel@tonic-gate 1053*0Sstevel@tonic-gate /* 1054*0Sstevel@tonic-gate * setup DMA handling for this handle 1055*0Sstevel@tonic-gate */ 1056*0Sstevel@tonic-gate int 1057*0Sstevel@tonic-gate zuluvm_dma_alloc_ctx(zuluvm_info_t devp, int dma, short *mmuctx, 1058*0Sstevel@tonic-gate uint64_t *tsbreg) 1059*0Sstevel@tonic-gate { 1060*0Sstevel@tonic-gate struct as *asp = ZULUVM_GET_AS; 1061*0Sstevel@tonic-gate int error = ZULUVM_NO_DEV; 1062*0Sstevel@tonic-gate zuluvm_state_t *zdev = (zuluvm_state_t *)devp; 1063*0Sstevel@tonic-gate int state, newstate; 1064*0Sstevel@tonic-gate 1065*0Sstevel@tonic-gate if (asp == NULL) { 1066*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_dma_alloc_ctx_done, "zuluvm", /* */, 1067*0Sstevel@tonic-gate tnf_int, error, ZULUVM_NO_HAT); 1068*0Sstevel@tonic-gate return (ZULUVM_NO_HAT); 1069*0Sstevel@tonic-gate } 1070*0Sstevel@tonic-gate 1071*0Sstevel@tonic-gate *tsbreg = 0; 1072*0Sstevel@tonic-gate state = ZULUVM_SET_STATE(zdev, ZULUVM_STATE_IDLE, 1073*0Sstevel@tonic-gate ZULUVM_STATE_STOPPED); 1074*0Sstevel@tonic-gate newstate = ZULUVM_GET_STATE(zdev); 1075*0Sstevel@tonic-gate TNF_PROBE_4(zuluvm_dma_alloc_ctx, "zuluvm", /* */, 1076*0Sstevel@tonic-gate tnf_opaque, devp, devp, 1077*0Sstevel@tonic-gate tnf_int, dma, dma, 1078*0Sstevel@tonic-gate tnf_int, oldstate, state, 1079*0Sstevel@tonic-gate tnf_int, newstate, newstate); 1080*0Sstevel@tonic-gate #ifdef DEBUG 1081*0Sstevel@tonic-gate if (zuluvm_debug_state) 1082*0Sstevel@tonic-gate cmn_err(CE_NOTE, "zuluvm_dma_alloc_ctx: state %d\n", state); 1083*0Sstevel@tonic-gate #endif 1084*0Sstevel@tonic-gate if (state != ZULUVM_STATE_STOPPED && state != ZULUVM_STATE_IDLE) { 1085*0Sstevel@tonic-gate while (state != ZULUVM_STATE_IDLE) { 1086*0Sstevel@tonic-gate state = ZULUVM_SET_STATE(zdev, ZULUVM_STATE_IDLE, 1087*0Sstevel@tonic-gate ZULUVM_STATE_STOPPED); 1088*0Sstevel@tonic-gate #ifdef DEBUG 1089*0Sstevel@tonic-gate if (zuluvm_debug_state) 1090*0Sstevel@tonic-gate cmn_err(CE_NOTE, "zuluvm_dma_alloc_ctx: (loop)" 1091*0Sstevel@tonic-gate " state %d\n", state); 1092*0Sstevel@tonic-gate #endif 1093*0Sstevel@tonic-gate if (state != ZULUVM_STATE_IDLE) 1094*0Sstevel@tonic-gate delay(1); 1095*0Sstevel@tonic-gate } 1096*0Sstevel@tonic-gate } 1097*0Sstevel@tonic-gate 1098*0Sstevel@tonic-gate if (zdev->zvm.arg != NULL) { 1099*0Sstevel@tonic-gate struct zulu_hat *zhat; 1100*0Sstevel@tonic-gate zuluvm_proc_t *proc; 1101*0Sstevel@tonic-gate 1102*0Sstevel@tonic-gate mutex_enter(&zdev->proc_lck); 1103*0Sstevel@tonic-gate proc = zuluvm_find_proc(zdev, asp); 1104*0Sstevel@tonic-gate if (proc != NULL) { 1105*0Sstevel@tonic-gate zhat = proc->zhat; 1106*0Sstevel@tonic-gate proc->refcnt++; 1107*0Sstevel@tonic-gate } 1108*0Sstevel@tonic-gate mutex_exit(&zdev->proc_lck); 1109*0Sstevel@tonic-gate 1110*0Sstevel@tonic-gate switch (dma) { 1111*0Sstevel@tonic-gate case ZULUVM_DMA1: 1112*0Sstevel@tonic-gate ZULUVM_LOCK; 1113*0Sstevel@tonic-gate zdev->zvm.proc1 = proc; 1114*0Sstevel@tonic-gate ZULUVM_UNLOCK; 1115*0Sstevel@tonic-gate error = ZULUVM_SUCCESS; 1116*0Sstevel@tonic-gate break; 1117*0Sstevel@tonic-gate case ZULUVM_DMA2: 1118*0Sstevel@tonic-gate ZULUVM_LOCK; 1119*0Sstevel@tonic-gate zdev->zvm.proc2 = proc; 1120*0Sstevel@tonic-gate ZULUVM_UNLOCK; 1121*0Sstevel@tonic-gate error = ZULUVM_SUCCESS; 1122*0Sstevel@tonic-gate break; 1123*0Sstevel@tonic-gate default: 1124*0Sstevel@tonic-gate mutex_enter(&zdev->proc_lck); 1125*0Sstevel@tonic-gate (void) zuluvm_proc_release(zdev, proc); 1126*0Sstevel@tonic-gate mutex_exit(&zdev->proc_lck); 1127*0Sstevel@tonic-gate } 1128*0Sstevel@tonic-gate 1129*0Sstevel@tonic-gate if (error == ZULUVM_SUCCESS) { 1130*0Sstevel@tonic-gate zulu_hat_validate_ctx(zhat); 1131*0Sstevel@tonic-gate if (zhat->zulu_ctx >= 0) { 1132*0Sstevel@tonic-gate *mmuctx = zhat->zulu_ctx; 1133*0Sstevel@tonic-gate } else { 1134*0Sstevel@tonic-gate printf("invalid context value: %d\n", 1135*0Sstevel@tonic-gate zhat->zulu_ctx); 1136*0Sstevel@tonic-gate 1137*0Sstevel@tonic-gate mutex_enter(&zdev->proc_lck); 1138*0Sstevel@tonic-gate (void) zuluvm_proc_release(zdev, proc); 1139*0Sstevel@tonic-gate mutex_exit(&zdev->proc_lck); 1140*0Sstevel@tonic-gate 1141*0Sstevel@tonic-gate error = ZULUVM_ERROR; 1142*0Sstevel@tonic-gate } 1143*0Sstevel@tonic-gate } else { 1144*0Sstevel@tonic-gate error = ZULUVM_ERROR; 1145*0Sstevel@tonic-gate } 1146*0Sstevel@tonic-gate } 1147*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_dma_alloc_ctx_done, "zuluvm", /* */, 1148*0Sstevel@tonic-gate tnf_int, error, error); 1149*0Sstevel@tonic-gate return (error); 1150*0Sstevel@tonic-gate } 1151*0Sstevel@tonic-gate 1152*0Sstevel@tonic-gate /* 1153*0Sstevel@tonic-gate * preload TLB 1154*0Sstevel@tonic-gate * this will try to pre-set the zulu tlb, mainly used for dma engine 2, 1155*0Sstevel@tonic-gate * video read-back. 1156*0Sstevel@tonic-gate */ 1157*0Sstevel@tonic-gate int 1158*0Sstevel@tonic-gate zuluvm_dma_preload(zuluvm_info_t devp, int dma, 1159*0Sstevel@tonic-gate int num, zulud_preload_t *list) 1160*0Sstevel@tonic-gate { 1161*0Sstevel@tonic-gate int i; 1162*0Sstevel@tonic-gate int error = ZULUVM_SUCCESS; 1163*0Sstevel@tonic-gate struct zulu_hat *zhat; 1164*0Sstevel@tonic-gate zuluvm_proc_t *proc = NULL; 1165*0Sstevel@tonic-gate 1166*0Sstevel@tonic-gate zuluvm_state_t *zdev = (zuluvm_state_t *)devp; 1167*0Sstevel@tonic-gate 1168*0Sstevel@tonic-gate TNF_PROBE_4(zuluvm_dma_preload, "zuluvm", /* */, 1169*0Sstevel@tonic-gate tnf_opaque, devp, devp, 1170*0Sstevel@tonic-gate tnf_int, dma, dma, 1171*0Sstevel@tonic-gate tnf_int, num, num, 1172*0Sstevel@tonic-gate tnf_opaque, list, list); 1173*0Sstevel@tonic-gate ZULUVM_LOCK; 1174*0Sstevel@tonic-gate switch (dma) { 1175*0Sstevel@tonic-gate case ZULUVM_DMA1: 1176*0Sstevel@tonic-gate proc = zdev->zvm.proc1; 1177*0Sstevel@tonic-gate break; 1178*0Sstevel@tonic-gate case ZULUVM_DMA2: 1179*0Sstevel@tonic-gate proc = zdev->zvm.proc2; 1180*0Sstevel@tonic-gate break; 1181*0Sstevel@tonic-gate } 1182*0Sstevel@tonic-gate 1183*0Sstevel@tonic-gate mutex_enter(&zdev->proc_lck); 1184*0Sstevel@tonic-gate if (proc == NULL || proc->valid == 0 || proc->zhat == NULL) { 1185*0Sstevel@tonic-gate mutex_exit(&zdev->proc_lck); 1186*0Sstevel@tonic-gate ZULUVM_UNLOCK; 1187*0Sstevel@tonic-gate return (ZULUVM_NO_HAT); 1188*0Sstevel@tonic-gate } 1189*0Sstevel@tonic-gate mutex_exit(&zdev->proc_lck); 1190*0Sstevel@tonic-gate 1191*0Sstevel@tonic-gate zhat = proc->zhat; 1192*0Sstevel@tonic-gate /* 1193*0Sstevel@tonic-gate * need to release this to avoid recursive enter in zuluvm_load_tte 1194*0Sstevel@tonic-gate * which gets called from zulu_hat_memload() 1195*0Sstevel@tonic-gate */ 1196*0Sstevel@tonic-gate ZULUVM_UNLOCK; 1197*0Sstevel@tonic-gate 1198*0Sstevel@tonic-gate mutex_enter(&zdev->load_lck); 1199*0Sstevel@tonic-gate for (i = 0; i < num; i++) { 1200*0Sstevel@tonic-gate int pg_size; 1201*0Sstevel@tonic-gate int res; 1202*0Sstevel@tonic-gate int first = 1; 1203*0Sstevel@tonic-gate caddr_t addr = ZULUVM_GET_PAGE(list[i].addr); 1204*0Sstevel@tonic-gate int64_t size = (int64_t)list[i].len; 1205*0Sstevel@tonic-gate while (size > 0) { 1206*0Sstevel@tonic-gate if (list[i].tlbtype & ~ZULUVM_DMA_MASK) { 1207*0Sstevel@tonic-gate error = ZULUVM_INVALID_MISS; 1208*0Sstevel@tonic-gate break; 1209*0Sstevel@tonic-gate } 1210*0Sstevel@tonic-gate res = zulu_hat_load(zhat, addr, 1211*0Sstevel@tonic-gate (list[i].tlbtype == ZULUVM_DMA2) ? S_WRITE : S_READ, 1212*0Sstevel@tonic-gate &pg_size); 1213*0Sstevel@tonic-gate if ((res != 0) || (pg_size < 0)) { 1214*0Sstevel@tonic-gate error = ZULUVM_NO_MAP; 1215*0Sstevel@tonic-gate break; 1216*0Sstevel@tonic-gate } 1217*0Sstevel@tonic-gate ZULUVM_STATS_PRELOAD(zdev); 1218*0Sstevel@tonic-gate TNF_PROBE_2(zuluvm_dma_preload_addr, "zuluvm", /* */, 1219*0Sstevel@tonic-gate tnf_opaque, addr, addr, 1220*0Sstevel@tonic-gate tnf_opaque, size, size); 1221*0Sstevel@tonic-gate if (first) { 1222*0Sstevel@tonic-gate first = 0; 1223*0Sstevel@tonic-gate size -= ZULU_HAT_PGDIFF(list[i].addr, 1224*0Sstevel@tonic-gate pg_size); 1225*0Sstevel@tonic-gate } else { 1226*0Sstevel@tonic-gate size -= ZULU_HAT_PGSZ(pg_size); 1227*0Sstevel@tonic-gate } 1228*0Sstevel@tonic-gate addr += ZULU_HAT_PGSZ(pg_size); 1229*0Sstevel@tonic-gate } 1230*0Sstevel@tonic-gate } 1231*0Sstevel@tonic-gate mutex_exit(&zdev->load_lck); 1232*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_dma_preload_done, "zuluvm", /* */, 1233*0Sstevel@tonic-gate tnf_int, error, error); 1234*0Sstevel@tonic-gate return (ZULUVM_SUCCESS); 1235*0Sstevel@tonic-gate } 1236*0Sstevel@tonic-gate 1237*0Sstevel@tonic-gate /* 1238*0Sstevel@tonic-gate * destroy DMA handling for this handle 1239*0Sstevel@tonic-gate */ 1240*0Sstevel@tonic-gate int 1241*0Sstevel@tonic-gate zuluvm_dma_free_ctx(zuluvm_info_t devp, int dma) 1242*0Sstevel@tonic-gate { 1243*0Sstevel@tonic-gate int error = ZULUVM_NO_DEV; 1244*0Sstevel@tonic-gate zuluvm_state_t *zdev = (zuluvm_state_t *)devp; 1245*0Sstevel@tonic-gate int state, newstate; 1246*0Sstevel@tonic-gate 1247*0Sstevel@tonic-gate state = ZULUVM_SET_STATE(zdev, ZULUVM_STATE_STOPPED, 1248*0Sstevel@tonic-gate ZULUVM_STATE_IDLE); 1249*0Sstevel@tonic-gate newstate = ZULUVM_GET_STATE(zdev); 1250*0Sstevel@tonic-gate TNF_PROBE_4(zuluvm_dma_free_ctx, "zuluvm", /* */, 1251*0Sstevel@tonic-gate tnf_opaque, devp, devp, 1252*0Sstevel@tonic-gate tnf_int, dma, dma, 1253*0Sstevel@tonic-gate tnf_int, oldstate, state, 1254*0Sstevel@tonic-gate tnf_int, newstate, newstate); 1255*0Sstevel@tonic-gate #ifdef DEBUG 1256*0Sstevel@tonic-gate if (zuluvm_debug_state) 1257*0Sstevel@tonic-gate cmn_err(CE_NOTE, "zuluvm_dma_free_ctx: state %d\n", state); 1258*0Sstevel@tonic-gate #endif 1259*0Sstevel@tonic-gate if (state != ZULUVM_STATE_IDLE && state != ZULUVM_STATE_STOPPED) { 1260*0Sstevel@tonic-gate int doit = 1; 1261*0Sstevel@tonic-gate while (doit) { 1262*0Sstevel@tonic-gate switch (state) { 1263*0Sstevel@tonic-gate case ZULUVM_STATE_CANCELED: 1264*0Sstevel@tonic-gate case ZULUVM_STATE_STOPPED: 1265*0Sstevel@tonic-gate doit = 0; 1266*0Sstevel@tonic-gate break; 1267*0Sstevel@tonic-gate case ZULUVM_STATE_IDLE: 1268*0Sstevel@tonic-gate state = ZULUVM_SET_STATE(zdev, 1269*0Sstevel@tonic-gate ZULUVM_STATE_STOPPED, 1270*0Sstevel@tonic-gate ZULUVM_STATE_IDLE); 1271*0Sstevel@tonic-gate break; 1272*0Sstevel@tonic-gate default: 1273*0Sstevel@tonic-gate state = ZULUVM_SET_STATE(zdev, 1274*0Sstevel@tonic-gate ZULUVM_STATE_CANCELED, state); 1275*0Sstevel@tonic-gate } 1276*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_dma_free_ctx, "zuluvm", /* */, 1277*0Sstevel@tonic-gate tnf_int, state, state); 1278*0Sstevel@tonic-gate #ifdef DEBUG 1279*0Sstevel@tonic-gate if (zuluvm_debug_state) 1280*0Sstevel@tonic-gate cmn_err(CE_NOTE, "zuluvm_dma_free_ctx: (loop1)" 1281*0Sstevel@tonic-gate " state %d\n", state); 1282*0Sstevel@tonic-gate #endif 1283*0Sstevel@tonic-gate } 1284*0Sstevel@tonic-gate } 1285*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_dma_free_ctx, "zuluvm", /* */, 1286*0Sstevel@tonic-gate tnf_int, state, state); 1287*0Sstevel@tonic-gate 1288*0Sstevel@tonic-gate error = ZULUVM_SUCCESS; 1289*0Sstevel@tonic-gate while (state != ZULUVM_STATE_STOPPED) { 1290*0Sstevel@tonic-gate state = ZULUVM_GET_STATE(zdev); 1291*0Sstevel@tonic-gate #ifdef DEBUG 1292*0Sstevel@tonic-gate if (zuluvm_debug_state) 1293*0Sstevel@tonic-gate cmn_err(CE_NOTE, "zuluvm_dma_free: (loop2) state %d\n", 1294*0Sstevel@tonic-gate state); 1295*0Sstevel@tonic-gate #endif 1296*0Sstevel@tonic-gate if (state != ZULUVM_STATE_STOPPED) 1297*0Sstevel@tonic-gate delay(1); 1298*0Sstevel@tonic-gate } 1299*0Sstevel@tonic-gate ZULUVM_LOCK; 1300*0Sstevel@tonic-gate if (zdev->zvm.arg != NULL) { 1301*0Sstevel@tonic-gate zuluvm_proc_t *proc = NULL; 1302*0Sstevel@tonic-gate switch (dma) { 1303*0Sstevel@tonic-gate case ZULUVM_DMA1: 1304*0Sstevel@tonic-gate proc = zdev->zvm.proc1; 1305*0Sstevel@tonic-gate zdev->zvm.proc1 = NULL; 1306*0Sstevel@tonic-gate break; 1307*0Sstevel@tonic-gate case ZULUVM_DMA2: 1308*0Sstevel@tonic-gate proc = zdev->zvm.proc2; 1309*0Sstevel@tonic-gate zdev->zvm.proc2 = NULL; 1310*0Sstevel@tonic-gate break; 1311*0Sstevel@tonic-gate default: 1312*0Sstevel@tonic-gate error = ZULUVM_NO_DEV; 1313*0Sstevel@tonic-gate } 1314*0Sstevel@tonic-gate ZULUVM_UNLOCK; 1315*0Sstevel@tonic-gate if (proc) { 1316*0Sstevel@tonic-gate mutex_enter(&zdev->proc_lck); 1317*0Sstevel@tonic-gate (void) zuluvm_proc_release(zdev, proc); 1318*0Sstevel@tonic-gate mutex_exit(&zdev->proc_lck); 1319*0Sstevel@tonic-gate } 1320*0Sstevel@tonic-gate } else { 1321*0Sstevel@tonic-gate ZULUVM_UNLOCK; 1322*0Sstevel@tonic-gate error = ZULUVM_NO_DEV; 1323*0Sstevel@tonic-gate } 1324*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_dma_free_ctx_done, "zuluvm", /* */, 1325*0Sstevel@tonic-gate tnf_int, error, error); 1326*0Sstevel@tonic-gate return (error); 1327*0Sstevel@tonic-gate } 1328*0Sstevel@tonic-gate 1329*0Sstevel@tonic-gate static void 1330*0Sstevel@tonic-gate zuluvm_do_retarget(zuluvm_state_t *zdev) 1331*0Sstevel@tonic-gate { 1332*0Sstevel@tonic-gate int i, idx; 1333*0Sstevel@tonic-gate uint_t cpu; 1334*0Sstevel@tonic-gate for (i = 0; i < ZULUVM_MAX_INTR; i++) { 1335*0Sstevel@tonic-gate if (zdev->interrupts[i].ino != -1) { 1336*0Sstevel@tonic-gate cpu = intr_dist_cpuid(); 1337*0Sstevel@tonic-gate idx = zdev->interrupts[i].offset; 1338*0Sstevel@tonic-gate if (zdev->imr[idx] & ZULUVM_IMR_V_MASK) 1339*0Sstevel@tonic-gate zdev->imr[idx] = ZULUVM_IMR_V_MASK | 1340*0Sstevel@tonic-gate (cpu<<ZULUVM_IMR_TARGET_SHIFT); 1341*0Sstevel@tonic-gate else 1342*0Sstevel@tonic-gate zdev->imr[idx] = 1343*0Sstevel@tonic-gate cpu<<ZULUVM_IMR_TARGET_SHIFT; 1344*0Sstevel@tonic-gate } 1345*0Sstevel@tonic-gate } 1346*0Sstevel@tonic-gate } 1347*0Sstevel@tonic-gate 1348*0Sstevel@tonic-gate static void 1349*0Sstevel@tonic-gate zuluvm_retarget_intr(void *arg) 1350*0Sstevel@tonic-gate { 1351*0Sstevel@tonic-gate zuluvm_state_t *zdev = (zuluvm_state_t *)arg; 1352*0Sstevel@tonic-gate ZULUVM_LOCK; 1353*0Sstevel@tonic-gate zuluvm_do_retarget(zdev); 1354*0Sstevel@tonic-gate ZULUVM_UNLOCK; 1355*0Sstevel@tonic-gate } 1356*0Sstevel@tonic-gate 1357*0Sstevel@tonic-gate int 1358*0Sstevel@tonic-gate zuluvm_add_intr(zuluvm_info_t devp, int ino, 1359*0Sstevel@tonic-gate uint_t (*handler)(caddr_t), caddr_t arg) 1360*0Sstevel@tonic-gate { 1361*0Sstevel@tonic-gate zuluvm_state_t *zdev = (zuluvm_state_t *)devp; 1362*0Sstevel@tonic-gate if (devp == NULL) { 1363*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_add_intr_done, "zuluvm", /* */, 1364*0Sstevel@tonic-gate tnf_int, error, ZULUVM_NO_DEV); 1365*0Sstevel@tonic-gate return (ZULUVM_NO_DEV); 1366*0Sstevel@tonic-gate } 1367*0Sstevel@tonic-gate if (ddi_add_intr(zdev->dip, ino, NULL, NULL, handler, arg) 1368*0Sstevel@tonic-gate != DDI_SUCCESS) { 1369*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_add_intr_done, "zuluvm", /* */, 1370*0Sstevel@tonic-gate tnf_int, error, ZULUVM_ERROR); 1371*0Sstevel@tonic-gate return (ZULUVM_ERROR); 1372*0Sstevel@tonic-gate } 1373*0Sstevel@tonic-gate return (ZULUVM_SUCCESS); 1374*0Sstevel@tonic-gate } 1375*0Sstevel@tonic-gate 1376*0Sstevel@tonic-gate int 1377*0Sstevel@tonic-gate zuluvm_rem_intr(zuluvm_info_t devp, int ino) 1378*0Sstevel@tonic-gate { 1379*0Sstevel@tonic-gate zuluvm_state_t *zdev = (zuluvm_state_t *)devp; 1380*0Sstevel@tonic-gate if (devp == NULL) { 1381*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_rem_intr_done, "zuluvm", /* */, 1382*0Sstevel@tonic-gate tnf_int, error, ZULUVM_NO_DEV); 1383*0Sstevel@tonic-gate return (ZULUVM_NO_DEV); 1384*0Sstevel@tonic-gate } 1385*0Sstevel@tonic-gate /* remove from distributin list */ 1386*0Sstevel@tonic-gate ZULUVM_LOCK; 1387*0Sstevel@tonic-gate zdev->imr[zdev->interrupts[ino].offset] &= ~ZULUVM_IMR_V_MASK; 1388*0Sstevel@tonic-gate ZULUVM_UNLOCK; 1389*0Sstevel@tonic-gate ddi_remove_intr(zdev->dip, ino, NULL); 1390*0Sstevel@tonic-gate return (ZULUVM_SUCCESS); 1391*0Sstevel@tonic-gate } 1392*0Sstevel@tonic-gate 1393*0Sstevel@tonic-gate int 1394*0Sstevel@tonic-gate zuluvm_enable_intr(zuluvm_info_t devp, int num) 1395*0Sstevel@tonic-gate { 1396*0Sstevel@tonic-gate zuluvm_state_t *zdev = (zuluvm_state_t *)devp; 1397*0Sstevel@tonic-gate 1398*0Sstevel@tonic-gate TNF_PROBE_2(zuluvm_enable_intr, "zuluvm_intr", /* */, 1399*0Sstevel@tonic-gate tnf_opaque, devp, devp, 1400*0Sstevel@tonic-gate tnf_int, num, num); 1401*0Sstevel@tonic-gate if (devp == NULL) { 1402*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_enable_intr_done, "zuluvm", /* */, 1403*0Sstevel@tonic-gate tnf_int, error, ZULUVM_NO_DEV); 1404*0Sstevel@tonic-gate return (ZULUVM_NO_DEV); 1405*0Sstevel@tonic-gate } 1406*0Sstevel@tonic-gate if (num < 0 || num > ZULUVM_IMR_MAX) { 1407*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_enable_intr_done, "zuluvm", /* */, 1408*0Sstevel@tonic-gate tnf_int, error, ZULUVM_BAD_IDX); 1409*0Sstevel@tonic-gate return (ZULUVM_BAD_IDX); 1410*0Sstevel@tonic-gate } 1411*0Sstevel@tonic-gate ZULUVM_LOCK; 1412*0Sstevel@tonic-gate zdev->imr[num] |= ZULUVM_IMR_V_MASK; 1413*0Sstevel@tonic-gate ZULUVM_UNLOCK; 1414*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_enable_intr_done, "zuluvm_intr", /* */, 1415*0Sstevel@tonic-gate tnf_int, error, ZULUVM_SUCCESS); 1416*0Sstevel@tonic-gate return (ZULUVM_SUCCESS); 1417*0Sstevel@tonic-gate } 1418*0Sstevel@tonic-gate 1419*0Sstevel@tonic-gate int 1420*0Sstevel@tonic-gate zuluvm_disable_intr(zuluvm_info_t devp, int num) 1421*0Sstevel@tonic-gate { 1422*0Sstevel@tonic-gate zuluvm_state_t *zdev = (zuluvm_state_t *)devp; 1423*0Sstevel@tonic-gate 1424*0Sstevel@tonic-gate TNF_PROBE_2(zuluvm_disable_intr, "zuluvm_intr", /* */, 1425*0Sstevel@tonic-gate tnf_opaque, devp, devp, 1426*0Sstevel@tonic-gate tnf_int, num, num); 1427*0Sstevel@tonic-gate if (devp == NULL) { 1428*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_disable_intr_done, "zuluvm", /* */, 1429*0Sstevel@tonic-gate tnf_int, error, ZULUVM_NO_DEV); 1430*0Sstevel@tonic-gate return (ZULUVM_NO_DEV); 1431*0Sstevel@tonic-gate } 1432*0Sstevel@tonic-gate if (num < 0 || num > ZULUVM_IMR_MAX) { 1433*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_disable_intr_done, "zuluvm", /* */, 1434*0Sstevel@tonic-gate tnf_int, error, ZULUVM_BAD_IDX); 1435*0Sstevel@tonic-gate return (ZULUVM_BAD_IDX); 1436*0Sstevel@tonic-gate } 1437*0Sstevel@tonic-gate ZULUVM_LOCK; 1438*0Sstevel@tonic-gate zdev->imr[num] &= ~ZULUVM_IMR_V_MASK; 1439*0Sstevel@tonic-gate ZULUVM_UNLOCK; 1440*0Sstevel@tonic-gate TNF_PROBE_1(zuluvm_disable_intr_done, "zuluvm_intr", /* */, 1441*0Sstevel@tonic-gate tnf_int, error, ZULUVM_SUCCESS); 1442*0Sstevel@tonic-gate return (ZULUVM_SUCCESS); 1443*0Sstevel@tonic-gate } 1444*0Sstevel@tonic-gate 1445*0Sstevel@tonic-gate static int 1446*0Sstevel@tonic-gate zuluvm_get_intr_props(zuluvm_state_t *zdev, 1447*0Sstevel@tonic-gate dev_info_t *devi) 1448*0Sstevel@tonic-gate { 1449*0Sstevel@tonic-gate int *intr; 1450*0Sstevel@tonic-gate int i; 1451*0Sstevel@tonic-gate uint_t nintr; 1452*0Sstevel@tonic-gate 1453*0Sstevel@tonic-gate zdev->agentid = ddi_getprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, 1454*0Sstevel@tonic-gate "portid", -1); 1455*0Sstevel@tonic-gate if (zdev->agentid == -1) { 1456*0Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: no portid property", 1457*0Sstevel@tonic-gate ddi_get_name(devi), 1458*0Sstevel@tonic-gate ddi_get_instance(devi)); 1459*0Sstevel@tonic-gate return (ZULUVM_ERROR); 1460*0Sstevel@tonic-gate } 1461*0Sstevel@tonic-gate 1462*0Sstevel@tonic-gate for (i = 0; i < ZULUVM_MAX_INTR; i++) { 1463*0Sstevel@tonic-gate zdev->interrupts[i].offset = 0; 1464*0Sstevel@tonic-gate zdev->interrupts[i].ino = -1; 1465*0Sstevel@tonic-gate } 1466*0Sstevel@tonic-gate 1467*0Sstevel@tonic-gate if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, 1468*0Sstevel@tonic-gate "interrupts", &intr, &nintr) == DDI_PROP_SUCCESS) { 1469*0Sstevel@tonic-gate 1470*0Sstevel@tonic-gate if (nintr == 0) { 1471*0Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: no interrupts in property", 1472*0Sstevel@tonic-gate ddi_get_name(devi), 1473*0Sstevel@tonic-gate ddi_get_instance(devi)); 1474*0Sstevel@tonic-gate ddi_prop_free(intr); 1475*0Sstevel@tonic-gate return (ZULUVM_ERROR); 1476*0Sstevel@tonic-gate } 1477*0Sstevel@tonic-gate if (nintr >= ZULUVM_MAX_INTR) { 1478*0Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: to many interrupts (%d)", 1479*0Sstevel@tonic-gate ddi_get_name(devi), 1480*0Sstevel@tonic-gate ddi_get_instance(devi), nintr); 1481*0Sstevel@tonic-gate ddi_prop_free(intr); 1482*0Sstevel@tonic-gate return (ZULUVM_ERROR); 1483*0Sstevel@tonic-gate } 1484*0Sstevel@tonic-gate for (i = 0; i < nintr; i++) { 1485*0Sstevel@tonic-gate zdev->interrupts[i].offset = intr[i]; 1486*0Sstevel@tonic-gate zdev->interrupts[i].ino = i; 1487*0Sstevel@tonic-gate } 1488*0Sstevel@tonic-gate ddi_prop_free(intr); 1489*0Sstevel@tonic-gate } else { 1490*0Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: no interrupts property", 1491*0Sstevel@tonic-gate ddi_get_name(devi), 1492*0Sstevel@tonic-gate ddi_get_instance(devi)); 1493*0Sstevel@tonic-gate } 1494*0Sstevel@tonic-gate return (ZULUVM_SUCCESS); 1495*0Sstevel@tonic-gate } 1496*0Sstevel@tonic-gate 1497*0Sstevel@tonic-gate /* *** enf of zulu *** */ 1498