hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-25 21:21:09 +0200
committerhachem <im@hachem.wtf>2026-09-25 21:21:09 +0200
commit09982d80c45805715984cc1cae96c37e4fc148c3 (patch)
treef711d6e7f4d4cb2d4dcb555d6a139aae343d7334 /kernel
parentfd3f51eecaecc12806a573c38263df1de43ee8c2 (diff)
feat: scheduler + cleanup
Diffstat (limited to 'kernel')
-rw-r--r--kernel/console.rv76
-rw-r--r--kernel/font.rv60
-rw-r--r--kernel/input.rv65
-rw-r--r--kernel/main.rv7
-rw-r--r--kernel/proc.rv36
-rw-r--r--kernel/shell.rv61
-rw-r--r--kernel/vmm.rv10
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()