Finish part C.
This commit is contained in:
parent
721a113c93
commit
9acc7c80f7
|
@ -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;
|
||||
|
|
|
@ -93,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"
|
||||
|
|
|
@ -294,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
|
||||
|
@ -312,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;
|
||||
}
|
||||
|
||||
|
@ -350,6 +392,10 @@ syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4,
|
|||
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;
|
||||
}
|
||||
|
|
17
kern/trap.c
17
kern/trap.c
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
19
lib/ipc.c
19
lib/ipc.c
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user