//! User-space shared memory: `shared_memory_create` / `shared_memory_map`. A process creates a shareable, //! zeroed, cacheable RAM region and gets back a pointer plus a **capability handle**; it //! passes that handle to another process as an `ipc_call` send_cap, and the receiver //! `shared_memory_map`s it to map the same physical pages. The kernel primitive under the display //! compositor↔native-driver and app↔compositor surface paths (docs/display-v2.md). The //! generalization of capability passing from endpoints to memory objects. const abi = @import("abi"); const sc = @import("system-call"); const ipc = @import("ipc"); inline fn failed(r: usize) bool { return r > ~@as(usize, 0) - 4095; // a wrapped -errno lands in the top page } /// A shared region: the `ptr` the CPU touches, and the `handle` (a capability) to hand to /// another process as an `ipc_call` send_cap. pub const Region = struct { ptr: [*]u8, handle: ipc.Handle, len: usize, }; /// Grant `len` bytes (rounded up to whole pages) of shareable, zeroed, cacheable RAM. /// Returns the region or null on failure. Two return values — virtual_address in rax, handle in rdx — /// so this is a hand-written stub like `dma.alloc`. pub fn create(len: usize) ?Region { var rax: usize = undefined; var rdx: usize = undefined; // out: the capability handle asm volatile ("syscall" : [rax] "={rax}" (rax), [rdx] "={rdx}" (rdx), : [n] "{rax}" (@intFromEnum(abi.SystemCall.shared_memory_create)), [a0] "{rdi}" (len), : .{ .rcx = true, .r11 = true, .memory = true }); if (failed(rax)) return null; return .{ .ptr = @ptrFromInt(rax), .handle = rdx, .len = len }; } /// Map the shared region named by a capability `handle` this process received (via an /// `ipc_call` send_cap) into its address space — the same physical pages the creator sees. /// Returns the pointer, or null on failure. pub fn map(handle: ipc.Handle) ?[*]u8 { const r = sc.systemCall1(.shared_memory_map, handle); if (failed(r)) return null; return @ptrFromInt(r); } /// The guest-physical base of the shared region named by `handle` (which this process must /// hold a capability for). The region's frames are contiguous, so this single address plus /// the region length is all a device needs — e.g. a virtio-gpu driver programming an /// `attach_backing`. Returns null on failure. pub fn physical(handle: ipc.Handle) ?usize { const r = sc.systemCall1(.shared_memory_physical, handle); if (failed(r)) return null; return r; }