Index: root/xen-unstable.hg/tools/firmware/hvmloader/Makefile =================================================================== --- root.orig/xen-unstable.hg/tools/firmware/hvmloader/Makefile +++ root/xen-unstable.hg/tools/firmware/hvmloader/Makefile @@ -40,7 +40,7 @@ OBJCOPY = objcopy CFLAGS += $(DEFINES) -I. $(XENINC) -fno-builtin -O2 -msoft-float LDFLAGS = -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(LOADADDR) -SRCS = hvmloader.c acpi_madt.c mp_tables.c util.c smbios.c acpi_utils.c +SRCS = hvmloader.c acpi_madt.c mp_tables.c util.c smbios.c acpi_utils.c e820.c OBJS = $(patsubst %.c,%.o,$(SRCS)) .PHONY: all Index: root/xen-unstable.hg/tools/firmware/hvmloader/e820.c =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/firmware/hvmloader/e820.c @@ -0,0 +1,187 @@ +/* + * e820.c: Functions for handling the e820 table. + * + * Leendert van Doorn, leendert@xxxxxxxxxxxxxx + * Stefan Berger, stefanb@xxxxxxxxxx + * Copyright (c) 2005, International Business Machines Corporation. + * + * 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 "acpi/acpi2_0.h" +#include +#include "util.h" +#include "hypercall.h" +#include "e820.h" +#include +#include + +void +print_e820_map(struct e820entry *map, int entries) +{ + struct e820entry *m; + + if (entries > 32) + entries = 32; + + for (m = map; m < &map[entries]; m++) { + printf("%08lx%08lx - %08lx%08lx ", + (unsigned long) (m->addr >> 32), + (unsigned long) (m->addr), + (unsigned long) ((m->addr+m->size) >> 32), + (unsigned long) ((m->addr+m->size))); + + switch (m->type) { + case E820_RAM: + printf("(RAM)\n"); break; + case E820_RESERVED: + printf("(Reserved)\n"); break; + case E820_ACPI: + printf("(ACPI Data)\n"); break; + case E820_NVS: + printf("(ACPI NVS)\n"); break; + default: + printf("(Type %ld)\n", m->type); break; + } + } +} + +static int e820_init(void) +{ + *E820_MAP_NR = 0; + return 0; +} + +static int e820_add_ram(unsigned char *start, uint64_t addr, uint64_t size) +{ + struct e820entry *e820entry = (struct e820entry *)start; + uint64_t end = addr + size; + int c; + + for (c = 0; c < *E820_MAP_NR; c++) { + /* + check for overlap of new memory region with an existing one + */ + if ((addr >= e820entry[c].addr && + addr < e820entry[c].addr + e820entry[c].size) || + (end >= e820entry[c].addr && + end < e820entry[c].addr + e820entry[c].size)) { + return -1; + } + } + + for (c = 0; c < *E820_MAP_NR; c++) { + if (e820entry[c].addr > end) { + memcpy(&e820entry[c+1], + &e820entry[c], + (*E820_MAP_NR + 1 - c) * + sizeof(struct e820entry)); + break; + } + } + + e820entry[c].addr = addr; + e820entry[c].size = size; + e820entry[c].type = E820_RAM; + + (*E820_MAP_NR)++; + return 0; +} + +int e820_reserve_range(unsigned char *e820, uint64_t start, uint64_t size, + uint32_t type) +{ + struct e820entry *e820entry = (struct e820entry *)e820; + int c = 0; + while (c < *E820_MAP_NR) { + if (e820entry[c].type == E820_RAM && + e820entry[c].addr <= start && + e820entry[c].addr + e820entry[c].size >= start + size) { + int sz = e820entry[c].size - size; + /* beginnings the same ? */ + if (e820entry[c].addr < start) { + (*E820_MAP_NR)++; + memcpy(&e820entry[c+1], + &e820entry[c], + (*E820_MAP_NR - c) * + sizeof(struct e820entry)); + e820entry[c].size = start - + e820entry[c].addr; + sz -= e820entry[c].size; + c++; + } + /* are the ends the same? */ + if (start + size < + e820entry[c].addr + e820entry[c].size) { + /* not the same */ + (*E820_MAP_NR)++; + memcpy(&e820entry[c+1], + &e820entry[c], + (*E820_MAP_NR - c) * + sizeof(struct e820entry)); + e820entry[c+1].addr = start + size; + e820entry[c+1].size = sz; + } + e820entry[c].addr = start; + e820entry[c].size = size; + e820entry[c].type = type; + break; + } + c++; + } + return 0; +} + + +int build_e820_map(unsigned char *start) +{ + unsigned long long mem_size, extra_mem_size = 0; + int rc; + domid_t domid; + + printf("Building e820 map at %x.\n",start); + domid = DOMID_SELF; + rc = hypercall_memory_op(XENMEM_current_reservation, &domid); + if (rc > 0) { + mem_size = rc * PAGE_SIZE; + printf("Got memory: 0x%x bytes\n",mem_size); + + /* + * Physical address space from HVM_BELOW_4G_RAM_END to 4G is reserved + * for PCI devices MMIO. So if HVM has more than HVM_BELOW_4G_RAM_END + * RAM, memory beyond HVM_BELOW_4G_RAM_END will go to 4G above. + */ + if ( mem_size > HVM_BELOW_4G_RAM_END ) { + extra_mem_size = mem_size - HVM_BELOW_4G_RAM_END; + mem_size = HVM_BELOW_4G_RAM_END; + } + + e820_init(); + e820_add_ram(start, 0x0, mem_size - PAGE_SIZE * 3); + + if ( extra_mem_size ) + e820_add_ram(start, (1ULL << 32), extra_mem_size); + + /* ??? */ + e820_reserve_range(start, 0x9F000, 0x1000 , E820_RESERVED); + /* ACPI data */ + e820_reserve_range(start, ACPI_PHYSICAL_ADDRESS, ACPI_TABLE_SIZE, + E820_ACPI); + /* BIOS */ + e820_reserve_range(start, 0xF0000, 0x10000, E820_RESERVED); + + rc = 0; + } + return rc; +} Index: root/xen-unstable.hg/tools/firmware/hvmloader/util.h =================================================================== --- root.orig/xen-unstable.hg/tools/firmware/hvmloader/util.h +++ root/xen-unstable.hg/tools/firmware/hvmloader/util.h @@ -37,5 +37,8 @@ void uuid_to_string(char *dest, uint8_t /* Debug output */ void puts(const char *s); +int printf(const char *fmt, ...); + + #endif /* __HVMLOADER_UTIL_H__ */ Index: root/xen-unstable.hg/tools/firmware/hvmloader/e820.h =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/firmware/hvmloader/e820.h @@ -0,0 +1,12 @@ +#ifndef E820_H +#define E820_H + +#include "acpi/acpi2_0.h" +#include +#define E820_MAP_NR ((unsigned char *)E820_MAP_PAGE + E820_MAP_NR_OFFSET) +#define E820_MAP ((struct e820entry *)(E820_MAP_PAGE + E820_MAP_OFFSET)) + +void print_e820_map(struct e820entry *map, int entries); +int build_e820_map(unsigned char *start); + +#endif Index: root/xen-unstable.hg/tools/firmware/hvmloader/util.c =================================================================== --- root.orig/xen-unstable.hg/tools/firmware/hvmloader/util.c +++ root/xen-unstable.hg/tools/firmware/hvmloader/util.c @@ -21,6 +21,12 @@ #include "acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */ #include "util.h" #include +#include + +static void putchar(int ch); +static void _doprint(void (*put)(int), char const *fmt, va_list ap); +static char *printnum(char *p, unsigned long num, int base); + void outw(uint16_t addr, uint16_t val) { @@ -229,3 +235,112 @@ uuid_to_string(char *dest, uint8_t *uuid } *p = 0; } + + +/* + * Lightweight printf that doesn't drag in everything under the sun. + */ +int +printf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _doprint(putchar, fmt, ap); + va_end(ap); + return 0; /* for gcc compat */ +} + +int +vprintf(const char *fmt, va_list ap) +{ + _doprint(putchar, fmt, ap); + return 0; /* for gcc compat */ +} + +static void +putchar(int ch) +{ + outb(0xE9, ch); +} + +#define isdigit(c) ((c) >= '0' && (c) <= '9') + + +/* + * A stripped down version of doprint, + * but still powerful enough for most tasks. + */ +static void +_doprint(void (*put)(int), char const *fmt, va_list ap) +{ + register char *str, c; + int lflag, zflag, nflag; + char buffer[17]; + unsigned value; + int i, slen, pad; + + for ( ; *fmt != '\0'; fmt++) { + pad = zflag = nflag = lflag = 0; + if (*fmt == '%') { + c = *++fmt; + if (c == '-' || isdigit(c)) { + if (c == '-') { + nflag = 1; + c = *++fmt; + } + zflag = c == '0'; + for (pad = 0; isdigit(c); c = *++fmt) + pad = (pad * 10) + c - '0'; + } + if (c == 'l') { /* long extension */ + lflag = 1; + c = *++fmt; + } + if (c == 'd' || c == 'u' || c == 'o' || c == 'x') { + if (lflag) + value = va_arg(ap, unsigned); + else + value = (unsigned) va_arg(ap, unsigned int); + str = buffer; + printnum(str, value, + c == 'o' ? 8 : (c == 'x' ? 16 : 10)); + goto printn; + } else if (c == 'O' || c == 'D' || c == 'X') { + value = va_arg(ap, unsigned); + str = buffer; + printnum(str, value, + c == 'O' ? 8 : (c == 'X' ? 16 : 10)); + printn: + slen = strlen(str); + for (i = pad - slen; i > 0; i--) + put(zflag ? '0' : ' '); + while (*str) put(*str++); + } else if (c == 's') { + str = va_arg(ap, char *); + slen = strlen(str); + if (nflag == 0) + for (i = pad - slen; i > 0; i--) put(' '); + while (*str) put(*str++); + if (nflag) + for (i = pad - slen; i > 0; i--) put(' '); + } else if (c == 'c') + put(va_arg(ap, int)); + else + put(*fmt); + } else + put(*fmt); + } +} + +static char * +printnum(char *p, unsigned long num, int base) +{ + unsigned long n; + + if ((n = num/base) > 0) + p = printnum(p, n, base); + *p++ = "0123456789ABCDEF"[(int)(num % base)]; + *p = '\0'; + return p; +} Index: root/xen-unstable.hg/tools/firmware/hvmloader/hvmloader.c =================================================================== --- root.orig/xen-unstable.hg/tools/firmware/hvmloader/hvmloader.c +++ root/xen-unstable.hg/tools/firmware/hvmloader/hvmloader.c @@ -27,6 +27,7 @@ #include "util.h" #include "acpi_utils.h" #include "smbios.h" +#include "e820.h" #include #include @@ -175,6 +176,11 @@ main(void) puts("Loading ROMBIOS ...\n"); memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios)); + /* print old map built by libxc */ + print_e820_map(E820_MAP, *E820_MAP_NR); + /* build e820 map (overwrite libxc-created one) */ + build_e820_map((unsigned char *)E820_MAP); + create_mp_tables(); if (cirrus_check()) {