*/
reloc_size = reloc_off;
printf("%d bytes of ROMBIOS high-memory extensions:\n", reloc_size);
- highbiosarea = (char *)(long)e820_malloc(reloc_size, 0);
+ highbiosarea = mem_alloc(reloc_size, 0);
BUG_ON(highbiosarea == NULL);
printf(" Relocating to 0x%x-0x%x ... ",
(uint32_t)&highbiosarea[0],
struct acpi_20_tcpa *tcpa;
static const uint16_t tis_signature[] = {0x0001, 0x0001, 0x0001};
uint16_t *tis_hdr;
+ void *lasa;
/* MADT. */
if ( (hvm_info->nr_vcpus > 1) || hvm_info->apic_mode )
tcpa->header.oem_revision = ACPI_OEM_REVISION;
tcpa->header.creator_id = ACPI_CREATOR_ID;
tcpa->header.creator_revision = ACPI_CREATOR_REVISION;
- tcpa->lasa = e820_malloc(ACPI_2_0_TCPA_LAML_SIZE, 0);
- if ( tcpa->lasa )
+ if ( (lasa = mem_alloc(ACPI_2_0_TCPA_LAML_SIZE, 0)) != NULL )
{
+ tcpa->lasa = virt_to_phys(lasa);
tcpa->laml = ACPI_2_0_TCPA_LAML_SIZE;
- memset((char *)(unsigned long)tcpa->lasa, 0, tcpa->laml);
+ memset(lasa, 0, tcpa->laml);
set_checksum(tcpa,
offsetof(struct acpi_header, checksum),
tcpa->header.length);
memset(buf, 0, high_sz);
/* Allocate data area and set up ACPI tables there. */
- buf = (uint8_t *)e820_malloc(high_sz, 0);
+ buf = mem_alloc(high_sz, 0);
__acpi_build_tables(buf, &low_sz, &high_sz);
printf(" - Lo data: %08lx-%08lx\n"
#define PCI_MEMBASE 0xf0000000
#define PCI_MEMSIZE 0x0c000000
+/* We reserve 16MB at the top of the 4GB memory hole. */
+#define RESERVED_MEMBASE 0xff000000
+#define RESERVED_MEMSIZE 0x01000000
+
#define ROMBIOS_SEG 0xF000
#define ROMBIOS_BEGIN 0x000F0000
#define ROMBIOS_SIZE 0x00010000
/* Replace possibly erroneous memory-size CMOS fields with correct values. */
static void cmos_write_memory_size(void)
{
- struct e820entry *map = E820;
- int i, nr = *E820_NR;
- uint32_t base_mem = 640, ext_mem = 0, alt_mem = 0;
+ uint32_t base_mem = 640, ext_mem, alt_mem;
- for ( i = 0; i < nr; i++ )
- if ( (map[i].addr >= 0x100000) && (map[i].type == E820_RAM) )
- break;
-
- if ( i != nr )
- {
- alt_mem = ext_mem = map[i].addr + map[i].size;
- ext_mem = (ext_mem > 0x0100000) ? (ext_mem - 0x0100000) >> 10 : 0;
- if ( ext_mem > 0xffff )
- ext_mem = 0xffff;
- alt_mem = (alt_mem > 0x1000000) ? (alt_mem - 0x1000000) >> 16 : 0;
- }
+ alt_mem = ext_mem = hvm_info->low_mem_pgend << PAGE_SHIFT;
+ ext_mem = (ext_mem > 0x0100000) ? (ext_mem - 0x0100000) >> 10 : 0;
+ if ( ext_mem > 0xffff )
+ ext_mem = 0xffff;
+ alt_mem = (alt_mem > 0x1000000) ? (alt_mem - 0x1000000) >> 16 : 0;
/* All BIOSes: conventional memory (CMOS *always* reports 640kB). */
cmos_outb(0x15, (uint8_t)(base_mem >> 0));
*/
static void init_vm86_tss(void)
{
- uint32_t tss;
+ void *tss;
struct xen_hvm_param p;
- tss = e820_malloc(128, 128);
- memset((char *)tss, 0, 128);
+ tss = mem_alloc(128, 128);
+ memset(tss, 0, 128);
p.domid = DOMID_SELF;
p.index = HVM_PARAM_VM86_TSS;
- p.value = tss;
+ p.value = virt_to_phys(tss);
hypercall_hvm_op(HVMOP_set_param, &p);
- printf("vm86 TSS at %08x\n", tss);
+ printf("vm86 TSS at %08lx\n", virt_to_phys(tss));
}
/* Create an E820 table based on memory parameters provided in hvm_info. */
e820[nr].type = E820_RAM;
nr++;
- if ( hvm_info->reserved_mem_pgstart )
- {
- /* Explicitly reserve space for special pages. */
- e820[nr].addr = hvm_info->reserved_mem_pgstart << PAGE_SHIFT;
- e820[nr].size = (uint32_t)-e820[nr].addr;
- e820[nr].type = E820_RESERVED;
- nr++;
- }
+ /* Explicitly reserve space for special pages. */
+ e820[nr].addr = RESERVED_MEMBASE;
+ e820[nr].size = (uint32_t)-e820[nr].addr;
+ e820[nr].type = E820_RESERVED;
+ nr++;
if ( hvm_info->high_mem_pgend )
{
printf("HVM Loader\n");
- build_e820_table();
-
init_hypercalls();
printf("CPU speed is %u MHz\n", get_cpu_mhz());
if ( virtual_vga != VGA_none )
{
- vga_ram = e820_malloc(8 << 20, 4096);
+ vga_ram = virt_to_phys(mem_alloc(8 << 20, 4096));
printf("VGA RAM at %08x\n", vga_ram);
}
if ( xen_pfiob && vga_ram )
outl(xen_pfiob + 4, vga_ram);
+ build_e820_table();
+
printf("Invoking ROMBIOS ...\n");
return 0;
}
static uint64_t
get_memsize(void)
{
- struct e820entry *map = E820;
- uint8_t num_entries = *E820_NR;
- uint64_t memsize = 0;
- int i;
+ uint64_t sz;
- /*
- * Walk through e820map, ignoring any entries that aren't marked
- * as usable or reserved.
- */
- for ( i = 0; i < num_entries; i++ )
- {
- if ( (map->type == E820_RAM) || (map->type == E820_RESERVED) )
- memsize += map->size;
- map++;
- }
+ sz = (uint64_t)hvm_info->low_mem_pgend << PAGE_SHIFT;
+ if ( hvm_info->high_mem_pgend )
+ sz += (hvm_info->high_mem_pgend << PAGE_SHIFT) - (1ull << 32);
/*
* Round up to the nearest MB. The user specifies domU pseudo-physical
* memory in megabytes, so not doing this could easily lead to reporting
* one less MB than the user specified.
*/
- return (memsize + (1 << 20) - 1) >> 20;
+ return (sz + (1ul << 20) - 1) >> 20;
}
int
*p = '\0';
}
-static void e820_collapse(void)
+void *mem_alloc(uint32_t size, uint32_t align)
{
- int i = 0;
- struct e820entry *ent = E820;
-
- while ( i < (*E820_NR-1) )
- {
- if ( (ent[i].type == ent[i+1].type) &&
- ((ent[i].addr + ent[i].size) == ent[i+1].addr) )
- {
- ent[i].size += ent[i+1].size;
- memcpy(&ent[i+1], &ent[i+2], (*E820_NR-i-2) * sizeof(*ent));
- (*E820_NR)--;
- }
- else
- {
- i++;
- }
- }
-}
-
-uint32_t e820_malloc(uint32_t size, uint32_t align)
-{
- uint32_t addr;
- int i;
- struct e820entry *ent = E820;
+ static uint32_t reserve = RESERVED_MEMBASE - 1;
+ static int over_allocated;
+ struct xen_memory_reservation xmr;
+ xen_pfn_t mfn;
+ uint32_t s, e;
/* Align to at least one kilobyte. */
if ( align < 1024 )
align = 1024;
- for ( i = *E820_NR - 1; i >= 0; i-- )
+ s = (reserve + align) & ~(align - 1);
+ e = s + size - 1;
+
+ BUG_ON((e < s) || (e >> PAGE_SHIFT) >= hvm_info->reserved_mem_pgstart);
+
+ while ( (reserve >> PAGE_SHIFT) != (e >> PAGE_SHIFT) )
{
- addr = (ent[i].addr + ent[i].size - size) & ~(align-1);
- if ( (ent[i].type != E820_RAM) || /* not ram? */
- (addr < ent[i].addr) || /* too small or starts above 4gb? */
- ((addr + size) < addr) ) /* ends above 4gb? */
+ reserve += PAGE_SIZE;
+
+ /* Try to allocate another page in the reserved area. */
+ xmr.domid = DOMID_SELF;
+ xmr.mem_flags = 0;
+ xmr.extent_order = 0;
+ xmr.nr_extents = 1;
+ set_xen_guest_handle(xmr.extent_start, &mfn);
+ mfn = reserve >> PAGE_SHIFT;
+ if ( !over_allocated &&
+ (hypercall_memory_op(XENMEM_populate_physmap, &xmr) == 1) )
continue;
- if ( addr != ent[i].addr )
+ /* If we fail, steal a page from the ordinary RAM map. */
+ over_allocated = 1;
+ if ( hvm_info->high_mem_pgend )
{
- memmove(&ent[i+1], &ent[i], (*E820_NR-i) * sizeof(*ent));
- (*E820_NR)++;
- ent[i].size = addr - ent[i].addr;
- ent[i+1].addr = addr;
- ent[i+1].size -= ent[i].size;
- i++;
+ mfn = --hvm_info->high_mem_pgend;
+ if ( mfn == (1ull << (32 - PAGE_SHIFT)) )
+ hvm_info->high_mem_pgend = 0;
}
+ else
+ {
+ mfn = --hvm_info->low_mem_pgend;
+ }
+ if ( hypercall_memory_op(XENMEM_decrease_reservation, &xmr) != 1 )
+ BUG();
- ent[i].type = E820_RESERVED;
-
- e820_collapse();
-
- return addr;
+ /* Now try the allocation again. Must not fail. */
+ mfn = reserve >> PAGE_SHIFT;
+ if ( hypercall_memory_op(XENMEM_populate_physmap, &xmr) != 1 )
+ BUG();
}
- return 0;
+ reserve = e;
+
+ return (void *)(unsigned long)s;
}
uint32_t ioapic_read(uint32_t reg)
int printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
int vprintf(const char *fmt, va_list ap);
-/* Reserve a RAM region in the e820 table. */
-uint32_t e820_malloc(uint32_t size, uint32_t align);
+/* Allocate memory in a reserved region below 4GB. */
+void *mem_alloc(uint32_t size, uint32_t align);
+#define virt_to_phys(v) ((unsigned long)(v))
/* Prepare the 32bit BIOS */
void highbios_setup(void);