skip to content
==> 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