diff options
| author | Hanjie Wu <hanjiew@andrew.cmu.edu> | 2023-04-28 21:14:37 -0400 |
|---|---|---|
| committer | Hanjie Wu <hanjiew@andrew.cmu.edu> | 2023-04-28 21:14:37 -0400 |
| commit | 119b5e6fde37c53a5037a6ba959ba60c882bd6d0 (patch) | |
| tree | a41be842bfc966befb80324cc405414b35cf91d2 /kern/inc/pv.h | |
| parent | ff90341c64565ac7d8034d2f8cf460532a5b51fd (diff) | |
Diffstat (limited to 'kern/inc/pv.h')
| -rw-r--r-- | kern/inc/pv.h | 133 |
1 files changed, 119 insertions, 14 deletions
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, |
