nx_nishios_userspace.nx
buildroot/runtime/nx_nishios_userspace.nx
about
nx_nishios_userspace.nx -- NishiOS rung-9: BARE-METAL USERSPACE (the kernel<->user privilege boundary).
The essence of "userspace running ON the kernel" (not under Linux): a user program runs at ring 3 and
can only touch privileged resources THROUGH the kernel via syscalls. The emu gains a privilege level
(cpl), a syscall TRAP (user 0F05 -> save return, cpl=0, vector to the kernel handler via LSTAR), sysret
(0F07 -> cpl=3, back to user), and a WRITE-PRIVILEGE CHECK (a store to the kernel region at cpl!=0
FAULTS). The user program: (1) tries to write the kernel buffer DIRECTLY -> faults/blocked; (2) asks
the kernel to write it via syscall -> the kernel does it on the user's behalf.
KAT: the direct privileged write is BLOCKED (fault raised, value never lands); the syscall write
SUCCEEDS (kernel wrote it); only the kernel-mediated value is in the buffer; clean exit. => the
privilege boundary is real: userspace reaches the hardware only through the kernel.
HONEST SCOPE: a minimal ring0/ring3 + one syscall (kwrite); full process model (multiple tasks, memory
isolation per process, ELF loading) is the continuation. No hw writes (Rule 26). expect_exit: 0 tier: ORIGINAL
dependencies 2 imports · 0 importers
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
structs
| none |
consts
| 15 | const K_MAGIC_2000000: i64 = 2000000 |
| 16 | const K_MAGIC_2048: i64 = 2048 |
| 17 | const K_MAGIC_2064: i64 = 2064 |
| 18 | const K_MAGIC_2056: i64 = 2056 |
| 19 | const K_MAGIC_4096: i64 = 4096 |
| 20 | const K_MAGIC_16384: i64 = 16384 |
functions
| 22 | func us_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } |
| 27 | func us_num(v: i64) -> i64 { nxi_out(v); return 0 } |
| 28 | func us_b(c: *u8, o: i64, b: i64) -> i64 { c[o]=(b & 0xff) as u8; return o+1 } called by 1: main |
| 29 | func us_i32(c: *u8, o: i64, v: i64) -> i64 { c[o]=(v&0xff) as u8; c[o+1]=((v>>8)&0xff) as u8; c[o+2]=((v>>16)&0xff) as u8; c[o+3]=((v>>24)&0xff) as u8; return o+4 } called by 1: main |
| 30 | func us_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 1: emu_user |
| 31 | func us_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_user |
| 32 | func us_i32r(code: *u8, off: i64) -> i64 { var v: i64=(code[off] as i64)|((code[off+1] as i64)<<8)|((code[off+2] as i64)<<16)|((code[off+3] as i64)<<24); if (v & 0x80000000)!=0 { v=v-(1<<32) } return v } called by 1: emu_user |
| 36 | func emu_user(code: *u8, len: i64, mem: *u8) -> i64 |
| 69 | func main() -> i64 |