code wiki / _hdl_build / nx_nishi_usb_os.nx

nx_nishi_usb_os.nx

buildroot/runtime/_hdl_build/nx_nishi_usb_os.nx

20581 B318 linesdepth 3pulls 3 transitivereach 0 importersview sourcekind tooltopic nishi
docsdependenciesstructsconstsfunctions

about

nx_nishi_usb_os.nx -- x86 ladder R-KERN-4: INTEGRATION -- one booted kernel that runs a userland. The kernel-internals rungs proved GDT/IDT (R-KERN-1), paging (R-KERN-2), and preemption (R-KERN-3) SEPARATELY. This fuses them into ONE kernel, loaded off the persisted image, that performs the full OS bring-up and then runs userland tasks: boot (MBR -> INT 13h load -> kernel) -> LONG mode -> lgdt (GDT) -> build the IDT in RAM with a TIMER gate (0x20) AND a SYSCALL gate (0x80) -> lidt -> build page tables + load CR3 -> STI -> launch. Then two userland tasks run preemptively (timer-driven, round-robin); each loops incrementing its own counter and issues `int 0x80`, which VECTORS THROUGH THE KERNEL'S IDT to the syscall handler the kernel installed -- the handler services it (increments a kernel-side syscall counter) and IRETs back. KAT: ONE kernel did it all -- (T1) booted off disk to LONG mode; (T2) lgdt loaded the GDT; (T3) lidt loaded the IDT and the syscall gate points at the kernel's handler; (T4) CR3 + the page walk works; (T5) BOTH userland tasks ran (preemptive multitasking); (T6) the tasks' syscalls were SERVICED by the kernel's handler (kernel-side count > 0). NEG/liar-kill (T7): with the timer masked, task B never runs. HONEST SCOPE: like the other rungs, the context switch + the IF-gated timer are modeled (as nx_kernel_sched), and the IDT here uses 8-byte handler slots (R-KERN-1 already proved the full split-field gate); the syscall path (task -> IDT[0x80] -> kernel handler -> iret) is genuinely vectored. The shared syscall counter is intentionally unlocked, so a preempt mid-increment can race (a lower bound, and an honest demonstration of why kernels CLI/lock in handlers). NEVER-BRICK (Rule 26): writes a FILE; INT 13h *reads* only; no /dev. expect_exit: 0 license_tier: ORIGINAL

dependencies 2 imports · 0 importers

nx_syscalls.nx nx_itoa_lib.nx nx_nishi_usb_os.nx

imports: nx_syscalls.nxnx_itoa_lib.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main os_puts sys_write sys_mmap build_image uf_movr emit_pte uf_movr ↻ wr16 wr64 wr32 sys_openat_wr sys_exit sys_write ↻ sys_close os_read sys_openat_rd sys_read sys_close ↻ run sys_mmap ↻ emu_os sys_mmap ↻ os_st64 os_ld16 os_ld64 os_mode pg_walk os_ld64 ↻ os_num nxi_out nxi_fd sys_mmap ↻ ccz_cat_num sys_write ↻ sys_munmap

structs

none

consts

25const IMG_MAGIC_200000: i64 = 200000
26const IMG_MAGIC_200001: i64 = 200001
27const IMG_MAGIC_32767: i64 = 32767
28const IMG_MAGIC_65536: i64 = 65536
29const IMG_MAGIC_5000000: i64 = 5000000
30const IMG_MAGIC_5000001: i64 = 5000001
51const IMG_SZ: i64 = 1024
52const IDT_BASE: i64 = 0xD000
53const SYS_SLOT: i64 = 0xD400 // IDT_BASE + 0x80*8
54const SYSCOUNT: i64 = 0xC000
55const STACK_A: i64 = 0x6000
56const STACK_B: i64 = 0x6800

functions

32func os_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
called by 1: main calls 1: sys_write
37func os_num(v: i64) -> i64 { nxi_out(v); return 0 }
called by 1: main calls 1: nxi_out
38func os_mode(cr0: i64, efer: i64) -> i64 { let pe: i64=cr0&1; let pg: i64=(cr0>>31)&1; let lme: i64=(efer>>8)&1; if pe==0 { return 0 } if pg==1 { if lme==1 { return 2 } } return 1 }
called by 1: emu_os
39func os_st64(mem: *u8, a: i64, v: i64) -> i64 { var i: i64=0; while i<8 { mem[a+i]=((v>>(i*8))&0xff) as u8; i=i+1 } return 0 }
called by 1: emu_os
40func os_ld64(mem: *u8, a: i64) -> i64 { var v: i64=0; var i: i64=0; while i<8 { v=v|((mem[a+i] as i64)<<(i*8)); i=i+1 } return v }
called by 2: pg_walkemu_os
41func os_ld16(mem: *u8, a: i64) -> i64 { return (mem[a] as i64) | ((mem[a+1] as i64)<<8) }
called by 1: emu_os
43func pg_walk(mem: *u8, cr3: i64, va: i64) -> i64
called by 1: emu_os calls 1: os_ld64
61func emu_os(mem: *u8, disk: *u8, entry: i64, taskA: i64, taskB: i64, timer_on: i64, st: *i64, loaded: *i64) -> i64
151func uf_movr(img: *u8, base: i64, o: i64, modrm: i64, imm: i64) -> i64
called by 2: emit_ptebuild_image
156func emit_pte(img: *u8, base: i64, o: i64, val: i64, addr: i64) -> i64
called by 1: build_image calls 1: uf_movr
162func wr16(img: *u8, a: i64, v: i64) -> i64 { img[a]=(v&0xff) as u8; img[a+1]=((v>>8)&0xff) as u8; return 0 }
called by 1: build_image
163func wr64(img: *u8, a: i64, v: i64) -> i64 { var i: i64=0; while i<8 { img[a+i]=((v>>(i*8))&0xff) as u8; i=i+1 } return 0 }
called by 1: build_image
164func wr32(img: *u8, a: i64, v: i64) -> i64 { var i: i64=0; while i<4 { img[a+i]=((v>>(i*8))&0xff) as u8; i=i+1 } return 0 }
called by 1: build_image
167func build_image(img: *u8, info: *i64) -> i64
called by 1: main calls 5: uf_movremit_ptewr16wr64wr32
256func os_read(path: *u8, out: *u8, cap: i64) -> i64
called by 1: main calls 3: sys_openat_rdsys_readsys_close
265func run(img: *u8, timer_on: i64, st: *i64, loaded: *i64) -> i64
called by 1: main calls 2: sys_mmapemu_os
274func main() -> i64