Compare commits

...

3 Commits

Author SHA1 Message Date
Danila Fedorin 9acc7c80f7 Finish part C. 2019-05-05 22:08:12 -07:00
Danila Fedorin 721a113c93 Implement parts A and B. 2019-05-05 19:42:15 -07:00
Danila Fedorin 86c4aa03ed Disable fast syscall for the time being. 2019-05-03 15:49:42 -07:00
12 changed files with 336 additions and 50 deletions

View File

@ -255,6 +255,7 @@ env_alloc(struct Env **newenv_store, envid_t parent_id)
// Enable interrupts while in user mode.
// LAB 4: Your code here.
e->env_tf.tf_eflags |= FL_IF;
// Clear the page fault handler until user installs one.
e->env_pgfault_upcall = 0;
@ -356,6 +357,7 @@ load_icode(struct Env *e, uint8_t *binary)
// LAB 3: Your code here.
// TODO validate the headers
lcr3(PADDR(e->env_pgdir));
struct Elf* elf = (struct Elf*) binary;
struct Proghdr* ph = (struct Proghdr*) (binary + elf->e_phoff);
struct Proghdr* phend = ph + elf->e_phnum;
@ -363,11 +365,10 @@ load_icode(struct Env *e, uint8_t *binary)
if(ph->p_type != ELF_PROG_LOAD) continue;
region_alloc(e, (void*) ph->p_va, ph->p_memsz);
lcr3(PADDR(e->env_pgdir));
memcpy((void*) ph->p_va, binary + ph->p_offset, ph->p_filesz);
memset((void*) ph->p_va + ph->p_filesz, 0, ph->p_memsz - ph->p_filesz);
lcr3(PADDR(kern_pgdir));
}
lcr3(PADDR(kern_pgdir));
e->env_tf.tf_eip = elf->e_entry;
// Now map one page for the program's initial stack
@ -528,6 +529,7 @@ env_run(struct Env *e)
e->env_status = ENV_RUNNING;
e->env_runs++;
lcr3(PADDR(e->env_pgdir));
unlock_kernel();
env_pop_tf(&e->env_tf);
}

View File

@ -55,6 +55,7 @@ i386_init(void)
// Acquire the big kernel lock before waking up APs
// Your code here:
lock_kernel();
// Starting non-boot CPUs
boot_aps();
@ -64,7 +65,10 @@ i386_init(void)
ENV_CREATE(TEST, ENV_TYPE_USER);
#else
// Touch all you want.
ENV_CREATE(user_primes, ENV_TYPE_USER);
ENV_CREATE(user_yield, ENV_TYPE_USER);
ENV_CREATE(user_yield, ENV_TYPE_USER);
ENV_CREATE(user_yield, ENV_TYPE_USER);
ENV_CREATE(user_yield, ENV_TYPE_USER);
#endif // TEST*
// Schedule and run the first user environment!
@ -121,6 +125,8 @@ mp_main(void)
// only one CPU can enter the scheduler at a time!
//
// Your code here:
lock_kernel();
sched_yield();
// Remove this after you finish Exercise 6
for (;;);

View File

@ -195,6 +195,7 @@ mem_init(void)
// - the new image at UENVS -- kernel R, user R
// - envs itself -- kernel RW, user NONE
// LAB 3: Your code here.
cprintf("Mapping envs from %p to %p\n", UENVS, ROUNDUP(envs_size, PGSIZE));
boot_map_region(kern_pgdir,
UENVS, ROUNDUP(envs_size, PGSIZE),
PADDR(envs), PTE_U);
@ -276,6 +277,11 @@ mem_init_mp(void)
// Permissions: kernel RW, user NONE
//
// LAB 4: Your code here:
for(int i = 0; i < NCPU; i++) {
uintptr_t kstacktop = KSTACKTOP - i * (KSTKSIZE + KSTKGAP);
boot_map_region(kern_pgdir, kstacktop - KSTKSIZE,
KSTKSIZE, PADDR(percpu_kstacks[i]), PTE_W);
}
}
@ -289,6 +295,7 @@ is_reserved(size_t pagenum) {
if(pagenum == 0) return true;
if(pagenum >= PGNUM(IOPHYSMEM) &&
pagenum < PGNUM(PADDR(boot_alloc(0)))) return true;
if(pagenum == PGNUM(MPENTRY_PADDR)) return true;
return false;
}
@ -596,7 +603,15 @@ mmio_map_region(physaddr_t pa, size_t size)
// Hint: The staff solution uses boot_map_region.
//
// Your code here:
panic("mmio_map_region not implemented");
size = ROUNDUP(size, PGSIZE);
if((base + size) > MMIOLIM)
panic("Not enough memory-mapped IO space!");
boot_map_region(kern_pgdir, base, size, pa, PTE_PCD | PTE_PWT | PTE_W);
uintptr_t to_return = base;
base += size;
return (void*) to_return;
}
static uintptr_t user_mem_check_addr;

