Beispiel #1
0
//PAGEBREAK: 32
// hand-craft the first user process. We link initcode.S into the kernel
// as a binary, the linker will generate __binary_initcode_start/_size
void userinit(void)
{
    struct proc *p;
    extern char _binary_initcode_start[], _binary_initcode_size[];

    p = allocproc();
    initproc = p;

    if((p->pgdir = kpt_alloc()) == NULL) {
        panic("userinit: out of memory?");
    }

    inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size);

    p->sz = PTE_SZ;

    // craft the trapframe as if
    memset(p->tf, 0, sizeof(*p->tf));

    p->tf->r14_svc = (uint)error_init;
    p->tf->spsr = spsr_usr ();
    p->tf->sp_usr = PTE_SZ;	// set the user stack
    p->tf->lr_usr = 0;

    // set the user pc. The actual pc loaded into r15_usr is in
    // p->tf, the trapframe.
    p->tf->pc = 0;					// beginning of initcode.S

    safestrcpy(p->name, "initcode", sizeof(p->name));
    p->cwd = namei("/");

    p->state = RUNNABLE;
}
Beispiel #2
0
// Return the address of the PTE in page directory that corresponds to
// virtual address va.  If alloc!=0, create any required page table pages.
static pte_t* walkpgdir (pgd_t *pgdbase, const void *va, int alloc)
{
    pgd_t *pgd;
    pmd_t *pmdbase;
    pmd_t *pmd;
    pte_t *ptebase;

    pgd = &pgdbase[PGD_IDX((uint64)va)];

    if(*pgd & (ENTRY_TABLE | ENTRY_VALID)) {
        pmdbase = (pmd_t*) p2v((*pgd) & PG_ADDR_MASK);
    } else {
        if (!alloc || (pmdbase = (pmd_t*) kpt_alloc()) == 0) {
            return 0;
        }

        memset(pmdbase, 0, PT_SZ);

        *pgd = v2p(pmdbase) | ENTRY_TABLE | ENTRY_VALID;
    }

    pmd = &pmdbase[PMD_IDX(va)];

    if (*pmd & (ENTRY_TABLE | ENTRY_VALID)) {
        ptebase = (pte_t*) p2v((*pmd) & PG_ADDR_MASK);
    } else {
        if (!alloc || (ptebase = (pte_t*) kpt_alloc()) == 0) {
           return 0;
        }

        // Make sure all those PTE_P bits are zero.
        memset(ptebase, 0, PT_SZ);

        // The permissions here are overly generous, but they can
        // be further restricted by the permissions in the page table
        // entries, if necessary.
        *pmd = v2p(ptebase) | ENTRY_TABLE | ENTRY_VALID;
    }

    return &ptebase[PTE_IDX(va)];
}
Beispiel #3
0
// Given a parent process's page table, create a copy
// of it for a child.
pgd_t* copyuvm (pgd_t *pgdir, uint sz)
{
    pgd_t *d;
    pte_t *pte;
    uint64 pa, i, ap;
    char *mem;

    // allocate a new first level page directory
    d = kpt_alloc();
    if (d == NULL ) {
        return NULL ;
    }

    // copy the whole address space over (no COW)
    for (i = 0; i < sz; i += PTE_SZ) {
        if ((pte = walkpgdir(pgdir, (void *) i, 0)) == 0) {
            panic("copyuvm: pte should exist");
        }

        if (!(*pte & (ENTRY_PAGE | ENTRY_VALID))) {
            panic("copyuvm: page not present");
        }

        pa = PTE_ADDR (*pte);
        ap = PTE_AP (*pte);

        if ((mem = alloc_page()) == 0) {
            goto bad;
        }

        memmove(mem, (char*) p2v(pa), PTE_SZ);

        if (mappages(d, (void*) i, PTE_SZ, v2p(mem), ap) < 0) {
            goto bad;
        }
    }
    return d;

bad: freevm(d);
    return 0;
}