bootloader: pass memory map to kernel

Previously, the bootloader would only provide a single memory range.
At least on VirtualBox, this memory range includes the ACPI tables,
which the kernel then happily overwrites when executing VM.  Much of
the infrastructure to use a fullblown memory map is already in place;
this patch adds the last (and strangely missing) bit of generating
the memory map in a multiboot-compatible way.

It should be noted that both the bootloader and the kernel actually
violate the multiboot specification by not packing the structure for
the memory ranges.  This is a NetBSD bug, but it is also a nonissue
for (our) practical purposes.  It can be fixed without changing the
code added in this patch.

Change-Id: I7c0a307a8a8133239531e1d2b80f376849f90247
This commit is contained in:
David van Moolenbroek 2014-12-22 23:15:02 +00:00
parent 29492bb71c
commit 3b0299dd65

View file

@ -666,6 +666,49 @@ userconf_init(void)
} }
} }
#if defined(PASS_MEMMAP) && defined(__minix)
/*
* Construct a memory map for the multiboot info structure, with memory ranges
* as reported by the BIOS. If successful, set the HAS_MMAP flag. Code copied
* largely from bootinfo_memmap.c.
*/
static void
memmap_init(struct multiboot_info * mbi)
{
multiboot_memory_map_t *mmap;
int buf[5], i, nranges;
nranges = 0;
i = 0;
do {
if (getmementry(&i, buf))
break;
nranges++;
} while (i);
if (nranges == 0)
return;
mbi->mmap_length = sizeof(multiboot_memory_map_t) * nranges;
mmap = alloc(mbi->mmap_length);
mbi->mmap_addr = vtophys(mmap);
i = 0;
while (nranges-- > 0) {
getmementry(&i, buf);
/* Stupid tricks to deal with alignment issues. */
memcpy(&mmap->mm_base_addr, buf, sizeof(buf));
mmap->mm_size = sizeof(*mmap) - sizeof(mmap->mm_size);
mmap++;
}
mbi->mi_flags |= MULTIBOOT_INFO_HAS_MMAP;
}
#endif /* PASS_MEMMAP && __minix */
int int
exec_multiboot(const char *file, char *args) exec_multiboot(const char *file, char *args)
{ {
@ -718,6 +761,14 @@ exec_multiboot(const char *file, char *args)
} }
} }
#if defined(PASS_MEMMAP) && defined(__minix)
/*
* The MINIX3 kernel needs a full memory map. Without it, it will do
* silly things such as overwriting the ACPI tables.
*/
memmap_init(mbi);
#endif /* PASS_MEMMAP && __minix */
#ifdef DEBUG #ifdef DEBUG
printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY], printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY],
marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]); marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]);