summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHanjie Wu <hanjiew@andrew.cmu.edu>2023-04-24 00:02:27 -0400
committerHanjie Wu <hanjiew@andrew.cmu.edu>2023-04-24 00:02:27 -0400
commite021b8f12ad129c0bdbda3111bb93a170e21ae41 (patch)
tree229879c8f03278388b2140ce5ce016c0354df0f0
parent4e6e2ced7f047a9a0439eb6d001b1a77daadfdff (diff)
new console
-rw-r--r--config.mk2
-rw-r--r--kern/hvcall.c30
-rw-r--r--kern/inc/pts.h8
-rw-r--r--kern/inc/pv.h9
-rw-r--r--kern/inc/toad.h8
-rw-r--r--kern/interrupt.c6
-rw-r--r--kern/kernel.c4
-rw-r--r--kern/pts.c96
-rw-r--r--kern/pv.c16
-rw-r--r--kern/sched.c12
-rw-r--r--kern/syscall_asm.S1
-rw-r--r--kern/syscall_misc.c20
-rw-r--r--kern/toad.c9
-rw-r--r--user/libsyscall/syscall.S6
14 files changed, 184 insertions, 43 deletions
diff --git a/config.mk b/config.mk
index 7870559..222453b 100644
--- a/config.mk
+++ b/config.mk
@@ -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();
diff --git a/kern/pts.c b/kern/pts.c
index 2d51620..2964a25 100644
--- a/kern/pts.c
+++ b/kern/pts.c
@@ -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;
diff --git a/kern/pv.c b/kern/pv.c
index 6e245fd..e82973c 100644
--- a/kern/pv.c
+++ b/kern/pv.c
@@ -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(&current->pts->lock);
current->pts->refcount--;
+ if (p->pv != NULL) {
+ queue_detach(&current->pts->pvs, &p->pv->pts_link);
+ }
mutex_unlock(&current->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, &current->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