ia64/xen-unstable

view tools/libxc/xc_resume.c @ 13608:30af6cfdb05c

Make domctl/sysctl interfaces 32-/64-bit invariant.
This kills off a fair amount of unpleasant CONFIG_COMPAT shimming and
avoids needing to keep the compat paths in sync as these interfaces
continue to develop.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Wed Jan 24 16:33:19 2007 +0000 (2007-01-24)
parents b280c75f2622
children 270a5e2ead43
line source
1 #include "xc_private.h"
2 #include "xg_private.h"
3 #include "xg_save_restore.h"
5 #if defined(__i386__) || defined(__x86_64__)
6 static int modify_returncode(int xc_handle, uint32_t domid)
7 {
8 vcpu_guest_context_t ctxt;
9 int rc;
11 if ( (rc = xc_vcpu_getcontext(xc_handle, domid, 0, &ctxt)) != 0 )
12 return rc;
13 ctxt.user_regs.eax = 1;
14 if ( (rc = xc_vcpu_setcontext(xc_handle, domid, 0, &ctxt)) != 0 )
15 return rc;
17 return 0;
18 }
19 #else
20 static int modify_returncode(int xc_handle, uint32_t domid)
21 {
22 return 0;
23 }
24 #endif
26 static int xc_domain_resume_cooperative(int xc_handle, uint32_t domid)
27 {
28 DECLARE_DOMCTL;
29 int rc;
31 /*
32 * Set hypercall return code to indicate that suspend is cancelled
33 * (rather than resuming in a new domain context).
34 */
35 if ( (rc = modify_returncode(xc_handle, domid)) != 0 )
36 return rc;
38 domctl.cmd = XEN_DOMCTL_resumedomain;
39 domctl.domain = domid;
40 return do_domctl(xc_handle, &domctl);
41 }
43 static int xc_domain_resume_any(int xc_handle, uint32_t domid)
44 {
45 DECLARE_DOMCTL;
46 xc_dominfo_t info;
47 int i, rc = -1;
48 #if defined(__i386__) || defined(__x86_64__)
49 unsigned long mfn, max_pfn = 0;
50 vcpu_guest_context_t ctxt;
51 start_info_t *start_info;
52 shared_info_t *shinfo = NULL;
53 xen_pfn_t *p2m_frame_list_list = NULL;
54 xen_pfn_t *p2m_frame_list = NULL;
55 xen_pfn_t *p2m = NULL;
56 #endif
58 if ( xc_domain_getinfo(xc_handle, domid, 1, &info) != 1 )
59 {
60 PERROR("Could not get domain info");
61 return rc;
62 }
64 /*
65 * (x86 only) Rewrite store_mfn and console_mfn back to MFN (from PFN).
66 */
67 #if defined(__i386__) || defined(__x86_64__)
68 /* Map the shared info frame */
69 shinfo = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
70 PROT_READ, info.shared_info_frame);
71 if ( shinfo == NULL )
72 {
73 ERROR("Couldn't map shared info");
74 goto out;
75 }
77 max_pfn = shinfo->arch.max_pfn;
79 p2m_frame_list_list =
80 xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, PROT_READ,
81 shinfo->arch.pfn_to_mfn_frame_list_list);
82 if ( p2m_frame_list_list == NULL )
83 {
84 ERROR("Couldn't map p2m_frame_list_list");
85 goto out;
86 }
88 p2m_frame_list = xc_map_foreign_batch(xc_handle, domid, PROT_READ,
89 p2m_frame_list_list,
90 P2M_FLL_ENTRIES);
91 if ( p2m_frame_list == NULL )
92 {
93 ERROR("Couldn't map p2m_frame_list");
94 goto out;
95 }
97 /* Map all the frames of the pfn->mfn table. For migrate to succeed,
98 the guest must not change which frames are used for this purpose.
99 (its not clear why it would want to change them, and we'll be OK
100 from a safety POV anyhow. */
101 p2m = xc_map_foreign_batch(xc_handle, domid, PROT_READ,
102 p2m_frame_list,
103 P2M_FL_ENTRIES);
104 if ( p2m == NULL )
105 {
106 ERROR("Couldn't map p2m table");
107 goto out;
108 }
110 if ( lock_pages(&ctxt, sizeof(ctxt)) )
111 {
112 ERROR("Unable to lock ctxt");
113 goto out;
114 }
116 if ( xc_vcpu_getcontext(xc_handle, domid, 0, &ctxt) )
117 {
118 ERROR("Could not get vcpu context");
119 goto out;
120 }
122 mfn = ctxt.user_regs.edx;
124 start_info = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
125 PROT_READ | PROT_WRITE, mfn);
126 if ( start_info == NULL )
127 {
128 ERROR("Couldn't map start_info");
129 goto out;
130 }
132 start_info->store_mfn = p2m[start_info->store_mfn];
133 start_info->console.domU.mfn = p2m[start_info->console.domU.mfn];
135 munmap(start_info, PAGE_SIZE);
136 #endif /* defined(__i386__) || defined(__x86_64__) */
138 /* Reset all secondary CPU states. */
139 for ( i = 1; i <= info.max_vcpu_id; i++ )
140 xc_vcpu_setcontext(xc_handle, domid, i, NULL);
142 /* Ready to resume domain execution now. */
143 domctl.cmd = XEN_DOMCTL_resumedomain;
144 domctl.domain = domid;
145 rc = do_domctl(xc_handle, &domctl);
147 #if defined(__i386__) || defined(__x86_64__)
148 out:
149 unlock_pages((void *)&ctxt, sizeof ctxt);
150 if (p2m)
151 munmap(p2m, P2M_FL_ENTRIES*PAGE_SIZE);
152 if (p2m_frame_list)
153 munmap(p2m_frame_list, P2M_FLL_ENTRIES*PAGE_SIZE);
154 if (p2m_frame_list_list)
155 munmap(p2m_frame_list_list, PAGE_SIZE);
156 if (shinfo)
157 munmap(shinfo, PAGE_SIZE);
158 #endif
160 return rc;
161 }
163 /*
164 * Resume execution of a domain after suspend shutdown.
165 * This can happen in one of two ways:
166 * 1. Resume with special return code.
167 * 2. Reset guest environment so it believes it is resumed in a new
168 * domain context.
169 * (2) should be used only for guests which cannot handle the special
170 * new return code. (1) is always safe (but slower).
171 */
172 int xc_domain_resume(int xc_handle, uint32_t domid)
173 {
174 /*
175 * XXX: Implement a way to select between options (1) and (2).
176 * Or expose the options as two different methods to Python.
177 */
178 return (0
179 ? xc_domain_resume_cooperative(xc_handle, domid)
180 : xc_domain_resume_any(xc_handle, domid));
181 }