code wiki / _hdl_build / nx_strap_emit.nx

nx_strap_emit.nx source

↩ module page · 176 lines · 9901 B

1// nx_strap_emit.nx -- S-MODE TRAP DELEGATION + sret (X-PAGE-STRAP-001). The real-OS trap path: instead 2// of every trap going to the M-mode monitor, an exception is DELEGATED (medeleg) to the S-mode kernel, 3// which handles it at stvec and returns with sret. Sequence: M-mode installs mtvec(=M handler) + 4// stvec(=S handler) + medeleg + drops to U-mode (mret, MPP=U); the U program ecalls; with the ecall-from-U 5// bit set in medeleg the trap vectors to the S-MODE handler (stvec), which confirms scause==8, prints 6// "STRAP", advances sepc+4, and sret's back to U; the U program then halts (finisher) -- reaching the 7// finisher PROVES sret returned. With medeleg=0 (the gate's control) the trap goes to the M-mode handler 8// instead -> "MTRAP", no STRAP. 9// medeleg (argv[1]) -- default 0x100 (delegate ecall-from-U, cause 8). out-path (argv[2]). 10// Sovereign, no gcc/.sh. license_tier: ORIGINAL 11import "nx_syscalls.nx" 12const ST_MAGIC_8192: i64 = 8192 13 14const ST_OUT: *u8 = "runtime/_hdl_build/_strap_virt.bin" 15const ST_GOLD: *u8 = "runtime/_hdl_build/_strap_virt.bin.gold" 16const ST_LOG: *u8 = "knowledge/status/priv.log" 17 18const ST_UART: i64 = 0x10000000 19const ST_FIN: i64 = 0x100000 20const ST_PASS: i64 = 0x5555 21const ST_MEM_BASE: i64 = 0x80000000 22const ST_CSR_MSTATUS: i64 = 0x300 23const ST_CSR_MTVEC: i64 = 0x305 24const ST_CSR_MEPC: i64 = 0x341 25const ST_CSR_STVEC: i64 = 0x105 26const ST_CSR_SEPC: i64 = 0x141 27const ST_CSR_SCAUSE: i64 = 0x142 28const ST_CSR_MEDELEG: i64 = 0x302 29const ST_MRET: i64 = 0x30200073 30const ST_SRET: i64 = 0x10200073 31const ST_ECALL: i64 = 0x00000073 32const ST_MPP_U: i64 = 0 33const ST_ECALL_U_CAUSE: i64 = 8 34 35const RV_X0: i64 = 0 36const RV_T0: i64 = 5 37const RV_T1: i64 = 6 38const RV_T3: i64 = 28 39const RV_T4: i64 = 29 40const RV_T5: i64 = 30 41 42func st_lui(rd: i64, imm20: i64) -> i64 { return ((imm20 & 0xFFFFF) << 12) | (rd << 7) | 0x37 } 43func st_addi(rd: i64, rs1: i64, imm: i64) -> i64 { return ((imm & 0xFFF) << 20) | (rs1 << 15) | (rd << 7) | 0x13 } 44func st_store(rs2: i64, rs1: i64, f3: i64, imm: i64) -> i64 { 45 let hi: i64 = ((imm >> 5) & 0x7f) << 25 46 let lo: i64 = (imm & 0x1f) << 7 47 return hi | (rs2 << 20) | (rs1 << 15) | (f3 << 12) | lo | 0x23 48} 49func st_branch(rs1: i64, rs2: i64, f3: i64, imm: i64) -> i64 { 50 let b12: i64 = ((imm >> 12) & 0x1) << 31 51 let b11: i64 = ((imm >> 11) & 0x1) << 7 52 let b10_5: i64 = ((imm >> 5) & 0x3f) << 25 53 let b4_1: i64 = ((imm >> 1) & 0xf) << 8 54 return b12 | b10_5 | (rs2 << 20) | (rs1 << 15) | (f3 << 12) | b4_1 | b11 | 0x63 55} 56func st_jal(rd: i64, imm: i64) -> i64 { 57 let b20: i64 = ((imm >> 20) & 0x1) << 31 58 let b19_12: i64 = ((imm >> 12) & 0xff) << 12 59 let b11: i64 = ((imm >> 11) & 0x1) << 20 60 let b10_1: i64 = ((imm >> 1) & 0x3ff) << 21 61 return b20 | b10_1 | b11 | b19_12 | (rd << 7) | 0x6f 62} 63func st_slli(rd: i64, rs1: i64, shamt: i64) -> i64 { return ((shamt & 0x3f) << 20) | (rs1 << 15) | (1 << 12) | (rd << 7) | 0x13 } 64func st_srli(rd: i64, rs1: i64, shamt: i64) -> i64 { return ((shamt & 0x3f) << 20) | (rs1 << 15) | (5 << 12) | (rd << 7) | 0x13 } 65func st_csrrw(rd: i64, csr: i64, rs1: i64) -> i64 { return ((csr & 0xfff) << 20) | (rs1 << 15) | (1 << 12) | (rd << 7) | 0x73 } 66func st_csrrs(rd: i64, csr: i64, rs1: i64) -> i64 { return ((csr & 0xfff) << 20) | (rs1 << 15) | (2 << 12) | (rd << 7) | 0x73 } 67func st_w32(buf: *u8, off: i64, w: i64) -> i64 { buf[off]=(w&0xff) as u8; buf[off+1]=((w>>8)&0xff) as u8; buf[off+2]=((w>>16)&0xff) as u8; buf[off+3]=((w>>24)&0xff) as u8; return off+4 } 68func st_li32(buf: *u8, off: i64, rd: i64, val: i64) -> i64 { 69 var hi: i64 = (val >> 12) & 0xFFFFF 70 var lo: i64 = val & 0xFFF 71 if lo >= 0x800 { lo = lo - 0x1000; hi = (hi + 1) & 0xFFFFF } 72 var o: i64 = st_w32(buf, off, st_lui(rd, hi)) 73 o = st_w32(buf, o, st_addi(rd, rd, lo)) 74 return o 75} 76func st_li32u(buf: *u8, off: i64, rd: i64, val: i64) -> i64 { 77 var o: i64 = st_li32(buf, off, rd, val) 78 o = st_w32(buf, o, st_slli(rd, rd, 32)) 79 o = st_w32(buf, o, st_srli(rd, rd, 32)) 80 return o 81} 82func st_emit_str(buf: *u8, off: i64, s: *u8, n: i64) -> i64 { 83 var o: i64 = off 84 var i: i64 = 0 85 while i < n { o = st_w32(buf, o, st_addi(RV_T1, RV_X0, s[i] as i64)); o = st_w32(buf, o, st_store(RV_T1, RV_T0, 0, 0)); i = i + 1 } 86 return o 87} 88func st_fin(buf: *u8, off: i64) -> i64 { // li FIN; li PASS; sw; (caller adds jal) 89 var o: i64 = st_li32(buf, off, RV_T5, ST_FIN) 90 o = st_li32(buf, o, RV_T1, ST_PASS) 91 o = st_w32(buf, o, st_store(RV_T1, RV_T5, 2, 0)) 92 return o 93} 94func st_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 95func st_fn(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(fd,"-" as *u8,1)}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48;k=1}; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(fd,bb,k); return 0 } 96 97// pos_out[0]=USER [1]=SHANDLER [2]=NOTS [3]=MHANDLER [4]=HALT 98func st_emit_image(buf: *u8, user_off: i64, sh_off: i64, nots_off: i64, mh_off: i64, halt_off: i64, pos_out: *i64, medeleg: i64) -> i64 { 99 var o: i64 = 0 100 o = st_w32(buf, o, st_lui(RV_T0, ST_UART >> 12)) // t0 = UART 101 o = st_li32u(buf, o, RV_T1, ST_MEM_BASE + mh_off) // mtvec = &m_handler 102 o = st_w32(buf, o, st_csrrw(RV_X0, ST_CSR_MTVEC, RV_T1)) 103 o = st_li32u(buf, o, RV_T1, ST_MEM_BASE + sh_off) // stvec = &s_handler 104 o = st_w32(buf, o, st_csrrw(RV_X0, ST_CSR_STVEC, RV_T1)) 105 o = st_li32(buf, o, RV_T1, medeleg) // medeleg (delegate ecall-from-U?) 106 o = st_w32(buf, o, st_csrrw(RV_X0, ST_CSR_MEDELEG, RV_T1)) 107 o = st_li32u(buf, o, RV_T1, ST_MEM_BASE + user_off) // mepc = &user 108 o = st_w32(buf, o, st_csrrw(RV_X0, ST_CSR_MEPC, RV_T1)) 109 o = st_li32(buf, o, RV_T1, ST_MPP_U) // mstatus = MPP=U 110 o = st_w32(buf, o, st_csrrw(RV_X0, ST_CSR_MSTATUS, RV_T1)) 111 o = st_w32(buf, o, ST_MRET) 112 pos_out[0] = o // USER (U-mode) 113 o = st_w32(buf, o, ST_ECALL) // syscall -> delegated (S) or not (M) 114 o = st_w32(buf, o, st_jal(RV_X0, halt_off - o)) // on sret-return, fall to HALT (proves sret) 115 pos_out[1] = o // S_HANDLER (stvec, S-mode) 116 o = st_w32(buf, o, st_csrrs(RV_T3, ST_CSR_SCAUSE, RV_X0)) // t3 = scause 117 o = st_li32(buf, o, RV_T4, ST_ECALL_U_CAUSE) // t4 = 8 118 let pcb: i64 = o 119 o = st_w32(buf, o, st_branch(RV_T3, RV_T4, 1, nots_off - pcb)) // bne -> NOTS 120 o = st_emit_str(buf, o, "STRAP" as *u8, 5) // an ecall-from-U handled in S-MODE 121 o = st_w32(buf, o, st_csrrs(RV_T1, ST_CSR_SEPC, RV_X0)) // sepc += 4 (skip past the ecall) 122 o = st_w32(buf, o, st_addi(RV_T1, RV_T1, 4)) 123 o = st_w32(buf, o, st_csrrw(RV_X0, ST_CSR_SEPC, RV_T1)) 124 o = st_w32(buf, o, ST_SRET) // return to U-mode 125 pos_out[2] = o // NOTS 126 o = st_emit_str(buf, o, "SX" as *u8, 2) 127 o = st_w32(buf, o, st_jal(RV_X0, halt_off - o)) 128 pos_out[3] = o // M_HANDLER (mtvec, M-mode: not delegated) 129 o = st_emit_str(buf, o, "MTRAP" as *u8, 5) 130 o = st_w32(buf, o, st_jal(RV_X0, halt_off - o)) 131 pos_out[4] = o // HALT 132 o = st_fin(buf, o) 133 o = st_w32(buf, o, st_jal(RV_X0, 0)) 134 return o 135} 136 137func st_parse_num(s: *u8) -> i64 { 138 var q: i64 = 0; var val: i64 = 0 139 if s[0] == (48 as u8) { if s[1] == (120 as u8) { 140 q = 2 141 var go: i64 = 1 142 while go == 1 { let c: i64 = s[q] as i64; var d: i64 = 0-1; if c>=48 { if c<=57 { d=c-48 } } if c>=97 { if c<=102 { d=c-87 } } if c>=65 { if c<=70 { d=c-55 } } if d<0 { go=0 } else { val=val*16+d; q=q+1 } } 143 return val 144 }} 145 var go2: i64 = 1 146 while go2 == 1 { let c: i64 = s[q] as i64; if c>=48 { if c<=57 { val=val*10+(c-48); q=q+1 } else { go2=0 } } else { go2=0 } } 147 return val 148} 149 150func main(argc: i64, argv: *i64) -> i64 { 151 var medeleg: i64 = 0x100 // default: delegate ecall-from-U (cause 8) to S-mode 152 var outp: *u8 = ST_OUT 153 if argc >= 2 { medeleg = st_parse_num(argv[1] as *u8) } 154 if argc >= 3 { outp = argv[2] as *u8 } 155 let scratch: *u8 = sys_mmap(ST_MAGIC_8192) 156 let pos: *i64 = sys_mmap(40) as *i64 157 st_emit_image(scratch, 0, 0, 0, 0, 0, pos, medeleg) 158 let user_off: i64 = pos[0] 159 let sh_off: i64 = pos[1] 160 let nots_off: i64 = pos[2] 161 let mh_off: i64 = pos[3] 162 let halt_off: i64 = pos[4] 163 let buf: *u8 = sys_mmap(ST_MAGIC_8192) 164 let sz: i64 = st_emit_image(buf, user_off, sh_off, nots_off, mh_off, halt_off, pos, medeleg) 165 let fd: i64 = sys_openat_wr(outp, MODE_0644) 166 if fd < 0 { st_p("STRAPEMIT verdict=RED reason=out-unwritable\n" as *u8); return 1 } 167 sys_write(fd, buf, sz); sys_close(fd) 168 let gold: *u8 = sys_mmap(8) 169 gold[0]=83 as u8; gold[1]=84 as u8; gold[2]=82 as u8; gold[3]=65 as u8; gold[4]=80 as u8 // "STRAP" 170 let gfd: i64 = sys_openat_wr(ST_GOLD, 420) 171 if gfd >= 0 { sys_write(gfd, gold, 5); sys_close(gfd) } 172 st_p("STRAPEMIT name=" as *u8); st_p(outp); st_p(" bytes=" as *u8); st_fn(1, sz); st_p(" (S-mode trap delegation + sret)\n" as *u8) 173 let lf: i64 = sys_openat_append(ST_LOG, 420) 174 if lf >= 0 { var n: i64=0; let m: *u8="STRAPEMIT authored _strap_virt.bin golden=STRAP\n" as *u8; while m[n]!=(0 as u8){n=n+1} sys_write(lf,m,n); sys_close(lf) } 175 return 0 176}