knekt
knekt is the kernel core. most of what the kernel does lives in the named parts around it, and knekt is the piece that wires them together.
boot
GRUB boots the kernel through Multiboot into a short piece of hand-written
assembly, which sets up just enough of the machine to call knekt's
main. main wakes the machine a piece at a time, the
serial port, the framebuffer (punkt),
the keyboard, memory (jenna),
the interrupt table and the timer. then it tiles the screen into windows
(kakel), starts a shell in each
(skalman) along with the scheduler
(chrone), and brings up the
filesystem (jakel).
when things go wrong
a fault in a ring-3 program ends that program and nothing else. a fault in the kernel prints the vector, the error code, the faulting address and the instruction pointer over serial and halts. a fixed capacity in the kernel that fills up says so on the serial port rather than dropping work without a word.
ring 3
programs are static elf64 executables, usually read from
jakel. each runs in ring 3 with page
tables, a kernel stack and a heap of its own, and talks to the kernel through the
syscall instruction. in coff's --elf mode a program reaches
them through builtins such as win_info() and
readfile().
system calls
| num | name | args | returns |
|---|---|---|---|
| 0 | SYS_EXIT | none | does not return |
| 1 | SYS_DEBUG_PRINT | str | none, the text goes to the program's window |
| 2 | SYS_WIN_INFO | none | width * 65536 + height |
| 3 | SYS_FILL | x, y, w, h, color | none |
| 4 | SYS_KEY_POLL | none | make_code * 2 + is_break or -1 |
| 5 | SYS_BLIT | buf, x, y, w, h | none |
| 6 | SYS_ALLOC | size | address of zeroed memory, or 0 if exhausted |
| 7 | SYS_TICKS | none | the kernel's monotonic ~100hz pit tick count |
| 8 | SYS_READFILE | name, buf, max | bytes read, or the size when buf is 0, or -1 |
| 9 | SYS_PRESENT | buf | 0, or -1 with no window |
| 10 | SYS_WIN_MAX | none | width * 65536 + height |
| 11 | SYS_MOUSE_POLL | none | (x * 1024 + y) * 8 + buttons, window-relative, or -1 when the pointer is not over the window |
| 12 | SYS_GLYPH | ch, buf | cell width * 65536 + cell height, and the glyph's rows written to buf |
| 13 | SYS_DEALLOC | ptr | 0, or -1 when ptr is not the start of a live block |
| 14 | SYS_SOUND | buf, len | bytes queued for oljud, or the bytes still waiting when buf is 0, or with len -1 as well, stops all sound and returns what was dropped, and -1 with no sound card |
| 15 | SYS_WRITEFILE | name, buf, len | len, or -1 |
| 16 | SYS_SLEEP | ticks | 0, after the ticks have passed |
| 17 | SYS_ARGC | none | how many arguments the task was started with |
| 18 | SYS_ARGV | i | argument i in the task's own memory, or 0 |
| 19 | SYS_LISTDIR | path, buf, max | how many entries were written, or -1 when the path is not a directory |
| 20 | SYS_SPAWN | line | the new task's id, or a negative error |
| 21 | SYS_PROTECT | addr, pages, mode | 0, or -1 when a page is not the task's own heap |
the drawing calls take coordinates relative to the program's own window. a
program draws a whole frame into its own buffer and shows it with one
SYS_PRESENT, which is also why SYS_GLYPH hands over a
font bitmap instead of drawing text. keys reach a program only while its
tavla has focus, through a queue of its
own.