code wiki / _hdl_build / nx_bootcap.nx

nx_bootcap.nx source

↩ module page · 90 lines · 4589 B

1// nx_bootcap.nx -- ONE boot-and-capture primitive for every organ that needs to know what the 2// live kernel actually SAID. 3// 4// WHY: measuring a kernel means booting the ARTIFACT and reading its serial -- not parsing a log 5// ABOUT the artifact, which can be stale, written by a different build, or absent entirely. That 6// boot-and-capture block had already been copy-pasted into nx_nishios_kernel_gate and 7// nx_kernel_adoption and was about to land in nx_kernel_census as a third copy; three copies of a 8// measurement primitive is three chances for the rulers to silently disagree about what booted. 9// 10// Also owns the TWO-ROOTS resolution: the buildroot keeps the image under runtime/_hdl_build/ 11// while the live serving root keeps it at ./ -- one name, two roots. Callers get the resolved 12// path back so they can PRINT which artifact they actually measured; a ruler that will not say 13// which artifact it read is not reporting a measurement. 14// license_tier: ORIGINAL 15import "rv64im_min_sim.nx" 16import "rv64im_min_csr.nx" 17import "rv64im_min_clint.nx" 18import "rv64im_min_uart.nx" 19import "rv64im_min_virtio.nx" 20import "rv64im_min_nvme.nx" 21 22const BOOTCAP_MEM_BASE: i64 = 0x80000000 23const BOOTCAP_MEM_SIZE: i64 = 65536 24const BOOTCAP_MAX_STEPS: i64 = 100000 25// res[] slots the caller reads back 26const BOOTCAP_R_HALTED: i64 = 0 27const BOOTCAP_R_CODE: i64 = 1 28const BOOTCAP_R_STEPS: i64 = 2 29const BOOTCAP_R_TXN: i64 = 3 30const BOOTCAP_R_N: i64 = 4 31 32// Boot `img` on a FRESH machine (every device re-allocated, so run N cannot contaminate run N+1 33// -- the negative-control runs depend on that isolation) and capture the UART. Returns tx count. 34func bootcap_run(img: *u8, ilen: i64, tx_buf: *u8, txcap: i64, res: *i64) -> i64 { 35 let rf_storage: *i64 = (sys_mmap(8 * NX_RV64IM_RF_N_REGS)) as *i64 36 let csr_storage: *i64 = (sys_mmap(8 * NX_CSR_SLOT_N)) as *i64 37 let clint_storage: *i64 = (sys_mmap(8 * NX_CLINT_SLOT_N)) as *i64 38 let uart_storage: *i64 = (sys_mmap(8 * NX_UART_SLOT_N)) as *i64 39 let virtio_storage:*i64 = (sys_mmap(8 * NX_VIRTIO_SLOT_N)) as *i64 40 let vnet_storage: *i64 = (sys_mmap(8 * NX_VIRTIO_SLOT_N)) as *i64 41 let nvme_storage: *i64 = (sys_mmap(8 * NX_NVME_SLOT_N)) as *i64 42 let nndev_storage: *i64 = (sys_mmap(8 * NX_NNDEV_SLOT_N)) as *i64 43 let mmu_storage: *i64 = (sys_mmap(8 * NX_MMU_SLOT_N)) as *i64 44 let mem: *u8 = sys_mmap(BOOTCAP_MEM_SIZE) 45 let rf: *NxRv64imRegfile = (sys_mmap(64)) as *NxRv64imRegfile 46 let csr: *NxRv64imCsrFile = (sys_mmap(64)) as *NxRv64imCsrFile 47 let clint: *NxClint = (sys_mmap(64)) as *NxClint 48 let uart: *NxUart = (sys_mmap(64)) as *NxUart 49 let virtio:*NxVirtioMmio = (sys_mmap(64)) as *NxVirtioMmio 50 let vnet: *NxVirtioMmio = (sys_mmap(64)) as *NxVirtioMmio 51 let nvme: *NxNvmeCtrl = (sys_mmap(64)) as *NxNvmeCtrl 52 let nndev: *NxNnDev = (sys_mmap(64)) as *NxNnDev 53 let mmu: *NxMmu = (sys_mmap(64)) as *NxMmu 54 let sim: *NxRv64imSim = (sys_mmap(128)) as *NxRv64imSim 55 nx_rv64im_rf_init(rf, rf_storage) 56 nx_rv64im_csr_init(csr, csr_storage, 0) 57 nx_clint_init(clint, clint_storage) 58 nx_uart_init(uart, uart_storage, tx_buf, txcap) 59 nx_virtio_init(virtio, virtio_storage) 60 nx_virtio_init_net(vnet, vnet_storage) 61 nx_nvme_init(nvme, nvme_storage) 62 nx_nndev_init(nndev, nndev_storage) 63 nx_mmu_init(mmu, mmu_storage) 64 nx_rv64im_sim_init(sim, rf, csr, clint, uart, BOOTCAP_MEM_BASE, mem, BOOTCAP_MEM_SIZE, 0) 65 nx_rv64im_sim_attach_virtio(sim, virtio) 66 nx_rv64im_sim_attach_virtio_net(sim, vnet) 67 nx_rv64im_sim_attach_nvme(sim, nvme) 68 nx_rv64im_sim_attach_nndev(sim, nndev) 69 nx_rv64im_sim_attach_mmu(sim, mmu) 70 var i: i64 = 0 71 while i < ilen { mem[i] = img[i]; i = i + 1 } 72 nx_rv64im_sim_run(sim, BOOTCAP_MAX_STEPS) 73 let cnt: i64 = nx_uart_tx_count(uart) 74 res[BOOTCAP_R_HALTED] = sim.halted 75 res[BOOTCAP_R_CODE] = sim.halt_code 76 res[BOOTCAP_R_STEPS] = sim.steps 77 res[BOOTCAP_R_TXN] = cnt 78 return cnt 79} 80 81// Resolve the kernel image across the two roots. Returns the buffer (0 if neither exists) and 82// writes the byte length to lenp[0]; `outpath` receives which path actually answered. 83func bootcap_load(primary: *u8, alt: *u8, lenp: *i64, outpath: *i64) -> *u8 { 84 var img: *u8 = sys_read_file(primary, lenp) 85 if lenp[0] > 0 { outpath[0] = primary as i64; return img } 86 img = sys_read_file(alt, lenp) 87 if lenp[0] > 0 { outpath[0] = alt as i64; return img } 88 outpath[0] = primary as i64 89 return 0 as *u8 90}