View File

@ -29,6 +29,23 @@ sched_yield(void)
// below to halt the cpu.
// LAB 4: Your code here.
struct Env* next_env = curenv ? curenv + 1 : envs;
struct Env* end_env = envs + NENV;
struct Env* to_run = NULL;
for(int i = 0; i < NENV; i++, next_env++) {
if(next_env == end_env) next_env = envs;
if(next_env->env_status == ENV_RUNNABLE) {
to_run = next_env;
break;
}
}
if(!to_run && curenv && curenv->env_status == ENV_RUNNING) {
to_run = curenv;
}
if(to_run) env_run(to_run);
// sched_halt never returns
sched_halt();
@ -76,7 +93,7 @@ sched_halt(void)
"pushl $0\n"
// LAB 4:
// Uncomment the following line after completing exercise 13
//"sti\n"
"sti\n"
"1:\n"
"hlt\n"
"jmp 1b\n"

View File

@ -80,9 +80,16 @@ sys_exofork(void)
// status is set to ENV_NOT_RUNNABLE, and the register set is copied
// from the current environment -- but tweaked so sys_exofork
// will appear to return 0.
struct Env* new_env;
int error_code;
error_code = env_alloc(&new_env, curenv->env_id);
if(error_code < 0) return error_code;
// LAB 4: Your code here.
panic("sys_exofork not implemented");
new_env->env_tf = curenv->env_tf;
new_env->env_tf.tf_regs.reg_eax = 0;
new_env->env_status = ENV_NOT_RUNNABLE;
return new_env->env_id;
}
// Set envid's env_status to status, which must be ENV_RUNNABLE
@ -100,9 +107,17 @@ sys_env_set_status(envid_t envid, int status)
// You should set envid2env's third argument to 1, which will
// check whether the current environment has permission to set
// envid's status.
struct Env* env;
int error_code;
// LAB 4: Your code here.
panic("sys_env_set_status not implemented");
error_code = envid2env(envid, &env, 1);
if(error_code < 0) return error_code;
if(status != ENV_RUNNABLE && status != ENV_NOT_RUNNABLE)
return -E_INVAL;
env->env_status = status;
return 0;
}
// Set the page fault upcall for 'envid' by modifying the corresponding struct
@ -116,10 +131,18 @@ sys_env_set_status(envid_t envid, int status)
static int
sys_env_set_pgfault_upcall(envid_t envid, void *func)
{
// LAB 4: Your code here.
panic("sys_env_set_pgfault_upcall not implemented");
struct Env* env;
int return_code;
if((return_code = envid2env(envid, &env, 1)) < 0) return return_code;
env->env_pgfault_upcall = func;
return 0;
}
#define SYS_CHECKPERMS(perm) \
((((perm) & (PTE_P | PTE_U)) == (PTE_P | PTE_U)) && \
(((perm) & ~(PTE_P | PTE_U | PTE_W | PTE_AVAIL)) == 0))
#define SYS_CHECKADDR(addr) (((uintptr_t) (addr) < UTOP) && ((uintptr_t) (addr) % PGSIZE == 0))
// Allocate a page of memory and map it at 'va' with permission
// 'perm' in the address space of 'envid'.
// The page's contents are set to 0.
@ -145,9 +168,22 @@ sys_page_alloc(envid_t envid, void *va, int perm)
// parameters for correctness.
// If page_insert() fails, remember to free the page you
// allocated!
struct Env* env;
int return_code;
if((return_code = envid2env(envid, &env, 1)) < 0) return return_code;
if(!SYS_CHECKPERMS(perm)) return -E_INVAL;
if(!SYS_CHECKADDR(va)) return -E_INVAL;
// LAB 4: Your code here.
panic("sys_page_alloc not implemented");
struct PageInfo* page = page_alloc(1);
if(!page) return -E_NO_MEM;
if((return_code = page_insert(env->env_pgdir, page, va, perm)) < 0) {
page_free(page);
return return_code;
}
return 0;
}
// Map the page of memory at 'srcva' in srcenvid's address space
@ -176,9 +212,24 @@ sys_page_map(envid_t srcenvid, void *srcva,
// parameters for correctness.
// Use the third argument to page_lookup() to
// check the current permissions on the page.
struct Env *srcenv, *dstenv;
pte_t* srcpte;
int return_code;
// LAB 4: Your code here.
panic("sys_page_map not implemented");
if((return_code = envid2env(srcenvid, &srcenv, 1)) < 0) return return_code;
if((return_code = envid2env(dstenvid, &dstenv, 1)) < 0) return return_code;
if(!SYS_CHECKADDR(srcva)) return -E_INVAL;
if(!SYS_CHECKADDR(dstva)) return -E_INVAL;
if(!SYS_CHECKPERMS(perm)) return -E_INVAL;
struct PageInfo* page = page_lookup(srcenv->env_pgdir, srcva, &srcpte);
if(page == NULL) return -E_INVAL;
if(perm & PTE_W && !(*srcpte & PTE_W)) return -E_INVAL;
if((return_code = page_insert(dstenv->env_pgdir, page, dstva, perm)) < 0)
return return_code;
return 0;
}
// Unmap the page of memory at 'va' in the address space of 'envid'.
@ -192,9 +243,14 @@ static int
sys_page_unmap(envid_t envid, void *va)
{
// Hint: This function is a wrapper around page_remove().
struct Env* env;
int return_code;
// LAB 4: Your code here.
panic("sys_page_unmap not implemented");
if((return_code = envid2env(envid, &env, 1)) < 0) return return_code;
if(!SYS_CHECKADDR(va)) return -E_INVAL;
page_remove(env->env_pgdir, va);
return 0;
}
// Try to send 'value' to the target env 'envid'.
@ -238,8 +294,38 @@ sys_page_unmap(envid_t envid, void *va)
static int
sys_ipc_try_send(envid_t envid, uint32_t value, void *srcva, unsigned perm)
{
// LAB 4: Your code here.
panic("sys_ipc_try_send not implemented");
struct Env* dest_env;
struct Env* src_env;
int return_code;
if((return_code = envid2env(0, &src_env, 0)) < 0)
return return_code;
if((return_code = envid2env(envid, &dest_env, 0)) < 0)
return return_code;
if(!dest_env->env_ipc_recving)
return -E_IPC_NOT_RECV;
if((uintptr_t) srcva < UTOP && dest_env->env_ipc_dstva) {
if(!SYS_CHECKADDR(srcva)) return -E_INVAL;
if(!SYS_CHECKPERMS(perm)) return -E_INVAL;
pte_t* srcpte;
struct PageInfo* page = page_lookup(src_env->env_pgdir, srcva, &srcpte);
if(page == NULL) return -E_INVAL;
if(perm & PTE_W && !(*srcpte & PTE_W)) return -E_INVAL;
page_insert(dest_env->env_pgdir, page, dest_env->env_ipc_dstva, perm);
dest_env->env_ipc_perm = perm;
}
dest_env->env_ipc_from = src_env->env_id;
dest_env->env_ipc_value = value;
dest_env->env_ipc_recving = false;
if(dest_env->env_status == ENV_NOT_RUNNABLE)
dest_env->env_status = ENV_RUNNABLE;
return 0;
}
// Block until a value is ready. Record that you want to receive
@ -256,8 +342,20 @@ sys_ipc_try_send(envid_t envid, uint32_t value, void *srcva, unsigned perm)
static int
sys_ipc_recv(void *dstva)
{
struct Env* env;
int return_code;
if((return_code = envid2env(0, &env, 1)) < 0)
return return_code;
// LAB 4: Your code here.
panic("sys_ipc_recv not implemented");
if((uintptr_t) dstva < UTOP) {
if(!SYS_CHECKADDR(dstva)) return -E_INVAL;
env->env_ipc_dstva = dstva;
}
env->env_ipc_recving = true;
env->env_status = ENV_NOT_RUNNABLE;
return 0;
}
@ -279,6 +377,25 @@ syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4,
return sys_getenvid();
case SYS_env_destroy:
return sys_env_destroy(a1);
case SYS_yield:
sys_yield();
return 0;
case SYS_exofork:
return sys_exofork();
case SYS_env_set_status:
return sys_env_set_status(a1, a2);
case SYS_env_set_pgfault_upcall:
return sys_env_set_pgfault_upcall(a1, (void*) a2);
case SYS_page_alloc:
return sys_page_alloc(a1, (void*) a2, a3);
case SYS_page_map:
return sys_page_map(a1, (void*) a2, a3, (void*) a4, a5);
case SYS_page_unmap:
return sys_page_unmap(a1, (void*) a2);
case SYS_ipc_try_send:
return sys_ipc_try_send(a1, a2, (void*) a3, a4);
case SYS_ipc_recv:
return sys_ipc_recv((void*) a1);
default:
return -E_INVAL;
}

