ia64/xen-unstable

view tools/libxc/xc_dom_ia64.c @ 19639:205b1badbcfd

Add support for superpages (hugepages) in PV domain

This patch adds the option "superpages" to the domain configuration
file. If it is set, the domain is populated using 2M pages.

This code does not support fallback to small pages. If the domain can
not be created with 2M pages, the create will fail.

The patch also includes support for saving and restoring domains with
the superpage flag set. However, if a domain has freed small pages
within its physical page array and then extended the array, the
restore will fill in those freed pages. It will then attempt to
allocate more than its memory limit and will fail. This is
significant because apparently Linux does this during boot, thus a
freshly booted Linux image can not be saved and restored successfully.

Signed-off-by: Dave McCracken <dcm@mccr.org>
author Keir Fraser <keir.fraser@citrix.com>
date Tue May 26 09:58:38 2009 +0100 (2009-05-26)
parents 031c8f407e01
children 2f9e1348aa98
line source
1 /*
2 * Xen domain builder -- ia64 bits.
3 *
4 * Most architecture-specific code for ia64 goes here.
5 * - fill architecture-specific structs.
6 *
7 * This code is licenced under the GPL.
8 * written 2006 by Gerd Hoffmann <kraxel@suse.de>.
9 *
10 */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <inttypes.h>
15 #include <assert.h>
16 #include <asm/kregs.h>
18 #include <xen/xen.h>
19 #include <xen/foreign/ia64.h>
20 #include <xen/io/protocols.h>
22 #include "xg_private.h"
23 #include "xc_dom.h"
24 #include "xenctrl.h"
26 #include <asm/dom_fw_common.h>
27 #include "ia64/xc_dom_ia64_util.h"
29 /* ------------------------------------------------------------------------ */
31 static int alloc_magic_pages(struct xc_dom_image *dom)
32 {
33 /* allocate special pages */
34 dom->console_pfn = dom->total_pages -1;
35 dom->xenstore_pfn = dom->total_pages -2;
36 dom->start_info_pfn = dom->total_pages -3;
37 return 0;
38 }
40 int start_info_ia64(struct xc_dom_image *dom)
41 {
42 start_info_ia64_t *start_info =
43 xc_dom_pfn_to_ptr(dom, dom->start_info_pfn, 1);
44 struct xen_ia64_boot_param_ia64 *bp =
45 (struct xen_ia64_boot_param_ia64 *)(start_info + 1);
47 xc_dom_printf("%s\n", __FUNCTION__);
49 memset(start_info, 0, sizeof(*start_info));
50 sprintf(start_info->magic, dom->guest_type);
51 start_info->flags = dom->flags;
52 start_info->nr_pages = dom->total_pages;
53 start_info->store_mfn = dom->xenstore_pfn;
54 start_info->store_evtchn = dom->xenstore_evtchn;
55 start_info->console.domU.mfn = dom->console_pfn;
56 start_info->console.domU.evtchn = dom->console_evtchn;
58 /*
59 * domain_start and domain_size are abused for arch_setup hypercall
60 * so that we need to clear them here.
61 */
62 XEN_IA64_MEMMAP_INFO_NUM_PAGES(bp) = 0;
63 XEN_IA64_MEMMAP_INFO_PFN(bp) = 0;
65 if ( dom->ramdisk_blob )
66 {
67 start_info->mod_start = dom->ramdisk_seg.vstart;
68 start_info->mod_len = dom->ramdisk_seg.vend - dom->ramdisk_seg.vstart;
69 bp->initrd_start = start_info->mod_start;
70 bp->initrd_size = start_info->mod_len;
71 }
72 bp->command_line = (dom->start_info_pfn << PAGE_SHIFT_IA64)
73 + offsetof(start_info_t, cmd_line);
74 if ( dom->cmdline )
75 {
76 strncpy((char *)start_info->cmd_line, dom->cmdline, MAX_GUEST_CMDLINE);
77 start_info->cmd_line[MAX_GUEST_CMDLINE - 1] = '\0';
78 }
79 return 0;
80 }
82 int shared_info_ia64(struct xc_dom_image *dom, void *ptr)
83 {
84 shared_info_ia64_t *shared_info = ptr;
85 int i;
87 xc_dom_printf("%s: called\n", __FUNCTION__);
89 memset(shared_info, 0, sizeof(*shared_info));
90 for (i = 0; i < MAX_VIRT_CPUS; i++)
91 shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
92 shared_info->arch.start_info_pfn = dom->start_info_pfn;
93 shared_info->arch.memmap_info_num_pages = 1; //XXX
94 shared_info->arch.memmap_info_pfn = dom->start_info_pfn - 1;
95 return 0;
96 }
98 extern unsigned long xc_ia64_fpsr_default(void);
100 static int vcpu_ia64(struct xc_dom_image *dom, void *ptr)
101 {
102 vcpu_guest_context_ia64_t *ctxt = ptr;
104 xc_dom_printf("%s: called\n", __FUNCTION__);
106 /* clear everything */
107 memset(ctxt, 0, sizeof(*ctxt));
109 ctxt->flags = 0;
110 /* PSR is set according to SAL 3.2.4: AC, IC and BN are set. */
111 ctxt->regs.psr = IA64_PSR_AC | IA64_PSR_IC | IA64_PSR_BN;
112 ctxt->regs.ip = dom->parms.virt_entry;
113 ctxt->regs.cfm = 1UL << 63;
114 #ifdef __ia64__ /* FIXME */
115 ctxt->regs.ar.fpsr = xc_ia64_fpsr_default();
116 #endif
117 ctxt->regs.r[28] = (dom->start_info_pfn << PAGE_SHIFT_IA64)
118 + sizeof(start_info_ia64_t);
119 return 0;
120 }
122 /* ------------------------------------------------------------------------ */
124 static struct xc_dom_arch xc_dom_arch = {
125 .guest_type = "xen-3.0-ia64",
126 .native_protocol = XEN_IO_PROTO_ABI_IA64,
127 .page_shift = PAGE_SHIFT_IA64,
128 .alloc_magic_pages = alloc_magic_pages,
129 .start_info = start_info_ia64,
130 .shared_info = shared_info_ia64,
131 .vcpu = vcpu_ia64,
132 };
134 static struct xc_dom_arch xc_dom_arch_ia64be = {
135 .guest_type = "xen-3.0-ia64be",
136 .native_protocol = XEN_IO_PROTO_ABI_IA64,
137 .page_shift = PAGE_SHIFT_IA64,
138 .alloc_magic_pages = alloc_magic_pages,
139 .start_info = start_info_ia64,
140 .shared_info = shared_info_ia64,
141 .vcpu = vcpu_ia64,
142 };
144 static void __init register_arch_hooks(void)
145 {
146 xc_dom_register_arch_hooks(&xc_dom_arch);
147 xc_dom_register_arch_hooks(&xc_dom_arch_ia64be);
148 }
150 #include "xc_efi.h"
152 int arch_setup_meminit(struct xc_dom_image *dom, int superpages)
153 {
154 xen_pfn_t pfn;
155 int rc;
156 unsigned long start;
157 unsigned long nbr;
159 /* setup initial p2m */
160 if (dom->guest_type && strcmp(dom->guest_type,
161 "hvm-3.0-ia64-sioemu") == 0) {
162 start = FW_MEM_BASE >> PAGE_SHIFT_IA64;
163 nbr = FW_MEM_SIZE >> PAGE_SHIFT_IA64;
164 } else {
165 start = 0;
166 nbr = dom->total_pages;
167 }
169 /* setup initial p2m */
170 dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * nbr);
171 for ( pfn = 0; pfn < nbr; pfn++ )
172 dom->p2m_host[pfn] = start + pfn;
174 /* allocate guest memory */
175 rc = xc_domain_memory_populate_physmap(dom->guest_xc, dom->guest_domid,
176 nbr, 0, 0,
177 dom->p2m_host);
178 return rc;
179 }
181 static int ia64_setup_memmap(struct xc_dom_image *dom)
182 {
183 unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
184 unsigned long memmap_info_num_pages;
185 unsigned long memmap_info_pfn;
186 xen_ia64_memmap_info_t* memmap_info;
187 unsigned int num_mds;
188 efi_memory_desc_t *md;
190 char* start_info;
191 struct xen_ia64_boot_param* bp;
193 /* setup memmap page */
194 memmap_info_num_pages = 1;
195 memmap_info_pfn = dom->start_info_pfn - 1;
196 xc_dom_printf("%s: memmap: mfn 0x%" PRIpfn " pages 0x%lx\n",
197 __FUNCTION__, memmap_info_pfn, memmap_info_num_pages);
198 memmap_info = xc_map_foreign_range(dom->guest_xc, dom->guest_domid,
199 page_size * memmap_info_num_pages,
200 PROT_READ | PROT_WRITE,
201 memmap_info_pfn);
202 if (NULL == memmap_info)
203 return -1;
204 /* [0, total_pages) */
205 memmap_info->efi_memdesc_size = sizeof(md[0]);
206 memmap_info->efi_memdesc_version = EFI_MEMORY_DESCRIPTOR_VERSION;
207 num_mds = 0;
208 md = (efi_memory_desc_t*)&memmap_info->memdesc;
209 md[num_mds].type = EFI_CONVENTIONAL_MEMORY;
210 md[num_mds].pad = 0;
211 md[num_mds].phys_addr = 0;
212 md[num_mds].virt_addr = 0;
213 md[num_mds].num_pages = dom->total_pages << (PAGE_SHIFT - EFI_PAGE_SHIFT);
214 md[num_mds].attribute = EFI_MEMORY_WB;
215 num_mds++;
216 memmap_info->efi_memmap_size = num_mds * sizeof(md[0]);
217 munmap(memmap_info, page_size * memmap_info_num_pages);
218 assert(num_mds <=
219 (page_size * memmap_info_num_pages -
220 offsetof(typeof(*memmap_info), memdesc))/sizeof(*md));
222 /*
223 * kludge: we need to pass memmap_info page's pfn and other magic pages
224 * somehow.
225 * we use xen_ia64_boot_param::efi_memmap::{efi_memmap, efi_memmap_size}
226 * for this purpose
227 */
228 start_info = xc_map_foreign_range(dom->guest_xc, dom->guest_domid,
229 page_size,
230 PROT_READ | PROT_WRITE,
231 dom->start_info_pfn);
232 if (NULL == start_info)
233 return -1;
234 bp = (struct xen_ia64_boot_param*)(start_info + sizeof(start_info_t));
235 memset(bp, 0, sizeof(*bp));
236 XEN_IA64_MEMMAP_INFO_NUM_PAGES(bp) = memmap_info_num_pages;
237 XEN_IA64_MEMMAP_INFO_PFN(bp) = memmap_info_pfn;
238 munmap(start_info, page_size);
239 return 0;
240 }
242 int arch_setup_bootearly(struct xc_dom_image *dom)
243 {
244 DECLARE_DOMCTL;
245 int rc;
247 xc_dom_printf("%s: setup firmware for %s\n", __FUNCTION__, dom->guest_type);
249 if (dom->guest_type && strcmp(dom->guest_type,
250 "hvm-3.0-ia64-sioemu") == 0) {
251 memset(&domctl, 0, sizeof(domctl));
252 domctl.u.arch_setup.flags = XEN_DOMAINSETUP_sioemu_guest;
253 domctl.u.arch_setup.bp = 0;
254 domctl.u.arch_setup.maxmem = 0;
255 domctl.cmd = XEN_DOMCTL_arch_setup;
256 domctl.domain = dom->guest_domid;
257 rc = xc_domctl(dom->guest_xc, &domctl);
258 xc_dom_printf("%s: hvm-3.0-ia64-sioemu: %d\n", __FUNCTION__, rc);
259 return rc;
260 }
262 rc = ia64_setup_memmap(dom);
263 if (rc)
264 return rc;
266 memset(&domctl, 0, sizeof(domctl));
267 domctl.cmd = XEN_DOMCTL_arch_setup;
268 domctl.domain = dom->guest_domid;
269 domctl.u.arch_setup.flags = XEN_DOMAINSETUP_query;
270 rc = do_domctl(dom->guest_xc, &domctl);
271 if (rc)
272 return rc;
273 rc = xen_ia64_dom_fw_setup(dom, domctl.u.arch_setup.hypercall_imm,
274 (dom->start_info_pfn << PAGE_SHIFT) +
275 sizeof(start_info_t),
276 dom->total_pages << PAGE_SHIFT);
277 if (rc)
278 return rc;
280 memset(&domctl, 0, sizeof(domctl));
281 domctl.cmd = XEN_DOMCTL_arch_setup;
282 domctl.domain = dom->guest_domid;
283 domctl.u.arch_setup.flags = 0;
285 domctl.u.arch_setup.bp = (dom->start_info_pfn << PAGE_SHIFT)
286 + sizeof(start_info_t);
287 domctl.u.arch_setup.maxmem = dom->total_pages << PAGE_SHIFT;
288 domctl.u.arch_setup.vhpt_size_log2 = dom->vhpt_size_log2;
289 rc = do_domctl(dom->guest_xc, &domctl);
290 return rc;
291 }
293 int arch_setup_bootlate(struct xc_dom_image *dom)
294 {
295 unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
296 shared_info_t *shared_info;
298 /* setup shared_info page */
299 xc_dom_printf("%s: shared_info: mfn 0x%" PRIpfn "\n",
300 __FUNCTION__, dom->shared_info_mfn);
301 shared_info = xc_map_foreign_range(dom->guest_xc, dom->guest_domid,
302 page_size,
303 PROT_READ | PROT_WRITE,
304 dom->shared_info_mfn);
305 if ( shared_info == NULL )
306 return -1;
307 dom->arch_hooks->shared_info(dom, shared_info);
308 munmap(shared_info, page_size);
309 return 0;
310 }
312 /*
313 * Local variables:
314 * mode: C
315 * c-set-style: "BSD"
316 * c-basic-offset: 4
317 * tab-width: 4
318 * indent-tabs-mode: nil
319 * End:
320 */