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 "system/hostmem.h" 15 #include "qapi/error.h" 16 #include "migration/cpr.h" 17 18 #define TYPE_MEMORY_BACKEND_SHM "memory-backend-shm" 19 20 OBJECT_DECLARE_SIMPLE_TYPE(HostMemoryBackendShm, MEMORY_BACKEND_SHM) 21 22 struct HostMemoryBackendShm { 23 HostMemoryBackend parent_obj; 24 }; 25 26 static bool 27 shm_backend_memory_alloc(HostMemoryBackend *backend, Error **errp) 28 { 29 g_autofree char *backend_name = host_memory_backend_get_name(backend); 30 uint32_t ram_flags; 31 int fd = cpr_find_fd(backend_name, 0); 32 33 if (!backend->size) { 34 error_setg(errp, "can't create shm backend with size 0"); 35 return false; 36 } 37 38 if (!backend->share) { 39 error_setg(errp, "can't create shm backend with `share=off`"); 40 return false; 41 } 42 43 if (fd >= 0) { 44 goto have_fd; 45 } 46 47 fd = qemu_shm_alloc(backend->size, errp); 48 if (fd < 0) { 49 return false; 50 } 51 cpr_save_fd(backend_name, 0, fd); 52 53 have_fd: 54 /* Let's do the same as memory-backend-ram,share=on would do. */ 55 ram_flags = RAM_SHARED; 56 ram_flags |= backend->reserve ? 0 : RAM_NORESERVE; 57 58 return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), 59 backend_name, backend->size, 60 ram_flags, fd, 0, errp); 61 } 62 63 static void 64 shm_backend_instance_init(Object *obj) 65 { 66 HostMemoryBackendShm *m = MEMORY_BACKEND_SHM(obj); 67 68 MEMORY_BACKEND(m)->share = true; 69 } 70 71 static void 72 shm_backend_class_init(ObjectClass *oc, void *data) 73 { 74 HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc); 75 76 bc->alloc = shm_backend_memory_alloc; 77 } 78 79 static const TypeInfo shm_backend_info = { 80 .name = TYPE_MEMORY_BACKEND_SHM, 81 .parent = TYPE_MEMORY_BACKEND, 82 .instance_init = shm_backend_instance_init, 83 .class_init = shm_backend_class_init, 84 .instance_size = sizeof(HostMemoryBackendShm), 85 }; 86 87 static void register_types(void) 88 { 89 type_register_static(&shm_backend_info); 90 } 91 92 type_init(register_types); 93