code wiki / _hdl_build / nx_virtio_rng_emit.nx

nx_virtio_rng_emit.nx source

↩ module page · 25 lines · 3727 B

1// nx_virtio_rng_emit.nx -- emit a COMPLETE legacy virtio-mmio virtio-rng DRIVER as a RV64 flat binary (via 2// nx_rv64_asm). The driver: (1) SCANS the 8 virtio-mmio slots for DeviceID==4 (rng); (2) does the legacy handshake 3// reset->ACK->DRIVER; (3) sets GuestPageSize, a virtqueue (desc/avail/used at 0x81000000), QueuePFN; (4) DRIVER_OK; 4// (5) posts a WRITE descriptor (16 bytes at 0x81002000), rings QueueNotify; (6) polls the used ring; (7) prints the 5// entropy the DEVICE wrote, as hex, over the UART; (8) halts PASS. Booted in qemu-system-riscv64 with a real 6// -device virtio-rng-device (force-legacy), the printed bytes are REAL entropy from the emulated device -- the 7// generated driver drove an ACTUAL device end-to-end. Writes knowledge/hw/virtio_rng.bin. expect_exit:0 ORIGINAL 8import "nx_rv64_asm.nx" 9const K_MAGIC_65536: i64 = 65536 10 11func vr_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 12func vr_pn(v: i64) -> i64 { let b: *u8=sys_mmap(28); var x: i64=v; if x==0{b[0]=48;sys_write(1,b,1);return 0} var d: i64=0; var y: i64=x; while y>0{d=d+1;y=y/10} var i: i64=d-1; y=x; while i>=0{b[i]=(48+(y%10)) as u8;y=y/10;i=i-1} sys_write(1,b,d); return 0 } 13 14func main() -> i64 { 15 vr_puts("nx_virtio_rng_emit assemble a complete legacy virtio-rng driver into a QEMU-bootable binary\n" as *u8) 16 let out: *u8 = sys_mmap(K_MAGIC_65536) 17 let nb: i64 = rvasm_assemble_str(" lui s2, 0x10000\n lui t2, 0x10001\n lui s3, 0x74727\n addi s3, s3, -0x68a\n li t4, 0\n li s5, 8\nfind:\n slli t0, t4, 12\n add t1, t2, t0\n lw t6, 0(t1)\n bne t6, s3, findnext\n lw t6, 8(t1)\n li t0, 4\n beq t6, t0, found\nfindnext:\n addi t4, t4, 1\n blt t4, s5, find\n lui a0, 0x100\n lui a1, 0x3\n addi a1, a1, 0x333\n sw a1, 0(a0)\nbadhalt:\n j badhalt\nfound:\n mv s1, t1\n sw zero, 0x70(s1)\n li t0, 1\n sw t0, 0x70(s1)\n li t0, 3\n sw t0, 0x70(s1)\n sw zero, 0x20(s1)\n lui t0, 0x1\n sw t0, 0x28(s1)\n sw zero, 0x30(s1)\n li t0, 8\n sw t0, 0x38(s1)\n lui t0, 0x1\n sw t0, 0x3c(s1)\n lui t0, 0x81\n sw t0, 0x40(s1)\n li t0, 7\n sw t0, 0x70(s1)\n lui s5, 0x81000\n slli s5, s5, 32\n srli s5, s5, 32\n lui s6, 0x81002\n slli s6, s6, 32\n srli s6, s6, 32\n sw s6, 0(s5)\n sw zero, 4(s5)\n li t0, 16\n sw t0, 8(s5)\n li t0, 2\n sh t0, 12(s5)\n sh zero, 14(s5)\n sh zero, 128(s5)\n sh zero, 132(s5)\n li t0, 1\n sh t0, 130(s5)\n sw zero, 0x50(s1)\n lui t3, 0x81001\n slli t3, t3, 32\n srli t3, t3, 32\npoll:\n lhu t0, 2(t3)\n beq t0, zero, poll\n li t4, 0\n li s5, 16\nprintloop:\n add t0, s6, t4\n lbu t1, 0(t0)\n srli t2, t1, 4\n andi t2, t2, 15\n jal ra, putnib\n andi t2, t1, 15\n jal ra, putnib\n addi t4, t4, 1\n blt t4, s5, printloop\n li a0, 10\npnl:\n lbu t6, 5(s2)\n andi t6, t6, 32\n beq t6, zero, pnl\n sb a0, 0(s2)\n lui a0, 0x100\n lui a1, 0x5\n addi a1, a1, 0x555\n sw a1, 0(a0)\ndonehalt:\n j donehalt\nputnib:\n li t6, 10\n blt t2, t6, pndig\n addi a0, t2, 0x57\n j pnwr\npndig:\n addi a0, t2, 0x30\npnwr:\n lbu t6, 5(s2)\n andi t6, t6, 32\n beq t6, zero, pnwr\n sb a0, 0(s2)\n ret\n" as *u8, out, K_MAGIC_65536) 18 if nb<0 { vr_puts(" ASSEMBLE FAILED rc="); vr_pn(0-nb); vr_puts("\n" as *u8); sys_exit(1); return 1 } 19 let fd: i64 = sys_openat_wr("knowledge/hw/virtio_rng.bin" as *u8, 420) 20 if fd<0 { vr_puts(" cannot write bin\n" as *u8); sys_exit(1); return 1 } 21 sys_write(fd, out, nb); sys_close(fd) 22 vr_puts(" wrote knowledge/hw/virtio_rng.bin bytes="); vr_pn(nb); vr_puts(" boot with qemu-system-riscv64 force-legacy + virtio-rng-device\n" as *u8) 23 vr_puts("verdict=GREEN legacy virtio-rng driver assembled and emitted\n" as *u8) 24 sys_exit(0); return 0 25}