View File

@ -89,6 +89,13 @@ void t_simderr();
void t_syscall();
void t_default();
void irq_timer();
void irq_kbd();
void irq_serial();
void irq_spurious();
void irq_ide();
void irq_error();
void
trap_init(void)
{
@ -125,6 +132,13 @@ trap_init(void)
SETGATE(idt[T_SYSCALL], 0, GD_KT, t_syscall, 3);
SETGATE(idt[T_DEFAULT], 0, GD_KT, t_default, 0);
SETGATE(idt[IRQ_OFFSET + IRQ_TIMER], 0, GD_KT, irq_timer, 0);
SETGATE(idt[IRQ_OFFSET + IRQ_KBD], 0, GD_KT, irq_kbd, 0);
SETGATE(idt[IRQ_OFFSET + IRQ_SERIAL], 0, GD_KT, irq_serial, 0);
SETGATE(idt[IRQ_OFFSET + IRQ_SPURIOUS], 0, GD_KT, irq_spurious, 0);
SETGATE(idt[IRQ_OFFSET + IRQ_IDE], 0, GD_KT, irq_ide, 0);
SETGATE(idt[IRQ_OFFSET + IRQ_ERROR], 0, GD_KT, irq_error, 0);
// Per-CPU setup
trap_init_percpu();
}
@ -160,18 +174,18 @@ trap_init_percpu(void)
// Setup a TSS so that we get the right stack
// when we trap to the kernel.
ts.ts_esp0 = KSTACKTOP;
ts.ts_ss0 = GD_KD;
ts.ts_iomb = sizeof(struct Taskstate);
thiscpu->cpu_ts.ts_esp0 = KSTACKTOP - thiscpu->cpu_id * (KSTKSIZE + KSTKGAP);
thiscpu->cpu_ts.ts_ss0 = GD_KD;
thiscpu->cpu_ts.ts_iomb = sizeof(struct Taskstate);
// Initialize the TSS slot of the gdt.
gdt[GD_TSS0 >> 3] = SEG16(STS_T32A, (uint32_t) (&ts),
gdt[(GD_TSS0 >> 3) + cpunum()] = SEG16(STS_T32A, (uint32_t) (&thiscpu->cpu_ts),
sizeof(struct Taskstate) - 1, 0);
gdt[GD_TSS0 >> 3].sd_s = 0;
gdt[(GD_TSS0 >> 3) + cpunum()].sd_s = 0;
// Load the TSS selector (like other segment selectors, the
// bottom three bits are special; we leave them 0)
ltr(GD_TSS0);
ltr(GD_TSS0 + (cpunum() << 3));
// Load the IDT
lidt(&idt_pd);
@ -243,6 +257,9 @@ trap_dispatch(struct Trapframe *tf)
tf->tf_regs.reg_esi);
tf->tf_regs.reg_eax = returned;
return;
} else if (tf->tf_trapno == IRQ_OFFSET + IRQ_TIMER) {
lapic_eoi();
sched_yield();
}
// Handle spurious interrupts
@ -294,6 +311,7 @@ trap(struct Trapframe *tf)
// Acquire the big kernel lock before doing any
// serious kernel work.
// LAB 4: Your code here.
lock_kernel();
assert(curenv);
// Garbage collect if current enviroment is a zombie
@ -373,11 +391,39 @@ page_fault_handler(struct Trapframe *tf)
// (the 'tf' variable points at 'curenv->env_tf').
// LAB 4: Your code here.
if(!curenv->env_pgfault_upcall) {
// Destroy the environment that caused the fault.
cprintf("[%08x] user fault va %08x ip %08x\n",
curenv->env_id, fault_va, tf->tf_eip);
print_trapframe(tf);
env_destroy(curenv);
}
user_mem_assert(curenv, curenv->env_pgfault_upcall, 1, PTE_U | PTE_P);
user_mem_assert(curenv, (void*) UXSTACKTOP - 1, 1, PTE_U | PTE_P | PTE_W);
// Destroy the environment that caused the fault.
cprintf("[%08x] user fault va %08x ip %08x\n",
curenv->env_id, fault_va, tf->tf_eip);
print_trapframe(tf);
env_destroy(curenv);
uintptr_t top_addr = UXSTACKTOP;
if(tf->tf_esp <= UXSTACKTOP && tf->tf_esp >= (UXSTACKTOP - PGSIZE)) {
top_addr = tf->tf_esp - 4;
}
struct UTrapframe utf;
utf.utf_eflags = tf->tf_eflags;
utf.utf_eip = tf->tf_eip;
utf.utf_err = tf->tf_err;
utf.utf_esp = tf->tf_esp;
utf.utf_fault_va = fault_va;
utf.utf_regs = tf->tf_regs;
struct UTrapframe* push_to = (struct UTrapframe*) top_addr - 1;
if((uintptr_t) push_to < USTACKTOP - PGSIZE) {
cprintf("[%08x] stack overflow in page fault handler\n",
curenv->env_id);
env_destroy(curenv);
}
*push_to = utf;
curenv->env_tf.tf_eip = (uintptr_t) curenv->env_pgfault_upcall;
curenv->env_tf.tf_esp = (uintptr_t) push_to;
env_run(curenv);
}

