1#include "virtgpu-shm.h"
 2
 3#include "virtgpu.h"
 4
 5#include <assert.h>
 6
 7static uint32_t virtgpu_ioctl_resource_create_blob(virtgpu *  gpu,
 8                                                   uint32_t   blob_mem,
 9                                                   uint32_t   blob_flags,
10                                                   size_t     blob_size,
11                                                   uint64_t   blob_id,
12                                                   uint32_t * res_id) {
13#ifdef SIMULATE_BO_SIZE_FIX
14    blob_size = align64(blob_size, 4096);
15#endif
16
17    drm_virtgpu_resource_create_blob args = {
18        .blob_mem   = blob_mem,
19        .blob_flags = blob_flags,
20        .bo_handle  = 0,
21        .res_handle = 0,
22        .size       = blob_size,
23        .pad        = 0,
24        .cmd_size   = 0,
25        .cmd        = 0,
26        .blob_id    = blob_id,
27    };
28
29    if (virtgpu_ioctl(gpu, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB, &args)) {
30        return 0;
31    }
32
33    *res_id = args.res_handle;
34    return args.bo_handle;
35}
36
37static void virtgpu_ioctl_gem_close(virtgpu * gpu, uint32_t gem_handle) {
38    drm_gem_close args = {
39        .handle = gem_handle,
40        .pad    = 0,
41    };
42
43    const int ret = virtgpu_ioctl(gpu, DRM_IOCTL_GEM_CLOSE, &args);
44    assert(!ret);
45#ifdef NDEBUG
46    UNUSED(ret);
47#endif
48}
49
50static void * virtgpu_ioctl_map(virtgpu * gpu, uint32_t gem_handle, size_t size) {
51    drm_virtgpu_map args = {
52        .offset = 0,
53        .handle = gem_handle,
54        .pad    = 0,
55    };
56
57    if (virtgpu_ioctl(gpu, DRM_IOCTL_VIRTGPU_MAP, &args)) {
58        return NULL;
59    }
60
61    void * ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, gpu->fd, args.offset);
62    if (ptr == MAP_FAILED) {
63        return NULL;
64    }
65
66    return ptr;
67}
68
69void virtgpu_shmem_destroy(virtgpu * gpu, virtgpu_shmem * shmem) {
70    munmap(shmem->mmap_ptr, shmem->mmap_size);
71    virtgpu_ioctl_gem_close(gpu, shmem->gem_handle);
72}
73
74int virtgpu_shmem_create(virtgpu * gpu, size_t size, virtgpu_shmem * shmem) {
75    size = align64(size, 16384);
76
77    uint32_t res_id;
78    uint32_t gem_handle = virtgpu_ioctl_resource_create_blob(gpu, VIRTGPU_BLOB_MEM_HOST3D,
79                                                             VIRTGPU_BLOB_FLAG_USE_MAPPABLE, size, 0, &res_id);
80
81    if (!gem_handle) {
82        return 1;
83    }
84
85    void * ptr = virtgpu_ioctl_map(gpu, gem_handle, size);
86    if (!ptr) {
87        virtgpu_ioctl_gem_close(gpu, gem_handle);
88        GGML_LOG_ERROR(GGML_VIRTGPU "%s: virtgpu_ioctl_map failed\n", __func__);
89        return 1;
90    }
91
92    shmem->res_id     = res_id;
93    shmem->mmap_size  = size;
94    shmem->mmap_ptr   = ptr;
95    shmem->gem_handle = gem_handle;
96
97    return 0;
98}