aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxc/xg_save_restore.h
blob: c735deab41113cd1fa9dd677ddade66250ed44bc (plain)
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
** xg_save_restore.h
** 
** Defintions and utilities for save / restore. 
*/

#include "xc_private.h"

#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 */ unsigned long *max_mfn,  
                             /* OUT */ unsigned long *hvirt_start, 
                             /* OUT */ unsigned int *pt_levels)
    
{ 
    xen_capabilities_info_t xen_caps = "";
    xen_platform_parameters_t xen_params;
    

    if (xc_version(xc_handle, XENVER_platform_parameters, &xen_params) != 0)
        return 0;
    
    if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0)
        return 0;

    if (xc_memory_op(xc_handle, XENMEM_maximum_ram_page, max_mfn) != 0)
        return 0; 
    
    *hvirt_start = xen_params.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_SHIFT - 10))
#define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1))


/* 
** The M2P is made up of some number of 'chunks' of at least 2MB in size. 
** The below definitions and utility function(s) deal with mapping the M2P 
** regarldess of the underlying machine memory size or architecture. 
*/
#define M2P_SHIFT       L2_PAGETABLE_SHIFT_PAE 
#define M2P_CHUNK_SIZE  (1 << M2P_SHIFT) 
#define M2P_SIZE(_m)    ROUNDUP(((_m) * sizeof(unsigned long)), M2P_SHIFT) 
#define M2P_CHUNKS(_m)  (M2P_SIZE((_m)) >> M2P_SHIFT)

/* Size in bytes of the P2M (rounded up to the nearest PAGE_SIZE bytes) */
#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))

/* Current guests allow 8MB 'slack' in their P2M */
#define NR_SLACK_ENTRIES   ((8 * 1024 * 1024) / PAGE_SIZE)

/* Is the given PFN within the 'slack' region at the top of the P2M? */
#define IS_REAL_PFN(_pfn)  ((max_pfn - (_pfn)) > NR_SLACK_ENTRIES) 

/* Returns TRUE if the PFN is currently mapped */
#define is_mapped(pfn_type) (!((pfn_type) & 0x80000000UL))

#define INVALID_P2M_ENTRY   (~0UL)