Exemple #1
0
/*
 * run an arbitrary function with arbitrary args on an ap core
 * first argument is always pml4 for process
 * make a field and a struct for the args cache line.
 *
 * Returns the return-code for the ICC or -1 if the process was
 * interrupted while issuing the ICC.
 */
int
runac(Mach *mp, APfunc func, int flushtlb, void *a, int32_t n)
{
	Proc *up = externup();
	uint8_t *dpg, *spg;

	if (n > sizeof(mp->NIX.icc->data))
		panic("runac: args too long");

	if(mp->online == 0)
		panic("Bad core");
	if(mp->proc != nil && mp->proc != up)
		panic("runapfunc: mach is busy with another proc?");

	memmove(mp->NIX.icc->data, a, n);
	if(flushtlb){
		DBG("runac flushtlb: cppml4 %#p %#p\n", mp->MMU.pml4->pa, machp()->MMU.pml4->pa);
		dpg = UINT2PTR(mp->MMU.pml4->va);
		spg = UINT2PTR(machp()->MMU.pml4->va);
		/* We should copy less:
		 *	memmove(dgp, spg, machp()->MMU.pml4->daddr * sizeof(PTE));
		 */
		memmove(dpg, spg, PTSZ);
		if(0){
			print("runac: upac pml4 %#p\n", up->ac->MMU.pml4->pa);
			dumpptepg(4, up->ac->MMU.pml4->pa);
		}
	}
	mp->NIX.icc->flushtlb = flushtlb;
	mp->NIX.icc->rc = ICCOK;

	DBG("runac: exotic proc on cpu%d\n", mp->machno);
	if(waserror()){
		qunlock(&up->debug);
		nexterror();
	}
	qlock(&up->debug);
	up->nicc++;
	up->state = Exotic;
	up->psstate = 0;
	qunlock(&up->debug);
	poperror();
	mfence();
	mp->NIX.icc->fn = func;
	sched();
	return mp->NIX.icc->rc;
}
Exemple #2
0
void
dumpmmu(Proc *p)
{
    int i;
    Page *pg;

    print("proc %#p\n", p);
    for(i = 3; i > 0; i--) {
        print("mmuptp[%d]:\n", i);
        for(pg = p->MMU.mmuptp[i]; pg != nil; pg = pg->next)
            print("\tpg %#p = va %#ullx pa %#ullx"
                  " daddr %#ulx next %#p prev %#p\n",
                  pg, pg->va, pg->pa, pg->daddr, pg->next, pg->prev);
    }
    print("pml4 %#ullx\n", machp()->MMU.pml4->pa);
    if(0)dumpptepg(4, machp()->MMU.pml4->pa);
}
Exemple #3
0
void
dumpptepg(int lvl, uintptr_t pa)
{
    PTE *pte;
    int tab, i;

    tab = 4 - lvl;
    pte = UINT2PTR(KADDR(pa));
    for(i = 0; i < PTSZ/sizeof(PTE); i++)
        if(pte[i] & PteP) {
            tabs(tab);
            print("l%d %#p[%#05x]: %#ullx\n", lvl, pa, i, pte[i]);

            /* skip kernel mappings */
            if((pte[i]&PteU) == 0) {
                tabs(tab+1);
                print("...kern...\n");
                continue;
            }
            if(lvl > 2)
                dumpptepg(lvl-1, PPN(pte[i]));
        }
}
Exemple #4
0
/*
 * Move the current process to an application core.
 * This is performed at the end of execac(), and
 * we pretend to be returning to user-space, but instead we
 * dispatch the process to another core.
 * 1. We do the final bookkeeping that syscall() would do after
 *    a return from sysexec(), because we are not returning.
 * 2. We dispatch the process to an AC using an ICC.
 *
 * This function won't return unless the process is reclaimed back
 * to the time-sharing core, and is the handler for the process
 * to deal with traps and system calls until the process dies.
 *
 * Remember that this function is the "line" between user and kernel
 * space, it's not expected to raise|handle any error.
 *
 * We install a safety error label, just in case we raise errors,
 * which we shouldn't. (noerrorsleft knows that for exotic processes
 * there is an error label pushed by us).
 */
void
runacore(void)
{
	Proc *up = externup();
	Ureg *ureg;
	void (*fn)(void);
	int rc, flush, s;
	char *n;
	uint64_t t1;

	if(waserror())
		panic("runacore: error: %s\n", up->errstr);
	ureg = up->dbgreg;
	fakeretfromsyscall(ureg);
	fpusysrfork(ureg);

	procpriority(up, PriKproc, 1);
	rc = runac(up->ac, actouser, 1, nil, 0);
	procpriority(up, PriNormal, 0);
	for(;;){
		t1 = fastticks(nil);
		flush = 0;
		fn = nil;
		switch(rc){
		case ICCTRAP:
			s = splhi();
			machp()->MMU.cr2 = up->ac->MMU.cr2;
			DBG("runacore: trap %llu cr2 %#llx ureg %#p\n",
				ureg->type, machp()->MMU.cr2, ureg);
			switch(ureg->type){
			case IdtIPI:
				if(up->procctl || up->nnote)
					notify(up->dbgreg);
				if(up->ac == nil)
					goto ToTC;
				kexit(up->dbgreg);
				break;
			case IdtNM:
			case IdtMF:
			case IdtXF:
				/* these are handled in the AC;
				 * If we get here, they left in m->NIX.icc->data
				 * a note to be posted to the process.
				 * Post it, and make the vector a NOP.
				 */
				n = up->ac->NIX.icc->note;
				if(n != nil)
					postnote(up, 1, n, NDebug);
				ureg->type = IdtIPI;		/* NOP */
				break;
			default:
				cr3put(machp()->MMU.pml4->pa);
				if(0 && ureg->type == IdtPF){
					print("before PF:\n");
					print("AC:\n");
					dumpptepg(4, up->ac->MMU.pml4->pa);
					print("\n%s:\n", rolename[NIXTC]);
					dumpptepg(4, machp()->MMU.pml4->pa);
				}
				trap(ureg);
			}
			splx(s);
			flush = 1;
			fn = actrapret;
			break;
		case ICCSYSCALL:
			DBG("runacore: syscall ax %#llx ureg %#p\n",
				ureg->ax, ureg);
			cr3put(machp()->MMU.pml4->pa);
			//syscall(ureg->ax, ureg);
			flush = 1;
			fn = acsysret;
			if(0)
			if(up->nqtrap > 2 || up->nsyscall > 1)
				goto ToTC;
			if(up->ac == nil)
				goto ToTC;
			break;
		default:
			panic("runacore: unexpected rc = %d", rc);
		}
		up->tctime += fastticks2us(fastticks(nil) - t1);
		procpriority(up, PriExtra, 1);
		rc = runac(up->ac, fn, flush, nil, 0);
		procpriority(up, PriNormal, 0);
	}
ToTC:
	/*
	 *  to procctl, then syscall,  to
	 *  be back in the TC
	 */
	DBG("runacore: up %#p: return\n", up);
}