// An empty user page table. p->pagetable = proc_pagetable(p); // Allocate a page for the process's kernel stack. // Map it high in memory, followed by an invalid // guard page. p->kvm = kvminitproc(p->pagetable); uint64 va = KSTACK((int)(p - proc)); // now we map the kernel stack char *pa = kalloc(); if(pa == 0) panic("kalloc"); kvmmap_proc(p->kvm, va, (uint64)pa, PGSIZE, PTE_R | PTE_W); p->kstack = va; if(p->pagetable == 0 || p->kvm == 0){ freeproc(p); release(&p->lock); return0; }
// Set up new context to start executing at forkret, // which returns to user space. memset(&p->context, 0, sizeof(p->context)); p->context.ra = (uint64)forkret; p->context.sp = p->kstack + PGSIZE;
return p; }
其中的辅助函数kvmmap_proc可以对着kvmmap照猫画虎完成
1 2 3 4 5
voidkvmmap_proc(pagetable_t kvm_pt, uint64 va, uint64 pa, uint64 sz, int perm) { if(mappages(kvm_pt, va, sz, pa, perm) != 0) panic("kvmmap_proc"); }
void scheduler(void) { structproc *p; structcpu *c = mycpu(); c->proc = 0; for(;;){ // Avoid deadlock by ensuring that devices can interrupt. intr_on(); int found = 0; for(p = proc; p < &proc[NPROC]; p++) { acquire(&p->lock); if(p->state == RUNNABLE) { // Switch to chosen process. It is the process's job // to release its lock and then reacquire it // before jumping back to us. p->state = RUNNING; c->proc = p; if(p->kvm) { w_satp(MAKE_SATP(p->kvm)); sfence_vma(); swtch(&c->context, &p->context); // Process is done running for now. // It should have changed its p->state before coming back. kvminithart(); } else panic("scheduler"); c->proc = 0;