aboutsummaryrefslogtreecommitdiff
path: root/NOTES.md
blob: 34637297692e36b0d1892faaf505639f225be338 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# Strix OS — Developer Notes

> **READ THIS FIRST after a context reset.** Then read `PLAN.md` for the full roadmap.
> Updated at every commit.

---

## How to Resume After Context Reset

1. Read this file top-to-bottom
2. Read `PLAN.md` — check the Progress Tracker table for current status
3. Run `cargo test` from `StrixKernel/` to confirm current build state
4. Continue from the first `🔲 TODO` item in PLAN.md

---

## Current Status

**Branch**: `CLAUDE_TEST`
**Phase**: Phase 2 — User Space Foundation
**Last commit**: `[Phase 2.2/2.3] SYSCALL/SYSRET MSR setup + syscall dispatcher`
**Next task**: `[Phase 2.4]` — Process structure (task/process.rs)

---

## Key Decisions & Rationale

| Decision | Rationale |
|----------|-----------|
| ext4 as primary filesystem | Nix requires symlinks, xattrs, POSIX perms; ext4 covers all. Impl as ext2 first |
| SYSCALL/SYSRET for syscall interface | Faster than int 0x80; Linux ABI compatible |
| GDT segment order: kcode/kdata/udata/ucode/tss | Required for STAR MSR arithmetic (see Phase 2.1 notes) |
| Heap 100 KiB → 4 MiB | Process table (256 entries) + 64 KiB kernel stacks needs > 16 MiB; start at 4 MiB |
| goblin crate for ELF parsing | no_std compatible, well-maintained, handles ELF64 |
| Embedded busybox initramfs | Self-contained rescue shell; no disk dependency for Phase 3 testing |
| OpenRC default init, `init=` configurable | Lightweight; swappable without kernel changes |
| W^X enforced on all mappings | Prevents code injection via data segments |
| All user pointers validated | Prevents kernel memory disclosure/corruption via syscalls |

---

## Architecture Notes

### GDT Segment Order (Critical for SYSCALL/SYSRET)
```
0x00: null
0x08: kernel code (DPL=0)  ← STAR[47:32]
0x10: kernel data (DPL=0)  ← auto: SYSCALL sets SS = CS+8
0x18: user data (DPL=3)    ← SYSRET: SS = STAR[63:48]+8
0x20: user code (DPL=3)    ← SYSRET: CS = STAR[63:48]+16
0x28/0x30: TSS (128-bit)
```
STAR MSR values: `STAR[47:32]=0x08`, `STAR[63:48]=0x10`

### Heap Layout
```
HEAP_START = 0x4444_4444_0000
HEAP_SIZE  = 4 MiB (was 100 KiB)
```

### Key Virtual Address Constants
```
Physical memory offset: 0x0000_2560_0000_0000 (from bootloader)
Heap start:             0x4444_4444_0000
User stack top:         0x7fff_f000_0000 (8 MiB stack)
User address limit:     0x0000_8000_0000_0000 (canonical boundary)
```

---

## Log

### [Step 0] 2026-04-08 — Bootstrap repo docs
**Done**: Created `PLAN.md` (full roadmap with progress tracker) and `NOTES.md` (this file).
**Next**: Phase 2.1 — Extend GDT.
**Decisions**: None new.

### [Phase 2.2/2.3] 2026-04-08 — SYSCALL/SYSRET MSR setup + dispatcher
**Done**:
- `src/syscall/mod.rs`: configure STAR/LSTAR/SFMASK/EFER.SCE MSRs
- Naked assembly `syscall_entry_asm`: swapgs, save user RSP, load kernel RSP, remap r10→rcx for arg4, call `syscall_handler`, restore, sysretq
- `src/syscall/dispatch.rs`: dispatcher with `write(1)`, `exit(60)`, `exit_group(231)`; unknown → `-ENOSYS`
- `sys_write`: validates user pointer before dereference; uses `read_volatile` to avoid aliasing UB
- Registered `syscall::init()` + `syscall::init_kernel_stack()` in `strix_os::init()`
- All existing integration tests still pass in QEMU
**Next**: Phase 2.4 — Process structure
**Decisions**:
- Use `swapgs` pattern for user/kernel GS switching (per-CPU scratch for user RSP)
- `sys_write` uses raw pointer + `read_volatile` loop (not `&[u8]` slice) on user memory
- `sys_exit` currently halts; Phase 2.5 will add proper process termination

### [Phase 2.1] 2026-04-08 — GDT user space segments + heap growth
**Done**:
- Restructured `StrixKernel/src/gdt.rs`: added `kernel_data`, `user_data`, `user_code` segments in the correct order for SYSCALL/SYSRET ABI
- Added `TSS.privilege_stack_table[0]` (RSP0) with an 8 KiB static initial stack
- Exposed `GDT` static and `Selectors` fields as `pub` for use by syscall setup
- Added `set_kernel_stack(VirtAddr)` for the scheduler to update RSP0 per-process
- Grew `HEAP_SIZE` from 100 KiB → 4 MiB in `allocator.rs` (needed for process table)
- Fixed pre-existing lifetime lint in `allocator.rs`
- Updated `flake.nix` to add `cpio`, `busybox`, `gdb`, `binutils`, `e2fsprogs`
- `basic_boot` integration test passes in QEMU via `nix develop`
**Next**: Phase 2.2 — SYSCALL/SYSRET MSR setup (`src/syscall/mod.rs`)
**Decisions**:
- GDT order: kernel_code(0x08) / kernel_data(0x10) / user_data(0x18) / user_code(0x20) / TSS(0x28)
- STAR MSR: `[47:32]=0x08`, `[63:48]=0x10` → SYSRET CS=0x20, SS=0x18
- `set_kernel_stack` uses raw pointer write inside `unsafe {}` block; safe when interrupts disabled

---