1 // arch/x64/multiboot.cc -- Code to interpret multiboot data and initialize
2 // free memory regions based thereupon.
4 // This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
6 // This software is provided 'as-is', without any express or implied warranty.
7 // In no event will the authors or contributors be held liable for any damages
8 // arising from the use of this software.
10 // Permission is hereby granted to everyone, free of charge, to use, copy,
11 // modify, prepare derivative works of, publish, distribute, perform,
12 // sublicense, and/or sell copies of the Software, provided that the above
13 // copyright notice and disclaimer of warranty be included in all copies or
14 // substantial portions of this software.
16 #include <kern/libc.h>
17 #include <kern/pagealloc.h>
19 #include <arch/multiboot.h>
20 #include <arch/addrs.h>
21 #include <arch/paging.h>
26 u32 x64_boot_info_phys;
37 void make_mem_avail(uintptr_t page_start, uintptr_t page_end)
41 if (page_start < dma32zonestart) {
44 if (page_end <= dma32zonestart)
45 len = page_end - page_start;
47 len = dma32zonestart - page_start;
49 isadmazone.free(&pages[page_start], len);
50 page_start = dma32zonestart;
53 if (page_start < highzonestart && page_end > dma32zonestart) {
56 if (page_end <= highzonestart)
57 len = page_end - page_start;
59 len = highzonestart - page_start;
61 dma32zone.free(&pages[page_start], len);
62 page_start = highzonestart;
65 if (page_end > highzonestart)
66 dma32zone.free(&pages[page_start], page_end - highzonestart);
71 if (x64_boot_info_phys > max_ktext_map) {
72 printf("Cannot access boot info at %#.8x\n", x64_boot_info_phys);
76 boot_info = (BootInfo *)phys_to_ktext(x64_boot_info_phys);
79 if (!(boot_info->flags & (1 << BootInfo::flag_mmap))) {
80 // FIXME: use mem_lower and mem_upper in this case.
81 printf("MultiBoot info does not contain a memory map.\n");
85 printf("BIOS Memory Map:\n");
88 while (off < boot_info->mmap_length) {
89 u32 phys = boot_info->mmap_addr + off;
91 if (phys > max_ktext_map) {
92 printf("Cannot access BIOS memory map entry at %#.8x\n", phys);
96 MemMap *mmap = (MemMap *)phys_to_ktext(phys);
98 printf("0x%016llx - 0x%016llx, type %d\n",
99 mmap->base, mmap->base + mmap->len - 1, mmap->type);
101 off += mmap->size + 4;
103 if (mmap->type == MemMap::Available) {
104 size_t page_end = (mmap->base + mmap->len) / page_size;
106 if (page_end > mem_end)
114 while (off < boot_info->mmap_length) {
115 u32 phys = boot_info->mmap_addr + off;
116 MemMap *mmap = (MemMap *)phys_to_ktext(phys);
117 off += mmap->size + 4;
119 if (mmap->type == MemMap::Available) {
120 // Don't use any page that isn't fully in this entry.
122 size_t page_start = (mmap->base + page_size - 1) / page_size;
123 size_t page_end = (mmap->base + mmap->len) / page_size;
126 // Don't make available any pages that overlap the
127 // kernel text/data or bootmem allocations.
129 uintptr_t kernelendpage =
130 (kvirt_to_phys((void *)next_free_bootmem) + page_size - 1) /
133 // Don't overwrite page 1; the BIOS will need it for later calls in
134 // emulation, and at least the BIOS I'm testing on doesn't mark
139 if (page_start >= page_end)
142 if (page_start <= kernelendpage && page_end >= 512) {
143 if (page_start < 512)
144 make_mem_avail(page_start, 512);
146 if (page_end > kernelendpage)
147 make_mem_avail(kernelendpage + 1, page_end);
149 make_mem_avail(page_start, page_end);