diff options
author | Andrew Waterman <waterman@s144.Millennium.Berkeley.EDU> | 2011-04-15 14:32:18 -0700 |
---|---|---|
committer | Andrew Waterman <waterman@s144.Millennium.Berkeley.EDU> | 2011-04-15 14:33:12 -0700 |
commit | ba0cf0546686acac7e891d9740009bcc4ada73ee (patch) | |
tree | 5a80659c0b61aab37e36290875713d7c2a09cd8f /pk | |
parent | 04c8f1c003bbee2f9b45f5e706103837a6d61a30 (diff) | |
download | pk-ba0cf0546686acac7e891d9740009bcc4ada73ee.zip pk-ba0cf0546686acac7e891d9740009bcc4ada73ee.tar.gz pk-ba0cf0546686acac7e891d9740009bcc4ada73ee.tar.bz2 |
[pk] fixed timer interrupt bug, etc.
Diffstat (limited to 'pk')
-rw-r--r-- | pk/entry.S | 1 | ||||
-rw-r--r-- | pk/fp.c | 2 | ||||
-rw-r--r-- | pk/handlers.c | 38 | ||||
-rw-r--r-- | pk/pcr.h | 3 | ||||
-rw-r--r-- | pk/pk.h | 8 | ||||
-rw-r--r-- | pk/syscall.c | 20 |
6 files changed, 35 insertions, 37 deletions
@@ -132,7 +132,6 @@ trap_entry: jal save_tf move $sp,$x2 move $a0,$x2 - ei jal handle_trap .end trap_entry @@ -195,8 +195,6 @@ int emulate_fp(trapframe_t* tf) if(have_fp) put_fp_state(fp_state.fpr,fp_state.fsr); - advance_pc(tf); - return 0; } diff --git a/pk/handlers.c b/pk/handlers.c index 4d99578..597c675 100644 --- a/pk/handlers.c +++ b/pk/handlers.c @@ -6,20 +6,10 @@ int have_vector = 1; static void handle_fp_disabled(trapframe_t* tf) { - if(have_fp) - init_fp(tf); - else - { -#ifdef PK_ENABLE_FP_EMULATION - if(emulate_fp(tf) != 0) - { - dump_tf(tf); - panic("FPU emulation failed!"); - } -#else - panic("FPU emulation disabled! pc %lx, insn %x",tf->epc,(uint32_t)tf->insn); -#endif - } + irq_enable(); + + kassert(have_fp); + init_fp(tf); } static void handle_vector_disabled(trapframe_t* tf) @@ -39,8 +29,13 @@ static void handle_privileged_instruction(trapframe_t* tf) static void handle_illegal_instruction(trapframe_t* tf) { #ifdef PK_ENABLE_FP_EMULATION + irq_enable(); + if(emulate_fp(tf) == 0) + { + advance_pc(tf); return; + } #endif dump_tf(tf); @@ -113,6 +108,19 @@ static void handle_interrupt(trapframe_t* tf) } } +static void handle_syscall(trapframe_t* tf) +{ + irq_enable(); + + long n = tf->gpr[2]; + sysret_t ret = syscall(tf->gpr[4], tf->gpr[5], tf->gpr[6], tf->gpr[7], n); + + tf->gpr[2] = ret.result; + tf->gpr[3] = ret.result == -1 ? ret.err : 0; + + advance_pc(tf); +} + void handle_trap(trapframe_t* tf) { typedef void (*trap_handler)(trapframe_t*); @@ -134,7 +142,7 @@ void handle_trap(trapframe_t* tf) }; int exccode = (tf->cause & CAUSE_EXCCODE) >> CAUSE_EXCCODE_SHIFT; - kassert(exccode < sizeof(trap_handlers)/sizeof(trap_handlers[0])); + kassert(exccode < ARRAY_SIZE(trap_handlers)); trap_handlers[exccode](tf); @@ -71,6 +71,9 @@ asm volatile ("mfcr %0,$cr%1" : "=r"(__tmp) : "i"(reg)); \ __tmp; }) +#define irq_disable() asm volatile("di") +#define irq_enable() asm volatile("ei") + #endif #endif @@ -8,6 +8,7 @@ #ifndef __ASSEMBLER__ #include <stdint.h> +#include <machine/syscall.h> typedef struct { @@ -37,7 +38,6 @@ void pop_tf(trapframe_t*); void dump_tf(trapframe_t*); void unhandled_trap(trapframe_t*); -void handle_syscall(trapframe_t*); void handle_misaligned_load(trapframe_t*); void handle_misaligned_store(trapframe_t*); void handle_fault_load(trapframe_t*); @@ -45,14 +45,18 @@ void handle_fault_store(trapframe_t*); void boot(); void sys_exit(int code) __attribute__((noreturn)); +sysret_t syscall(long a0, long a1, long a2, long a3, long n); long load_elf(const char* fn, int* user64); static inline void advance_pc(trapframe_t* tf) { - tf->epc += 4; + int rvc = (tf->insn & 0x3) < 0x3; + tf->epc += rvc ? 2 : 4; } +#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) + #ifdef __cplusplus } #endif diff --git a/pk/syscall.c b/pk/syscall.c index d303324..9482378 100644 --- a/pk/syscall.c +++ b/pk/syscall.c @@ -92,7 +92,7 @@ sysret_t sys_unlink(const char* name, size_t len) return frontend_syscall(SYS_unlink,(long)name,len,0,0); } -void handle_syscall(trapframe_t* tf) +sysret_t syscall(long a0, long a1, long a2, long a3, long n) { const static void* syscall_table[] = { [SYS_exit] = sys_exit, @@ -108,22 +108,8 @@ void handle_syscall(trapframe_t* tf) [SYS_unlink] = sys_unlink, }; - syscall_t p; - unsigned long n = tf->gpr[2]; - if(n >= sizeof(syscall_table)/sizeof(void*) || !syscall_table[n]) - { - dump_tf(tf); + if(n >= ARRAY_SIZE(syscall_table) || !syscall_table[n]) panic("bad syscall #%ld!",n); - } - else - p = (syscall_t)syscall_table[n]; - sysret_t ret = p(tf->gpr[4],tf->gpr[5],tf->gpr[6],tf->gpr[7],n); - tf->gpr[2] = ret.result; - tf->gpr[3] = ret.result == -1 ? ret.err : 0; - - //printk("syscall %d (%x,%x,%x,%x) from %x == %d\n",n,tf->gpr[4],tf->gpr[5],tf->gpr[6],tf->gpr[7],tf->gpr[31],tf->gpr[2]); - - advance_pc(tf); - pop_tf(tf); + return ((syscall_t)syscall_table[n])(a0, a1, a2, a3, n); } |