Files
Wellington Dias 1d51343ac1 Build and run the runtime natively on Linux.
Shared runtime code now goes through runtime/platform/platform.h, implemented by platform/win32.c and a new
platform/linux.c: futex locks, a userfaultfd and PAGEMAP_SCAN write watch, signal-based async preemption, our own
fiber switch, and a SIGSEGV handler for the thaw and crash hooks. The window, input, menu and software keyboard get
SDL3 back ends beside the Win32 ones, with the swapchain (gfx_present.c) and input merging (input.c) shared. SHA-256
replaces BCrypt, ELF builds get their own override sections, and the build tools gain Linux branches.

On Linux the selftest and the gfx-abi, astc, nvn and window probes pass. probe-vkmem still fails: imported guest
memory cannot be write-watched on Linux, which the shadow buffers in vk_memory.c will address.
2026-10-29 16:56:56 -03:00

69 lines
2.9 KiB
C

// Adapted from MacNativeGames games/totk/runtime/ipc.h @ b75be8c (MIT, Copyright (c) 2026 MacNativeGames
// contributors). Message framing per libnx sf/hipc.h, cmif.h, tipc.h (ISC), read for the layout only.
// In-process Horizon IPC: HIPC messages with CMIF or TIPC payloads, answered in
// place in the caller's message buffer. Services are host implementations looked up by name through sm:.
#pragma once
#include <stdint.h>
#include "host.h"
#define IPC_MAX_BUF 8
#define IPC_MSG_BYTES 0x100
#define IPC_R_BAD_HANDLE 0xE401u // kernel: invalid handle
#define IPC_R_UNKNOWN_COMMAND 0xF601u // sf: unknown command (module 10, description 123)
typedef struct { uint64_t addr, size; unsigned index; } IpcBuffer;
typedef struct {
unsigned type, cmd; // HIPC type (4/5/6/7 CMIF, >= 16 TIPC) and command id
int has_pid;
uint64_t pid;
uint32_t copy[8], move[8];
unsigned ncopy, nmove;
IpcBuffer x[IPC_MAX_BUF], a[IPC_MAX_BUF], b[IPC_MAX_BUF], w[IPC_MAX_BUF], c[IPC_MAX_BUF];
unsigned nx, na, nb, nw, nc;
const uint8_t *data; // command arguments after the CMIF header (TIPC: after the HIPC header)
uint32_t data_size;
} IpcRequest;
typedef struct {
uint32_t result;
uint8_t data[0x100];
uint32_t data_size;
uint32_t copy[8], move[8];
unsigned ncopy, nmove;
IpcBuffer xout[IPC_MAX_BUF]; // pointer data the service placed into the client's C buffers
unsigned nxout;
} IpcResponse;
typedef struct IpcSession IpcSession;
typedef void (*IpcHandler)(IpcSession *s, const IpcRequest *rq, IpcResponse *rs);
// One server object. Every kernel handle to it (the first one, CloneCurrentObject copies) holds a reference; the
// last CloseHandle calls close(state).
struct IpcSession {
const char *name;
IpcHandler handler;
void *state;
void (*close)(void *state);
int32_t refs;
};
uint32_t ipc_session_new(const char *name, IpcHandler handler, void *state, void (*close)(void *state)); // handle
void ipc_out(IpcResponse *rs, const void *p, uint32_t n);
const void *ipc_arg(const IpcRequest *rq, uint32_t off, uint32_t n);
void *ipc_guest(uint64_t addr, uint64_t size); // a client buffer as a host pointer (identity map), range checked
__attribute__((noreturn)) void ipc_unimplemented(const IpcSession *s, const IpcRequest *rq);
#define IPC_OUT(rs, v) ipc_out((rs), &(v), sizeof(v))
#define IPC_ARG(rq, T, off) (*(const T *)ipc_arg((rq), (off), sizeof(T)))
// Transfer memory from svcCreateTransferMemory (0x15), a KERN_TMEM handle object.
typedef struct { uint64_t addr, size; uint32_t perm; } IpcTransferMemory;
// Server objects alive now and closed so far (the probe checks CloseHandle releases them).
long ipc_sessions_live(void);
uint64_t ipc_sessions_released(void);
// The guest frame chain of the request being served, for fatal reports from services.
void ipc_backtrace(void);