Implement parts A and B.

This commit is contained in:
2019-05-05 19:42:15 -07:00
parent 86c4aa03ed
commit 721a113c93
9 changed files with 246 additions and 39 deletions

View File

@@ -23,18 +23,22 @@ pgfault(struct UTrapframe *utf)
// Hint:
// Use the read-only page table mappings at uvpt
// (see <inc/memlayout.h>).
// LAB 4: Your code here.
if(!((err & FEC_WR) && (uvpt[(uintptr_t) addr >> PGSHIFT] & PTE_COW)))
panic("page fault (addr %p)! %c", addr, (err & FEC_WR) ? 'w' : 'r');
// Allocate a new page, map it at a temporary location (PFTEMP),
// copy the data from the old page to the new page, then move the new
// page to the old page's address.
// Hint:
// You should make three system calls.
void* temp_addr = (void*) PFTEMP;
void* fault_addr = ROUNDDOWN(addr, PGSIZE);
if(sys_page_alloc(0, temp_addr, PTE_P | PTE_W | PTE_U) < 0)
panic("failed to allocate new page");
// LAB 4: Your code here.
panic("pgfault not implemented");
memcpy(temp_addr, fault_addr, PGSIZE);
sys_page_map(0, temp_addr, 0, fault_addr, PTE_P | PTE_U | PTE_W);
sys_page_unmap(0, temp_addr);
}
//
@@ -52,9 +56,27 @@ static int
duppage(envid_t envid, unsigned pn)
{
int r;
bool change_own = false;
pte_t new_pte = uvpt[pn];
pte_t perms = new_pte & (PTE_P | PTE_U | PTE_W | PTE_AVAIL);
void* addr = (void*) (pn * PGSIZE);
// If we're writable, remove write permission
if((new_pte & PTE_W) || (new_pte & PTE_COW)) {
perms = (perms & ~PTE_W) | PTE_COW;
change_own = true;
}
// Map either with the same permissions or with COW.
if((r = sys_page_map(0, addr, envid, addr, perms)) < 0)
return r;
// Update our own permissions if necessary
if(change_own) {
if((r = sys_page_map(0, addr, 0, addr, perms)) < 0)
return r;
}
// LAB 4: Your code here.
panic("duppage not implemented");
return 0;
}
@@ -77,8 +99,43 @@ duppage(envid_t envid, unsigned pn)
envid_t
fork(void)
{
// LAB 4: Your code here.
panic("fork not implemented");
set_pgfault_handler(pgfault);
int return_code;
envid_t forked;
forked = sys_exofork();
if(forked < 0) return forked;
if(forked == 0) { thisenv = &envs[ENVX(sys_getenvid())]; return 0; }
// Map all accessible page directory entries
for(int pde_i = 0; pde_i < PDX(UTOP); pde_i++) {
pde_t pde = uvpd[pde_i];
if(!(pde & PTE_P)) continue;
// For each PDE, map all the underlying PTEs
for(int pte_i = 0; pte_i < NPTENTRIES; pte_i++) {
int pn = pde_i * NPTENTRIES + pte_i;
pte_t pte = uvpt[pn];
if(!(pte & PTE_P)) continue;
// Do not map user exception stack, though
if(pn == ((UXSTACKTOP - PGSIZE) >> PGSHIFT)) continue;
if((return_code = duppage(forked, pn)) < 0) return return_code;
}
}
// Allocate new page for the exception stack
return_code = sys_page_alloc(forked, (void*) UXSTACKTOP - PGSIZE,
PTE_P | PTE_U | PTE_W);
if(return_code < 0) return return_code;
// Set the upcall entry point
sys_env_set_pgfault_upcall(forked, thisenv->env_pgfault_upcall);
sys_env_set_status(forked, ENV_RUNNABLE);
return forked;
}
// Challenge!

View File

@@ -65,18 +65,29 @@ _pgfault_upcall:
// ways as registers become unavailable as scratch space.
//
// LAB 4: Your code here.
mov 40(%esp), %eax // Take the EIP from memory
mov 48(%esp), %ebp // Take the ESP from memory
sub $4, %ebp // Push onto trap-time ESP
mov %eax, (%ebp)
mov %ebp, 48(%esp) // Put ESP back
// Restore the trap-time registers. After you do this, you
// can no longer modify any general-purpose registers.
// LAB 4: Your code here.
add $0x8, %esp
popal
// Restore eflags from the stack. After you do this, you can
// no longer use arithmetic operations or anything else that
// modifies eflags.
// LAB 4: Your code here.
add $0x4, %esp
popfl
// Switch back to the adjusted trap-time stack.
// LAB 4: Your code here.
pop %esp
// Return to re-execute the instruction that faulted.
// LAB 4: Your code here.
ret

View File

@@ -27,9 +27,9 @@ set_pgfault_handler(void (*handler)(struct UTrapframe *utf))
int r;
if (_pgfault_handler == 0) {
// First time through!
// LAB 4: Your code here.
panic("set_pgfault_handler not implemented");
if(sys_page_alloc(0, (void*) UXSTACKTOP - PGSIZE, PTE_U | PTE_P | PTE_W) < 0)
panic("set_pgfault_handler");
sys_env_set_pgfault_upcall(0, _pgfault_upcall);
}
// Save handler pointer for assembly to call.