/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * arch/wasm32/include/uapi/asm/hosttrans.h * * THE USERSPACE FACE of the wasm32 generic host transport (devid 6): * /dev/hwjs-transport, a misc char device whose two ioctls let an ordinary * guest program move requests and payload bytes between Linux USERSPACE and * HardwareJS without a filesystem, a socket or a driver of its own. * * A guest program includes THIS header and nothing else. The wire ABI it * rides on (the shared-memory ring in the host-carved MMIO window, the * submission/completion index discipline, the release/acquire rules) is * arch/wasm32/include/asm/hosttrans.h and is deliberately NOT visible here: * userspace never touches the ring. It hands the kernel a request plus a * user pointer, the kernel bounces the payload through a kernel buffer and * puts THAT address on the wire, and the answer comes back in the same * struct. See the bounce-buffer note in asm/hosttrans.h for why an mmap of * the ring is not merely unimplemented but impossible on this arch. * * THE OPCODES ARE TRANSPORT VERBS, NOT FILE OPERATIONS. READ/WRITE/FLUSH/ * STAT name what the TRANSPORT does with a buffer and an object id; what an * object id means is entirely the host backend's business. Nothing in the * kernel half knows or may learn. * * These values are mirrored by WASM_HOSTTRANS_OP_* in asm/hosttrans.h and * PINNED to them by static_assert there, so a drift between the userspace * name and the wire value fails the build instead of the boot. */ #ifndef _ASM_WASM32_HOSTTRANS_H #define _ASM_WASM32_HOSTTRANS_H #include #include /* Transport verbs. Generic by construction — see the note above. */ #define HWJS_XPORT_OP_NOP 0u /* completes 0/0; the liveness probe */ #define HWJS_XPORT_OP_READ 1u /* host fills buf, reports length */ #define HWJS_XPORT_OP_WRITE 2u /* host consumes buf */ #define HWJS_XPORT_OP_FLUSH 3u #define HWJS_XPORT_OP_STAT 4u #define HWJS_XPORT_OP_ECHO 5u /* host copies buf back over itself */ /* * What the transport is, as the kernel currently sees it. Answered even * when the host has not attached (`active == 0`): a program that cannot * tell "no backend" from "backend refused" ends up retrying a refusal * forever, so the grant boundary is a READABLE word, not an errno on the * query. */ struct hwjs_xport_info { __u32 abi_version; /* == WASM_HOSTTRANS_ABI_VERSION */ __u32 active; /* HOST-owned grant word; 0 => SUBMIT gives * -ENODEV, loudly and immediately */ __u32 features; /* kernel-declared feature bits (v1: 0) */ __u32 sq_slots; /* submission ring depth */ __u32 cq_slots; /* completion ring depth */ __u32 max_xfer; /* per-request byte ceiling; a longer * SUBMIT is refused -EMSGSIZE by name */ __u32 notify_seq; /* monotonic doorbell count (diagnostic) */ __u32 inflight; /* requests submitted and not yet completed */ }; /* * One request. Filled by the caller, completed in place: `status` and * `out_length` are the only fields the kernel writes back. * * `buf` is a USER pointer into the calling process's own address space — * which on this arch is a DIFFERENT wasm Memory from the kernel's, so it * can never be the address the host reads. The kernel copies through a * kernel buffer in both directions; that is not an optimisation the driver * declined to make, it is the only thing that can work here. * * WHEN @buf IS COPIED, AND IN WHICH DIRECTION. WRITE and ECHO are the verbs * whose buffer the host CONSUMES, so [buf, buf+buf_len) is copied INTO the * kernel before submission. READ, STAT and ECHO are the verbs whose buffer * the host FILLS, so on a zero @status the first @out_length bytes are copied * back OUT to @buf afterwards. NOP and FLUSH carry no payload and pay for no * copy. Pass buf = 0, buf_len = 0 for those. * * SUBMIT BLOCKS until the completion for this request arrives. It parks * cooperatively (the ordinary wait machinery), so a blocked submitter costs * no CPU and a signal interrupts it with -EINTR/-ERESTARTSYS. An interrupted * SUBMIT leaves the request with the host: it is reaped when the completion * lands, and its slot is not lost. */ struct hwjs_xport_op { __u32 opcode; /* HWJS_XPORT_OP_* */ __u32 object_id; /* opaque to the kernel; the host's namespace */ __u64 offset; /* opaque byte offset within the object */ __u32 length; /* requested byte count (<= max_xfer) */ __u32 flags; /* opcode-specific; passed through verbatim */ __u64 buf; /* USER pointer, or 0 for no buffer */ __u32 buf_len; /* capacity at @buf (<= max_xfer) */ __s32 status; /* OUT: 0 or -errno, as the host reported */ __u32 out_length; /* OUT: bytes actually transferred */ __u32 reserved; /* must be 0; a new field carves from here */ }; #define HWJS_XPORT_IOC_MAGIC 'H' /* Report the transport's geometry + the host grant word. */ #define HWJS_XPORT_INFO _IOR(HWJS_XPORT_IOC_MAGIC, 0x01, \ struct hwjs_xport_info) /* Submit one request and block until its completion arrives. */ #define HWJS_XPORT_SUBMIT _IOWR(HWJS_XPORT_IOC_MAGIC, 0x02, \ struct hwjs_xport_op) #endif /* _ASM_WASM32_HOSTTRANS_H */