hostmem-memfd.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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 "sysemu/hostmem.h"
  14. #include "sysemu/sysemu.h"
  15. #include "qom/object_interfaces.h"
  16. #include "qemu/memfd.h"
  17. #include "qemu/module.h"
  18. #include "qapi/error.h"
  19. #define TYPE_MEMORY_BACKEND_MEMFD "memory-backend-memfd"
  20. #define MEMORY_BACKEND_MEMFD(obj) \
  21. OBJECT_CHECK(HostMemoryBackendMemfd, (obj), TYPE_MEMORY_BACKEND_MEMFD)
  22. typedef struct HostMemoryBackendMemfd HostMemoryBackendMemfd;
  23. struct HostMemoryBackendMemfd {
  24. HostMemoryBackend parent_obj;
  25. bool hugetlb;
  26. uint64_t hugetlbsize;
  27. bool seal;
  28. };
  29. static void
  30. memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
  31. {
  32. HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(backend);
  33. char *name;
  34. int fd;
  35. if (!backend->size) {
  36. error_setg(errp, "can't create backend with size 0");
  37. return;
  38. }
  39. backend->force_prealloc = mem_prealloc;
  40. fd = qemu_memfd_create(TYPE_MEMORY_BACKEND_MEMFD, backend->size,
  41. m->hugetlb, m->hugetlbsize, m->seal ?
  42. F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL : 0,
  43. errp);
  44. if (fd == -1) {
  45. return;
  46. }
  47. name = host_memory_backend_get_name(backend);
  48. memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend),
  49. name, backend->size,
  50. backend->share, fd, errp);
  51. g_free(name);
  52. }
  53. static bool
  54. memfd_backend_get_hugetlb(Object *o, Error **errp)
  55. {
  56. return MEMORY_BACKEND_MEMFD(o)->hugetlb;
  57. }
  58. static void
  59. memfd_backend_set_hugetlb(Object *o, bool value, Error **errp)
  60. {
  61. MEMORY_BACKEND_MEMFD(o)->hugetlb = value;
  62. }
  63. static void
  64. memfd_backend_set_hugetlbsize(Object *obj, Visitor *v, const char *name,
  65. void *opaque, Error **errp)
  66. {
  67. HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(obj);
  68. Error *local_err = NULL;
  69. uint64_t value;
  70. if (host_memory_backend_mr_inited(MEMORY_BACKEND(obj))) {
  71. error_setg(&local_err, "cannot change property value");
  72. goto out;
  73. }
  74. visit_type_size(v, name, &value, &local_err);
  75. if (local_err) {
  76. goto out;
  77. }
  78. if (!value) {
  79. error_setg(&local_err, "Property '%s.%s' doesn't take value '%"
  80. PRIu64 "'", object_get_typename(obj), name, value);
  81. goto out;
  82. }
  83. m->hugetlbsize = value;
  84. out:
  85. error_propagate(errp, local_err);
  86. }
  87. static void
  88. memfd_backend_get_hugetlbsize(Object *obj, Visitor *v, const char *name,
  89. void *opaque, Error **errp)
  90. {
  91. HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(obj);
  92. uint64_t value = m->hugetlbsize;
  93. visit_type_size(v, name, &value, errp);
  94. }
  95. static bool
  96. memfd_backend_get_seal(Object *o, Error **errp)
  97. {
  98. return MEMORY_BACKEND_MEMFD(o)->seal;
  99. }
  100. static void
  101. memfd_backend_set_seal(Object *o, bool value, Error **errp)
  102. {
  103. MEMORY_BACKEND_MEMFD(o)->seal = value;
  104. }
  105. static void
  106. memfd_backend_instance_init(Object *obj)
  107. {
  108. HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(obj);
  109. /* default to sealed file */
  110. m->seal = true;
  111. MEMORY_BACKEND(m)->share = true;
  112. }
  113. static void
  114. memfd_backend_class_init(ObjectClass *oc, void *data)
  115. {
  116. HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc);
  117. bc->alloc = memfd_backend_memory_alloc;
  118. if (qemu_memfd_check(MFD_HUGETLB)) {
  119. object_class_property_add_bool(oc, "hugetlb",
  120. memfd_backend_get_hugetlb,
  121. memfd_backend_set_hugetlb,
  122. &error_abort);
  123. object_class_property_set_description(oc, "hugetlb",
  124. "Use huge pages",
  125. &error_abort);
  126. object_class_property_add(oc, "hugetlbsize", "int",
  127. memfd_backend_get_hugetlbsize,
  128. memfd_backend_set_hugetlbsize,
  129. NULL, NULL, &error_abort);
  130. object_class_property_set_description(oc, "hugetlbsize",
  131. "Huge pages size (ex: 2M, 1G)",
  132. &error_abort);
  133. }
  134. object_class_property_add_bool(oc, "seal",
  135. memfd_backend_get_seal,
  136. memfd_backend_set_seal,
  137. &error_abort);
  138. object_class_property_set_description(oc, "seal",
  139. "Seal growing & shrinking",
  140. &error_abort);
  141. }
  142. static const TypeInfo memfd_backend_info = {
  143. .name = TYPE_MEMORY_BACKEND_MEMFD,
  144. .parent = TYPE_MEMORY_BACKEND,
  145. .instance_init = memfd_backend_instance_init,
  146. .class_init = memfd_backend_class_init,
  147. .instance_size = sizeof(HostMemoryBackendMemfd),
  148. };
  149. static void register_types(void)
  150. {
  151. if (qemu_memfd_check(MFD_ALLOW_SEALING)) {
  152. type_register_static(&memfd_backend_info);
  153. }
  154. }
  155. type_init(register_types);