1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
/*
** xg_save_restore.h
**
** Defintions and utilities for save / restore.
*/
#define DEBUG 1
#define PROGRESS 0
#define ERR(_f, _a...) do { \
fprintf(stderr, _f "\n" , ## _a); \
fflush(stderr); } \
while (0)
#if DEBUG
#define DPRINTF(_f, _a...) fprintf(stderr, _f , ## _a)
#else
#define DPRINTF(_f, _a...) ((void)0)
#endif
#if PROGRESS
#define PPRINTF(_f, _a...) fprintf(stderr, _f , ## _a)
#else
#define PPRINTF(_f, _a...)
#endif
/*
** We process save/restore/migrate in batches of pages; the below
** determines how many pages we (at maximum) deal with in each batch.
*/
#define MAX_BATCH_SIZE 1024 /* up to 1024 pages (4MB) at a time */
/* When pinning page tables at the end of restore, we also use batching. */
#define MAX_PIN_BATCH 1024
/*
** Determine various platform information required for save/restore, in
** particular:
**
** - the maximum MFN on this machine, used to compute the size of
** the M2P table;
**
** - the starting virtual address of the the hypervisor; we use this
** to determine which parts of guest address space(s) do and don't
** require canonicalization during save/restore; and
**
** - the number of page-table levels for save/ restore. This should
** be a property of the domain, but for the moment we just read it
** from the hypervisor.
**
** Returns 1 on success, 0 on failure.
*/
static int get_platform_info(int xc_handle, uint32_t dom,
/* OUT */ uint32_t *max_mfn,
/* OUT */ uint32_t *hvirt_start,
/* OUT */ uint32_t *pt_levels)
{
xen_capabilities_info_t xen_caps = "";
xen_parameters_info_t xen_parms;
xc_physinfo_t physinfo;
if (xc_physinfo(xc_handle, &physinfo) != 0)
return 0;
if (xc_version(xc_handle, XENVER_parameters, &xen_parms) != 0)
return 0;
if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0)
return 0;
*max_mfn = physinfo.total_pages;
*hvirt_start = xen_parms.virt_start;
if (strstr(xen_caps, "xen-3.0-x86_64"))
*pt_levels = 4;
else if (strstr(xen_caps, "xen-3.0-x86_32p"))
*pt_levels = 3;
else if (strstr(xen_caps, "xen-3.0-x86_32"))
*pt_levels = 2;
else
return 0;
return 1;
}
/*
** Save/restore deal with the mfn_to_pfn (M2P) and pfn_to_mfn (P2M) tables.
** The M2P simply holds the corresponding PFN, while the top bit of a P2M
** entry tell us whether or not the the PFN is currently mapped.
*/
#define PFN_TO_KB(_pfn) ((_pfn) * PAGE_SIZE / 1024)
#define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1))
/* Size in bytes of the M2P and P2M (both rounded up to nearest PAGE_SIZE) */
#define M2P_SIZE ROUNDUP((max_mfn * sizeof(unsigned long)), PAGE_SHIFT)
#define P2M_SIZE ROUNDUP((max_pfn * sizeof(unsigned long)), PAGE_SHIFT)
/* Number of unsigned longs in a page */
#define ulpp (PAGE_SIZE/sizeof(unsigned long))
/* Number of entries in the pfn_to_mfn_frame_list */
#define P2M_FL_ENTRIES (((max_pfn)+ulpp-1)/ulpp)
/* Size in bytes of the pfn_to_mfn_frame_list */
#define P2M_FL_SIZE ((P2M_FL_ENTRIES)*sizeof(unsigned long))
/* Number of entries in the pfn_to_mfn_frame_list_list */
#define P2M_FLL_ENTRIES (((max_pfn)+(ulpp*ulpp)-1)/(ulpp*ulpp))
/* Returns TRUE if the PFN is currently mapped */
#define is_mapped(pfn_type) (!((pfn_type) & 0x80000000UL))
#define INVALID_P2M_ENTRY (~0UL)
|