View File

@ -82,6 +82,12 @@ TRAPHANDLER_NOEC(t_mchk, T_MCHK);
TRAPHANDLER_NOEC(t_simderr, T_SIMDERR);
TRAPHANDLER_NOEC(t_syscall, T_SYSCALL);
TRAPHANDLER(t_default, T_DEFAULT);
TRAPHANDLER_NOEC(irq_timer, IRQ_OFFSET + IRQ_TIMER);
TRAPHANDLER_NOEC(irq_kbd, IRQ_OFFSET + IRQ_KBD);
TRAPHANDLER_NOEC(irq_serial, IRQ_OFFSET + IRQ_SERIAL);
TRAPHANDLER_NOEC(irq_spurious, IRQ_OFFSET + IRQ_SPURIOUS);
TRAPHANDLER_NOEC(irq_ide, IRQ_OFFSET + IRQ_IDE);
TRAPHANDLER_NOEC(irq_error, IRQ_OFFSET + IRQ_ERROR);
// HINT 1 : TRAPHANDLER_NOEC(t_divide, T_DIVIDE);
// Do something like this if there is no error code for the trap

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

@ -22,9 +22,14 @@
int32_t
ipc_recv(envid_t *from_env_store, void *pg, int *perm_store)
{
// LAB 4: Your code here.
panic("ipc_recv not implemented");
return 0;
int return_code;
if((return_code = sys_ipc_recv(pg ? pg : (void*) ~0)) < 0)
return return_code;
if(from_env_store) *from_env_store = thisenv->env_ipc_from;
if(perm_store) *perm_store = thisenv->env_ipc_perm;
return thisenv->env_ipc_value;
}
// Send 'val' (and 'pg' with 'perm', if 'pg' is nonnull) to 'toenv'.
@ -38,8 +43,12 @@ ipc_recv(envid_t *from_env_store, void *pg, int *perm_store)
void
ipc_send(envid_t to_env, uint32_t val, void *pg, int perm)
{
// LAB 4: Your code here.
panic("ipc_send not implemented");
int return_code = -E_IPC_NOT_RECV;
while(return_code == -E_IPC_NOT_RECV) {
return_code = sys_ipc_try_send(to_env, val, pg ? pg : (void*) ~0, perm);
sys_yield();
}
if(return_code != 0) panic("failed to send\n");
}
// Find the first environment of the given type. We'll use this to

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.

View File

@ -55,13 +55,13 @@ fast_syscall(int num, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4) {
void
sys_cputs(const char *s, size_t len)
{
fast_syscall(SYS_cputs, (uint32_t)s, len, 0, 0);
syscall(SYS_cputs, 0, (uint32_t)s, len, 0, 0, 0);
}
int
sys_cgetc(void)
{
return fast_syscall(SYS_cgetc, 0, 0, 0, 0);
return syscall(SYS_cgetc, 0, 0, 0, 0, 0, 0);
}
int