diff options
| author | hachem <im@hachem.wtf> | 2026-09-25 21:21:09 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-09-25 21:21:09 +0200 |
| commit | 09982d80c45805715984cc1cae96c37e4fc148c3 (patch) | |
| tree | f711d6e7f4d4cb2d4dcb555d6a139aae343d7334 /kernel | |
| parent | fd3f51eecaecc12806a573c38263df1de43ee8c2 (diff) | |
feat: scheduler + cleanup
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/console.rv | 76 | ||||
| -rw-r--r-- | kernel/font.rv | 60 | ||||
| -rw-r--r-- | kernel/input.rv | 65 | ||||
| -rw-r--r-- | kernel/main.rv | 7 | ||||
| -rw-r--r-- | kernel/proc.rv | 36 | ||||
| -rw-r--r-- | kernel/shell.rv | 61 | ||||
| -rw-r--r-- | kernel/vmm.rv | 10 |
7 files changed, 194 insertions, 121 deletions
diff --git a/kernel/console.rv b/kernel/console.rv index a949cd2..d0ee43c 100644 --- a/kernel/console.rv +++ b/kernel/console.rv @@ -1,12 +1,12 @@ const FW = 8 # glyph width in pixels -const FH = 16 # glyph height in pixels (8x16 VGA bitmap font) +const FH = 16 # glyph height in pixels (8x16 vga bitmap font) const FG = 0xd0d0d0 const CON_BG = 0x101018 -global con = { col = 0, row = 0, scale = 1, cur_on = :true, blink = 0 } +global con = { col = 0, row = 0, scale = 1, shown = :false, cur_x = 0, cur_y = 0, blink = 0 } -# cell size in pixels at the current zoom. named cell_* (not cw/ch) so they don't -# collide with draw_glyph's `ch` character parameter. +# cell size in pixels at the current zoom. named cell_* (not cw/ch) so they dont +# collide with draw_glyphs `ch` character parameter fn cell_w() FW * con.scale fn cell_h() FH * con.scale fn con_cols() fb_width() / cell_w() @@ -19,9 +19,9 @@ fn draw_glyph(col, row, ch) do const code = ch:ascii() if code < 32 return :nil if code > 127 return :nil - const g = FONT[code - 32] + const glyph = FONT[code - 32] for fy in 0..FH do - const bits = g[fy] + const bits = glyph[fy] for fx in 0..FW do if (bits shr fx) band 1 == 1 fill_rect(x0 + fx * con.scale, y0 + fy * con.scale, con.scale, con.scale, FG) end @@ -37,7 +37,7 @@ fn con_newline() do end end -# we dont do Shift/Cntrl +# we dont do shift/cntrl # thats a job for future me lmao fn con_putc(ch) do const code = ch:ascii() @@ -53,31 +53,61 @@ fn con_putc(ch) do if con.col >= con_cols() con_newline() end -fn puts(s) serial_puts(s) +fn puts(str) serial_puts(str) const CUR = 0x50fa7b -fn cursor_paint(color) fill_rect(con.col * cell_w(), con.row * cell_h(), cell_w(), cell_h(), color) +# the cursor is an overlay block. its cleared before any drawing and shown after, +# so it never sits under a glyph, cur_x/cur_y remember where it was actually drawn +# so we always clear the right cell even after the head moved (backspace etc) +fn cursor_clear() do + if con.shown do + fill_rect(con.cur_x * cell_w(), con.cur_y * cell_h(), cell_w(), cell_h(), CON_BG) + con.shown = :false + end +end +fn cursor_show() do + con.cur_x = con.col + con.cur_y = con.row + fill_rect(con.cur_x * cell_w(), con.cur_y * cell_h(), cell_w(), cell_h(), CUR) + con.shown = :true +end + +fn drain() do + let byte = serial_next() + while byte >= 0 do con_putc(string.of_ascii(byte)) byte = serial_next() end +end global flush_console = fn() do - cursor_paint(CON_BG) - let c = serial_next() - while c >= 0 do - con_putc(string.of_ascii(c)) - c = serial_next() - end - # after any output the cursor is solid at the new head restart the blink phase - con.cur_on = :true + cursor_clear() + drain() con.blink = 0 - cursor_paint(CUR) + cursor_show() end -# the PIT fires ~100x/sec -# blink the cursor every 50 ticks (~2 Hz) -global on_tick = fn(t) do +# called each pit tick from the event loop (scheduler task 0). render any output a +# running process left in the serial mirror (this is how its writes reach the +# screen while time sliced), reprint the prompt when one exits, else blink +global on_tick = fn(ticks) do + let byte = serial_next() + if byte >= 0 do + cursor_clear() + con_putc(string.of_ascii(byte)) + drain() + con.blink = 0 + cursor_show() + return :nil + end + if proc_exited() do + cursor_clear() + puts("% ") + drain() + con.blink = 0 + cursor_show() + return :nil + end con.blink += 1 if con.blink >= 50 do con.blink = 0 - con.cur_on = not con.cur_on - cursor_paint(if con.cur_on CUR else CON_BG) + if con.shown cursor_clear() else cursor_show() end end diff --git a/kernel/font.rv b/kernel/font.rv index 7bd7c6a..0720dd4 100644 --- a/kernel/font.rv +++ b/kernel/font.rv @@ -1,7 +1,7 @@ -# IBM VGA 8x16 font (from Linux lib/fonts/font_8x16.c) -# ASCII 0x20..0x7f, indexed by (code - 32). -# one byte per row, 16 rows. -# bit 0 (LSB) of a byte is the leftmost pixel (VGA data is MSB-first, reversed here). +# ibm vga 8x16 font (from linux lib/fonts/font_8x16.c) +# ascii 0x20..0x7f, indexed by (code - 32) +# one byte per row, 16 rows +# bit 0 (lsb) of a byte is the leftmost pixel (vga data is msb first, reversed here) global FONT = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, # space { 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }, # ! @@ -36,32 +36,32 @@ global FONT = { { 0x00, 0x00, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00 }, # > { 0x00, 0x00, 0x3E, 0x63, 0x63, 0x30, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }, # ? { 0x00, 0x00, 0x00, 0x3E, 0x63, 0x63, 0x7B, 0x7B, 0x7B, 0x3B, 0x03, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # @ - { 0x00, 0x00, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }, # A - { 0x00, 0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3F, 0x00, 0x00, 0x00, 0x00 }, # B - { 0x00, 0x00, 0x3C, 0x66, 0x43, 0x03, 0x03, 0x03, 0x03, 0x43, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00 }, # C - { 0x00, 0x00, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00, 0x00, 0x00, 0x00 }, # D - { 0x00, 0x00, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x46, 0x66, 0x7F, 0x00, 0x00, 0x00, 0x00 }, # E - { 0x00, 0x00, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x06, 0x06, 0x0F, 0x00, 0x00, 0x00, 0x00 }, # F - { 0x00, 0x00, 0x3C, 0x66, 0x43, 0x03, 0x03, 0x7B, 0x63, 0x63, 0x66, 0x5C, 0x00, 0x00, 0x00, 0x00 }, # G - { 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }, # H - { 0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 }, # I - { 0x00, 0x00, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x33, 0x33, 0x1E, 0x00, 0x00, 0x00, 0x00 }, # J - { 0x00, 0x00, 0x67, 0x66, 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00 }, # K - { 0x00, 0x00, 0x0F, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00, 0x00, 0x00, 0x00 }, # L - { 0x00, 0x00, 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }, # M - { 0x00, 0x00, 0x63, 0x67, 0x6F, 0x7F, 0x7B, 0x73, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }, # N - { 0x00, 0x00, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # O - { 0x00, 0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x06, 0x06, 0x0F, 0x00, 0x00, 0x00, 0x00 }, # P - { 0x00, 0x00, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x6B, 0x7B, 0x3E, 0x30, 0x70, 0x00, 0x00 }, # Q - { 0x00, 0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x66, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00 }, # R - { 0x00, 0x00, 0x3E, 0x63, 0x63, 0x06, 0x1C, 0x30, 0x60, 0x63, 0x63, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # S - { 0x00, 0x00, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 }, # T - { 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # U - { 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x08, 0x00, 0x00, 0x00, 0x00 }, # V - { 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x6B, 0x6B, 0x6B, 0x7F, 0x77, 0x36, 0x00, 0x00, 0x00, 0x00 }, # W - { 0x00, 0x00, 0x63, 0x63, 0x36, 0x3E, 0x1C, 0x1C, 0x3E, 0x36, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }, # X - { 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 }, # Y - { 0x00, 0x00, 0x7F, 0x63, 0x61, 0x30, 0x18, 0x0C, 0x06, 0x43, 0x63, 0x7F, 0x00, 0x00, 0x00, 0x00 }, # Z + { 0x00, 0x00, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }, # a + { 0x00, 0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3F, 0x00, 0x00, 0x00, 0x00 }, # b + { 0x00, 0x00, 0x3C, 0x66, 0x43, 0x03, 0x03, 0x03, 0x03, 0x43, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00 }, # c + { 0x00, 0x00, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00, 0x00, 0x00, 0x00 }, # d + { 0x00, 0x00, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x46, 0x66, 0x7F, 0x00, 0x00, 0x00, 0x00 }, # e + { 0x00, 0x00, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x06, 0x06, 0x0F, 0x00, 0x00, 0x00, 0x00 }, # f + { 0x00, 0x00, 0x3C, 0x66, 0x43, 0x03, 0x03, 0x7B, 0x63, 0x63, 0x66, 0x5C, 0x00, 0x00, 0x00, 0x00 }, # g + { 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }, # h + { 0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 }, # i + { 0x00, 0x00, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x33, 0x33, 0x1E, 0x00, 0x00, 0x00, 0x00 }, # j + { 0x00, 0x00, 0x67, 0x66, 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00 }, # k + { 0x00, 0x00, 0x0F, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00, 0x00, 0x00, 0x00 }, # l + { 0x00, 0x00, 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }, # m + { 0x00, 0x00, 0x63, 0x67, 0x6F, 0x7F, 0x7B, 0x73, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }, # n + { 0x00, 0x00, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # o + { 0x00, 0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x06, 0x06, 0x0F, 0x00, 0x00, 0x00, 0x00 }, # p + { 0x00, 0x00, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x6B, 0x7B, 0x3E, 0x30, 0x70, 0x00, 0x00 }, # q + { 0x00, 0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x66, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00 }, # r + { 0x00, 0x00, 0x3E, 0x63, 0x63, 0x06, 0x1C, 0x30, 0x60, 0x63, 0x63, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # s + { 0x00, 0x00, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 }, # t + { 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # u + { 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x08, 0x00, 0x00, 0x00, 0x00 }, # v + { 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x6B, 0x6B, 0x6B, 0x7F, 0x77, 0x36, 0x00, 0x00, 0x00, 0x00 }, # w + { 0x00, 0x00, 0x63, 0x63, 0x36, 0x3E, 0x1C, 0x1C, 0x3E, 0x36, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }, # x + { 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 }, # y + { 0x00, 0x00, 0x7F, 0x63, 0x61, 0x30, 0x18, 0x0C, 0x06, 0x43, 0x63, 0x7F, 0x00, 0x00, 0x00, 0x00 }, # z { 0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00, 0x00, 0x00, 0x00 }, # [ { 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00 }, # \ { 0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00, 0x00, 0x00, 0x00 }, # ] diff --git a/kernel/input.rv b/kernel/input.rv index d069521..fe25c81 100644 --- a/kernel/input.rv +++ b/kernel/input.rv @@ -1,10 +1,10 @@ # keyboard scancode table -# ts is NOT a good way to write a driver LMAO +# ts is not a good way to write a driver lmao const KBD = " 1234567890-= qwertyuiop[] asdfghjkl;'` \\zxcvbnm,./ " -# same layout, shifted. index 42 (left shift) / 54 (right shift) stay blank. +# same layout, shifted. index 42 (left shift) / 54 (right shift) stay blank const KBD_SHIFT = " !@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"~ |ZXCVBNM<>? " -# 8259 PIC +# 8259 pic fn pic_remap() do outb(0x20, 0x11) outb(0xa0, 0x11) outb(0x21, 0x20) outb(0xa1, 0x28) @@ -14,9 +14,9 @@ fn pic_remap() do end fn pic_unmask(line) outb(0x21, inb(0x21) band (255 bxor (1 shl line))) -# 8253/8254 PIT channel 0, mode 3 (square wave) -# divisor 11931 -> ~100 Hz (1193182 / 11931) -# the ISR just counts ticks +# 8253/8254 pit channel 0, mode 3 (square wave) +# divisor 11931 -> ~100 hz (1193182 / 11931) +# the isr just counts ticks fn pit_init() do outb(0x43, 0x36) outb(0x40, 11931 band 0xff) @@ -25,33 +25,36 @@ end # she stroke my keys till i handle # no fr this is just a key stroke handler -global sh = { line = "", shift = :false } +global shell = { line = "", shift = :false } + +# decode one scancode to a character string, or :nil for releases / modifiers / +# unmapped keys. this is the only scancode decoder now, used by both the shell +# and the read() syscall +fn decode_key(code) do + if code == 0x2a or code == 0x36 do shell.shift = :true return :nil end # shift down + if code == 0xaa or code == 0xb6 do shell.shift = :false return :nil end # shift up + if code >= 128 return :nil # other releases + if code == 28 return "\n" # enter + if code == 14 return "\x08" # backspace + if code < 2 return :nil + if code >= KBD:len() return :nil + const ch = if shell.shift KBD_SHIFT[code] else KBD[code] + if ch == " " and code != 0x39 return :nil # blank cells = modifiers/unmapped + ch +end + global on_key = fn(code) do - # shift: 0x2a/0x36 press, - # 0xaa/0xb6 release - # index a blank cell and type a stray space. - if code == 0x2a do sh.shift = :true return :nil end - if code == 0x36 do sh.shift = :true return :nil end - if code == 0xaa do sh.shift = :false return :nil end - if code == 0xb6 do sh.shift = :false return :nil end - if code >= 128 return :nil # other key releases - if code == 28 do # Enter - puts("\n") - run(sh.line) - sh.line = "" + const ch = decode_key(code) + if ch == :nil return :nil + # a process blocked in read() gets first dibs, if it takes the byte, the shell + # doesnt see it (the process echoes its own input via write()) + if stdin_deliver(ch:ascii()) return :nil + # otherwise the shells line editor + if ch == "\n" do puts("\n") run(shell.line) shell.line = "" return :nil end + if ch == "\x08" do + if shell.line:len() > 0 do shell.line = shell.line:sub(0, shell.line:len() - 1) puts("\x08 \x08") end return :nil end - if code == 14 do # Backspace - if sh.line:len() > 0 do - sh.line = sh.line:sub(0, sh.line:len() - 1) - puts("\x08 \x08") - end - return :nil - end - if code < 2 return :nil - if code >= KBD:len() return :nil - const ch = if sh.shift KBD_SHIFT[code] else KBD[code] - if ch == " " and code != 0x39 return :nil - sh.line ~= ch + shell.line ~= ch puts(ch) end diff --git a/kernel/main.rv b/kernel/main.rv index 35413ef..4a0db06 100644 --- a/kernel/main.rv +++ b/kernel/main.rv @@ -2,9 +2,10 @@ pic_remap() pit_init() -pic_unmask(0) # PIT (IRQ0) -> cursor blink / uptime -pic_unmask(1) # keyboard (IRQ1) +pic_unmask(0) # pit (irq0) -> cursor blink / uptime +pic_unmask(1) # keyboard (irq1) cmd_clear() -puts("revel shell, live in revo. type `help`\n> ") +dump_memmap() +puts("revel shell, live in revo. type `help`\n% ") flush_console() diff --git a/kernel/proc.rv b/kernel/proc.rv index af6e8f7..162d24b 100644 --- a/kernel/proc.rv +++ b/kernel/proc.rv @@ -1,7 +1,7 @@ -# parse the embedded ELF (physical address from elf_phys()) and run it in ring 3 +# parse the embedded elf (physical address from elf_phys()) and run it in ring 3 const PT_LOAD = 1 -const PAGE_FLAGS = 6 # WRITE | USER +const PAGE_FLAGS = 6 # write | user fn cmd_run() do const base = elf_phys() @@ -13,28 +13,28 @@ fn cmd_run() do const phoff = mem_read(base + 32, 8) const phnum = mem_read(base + 56, 2) const phentsize = mem_read(base + 54, 2) - const as = as_create() + const space = as_create() for i in 0..phnum do - const ph = base + phoff + i * phentsize - if mem_read(ph, 4) == PT_LOAD do - const offset = mem_read(ph + 8, 8) - const vaddr = mem_read(ph + 16, 8) - const filesz = mem_read(ph + 32, 8) - const memsz = mem_read(ph + 40, 8) - let off = 0 - while off < memsz do + const phdr = base + phoff + i * phentsize + if mem_read(phdr, 4) == PT_LOAD do + const offset = mem_read(phdr + 8, 8) + const vaddr = mem_read(phdr + 16, 8) + const filesz = mem_read(phdr + 32, 8) + const memsz = mem_read(phdr + 40, 8) + let seg_off = 0 + while seg_off < memsz do const frame = frame_alloc() mem_zero(frame, 4096) - if off < filesz do - const left = filesz - off - mem_copy(frame, base + offset + off, if left > 4096 4096 else left) + if seg_off < filesz do + const left = filesz - seg_off + mem_copy(frame, base + offset + seg_off, if left > 4096 4096 else left) end - as_map(as, vaddr + off, frame, PAGE_FLAGS) - off = off + 4096 + as_map(space, vaddr + seg_off, frame, PAGE_FLAGS) + seg_off = seg_off + 4096 end end end const stack_top = 0x7fff0000 - as_map(as, stack_top - 4096, frame_alloc(), PAGE_FLAGS) - proc_run(as, entry, stack_top) + as_map(space, stack_top - 4096, frame_alloc(), PAGE_FLAGS) + proc_run(space, entry, stack_top) end diff --git a/kernel/shell.rv b/kernel/shell.rv index 9d3d95d..8d9019f 100644 --- a/kernel/shell.rv +++ b/kernel/shell.rv @@ -1,13 +1,13 @@ # this is just a simple prompt to test that shit is working -fn cmd_help() puts("commands: help, clear, bars, echo <text>, time, run, zoom in|out\n") +fn cmd_help() puts("commands: help, clear, bars, echo <text>, time, mem, uptime, ps, run, zoom in|out\n") -fn zoom_by(d) do - let s = con.scale + d - if s < 1 do s = 1 end - if s > 6 do s = 6 end - con.scale = s +fn zoom_by(delta) do + let scale = con.scale + delta + if scale < 1 do scale = 1 end + if scale > 6 do scale = 6 end + con.scale = scale cmd_clear() - puts("zoom " ~ s ~ "x\n") + puts("zoom " ~ scale ~ "x\n") end fn cmd_zoom(words) do @@ -30,25 +30,64 @@ fn cmd_bars() do puts("painted 8 bars from revo\n") end -fn bcd(b) (b shr 4) * 10 + (b band 15) +fn bcd(byte) (byte shr 4) * 10 + (byte band 15) fn rtc(reg) do outb(0x70, reg) inb(0x71) end fn cmd_time() puts("utc " ~ bcd(rtc(4)) ~ ":" ~ bcd(rtc(2)) ~ ":" ~ bcd(rtc(0)) ~ "\n") +# 0x prefixed 16 digit hex, matching the kernels serial writehex +fn hex(n) do + const digits = "0123456789abcdef" + let out = "" + for i in 0..16 do out = out ~ digits[(n shr ((15 - i) * 4)) band 15] end + "0x" ~ out +end + +fn mem_type_name(kind) do + if kind == 0 return "usable" + if kind == 1 return "reserved" + if kind == 2 return "acpi-reclaimable" + if kind == 3 return "acpi-nvs" + if kind == 4 return "bad" + if kind == 5 return "bootloader-reclaimable" + if kind == 6 return "kernel+modules" + if kind == 7 return "framebuffer" + "unknown" +end + +# the boot memory map dump, in revo now (called from kmain once the vm is up) +fn dump_memmap() do + puts("memory map:\n") + for i in 0..memmap_count() do + puts(" " ~ hex(memmap_base(i)) ~ " len=" ~ hex(memmap_len(i)) ~ " type=" ~ mem_type_name(memmap_kind(i)) ~ "\n") + end + puts("usable: " ~ (mem_total() shr 20) ~ " MiB, free: " ~ (mem_free() shr 20) ~ " MiB\n") +end + +fn cmd_mem() puts((mem_free() shr 20) ~ " MiB free / " ~ (mem_total() shr 20) ~ " MiB usable\n") +fn cmd_uptime() puts(math.floor(uptime() / 100) ~ "s (" ~ uptime() ~ " ticks)\n") +fn cmd_ps() puts(proc_count() ~ " process(es) running\n") + fn run(line) do - if line:trim():len() == 0 do puts("> ") return :nil end + if line:trim():len() == 0 do puts("% ") return :nil end const words = line:split(" ") const cmd = words[0] + # `run` launches a process, its prompt is reprinted by on_tick when the process + # exits (so it lands below the programs output, not before it). return early to + # skip the trailing prompt here + if cmd == "run" do cmd_run() return :nil end match cmd | "help" => cmd_help() | "clear" => cmd_clear() | "bars" => cmd_bars() | "time" => cmd_time() - | "run" => cmd_run() + | "mem" => cmd_mem() + | "uptime" => cmd_uptime() + | "ps" => cmd_ps() | "zoom" => cmd_zoom(words) | "echo" => if line:len() > 5 puts(line:sub(5, line:len() - 5) ~ "\n") else puts("\n") | _ => puts("unknown command: " ~ cmd ~ "\n") - puts("> ") + puts("% ") end diff --git a/kernel/vmm.rv b/kernel/vmm.rv index d6673b3..ece5682 100644 --- a/kernel/vmm.rv +++ b/kernel/vmm.rv @@ -1,12 +1,12 @@ -# build the 4-level page tables for one user page -# everything here only writes small entries we construct, so it's f64-safe +# build the 4 level page tables for one user page +# everything here only writes small entries we construct, so its f64 safe const PTE_ADDR = 0x000FFFFFFFFFF000 fn pte_idx(virt, level) (virt shr (12 + 9 * level)) band 0x1ff -# next-level table phys under entry `i` of table `tbl`, creating it if absent -fn next_table(tbl, i) do - const slot = tbl + i * 8 +# next level table phys under entry `index` of table `table`, creating it if absent +fn next_table(table, index) do + const slot = table + index * 8 const entry = mem_read(slot, 8) if (entry band 1) != 0 return entry band PTE_ADDR const frame = frame_alloc() |
