ia64/xen-unstable

view tools/firmware/hvmloader/32bitbios_support.c @ 18394:dade7f0bdc8d

hvm: Use main memory for video memory.

When creating an HVM domain, if e.g. another domain is created before
qemu allocates video memory, the extra 8MB memory ballooning is not
available any more, because it got consumed by the other domain.

This fixes it by taking video memory from the main memory:

- make hvmloader use e820_malloc to reserve some of the main memory
and notify ioemu of its address through the Xen platform PCI card.
- add XENMAPSPACE_mfn to the xen_add_to_physmap memory op, to allow
ioemu to move the MFNs between the original position and the PCI
mapping, when LFB acceleration is disabled/enabled
- add a remove_from_physmap memory op, to allow ioemu to unmap it
completely for the case of old guests with acceleration disabled.
- add xc_domain_memory_translate_gpfn_list to libxc to allow ioemu to
get the MFNs of the video memory.
- have xend save the PCI memory space instead of ioemu: if a memory
page is there, the guest can access it like usual memory, so xend
can safely be responsible to save it. The extra benefit is that
live migration will apply the logdirty optimization there too.
- handle old saved images, populating the video memory from ioemu if
really needed.

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Aug 27 14:53:39 2008 +0100 (2008-08-27)
parents c7c67a1a7077
children 67ffce500feb
line source
1 /*
2 * 32bitbios_support.c - relocation of 32bit BIOS implementation
3 *
4 * Stefan Berger, stefanb@us.ibm.com
5 * Copyright (c) 2006, International Business Machines Corporation.
6 *
7 * Keir Fraser, keir@xensource.com
8 * Copyright (c) 2007, XenSource Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms and conditions of the GNU General Public License,
12 * version 2, as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21 * Place - Suite 330, Boston, MA 02111-1307 USA.
22 */
24 #include <inttypes.h>
25 #include <elf.h>
26 #ifdef __sun__
27 #include <sys/machelf.h>
28 #endif
30 #include "util.h"
31 #include "config.h"
33 #include "../rombios/32bit/32bitbios_flat.h"
35 static void relocate_32bitbios(char *elfarray, uint32_t elfarraysize)
36 {
37 Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfarray;
38 Elf32_Shdr *shdr = (Elf32_Shdr *)&elfarray[ehdr->e_shoff];
39 char *secstrings = &elfarray[shdr[ehdr->e_shstrndx].sh_offset];
40 char *jump_table;
41 uint32_t reloc_off, reloc_size;
42 char *highbiosarea;
43 int i, jump_sec_idx = 0;
45 /*
46 * Step 1. General elf cleanup, and compute total relocation size.
47 */
48 reloc_off = 0;
49 for ( i = 0; i < ehdr->e_shnum; i++ )
50 {
51 /* By default all section data points into elf image data array. */
52 shdr[i].sh_addr = (Elf32_Addr)&elfarray[shdr[i].sh_offset];
54 if ( !strcmp(".biosjumptable", secstrings + shdr[i].sh_name) )
55 {
56 /* We do not relocate the BIOS jump table to high memory. */
57 shdr[i].sh_flags &= ~SHF_ALLOC;
58 jump_sec_idx = i;
59 }
61 /* Fix up a corner case of address alignment. */
62 if ( shdr[i].sh_addralign == 0 )
63 shdr[i].sh_addralign = 1;
65 /* Any section which contains run-time data must be relocated. */
66 if ( shdr[i].sh_flags & SHF_ALLOC )
67 {
68 uint32_t mask = shdr[i].sh_addralign - 1;
69 reloc_off = (reloc_off + mask) & ~mask;
70 reloc_off += shdr[i].sh_size;
71 }
72 }
74 /*
75 * Step 2. Now we know the relocation size, allocate a chunk of high mem.
76 */
77 reloc_size = reloc_off;
78 printf("%d bytes of ROMBIOS high-memory extensions:\n", reloc_size);
79 highbiosarea = (char *)(long)e820_malloc(reloc_size, 0);
80 BUG_ON(highbiosarea == NULL);
81 printf(" Relocating to 0x%x-0x%x ... ",
82 (uint32_t)&highbiosarea[0],
83 (uint32_t)&highbiosarea[reloc_size]);
85 /*
86 * Step 3. Copy run-time data into the newly-allocated high-memory chunk.
87 */
88 reloc_off = 0;
89 for ( i = 0; i < ehdr->e_shnum; i++ )
90 {
91 uint32_t mask = shdr[i].sh_addralign - 1;
93 /* Nothing to do for non-run-time sections. */
94 if ( !(shdr[i].sh_flags & SHF_ALLOC) )
95 continue;
97 /* Copy from old location. */
98 reloc_off = (reloc_off + mask) & ~mask;
99 if ( shdr[i].sh_type == SHT_NOBITS )
100 memset(&highbiosarea[reloc_off], 0, shdr[i].sh_size);
101 else
102 memcpy(&highbiosarea[reloc_off], (void *)shdr[i].sh_addr,
103 shdr[i].sh_size);
105 /* Update address to new location. */
106 shdr[i].sh_addr = (Elf32_Addr)&highbiosarea[reloc_off];
107 reloc_off += shdr[i].sh_size;
108 }
109 BUG_ON(reloc_off != reloc_size);
111 /*
112 * Step 4. Perform relocations in high memory.
113 */
114 for ( i = 0; i < ehdr->e_shnum; i++ )
115 {
116 Elf32_Sym *syms, *sym;
117 Elf32_Rel *rels;
118 char *code;
119 uint32_t *loc, fix;
120 int j;
122 if ( shdr[i].sh_type == SHT_RELA )
123 printf("Unsupported section type SHT_RELA\n");
125 if ( shdr[i].sh_type != SHT_REL )
126 continue;
128 syms = (Elf32_Sym *)shdr[shdr[i].sh_link].sh_addr;
129 rels = (Elf32_Rel *)shdr[i].sh_addr;
130 code = (char *)shdr[shdr[i].sh_info].sh_addr;
132 for ( j = 0; j < shdr[i].sh_size / sizeof(Elf32_Rel); j++ )
133 {
134 sym = &syms[ELF32_R_SYM(rels[j].r_info)];
135 loc = (uint32_t *)&code[rels[j].r_offset];
136 fix = shdr[sym->st_shndx].sh_addr + sym->st_value;
138 switch ( ELF32_R_TYPE(rels[j].r_info) )
139 {
140 case R_386_PC32:
141 *loc += fix - (uint32_t)loc;
142 break;
144 case R_386_32:
145 *loc += fix;
146 break;
147 }
148 }
149 }
151 /* Step 5. Find the ROMBIOS jump-table stub and copy in the real table. */
152 for ( jump_table = (char *)ROMBIOS_BEGIN;
153 jump_table != (char *)ROMBIOS_END;
154 jump_table++ )
155 if ( !strncmp(jump_table, "___JMPT", 7) )
156 break;
157 BUG_ON(jump_table == NULL);
158 BUG_ON(jump_sec_idx == 0);
159 memcpy(jump_table, (char *)shdr[jump_sec_idx].sh_addr,
160 shdr[jump_sec_idx].sh_size);
162 printf("done\n");
163 }
165 void highbios_setup(void)
166 {
167 relocate_32bitbios((char *)highbios_array, sizeof(highbios_array));
168 }