debuggers.hg

view tools/libxc/xg_save_restore.h @ 16715:c5deb251b9dc

Update version to 3.2.0-rc4
author Keir Fraser <keir.fraser@citrix.com>
date Sat Dec 29 17:57:37 2007 +0000 (2007-12-29)
parents 4c8394e3b011
children 0164d924ceba
line source
1 /*
2 ** xg_save_restore.h
3 **
4 ** Defintions and utilities for save / restore.
5 */
7 #include "xc_private.h"
9 #include <xen/foreign/x86_32.h>
10 #include <xen/foreign/x86_64.h>
12 /*
13 ** We process save/restore/migrate in batches of pages; the below
14 ** determines how many pages we (at maximum) deal with in each batch.
15 */
16 #define MAX_BATCH_SIZE 1024 /* up to 1024 pages (4MB) at a time */
18 /* When pinning page tables at the end of restore, we also use batching. */
19 #define MAX_PIN_BATCH 1024
23 /*
24 ** Determine various platform information required for save/restore, in
25 ** particular:
26 **
27 ** - the maximum MFN on this machine, used to compute the size of
28 ** the M2P table;
29 **
30 ** - the starting virtual address of the the hypervisor; we use this
31 ** to determine which parts of guest address space(s) do and don't
32 ** require canonicalization during save/restore; and
33 **
34 ** - the number of page-table levels for save/ restore. This should
35 ** be a property of the domain, but for the moment we just read it
36 ** from the hypervisor.
37 **
38 ** - The width of a guest word (unsigned long), in bytes.
39 **
40 ** Returns 1 on success, 0 on failure.
41 */
42 static inline int get_platform_info(int xc_handle, uint32_t dom,
43 /* OUT */ unsigned long *max_mfn,
44 /* OUT */ unsigned long *hvirt_start,
45 /* OUT */ unsigned int *pt_levels,
46 /* OUT */ unsigned int *guest_width)
47 {
48 xen_capabilities_info_t xen_caps = "";
49 xen_platform_parameters_t xen_params;
50 DECLARE_DOMCTL;
52 if (xc_version(xc_handle, XENVER_platform_parameters, &xen_params) != 0)
53 return 0;
55 if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0)
56 return 0;
58 *max_mfn = xc_memory_op(xc_handle, XENMEM_maximum_ram_page, NULL);
60 *hvirt_start = xen_params.virt_start;
62 memset(&domctl, 0, sizeof(domctl));
63 domctl.domain = dom;
64 domctl.cmd = XEN_DOMCTL_get_address_size;
66 if ( do_domctl(xc_handle, &domctl) != 0 )
67 return 0;
69 *guest_width = domctl.u.address_size.size / 8;
71 if (strstr(xen_caps, "xen-3.0-x86_64"))
72 /* Depends on whether it's a compat 32-on-64 guest */
73 *pt_levels = ( (*guest_width == 8) ? 4 : 3 );
74 else if (strstr(xen_caps, "xen-3.0-x86_32p"))
75 *pt_levels = 3;
76 else if (strstr(xen_caps, "xen-3.0-x86_32"))
77 *pt_levels = 2;
78 else
79 return 0;
81 return 1;
82 }
85 /*
86 ** Save/restore deal with the mfn_to_pfn (M2P) and pfn_to_mfn (P2M) tables.
87 ** The M2P simply holds the corresponding PFN, while the top bit of a P2M
88 ** entry tell us whether or not the the PFN is currently mapped.
89 */
91 #define PFN_TO_KB(_pfn) ((_pfn) << (PAGE_SHIFT - 10))
94 /*
95 ** The M2P is made up of some number of 'chunks' of at least 2MB in size.
96 ** The below definitions and utility function(s) deal with mapping the M2P
97 ** regarldess of the underlying machine memory size or architecture.
98 */
99 #define M2P_SHIFT L2_PAGETABLE_SHIFT_PAE
100 #define M2P_CHUNK_SIZE (1 << M2P_SHIFT)
101 #define M2P_SIZE(_m) ROUNDUP(((_m) * sizeof(xen_pfn_t)), M2P_SHIFT)
102 #define M2P_CHUNKS(_m) (M2P_SIZE((_m)) >> M2P_SHIFT)
104 /* Returns TRUE if the PFN is currently mapped */
105 #define is_mapped(pfn_type) (!((pfn_type) & 0x80000000UL))
108 /* 32-on-64 support: saving 32bit guests from 64bit tools and vice versa */
109 typedef union
110 {
111 vcpu_guest_context_x86_64_t x64;
112 vcpu_guest_context_x86_32_t x32;
113 vcpu_guest_context_t c;
114 } vcpu_guest_context_either_t;
116 typedef union
117 {
118 shared_info_x86_64_t x64;
119 shared_info_x86_32_t x32;
120 shared_info_t s;
121 } shared_info_either_t;
123 typedef union
124 {
125 start_info_x86_64_t x64;
126 start_info_x86_32_t x32;
127 start_info_t s;
128 } start_info_either_t;
130 #define GET_FIELD(_p, _f) ((guest_width==8) ? ((_p)->x64._f) : ((_p)->x32._f))
132 #define SET_FIELD(_p, _f, _v) do { \
133 if (guest_width == 8) \
134 (_p)->x64._f = (_v); \
135 else \
136 (_p)->x32._f = (_v); \
137 } while (0)
139 #define MEMCPY_FIELD(_d, _s, _f) do { \
140 if (guest_width == 8) \
141 memcpy(&(_d)->x64._f, &(_s)->x64._f,sizeof((_d)->x64._f)); \
142 else \
143 memcpy(&(_d)->x32._f, &(_s)->x32._f,sizeof((_d)->x32._f)); \
144 } while (0)
146 #define MEMSET_ARRAY_FIELD(_p, _f, _v) do { \
147 if (guest_width == 8) \
148 memset(&(_p)->x64._f[0], (_v), sizeof((_p)->x64._f)); \
149 else \
150 memset(&(_p)->x32._f[0], (_v), sizeof((_p)->x32._f)); \
151 } while (0)
153 #ifndef MAX
154 #define MAX(_a, _b) ((_a) >= (_b) ? (_a) : (_b))
155 #endif
156 #ifndef MIN
157 #define MIN(_a, _b) ((_a) <= (_b) ? (_a) : (_b))
158 #endif