1 /* 2 * QEMU host POSIX shared memory object backend 3 * 4 * Copyright (C) 2024 Red Hat Inc 5 * 6 * Authors: 7 * Stefano Garzarella <sgarzare@redhat.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 */ 12 13 #include "qemu/osdep.h" 14 #include "sysemu/hostmem.h" 15 #include "qapi/error.h" 16 17 #define TYPE_MEMORY_BACKEND_SHM "memory-backend-shm" 18 19 OBJECT_DECLARE_SIMPLE_TYPE(HostMemoryBackendShm, MEMORY_BACKEND_SHM) 20 21 struct HostMemoryBackendShm { 22 HostMemoryBackend parent_obj; 23 }; 24 25 static bool 26 shm_backend_memory_alloc(HostMemoryBackend *backend, Error **errp) 27 { 28 g_autoptr(GString) shm_name = g_string_new(NULL); 29 g_autofree char *backend_name = NULL; 30 uint32_t ram_flags; 31 int fd, oflag; 32 mode_t mode; 33 34 if (!backend->size) { 35 error_setg(errp, "can't create shm backend with size 0"); 36 return false; 37 } 38 39 if (!backend->share) { 40 error_setg(errp, "can't create shm backend with `share=off`"); 41 return false; 42 } 43 44 /* 45 * Let's use `mode = 0` because we don't want other processes to open our 46 * memory unless we share the file descriptor with them. 47 */ 48 mode = 0; 49 oflag = O_RDWR | O_CREAT | O_EXCL; 50 backend_name = host_memory_backend_get_name(backend); 51 52 /* 53 * Some operating systems allow creating anonymous POSIX shared memory 54 * objects (e.g. FreeBSD provides the SHM_ANON constant), but this is not 55 * defined by POSIX, so let's create a unique name. 56 * 57 * From Linux's shm_open(3) man-page: 58 * For portable use, a shared memory object should be identified 59 * by a name of the form /somename;" 60 */ 61 g_string_printf(shm_name, "/qemu-" FMT_pid "-shm-%s", getpid(), 62 backend_name); 63 64 fd = shm_open(shm_name->str, oflag, mode); 65 if (fd < 0) { 66 error_setg_errno(errp, errno, 67 "failed to create POSIX shared memory"); 68 return false; 69 } 70 71 /* 72 * We have the file descriptor, so we no longer need to expose the 73 * POSIX shared memory object. However it will remain allocated as long as 74 * there are file descriptors pointing to it. 75 */ 76 shm_unlink(shm_name->str); 77 78 if (ftruncate(fd, backend->size) == -1) { 79 error_setg_errno(errp, errno, 80 "failed to resize POSIX shared memory to %" PRIu64, 81 backend->size); 82 close(fd); 83 return false; 84 } 85 86 ram_flags = RAM_SHARED; 87 ram_flags |= backend->reserve ? 0 : RAM_NORESERVE; 88 89 return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), 90 backend_name, backend->size, 91 ram_flags, fd, 0, errp); 92 } 93 94 static void 95 shm_backend_instance_init(Object *obj) 96 { 97 HostMemoryBackendShm *m = MEMORY_BACKEND_SHM(obj); 98 99 MEMORY_BACKEND(m)->share = true; 100 } 101 102 static void 103 shm_backend_class_init(ObjectClass *oc, void *data) 104 { 105 HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc); 106 107 bc->alloc = shm_backend_memory_alloc; 108 } 109 110 static const TypeInfo shm_backend_info = { 111 .name = TYPE_MEMORY_BACKEND_SHM, 112 .parent = TYPE_MEMORY_BACKEND, 113 .instance_init = shm_backend_instance_init, 114 .class_init = shm_backend_class_init, 115 .instance_size = sizeof(HostMemoryBackendShm), 116 }; 117 118 static void register_types(void) 119 { 120 type_register_static(&shm_backend_info); 121 } 122 123 type_init(register_types); 124