diff options
| author | Hanjie Wu <hanjiew@andrew.cmu.edu> | 2023-04-23 02:02:46 -0400 |
|---|---|---|
| committer | Hanjie Wu <hanjiew@andrew.cmu.edu> | 2023-04-23 02:02:46 -0400 |
| commit | f33b6e947b7d61b62e28983fcc54a08f15fca509 (patch) | |
| tree | 0a67a35638d6b8baa6a98647726adc643c99c67d | |
| parent | aeb97c4547e79f6875eb641d2420b89ade8c5337 (diff) | |
syscall
| -rw-r--r-- | kern/hvcall.c | 27 | ||||
| -rw-r--r-- | kern/inc/pv.h | 2 | ||||
| -rw-r--r-- | kern/pv.c | 6 | ||||
| -rw-r--r-- | kern/syscall_asm.S | 6 |
4 files changed, 27 insertions, 14 deletions
diff --git a/kern/hvcall.c b/kern/hvcall.c index d8dfeed..9e348bd 100644 --- a/kern/hvcall.c +++ b/kern/hvcall.c @@ -52,16 +52,31 @@ static void hvcall_print_at(stack_frame_t* f); static void hvcall_refpd(int ref); static void hvcall_loadpd(stack_frame_t* f); -// 0: not pv, 1: processed -int handle_pv_syscall(stack_frame_t* f, int index) { - if (get_current()->process->pv == NULL) { - return 0; +// 0: processed +int pv_handle_syscall(stack_frame_t* f, int index) { + thread_t* t = get_current(); + pv_t* pv = t->process->pv; + if (pv == NULL) { + return -1; } if (f->eip >= USER_MEM_START) { - // inject interrupt - return 1; + pv_idt_entry_t* idt = pv_classify_interrupt(pv, index); + if (idt->eip == 0) { + goto no_idt_handler; + } + if (idt->desc != VIDT_DPL_3) { + idt = &pv->vidt.fault[SWEXN_CAUSE_PROTFAULT - PV_FAULT_START]; + if (idt->eip == 0) { + goto no_idt_handler; + } + } + do_inject_irq(t, pv, f, 0, idt->eip); + return 0; } pv_die("Syscall is not allowed for PV kernels"); + +no_idt_handler: + pv_die("No interrupt handler installed"); return 1; } diff --git a/kern/inc/pv.h b/kern/inc/pv.h index eeecd47..b73fe3e 100644 --- a/kern/inc/pv.h +++ b/kern/inc/pv.h @@ -130,6 +130,8 @@ int pv_inject_irq(stack_frame_t* f, int index, int arg); void pv_check_pending_irq(stack_frame_t* f); +void do_inject_irq(thread_t* t, pv_t* pv, stack_frame_t* f, int arg, va_t eip); + typedef struct pv_frame_s { reg_t cr2; reg_t error_code; @@ -270,11 +270,7 @@ no_idt_handler: pv_die("No interrupt handler installed"); } -static inline void do_inject_irq(thread_t* t, - pv_t* pv, - stack_frame_t* f, - int arg, - va_t eip) { +void do_inject_irq(thread_t* t, pv_t* pv, stack_frame_t* f, int arg, va_t eip) { reg_t new_esp; pv_frame_t pv_f; pv_f.cr2 = 0; diff --git a/kern/syscall_asm.S b/kern/syscall_asm.S index 5d63a39..ca1c5a5 100644 --- a/kern/syscall_asm.S +++ b/kern/syscall_asm.S @@ -28,10 +28,10 @@ sys_\name: cld push $\index push %esp - call handle_pv_syscall + call pv_handle_syscall add $0x8, %esp test %eax, %eax - jne return_to_user + je return_to_user push %esp call sys_\name\()_real add $0x4, %esp @@ -100,7 +100,7 @@ sys_\name: cld push $\index push %esp - call handle_pv_syscall + call pv_handle_syscall add $0x8, %esp jmp return_to_user /* check pending exit before iret */ .endm |
