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 ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD : 0; 58 59 return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), 60 backend_name, backend->size, 61 ram_flags, fd, 0, errp); 62 } 63 64 static void 65 shm_backend_instance_init(Object *obj) 66 { 67 HostMemoryBackendShm *m = MEMORY_BACKEND_SHM(obj); 68 69 MEMORY_BACKEND(m)->share = true; 70 } 71 72 static void 73 shm_backend_class_init(ObjectClass *oc, const void *data) 74 { 75 HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc); 76 77 bc->alloc = shm_backend_memory_alloc; 78 } 79 80 static const TypeInfo shm_backend_info = { 81 .name = TYPE_MEMORY_BACKEND_SHM, 82 .parent = TYPE_MEMORY_BACKEND, 83 .instance_init = shm_backend_instance_init, 84 .class_init = shm_backend_class_init, 85 .instance_size = sizeof(HostMemoryBackendShm), 86 }; 87 88 static void register_types(void) 89 { 90 type_register_static(&shm_backend_info); 91 } 92 93 type_init(register_types); 94