xref: /qemu/migration/postcopy-ram.h (revision d91f33c7)
1be07b0acSJuan Quintela /*
2be07b0acSJuan Quintela  * Postcopy migration for RAM
3be07b0acSJuan Quintela  *
4be07b0acSJuan Quintela  * Copyright 2013 Red Hat, Inc. and/or its affiliates
5be07b0acSJuan Quintela  *
6be07b0acSJuan Quintela  * Authors:
7be07b0acSJuan Quintela  *  Dave Gilbert  <dgilbert@redhat.com>
8be07b0acSJuan Quintela  *
9be07b0acSJuan Quintela  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10be07b0acSJuan Quintela  * See the COPYING file in the top-level directory.
11be07b0acSJuan Quintela  *
12be07b0acSJuan Quintela  */
13be07b0acSJuan Quintela #ifndef QEMU_POSTCOPY_RAM_H
14be07b0acSJuan Quintela #define QEMU_POSTCOPY_RAM_H
15be07b0acSJuan Quintela 
16be07b0acSJuan Quintela /* Return true if the host supports everything we need to do postcopy-ram */
1774c38cf7SPeter Xu bool postcopy_ram_supported_by_host(MigrationIncomingState *mis,
1874c38cf7SPeter Xu                                     Error **errp);
19be07b0acSJuan Quintela 
20be07b0acSJuan Quintela /*
21be07b0acSJuan Quintela  * Make all of RAM sensitive to accesses to areas that haven't yet been written
22be07b0acSJuan Quintela  * and wire up anything necessary to deal with it.
23be07b0acSJuan Quintela  */
242a7eb148SWei Yang int postcopy_ram_incoming_setup(MigrationIncomingState *mis);
25be07b0acSJuan Quintela 
26be07b0acSJuan Quintela /*
27be07b0acSJuan Quintela  * Initialise postcopy-ram, setting the RAM to a state where we can go into
28be07b0acSJuan Quintela  * postcopy later; must be called prior to any precopy.
29be07b0acSJuan Quintela  * called from ram.c's similarly named ram_postcopy_incoming_init
30be07b0acSJuan Quintela  */
31c136180cSDavid Hildenbrand int postcopy_ram_incoming_init(MigrationIncomingState *mis);
32be07b0acSJuan Quintela 
33be07b0acSJuan Quintela /*
34be07b0acSJuan Quintela  * At the end of a migration where postcopy_ram_incoming_init was called.
35be07b0acSJuan Quintela  */
36be07b0acSJuan Quintela int postcopy_ram_incoming_cleanup(MigrationIncomingState *mis);
37be07b0acSJuan Quintela 
38be07b0acSJuan Quintela /*
39be07b0acSJuan Quintela  * Userfault requires us to mark RAM as NOHUGEPAGE prior to discard
40be07b0acSJuan Quintela  * however leaving it until after precopy means that most of the precopy
41be07b0acSJuan Quintela  * data is still THPd
42be07b0acSJuan Quintela  */
43be07b0acSJuan Quintela int postcopy_ram_prepare_discard(MigrationIncomingState *mis);
44be07b0acSJuan Quintela 
45be07b0acSJuan Quintela /*
46be07b0acSJuan Quintela  * Called at the start of each RAMBlock by the bitmap code.
47be07b0acSJuan Quintela  */
48810cf2bbSWei Yang void postcopy_discard_send_init(MigrationState *ms, const char *name);
49be07b0acSJuan Quintela 
50be07b0acSJuan Quintela /*
51be07b0acSJuan Quintela  * Called by the bitmap code for each chunk to discard.
52be07b0acSJuan Quintela  * May send a discard message, may just leave it queued to
53be07b0acSJuan Quintela  * be sent later.
54be07b0acSJuan Quintela  * @start,@length: a range of pages in the migration bitmap in the
55be07b0acSJuan Quintela  *  RAM block passed to postcopy_discard_send_init() (length=1 is one page)
56be07b0acSJuan Quintela  */
57810cf2bbSWei Yang void postcopy_discard_send_range(MigrationState *ms, unsigned long start,
58810cf2bbSWei Yang                                  unsigned long length);
59be07b0acSJuan Quintela 
60be07b0acSJuan Quintela /*
61be07b0acSJuan Quintela  * Called at the end of each RAMBlock by the bitmap code.
62810cf2bbSWei Yang  * Sends any outstanding discard messages.
63be07b0acSJuan Quintela  */
64810cf2bbSWei Yang void postcopy_discard_send_finish(MigrationState *ms);
65be07b0acSJuan Quintela 
66be07b0acSJuan Quintela /*
67be07b0acSJuan Quintela  * Place a page (from) at (host) efficiently
68be07b0acSJuan Quintela  *    There are restrictions on how 'from' must be mapped, in general best
69be07b0acSJuan Quintela  *    to use other postcopy_ routines to allocate.
70be07b0acSJuan Quintela  * returns 0 on success
71be07b0acSJuan Quintela  */
72be07b0acSJuan Quintela int postcopy_place_page(MigrationIncomingState *mis, void *host, void *from,
738be4620bSAlexey Perevalov                         RAMBlock *rb);
74be07b0acSJuan Quintela 
75be07b0acSJuan Quintela /*
76be07b0acSJuan Quintela  * Place a zero page at (host) atomically
77be07b0acSJuan Quintela  * returns 0 on success
78be07b0acSJuan Quintela  */
79be07b0acSJuan Quintela int postcopy_place_page_zero(MigrationIncomingState *mis, void *host,
808be4620bSAlexey Perevalov                              RAMBlock *rb);
81be07b0acSJuan Quintela 
82bac3b212SJuan Quintela /* The current postcopy state is read/set by postcopy_state_get/set
83bac3b212SJuan Quintela  * which update it atomically.
84bac3b212SJuan Quintela  * The state is updated as postcopy messages are received, and
85bac3b212SJuan Quintela  * in general only one thread should be writing to the state at any one
86bac3b212SJuan Quintela  * time, initially the main thread and then the listen thread;
87bac3b212SJuan Quintela  * Corner cases are where either thread finishes early and/or errors.
88bac3b212SJuan Quintela  * The state is checked as messages are received to ensure that
89bac3b212SJuan Quintela  * the source is sending us messages in the correct order.
90bac3b212SJuan Quintela  * The state is also used by the RAM reception code to know if it
91bac3b212SJuan Quintela  * has to place pages atomically, and the cleanup code at the end of
92bac3b212SJuan Quintela  * the main thread to know if it has to delay cleanup until the end
93bac3b212SJuan Quintela  * of postcopy.
94bac3b212SJuan Quintela  */
95bac3b212SJuan Quintela typedef enum {
96bac3b212SJuan Quintela     POSTCOPY_INCOMING_NONE = 0,  /* Initial state - no postcopy */
97bac3b212SJuan Quintela     POSTCOPY_INCOMING_ADVISE,
98bac3b212SJuan Quintela     POSTCOPY_INCOMING_DISCARD,
99bac3b212SJuan Quintela     POSTCOPY_INCOMING_LISTENING,
100bac3b212SJuan Quintela     POSTCOPY_INCOMING_RUNNING,
101bac3b212SJuan Quintela     POSTCOPY_INCOMING_END
102bac3b212SJuan Quintela } PostcopyState;
103bac3b212SJuan Quintela 
104bac3b212SJuan Quintela PostcopyState postcopy_state_get(void);
105bac3b212SJuan Quintela /* Set the state and return the old state */
106bac3b212SJuan Quintela PostcopyState postcopy_state_set(PostcopyState new_state);
107bac3b212SJuan Quintela 
1089ab7ef9bSPeter Xu void postcopy_fault_thread_notify(MigrationIncomingState *mis);
1099ab7ef9bSPeter Xu 
1101693c64cSDr. David Alan Gilbert /*
1111693c64cSDr. David Alan Gilbert  * To be called once at the start before any device initialisation
1121693c64cSDr. David Alan Gilbert  */
1131693c64cSDr. David Alan Gilbert void postcopy_infrastructure_init(void);
1141693c64cSDr. David Alan Gilbert 
1151693c64cSDr. David Alan Gilbert /* Add a notifier to a list to be called when checking whether the devices
1161693c64cSDr. David Alan Gilbert  * can support postcopy.
1171693c64cSDr. David Alan Gilbert  * It's data is a *PostcopyNotifyData
1181693c64cSDr. David Alan Gilbert  * It should return 0 if OK, or a negative value on failure.
1191693c64cSDr. David Alan Gilbert  * On failure it must set the data->errp to an error.
1201693c64cSDr. David Alan Gilbert  *
1211693c64cSDr. David Alan Gilbert  */
1221693c64cSDr. David Alan Gilbert enum PostcopyNotifyReason {
1231693c64cSDr. David Alan Gilbert     POSTCOPY_NOTIFY_PROBE = 0,
124d3dff7a5SDr. David Alan Gilbert     POSTCOPY_NOTIFY_INBOUND_ADVISE,
1256864a7b5SDr. David Alan Gilbert     POSTCOPY_NOTIFY_INBOUND_LISTEN,
12646343570SDr. David Alan Gilbert     POSTCOPY_NOTIFY_INBOUND_END,
1271693c64cSDr. David Alan Gilbert };
1281693c64cSDr. David Alan Gilbert 
1291693c64cSDr. David Alan Gilbert struct PostcopyNotifyData {
1301693c64cSDr. David Alan Gilbert     enum PostcopyNotifyReason reason;
1311693c64cSDr. David Alan Gilbert };
1321693c64cSDr. David Alan Gilbert 
1331693c64cSDr. David Alan Gilbert void postcopy_add_notifier(NotifierWithReturn *nn);
1341693c64cSDr. David Alan Gilbert void postcopy_remove_notifier(NotifierWithReturn *n);
1351693c64cSDr. David Alan Gilbert /* Call the notifier list set by postcopy_add_start_notifier */
1361693c64cSDr. David Alan Gilbert int postcopy_notify(enum PostcopyNotifyReason reason, Error **errp);
1371693c64cSDr. David Alan Gilbert 
138095c12a4SPeter Xu void postcopy_thread_create(MigrationIncomingState *mis,
139095c12a4SPeter Xu                             QemuThread *thread, const char *name,
140095c12a4SPeter Xu                             void *(*fn)(void *), int joinable);
141095c12a4SPeter Xu 
14200fa4fc8SDr. David Alan Gilbert struct PostCopyFD;
14300fa4fc8SDr. David Alan Gilbert 
14400fa4fc8SDr. David Alan Gilbert /* ufd is a pointer to the struct uffd_msg *TODO: more Portable! */
14500fa4fc8SDr. David Alan Gilbert typedef int (*pcfdhandler)(struct PostCopyFD *pcfd, void *ufd);
146d488b349SDr. David Alan Gilbert /* Notification to wake, either on place or on reception of
147d488b349SDr. David Alan Gilbert  * a fault on something that's already arrived (race)
148d488b349SDr. David Alan Gilbert  */
149d488b349SDr. David Alan Gilbert typedef int (*pcfdwake)(struct PostCopyFD *pcfd, RAMBlock *rb, uint64_t offset);
15000fa4fc8SDr. David Alan Gilbert 
15100fa4fc8SDr. David Alan Gilbert struct PostCopyFD {
15200fa4fc8SDr. David Alan Gilbert     int fd;
15300fa4fc8SDr. David Alan Gilbert     /* Data to pass to handler */
15400fa4fc8SDr. David Alan Gilbert     void *data;
15500fa4fc8SDr. David Alan Gilbert     /* Handler to be called whenever we get a poll event */
15600fa4fc8SDr. David Alan Gilbert     pcfdhandler handler;
157d488b349SDr. David Alan Gilbert     /* Notification to wake shared client */
158d488b349SDr. David Alan Gilbert     pcfdwake waker;
15900fa4fc8SDr. David Alan Gilbert     /* A string to use in error messages */
16000fa4fc8SDr. David Alan Gilbert     const char *idstr;
16100fa4fc8SDr. David Alan Gilbert };
16200fa4fc8SDr. David Alan Gilbert 
16300fa4fc8SDr. David Alan Gilbert /* Register a userfaultfd owned by an external process for
16400fa4fc8SDr. David Alan Gilbert  * shared memory.
16500fa4fc8SDr. David Alan Gilbert  */
16600fa4fc8SDr. David Alan Gilbert void postcopy_register_shared_ufd(struct PostCopyFD *pcfd);
16700fa4fc8SDr. David Alan Gilbert void postcopy_unregister_shared_ufd(struct PostCopyFD *pcfd);
1683a4452d8Szhaolichang /* Call each of the shared 'waker's registered telling them of
169d488b349SDr. David Alan Gilbert  * availability of a block.
170d488b349SDr. David Alan Gilbert  */
171d488b349SDr. David Alan Gilbert int postcopy_notify_shared_wake(RAMBlock *rb, uint64_t offset);
1725efc3564SDr. David Alan Gilbert /* postcopy_wake_shared: Notify a client ufd that a page is available
1735efc3564SDr. David Alan Gilbert  *
1745efc3564SDr. David Alan Gilbert  * Returns 0 on success
1755efc3564SDr. David Alan Gilbert  *
1765efc3564SDr. David Alan Gilbert  * @pcfd: Structure with fd, handler and name as above
1775efc3564SDr. David Alan Gilbert  * @client_addr: Address in the client program, not QEMU
1785efc3564SDr. David Alan Gilbert  * @rb: The RAMBlock the page is in
1795efc3564SDr. David Alan Gilbert  */
1805efc3564SDr. David Alan Gilbert int postcopy_wake_shared(struct PostCopyFD *pcfd, uint64_t client_addr,
1815efc3564SDr. David Alan Gilbert                          RAMBlock *rb);
182096bf4c8SDr. David Alan Gilbert /* Callback from shared fault handlers to ask for a page */
183096bf4c8SDr. David Alan Gilbert int postcopy_request_shared_page(struct PostCopyFD *pcfd, RAMBlock *rb,
184096bf4c8SDr. David Alan Gilbert                                  uint64_t client_addr, uint64_t offset);
18500fa4fc8SDr. David Alan Gilbert 
18636f62f11SPeter Xu /* Hard-code channels for now for postcopy preemption */
18736f62f11SPeter Xu enum PostcopyChannels {
18836f62f11SPeter Xu     RAM_CHANNEL_PRECOPY = 0,
18936f62f11SPeter Xu     RAM_CHANNEL_POSTCOPY = 1,
19036f62f11SPeter Xu     RAM_CHANNEL_MAX,
19136f62f11SPeter Xu };
19236f62f11SPeter Xu 
1936720c2b3Smanish.mishra void postcopy_preempt_new_channel(MigrationIncomingState *mis, QEMUFile *file);
194fc063a7bSPeter Xu void postcopy_preempt_setup(MigrationState *s);
1955655aab0SPeter Xu int postcopy_preempt_establish_channel(MigrationState *s);
19636f62f11SPeter Xu 
197be07b0acSJuan Quintela #endif
198