From: Minep Date: Fri, 24 Jun 2022 10:08:17 +0000 (+0100) Subject: feat: experimental tty console with scrollback buffer. X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/commitdiff_plain/1f37d39e678168ffc089bcde6f9ea203c4763550 feat: experimental tty console with scrollback buffer. --- diff --git a/lunaix-os/includes/klibc/string.h b/lunaix-os/includes/klibc/string.h index 9cbcb31..8337ef1 100644 --- a/lunaix-os/includes/klibc/string.h +++ b/lunaix-os/includes/klibc/string.h @@ -4,16 +4,16 @@ #include int -memcmp(const void*, const void*, size_t); +memcmp(const void* dest, const void* src, size_t size); void* -memcpy(void* __restrict, const void* __restrict, size_t); +memcpy(void* dest, const void* src, size_t size); void* -memmove(void*, const void*, size_t); +memmove(void* dest, const void* src, size_t size); void* -memset(void*, int, size_t); +memset(void* dest, int val, size_t size); size_t strlen(const char* str); diff --git a/lunaix-os/includes/lunaix/ds/fifobuf.h b/lunaix-os/includes/lunaix/ds/fifobuf.h new file mode 100644 index 0000000..f5f08c1 --- /dev/null +++ b/lunaix-os/includes/lunaix/ds/fifobuf.h @@ -0,0 +1,18 @@ +#ifndef __LUNAIX_FIFO_BUF_H +#define __LUNAIX_FIFO_BUF_H + +#include + +#define FIFO_DIRTY 1 + +struct fifo_buffer +{ + void* data; + unsigned int wr_pos; + unsigned int rd_pos; + unsigned int size; + unsigned int flags; + mutex_t lock; +}; + +#endif /* __LUNAIX_FIFO_BUF_H */ diff --git a/lunaix-os/includes/lunaix/lxconsole.h b/lunaix-os/includes/lunaix/lxconsole.h new file mode 100644 index 0000000..a264766 --- /dev/null +++ b/lunaix-os/includes/lunaix/lxconsole.h @@ -0,0 +1,15 @@ +#ifndef __LUNAIX_LXCONSOLE_H +#define __LUNAIX_LXCONSOLE_H + +void +lxconsole_init(); + +void +console_write_str(char* str); + +void +console_write_char(char chr); + +void +console_start_flushing(); +#endif /* __LUNAIX_LXCONSOLE_H */ diff --git a/lunaix-os/includes/lunaix/mm/pmm.h b/lunaix-os/includes/lunaix/mm/pmm.h index d45af82..44aa99d 100644 --- a/lunaix-os/includes/lunaix/mm/pmm.h +++ b/lunaix-os/includes/lunaix/mm/pmm.h @@ -2,19 +2,29 @@ #define __LUNAIX_PMM_H // Physical memory manager -#include -#include #include +#include +#include -#define PM_PAGE_SIZE 4096 -#define PM_BMP_MAX_SIZE (1024 * 1024) +#define PM_PAGE_SIZE 4096 +#define PM_BMP_MAX_SIZE (1024 * 1024) +/** + * @brief 长久页:不会被缓存,但允许释放 + * + */ +#define PP_FGPERSIST 0x1 -#define PP_FGPERSIST 0x1 +/** + * @brief 锁定页:不会被缓存,不能被释放 + * + */ +#define PP_FGLOCKED 0x2 typedef uint32_t pp_attr_t; -struct pp_struct { +struct pp_struct +{ pid_t owner; uint32_t ref_counts; pp_attr_t attr; @@ -22,70 +32,81 @@ struct pp_struct { /** * @brief 标注物理页为可使用 - * + * * @param ppn page number */ -void pmm_mark_page_free(uintptr_t ppn); +void +pmm_mark_page_free(uintptr_t ppn); /** * @brief 标注物理页为已占用 - * - * @param ppn + * + * @param ppn */ -void pmm_mark_page_occupied(pid_t owner, uintptr_t ppn, pp_attr_t attr); +void +pmm_mark_page_occupied(pid_t owner, uintptr_t ppn, pp_attr_t attr); /** * @brief 标注多个连续的物理页为可用 - * + * * @param start_ppn 起始PPN * @param page_count 数量 */ -void pmm_mark_chunk_free(uintptr_t start_ppn, size_t page_count); +void +pmm_mark_chunk_free(uintptr_t start_ppn, size_t page_count); /** * @brief 标注多个连续的物理页为已占用 - * + * * @param start_ppn 起始PPN * @param page_count 数量 */ -void pmm_mark_chunk_occupied(pid_t owner, uintptr_t start_ppn, size_t page_count, pp_attr_t attr); +void +pmm_mark_chunk_occupied(pid_t owner, + uintptr_t start_ppn, + size_t page_count, + pp_attr_t attr); /** * @brief 分配一个可用的物理页 - * + * * @return void* 可用的页地址,否则为 NULL */ -void* pmm_alloc_page(pid_t owner, pp_attr_t attr); +void* +pmm_alloc_page(pid_t owner, pp_attr_t attr); /** * @brief 分配一个连续的物理内存区域 - * - * @param owner + * + * @param owner * @param num_pages 区域大小,单位为页 - * @param attr - * @return void* + * @param attr + * @return void* */ void* pmm_alloc_cpage(pid_t owner, size_t num_pages, pp_attr_t attr); /** * @brief 初始化物理内存管理器 - * + * * @param mem_upper_lim 最大可用内存地址 */ -void pmm_init(uintptr_t mem_upper_lim); +void +pmm_init(uintptr_t mem_upper_lim); -struct pp_struct* pmm_query(void* pa); +struct pp_struct* +pmm_query(void* pa); /** * @brief 释放一个已分配的物理页,假若页地址不存在,则无操作。 - * + * * @param page 页地址 * @return 是否成功 */ -int pmm_free_page(pid_t owner, void* page); - +int +pmm_free_page(pid_t owner, void* page); -int pmm_ref_page(pid_t owner, void* page); +int +pmm_ref_page(pid_t owner, void* page); #endif /* __LUNAIX_PMM_H */ diff --git a/lunaix-os/includes/lunaix/mm/vmm.h b/lunaix-os/includes/lunaix/mm/vmm.h index bd074c5..eab7315 100644 --- a/lunaix-os/includes/lunaix/mm/vmm.h +++ b/lunaix-os/includes/lunaix/mm/vmm.h @@ -18,6 +18,12 @@ */ #define VMAP_NOMAP 2 +/** + * @brief 规定下一个可用页映射应当限定在指定的4MB地址空间内 + * + */ +#define VALLOC_PDE 1 + /** * @brief 初始化虚拟内存管理器 * @@ -97,4 +103,7 @@ vmm_mount_pd(uintptr_t mnt, void* pde); void* vmm_unmount_pd(uintptr_t mnt); +void* +vmm_next_free(uintptr_t start, int options); + #endif /* __LUNAIX_VMM_H */ diff --git a/lunaix-os/includes/lunaix/tty/console.h b/lunaix-os/includes/lunaix/tty/console.h new file mode 100644 index 0000000..5e0ffcc --- /dev/null +++ b/lunaix-os/includes/lunaix/tty/console.h @@ -0,0 +1,13 @@ +#ifndef __LUNAIX_CONSOLE_H +#define __LUNAIX_CONSOLE_H + +#include +#include + +struct console +{ + struct lx_timer* flush_timer; + struct fifo_buffer buffer; +}; + +#endif /* __LUNAIX_CONSOLE_H */ diff --git a/lunaix-os/includes/lunaix/tty/tty.h b/lunaix-os/includes/lunaix/tty/tty.h index cbb3924..518d376 100644 --- a/lunaix-os/includes/lunaix/tty/tty.h +++ b/lunaix-os/includes/lunaix/tty/tty.h @@ -9,8 +9,8 @@ typedef unsigned short vga_attribute; #define VGA_COLOR_RED 4 #define VGA_COLOR_MAGENTA 5 #define VGA_COLOR_BROWN 6 -#define VGA_COLOR_LIGHT_GREY 7 #define VGA_COLOR_DARK_GREY 8 +#define VGA_COLOR_LIGHT_GREY 7 #define VGA_COLOR_LIGHT_BLUE 9 #define VGA_COLOR_LIGHT_GREEN 10 #define VGA_COLOR_LIGHT_CYAN 11 @@ -19,42 +19,25 @@ typedef unsigned short vga_attribute; #define VGA_COLOR_LIGHT_BROWN 14 #define VGA_COLOR_WHITE 15 -void -tty_init(void* vga_buf); +#define TTY_WIDTH 80 +#define TTY_HEIGHT 25 void -tty_set_buffer(void* vga_buf); +tty_init(void* vga_buf); void tty_set_theme(vga_attribute fg, vga_attribute bg); -void -tty_put_char(char chr); - -void -tty_put_str(char* str); - -void -tty_scroll_up(); - -void -tty_clear(); - -void -tty_clear_line(unsigned int y); - -void -tty_set_cpos(unsigned int x, unsigned int y); - -void -tty_get_cpos(unsigned int* x, unsigned int* y); - vga_attribute tty_get_theme(); -void tty_set_cursor(unsigned char x, unsigned char y); +size_t +tty_flush_buffer(char* data, size_t pos, size_t limit, size_t buf_size); -void tty_sync_cursor(); +void +tty_clear_line(int line_num); +void +tty_put_str_at(char* str, int x, int y); #endif /* __LUNAIX_TTY_H */ diff --git a/lunaix-os/kernel/k_init.c b/lunaix-os/kernel/k_init.c index c173ad9..7acd306 100644 --- a/lunaix-os/kernel/k_init.c +++ b/lunaix-os/kernel/k_init.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -58,7 +59,12 @@ _kernel_pre_init() vmm_init(); rtc_init(); - tty_init((void*)VGA_BUFFER_PADDR); + unsigned int map_size = + _k_init_mb_info->mmap_length / sizeof(multiboot_memory_map_t); + + setup_memory((multiboot_memory_map_t*)_k_init_mb_info->mmap_addr, map_size); + + tty_init((void*)VGA_BUFFER_VADDR); tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_BLACK); __kernel_ptd = cpu_rcr3(); @@ -71,14 +77,7 @@ _kernel_pre_init() void _kernel_init() { - kprintf("[MM] Mem: %d KiB, Extended Mem: %d KiB\n", - _k_init_mb_info->mem_lower, - _k_init_mb_info->mem_upper); - - unsigned int map_size = - _k_init_mb_info->mmap_length / sizeof(multiboot_memory_map_t); - - setup_memory((multiboot_memory_map_t*)_k_init_mb_info->mmap_addr, map_size); + lxconsole_init(); kprintf(KINFO "[MM] Allocated %d pages for stack start at %p\n", KSTACK_SIZE >> PG_SIZE_BITS, @@ -181,31 +180,23 @@ setup_memory(multiboot_memory_map_t* map, size_t map_size) // First pass, to mark the physical pages for (unsigned int i = 0; i < map_size; i++) { multiboot_memory_map_t mmap = map[i]; - kprintf("[MM] Base: 0x%x, len: %u KiB, type: %u\n", - map[i].addr_low, - map[i].len_low >> 10, - map[i].type); if (mmap.type == MULTIBOOT_MEMORY_AVAILABLE) { // 整数向上取整除法 uintptr_t pg = map[i].addr_low + 0x0fffU; pmm_mark_chunk_free(pg >> PG_SIZE_BITS, map[i].len_low >> PG_SIZE_BITS); - kprintf(KINFO "[MM] Freed %u pages start from 0x%x\n", - map[i].len_low >> PG_SIZE_BITS, - pg & ~0x0fffU); } } // 将内核占据的页,包括前1MB,hhk_init 设为已占用 size_t pg_count = V2P(&__kernel_end) >> PG_SIZE_BITS; pmm_mark_chunk_occupied(KERNEL_PID, 0, pg_count, 0); - kprintf(KINFO "[MM] Allocated %d pages for kernel.\n", pg_count); size_t vga_buf_pgs = VGA_BUFFER_SIZE >> PG_SIZE_BITS; - // 首先,标记VGA部分为已占用 + // 首先,标记VGA部分为已占用,并且锁定 pmm_mark_chunk_occupied( - KERNEL_PID, VGA_BUFFER_PADDR >> PG_SIZE_BITS, vga_buf_pgs, 0); + KERNEL_PID, VGA_BUFFER_PADDR >> PG_SIZE_BITS, vga_buf_pgs, PP_FGLOCKED); // 重映射VGA文本缓冲区(以后会变成显存,i.e., framebuffer) for (size_t i = 0; i < vga_buf_pgs; i++) { @@ -216,16 +207,7 @@ setup_memory(multiboot_memory_map_t* map, size_t map_size) VMAP_NULL); } - assert_msg(!((uintptr_t)&__usrtext_start & 0xfff) && - !((uintptr_t)&__usrtext_end & 0xfff), - "Bad usrtext alignment"); - for (uintptr_t i = &__usrtext_start; i < &__usrtext_end; i += PG_SIZE) { vmm_set_mapping(PD_REFERENCED, i, V2P(i), PG_PREM_UR, VMAP_NULL); } - - // 更新VGA缓冲区位置至虚拟地址 - tty_set_buffer((void*)VGA_BUFFER_VADDR); - - kprintf(KINFO "[MM] Mapped VGA to %p.\n", VGA_BUFFER_VADDR); } diff --git a/lunaix-os/kernel/kprintf.c b/lunaix-os/kernel/kprintf.c index a862bcc..374fff2 100644 --- a/lunaix-os/kernel/kprintf.c +++ b/lunaix-os/kernel/kprintf.c @@ -1,6 +1,7 @@ +#include +#include #include #include -#include #define MAX_KPRINTF_BUF_SIZE 1024 #define MAX_XFMT_SIZE 1024 @@ -8,57 +9,81 @@ static char buf[MAX_KPRINTF_BUF_SIZE]; void -__kprintf(const char* component, const char* fmt, va_list args) { - if (!fmt) return; +__kprintf(const char* component, const char* fmt, va_list args) +{ + if (!fmt) + return; char log_level = '0'; char expanded_fmt[MAX_XFMT_SIZE]; - vga_attribute current_theme = tty_get_theme(); if (*fmt == '\x1b') { log_level = *(++fmt); fmt++; } - switch (log_level) - { - case '0': - snprintf(expanded_fmt, MAX_XFMT_SIZE, "[%s] (%s) %s", "INFO", component, fmt); - break; - case '1': - tty_set_theme(VGA_COLOR_BROWN, current_theme >> 12); - snprintf(expanded_fmt, MAX_XFMT_SIZE, "[%s] (%s) %s", "WARN", component, fmt); - break; - case '2': - tty_set_theme(VGA_COLOR_LIGHT_RED, current_theme >> 12); - snprintf(expanded_fmt, MAX_XFMT_SIZE, "[%s] (%s) %s", "EROR", component, fmt); - break; - case '3': - tty_set_theme(VGA_COLOR_LIGHT_BLUE, current_theme >> 12); - snprintf(expanded_fmt, MAX_XFMT_SIZE, "[%s] (%s) %s", "DEBG", component, fmt); - break; - default: - snprintf(expanded_fmt, MAX_XFMT_SIZE, "[%s] (%s) %s", "LOG", component, fmt); - break; + switch (log_level) { + case '0': + snprintf(expanded_fmt, + MAX_XFMT_SIZE, + "[%s] (%s) %s", + "INFO", + component, + fmt); + break; + case '1': + // tty_set_theme(VGA_COLOR_BROWN, current_theme >> 12); + snprintf(expanded_fmt, + MAX_XFMT_SIZE, + "\x033[6;0m[%s] (%s) %s\x033[39;49m", + "WARN", + component, + fmt); + break; + case '2': + // tty_set_theme(VGA_COLOR_LIGHT_RED, current_theme >> 12); + snprintf(expanded_fmt, + MAX_XFMT_SIZE, + "\x033[12;0m[%s] (%s) %s\x033[39;49m", + "EROR", + component, + fmt); + break; + case '3': + // tty_set_theme(VGA_COLOR_LIGHT_BLUE, current_theme >> 12); + snprintf(expanded_fmt, + MAX_XFMT_SIZE, + "\x033[9;0m[%s] (%s) %s\x033[39;49m", + "DEBG", + component, + fmt); + break; + default: + snprintf(expanded_fmt, + MAX_XFMT_SIZE, + "[%s] (%s) %s", + "LOG", + component, + fmt); + break; } __sprintf_internal(buf, expanded_fmt, MAX_KPRINTF_BUF_SIZE, args); - tty_put_str(buf); - tty_set_theme(current_theme >> 8, current_theme >> 12); + console_write_str(buf); } void -kprint_panic(const char* fmt, ...) { +kprint_panic(const char* fmt, ...) +{ va_list args; va_start(args, fmt); - + tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_RED); tty_clear_line(10); tty_clear_line(11); tty_clear_line(12); - tty_set_cpos(0, 11); __sprintf_internal(buf, fmt, MAX_KPRINTF_BUF_SIZE, args); - tty_put_str(buf); + tty_put_str_at(buf, 0, 11); va_end(args); } \ No newline at end of file diff --git a/lunaix-os/kernel/lxconsole.c b/lunaix-os/kernel/lxconsole.c new file mode 100644 index 0000000..25c4faa --- /dev/null +++ b/lunaix-os/kernel/lxconsole.c @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include +#include + +static struct console lx_console; + +volatile int can_flush = 0; + +void +lxconsole_init() +{ + memset(&lx_console, 0, sizeof(lx_console)); + lx_console.buffer.data = VGA_BUFFER_VADDR + 0x1000; + lx_console.buffer.size = 8192; + mutex_init(&lx_console.buffer.lock); + + // 分配控制台缓存 + for (size_t i = 0; i < PG_ALIGN(lx_console.buffer.size); i += PG_SIZE) { + uintptr_t pa = pmm_alloc_page(KERNEL_PID, 0); + vmm_set_mapping(PD_REFERENCED, + (uintptr_t)lx_console.buffer.data + i, + pa, + PG_PREM_URW, + 0); + } + + memset(lx_console.buffer.data, 0, lx_console.buffer.size); + + lx_console.flush_timer = NULL; +} + +void +console_schedule_flush() +{ + // TODO make the flush on-demand rather than periodic +} + +void +console_view_up(struct fifo_buffer* buffer) +{ + // mutex_lock(&buffer->lock); + size_t p = buffer->rd_pos - 2; + while (p < buffer->rd_pos && p != buffer->wr_pos && + ((char*)buffer->data)[p] != '\n') { + p--; + } + p++; + + if (p < buffer->rd_pos) { + p = 0; + } + + buffer->rd_pos = p; + // mutex_unlock(&buffer->lock); +} + +void +console_view_down(struct fifo_buffer* buffer) +{ + // mutex_lock(&buffer->lock); + size_t p = buffer->rd_pos; + while (p != buffer->wr_pos && ((char*)buffer->data)[p] != '\n') { + p = (p + 1) % buffer->size; + } + + buffer->rd_pos = p + 1; + // mutex_unlock(&buffer->lock); +} + +void +__flush_cb(void* arg) +{ + if (mutex_on_hold(&lx_console.buffer.lock)) { + return; + } + if (!(lx_console.buffer.flags & FIFO_DIRTY)) { + return; + } + + size_t pos = tty_flush_buffer(lx_console.buffer.data, + lx_console.buffer.rd_pos, + lx_console.buffer.wr_pos, + lx_console.buffer.size); + lx_console.flush_timer = NULL; + if (pos < lx_console.buffer.wr_pos) { + console_view_down(&lx_console.buffer); + } else { + // clear the dirty bit only if we have flush all the data + // that means: read pointer == write pointer + lx_console.buffer.flags &= ~FIFO_DIRTY; + } +} + +void +console_write(struct console* console, uint8_t* data, size_t size) +{ + mutex_lock(&console->buffer.lock); + uint8_t* buffer = console->buffer.data; + uintptr_t ptr = console->buffer.wr_pos; + uintptr_t rd_ptr = console->buffer.rd_pos; + + for (size_t i = 0; i < size; i++) { + buffer[(ptr + i) % console->buffer.size] = data[i]; + } + + uintptr_t new_ptr = (ptr + size) % console->buffer.size; + console->buffer.wr_pos = new_ptr; + if (new_ptr < ptr + size && new_ptr > rd_ptr) { + console->buffer.rd_pos = new_ptr; + } + console->buffer.flags |= FIFO_DIRTY; + mutex_unlock(&console->buffer.lock); +} + +void +console_write_str(char* str) +{ + console_write(&lx_console, str, strlen(str)); +} + +void +console_write_char(char str) +{ + console_write(&lx_console, &str, 1); +} + +void +console_start_flushing() +{ + struct lx_timer* timer = + timer_run_ms(20, __flush_cb, NULL, TIMER_MODE_PERIODIC); + lx_console.flush_timer = timer; +} \ No newline at end of file diff --git a/lunaix-os/kernel/lxinit.c b/lunaix-os/kernel/lxinit.c index 91a4e50..8a19841 100644 --- a/lunaix-os/kernel/lxinit.c +++ b/lunaix-os/kernel/lxinit.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -9,7 +10,6 @@ #include #include #include -#include extern uint8_t __kernel_start; @@ -94,8 +94,7 @@ _lxinit_main() if (i == 3) { i = *(int*)0xdeadc0de; // seg fault! } - tty_put_char('0' + i); - tty_put_char('\n'); + kprintf(KINFO "%d\n", i); _exit(0); } kprintf(KINFO "Forked %d\n", pid); @@ -133,7 +132,7 @@ _lxinit_main() } if ((keyevent.state & KBD_KEY_FPRESSED) && (keyevent.keycode & 0xff00) <= KEYPAD) { - tty_put_char((char)(keyevent.keycode & 0x00ff)); + console_write_char((char)(keyevent.keycode & 0x00ff)); // FIXME: io to vga port is privileged and cause #GP in user mode // tty_sync_cursor(); } diff --git a/lunaix-os/kernel/mm/pmm.c b/lunaix-os/kernel/mm/pmm.c index ad80dbf..9c0d3eb 100644 --- a/lunaix-os/kernel/mm/pmm.c +++ b/lunaix-os/kernel/mm/pmm.c @@ -16,32 +16,27 @@ pmm_mark_page_free(uintptr_t ppn) void pmm_mark_page_occupied(pid_t owner, uintptr_t ppn, pp_attr_t attr) { - pm_table[ppn] = (struct pp_struct) { - .owner = owner, - .ref_counts = 1, - .attr = attr - }; + pm_table[ppn] = + (struct pp_struct){ .owner = owner, .ref_counts = 1, .attr = attr }; } void pmm_mark_chunk_free(uintptr_t start_ppn, size_t page_count) { - for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) - { + for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) { pm_table[i].ref_counts = 0; } } void -pmm_mark_chunk_occupied(pid_t owner, uint32_t start_ppn, size_t page_count, pp_attr_t attr) +pmm_mark_chunk_occupied(pid_t owner, + uint32_t start_ppn, + size_t page_count, + pp_attr_t attr) { - for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) - { - pm_table[i] = (struct pp_struct) { - .owner = owner, - .ref_counts = 1, - .attr = attr - }; + for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) { + pm_table[i] = + (struct pp_struct){ .owner = owner, .ref_counts = 1, .attr = attr }; } } @@ -59,21 +54,18 @@ pmm_init(uintptr_t mem_upper_lim) // mark all as occupied for (size_t i = 0; i < PM_BMP_MAX_SIZE; i++) { - pm_table[i] = (struct pp_struct) { - .owner = 0, - .attr = 0, - .ref_counts = 1 - }; + pm_table[i] = + (struct pp_struct){ .owner = 0, .attr = 0, .ref_counts = 1 }; } } void* -pmm_alloc_cpage(pid_t owner, size_t num_pages, pp_attr_t attr) { +pmm_alloc_cpage(pid_t owner, size_t num_pages, pp_attr_t attr) +{ size_t p1 = 0; size_t p2 = 0; - while (p2 < max_pg && p2 - p1 < num_pages) - { + while (p2 < max_pg && p2 - p1 < num_pages) { (!(&pm_table[p2])->ref_counts) ? (p2++) : (p1 = p2); } @@ -98,11 +90,9 @@ pmm_alloc_page(pid_t owner, pp_attr_t attr) pm = &pm_table[pg_lookup_ptr]; if (!pm->ref_counts) { - *pm = (struct pp_struct) { - .attr = attr, - .owner = owner, - .ref_counts = 1 - }; + *pm = (struct pp_struct){ .attr = attr, + .owner = owner, + .ref_counts = 1 }; good_page_found = pg_lookup_ptr << 12; break; } else { @@ -128,22 +118,30 @@ int pmm_free_page(pid_t owner, void* page) { struct pp_struct* pm = &pm_table[(intptr_t)page >> 12]; - + // Is this a MMIO mapping or double free? if (((intptr_t)page >> 12) >= max_pg || !(pm->ref_counts)) { return 0; } - // TODO: 检查权限,保证:1) 只有正在使用该页(包括被分享者)的进程可以释放; 2) 内核可释放所有页。 + // 如果是锁定页,则不作处理 + if ((pm->attr & PP_FGLOCKED)) { + return 0; + } + + // TODO: 检查权限,保证:1) 只有正在使用该页(包括被分享者)的进程可以释放; + // 2) 内核可释放所有页。 pm->ref_counts--; return 1; } -int pmm_ref_page(pid_t owner, void* page) { - (void*) owner; // TODO: do smth with owner - +int +pmm_ref_page(pid_t owner, void* page) +{ + (void*)owner; // TODO: do smth with owner + uint32_t ppn = (uintptr_t)page >> 12; - + if (ppn >= PM_BMP_MAX_SIZE) { return 0; } @@ -157,9 +155,11 @@ int pmm_ref_page(pid_t owner, void* page) { return 1; } -struct pp_struct* pmm_query(void* pa) { +struct pp_struct* +pmm_query(void* pa) +{ uint32_t ppn = (uintptr_t)pa >> 12; - + if (ppn >= PM_BMP_MAX_SIZE) { return NULL; } diff --git a/lunaix-os/kernel/proc0.c b/lunaix-os/kernel/proc0.c index 4cc414c..cece368 100644 --- a/lunaix-os/kernel/proc0.c +++ b/lunaix-os/kernel/proc0.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -84,12 +85,6 @@ init_platform() { assert_msg(kalloc_init(), "Fail to initialize heap"); - // Fuck it, I will no longer bother this little 1MiB - // I just release 4 pages for my APIC & IOAPIC remappings - // for (size_t i = 0; i < 3; i++) { - // vmm_del_mapping(PD_REFERENCED, (void*)(i << PG_SIZE_BITS)); - // } - // 锁定所有系统预留页(内存映射IO,ACPI之类的),并且进行1:1映射 lock_reserved_memory(); @@ -112,6 +107,8 @@ init_platform() syscall_install(); + console_start_flushing(); + unlock_reserved_memory(); for (size_t i = 0; i < (uintptr_t)(&__init_hhk_end); i += PG_SIZE) { diff --git a/lunaix-os/kernel/tty/tty.c b/lunaix-os/kernel/tty/tty.c index 4164239..b491355 100644 --- a/lunaix-os/kernel/tty/tty.c +++ b/lunaix-os/kernel/tty/tty.c @@ -1,24 +1,27 @@ #include #include #include +#include +#include #include #include -#define TTY_WIDTH 80 -#define TTY_HEIGHT 25 +vga_attribute* tty_vga_buffer = (vga_attribute*)VGA_BUFFER_PADDR; -static vga_attribute* tty_vga_buffer = (vga_attribute*)VGA_BUFFER_PADDR; +vga_attribute tty_theme_color = VGA_COLOR_BLACK; -static vga_attribute tty_theme_color = VGA_COLOR_BLACK; - -static uint32_t tty_x = 0; -static uint32_t tty_y = 0; +#define TTY_CLEAR \ + asm volatile("rep stosw" ::"D"(tty_vga_buffer), \ + "c"(TTY_HEIGHT * TTY_WIDTH), \ + "a"(tty_theme_color) \ + : "memory"); void tty_init(void* vga_buf) { tty_vga_buffer = (vga_attribute*)vga_buf; - tty_clear(); + + TTY_CLEAR io_outb(0x3D4, 0x0A); io_outb(0x3D5, (io_inb(0x3D5) & 0xC0) | 13); @@ -27,56 +30,85 @@ tty_init(void* vga_buf) io_outb(0x3D5, (io_inb(0x3D5) & 0xE0) | 15); } -void -tty_set_buffer(void* vga_buf) -{ - tty_vga_buffer = (vga_attribute*)vga_buf; -} - void tty_set_theme(vga_attribute fg, vga_attribute bg) { tty_theme_color = (bg << 4 | fg) << 8; } -void -tty_put_char(char chr) +size_t +tty_flush_buffer(char* data, size_t pos, size_t limit, size_t buf_size) { - switch (chr) { - case '\t': - tty_x += 4; - break; - case '\n': - tty_y++; - // fall through - case '\r': - tty_x = 0; - break; - case '\x08': - tty_x = tty_x ? tty_x - 1 : 0; - *(tty_vga_buffer + tty_x + tty_y * TTY_WIDTH) = - (tty_theme_color | 0x20); - break; - default: - *(tty_vga_buffer + tty_x + tty_y * TTY_WIDTH) = - (tty_theme_color | chr); - tty_x++; - break; - } + int x = 0, y = 0; - if (tty_x >= TTY_WIDTH) { - tty_x = 0; - tty_y++; - } - if (tty_y >= TTY_HEIGHT) { - tty_scroll_up(); - } -} + // Clear screen + TTY_CLEAR -void -tty_sync_cursor() -{ - tty_set_cursor(tty_x, tty_y); + int state = 0; + int g[2] = { 0, 0 }; + vga_attribute current_theme = tty_theme_color; + while (1) { + size_t ptr = pos % buf_size; + if (pos == limit) { + break; + } + char chr = data[pos]; + if (state == 0 && chr == '\x033') { + state = 1; + } else if (state == 1 && chr == '[') { + state = 2; + } else if (state > 1) { + if ('0' <= chr && chr <= '9') { + g[state - 2] = (chr - '0') + g[state - 2] * 10; + } else if (chr == ';' && state == 2) { + state = 3; + } else { + if (g[0] == 39 && g[1] == 49) { + current_theme = tty_theme_color; + } else { + current_theme = (g[1] << 4 | g[0]) << 8; + } + g[0] = 0; + g[1] = 0; + state = 0; + } + } else { + state = 0; + switch (chr) { + case '\t': + x += 4; + break; + case '\n': + y++; + // fall through + case '\r': + x = 0; + break; + case '\x08': + x = x ? x - 1 : 0; + *(tty_vga_buffer + x + y * TTY_WIDTH) = + (current_theme | 0x20); + break; + default: + *(tty_vga_buffer + x + y * TTY_WIDTH) = + (current_theme | chr); + (x)++; + break; + } + + if (x >= TTY_WIDTH) { + x = 0; + y++; + } + if (y >= TTY_HEIGHT) { + y--; + break; + } + } + pos++; + } + tty_set_cursor(x, y); + return pos; } void @@ -93,64 +125,25 @@ tty_set_cursor(uint8_t x, uint8_t y) } void -tty_put_str(char* str) -{ - while (*str != '\0') { - tty_put_char(*str); - str++; - } - // FIXME: This does not work in user mode. - // Work around: - // 1. (Easy) Define an IO Permission bitmap in TSS - // 2. (More effort) Mount onto file system. (/dev/tty) - // tty_sync_cursor(); -} - -void -tty_scroll_up() +tty_clear_line(int line_num) { - size_t last_line = TTY_WIDTH * (TTY_HEIGHT - 1); - memcpy(tty_vga_buffer, tty_vga_buffer + TTY_WIDTH, last_line * 2); - for (size_t i = 0; i < TTY_WIDTH; i++) { - *(tty_vga_buffer + i + last_line) = tty_theme_color; - } - tty_y = tty_y == 0 ? 0 : TTY_HEIGHT - 1; + asm volatile("rep stosw" ::"D"(tty_vga_buffer + line_num * TTY_WIDTH), + "c"(TTY_WIDTH), + "a"(tty_theme_color) + : "memory"); } void -tty_clear() +tty_put_str_at(char* str, int x, int y) { - for (uint32_t i = 0; i < TTY_WIDTH * TTY_HEIGHT; i++) { - *(tty_vga_buffer + i) = tty_theme_color; - } - tty_x = 0; - tty_y = 0; -} - -void -tty_clear_line(unsigned int y) -{ - for (size_t i = 0; i < TTY_WIDTH; i++) { - *(tty_vga_buffer + i + y * TTY_WIDTH) = tty_theme_color; + char c; + while ((c = (*str)) && y < TTY_HEIGHT) { + *(tty_vga_buffer + x + y * TTY_WIDTH) = c | tty_theme_color; + x++; + if (x >= TTY_WIDTH) { + y++; + x = 0; + } + str++; } -} - -void -tty_set_cpos(unsigned int x, unsigned int y) -{ - tty_x = x % TTY_WIDTH; - tty_y = y % TTY_HEIGHT; -} - -void -tty_get_cpos(unsigned int* x, unsigned int* y) -{ - *x = tty_x; - *y = tty_y; -} - -vga_attribute -tty_get_theme() -{ - return tty_theme_color; } \ No newline at end of file