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:
parent
29492bb71c
commit
3b0299dd65
1 changed files with 51 additions and 0 deletions
|
@ -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]);
|
||||||
|
|
Loading…
Reference in a new issue