summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kern/hvcall.c105
-rw-r--r--kern/inc/console.h15
-rw-r--r--kern/inc/pts.h40
-rw-r--r--kern/inc/pv.h133
-rw-r--r--kern/inc/timer.h3
-rw-r--r--kern/inc/toad.h5
-rw-r--r--kern/interrupt.c104
-rw-r--r--kern/kernel.c4
-rw-r--r--kern/mm.c2
-rw-r--r--kern/pts.c2
-rw-r--r--kern/pv.c7
-rw-r--r--kern/sched.c2
-rw-r--r--kern/syscall_asm.S3
-rw-r--r--kern/timer.c4
-rw-r--r--kern/toad.c1
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) {
diff --git a/kern/mm.c b/kern/mm.c
index b553018..a1dfea6 100644
--- a/kern/mm.c
+++ b/kern/mm.c
@@ -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;
diff --git a/kern/pts.c b/kern/pts.c
index 9fdabf5..b11bee3 100644
--- a/kern/pts.c
+++ b/kern/pts.c
@@ -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
*/
diff --git a/kern/pv.c b/kern/pv.c
index e82973c..2b26ff9 100644
--- a/kern/pv.c
+++ b/kern/pv.c
@@ -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~^:.. ^~^^:........ "
" "