Ejemplo n.º 1
0
/* #define DEBUG_CONFIG  */
pcireg_t
mpc_conf_read(void *cpv, pcitag_t tag, int offset)
{
	struct pcibr_config *cp = cpv;
	pcireg_t data;
	u_int32_t reg;
	int s;
	int daddr = 0;
	faultbuf env;
	void *oldh;

	if (offset & 3 || offset < 0 || offset >= 0x100) {
#ifdef DEBUG_CONFIG 
		printf ("pci_conf_read: bad reg %x\n", offset);
#endif /* DEBUG_CONFIG */
		return(~0);
	}

	reg = mpc_gen_config_reg(cpv, tag, offset);
	/* if invalid tag, return -1 */
	if (reg == 0xffffffff)
		return(~0);

	if ((cp->config_type & 2) && (offset & 0x04))
		daddr += 4;

	s = splhigh();

	oldh = curpcb->pcb_onfault;
	if (setfault(&env)) {
		/* we faulted during the read? */
		curpcb->pcb_onfault = oldh;
		splx(s);
		return 0xffffffff;
	}

	bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, reg);
	bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
	data = bus_space_read_4(cp->lc_iot, cp->ioh_cfc, daddr);
	bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, 0); /* disable */
	bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */

	curpcb->pcb_onfault = oldh;

	splx(s);
#ifdef DEBUG_CONFIG
	if (!((offset == 0) && (data == 0xffffffff))) {
		unsigned int bus, dev, fcn;
		mpc_decompose_tag(cpv, tag, &bus, &dev, &fcn);
		printf("mpc_conf_read bus %x dev %x fcn %x offset %x", bus, dev, fcn,
			offset);
		printf(" daddr %x reg %x",daddr, reg);
		printf(" data %x\n", data);
	}
