2 * Postcopy migration for RAM
4 * Copyright 2013-2015 Red Hat, Inc. and/or its affiliates
7 * Dave Gilbert <dgilbert@redhat.com>
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.
15 * Postcopy is a migration technique where the execution flips from the
16 * source to the destination before all the data has been copied.
23 #include "qemu-common.h"
24 #include "migration/migration.h"
25 #include "migration/postcopy-ram.h"
26 #include "sysemu/sysemu.h"
27 #include "qemu/error-report.h"
30 /* Postcopy needs to detect accesses to pages that haven't yet been copied
31 * across, and efficiently map new pages in, the techniques for doing this
32 * are target OS specific.
34 #if defined(__linux__)
37 #include <sys/ioctl.h>
38 #include <sys/syscall.h>
39 #include <sys/types.h>
40 #include <asm/types.h> /* for __u64 */
43 #if defined(__linux__) && defined(__NR_userfaultfd)
44 #include <linux/userfaultfd.h>
46 static bool ufd_version_check(int ufd
)
48 struct uffdio_api api_struct
;
51 api_struct
.api
= UFFD_API
;
52 api_struct
.features
= 0;
53 if (ioctl(ufd
, UFFDIO_API
, &api_struct
)) {
54 error_report("postcopy_ram_supported_by_host: UFFDIO_API failed: %s",
59 ioctl_mask
= (__u64
)1 << _UFFDIO_REGISTER
|
60 (__u64
)1 << _UFFDIO_UNREGISTER
;
61 if ((api_struct
.ioctls
& ioctl_mask
) != ioctl_mask
) {
62 error_report("Missing userfault features: %" PRIx64
,
63 (uint64_t)(~api_struct
.ioctls
& ioctl_mask
));
70 bool postcopy_ram_supported_by_host(void)
72 long pagesize
= getpagesize();
74 bool ret
= false; /* Error unless we change it */
75 void *testarea
= NULL
;
76 struct uffdio_register reg_struct
;
77 struct uffdio_range range_struct
;
78 uint64_t feature_mask
;
80 if ((1ul << qemu_target_page_bits()) > pagesize
) {
81 error_report("Target page size bigger than host page size");
85 ufd
= syscall(__NR_userfaultfd
, O_CLOEXEC
);
87 error_report("%s: userfaultfd not available: %s", __func__
,
92 /* Version and features check */
93 if (!ufd_version_check(ufd
)) {
98 * We need to check that the ops we need are supported on anon memory
99 * To do that we need to register a chunk and see the flags that
102 testarea
= mmap(NULL
, pagesize
, PROT_READ
| PROT_WRITE
, MAP_PRIVATE
|
103 MAP_ANONYMOUS
, -1, 0);
104 if (testarea
== MAP_FAILED
) {
105 error_report("%s: Failed to map test area: %s", __func__
,
109 g_assert(((size_t)testarea
& (pagesize
-1)) == 0);
111 reg_struct
.range
.start
= (uintptr_t)testarea
;
112 reg_struct
.range
.len
= pagesize
;
113 reg_struct
.mode
= UFFDIO_REGISTER_MODE_MISSING
;
115 if (ioctl(ufd
, UFFDIO_REGISTER
, ®_struct
)) {
116 error_report("%s userfault register: %s", __func__
, strerror(errno
));
120 range_struct
.start
= (uintptr_t)testarea
;
121 range_struct
.len
= pagesize
;
122 if (ioctl(ufd
, UFFDIO_UNREGISTER
, &range_struct
)) {
123 error_report("%s userfault unregister: %s", __func__
, strerror(errno
));
127 feature_mask
= (__u64
)1 << _UFFDIO_WAKE
|
128 (__u64
)1 << _UFFDIO_COPY
|
129 (__u64
)1 << _UFFDIO_ZEROPAGE
;
130 if ((reg_struct
.ioctls
& feature_mask
) != feature_mask
) {
131 error_report("Missing userfault map features: %" PRIx64
,
132 (uint64_t)(~reg_struct
.ioctls
& feature_mask
));
140 munmap(testarea
, pagesize
);
149 /* No target OS support, stubs just fail */
150 bool postcopy_ram_supported_by_host(void)
152 error_report("%s: No OS support", __func__
);