qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

Add memfd based hostmem

Add a new memory backend, similar to hostmem-file, except that it
doesn't need to create files. It also enforces memory sealing.

This backend is mainly useful for sharing the memory with other
processes.

Note that Linux supports transparent huge-pages of shmem/memfd memory
since 4.8. It is relatively easier to set up THP than a dedicate
hugepage mount point by using "madvise" in
/sys/kernel/mm/transparent_hugepage/shmem_enabled.

Since 4.14, memfd allows to set hugetlb requirement explicitly.

Pending for merge in 4.16 is memfd sealing support for hugetlb backed
memory.

Usage:
-object memory-backend-memfd,id=mem1,size=1G

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20180201132757.23063-5-marcandre.lureau@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

authored by

Marc-André Lureau and committed by
Paolo Bonzini
dbb9e0f4 2ef8c0c9

+194
+2
backends/Makefile.objs
··· 8 8 9 9 common-obj-y += cryptodev.o 10 10 common-obj-y += cryptodev-builtin.o 11 + 12 + common-obj-$(CONFIG_LINUX) += hostmem-memfd.o
+170
backends/hostmem-memfd.c
··· 1 + /* 2 + * QEMU host memfd memory backend 3 + * 4 + * Copyright (C) 2018 Red Hat Inc 5 + * 6 + * Authors: 7 + * Marc-André Lureau <marcandre.lureau@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 + #include "qemu/osdep.h" 13 + #include "qemu-common.h" 14 + #include "sysemu/hostmem.h" 15 + #include "sysemu/sysemu.h" 16 + #include "qom/object_interfaces.h" 17 + #include "qemu/memfd.h" 18 + #include "qapi/error.h" 19 + 20 + #define TYPE_MEMORY_BACKEND_MEMFD "memory-backend-memfd" 21 + 22 + #define MEMORY_BACKEND_MEMFD(obj) \ 23 + OBJECT_CHECK(HostMemoryBackendMemfd, (obj), TYPE_MEMORY_BACKEND_MEMFD) 24 + 25 + typedef struct HostMemoryBackendMemfd HostMemoryBackendMemfd; 26 + 27 + struct HostMemoryBackendMemfd { 28 + HostMemoryBackend parent_obj; 29 + 30 + bool hugetlb; 31 + uint64_t hugetlbsize; 32 + bool seal; 33 + }; 34 + 35 + static void 36 + memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp) 37 + { 38 + HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(backend); 39 + char *name; 40 + int fd; 41 + 42 + if (!backend->size) { 43 + error_setg(errp, "can't create backend with size 0"); 44 + return; 45 + } 46 + 47 + if (host_memory_backend_mr_inited(backend)) { 48 + return; 49 + } 50 + 51 + backend->force_prealloc = mem_prealloc; 52 + fd = qemu_memfd_create(TYPE_MEMORY_BACKEND_MEMFD, backend->size, 53 + m->hugetlb, m->hugetlbsize, m->seal ? 54 + F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL : 0, 55 + errp); 56 + if (fd == -1) { 57 + return; 58 + } 59 + 60 + name = object_get_canonical_path(OBJECT(backend)); 61 + memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), 62 + name, backend->size, true, fd, errp); 63 + g_free(name); 64 + } 65 + 66 + static bool 67 + memfd_backend_get_hugetlb(Object *o, Error **errp) 68 + { 69 + return MEMORY_BACKEND_MEMFD(o)->hugetlb; 70 + } 71 + 72 + static void 73 + memfd_backend_set_hugetlb(Object *o, bool value, Error **errp) 74 + { 75 + MEMORY_BACKEND_MEMFD(o)->hugetlb = value; 76 + } 77 + 78 + static void 79 + memfd_backend_set_hugetlbsize(Object *obj, Visitor *v, const char *name, 80 + void *opaque, Error **errp) 81 + { 82 + HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(obj); 83 + Error *local_err = NULL; 84 + uint64_t value; 85 + 86 + if (host_memory_backend_mr_inited(MEMORY_BACKEND(obj))) { 87 + error_setg(&local_err, "cannot change property value"); 88 + goto out; 89 + } 90 + 91 + visit_type_size(v, name, &value, &local_err); 92 + if (local_err) { 93 + goto out; 94 + } 95 + if (!value) { 96 + error_setg(&local_err, "Property '%s.%s' doesn't take value '%" 97 + PRIu64 "'", object_get_typename(obj), name, value); 98 + goto out; 99 + } 100 + m->hugetlbsize = value; 101 + out: 102 + error_propagate(errp, local_err); 103 + } 104 + 105 + static void 106 + memfd_backend_get_hugetlbsize(Object *obj, Visitor *v, const char *name, 107 + void *opaque, Error **errp) 108 + { 109 + HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(obj); 110 + uint64_t value = m->hugetlbsize; 111 + 112 + visit_type_size(v, name, &value, errp); 113 + } 114 + 115 + static bool 116 + memfd_backend_get_seal(Object *o, Error **errp) 117 + { 118 + return MEMORY_BACKEND_MEMFD(o)->seal; 119 + } 120 + 121 + static void 122 + memfd_backend_set_seal(Object *o, bool value, Error **errp) 123 + { 124 + MEMORY_BACKEND_MEMFD(o)->seal = value; 125 + } 126 + 127 + static void 128 + memfd_backend_instance_init(Object *obj) 129 + { 130 + HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(obj); 131 + 132 + /* default to sealed file */ 133 + m->seal = true; 134 + } 135 + 136 + static void 137 + memfd_backend_class_init(ObjectClass *oc, void *data) 138 + { 139 + HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc); 140 + 141 + bc->alloc = memfd_backend_memory_alloc; 142 + 143 + object_class_property_add_bool(oc, "hugetlb", 144 + memfd_backend_get_hugetlb, 145 + memfd_backend_set_hugetlb, 146 + &error_abort); 147 + object_class_property_add(oc, "hugetlbsize", "int", 148 + memfd_backend_get_hugetlbsize, 149 + memfd_backend_set_hugetlbsize, 150 + NULL, NULL, &error_abort); 151 + object_class_property_add_bool(oc, "seal", 152 + memfd_backend_get_seal, 153 + memfd_backend_set_seal, 154 + &error_abort); 155 + } 156 + 157 + static const TypeInfo memfd_backend_info = { 158 + .name = TYPE_MEMORY_BACKEND_MEMFD, 159 + .parent = TYPE_MEMORY_BACKEND, 160 + .instance_init = memfd_backend_instance_init, 161 + .class_init = memfd_backend_class_init, 162 + .instance_size = sizeof(HostMemoryBackendMemfd), 163 + }; 164 + 165 + static void register_types(void) 166 + { 167 + type_register_static(&memfd_backend_info); 168 + } 169 + 170 + type_init(register_types);
+22
qemu-options.hx
··· 4024 4024 traditionally used to define guest RAM. Please refer to 4025 4025 @option{memory-backend-file} for a description of the options. 4026 4026 4027 + @item -object memory-backend-memfd,id=@var{id},merge=@var{on|off},dump=@var{on|off},prealloc=@var{on|off},size=@var{size},host-nodes=@var{host-nodes},policy=@var{default|preferred|bind|interleave},seal=@var{on|off},hugetlb=@var{on|off},hugetlbsize=@var{size} 4028 + 4029 + Creates an anonymous memory file backend object, which allows QEMU to 4030 + share the memory with an external process (e.g. when using 4031 + vhost-user). The memory is allocated with memfd and optional 4032 + sealing. (Linux only) 4033 + 4034 + The @option{seal} option creates a sealed-file, that will block 4035 + further resizing the memory ('on' by default). 4036 + 4037 + The @option{hugetlb} option specify the file to be created resides in 4038 + the hugetlbfs filesystem (since Linux 4.14). Used in conjunction with 4039 + the @option{hugetlb} option, the @option{hugetlbsize} option specify 4040 + the hugetlb page size on systems that support multiple hugetlb page 4041 + sizes (it must be a power of 2 value supported by the system). 4042 + 4043 + In some versions of Linux, the @option{hugetlb} option is incompatible 4044 + with the @option{seal} option (requires at least Linux 4.16). 4045 + 4046 + Please refer to @option{memory-backend-file} for a description of the 4047 + other options. 4048 + 4027 4049 @item -object rng-random,id=@var{id},filename=@var{/dev/random} 4028 4050 4029 4051 Creates a random number generator backend which obtains entropy from