#endif

	return(data);
}
Ejemplo n.º 2
0
/* Call an RTAS method by token */
int
rtas_call_method(cell_t token, int nargs, int nreturns, ...)
{
	vm_offset_t argsptr;
	faultbuf env, *oldfaultbuf;
	va_list ap;
	struct {
		cell_t token;
		cell_t nargs;
		cell_t nreturns;
		cell_t args_n_results[12];
	} args;
	int n, result;

	if (!rtas_exists() || nargs + nreturns > 12)
		return (-1);

	args.token = token;
	va_start(ap, nreturns);

	mtx_lock_spin(&rtas_mtx);
	rtas_bounce_offset = 0;

	args.nargs = nargs;
	args.nreturns = nreturns;

	for (n = 0; n < nargs; n++)
		args.args_n_results[n] = va_arg(ap, cell_t);

	argsptr = rtas_real_map(&args, sizeof(args));

	/* Get rid of any stale machine checks that have been waiting.  */
	__asm __volatile ("sync; isync");
	oldfaultbuf = curthread->td_pcb->pcb_onfault;
        if (!setfault(env)) {
		__asm __volatile ("sync");
		result = rtascall(argsptr, rtas_private_data);
		__asm __volatile ("sync; isync");
	} else {
		result = RTAS_HW_ERROR;
	}
	curthread->td_pcb->pcb_onfault = oldfaultbuf;
	__asm __volatile ("sync");

	rtas_real_unmap(argsptr, &args, sizeof(args));
	mtx_unlock_spin(&rtas_mtx);

	if (result < 0)
		return (result);

	for (n = nargs; n < nargs + nreturns; n++)
		*va_arg(ap, cell_t *) = args.args_n_results[n];
	return (result);
}
Ejemplo n.º 3
0
int
copyoutstr(const void *kaddr, void *udaddr, size_t len, size_t *done)
{
    struct pmap *pm = curproc->p_vmspace->vm_map.pmap;
    int rv, msr, pid, tmp, ctx;
    struct faultbuf env;

    if ((rv = setfault(&env))) {
        curpcb->pcb_onfault = NULL;
        /* XXXX -- len may be lost on a fault */
        if (done)
            *done = len;
        return rv;
    }

    if (!(ctx = pm->pm_ctx)) {
        /* No context -- assign it one */
        ctx_alloc(pm);
        ctx = pm->pm_ctx;
    }

    if (len) {
        __asm volatile("mtctr %3;"		/* Set up counter */
                       "mfmsr %0;"			/* Save MSR */
                       "li %1,0x20; "
                       "andc %1,%0,%1; mtmsr %1;"	/* Disable IMMU */
                       "mfpid %1;"			/* Save old PID */
                       "sync; isync;"

                       "li %3,0;"			/* Clear len */

                       "1:"
                       "mtpid %1;sync;"
                       "lbz %2,0(%6); addi %6,%6,1;"	/* Store kernel byte */
                       "sync; isync;"
                       "mtpid %4; sync;"		/* Load user ctx */
                       "stb %2,0(%5);  dcbf 0,%5; addi %5,%5,1;"	/* Load byte */
                       "sync; isync;"
                       "addi %3,%3,1;"			/* Inc len */
                       "or. %2,%2,%2;"
                       "bdnzf 2,1b;"			/*
							 * while(ctr-- && !zero)
							 */

                       "mtpid %1; mtmsr %0;"		/* Restore PID, MSR */
                       "sync; isync;"
                       : "=&r" (msr), "=&r" (pid), "=&r" (tmp), "+b" (len)
                       : "r" (ctx), "b" (udaddr), "b" (kaddr));
    }
    curpcb->pcb_onfault = NULL;
    if (done)
        *done = len;
    return 0;
}
Ejemplo n.º 4
0
int
badaddr_read(void *addr, size_t size, int *rptr)
{
	struct thread	*td;
	faultbuf	env;
	int		x;

	/* Get rid of any stale machine checks that have been waiting.  */
	__asm __volatile ("sync; isync");

	td = curthread;

	if (setfault(env)) {
		td->td_pcb->pcb_onfault = 0;
		__asm __volatile ("sync");
		return (1);
	}

	__asm __volatile ("sync");

	switch (size) {
	case 1:
		x = *(volatile int8_t *)addr;
		break;
	case 2:
		x = *(volatile int16_t *)addr;
		break;
	case 4:
		x = *(volatile int32_t *)addr;
		break;
	default:
		panic("badaddr: invalid size (%d)", size);
	}

	/* Make sure we took the machine check, if we caused one. */
	__asm __volatile ("sync; isync");

	td->td_pcb->pcb_onfault = 0;
	__asm __volatile ("sync");	/* To be sure. */

	/* Use the value to avoid reorder. */
	if (rptr)
		*rptr = x;

	return (0);
}
Ejemplo n.º 5
0
static int
badaddr(void *addr, size_t size)
{
	struct thread	*td;
	faultbuf	env, *oldfaultbuf;
	int		x;

	/* Get rid of any stale machine checks that have been waiting.  */
	__asm __volatile ("sync; isync");

	td = curthread;

	oldfaultbuf = td->td_pcb->pcb_onfault;
	if (setfault(env)) {
		td->td_pcb->pcb_onfault = oldfaultbuf;
		__asm __volatile ("sync");
		return 1;
	}

	__asm __volatile ("sync");

	switch (size) {
	case 1:
		x = *(volatile int8_t *)addr;
		break;
	case 2:
		x = *(volatile int16_t *)addr;
		break;
	case 4:
		x = *(volatile int32_t *)addr;
		break;
	default:
		panic("badaddr: invalid size (%zd)", size);
	}

	/* Make sure we took the machine check, if we caused one. */
	__asm __volatile ("sync; isync");

	td->td_pcb->pcb_onfault = oldfaultbuf;
	__asm __volatile ("sync");	/* To be sure. */

	return (0);
}
Ejemplo n.º 6
0
int
copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done)
{
    struct		thread *td;
    faultbuf	env;
    const char	*up;
    char		*kp;
    size_t		l;
    int		rv, c;

    if (!is_uaddr(udaddr) || is_uaddr(kaddr))
        return (EFAULT);

    td = curthread;

    if (setfault(env)) {
        td->td_pcb->pcb_onfault = NULL;
        return (EFAULT);
    }

    kp = kaddr;
    up = udaddr;

    rv = ENAMETOOLONG;

    for (l = 0; len-- > 0; l++) {

        c = *up++;

        if (!(*kp++ = c)) {
            l++;
            rv = 0;
            break;
        }
    }

    if (done != NULL) {
        *done = l;
    }

    td->td_pcb->pcb_onfault = NULL;
    return (rv);
}
Ejemplo n.º 7
0
int
copyin(const void *udaddr, void *kaddr, size_t len)
{
    struct		thread *td;
    faultbuf	env;

    if (!is_uaddr(udaddr) || is_uaddr(kaddr))
        return (EFAULT);

    td = curthread;

    if (setfault(env)) {
        td->td_pcb->pcb_onfault = NULL;
        return (EFAULT);
    }

    bcopy(udaddr, kaddr, len);

    td->td_pcb->pcb_onfault = NULL;
    return (0);
}
Ejemplo n.º 8
0
int
suword(void *addr, long word)
{
    struct		thread *td;
    faultbuf	env;

    if (!is_uaddr(addr))
        return (EFAULT);

    td = curthread;

    if (setfault(env)) {
        td->td_pcb->pcb_onfault = NULL;
        return (EFAULT);
    }

    *(long *)addr = word;

    td->td_pcb->pcb_onfault = NULL;
    return (0);
}
Ejemplo n.º 9
0
int
subyte(void *addr, int byte)
{
    struct		thread *td;
    faultbuf	env;

    if (!is_uaddr(addr))
        return (EFAULT);

    td = curthread;

    if (setfault(env)) {
        td->td_pcb->pcb_onfault = NULL;
        return (EFAULT);
    }

    *(char *)addr = (char)byte;

    td->td_pcb->pcb_onfault = NULL;
    return (0);
}
Ejemplo n.º 10
0
int
copyout(const void *kaddr, void *udaddr, size_t len)
{
	struct		thread *td;
	faultbuf	env;

	if (!is_uaddr(udaddr))
		return (EFAULT);

	td = PCPU_GET(curthread);

	if (setfault(env)) {
		td->td_pcb->pcb_onfault = NULL;
		return (EFAULT);
	}

	bcopy(kaddr, udaddr, len);

	td->td_pcb->pcb_onfault = NULL;
	return (0);
}
Ejemplo n.º 11
0
long
fuword(const void *addr)
{
    struct		thread *td;
    faultbuf	env;
    long		val;

    if (!is_uaddr(addr))
        return (EFAULT);

    td = curthread;

    if (setfault(env)) {
        td->td_pcb->pcb_onfault = NULL;
        return (EFAULT);
    }

    val = *(const long *)addr;

    td->td_pcb->pcb_onfault = NULL;
    return (val);
}
Ejemplo n.º 12
0
int
fubyte(const void *addr)
{
    struct		thread *td;
    faultbuf	env;
    int		val;

    if (!is_uaddr(addr))
        return (EFAULT);

    td = curthread;

    if (setfault(env)) {
        td->td_pcb->pcb_onfault = NULL;
        return (EFAULT);
    }

    val = *(const u_char *)addr;

    td->td_pcb->pcb_onfault = NULL;
    return (val);
}