diff options
| -rw-r--r-- | kern/hvcall.c | 105 | ||||
| -rw-r--r-- | kern/inc/console.h | 15 | ||||
| -rw-r--r-- | kern/inc/pts.h | 40 | ||||
| -rw-r--r-- | kern/inc/pv.h | 133 | ||||
| -rw-r--r-- | kern/inc/timer.h | 3 | ||||
| -rw-r--r-- | kern/inc/toad.h | 5 | ||||
| -rw-r--r-- | kern/interrupt.c | 104 | ||||
| -rw-r--r-- | kern/kernel.c | 4 | ||||
| -rw-r--r-- | kern/mm.c | 2 | ||||
| -rw-r--r-- | kern/pts.c | 2 | ||||
| -rw-r--r-- | kern/pv.c | 7 | ||||
| -rw-r--r-- | kern/sched.c | 2 | ||||
| -rw-r--r-- | kern/syscall_asm.S | 3 | ||||
| -rw-r--r-- | kern/timer.c | 4 | ||||
| -rw-r--r-- | kern/toad.c | 1 |
15 files changed, 387 insertions, 43 deletions
diff --git a/kern/hvcall.c b/kern/hvcall.c index d387771..391882a 100644 --- a/kern/hvcall.c +++ b/kern/hvcall.c @@ -1,6 +1,6 @@ -/** @file syscall_hvcall.c +/** @file hvcall.c * - * @brief miscellaneous syscalls. + * @brief hypercalls. * * @author Hanjie Wu (hanjiew) * @bug No functional bugs @@ -34,25 +34,87 @@ #include <timer.h> #include <usermem.h> +/** reference a page table to prevent hypevisor of freeing its shadow page table + */ #define HV_REFPD_OP HV_RESERVED_0 +/** release the reference to a page table to let hypevisor free its + * shadow page table + */ #define HV_UNREFPD_OP HV_RESERVED_1 +/** load a previously referenced page table so hypervisor do not need to + * retranslate it + */ #define HV_LOADPD_OP HV_RESERVED_2 +/** + * @brief exit() hypercall handler + * @param f saved regs + */ static void hvcall_exit(stack_frame_t* f); +/** + * @brief iret() hypercall handler + * @param f saved regs + */ static void hvcall_iret(stack_frame_t* f); +/** + * @brief setidt() hypercall handler + * @param f saved regs + */ static void hvcall_setidt(stack_frame_t* f); +/** + * @brief setpd() hypercall handler + * @param f saved regs + */ static void hvcall_setpd(stack_frame_t* f); +/** + * @brief adjustpg() hypercall handler + * @param f saved regs + */ static void hvcall_adjustpg(stack_frame_t* f); +/** + * @brief print() hypercall handler + * @param f saved regs + */ static void hvcall_print(stack_frame_t* f); +/** + * @brief set_color() hypercall handler + * @param f saved regs + */ static void hvcall_set_color(stack_frame_t* f); +/** + * @brief set_cursor() hypercall handler + * @param f saved regs + */ static void hvcall_set_cursor(stack_frame_t* f); +/** + * @brief get_cursor() hypercall handler + * @param f saved regs + */ static void hvcall_get_cursor(stack_frame_t* f); +/** + * @brief print_at() hypercall handler + * @param f saved regs + */ static void hvcall_print_at(stack_frame_t* f); +/** + * @brief refpd/unrefpd() hypercall handler + * @param f saved regs + */ static void hvcall_refpd(int ref); +/** + * @brief loadpd() hypercall handler + * @param f saved regs + */ static void hvcall_loadpd(stack_frame_t* f); -// 0: processed +/** + * @brief try to handle a syscall for PV guest + * @param index syscall index + * @param f saved regs + * @return 0 if a syscall is injected to PV guest, -1 if current thread is not + * PV guest + */ int pv_handle_syscall(int index, stack_frame_t* f) { thread_t* t = get_current(); pv_t* pv = t->process->pv; @@ -65,7 +127,7 @@ int pv_handle_syscall(int index, stack_frame_t* f) { goto no_idt_handler; } if (idt->desc != VIDT_DPL_3) { - idt = &pv->vidt.fault[SWEXN_CAUSE_PROTFAULT - PV_FAULT_START]; + idt = &pv->vidt.fault_irq[SWEXN_CAUSE_PROTFAULT - PV_FAULT_START]; if (idt->eip == 0) { goto no_idt_handler; } @@ -80,8 +142,13 @@ no_idt_handler: return 1; } +/** + * @brief all hypercall entry + * @param f saved regs + */ void sys_hvcall_real(stack_frame_t* f) { pv_t* pv = get_current()->process->pv; + /** hide hypercall for non-PV process and usermode programs in PV guest */ if (pv == NULL || f->eip >= USER_MEM_START) { return; } @@ -153,6 +220,7 @@ read_arg_fail: pv_die("Bad argument address"); } +/** eflags that can be changed by PV guests */ #define EFLAGS_PV_MASK \ (EFL_CF | EFL_PF | EFL_AF | EFL_ZF | EFL_SF | EFL_TF | EFL_DF | EFL_OF | \ EFL_RF) @@ -161,7 +229,7 @@ static void hvcall_iret(stack_frame_t* f) { thread_t* t = get_current(); pv_t* pv = t->process->pv; reg_t esp = f->esp; - reg_t regs[5]; + reg_t regs[5]; /* eip, eflags, esp, esp0, eax */ if (copy_from_user(esp, 5 * sizeof(reg_t), regs) != 0) { goto read_arg_fail; } @@ -205,11 +273,11 @@ static void hvcall_setidt(stack_frame_t* f) { if (copy_from_user(esp + 2 * sizeof(va_t), sizeof(int), &is_dpl0) != 0) { goto read_arg_fail; } - if (index < 0 || index >= IDT_ENTS) { - goto bad_idt_index; - } pv_t* pv = get_current()->process->pv; pv_idt_entry_t* idt = pv_classify_interrupt(pv, index); + if (idt == NULL) { + goto bad_idt_index; + } idt->eip = eip0; idt->desc = ((idt->desc & (~VIDT_DPL_MASK)) | (is_dpl0 != 0 ? VIDT_DPL_0 : VIDT_DPL_3)); @@ -221,6 +289,13 @@ read_arg_fail: pv_die("Bad argument address"); } +/** + * @brief translate a PV guest's page table to shadow page tables + * @param pv PV control block for PV guest + * @param pd guest page table physical address + * @param wp is CR0_WP bit enabled for guest + * @return shadow page table, or NULL on failure + */ static pv_pd_t* translate_pv_pd(pv_t* pv, pa_t pd, int wp); static void hvcall_setpd(stack_frame_t* f) { @@ -254,7 +329,9 @@ read_arg_fail: pv_die("Bad argument address"); } +/** customizable bits in pde */ #define PDE_RESV_MASK 0xf00 +/** customizable bits in pte */ #define PTE_RESV_MASK 0xe00 static pv_pd_t* translate_pv_pd(pv_t* pv, pa_t pd, int wp) { @@ -303,7 +380,8 @@ static pv_pd_t* translate_pv_pd(pv_t* pv, pa_t pd, int wp) { if (pd >= mem_limit) { goto bad_pt; } - pd += pv->mem_base; + pd += pv->mem_base; /** convert guest physical address to host physical + address */ for (i = 0; i < NUM_PAGE_ENTRY - USER_PD_START; i++) { page_directory_t* old_pd = (page_directory_t*)map_phys_page(pd, NULL); pde_t old_pde = (*old_pd)[i]; @@ -327,13 +405,15 @@ static pv_pd_t* translate_pv_pd(pv_t* pv, pa_t pd, int wp) { } pa_t pa = get_page_base(old_pte); if (pa > mem_limit) { - pa = overflow_pa; + pa = overflow_pa; /** emulate memory access outside physical + address limit */ } else { pa = pv->mem_base + pa; } int old_us = (old_pte & (1 << PTE_US_SHIFT)); int old_rw = (old_pte & (1 << PTE_RW_SHIFT)); int new_mask, new_user_mask; + /** if WP is disabled, PV kernel can always write anywhere */ if (wp == 0) { new_mask = ((1 << PTE_P_SHIFT) | (PTE_RW << PTE_RW_SHIFT) | (PTE_USER << PTE_US_SHIFT)); @@ -341,6 +421,7 @@ static pv_pd_t* translate_pv_pd(pv_t* pv, pa_t pd, int wp) { new_mask = ((1 << PTE_P_SHIFT) | old_rw | (PTE_USER << PTE_US_SHIFT)); } + /** hide PV kernel in usermode program's page table */ if ((old_us & old_pde_us) != 0) { new_user_mask = ((1 << PTE_P_SHIFT) | old_rw | (PTE_USER << PTE_US_SHIFT)); @@ -363,6 +444,7 @@ static pv_pd_t* translate_pv_pd(pv_t* pv, pa_t pd, int wp) { free_user_pages(new_pt, 1); goto alloc_pt_fail; } + /** write the new page table */ memcpy((void*)map_phys_page(new_pt, NULL), t_pt, PAGE_SIZE); memcpy((void*)map_phys_page(new_user_pt, NULL), t_user_pt, PAGE_SIZE); pde_t new_pde = ((old_pde & PDE_RESV_MASK) | @@ -372,6 +454,7 @@ static pv_pd_t* translate_pv_pd(pv_t* pv, pa_t pd, int wp) { } else { new_pde |= (old_pde & (1 << PTE_RW_SHIFT)); } + /** insert the page table into page directory */ (*t_pd)[USER_PD_START + i] = (new_pt | new_pde); (*t_user_pd)[USER_PD_START + i] = (new_user_pt | new_pde); } @@ -687,7 +770,7 @@ static void hvcall_refpd(int ref) { } else { pv_pd->refcount--; if (pv_pd->refcount <= 0) { - pv_die("Page table destroyed by kerenl"); + pv_die("Page table destroyed by PV kerenl"); } } } diff --git a/kern/inc/console.h b/kern/inc/console.h index dbfdbb0..050b04b 100644 --- a/kern/inc/console.h +++ b/kern/inc/console.h @@ -9,6 +9,21 @@ #ifndef _CONSOLE_H #define _CONSOLE_H +/** @brief Prints character ch at the current location + * of the cursor. + * + * If the character is a newline ('\n'), the cursor is + * be moved to the beginning of the next line (scrolling if necessary). If + * the character is a carriage return ('\r'), the cursor + * is immediately reset to the beginning of the current + * line, causing any future output to overwrite any existing + * output on the line. If backsapce ('\b') is encountered, + * the previous character is erased. See the main console.c description + * for more backspace behavior. + * + * @param ch the character to print + * @return The input character + */ int putbyte(char ch); #endif diff --git a/kern/inc/pts.h b/kern/inc/pts.h index 4c0c9f9..236c37f 100644 --- a/kern/inc/pts.h +++ b/kern/inc/pts.h @@ -63,9 +63,10 @@ typedef struct kbd_request_s { /** maximum readline size */ #define MAX_READLINE (CHR_RING_SIZE - 1) +/** a pair of virtual console and keyboard scancode queue */ typedef struct pts_s { - queue_t pts_link; - queue_t* pvs; + queue_t pts_link; /** in all_pts */ + queue_t* pvs; /** PV guests on this pts */ int refcount; mutex_t lock; @@ -86,18 +87,24 @@ typedef struct pts_s { char chr_ring[CHR_RING_SIZE]; int chr_r_pos; int chr_w_pos; - int forward_tab; + int forward_tab; /** whether we should forward tab key to the guest */ } pts_t; +/** foregound pts */ extern pts_t* active_pts; + +/** lock for operating active_pts */ extern spl_t pts_lock; +/** @brief initialize pts system + */ void setup_pts(); +/** @brief initialize a pts and add it to all_pts + * @param pts pts + */ void pts_init(pts_t* pts); -int putbyte(char ch); - /** @brief Prints character ch at the current location * of the cursor. * @@ -110,6 +117,7 @@ int putbyte(char ch); * the previous character is erased. See the main console.c description * for more backspace behavior. * + * @param pts pts * @param ch the character to print * @return The input character */ @@ -128,6 +136,7 @@ int pts_putbyte(pts_t* pts, char ch); * as per putbyte. If len is not a positive integer or s * is null, the function has no effect. * + * @param pts pts * @param s The string to be printed. * @param len The length of the string s. * @return Void. @@ -139,6 +148,7 @@ void pts_putbytes(pts_t* pts, const char* s, int len); * * If the color code is invalid, the function has no effect. * + * @param pts pts * @param color The new color code. * @return 0 on success or integer error code less than 0 if * color code is invalid. @@ -148,6 +158,7 @@ int pts_set_term_color(pts_t* pts, int color); /** @brief Writes the current foreground and background * color of characters printed on the console * into the argument color. + * @param pts pts * @param color The address to which the current color * information will be written. * @return Void. @@ -162,6 +173,7 @@ void pts_get_term_color(pts_t* pts, int* color); * currently hidden, a call to set_cursor() does not show * the cursor. * + * @param pts pts * @param row The new row for the cursor. * @param col The new column for the cursor. * @return 0 on success or integer error code less than 0 if @@ -171,6 +183,7 @@ int pts_set_cursor(pts_t* pts, int row, int col); /** @brief Writes the current position of the cursor * into the arguments row and col. + * @param pts pts * @param row The address to which the current cursor * row will be written. * @param col The address to which the current cursor @@ -179,10 +192,23 @@ int pts_set_cursor(pts_t* pts, int row, int col); */ void pts_get_cursor(pts_t* pts, int* row, int* col); +/** @brief print a string from user memory to (row, col) using color and restore + * everything after printing. + * @param pts pts + * @param len length of the string. + * @param buf string. + * @param row The address to which the current cursor + * row will be written. + * @param col The address to which the current cursor + * column will be written. + * @param color color. + * @return 0 on success, non-zero on failure + */ int pts_print_at(pts_t* pts, int len, va_t buf, int row, int col, int color); /** * @brief read a line to userspace + * @param pts pts * @param len max length to read * @param buf buffer * @return size on success, -1 on failure @@ -195,6 +221,10 @@ int do_readline(int len, va_t buf); */ int do_getchar(); +/** + * @brief switch to a pts + * @param pts pts + */ void switch_pts(pts_t* pts); #endif /* _PTS_H */ diff --git a/kern/inc/pv.h b/kern/inc/pv.h index c0708dc..294966c 100644 --- a/kern/inc/pv.h +++ b/kern/inc/pv.h @@ -1,3 +1,11 @@ +/** @file pv.h + * + * @brief PV functions + * + * @author Hanjie Wu (hanjiew) + * @bug No functional bugs + */ + #ifndef _PV_H_ #define _PV_H_ @@ -14,60 +22,86 @@ #include <loader.h> #include <paging.h> +/** RPL3 means RPL is 3 */ #define SEGSEL_RPL3 3 +/** cs for PV guest */ #define SEGSEL_PV_CS (SEGSEL_SPARE0 | SEGSEL_RPL3) +/** cs index for PV guest */ #define SEGSEL_PV_CS_IDX SEGSEL_SPARE0_IDX +/** ds for PV guest */ #define SEGSEL_PV_DS (SEGSEL_SPARE1 | SEGSEL_RPL3) +/** ds index for PV guest */ #define SEGSEL_PV_DS_IDX SEGSEL_SPARE1_IDX +/** fs for PV guest */ #define SEGSEL_PV_FS (SEGSEL_SPARE3 | SEGSEL_RPL3) +/** fs index for PV guest */ #define SEGSEL_PV_FS_IDX SEGSEL_SPARE3_IDX +/** VM limit for a PV guest */ #define PV_VM_LIMIT (va_t)(~(USER_MEM_START - 1)) +/** default memory size (MB) for a PV guest */ #define PV_DEFAULT_SIZE 24 +/** minimum memory size (MB) for a PV guest */ #define PV_MINIMUM_SIZE 20 +/** shadow page table structure */ typedef struct pv_pd_s { int refcount; - queue_t pv_link; - pa_t guest_pd; + queue_t pv_link; /** in pv_t's shadow_pds */ + pa_t guest_pd; /** physical address of original guest page table */ int wp; - pa_t cr3; - pa_t user_cr3; + pa_t cr3; /** shadow page table for PV kernel mode */ + pa_t user_cr3; /** shadow page table for user mode */ } pv_pd_t; +/** DPL_0 means DPL is 0 */ #define VIDT_DPL_0 0 +/** DPL_3 means DPL is 3 */ #define VIDT_DPL_3 3 +/** all bits used in dpl */ #define VIDT_DPL_MASK 3 +/** virtual idt entry structure */ typedef struct pv_idt_entry_s { va_t eip; - int desc; + int desc; /** currently only contains dpl */ } pv_idt_entry_t; +/** virtual IRQ table */ typedef struct pv_irq_s { int pending; int arg; } pv_irq_t; +/** index where fault starts */ #define PV_FAULT_START 0 +/** index where fault ends */ #define PV_FAULT_END 20 +/** index where IRQ starts */ #define PV_IRQ_START 32 +/** index where IRQ ends */ #define PV_IRQ_END 34 +/** index where syscall area 1 starts */ #define PV_SYSCALL_1_START 65 +/** index where syscall area 1 ends */ #define PV_SYSCALL_1_END 117 +/** index where syscall area 2 starts */ #define PV_SYSCALL_2_START 128 +/** index where syscall area 2 ends */ #define PV_SYSCALL_2_END 135 +/** virtual idt structure */ typedef struct pv_idt_s { - pv_idt_entry_t fault[PV_FAULT_END - PV_FAULT_START]; - pv_idt_entry_t irq[PV_IRQ_END - PV_IRQ_START]; - pv_irq_t pending_irq[PV_IRQ_END - PV_IRQ_START]; + pv_idt_entry_t fault_irq[PV_IRQ_END - PV_FAULT_START]; + pv_irq_t pending_irq[PV_IRQ_END - + PV_IRQ_START]; /** pending keyboard/timer IRQ */ pv_idt_entry_t syscall_1[PV_SYSCALL_1_END - PV_SYSCALL_1_START]; pv_idt_entry_t syscall_2[PV_SYSCALL_2_END - PV_SYSCALL_2_START]; } pv_idt_t; +/** PV control block structure */ typedef struct pv_s { int n_pages; pa_t mem_base; @@ -76,9 +110,12 @@ typedef struct pv_s { queue_t* shadow_pds; pv_idt_t vidt; va_t vesp0; - queue_t pts_link; + queue_t pts_link; /** in pts_t's pvs */ } pv_t; +/** + * @brief initialize PV system + */ void pv_init(); struct process_s; @@ -86,25 +123,44 @@ typedef struct process_s process_t; struct thread_s; typedef struct thread_s thread_t; +/** + * @brief create a PV guest + * @param t thread control block + * @param elf the guest kernel + * @param exe name of guest kernel file + * @param mem_size size of guest kernel memory + * @return the guest kernel thread, NULL on failure + */ thread_t* create_pv_process(thread_t* t, simple_elf_t* elf, char* exe, va_size_t mem_size); +/** + * @brief block interrupt for a PV guest + * @param pv PV control block for PV guest + */ static inline void pv_mask_interrupt(pv_t* pv) { pv->vif = 0; } +/** + * @brief unblock interrupt for a PV guest + * @param pv PV control block for PV guest + */ static inline void pv_unmask_interrupt(pv_t* pv) { pv->vif = EFL_IF; } +/** + * @brief find a vidt entry for a interrupt index + * @param pv PV control block for PV guest + * @param index interrupt index + * @return vidt entry, NULL on failure + */ static inline pv_idt_entry_t* pv_classify_interrupt(pv_t* pv, int index) { - if (index >= PV_FAULT_START && index < PV_FAULT_END) { - return &pv->vidt.fault[index - PV_FAULT_START]; - } - if (index >= PV_IRQ_START && index < PV_IRQ_END) { - return &pv->vidt.irq[index - PV_IRQ_START]; + if (index >= PV_FAULT_START && index < PV_IRQ_END) { + return &pv->vidt.fault_irq[index - PV_FAULT_START]; } if (index >= PV_SYSCALL_1_START && index < PV_SYSCALL_1_END) { return &pv->vidt.syscall_1[index - PV_SYSCALL_1_START]; @@ -115,24 +171,73 @@ static inline pv_idt_entry_t* pv_classify_interrupt(pv_t* pv, int index) { return NULL; } +/** + * @brief destroy a pv control block + * @param pv PV control block for PV guest + */ void destroy_pv(pv_t* pv); +/** + * @brief kill current PV guest and print a reason + * @param reason reason + */ void pv_die(char* reason); +/** + * @brief switch PV guest to kernel/user mode + * @param p process block of PV guest + * @param kernelmode is switching to kernel mode? + */ void pv_switch_mode(process_t* p, int kernelmode); +/** + * @brief load a shadow page table + * @param p process block of PV guest + * @param pv_pd shadow page table + */ void pv_select_pd(process_t* p, pv_pd_t* pv_pd); +/** + * @brief handel a fault happened when PV guest is running + * @param frame fault frame + * @param t PV guest thread + */ void pv_handle_fault(ureg_t* frame, thread_t* t); +/** + * @brief Pend an IRQ request to PV guest + * @param pv PV control block for PV guest + * @param index IRQ index + * @param arg a custom arg to push to PV guest kernel stack + */ void pv_pend_irq(pv_t* pv, int index, int arg); struct stack_frame_s; typedef struct stack_frame_s stack_frame_t; + +/** + * @brief try to inject an IRQ to PV guest, or mark it as pending if the guest + * is currently blocking interrupt + * @param f stack frame of PV guest + * @param index IRQ index + * @param arg a custom arg to push to PV guest kernel stack + */ int pv_inject_irq(stack_frame_t* f, int index, int arg); +/** + * @brief check if there is a pending IRQ and inject it if one exists + * @param f stack frame of PV guest + */ void pv_check_pending_irq(stack_frame_t* f); +/** + * @brief arrange the stack layout for injecting an interrupt (fault/IRQ) + * @param t PV guest thread + * @param pv PV control block for PV guest + * @param f stack frame of PV guest + * @param arg a custom arg to push to PV guest kernel stack + * @param eip guest handler address + */ void pv_inject_interrupt(thread_t* t, pv_t* pv, stack_frame_t* f, diff --git a/kern/inc/timer.h b/kern/inc/timer.h index 759cf9e..64c5011 100644 --- a/kern/inc/timer.h +++ b/kern/inc/timer.h @@ -21,6 +21,9 @@ extern heap_t timers; */ void timer_init(); +/** + * @brief switch to LAPIC timer + */ void setup_lapic_timer(); #endif diff --git a/kern/inc/toad.h b/kern/inc/toad.h index f0dfbf5..c206340 100644 --- a/kern/inc/toad.h +++ b/kern/inc/toad.h @@ -1,8 +1,9 @@ #ifndef _TOAD_H #define _TOAD_H -extern - +/** + * @brief print the elder to show that we have started + */ void print_toad(); #endif diff --git a/kern/interrupt.c b/kern/interrupt.c index ba08bbd..814a2b6 100644 --- a/kern/interrupt.c +++ b/kern/interrupt.c @@ -231,32 +231,113 @@ void sys_readfile(); */ void sys_swexn(); +/** + * @brief syscall 67 entry + */ void sys_67(); +/** + * @brief syscall 86 entry + */ void sys_86(); +/** + * @brief syscall 97 entry + */ void sys_97(); +/** + * @brief syscall 99 entry + */ void sys_99(); +/** + * @brief syscall 100 entry + */ void sys_100(); +/** + * @brief syscall 101 entry + */ void sys_101(); +/** + * @brief syscall 102 entry + */ void sys_102(); +/** + * @brief syscall 103 entry + */ void sys_103(); +/** + * @brief syscall 104 entry + */ void sys_104(); +/** + * @brief syscall 105 entry + */ void sys_105(); +/** + * @brief syscall 106 entry + */ void sys_106(); +/** + * @brief syscall 107 entry + */ void sys_107(); +/** + * @brief syscall 108 entry + */ void sys_108(); +/** + * @brief syscall 109 entry + */ void sys_109(); +/** + * @brief syscall 110 entry + */ void sys_110(); +/** + * @brief syscall 111 entry + */ void sys_111(); +/** + * @brief syscall 112 entry + */ void sys_112(); +/** + * @brief syscall 113 entry + */ void sys_113(); +/** + * @brief syscall 114 entry + */ void sys_114(); +/** + * @brief syscall 115 entry + */ void sys_115(); +/** + * @brief syscall 128 entry + */ void sys_128(); +/** + * @brief syscall 129 entry + */ void sys_129(); +/** + * @brief syscall 130 entry + */ void sys_130(); +/** + * @brief syscall 131 entry + */ void sys_131(); +/** + * @brief syscall 132 entry + */ void sys_132(); +/** + * @brief syscall 133 entry + */ void sys_133(); +/** + * @brief syscall 134 entry + */ void sys_134(); /** @@ -264,6 +345,9 @@ void sys_134(); */ void sys_nonexist(); +/** + * @brief hypercall entry + */ void sys_hvcall(); /** index of first syscall */ @@ -447,6 +531,12 @@ void handle_fault(ureg_t* frame) { handle_user_fault(frame, current); } +/** + * @brief handle a ZFOD caused fault + * @param frame ureg registers + * @param t current thread + * @return -1 if not ZFOD fault, 0 for success + */ static int handle_zfod(ureg_t* frame, thread_t* t) { int result = -1; process_t* p = t->process; @@ -470,6 +560,11 @@ static int handle_zfod(ureg_t* frame, thread_t* t) { return result; } +/** + * @brief handle a kernel mode fault + * @param frame ureg registers + * @param t current thread + */ static void handle_kernel_fault(ureg_t* frame, thread_t* t) { /* recover from accessing user memory */ if ((frame->cause == SWEXN_CAUSE_PAGEFAULT || @@ -480,10 +575,15 @@ static void handle_kernel_fault(ureg_t* frame, thread_t* t) { } /* all other non recoverable fault */ dump_fault(frame); - while (1) { - } + do { + } while (1); } +/** + * @brief handle user mode fault + * @param frame ureg registers + * @param t current thread + */ static void handle_user_fault(ureg_t* frame, thread_t* t) { /* send to user swexn */ if (t->eip3 != 0 && t->df3 == 0) { diff --git a/kern/kernel.c b/kern/kernel.c index bd675a5..6168224 100644 --- a/kern/kernel.c +++ b/kern/kernel.c @@ -33,8 +33,6 @@ #include <timer.h> #include <toad.h> -void print_toad(); - /** * @brief entry for a cpu core * @param cpuid cpuid @@ -73,6 +71,7 @@ int kernel_main(mbinfo_t* mbinfo, int argc, char** argv, char** envp) { const char* init_args[] = {INIT_NAME}; thread_t* init = create_process(INIT_PID, INIT_NAME, 1, init_args); + assert(init != NULL); init_process = init->process; add_thread(init); insert_ready_tail(init); @@ -103,6 +102,7 @@ static void kernel_smp_entry(int cpuid) { static void kernel_smp_main() { const char* idle_args[] = {IDLE_NAME}; thread_t* idle = create_process(IDLE_PID, IDLE_NAME, 1, idle_args); + assert(idle != NULL); set_idle(idle); while (1) { @@ -45,7 +45,7 @@ static unsigned char* user_page_bitmap; /** minimum size of last bin */ #define LAST_BIN_SIZE (1 << (NUM_BINS - 1)) /** bins for free chunks */ -static pa_t bins[9]; +static pa_t bins[NUM_BINS]; mutex_t mm_lock = MUTEX_INIT; @@ -38,6 +38,7 @@ a_char_on_screen_t (*console_mem)[CONSOLE_WIDTH] = pts_t* active_pts = NULL; spl_t pts_lock = SPL_INIT; +/** all pts structures */ queue_t* all_pts = NULL; pts_t kernel_pts; @@ -88,6 +89,7 @@ void switch_pts(pts_t* new_pts) { /** * @brief Move the cursor to a position. Position is checked before calling this * function + * @param pts pts * @param x x * @param y y */ @@ -332,11 +332,12 @@ int pv_inject_irq(stack_frame_t* f, int index, int arg) { if (pv == NULL) { return -1; } + /** IRQ happens in host kernel mode or PV guest blocks interrupt */ if (f->cs != SEGSEL_PV_CS || (pv->vif & EFL_IF) == 0) { pv_pend_irq(pv, index, arg); return 0; } - pv_idt_entry_t* idt = &pv->vidt.irq[index - PV_IRQ_START]; + pv_idt_entry_t* idt = &pv->vidt.fault_irq[index]; if (idt->eip == 0) { goto no_idt_handler; } @@ -359,11 +360,11 @@ void pv_check_pending_irq(stack_frame_t* f) { int i; for (i = 0; i < (PV_IRQ_END - PV_IRQ_START); i++) { if (vidt->pending_irq[i].pending != 0) { - if (vidt->irq[i].eip == 0) { + if (vidt->fault_irq[i + PV_IRQ_START].eip == 0) { goto no_idt_handler; } pv_inject_interrupt(t, pv, f, vidt->pending_irq[i].arg, - vidt->irq[i].eip); + vidt->fault_irq[i + PV_IRQ_START].eip); vidt->pending_irq[i].pending = 0; restore_if(old_if); return; diff --git a/kern/sched.c b/kern/sched.c index f797409..21b2c90 100644 --- a/kern/sched.c +++ b/kern/sched.c @@ -358,6 +358,7 @@ void destroy_thread(thread_t* t) { free_user_pages(r->paddr, r->size / PAGE_SIZE); } vector_free(&p->regions); + /** PV guests' page tables are managed by pv_pd_t */ if (p->pv == NULL) { destroy_pd(p->cr3); } else { @@ -726,6 +727,7 @@ void kill_current() { free_user_pages(r->paddr, r->size / PAGE_SIZE); } vector_free(&p->regions); + /** PV guests' page tables are managed by pv_pd_t */ if (p->pv == NULL) { destroy_pd(old_cr3); } else { diff --git a/kern/syscall_asm.S b/kern/syscall_asm.S index d246954..34b08f4 100644 --- a/kern/syscall_asm.S +++ b/kern/syscall_asm.S @@ -106,6 +106,9 @@ sys_\name: jmp return_to_user /* check pending exit before iret */ .endm +/* some ABIs do not place syscall index in a register so we + * need to set different entries for the syscalls + */ NONEXIST_SYSCALL 67 0x43 NONEXIST_SYSCALL 86 0x56 NONEXIST_SYSCALL 97 0x61 diff --git a/kern/timer.c b/kern/timer.c index 0d623ae..387c5f9 100644 --- a/kern/timer.c +++ b/kern/timer.c @@ -40,9 +40,6 @@ void timer_test_handler(); void timer_init() { /* use 10x slower frequency for APIC timer testing */ int counter = TIMER_RATE / (TIMER_FREQ / 10); - outb(TIMER_MODE_IO_PORT, TIMER_ONE_SHOT); - outb(TIMER_PERIOD_IO_PORT, counter & 0xFF); - outb(TIMER_PERIOD_IO_PORT, (counter >> 8) & 0xFF); if (heap_init(&timers) != 0) { panic("no space to initialize timer heap"); } @@ -70,6 +67,7 @@ void timer_init() { } } + /* 10 10x slow tests to calculate LAPIC frequency */ lapic_dt = (0xffffffff - lapic_read(LAPIC_TIMER_CUR)) / 100; lapic_write(LAPIC_TIMER_INIT, 0); idt[TIMER_IDT_ENTRY] = old_idt; diff --git a/kern/toad.c b/kern/toad.c index 7288375..32faf51 100644 --- a/kern/toad.c +++ b/kern/toad.c @@ -1,6 +1,7 @@ #include <pts.h> #include <sched.h> +/* https://en.wikipedia.org/wiki/Toad_worship */ const char toad[] = "..:. ......::.. ..^7JYYJJJJJYJJJJ??7~^:.. ^~^^:........ " " " |
