diff options
| author | Hanjie Wu <hanjiew@andrew.cmu.edu> | 2023-04-24 00:02:27 -0400 |
|---|---|---|
| committer | Hanjie Wu <hanjiew@andrew.cmu.edu> | 2023-04-24 00:02:27 -0400 |
| commit | e021b8f12ad129c0bdbda3111bb93a170e21ae41 (patch) | |
| tree | 229879c8f03278388b2140ce5ce016c0354df0f0 | |
| parent | 4e6e2ced7f047a9a0439eb6d001b1a77daadfdff (diff) | |
new console
| -rw-r--r-- | config.mk | 2 | ||||
| -rw-r--r-- | kern/hvcall.c | 30 | ||||
| -rw-r--r-- | kern/inc/pts.h | 8 | ||||
| -rw-r--r-- | kern/inc/pv.h | 9 | ||||
| -rw-r--r-- | kern/inc/toad.h | 8 | ||||
| -rw-r--r-- | kern/interrupt.c | 6 | ||||
| -rw-r--r-- | kern/kernel.c | 4 | ||||
| -rw-r--r-- | kern/pts.c | 96 | ||||
| -rw-r--r-- | kern/pv.c | 16 | ||||
| -rw-r--r-- | kern/sched.c | 12 | ||||
| -rw-r--r-- | kern/syscall_asm.S | 1 | ||||
| -rw-r--r-- | kern/syscall_misc.c | 20 | ||||
| -rw-r--r-- | kern/toad.c | 9 | ||||
| -rw-r--r-- | user/libsyscall/syscall.S | 6 |
14 files changed, 184 insertions, 43 deletions
@@ -199,7 +199,7 @@ KERNEL_OBJS = pts.o kernel.o loader.o malloc_wrappers.o sync_asm.o \ exec_basic loader_test2 score yield_desc_mkrun \ exec_basic_helper make_crash shell \ exec_nonexist make_crash_helper slaughter \ - minclone_many + minclone_many new_shell ########################################################################### diff --git a/kern/hvcall.c b/kern/hvcall.c index e1f7f93..c57b668 100644 --- a/kern/hvcall.c +++ b/kern/hvcall.c @@ -24,11 +24,11 @@ #include <asm_instr.h> #include <assert.h> -#include <pts.h> #include <loader.h> #include <malloc.h> #include <mm.h> #include <paging.h> +#include <pts.h> #include <sched.h> #include <sync.h> #include <timer.h> @@ -642,8 +642,8 @@ static void hvcall_print_at(stack_frame_t* f) { reg_t esp = f->esp; int len; va_t base; - int row, col, old_row, old_col; - int color, old_color; + int row, col; + int color; if (copy_from_user(esp, sizeof(int), &len) != 0) { goto read_arg_fail; } @@ -661,28 +661,14 @@ static void hvcall_print_at(stack_frame_t* f) { } pts_t* pts = get_current()->pts; mutex_lock(&pts->lock); - pts_get_cursor(pts, &old_row, &old_col); - if (pts_set_cursor(pts, row, col) != 0) { - goto bad_pos; - } - pts_get_term_color(pts, &old_color); - if (pts_set_term_color(pts, color) != 0) { - goto bad_color; - } - if (print_buf_from_user(pts, base, len) != 0) { - goto bad_print; - } - pts_set_term_color(pts, old_color); - pts_set_cursor(pts, old_row, old_col); + int result = pts_print_at(pts, len, base, row, col, color); mutex_unlock(&pts->lock); + if (result != 0) { + goto print_fail; + } return; -bad_print: - pts_set_term_color(pts, old_color); -bad_color: - pts_set_cursor(pts, old_row, old_col); -bad_pos: - mutex_unlock(&pts->lock); +print_fail: pv_die("Bad argument"); read_arg_fail: pv_die("Bad argument address"); diff --git a/kern/inc/pts.h b/kern/inc/pts.h index c300fb9..4c0c9f9 100644 --- a/kern/inc/pts.h +++ b/kern/inc/pts.h @@ -65,6 +65,7 @@ typedef struct kbd_request_s { typedef struct pts_s { queue_t pts_link; + queue_t* pvs; int refcount; mutex_t lock; @@ -85,11 +86,14 @@ typedef struct pts_s { char chr_ring[CHR_RING_SIZE]; int chr_r_pos; int chr_w_pos; + int forward_tab; } pts_t; extern pts_t* active_pts; extern spl_t pts_lock; +void setup_pts(); + void pts_init(pts_t* pts); int putbyte(char ch); @@ -175,6 +179,8 @@ int pts_set_cursor(pts_t* pts, int row, int col); */ void pts_get_cursor(pts_t* pts, int* row, int* col); +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 len max length to read @@ -189,4 +195,6 @@ int do_readline(int len, va_t buf); */ int do_getchar(); +void switch_pts(pts_t* pts); + #endif /* _PTS_H */ diff --git a/kern/inc/pv.h b/kern/inc/pv.h index 123a127..c0708dc 100644 --- a/kern/inc/pv.h +++ b/kern/inc/pv.h @@ -76,6 +76,7 @@ typedef struct pv_s { queue_t* shadow_pds; pv_idt_t vidt; va_t vesp0; + queue_t pts_link; } pv_t; void pv_init(); @@ -124,13 +125,19 @@ void pv_select_pd(process_t* p, pv_pd_t* pv_pd); void pv_handle_fault(ureg_t* frame, thread_t* t); +void pv_pend_irq(pv_t* pv, int index, int arg); + struct stack_frame_s; typedef struct stack_frame_s stack_frame_t; int pv_inject_irq(stack_frame_t* f, int index, int arg); void pv_check_pending_irq(stack_frame_t* f); -void pv_inject_interrupt(thread_t* t, pv_t* pv, stack_frame_t* f, int arg, va_t eip); +void pv_inject_interrupt(thread_t* t, + pv_t* pv, + stack_frame_t* f, + int arg, + va_t eip); typedef struct pv_frame_s { reg_t cr2; diff --git a/kern/inc/toad.h b/kern/inc/toad.h new file mode 100644 index 0000000..f0dfbf5 --- /dev/null +++ b/kern/inc/toad.h @@ -0,0 +1,8 @@ +#ifndef _TOAD_H +#define _TOAD_H + +extern + +void print_toad(); + +#endif diff --git a/kern/interrupt.c b/kern/interrupt.c index 467c7c9..fd6839a 100644 --- a/kern/interrupt.c +++ b/kern/interrupt.c @@ -261,6 +261,10 @@ void sys_halt(); */ void sys_task_vanish(); /** + * @brief new_console() syscall entry + */ +void sys_new_console(); +/** * @brief set_status() syscall entry */ void sys_set_status(); @@ -389,6 +393,8 @@ void idt_init() { idt[86] = make_idt((va_t)sys_86, IDT_TYPE_T32, IDT_DPL_USER); idt[TASK_VANISH_INT] = make_idt((va_t)sys_task_vanish, IDT_TYPE_T32, IDT_DPL_USER); + idt[NEW_CONSOLE_INT] = + make_idt((va_t)sys_new_console, IDT_TYPE_T32, IDT_DPL_USER); idt[SET_STATUS_INT] = make_idt((va_t)sys_set_status, IDT_TYPE_T32, IDT_DPL_USER); idt[VANISH_INT] = make_idt((va_t)sys_vanish, IDT_TYPE_T32, IDT_DPL_USER); diff --git a/kern/kernel.c b/kern/kernel.c index c5b60c7..057b6fe 100644 --- a/kern/kernel.c +++ b/kern/kernel.c @@ -24,13 +24,14 @@ #include <assert.h> #include <common.h> -#include <pts.h> #include <interrupt.h> #include <mm.h> #include <paging.h> +#include <pts.h> #include <pv.h> #include <sched.h> #include <timer.h> +#include <toad.h> void print_toad(); @@ -61,6 +62,7 @@ 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(); @@ -40,6 +40,15 @@ pts_t* active_pts = NULL; spl_t pts_lock = SPL_INIT; queue_t* all_pts = NULL; +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; +} + void pts_init(pts_t* pts) { pts->cur_x = pts->cur_y = 0; pts->cur_color = DEFAULT_COLOR; @@ -52,10 +61,29 @@ void pts_init(pts_t* pts) { pts->input_cv = CV_INIT; pts->kh_r_pos = pts->kh_w_pos = 0; pts->chr_r_pos = pts->chr_w_pos = 0; + pts->forward_tab = 0; pts->lock = MUTEX_INIT; + pts->pvs = NULL; pts->refcount = 0; - queue_insert_head(&all_pts, &pts->pts_link); + queue_insert_tail(&all_pts, &pts->pts_link); +} + +void switch_pts(pts_t* new_pts) { + int old_if = spl_lock(&pts_lock); + pts_t* pts = active_pts; + active_pts = new_pts; + if (pts->refcount == 0) { + queue_detach(&all_pts, &pts->pts_link); + sfree(pts, sizeof(pts_t)); + } + memcpy(console_mem, new_pts->mem, sizeof(new_pts->mem)); + int pos = new_pts->cur_y * CONSOLE_WIDTH + new_pts->cur_x; + outb(CRTC_IDX_REG, CRTC_CURSOR_LSB_IDX); + outb(CRTC_DATA_REG, pos & 0xff); + outb(CRTC_IDX_REG, CRTC_CURSOR_MSB_IDX); + outb(CRTC_DATA_REG, pos >> 8); + spl_unlock(&pts_lock, old_if); } /** @@ -117,6 +145,13 @@ static inline void draw_char(pts_t* pts, } int putbyte(char ch) { + if (active_pts == NULL) { + /* this only happens when panicking before setup_pts */ + active_pts = &kernel_pts; + pts_putbyte(&kernel_pts, ch); + active_pts = NULL; + return 0; + } return pts_putbyte(get_current()->pts, ch); } @@ -202,18 +237,71 @@ void pts_get_cursor(pts_t* pts, int* row, int* col) { *col = pts->cur_x; } +int pts_print_at(pts_t* pts, int len, va_t buf, int row, int col, int color) { + int old_row, old_col; + int old_color; + pts_get_cursor(pts, &old_row, &old_col); + if (pts_set_cursor(pts, row, col) != 0) { + goto bad_pos; + } + pts_get_term_color(pts, &old_color); + if (pts_set_term_color(pts, color) != 0) { + goto bad_color; + } + if (print_buf_from_user(pts, buf, len) != 0) { + goto bad_print; + } + pts_set_term_color(pts, old_color); + pts_set_cursor(pts, old_row, old_col); + return 0; + +bad_print: + pts_set_term_color(pts, old_color); +bad_color: + pts_set_cursor(pts, old_row, old_col); +bad_pos: + return -1; +} + /** * @brief keyboard inturrupt handler */ void kbd_handler_real(stack_frame_t* f) { unsigned char sc = inb(KEYBOARD_PORT); pic_acknowledge(KBD_IRQ); + pts_t* pts = active_pts; + int should_insert = 0; kh_type kh = process_scancode(sc); - if (pv_inject_irq(f, KEY_IDT_ENTRY, kh) == 0) { + if (KH_HASDATA(kh) && KH_ISMAKE(kh)) { + should_insert = 1; + if (KH_GETCHAR(kh) == KHE_TAB) { + if (KH_SHIFT(kh) != 0) { + if (pts->forward_tab == 0) { + pts->forward_tab = 1; + return; + } + /* else forward shift+tab to client */ + } else if (KH_CTL(kh) != 0) { + if (pts->forward_tab != 0) { + pts->forward_tab = 0; + return; + } + } else if (pts->forward_tab == 0) { + pts_t* new_pts = + queue_data(pts->pts_link.next, pts_t, pts_link); + if (new_pts != pts) { + switch_pts(new_pts); + } + return; + } + } + } + if (pts->pvs != NULL) { + pv_t* pv = queue_data(pts->pvs, pv_t, pts_link); + pv_pend_irq(pv, KEY_IDT_ENTRY, kh); return; } - pts_t* pts = active_pts; - if (KH_HASDATA(kh) && KH_ISMAKE(kh)) { + if (should_insert != 0) { int next_w_pos = (pts->kh_w_pos + 1) % KH_RING_SIZE; if (next_w_pos != pts->kh_r_pos) { pts->kh_ring[pts->kh_w_pos] = kh; @@ -85,6 +85,11 @@ thread_t* create_pv_process(thread_t* t, pv->shadow_pds = NULL; pv->vif = 0; memset(&pv->vidt, 0, sizeof(pv_idt_t)); + + mutex_lock(&t->pts->lock); + queue_insert_head(&t->pts->pvs, &pv->pts_link); + mutex_unlock(&t->pts->lock); + p->pv = pv; int n_bootmem_pages = mem_size / PAGE_SIZE; @@ -314,6 +319,13 @@ push_frame_fail: pv_die("Error when pushing interrupt frame to stack"); } +void pv_pend_irq(pv_t* pv, int index, int arg) { + pv_irq_t* irq = &pv->vidt.pending_irq[index - PV_IRQ_START]; + irq->pending = 1; + irq->arg = arg; + return; +} + int pv_inject_irq(stack_frame_t* f, int index, int arg) { thread_t* t = get_current(); pv_t* pv = t->process->pv; @@ -321,9 +333,7 @@ int pv_inject_irq(stack_frame_t* f, int index, int arg) { return -1; } if (f->cs != SEGSEL_PV_CS || (pv->vif & EFL_IF) == 0) { - pv_irq_t* irq = &pv->vidt.pending_irq[index - PV_IRQ_START]; - irq->pending = 1; - irq->arg = arg; + pv_pend_irq(pv, index, arg); return 0; } pv_idt_entry_t* idt = &pv->vidt.irq[index - PV_IRQ_START]; diff --git a/kern/sched.c b/kern/sched.c index 35e8a58..fbb5c6c 100644 --- a/kern/sched.c +++ b/kern/sched.c @@ -15,11 +15,11 @@ #include <x86/seg.h> #include <asm_instr.h> -#include <pts.h> #include <loader.h> #include <malloc.h> #include <mm.h> #include <paging.h> +#include <pts.h> #include <pv.h> #include <sched.h> #include <sync.h> @@ -334,10 +334,13 @@ alloc_tcb_fail: } void destroy_thread(thread_t* t) { + process_t* p = t->process; mutex_lock(&t->pts->lock); t->pts->refcount--; + if (p->pv != NULL) { + queue_detach(&t->pts->pvs, &p->pv->pts_link); + } mutex_unlock(&t->pts->lock); - process_t* p = t->process; sfree(t->stack, K_STACK_SIZE); sfree(t, sizeof(thread_t)); mutex_lock(&p->refcount_lock); @@ -664,16 +667,19 @@ void kill_current() { spl_unlock(&ready_lock, old_if); } } + p = current->process; mutex_lock(¤t->pts->lock); current->pts->refcount--; + if (p->pv != NULL) { + queue_detach(¤t->pts->pvs, &p->pv->pts_link); + } mutex_unlock(¤t->pts->lock); if (current->rb_node.parent != NULL) { remove_thread(current); } - p = current->process; mutex_lock(&p->refcount_lock); p->refcount--; queue_detach(&p->threads, ¤t->process_link); diff --git a/kern/syscall_asm.S b/kern/syscall_asm.S index f3b3552..d246954 100644 --- a/kern/syscall_asm.S +++ b/kern/syscall_asm.S @@ -59,6 +59,7 @@ SYSCALL get_ticks 0x53 SYSCALL misbehave 0x54 SYSCALL halt 0x55 SYSCALL task_vanish 0x57 +SYSCALL new_console 0x58 SYSCALL set_status 0x59 SYSCALL vanish 0x60 SYSCALL readfile 0x62 diff --git a/kern/syscall_misc.c b/kern/syscall_misc.c index 8bcacf1..6bc91d6 100644 --- a/kern/syscall_misc.c +++ b/kern/syscall_misc.c @@ -29,6 +29,7 @@ #include <sched.h> #include <sync.h> #include <timer.h> +#include <toad.h> #include <usermem.h> /** @@ -159,3 +160,22 @@ static reg_t read_dot_file(va_t buf, int count, int offset) { } return (reg_t)written; } + +void sys_new_console_real(stack_frame_t* f) { + thread_t* t = get_current(); + pts_t* old_pts = t->pts; + pts_t* pts = smalloc(sizeof(pts_t)); + if (pts == NULL) { + f->eax = (reg_t)-1; + return; + } + pts_init(pts); + + pts->refcount++; + t->pts = pts; + mutex_lock(&old_pts->lock); + old_pts->refcount--; + mutex_unlock(&old_pts->lock); + switch_pts(pts); + print_toad(); +} diff --git a/kern/toad.c b/kern/toad.c index 96cf60f..7288375 100644 --- a/kern/toad.c +++ b/kern/toad.c @@ -57,14 +57,7 @@ const char toad[] = "........:^!J5PBBBBBB"; void print_toad() { - pts_t* pts = smalloc(sizeof(pts_t)); - pts_init(pts); - get_current()->pts = pts; - pts->refcount++; - - active_pts = pts; - pts->refcount++; - + pts_t* pts = get_current()->pts; pts_set_cursor(pts, 0, 0); pts_set_term_color(pts, FGND_WHITE | BGND_BLACK); pts_putbytes(pts, toad, sizeof(toad) - 1); diff --git a/user/libsyscall/syscall.S b/user/libsyscall/syscall.S index d661cf8..26eb59d 100644 --- a/user/libsyscall/syscall.S +++ b/user/libsyscall/syscall.S @@ -216,3 +216,9 @@ yield: mov 0x4(%esp), %esi int $YIELD_INT ret + +.global new_console + +new_console: + int $NEW_CONSOLE_INT + ret |
