code wiki / _hdl_build / _nvme_diag.nx
_nvme_diag.nx source
↩ module page · 78 lines · 4241 B
1// _nvme_diag.nx -- diagnostic: load the NVMe image, run it on the sovereign emu, then DUMP the
2// NVMe controller storage + ACQ RAM so we can see whether the doorbell DMA posted the CQE.
3// Sovereign. license_tier: ORIGINAL
4import "rv64im_min_sim.nx"
5import "rv64im_min_csr.nx"
6import "rv64im_min_clint.nx"
7import "rv64im_min_uart.nx"
8import "rv64im_min_virtio.nx"
9import "rv64im_min_nvme.nx"
10
11const D_MEM_BASE: i64 = 0x80000000
12const D_MEM_SIZE: i64 = 65536
13const D_TX_CAP: i64 = 4096
14const D_MAX_STEPS: i64 = 100000
15
16func d_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
17func d_n(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; 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(1,bb,k); return 0 }
18func d_hex(v: i64) -> i64 { let d: *u8=sys_mmap(16); var i: i64=0; while i<8{let nib: i64=(v >> ((7-i)*4)) & 0xf; if nib<10{d[i]=(48+nib) as u8} else {d[i]=(87+nib) as u8} i=i+1}; sys_write(1,d,8); return 0 }
19
20func main(argc: i64, argv: *i64) -> i64 {
21 var binp: *u8 = "runtime/_hdl_build/_nvme_admin_virt.bin" as *u8
22 if argc >= 2 { binp = argv[1] as *u8 }
23 let lenp: *i64 = sys_mmap(16) as *i64
24 let img: *u8 = sys_read_file(binp, lenp)
25 let ilen: i64 = lenp[0]
26 if ilen <= 0 { d_p("diag: image missing\n" as *u8); sys_exit(1); return 1 }
27
28 let rf_storage: *i64 = (sys_mmap(8 * NX_RV64IM_RF_N_REGS)) as *i64
29 let csr_storage: *i64 = (sys_mmap(8 * NX_CSR_SLOT_N)) as *i64
30 let clint_storage: *i64 = (sys_mmap(8 * NX_CLINT_SLOT_N)) as *i64
31 let uart_storage: *i64 = (sys_mmap(8 * NX_UART_SLOT_N)) as *i64
32 let virtio_storage:*i64 = (sys_mmap(8 * NX_VIRTIO_SLOT_N)) as *i64
33 let vnet_storage: *i64 = (sys_mmap(8 * NX_VIRTIO_SLOT_N)) as *i64
34 let nvme_storage: *i64 = (sys_mmap(8 * NX_NVME_SLOT_N)) as *i64
35 let mem: *u8 = sys_mmap(D_MEM_SIZE)
36 let tx_buf: *u8 = sys_mmap(D_TX_CAP)
37 let rf: *NxRv64imRegfile = (sys_mmap(64)) as *NxRv64imRegfile
38 let csr: *NxRv64imCsrFile = (sys_mmap(64)) as *NxRv64imCsrFile
39 let clint: *NxClint = (sys_mmap(64)) as *NxClint
40 let uart: *NxUart = (sys_mmap(64)) as *NxUart
41 let virtio:*NxVirtioMmio = (sys_mmap(64)) as *NxVirtioMmio
42 let vnet: *NxVirtioMmio = (sys_mmap(64)) as *NxVirtioMmio
43 let nvme: *NxNvmeCtrl = (sys_mmap(64)) as *NxNvmeCtrl
44 let sim: *NxRv64imSim = (sys_mmap(128)) as *NxRv64imSim
45
46 nx_rv64im_rf_init(rf, rf_storage)
47 nx_rv64im_csr_init(csr, csr_storage, 0)
48 nx_clint_init(clint, clint_storage)
49 nx_uart_init(uart, uart_storage, tx_buf, D_TX_CAP)
50 nx_virtio_init(virtio, virtio_storage)
51 nx_virtio_init_net(vnet, vnet_storage)
52 nx_nvme_init(nvme, nvme_storage)
53 nx_rv64im_sim_init(sim, rf, csr, clint, uart, D_MEM_BASE, mem, D_MEM_SIZE, 0)
54 nx_rv64im_sim_attach_virtio(sim, virtio)
55 nx_rv64im_sim_attach_virtio_net(sim, vnet)
56 nx_rv64im_sim_attach_nvme(sim, nvme)
57
58 var i: i64 = 0
59 while i < ilen { mem[i] = img[i]; i = i + 1 }
60
61 nx_rv64im_sim_run(sim, D_MAX_STEPS)
62
63 let cnt: i64 = nx_uart_tx_count(uart)
64 d_p("serial: " as *u8); sys_write(1, tx_buf, cnt); d_p("\n" as *u8)
65 d_p("halted=" as *u8); d_n(sim.halted); d_p(" steps=" as *u8); d_n(sim.steps); d_p("\n" as *u8)
66 d_p("CC=0x" as *u8); d_hex(nvme_storage[NX_NVME_SLOT_CC])
67 d_p(" CSTS=0x" as *u8); d_hex(nvme_storage[NX_NVME_SLOT_CSTS])
68 d_p(" ASQ_LO=0x" as *u8); d_hex(nvme_storage[NX_NVME_SLOT_ASQ_LO])
69 d_p(" ACQ_LO=0x" as *u8); d_hex(nvme_storage[NX_NVME_SLOT_ACQ_LO])
70 d_p(" SQTAIL=" as *u8); d_n(nvme_storage[NX_NVME_SLOT_SQTAIL])
71 d_p(" CQPEEK=0x" as *u8); d_hex(nvme_storage[NX_NVME_SLOT_CQPEEK]); d_p("\n" as *u8)
72 // dump SQE bytes at asq off 0x5000 (opcode@0, cid@2)
73 d_p("SQE[0..4]=" as *u8); var j: i64 = 0; while j < 4 { d_hex(mem[0x5000 + j] as i64); d_p(" " as *u8); j = j + 1 } d_p("\n" as *u8)
74 // dump CQE bytes at acq off 0x6000 (cid@12, status@14)
75 d_p("CQE[10..16]=" as *u8); var k: i64 = 10; while k < 16 { d_hex(mem[0x6000 + k] as i64); d_p(" " as *u8); k = k + 1 } d_p("\n" as *u8)
76 sys_exit(0)
77 return 0
78}