Exemplo n.º 1
0
void
hzclock(Ureg *ur)
{
	Proc *up = externup();
	uintptr_t pc;

	machp()->ticks++;
	if(machp()->machno == 0)
		sys->ticks = machp()->ticks;

	pc = userpc(ur);
	if(machp()->proc)
		machp()->proc->pc = pc;

	if(machp()->mmuflush){
		if(up)
			mmuflush();
		machp()->mmuflush = 0;
	}

	accounttime();
	kmapinval();

	if(kproftimer != nil)
		kproftimer(pc);
	oprof_alarm_handler(ur);

	if(machp()->online == 0)
		return;

	if(active.exiting) {
		print("someone's exiting\n");
		exit(0);
	}

	if(machp()->machno == 0) {
		/* since sys->ticks is only updated if machp()->machno == 0 */
		checkalarms();
	}

	if(up && up->state == Running)
		hzsched();	/* in proc.c */
}
Exemplo n.º 2
0
/*
 *  All traps come here.  It is slower to have all traps call trap()
 *  rather than directly vectoring the handler.  However, this avoids a
 *  lot of code duplication and possible bugs.  The only exception is
 *  VectorSYSCALL.
 *  Trap is called with interrupts disabled via interrupt-gates.
 */
void
trap(Ureg* ureg)
{
    int clockintr, vno, user;
    // cache the previous vno to see what might be causing
    // trouble
    vno = ureg->type;
    uint64_t gsbase = rdmsr(GSbase);
    //if (sce > scx) iprint("====================");
    lastvno = vno;
    if (gsbase < 1ULL<<63)
        die("bogus gsbase");
    Proc *up = externup();
    char buf[ERRMAX];
    Vctl *ctl, *v;

    machp()->perf.intrts = perfticks();
    user = userureg(ureg);
    if(user && (machp()->NIX.nixtype == NIXTC)) {
        up->dbgreg = ureg;
        cycles(&up->kentry);
    }

    clockintr = 0;

    //_pmcupdate(machp());

    if(ctl = vctl[vno]) {
        if(ctl->isintr) {
            machp()->intr++;
            if(vno >= VectorPIC && vno != VectorSYSCALL)
                machp()->lastintr = ctl->Vkey.irq;
        } else if(up)
            up->nqtrap++;

        if(ctl->isr) {
            ctl->isr(vno);
            if(islo())print("trap %d: isr %p enabled interrupts\n", vno, ctl->isr);
        }
        for(v = ctl; v != nil; v = v->next) {
            if(v->f) {
                v->f(ureg, v->a);
                if(islo())print("trap %d: ctlf %p enabled interrupts\n", vno, v->f);
            }
        }
        if(ctl->eoi) {
            ctl->eoi(vno);
            if(islo())print("trap %d: eoi %p enabled interrupts\n", vno, ctl->eoi);
        }

        intrtime(vno);
        if(ctl->isintr) {
            if(ctl->Vkey.irq == IrqCLOCK || ctl->Vkey.irq == IrqTIMER)
                clockintr = 1;

            if (ctl->Vkey.irq == IrqTIMER)
                oprof_alarm_handler(ureg);

            if(up && !clockintr)
                preempted();
        }
    }
    else if(vno < nelem(excname) && user) {
        spllo();
        snprint(buf, sizeof buf, "sys: trap: %s", excname[vno]);
        postnote(up, 1, buf, NDebug);
    }
    else if(vno >= VectorPIC && vno != VectorSYSCALL) {
        /*
         * An unknown interrupt.
         * Check for a default IRQ7. This can happen when
         * the IRQ input goes away before the acknowledge.
         * In this case, a 'default IRQ7' is generated, but
         * the corresponding bit in the ISR isn't set.
         * In fact, just ignore all such interrupts.
         */

        /* clear the interrupt */
        i8259isr(vno);

        iprint("cpu%d: spurious interrupt %d, last %d\n",
               machp()->machno, vno, machp()->lastintr);
        intrtime(vno);
        if(user)
            kexit(ureg);
        return;
    }
    else {
        if(vno == VectorNMI) {
            nmienable();
            if(machp()->machno != 0) {
                iprint("cpu%d: PC %#llx\n",
                       machp()->machno, ureg->ip);
                for(;;);
            }
        }
        dumpregs(ureg);
        if(!user) {
            ureg->sp = PTR2UINT(&ureg->sp);
            dumpstackwithureg(ureg);
        }
        if(vno < nelem(excname))
            panic("%s", excname[vno]);
        panic("unknown trap/intr: %d\n", vno);
    }
    splhi();

    /* delaysched set because we held a lock or because our quantum ended */
    if(up && up->delaysched && clockintr) {
        if(0)
            if(user && up->ac == nil && up->nqtrap == 0 && up->nqsyscall == 0) {
                if(!waserror()) {
                    up->ac = getac(up, -1);
                    poperror();
                    runacore();
                    return;
                }
            }
        sched();
        splhi();
    }


    if(user) {
        if(up && up->procctl || up->nnote)
            notify(ureg);
        kexit(ureg);
    }
}