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 // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 // this software and associated documentation files (the "Software"), to deal with
8 // the Software without restriction, including without limitation the rights to
9 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10 // of the Software, and to permit persons to whom the Software is furnished to do
11 // so, subject to the following condition:
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
24 #include <kern/libc.h>
25 #include <kern/pagealloc.h>
27 #include <arch/multiboot.h>
28 #include <arch/addrs.h>
29 #include <arch/paging.h>
34 u32 x64_boot_info_phys;
45 void make_mem_avail(uintptr_t page_start, uintptr_t page_end)
49 if (page_start < dma32zonestart) {
52 if (page_end <= dma32zonestart)
53 len = page_end - page_start;
55 len = dma32zonestart - page_start;
57 isadmazone.free(&pages[page_start], len);
58 page_start = dma32zonestart;
61 if (page_start < highzonestart && page_end > dma32zonestart) {
64 if (page_end <= highzonestart)
65 len = page_end - page_start;
67 len = highzonestart - page_start;
69 dma32zone.free(&pages[page_start], len);
70 page_start = highzonestart;
73 if (page_end > highzonestart)
74 dma32zone.free(&pages[page_start], page_end - highzonestart);
79 if (x64_boot_info_phys > max_ktext_map) {
80 printf("Cannot access boot info at %#.8x\n", x64_boot_info_phys);
84 boot_info = (BootInfo *)phys_to_ktext(x64_boot_info_phys);
87 if (!(boot_info->flags & (1 << BootInfo::flag_mmap))) {
88 // FIXME: use mem_lower and mem_upper in this case.
89 printf("MultiBoot info does not contain a memory map.\n");
93 printf("BIOS Memory Map:\n");
96 while (off < boot_info->mmap_length) {
97 u32 phys = boot_info->mmap_addr + off;
99 if (phys > max_ktext_map) {
100 printf("Cannot access BIOS memory map entry at %#.8x\n", phys);
104 MemMap *mmap = (MemMap *)phys_to_ktext(phys);
106 printf("0x%016llx - 0x%016llx, type %d\n",
107 mmap->base, mmap->base + mmap->len - 1, mmap->type);
109 off += mmap->size + 4;
111 if (mmap->type == MemMap::Available) {
112 size_t page_end = (mmap->base + mmap->len) / page_size;
114 if (page_end > mem_end)
122 while (off < boot_info->mmap_length) {
123 u32 phys = boot_info->mmap_addr + off;
124 MemMap *mmap = (MemMap *)phys_to_ktext(phys);
125 off += mmap->size + 4;
127 if (mmap->type == MemMap::Available) {
128 // Don't use any page that isn't fully in this entry.
130 size_t page_start = (mmap->base + page_size - 1) / page_size;
131 size_t page_end = (mmap->base + mmap->len) / page_size;
134 // Don't make available any pages that overlap the
135 // kernel text/data or bootmem allocations.
137 uintptr_t kernelendpage =
138 (kvirt_to_phys((void *)next_free_bootmem) + page_size - 1) /
141 // Don't overwrite page 1; the BIOS will need it for later calls in
142 // emulation, and at least the BIOS I'm testing on doesn't mark
147 if (page_start >= page_end)
150 if (page_start <= kernelendpage && page_end >= 512) {
151 if (page_start < 512)
152 make_mem_avail(page_start, 512);
154 if (page_end > kernelendpage)
155 make_mem_avail(kernelendpage + 1, page_end);
157 make_mem_avail(page_start, page_end);