Ejemplo n.º 1
0
paddr_t
sun68k_bus_mmap(bus_space_tag_t t, bus_type_t iospace, bus_addr_t paddr,
    off_t offset, int prot, int flags)
{
	paddr_t npaddr;

	npaddr = m68k_trunc_page(paddr + offset);
	return (npaddr | (paddr_t)iospace | PMAP_NC);
}
Ejemplo n.º 2
0
void
bus_tmapout(void *vp)
{
	vaddr_t pgva;

	pgva = m68k_trunc_page(vp);
	if (pgva != tmp_vpages[1])
		return;

	set_pte(pgva, PG_INVAL);
	--tmp_vpages_inuse;
}
Ejemplo n.º 3
0
void
bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
{
	vaddr_t kva;
	vsize_t offset;

	if (t->bustype == HP300_BUS_SPACE_INTIO) {
		/*
		 * Intio space is direct-mapped in pmap_bootstrap(); nothing
		 * to do
		 */
		return;
	}

	if (t->bustype != HP300_BUS_SPACE_DIO &&
	    t->bustype != HP300_BUS_SPACE_SGC)
		panic("%s: bad space tag", __func__);

	kva = m68k_trunc_page(bsh);
	offset = m68k_page_offset(bsh);
	size = m68k_round_page(offset + size);

#ifdef DIAGNOSTIC
	if (bsh < (vaddr_t)extiobase ||
	    bsh >= ((vaddr_t)extiobase + ptoa(EIOMAPSIZE)))
		panic("%s: bad bus space handle", __func__);
#endif

	/*
	 * Unmap the range.
	 */
	physunaccess((void *)kva, size);

	/*
	 * Free it from the extio extent map.
	 */
	if (extent_free(extio_ex, kva, size,
	    EX_NOWAIT | (extio_ex_malloc_safe ? EX_MALLOCOK : 0)))
		printf("%s: kva 0x%lx size 0x%lx: "
		    "can't free region\n", __func__, (u_long)bsh, size);
}
/*
 * Unmap a previously-mapped user I/O request.
 */
void
vunmapbuf(struct buf *bp, vsize_t len)
{
	vaddr_t kva;
	vsize_t off;

	if ((bp->b_flags & B_PHYS) == 0)
		panic("vunmapbuf");

	kva = m68k_trunc_page(bp->b_data);
	off = (vaddr_t)bp->b_data - kva;
	len = m68k_round_page(off + len);

#ifdef M68K_VAC
	pmap_remove(vm_map_pmap(phys_map), kva, kva + len);
#else
	pmap_kremove(kva, len);
#endif
	pmap_update(pmap_kernel());
	uvm_km_free(phys_map, kva, len, UVM_KMF_VAONLY);
	bp->b_data = bp->b_saveaddr;
	bp->b_saveaddr = 0;
}
/*
 * Map a user I/O request into kernel virtual address space.
 * Note: the pages are already locked by uvm_vslock(), so we
 * do not need to pass an access_type to pmap_enter().
 */
