Files
xen/tools/firmware/hvmloader/32bitbios_support.c
T
Keir Fraser d818f3cb7c 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>
2008-08-27 14:53:39 +01:00

169 lines
5.2 KiB
C

/*
* 32bitbios_support.c - relocation of 32bit BIOS implementation
*
* Stefan Berger, stefanb@us.ibm.com
* Copyright (c) 2006, International Business Machines Corporation.
*
* Keir Fraser, keir@xensource.com
* Copyright (c) 2007, XenSource Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
#include <inttypes.h>
#include <elf.h>
#ifdef __sun__
#include <sys/machelf.h>
#endif
#include "util.h"
#include "config.h"
#include "../rombios/32bit/32bitbios_flat.h"
static void relocate_32bitbios(char *elfarray, uint32_t elfarraysize)
{
Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfarray;
Elf32_Shdr *shdr = (Elf32_Shdr *)&elfarray[ehdr->e_shoff];
char *secstrings = &elfarray[shdr[ehdr->e_shstrndx].sh_offset];
char *jump_table;
uint32_t reloc_off, reloc_size;
char *highbiosarea;
int i, jump_sec_idx = 0;
/*
* Step 1. General elf cleanup, and compute total relocation size.
*/
reloc_off = 0;
for ( i = 0; i < ehdr->e_shnum; i++ )
{
/* By default all section data points into elf image data array. */
shdr[i].sh_addr = (Elf32_Addr)&elfarray[shdr[i].sh_offset];
if ( !strcmp(".biosjumptable", secstrings + shdr[i].sh_name) )
{
/* We do not relocate the BIOS jump table to high memory. */
shdr[i].sh_flags &= ~SHF_ALLOC;
jump_sec_idx = i;
}
/* Fix up a corner case of address alignment. */
if ( shdr[i].sh_addralign == 0 )
shdr[i].sh_addralign = 1;
/* Any section which contains run-time data must be relocated. */
if ( shdr[i].sh_flags & SHF_ALLOC )
{
uint32_t mask = shdr[i].sh_addralign - 1;
reloc_off = (reloc_off + mask) & ~mask;
reloc_off += shdr[i].sh_size;
}
}
/*
* Step 2. Now we know the relocation size, allocate a chunk of high mem.
*/
reloc_size = reloc_off;
printf("%d bytes of ROMBIOS high-memory extensions:\n", reloc_size);
highbiosarea = (char *)(long)e820_malloc(reloc_size, 0);
BUG_ON(highbiosarea == NULL);
printf(" Relocating to 0x%x-0x%x ... ",
(uint32_t)&highbiosarea[0],
(uint32_t)&highbiosarea[reloc_size]);
/*
* Step 3. Copy run-time data into the newly-allocated high-memory chunk.
*/
reloc_off = 0;
for ( i = 0; i < ehdr->e_shnum; i++ )
{
uint32_t mask = shdr[i].sh_addralign - 1;
/* Nothing to do for non-run-time sections. */
if ( !(shdr[i].sh_flags & SHF_ALLOC) )
continue;
/* Copy from old location. */
reloc_off = (reloc_off + mask) & ~mask;
if ( shdr[i].sh_type == SHT_NOBITS )
memset(&highbiosarea[reloc_off], 0, shdr[i].sh_size);
else
memcpy(&highbiosarea[reloc_off], (void *)shdr[i].sh_addr,
shdr[i].sh_size);
/* Update address to new location. */
shdr[i].sh_addr = (Elf32_Addr)&highbiosarea[reloc_off];
reloc_off += shdr[i].sh_size;
}
BUG_ON(reloc_off != reloc_size);
/*
* Step 4. Perform relocations in high memory.
*/
for ( i = 0; i < ehdr->e_shnum; i++ )
{
Elf32_Sym *syms, *sym;
Elf32_Rel *rels;
char *code;
uint32_t *loc, fix;
int j;
if ( shdr[i].sh_type == SHT_RELA )
printf("Unsupported section type SHT_RELA\n");
if ( shdr[i].sh_type != SHT_REL )
continue;
syms = (Elf32_Sym *)shdr[shdr[i].sh_link].sh_addr;
rels = (Elf32_Rel *)shdr[i].sh_addr;
code = (char *)shdr[shdr[i].sh_info].sh_addr;
for ( j = 0; j < shdr[i].sh_size / sizeof(Elf32_Rel); j++ )
{
sym = &syms[ELF32_R_SYM(rels[j].r_info)];
loc = (uint32_t *)&code[rels[j].r_offset];
fix = shdr[sym->st_shndx].sh_addr + sym->st_value;
switch ( ELF32_R_TYPE(rels[j].r_info) )
{
case R_386_PC32:
*loc += fix - (uint32_t)loc;
break;
case R_386_32:
*loc += fix;
break;
}
}
}
/* Step 5. Find the ROMBIOS jump-table stub and copy in the real table. */
for ( jump_table = (char *)ROMBIOS_BEGIN;
jump_table != (char *)ROMBIOS_END;
jump_table++ )
if ( !strncmp(jump_table, "___JMPT", 7) )
break;
BUG_ON(jump_table == NULL);
BUG_ON(jump_sec_idx == 0);
memcpy(jump_table, (char *)shdr[jump_sec_idx].sh_addr,
shdr[jump_sec_idx].sh_size);
printf("done\n");
}
void highbios_setup(void)
{
relocate_32bitbios((char *)highbios_array, sizeof(highbios_array));
}