hostmem-memfd.c 4.7 KB

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