int
vmapbuf(struct buf *bp, vsize_t len)
{
	struct pmap *upmap, *kpmap __unused;
	vaddr_t uva;		/* User VA (map from) */
	vaddr_t kva;		/* Kernel VA (new to) */
	paddr_t pa; 		/* physical address */
	vsize_t off;

	if ((bp->b_flags & B_PHYS) == 0)
		panic("vmapbuf");

	uva = m68k_trunc_page(bp->b_saveaddr = bp->b_data);
	off = (vaddr_t)bp->b_data - uva;
	len = m68k_round_page(off + len);
	kva = uvm_km_alloc(phys_map, len, 0, UVM_KMF_VAONLY | UVM_KMF_WAITVA);
	bp->b_data = (void *)(kva + off);

	upmap = vm_map_pmap(&bp->b_proc->p_vmspace->vm_map);
	kpmap = vm_map_pmap(phys_map);
	do {
		if (pmap_extract(upmap, uva, &pa) == false)
			panic("vmapbuf: null page frame");
#ifdef M68K_VAC
		pmap_enter(kpmap, kva, pa, VM_PROT_READ | VM_PROT_WRITE,
		    PMAP_WIRED);
#else
		pmap_kenter_pa(kva, pa, VM_PROT_READ | VM_PROT_WRITE, 0);
#endif
		uva += PAGE_SIZE;
		kva += PAGE_SIZE;
		len -= PAGE_SIZE;
	} while (len);
	pmap_update(kpmap);

	return 0;
}
Ejemplo n.º 6
0
static void
grfiv_attach(struct device *parent, struct device *self, void *aux)
{
	struct obio_attach_args *oa = (struct obio_attach_args *)aux;
	struct grfbus_softc *sc;
	struct grfmode *gm;
	u_long base, length;
	u_int32_t vbase1, vbase2;

	sc = (struct grfbus_softc *)self;

	sc->card_id = 0;

	switch (current_mac_model->class) {
	case MACH_CLASSQ2:
		if (current_mac_model->machineid != MACH_MACLC575) {
			sc->sc_basepa = VALKYRIE_BASE;
			length = 0x00100000;		/* 1MB */

			if (sc->sc_basepa <= mac68k_video.mv_phys &&
			    mac68k_video.mv_phys < (sc->sc_basepa + length)) {
				sc->sc_fbofs =
				    mac68k_video.mv_phys - sc->sc_basepa;
			} else {
				sc->sc_basepa =
				    m68k_trunc_page(mac68k_video.mv_phys);
				sc->sc_fbofs =
				    m68k_page_offset(mac68k_video.mv_phys);
				length = mac68k_video.mv_len + sc->sc_fbofs;
			}

			printf(" @ %lx: Valkyrie video subsystem\n",
			    sc->sc_basepa + sc->sc_fbofs);
			break;
		}
		/* See note in grfiv_match() */
		/*FALLTHROUGH*/
	case MACH_CLASSQ:
		base = DAFB_CONTROL_BASE;
		sc->sc_tag = oa->oa_tag;
		if (bus_space_map(sc->sc_tag, base, 0x20, 0, &sc->sc_regh)) {
			printf(": failed to map DAFB register space\n");
			return;
		}

		sc->sc_basepa = DAFB_BASE;
		length = 0x00100000;		/* 1MB */

		/* Compute the current frame buffer offset */
		vbase1 = bus_space_read_4(sc->sc_tag, sc->sc_regh, 0x0) & 0xfff;
#if 1
		/*
		 * XXX The following exists because the DAFB v7 in these
		 * systems doesn't return reasonable values to use for fbofs.
		 * Ken'ichi Ishizaka gets credit for this hack.  (sar 19990426)
		 * (Does this get us the correct result for _all_ DAFB-
		 * equipped systems and monitor combinations?  It seems
		 * possible, if not likely...)
		 */
		switch (current_mac_model->machineid) {
		case MACH_MACLC475:
		case MACH_MACLC475_33:
		case MACH_MACLC575:
		case MACH_MACQ605:
		case MACH_MACQ605_33:
			vbase1 &= 0x3f;
			break;
		}
#endif
		vbase2 = bus_space_read_4(sc->sc_tag, sc->sc_regh, 0x4) & 0xf;
		sc->sc_fbofs = (vbase1 << 9) | (vbase2 << 5);

		printf(" @ %lx: DAFB video subsystem, monitor sense %x\n",
		    sc->sc_basepa + sc->sc_fbofs,
		    (bus_space_read_4(sc->sc_tag, sc->sc_regh, 0x1c) & 0x7));

		bus_space_unmap(sc->sc_tag, sc->sc_regh, 0x20);
		break;
	case MACH_CLASSAV:
		sc->sc_basepa = CIVIC_BASE;
		length = 0x00200000;		/* 2MB */
		if (mac68k_video.mv_phys >= sc->sc_basepa &&
		    mac68k_video.mv_phys < (sc->sc_basepa + length)) {
			sc->sc_fbofs = mac68k_video.mv_phys - sc->sc_basepa;
		} else {
			sc->sc_basepa = m68k_trunc_page(mac68k_video.mv_phys);
			sc->sc_fbofs = m68k_page_offset(mac68k_video.mv_phys);
			length = mac68k_video.mv_len + sc->sc_fbofs;
		}

		printf(" @ %lx: CIVIC video subsystem\n",
		    sc->sc_basepa + sc->sc_fbofs);
		break;
	case MACH_CLASSIIci:
	case MACH_CLASSIIsi:
		sc->sc_basepa = m68k_trunc_page(mac68k_video.mv_phys);
		sc->sc_fbofs = m68k_page_offset(mac68k_video.mv_phys);
		length = mac68k_video.mv_len + sc->sc_fbofs;

		printf(" @ %lx: RBV video subsystem, ",
		    sc->sc_basepa + sc->sc_fbofs);
		switch (via2_reg(rMonitor) & RBVMonitorMask) {
		case RBVMonIDBWP:
			printf("15\" monochrome portrait");
			break;
		case RBVMonIDRGB12:
			printf("12\" color");
			break;
		case RBVMonIDRGB15:
			printf("15\" color");
			break;
		case RBVMonIDStd:
			printf("Macintosh II");
			break;
		default:
			printf("unrecognized");
			break;
		}
		printf(" display\n");

		break;
	default:
		sc->sc_basepa = m68k_trunc_page(mac68k_video.mv_phys);
		sc->sc_fbofs = m68k_page_offset(mac68k_video.mv_phys);
		length = mac68k_video.mv_len + sc->sc_fbofs;

		printf(" @ %lx: On-board video\n",
		    sc->sc_basepa + sc->sc_fbofs);
		break;
	}

	if (bus_space_map(sc->sc_tag, sc->sc_basepa, length, 0,
	    &sc->sc_handle)) {
		printf("%s: failed to map video RAM\n", sc->sc_dev.dv_xname);
		return;
	}

	if (sc->sc_basepa <= mac68k_video.mv_phys &&
	    mac68k_video.mv_phys < (sc->sc_basepa + length)) {
		/* XXX Hack */
		mac68k_video.mv_kvaddr = sc->sc_handle.base + sc->sc_fbofs;
	}

	gm = &(sc->curr_mode);
	gm->mode_id = 0;
	gm->psize = mac68k_video.mv_depth;
	gm->ptype = 0;
	gm->width = mac68k_video.mv_width;
	gm->height = mac68k_video.mv_height;
	gm->rowbytes = mac68k_video.mv_stride;
	gm->hres = 80;				/* XXX hack */
	gm->vres = 80;				/* XXX hack */
	gm->fbsize = gm->height * gm->rowbytes;
	gm->fbbase = (void *)sc->sc_handle.base; /* XXX yet another hack */
	gm->fboff = sc->sc_fbofs;

	/* Perform common video attachment. */
	grf_establish(sc, NULL, grfiv_mode);
}
Ejemplo n.º 7
0
/*ARGSUSED*/
void 
trap(struct trapframe *tf, int type, u_int code, u_int v)
{
	struct lwp *l;
	struct proc *p;
	struct pcb *pcb;
	ksiginfo_t ksi;
	int tmp;
	int rv;
	u_quad_t sticks;
	void *onfault;

	curcpu()->ci_data.cpu_ntrap++;
	l = curlwp;
	p = l->l_proc;
	pcb = lwp_getpcb(l);
	onfault = pcb->pcb_onfault;

	KSI_INIT_TRAP(&ksi);
	ksi.ksi_trap = type & ~T_USER;

	KASSERT(pcb != NULL);

	if (USERMODE(tf->tf_sr)) {
		type |= T_USER;
		sticks = p->p_sticks;
		l->l_md.md_regs = tf->tf_regs;
		LWP_CACHE_CREDS(l, p);
	} else {
		sticks = 0;
		/* XXX: Detect trap recursion? */
	}

	switch (type) {
	default:
	dopanic:
		printf("trap type=0x%x, code=0x%x, v=0x%x\n", type, code, v);
		/*
		 * Let the kernel debugger see the trap frame that
		 * caused us to panic.  This is a convenience so
		 * one can see registers at the point of failure.
		 */
		tmp = splhigh();
#ifdef KGDB
		/* If connected, step or cont returns 1 */
		if (kgdb_trap(type, tf))
			goto kgdb_cont;
#endif
#ifdef	DDB
		(void) kdb_trap(type, (db_regs_t *) tf);
#endif
#ifdef KGDB
	kgdb_cont:
#endif
		splx(tmp);
		if (panicstr) {
			/*
			 * Note: panic is smart enough to do:
			 *   boot(RB_AUTOBOOT | RB_NOSYNC, NULL)
			 * if we call it again.
			 */
			panic("trap during panic!");
		}
		regdump(tf, 128);
		type &= ~T_USER;
		if ((u_int)type < trap_types)
			panic(trap_type[type]);
		panic("trap type 0x%x", type);

	case T_BUSERR:		/* kernel bus error */
		if (onfault == NULL)
			goto dopanic;
		rv = EFAULT;
		/*FALLTHROUGH*/

	copyfault:
		/*
		 * If we have arranged to catch this fault in any of the
		 * copy to/from user space routines, set PC to return to
		 * indicated location and set flag informing buserror code
		 * that it may need to clean up stack frame.
		 */
		tf->tf_stackadj = exframesize[tf->tf_format];
		tf->tf_format = tf->tf_vector = 0;
		tf->tf_pc = (int)onfault;
		tf->tf_regs[D0] = rv;
		goto done;

	case T_BUSERR|T_USER:	/* bus error */
	case T_ADDRERR|T_USER:	/* address error */
		ksi.ksi_addr = (void *)v;
		ksi.ksi_signo = SIGBUS;
		ksi.ksi_code = (type == (T_BUSERR|T_USER)) ?
			BUS_OBJERR : BUS_ADRERR;
		break;

	case T_COPERR:		/* kernel coprocessor violation */
	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
	case T_FMTERR:		/* ...just in case... */
		/*
		 * The user has most likely trashed the RTE or FP state info
		 * in the stack frame of a signal handler.
		 */
		printf("pid %d: kernel %s exception\n", p->p_pid,
		       type==T_COPERR ? "coprocessor" : "format");
		type |= T_USER;

		mutex_enter(p->p_lock);
		SIGACTION(p, SIGILL).sa_handler = SIG_DFL;
		sigdelset(&p->p_sigctx.ps_sigignore, SIGILL);
		sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL);
		sigdelset(&l->l_sigmask, SIGILL);
		mutex_exit(p->p_lock);

		ksi.ksi_signo = SIGILL;
		ksi.ksi_addr = (void *)(int)tf->tf_format;
		ksi.ksi_code = (type == T_COPERR) ?
			ILL_COPROC : ILL_ILLOPC;
		break;

	case T_COPERR|T_USER:	/* user coprocessor violation */
	/* What is a proper response here? */
		ksi.ksi_signo = SIGFPE;
		ksi.ksi_code = FPE_FLTINV;
		break;

	case T_FPERR|T_USER:	/* 68881 exceptions */
		/*
		 * We pass along the 68881 status register which locore stashed
		 * in code for us.
		 */
		ksi.ksi_signo = SIGFPE;
		ksi.ksi_code = fpsr2siginfocode(code);
		break;

	case T_FPEMULI:		/* FPU faults in supervisor mode */
	case T_FPEMULD:
		if (nofault)	/* Doing FPU probe? */
			longjmp(nofault);
		goto dopanic;

	case T_FPEMULI|T_USER:	/* unimplemented FP instruction */
	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
#ifdef	FPU_EMULATE
		if (fpu_emulate(tf, &pcb->pcb_fpregs, &ksi) == 0)
			; /* XXX - Deal with tracing? (tf->tf_sr & PSL_T) */
#else
		uprintf("pid %d killed: no floating point support\n", p->p_pid);
		ksi.ksi_signo = SIGILL;
		ksi.ksi_code = ILL_ILLOPC;
#endif
		break;

	case T_ILLINST|T_USER:	/* illegal instruction fault */
	case T_PRIVINST|T_USER:	/* privileged instruction fault */
		ksi.ksi_addr = (void *)(int)tf->tf_format;
		ksi.ksi_signo = SIGILL;
		ksi.ksi_code = (type == (T_PRIVINST|T_USER)) ?
			ILL_PRVOPC : ILL_ILLOPC;
		break;

	case T_ZERODIV|T_USER:	/* Divide by zero */
		ksi.ksi_code = FPE_FLTDIV;
	case T_CHKINST|T_USER:	/* CHK instruction trap */
	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
		ksi.ksi_addr = (void *)(int)tf->tf_format;
		ksi.ksi_signo = SIGFPE;
		break;

	/*
	 * XXX: Trace traps are a nightmare.
	 *
	 *	HP-UX uses trap #1 for breakpoints,
	 *	NetBSD/m68k uses trap #2,
	 *	SUN 3.x uses trap #15,
	 *	DDB and KGDB uses trap #15 (for kernel breakpoints;
	 *	handled elsewhere).
	 *
	 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
	 * supported yet.
	 *
	 * XXX: We should never get kernel-mode T_TRAP15
	 * XXX: because locore.s now gives them special treatment.
	 */
	case T_TRAP15:		/* kernel breakpoint */
		tf->tf_sr &= ~PSL_T;
		goto done;

	case T_TRACE|T_USER:	/* user trace trap */
#ifdef COMPAT_SUNOS
		/*
		 * SunOS uses Trap #2 for a "CPU cache flush"
		 * Just flush the on-chip caches and return.
		 * XXX - Too bad NetBSD uses trap 2...
		 */
		if (p->p_emul == &emul_sunos) {
			/* get out fast */
			goto done;
		}
#endif
		/* FALLTHROUGH */
	case T_TRACE:		/* tracing a trap instruction */
	case T_TRAP15|T_USER:	/* SUN user trace trap */
		tf->tf_sr &= ~PSL_T;
		ksi.ksi_signo = SIGTRAP;
		break;

	case T_ASTFLT:		/* system async trap, cannot happen */
		goto dopanic;

	case T_ASTFLT|T_USER:	/* user async trap */
		astpending = 0;
		/* T_SSIR is not used on a Sun2. */
		if (l->l_pflag & LP_OWEUPC) {
			l->l_pflag &= ~LP_OWEUPC;
			ADDUPROF(l);
		}
		if (curcpu()->ci_want_resched)
			preempt();
		goto douret;

	case T_MMUFLT:		/* kernel mode page fault */
		/* Hacks to avoid calling VM code from debugger. */
#ifdef	DDB
		if (db_recover != 0)
			goto dopanic;
#endif
#ifdef	KGDB
		if (kgdb_recover != 0)
			goto dopanic;
#endif
		/*
		 * If we were doing profiling ticks or other user mode
		 * stuff from interrupt code, Just Say No.
		 */
		if (onfault == (void *)fubail || onfault == (void *)subail) {
#ifdef	DEBUG
			if (mmudebug & MDB_CPFAULT) {
				printf("trap: copyfault fu/su bail\n");
				Debugger();
			}
#endif
			rv = EFAULT;
			goto copyfault;
		}
		/*FALLTHROUGH*/

	case T_MMUFLT|T_USER: { 	/* page fault */
		vaddr_t va;
		struct vmspace *vm = p->p_vmspace;
		struct vm_map *map;
		vm_prot_t ftype;
		extern struct vm_map *kernel_map;

#ifdef DEBUG
		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
		printf("trap: T_MMUFLT pid=%d, code=0x%x, v=0x%x, pc=0x%x, sr=0x%x\n",
		       p->p_pid, code, v, tf->tf_pc, tf->tf_sr);
#endif

		/*
		 * It is only a kernel address space fault iff:
		 * 	1. (type & T_USER) == 0  and: (2 or 3)
		 * 	2. pcb_onfault not set or
		 *	3. pcb_onfault set but supervisor space data fault
		 * The last can occur during an exec() copyin where the
		 * argument space is lazy-allocated.
		 */
		map = &vm->vm_map;
		if ((type & T_USER) == 0) {
			/* supervisor mode fault */
			if (onfault == NULL || KDFAULT(code))
				map = kernel_map;
		}

		if (WRFAULT(code))
			ftype = VM_PROT_WRITE;
		else
			ftype = VM_PROT_READ;
		va = m68k_trunc_page((vaddr_t)v);

		/*
		 * Need to resolve the fault.
		 *
		 * We give the pmap code a chance to resolve faults by
		 * reloading translations that it was forced to unload.
		 * This function does that, and calls vm_fault if it
		 * could not resolve the fault by reloading the MMU.
		 * This function may also, for example, disallow any
		 * faults in the kernel text segment, etc.
		 */
		pcb->pcb_onfault = NULL;
		rv = _pmap_fault(map, va, ftype);
		pcb->pcb_onfault = onfault;

#ifdef	DEBUG
		if (rv && MDB_ISPID(p->p_pid)) {
			printf("vm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
			       map, va, ftype, rv);
			if (mmudebug & MDB_WBFAILED)
				Debugger();
		}
#endif	/* DEBUG */

		/*
		 * If this was a stack access we keep track of the maximum
		 * accessed stack size.  Also, if vm_fault gets a protection
		 * failure it is due to accessing the stack region outside
		 * the current limit and we need to reflect that as an access
		 * error.
		 */
		if (rv == 0) {
			if (map != kernel_map && (void *)va >= vm->vm_maxsaddr)
				uvm_grow(p, va);

			if ((type & T_USER) == 0 && ucas_ras_check(tf)) {
				return;
			}
			goto finish;
		}
		if (rv == EACCES) {
			ksi.ksi_code = SEGV_ACCERR;
			rv = EFAULT;
		} else
			ksi.ksi_code = SEGV_MAPERR;
		if ((type & T_USER) == 0) {
			/* supervisor mode fault */
			if (onfault) {
#ifdef	DEBUG
				if (mmudebug & MDB_CPFAULT) {
					printf("trap: copyfault pcb_onfault\n");
					Debugger();
				}
#endif
				goto copyfault;
			}
			printf("vm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
			       map, va, ftype, rv);
			goto dopanic;
		}
		ksi.ksi_addr = (void *)v;
		switch (rv) {
		case ENOMEM:
			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
			       p->p_pid, p->p_comm,
			       l->l_cred ?
			       kauth_cred_geteuid(l->l_cred) : -1);
			ksi.ksi_signo = SIGKILL;
			break;
		case EINVAL:
			ksi.ksi_signo = SIGBUS;
			ksi.ksi_code = BUS_ADRERR;
			break;
		case EACCES:
			ksi.ksi_signo = SIGSEGV;
			ksi.ksi_code = SEGV_ACCERR;
			break;
		default:
			ksi.ksi_signo = SIGSEGV;
			ksi.ksi_code = SEGV_MAPERR;
			break;
		}
		break;
		} /* T_MMUFLT */
	} /* switch */

finish:
	/* If trap was from supervisor mode, just return. */
	if ((type & T_USER) == 0)
		goto done;
	/* Post a signal if necessary. */
	if (ksi.ksi_signo)
		trapsignal(l, &ksi);
douret:
	userret(l, tf, sticks);

done:;
	/* XXX: Detect trap recursion? */
}