diff options
| author | Hanjie Wu <hanjiew@andrew.cmu.edu> | 2023-04-24 03:51:54 -0400 |
|---|---|---|
| committer | Hanjie Wu <hanjiew@andrew.cmu.edu> | 2023-04-24 03:55:02 -0400 |
| commit | 6b13d5d9b1ff1cb38bb50e918e51a241a225f8da (patch) | |
| tree | 90e8e5da37402975d769184aeb4b51fa13b610f3 | |
| parent | e021b8f12ad129c0bdbda3111bb93a170e21ae41 (diff) | |
timer
| -rw-r--r-- | config.mk | 2 | ||||
| -rw-r--r-- | kern/hvcall.c | 10 | ||||
| -rw-r--r-- | kern/inc/interrupt.h | 54 | ||||
| -rw-r--r-- | kern/inc/paging.h | 3 | ||||
| -rw-r--r-- | kern/inc/timer.h | 2 | ||||
| -rw-r--r-- | kern/interrupt.c | 50 | ||||
| -rw-r--r-- | kern/kernel.c | 11 | ||||
| -rw-r--r-- | kern/paging.c | 2 | ||||
| -rw-r--r-- | kern/pts.c | 1 | ||||
| -rw-r--r-- | kern/sched.c | 1 | ||||
| -rw-r--r-- | kern/timer.c | 44 | ||||
| -rw-r--r-- | kern/timer_asm.S | 18 |
12 files changed, 133 insertions, 65 deletions
@@ -165,7 +165,7 @@ KERNEL_OBJS = pts.o kernel.o loader.o malloc_wrappers.o sync_asm.o \ mm.o asm_instr.o sched.o sched_asm.o syscall_asm.o interrupt.o \ paging.o timer.o interrupt_asm.o usermem.o syscall_process.o \ syscall_memory.o syscall_thread.o common.o sync.o syscall_io.o \ - usermem_asm.o syscall_misc.o pv.o hvcall.o toad.o + usermem_asm.o syscall_misc.o pv.o hvcall.o toad.o timer_asm.o ########################################################################### # WARNING: Do not put **test** programs into the REQPROGS variables. Your diff --git a/kern/hvcall.c b/kern/hvcall.c index c57b668..d387771 100644 --- a/kern/hvcall.c +++ b/kern/hvcall.c @@ -316,6 +316,7 @@ static pv_pd_t* translate_pv_pd(pv_t* pv, pa_t pd, int wp) { } pt_pa += pv->mem_base; page_table_t* pt = (page_table_t*)map_phys_page(pt_pa, NULL); + int old_pde_us = (old_pde & (1 << PTE_US_SHIFT)); int j; for (j = 0; j < NUM_PAGE_ENTRY; j++) { pte_t old_pte = (*pt)[j]; @@ -340,7 +341,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)); } - if (old_us != 0) { + if ((old_us & old_pde_us) != 0) { new_user_mask = ((1 << PTE_P_SHIFT) | old_rw | (PTE_USER << PTE_US_SHIFT)); } else { @@ -543,7 +544,7 @@ static void hvcall_print(stack_frame_t* f) { if (copy_from_user(esp, sizeof(int), &len) != 0) { goto read_arg_fail; } - if (len < 0) { + if (len < 0 || len > HV_PRINT_MAX) { goto bad_length; } if (copy_from_user(esp + sizeof(va_t), sizeof(va_t), &base) != 0) { @@ -659,6 +660,9 @@ static void hvcall_print_at(stack_frame_t* f) { if (copy_from_user(esp + 4 * sizeof(va_t), sizeof(int), &color) != 0) { goto read_arg_fail; } + if (len < 0 || len > HV_PRINT_MAX) { + goto bad_length; + } pts_t* pts = get_current()->pts; mutex_lock(&pts->lock); int result = pts_print_at(pts, len, base, row, col, color); @@ -670,6 +674,8 @@ static void hvcall_print_at(stack_frame_t* f) { print_fail: pv_die("Bad argument"); +bad_length: + pv_die("Bad buffer length"); read_arg_fail: pv_die("Bad argument address"); } diff --git a/kern/inc/interrupt.h b/kern/inc/interrupt.h index 7c15ccd..f90ee04 100644 --- a/kern/inc/interrupt.h +++ b/kern/inc/interrupt.h @@ -9,6 +9,10 @@ #ifndef _INTERRUPT_H_ #define _INTERRUPT_H_ +#include <x86/seg.h> + +#include <paging.h> + /** * IRQ # of timer */ @@ -20,6 +24,56 @@ #define KBD_IRQ 1 /** + * @brief an idt entry + */ +typedef struct idt_s { + unsigned long lo; + unsigned long hi; +} idt_t; + +/** means this entry requires ring 0 privilige */ +#define IDT_DPL_KERNEL 0 +/** means this entry requires ring 3 privilige */ +#define IDT_DPL_USER 3 +/** means this entry is valid */ +#define IDT_P 1 +/** means this entry is a 32 bit interrupt */ +#define IDT_TYPE_I32 0xe +/** means this entry is a 32 bit trap */ +#define IDT_TYPE_T32 0xf + +/** P bit's position */ +#define IDT_P_SHIFT (47 - 32) +/** DPL's position */ +#define IDT_DPL_SHIFT (45 - 32) +/** TYPE's position */ +#define IDT_TYPE_SHIFT (40 - 32) +/** CS's position */ +#define IDT_CS_SHIFT 16 + +/** EIP's high part's bits */ +#define IDT_EIP_HI_MASK 0xffff0000 +/** EIP's low part's bits */ +#define IDT_EIP_LO_MASK 0x0000ffff + +#define IDT_FAULT_15 15 + +/** + * @brief create an idt entry + * @param eip eip + * @param type type + * @param dpl dpl + * @return the idt entry + */ +static inline idt_t make_idt(va_t eip, int type, int dpl) { + idt_t idt; + idt.hi = ((eip & IDT_EIP_HI_MASK) | (IDT_P << IDT_P_SHIFT) | + (dpl << IDT_DPL_SHIFT) | (type << IDT_TYPE_SHIFT)); + idt.lo = ((SEGSEL_KERNEL_CS << IDT_CS_SHIFT) | (eip & IDT_EIP_LO_MASK)); + return idt; +} + +/** * @brief initialize idt */ void idt_init(); diff --git a/kern/inc/paging.h b/kern/inc/paging.h index 182f50f..de00981 100644 --- a/kern/inc/paging.h +++ b/kern/inc/paging.h @@ -56,6 +56,7 @@ typedef unsigned int reg_t; /** means a page can only be accessed in ring 0 */ #define PTE_SUPERVISOR 0 #define PTE_PCD 1 +#define PTE_PWT 1 /** means a page's TLB entry should not be flushed on switching cr3 */ #define PTE_G 1 @@ -65,6 +66,8 @@ typedef unsigned int reg_t; #define PTE_RW_SHIFT 1 /** USER/SUPERVISOR bit's position */ #define PTE_US_SHIFT 2 +/** PWT bit's position */ +#define PTE_PWT_SHIFT 3 /** PCD bit's position */ #define PTE_PCD_SHIFT 4 /** G bit's position */ diff --git a/kern/inc/timer.h b/kern/inc/timer.h index 8d6368e..759cf9e 100644 --- a/kern/inc/timer.h +++ b/kern/inc/timer.h @@ -21,4 +21,6 @@ extern heap_t timers; */ void timer_init(); +void setup_lapic_timer(); + #endif diff --git a/kern/interrupt.c b/kern/interrupt.c index fd6839a..ba08bbd 100644 --- a/kern/interrupt.c +++ b/kern/interrupt.c @@ -31,56 +31,6 @@ #include <timer.h> #include <usermem.h> -/** means this entry requires ring 0 privilige */ -#define IDT_DPL_KERNEL 0 -/** means this entry requires ring 3 privilige */ -#define IDT_DPL_USER 3 -/** means this entry is valid */ -#define IDT_P 1 -/** means this entry is a 32 bit interrupt */ -#define IDT_TYPE_I32 0xe -/** means this entry is a 32 bit trap */ -#define IDT_TYPE_T32 0xf - -/** P bit's position */ -#define IDT_P_SHIFT (47 - 32) -/** DPL's position */ -#define IDT_DPL_SHIFT (45 - 32) -/** TYPE's position */ -#define IDT_TYPE_SHIFT (40 - 32) -/** CS's position */ -#define IDT_CS_SHIFT 16 - -/** EIP's high part's bits */ -#define IDT_EIP_HI_MASK 0xffff0000 -/** EIP's low part's bits */ -#define IDT_EIP_LO_MASK 0x0000ffff - -#define IDT_FAULT_15 15 - -/** - * @brief an idt entry - */ -typedef struct idt_s { - unsigned long lo; - unsigned long hi; -} idt_t; - -/** - * @brief create an idt entry - * @param eip eip - * @param type type - * @param dpl dpl - * @return the idt entry - */ -static inline idt_t make_idt(va_t eip, int type, int dpl) { - idt_t idt; - idt.hi = ((eip & IDT_EIP_HI_MASK) | (IDT_P << IDT_P_SHIFT) | - (dpl << IDT_DPL_SHIFT) | (type << IDT_TYPE_SHIFT)); - idt.lo = ((SEGSEL_KERNEL_CS << IDT_CS_SHIFT) | (eip & IDT_EIP_LO_MASK)); - return idt; -} - /** * @brief DE handler entry */ diff --git a/kern/kernel.c b/kern/kernel.c index 057b6fe..bd675a5 100644 --- a/kern/kernel.c +++ b/kern/kernel.c @@ -55,6 +55,7 @@ static void kernel_smp_main(); int kernel_main(mbinfo_t* mbinfo, int argc, char** argv, char** envp) { int smp_good = (smp_init(mbinfo) == 0); paging_init(); + setup_pts(); percpu_t percpu; setup_percpu(&percpu); thread_t kthread; @@ -62,12 +63,12 @@ int kernel_main(mbinfo_t* mbinfo, int argc, char** argv, char** envp) { setup_kth(&kthread, &kprocess); set_mapped_phys_page(mapped_phys_pages); set_mapped_phys_page_pte(mapped_phys_page_ptes); - setup_pts(); idt_init(); mm_init(); - timer_init(); pv_init(); + timer_init(); + print_toad(); const char* init_args[] = {INIT_NAME}; @@ -76,11 +77,12 @@ int kernel_main(mbinfo_t* mbinfo, int argc, char** argv, char** envp) { add_thread(init); insert_ready_tail(init); - if (smp_good && smp_num_cpus() > 1 && 0) { - /* SMP not enabled */ + if (smp_good && smp_num_cpus() > 1) { + set_cr3((pa_t)&kernel_pd); smp_boot(kernel_smp_entry); } + setup_lapic_timer(); kernel_smp_main(); return -1; } @@ -94,6 +96,7 @@ static void kernel_smp_entry(int cpuid) { setup_kth(&kthread, &kprocess); set_mapped_phys_page(mapped_phys_pages + cpuid * PAGE_SIZE); set_mapped_phys_page_pte(mapped_phys_page_ptes + cpuid); + setup_lapic_timer(); kernel_smp_main(); } diff --git a/kern/paging.c b/kern/paging.c index eb81dd9..73c86da 100644 --- a/kern/paging.c +++ b/kern/paging.c @@ -61,7 +61,7 @@ void paging_init() { pte_t* lapic_pte = (pte_t*)kernel_pt + (LAPIC_VIRT_BASE / PAGE_SIZE); *lapic_pte = (make_pte(lapic_pa, PTE_G, PTE_SUPERVISOR, PTE_RW, PTE_PRESENT) | - (PTE_PCD << PTE_PCD_SHIFT)); + (PTE_PWT << PTE_PWT_SHIFT) | (PTE_PCD << PTE_PCD_SHIFT)); set_cr4(get_cr4() | CR4_PSE | CR4_PGE); set_cr3((uint32_t)kernel_pd); @@ -44,7 +44,6 @@ pts_t kernel_pts; void setup_pts() { pts_init(&kernel_pts); - get_current()->pts = &kernel_pts; kernel_pts.refcount++; /* kernel's refcount for all kths */ active_pts = &kernel_pts; } diff --git a/kern/sched.c b/kern/sched.c index fbb5c6c..7764c26 100644 --- a/kern/sched.c +++ b/kern/sched.c @@ -88,6 +88,7 @@ void setup_kth(thread_t* kthread, process_t* kprocess) { kprocess->refcount = 1; kprocess->cr3 = (pa_t)kernel_pd; kthread->process = kprocess; + kthread->pts = active_pts; set_current(kthread); set_kthread(kthread); } diff --git a/kern/timer.c b/kern/timer.c index a202cb5..53fd576 100644 --- a/kern/timer.c +++ b/kern/timer.c @@ -10,8 +10,10 @@ #include <stdio.h> #include <string.h> +#include <apic.h> #include <assert.h> #include <x86/asm.h> +#include <x86/idt.h> #include <x86/interrupt_defines.h> #include <x86/timer_defines.h> @@ -26,19 +28,49 @@ spl_t timer_lock = SPL_INIT; heap_t timers; -/* we want a 2ms thread switch but since sometimes interrupts are disabled, we - * set a higher rate to compensate this - */ -#define TIMER_FREQ 1000 +static uint32_t lapic_dt; + +/* 2ms */ +#define TIMER_FREQ 500 + +int timer_test_status; + +void timer_test_handler(); void timer_init() { - int counter = TIMER_RATE / TIMER_FREQ; + /* use 10x slower frequency for APIC timer testing */ + int counter = TIMER_RATE / (TIMER_FREQ / 10); outb(TIMER_MODE_IO_PORT, TIMER_SQUARE_WAVE); 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"); } + idt_t* idt = (idt_t*)idt_base(); + idt_t old_idt = idt[TIMER_IDT_ENTRY]; + idt[TIMER_IDT_ENTRY] = + make_idt((va_t)timer_test_handler, IDT_TYPE_I32, IDT_DPL_KERNEL); + + lapic_write(LAPIC_LVT_TIMER, (LAPIC_ONESHOT | TIMER_IDT_ENTRY)); + lapic_write(LAPIC_TIMER_DIV, LAPIC_X1); + lapic_write(LAPIC_TIMER_INIT, 0xffffffff); + + timer_test_status = 10; + enable_interrupts(); + while (timer_test_status != 0) { + } + disable_interrupts(); + + lapic_dt = (0xffffffff - lapic_read(LAPIC_TIMER_CUR)) / 100; + lapic_write(LAPIC_TIMER_INIT, 0); + idt[TIMER_IDT_ENTRY] = old_idt; +} + +void setup_lapic_timer() { + lapic_write(LAPIC_LVT_TIMER, (LAPIC_PERIODIC | TIMER_IDT_ENTRY)); + lapic_write(LAPIC_TIMER_DIV, LAPIC_X1); + lapic_write(LAPIC_TIMER_INIT, lapic_dt); + outb(TIMER_MODE_IO_PORT, TIMER_ONE_SHOT); } /** @@ -61,7 +93,7 @@ static void check_timers() { } void timer_handler_real(stack_frame_t* f) { - pic_acknowledge(TIMER_IRQ); + apic_eoi(); ticks++; check_timers(); pv_inject_irq(f, TIMER_IDT_ENTRY, 0); diff --git a/kern/timer_asm.S b/kern/timer_asm.S new file mode 100644 index 0000000..cf4c76f --- /dev/null +++ b/kern/timer_asm.S @@ -0,0 +1,18 @@ +#include <x86/seg.h> +#include <x86/interrupt_defines.h> +#include <x86/timer_defines.h> + +.text + +.global timer_test_handler +.type timer_test_handler, %function +timer_test_handler: + push %eax + mov timer_test_status, %eax + dec %eax + mov %eax, timer_test_status + mov $INT_ACK_CURRENT, %al + mov $INT_CTL_PORT, %dx + outb %al, %dx + pop %eax + iret |
