aboutsummaryrefslogtreecommitdiff
path: root/pk
diff options
context:
space:
mode:
Diffstat (limited to 'pk')
-rw-r--r--pk/entry.S1
-rw-r--r--pk/fp.c2
-rw-r--r--pk/handlers.c38
-rw-r--r--pk/pcr.h3
-rw-r--r--pk/pk.h8
-rw-r--r--pk/syscall.c20
6 files changed, 35 insertions, 37 deletions
diff --git a/pk/entry.S b/pk/entry.S
index a0cdcbc..5fe0be2 100644
--- a/pk/entry.S
+++ b/pk/entry.S
@@ -132,7 +132,6 @@ trap_entry:
jal save_tf
move $sp,$x2
move $a0,$x2
- ei
jal handle_trap
.end trap_entry
diff --git a/pk/fp.c b/pk/fp.c
index 2d369d6..a17bf49 100644
--- a/pk/fp.c
+++ b/pk/fp.c
@@ -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);
diff --git a/pk/pcr.h b/pk/pcr.h
index a8f0b4c..b467132 100644
--- a/pk/pcr.h
+++ b/pk/pcr.h
@@ -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
diff --git a/pk/pk.h b/pk/pk.h
index 3887d84..85967ef 100644
--- a/pk/pk.h
+++ b/pk/pk.h
@@ -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);
}