Files
xen/tools/firmware/hvmloader/e820.c
T
Ian Campbell 443701ef0c Replace FSF street address with canonical URL
As recommended in http://www.gnu.org/licenses/gpl-howto.en.html.

This is the result of:
$ git grep -El Mass\|Temple\|Franklin | xargs ./fsf.pl

Where fsf.pl is:
    #!/usr/bin/perl -w -pi.bak -0777
    my $repl = 'If not, see <http://www.gnu.org/licenses/>.';
    my $br = qr/(?:\s*\n\s*(?:[\*\#]|\/\/|\.\\" )?\s*|\s+)/;

    my $inwt = qr/[Ii]f${br}not,${br}write${br}(?:to${br})?the${br}Free${br}Software${br}Foundation,(?:${br}Inc\.,)?/;

    my $mass = qr/675${br}Mass${br}Ave,?${br}Cambridge,?${br}MA${br}02139,?${br}USA,?\.?/;
    my $franklin = qr/51${br}Franklin${br}St(?:reet)?(?:,${br}| - )Fifth${br}Floor,?${br}Boston,?${br}MA,?${br}02110-1301,?${br}USA,?\.?/;
    my $temple = qr/59${br}Temple${br}Place(?:,${br}| - )Suite${br}330,?${br}Boston,?${br}MA,?${br}021110?-1307,?${br}USA,?\.?/;

    s|$inwt$br$mass|$repl|m;
    s|$inwt$br$franklin|$repl|m;
    s|$inwt$br$temple|$repl|m;

The only remaining mentions of these addresses are in COPYING files which I
haven't touched.

Some of the changed files are imports from elsewhere, however
filtering them out is tricky, I think it is tolerable to have these
files be modified here and then perhaps reverted on the next sync,
since it's only 1-2 lines and obvious what is going on.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
2015-07-29 11:14:07 +01:00

289 lines
8.3 KiB
C

/*
* HVM e820 support.
*
* Leendert van Doorn, leendert@watson.ibm.com
* Copyright (c) 2005, International Business Machines Corporation.
* Copyright (c) 2006, Keir Fraser, XenSource Inc.
* Copyright (c) 2011, Citrix 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, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "util.h"
struct e820map memory_map;
void memory_map_setup(void)
{
unsigned int nr_entries = E820MAX, i;
int rc;
uint64_t alloc_addr = RESERVED_MEMORY_DYNAMIC_START;
uint64_t alloc_size = RESERVED_MEMORY_DYNAMIC_END - alloc_addr;
rc = get_mem_mapping_layout(memory_map.map, &nr_entries);
if ( rc || !nr_entries )
{
printf("Get guest memory maps[%d] failed. (%d)\n", nr_entries, rc);
BUG();
}
memory_map.nr_map = nr_entries;
for ( i = 0; i < nr_entries; i++ )
{
if ( memory_map.map[i].type == E820_RESERVED &&
check_overlap(alloc_addr, alloc_size,
memory_map.map[i].addr, memory_map.map[i].size) )
{
printf("Fail to setup memory map due to conflict");
printf(" on dynamic reserved memory range.\n");
BUG();
}
}
}
/*
* Sometimes hvmloader may have relocated RAM so low_mem_pgend/high_mem_end
* would be changed over there. But memory_map[] just records the
* original low/high memory, so we need to sync these entries once
* hvmloader modifies low/high memory.
*/
void adjust_memory_map(void)
{
uint32_t low_mem_end = hvm_info->low_mem_pgend << PAGE_SHIFT;
uint64_t high_mem_end = (uint64_t)hvm_info->high_mem_pgend << PAGE_SHIFT;
unsigned int i;
for ( i = 0; i < memory_map.nr_map; i++ )
{
uint64_t map_start = memory_map.map[i].addr;
uint64_t map_size = memory_map.map[i].size;
uint64_t map_end = map_start + map_size;
/* If we need to adjust lowmem. */
if ( memory_map.map[i].type == E820_RAM &&
low_mem_end > map_start && low_mem_end < map_end )
{
memory_map.map[i].size = low_mem_end - map_start;
continue;
}
/* Modify the existing highmem region if it exists. */
if ( memory_map.map[i].type == E820_RAM &&
high_mem_end && map_start == ((uint64_t)1 << 32) )
{
if ( high_mem_end != map_end )
memory_map.map[i].size = high_mem_end - map_start;
high_mem_end = 0;
continue;
}
}
/* If there was no highmem region, just create one. */
if ( high_mem_end )
{
memory_map.map[i].addr = ((uint64_t)1 << 32);
memory_map.map[i].size =
((uint64_t)hvm_info->high_mem_pgend << PAGE_SHIFT) -
memory_map.map[i].addr;
memory_map.map[i].type = E820_RAM;
}
}
void dump_e820_table(struct e820entry *e820, unsigned int nr)
{
uint64_t last_end = 0, start, end;
int i;
printf("E820 table:\n");
for ( i = 0; i < nr; i++ )
{
start = e820[i].addr;
end = e820[i].addr + e820[i].size;
if ( start < last_end )
printf(" OVERLAP!!\n");
else if ( start > last_end )
printf(" HOLE: %08x:%08x - %08x:%08x\n",
(uint32_t)(last_end >> 32), (uint32_t)last_end,
(uint32_t)(start >> 32), (uint32_t)start);
printf(" [%02d]: %08x:%08x - %08x:%08x: ", i,
(uint32_t)(start >> 32), (uint32_t)start,
(uint32_t)(end >> 32), (uint32_t)end);
switch ( e820[i].type )
{
case E820_RAM:
printf("RAM\n");
break;
case E820_RESERVED:
printf("RESERVED\n");
break;
case E820_ACPI:
printf("ACPI\n");
break;
case E820_NVS:
printf("NVS\n");
break;
default:
printf("UNKNOWN (%08x)\n", e820[i].type);
break;
}
last_end = end;
}
}
/* Create an E820 table based on memory parameters provided in hvm_info. */
int build_e820_table(struct e820entry *e820,
unsigned int lowmem_reserved_base,
unsigned int bios_image_base)
{
unsigned int nr = 0, i, j;
uint32_t low_mem_end = hvm_info->low_mem_pgend << PAGE_SHIFT;
if ( !lowmem_reserved_base )
lowmem_reserved_base = 0xA0000;
/* Lowmem must be at least 512K to keep Windows happy) */
ASSERT ( lowmem_reserved_base > 512<<10 );
ASSERT ( bios_image_base < 0x100000 );
/*
* 0x0-lowmem_reserved_base: Ordinary RAM.
*/
e820[nr].addr = 0x00000;
e820[nr].size = lowmem_reserved_base;
e820[nr].type = E820_RAM;
nr++;
/* lowmem_reserved_base-0xA0000: reserved by BIOS implementation. */
if ( lowmem_reserved_base < 0xA0000 )
{
/* Reserved for internal use. */
e820[nr].addr = lowmem_reserved_base;
e820[nr].size = 0xA0000-lowmem_reserved_base;
e820[nr].type = E820_RESERVED;
nr++;
}
/*
* Following regions are standard regions of the PC memory map.
* They are not covered by e820 regions. OSes will not use as RAM.
* 0xA0000-0xC0000: VGA memory-mapped I/O. Not covered by E820.
* 0xC0000-0xE0000: 16-bit devices, expansion ROMs (inc. vgabios).
* TODO: free pages which turn out to be unused.
*/
/*
* BIOS region.
*/
e820[nr].addr = bios_image_base;
e820[nr].size = 0x100000-bios_image_base;
e820[nr].type = E820_RESERVED;
nr++;
/*
* Explicitly reserve space for special pages.
* This space starts at RESERVED_MEMBASE an extends to cover various
* fixed hardware mappings (e.g., LAPIC, IOAPIC, default SVGA framebuffer).
*
* If igd_opregion_pgbase we need to split the RESERVED region in two.
*/
if ( igd_opregion_pgbase )
{
uint32_t igd_opregion_base = igd_opregion_pgbase << PAGE_SHIFT;
e820[nr].addr = RESERVED_MEMBASE;
e820[nr].size = (uint32_t) igd_opregion_base - RESERVED_MEMBASE;
e820[nr].type = E820_RESERVED;
nr++;
e820[nr].addr = igd_opregion_base;
e820[nr].size = IGD_OPREGION_PAGES * PAGE_SIZE;
e820[nr].type = E820_NVS;
nr++;
e820[nr].addr = igd_opregion_base + IGD_OPREGION_PAGES * PAGE_SIZE;
e820[nr].size = (uint32_t)-e820[nr].addr;
e820[nr].type = E820_RESERVED;
nr++;
}
else
{
e820[nr].addr = RESERVED_MEMBASE;
e820[nr].size = (uint32_t)-e820[nr].addr;
e820[nr].type = E820_RESERVED;
nr++;
}
/* Low RAM goes here. Reserve space for special pages. */
BUG_ON(low_mem_end < (2u << 20));
/*
* Construct E820 table according to recorded memory map.
*
* The memory map created by toolstack may include,
*
* #1. Low memory region
*
* Low RAM starts at least from 1M to make sure all standard regions
* of the PC memory map, like BIOS, VGA memory-mapped I/O and vgabios,
* have enough space.
*
* #2. Reserved regions if they exist
*
* #3. High memory region if it exists
*
* Note we just have one low memory entry and one high mmeory entry if
* exists.
*/
for ( i = 0; i < memory_map.nr_map; i++ )
{
e820[nr] = memory_map.map[i];
nr++;
}
/* Finally we need to sort all e820 entries. */
for ( j = 0; j < nr - 1; j++ )
{
for ( i = j + 1; i < nr; i++ )
{
if ( e820[j].addr > e820[i].addr )
{
struct e820entry tmp = e820[j];
e820[j] = e820[i];
e820[i] = tmp;
}
}
}
return nr;
}
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/