==> include/mesh/cuda_driver.h <==1/* @ajax/cuda-driver: the CUDA driver API calls meshd (and kcheck, and the MPS
2 * workers) make, as a table of functions loaded at runtime from libcuda.so.1.
3 * Building needs no CUDA headers or toolkit; running needs the driver. The
4 * types and constants are the CUDA 13.0 ABI, as alpha-rust-mesh's cudarc
5 * 0.19 bindings (feature cuda-13000) declare them.
6 *
7 * Tests swap the table (mesh_cuda_set) for a fake driver, so every call
8 * sequence above it is testable without a GPU. */
9#ifndef MESH_CUDA_DRIVER_H
10#define MESH_CUDA_DRIVER_H
11
12#include <stdbool.h>
13#include <stddef.h>
14#include <stdint.h>
15
16typedef int CUresult;
17typedef int CUdevice;
18typedef unsigned long long CUdeviceptr;
19typedef struct CUctx_st *CUcontext;
20typedef struct CUmod_st *CUmodule;
21typedef struct CUfunc_st *CUfunction;
22typedef struct CUstream_st *CUstream;
23typedef struct CUgreenCtx_st *CUgreenCtx;
24typedef struct CUdevResourceDesc_st *CUdevResourceDesc;
25
26/* CUdevResource (CUDA 13.0: type, 92 bytes of padding, a 48-byte union), with
27 * spare room after it in case a newer driver writes a longer struct. */
28typedef struct {
29 int type;
30 unsigned char internal_padding[92];
31 union {
32 struct {
33 unsigned int smCount;
34 unsigned int minSmPartitionSize;
35 unsigned int smCoscheduledAlignment;
36 } sm;
37 unsigned char oversize[48];
38 } u;
39 unsigned char spare[64];
40} CUdevResource;
41
42#define CUDA_SUCCESS 0
43#define CUDA_ERROR_NOT_READY 600
44/* CUdevice_attribute */
45#define CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_BLOCK 1
46#define CU_DEVICE_ATTRIBUTE_MAX_REGISTERS_PER_BLOCK 12
47#define CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT 16
48#define CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR 75
49#define CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR 76
50#define CU_DEVICE_ATTRIBUTE_HOST_NATIVE_ATOMIC_SUPPORTED 86
51#define CU_DEVICE_ATTRIBUTE_MAX_SHARED_MEMORY_PER_BLOCK_OPTIN 97
52#define CU_DEVICE_ATTRIBUTE_MAX_BLOCKS_PER_MULTIPROCESSOR 106
53/* CUfunction_attribute */
54#define CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK 0
55#define CU_FUNC_ATTRIBUTE_SHARED_SIZE_BYTES 1
56#define CU_FUNC_ATTRIBUTE_LOCAL_SIZE_BYTES 3
57#define CU_FUNC_ATTRIBUTE_NUM_REGS 4
58#define CU_FUNC_ATTRIBUTE_MAX_DYNAMIC_SHARED_SIZE_BYTES 8
59/* CUlimit, stream flags, host-register flags, module loading modes */
60#define CU_LIMIT_STACK_SIZE 0
61#define CU_STREAM_NON_BLOCKING 1u
62#define CU_MEMHOSTREGISTER_PORTABLE 1u
63#define CU_MEMHOSTREGISTER_DEVICEMAP 2u
64#define CU_MODULE_EAGER_LOADING 1
65#define CU_MODULE_LAZY_LOADING 2
66/* green contexts */
67#define CU_DEV_RESOURCE_TYPE_SM 1
68#define CU_DEV_SM_RESOURCE_SPLIT_IGNORE_SM_COSCHEDULING 1u
69#define CU_GREEN_CTX_DEFAULT_STREAM 1u
70
71/* The calls, by their libcuda symbol names (the _v2 ones are what the CUDA
72 * 13 headers' macros resolve to). */
73typedef struct {
74 CUresult (*cuInit)(unsigned int flags);
75 CUresult (*cuGetErrorName)(CUresult r, const char **name);
76 CUresult (*cuModuleGetLoadingMode)(int *mode);
77 CUresult (*cuDeviceGet)(CUdevice *dev, int ordinal);
78 CUresult (*cuDeviceGetName)(char *name, int len, CUdevice dev);
79 CUresult (*cuDeviceGetAttribute)(int *v, int attrib, CUdevice dev);
80 CUresult (*cuDevicePrimaryCtxRetain)(CUcontext *ctx, CUdevice dev);
81 CUresult (*cuCtxSetCurrent)(CUcontext ctx);
82 CUresult (*cuCtxGetLimit)(size_t *v, int limit);
83 CUresult (*cuCtxSetLimit)(int limit, size_t v);
84 CUresult (*cuDeviceGetDevResource)(CUdevice dev, CUdevResource *res, int type);
85 CUresult (*cuDevSmResourceSplitByCount)(CUdevResource *result, unsigned int *nb_groups, const CUdevResource *input,
86 CUdevResource *remaining, unsigned int flags, unsigned int min_count);
87 CUresult (*cuDevResourceGenerateDesc)(CUdevResourceDesc *desc, CUdevResource *resources, unsigned int n);
88 CUresult (*cuGreenCtxCreate)(CUgreenCtx *g, CUdevResourceDesc desc, CUdevice dev, unsigned int flags);
89 CUresult (*cuCtxFromGreenCtx)(CUcontext *ctx, CUgreenCtx g);
90 CUresult (*cuGreenCtxStreamCreate)(CUstream *s, CUgreenCtx g, unsigned int flags, int priority);
91 CUresult (*cuStreamCreate)(CUstream *s, unsigned int flags);
92 CUresult (*cuStreamDestroy_v2)(CUstream s);
93 CUresult (*cuStreamQuery)(CUstream s);
94 CUresult (*cuStreamSynchronize)(CUstream s);
95 CUresult (*cuMemHostRegister_v2)(void *p, size_t bytes, unsigned int flags);
96 CUresult (*cuMemHostGetDevicePointer_v2)(CUdeviceptr *d, void *p, unsigned int flags);
97 CUresult (*cuModuleLoadData)(CUmodule *m, const void *image);
98 CUresult (*cuModuleGetFunction)(CUfunction *f, CUmodule m, const char *name);
99 CUresult (*cuModuleUnload)(CUmodule m);
100 CUresult (*cuModuleGetGlobal_v2)(CUdeviceptr *d, size_t *bytes, CUmodule m, const char *name);
101 CUresult (*cuFuncGetAttribute)(int *v, int attrib, CUfunction f);
102 CUresult (*cuFuncSetAttribute)(CUfunction f, int attrib, int v);
103 CUresult (*cuOccupancyMaxActiveBlocksPerMultiprocessor)(int *blocks, CUfunction f, int threads, size_t smem);
104 CUresult (*cuMemAlloc_v2)(CUdeviceptr *d, size_t bytes);
105 CUresult (*cuMemFree_v2)(CUdeviceptr d);
106 CUresult (*cuMemsetD8Async)(CUdeviceptr d, unsigned char v, size_t n, CUstream s);
107 CUresult (*cuMemcpyDtoH_v2)(void *dst, CUdeviceptr src, size_t n);
108 CUresult (*cuLaunchKernel)(CUfunction f, unsigned int gx, unsigned int gy, unsigned int gz, unsigned int bx, unsigned int by,
109 unsigned int bz, unsigned int smem, CUstream s, void **params, void **extra);
110} mesh_cuda_fns;
111
112/* The table in use: the loaded driver, or the one a test set; NULL before either. */
113const mesh_cuda_fns *mesh_cuda(void);
114/* dlopen("libcuda.so.1") and every symbol above (once; later calls return the
115 * first result). False with *err ("cuda: cannot open libcuda.so.1: ..." or
116 * "cuda: libcuda.so.1 has no cuX"). */
117bool mesh_cuda_load(char **err);
118/* Uses fns instead of the driver (tests); NULL: back to unloaded. */
119void mesh_cuda_set(const mesh_cuda_fns *fns);
120/* The table in use was set by mesh_cuda_set (a fake driver: no libcuda is mapped). */
121bool mesh_cuda_injected(void);
122
123/* The variant name of a CUresult ("CUDA_ERROR_NOT_READY"), as Rust's {:?}; NULL if unknown. */
124const char *mesh_cu_result_name(CUresult r);
125/* Rust's `{r:?}` of a CUresult: its name, or "cudaError_enum(N)" for an unknown code (malloc'd). */
126char *mesh_cu_result_debug(CUresult r);
127/* cuda.rs's ck: true on CUDA_SUCCESS; else *err = "<what>: <cuGetErrorName>" (or the Debug name). */
128bool mesh_cu_ck(CUresult r, const char *what, char **err);
129/* mps.rs's ck: "<what>: <Debug name>" (no cuGetErrorName). */
130bool mesh_cu_ck_debug(CUresult r, const char *what, char **err);
131
132typedef struct {
133 CUresult code;
134 const char *name;
135} mesh_cu_name;
136
137#endif