1 // base_init() puts those Mem_region_map's on the stack which is slightly
2 // larger than our warning limit, it's init code only, so it's ok
3 #pragma GCC diagnostic ignored "-Wframe-larger-than="
5 IMPLEMENTATION [ia32,ux,amd64]:
11 #include "mem_region.h"
17 Kmem_alloc::to_phys(void *v)
19 return Mem_layout::pmem_to_phys(v);
22 PUBLIC static FIASCO_INIT
24 Kmem_alloc::base_init()
27 printf("Kmem_alloc::base_init(): kip=%p\n", Kip::k());
28 unsigned long available_size = 0;
29 unsigned long requested_size;
31 Mem_region_map<64> map;
33 available_size = create_free_map(Kip::k(), &map);
35 requested_size = Koptions::o()->kmemsize << 10;
38 requested_size = available_size / 100 * Config::kernel_mem_per_cent;
39 if (requested_size > Config::kernel_mem_max)
40 requested_size = Config::kernel_mem_max;
43 if (requested_size > (0 - Mem_layout::Physmem))
44 requested_size = 0 - Mem_layout::Physmem; // maximum mappable memory
46 requested_size = (requested_size + Config::PAGE_SIZE - 1)
47 & ~(Config::PAGE_SIZE - 1);
51 printf("Kmem_alloc: available_memory=%lu KB requested_size=%lu\n",
52 available_size / 1024, requested_size / 1024);
54 printf("Kmem_alloc:: available blocks:\n");
55 for (unsigned i = 0; i < map.length(); ++i)
56 printf(" %2u [%014lx; %014lx)\n", i, map[i].start, map[i].end + 1);
59 unsigned long base = 0;
60 unsigned long sp_base = 0;
61 unsigned long end = map[map.length() - 1].end;
62 unsigned last = map.length();
64 unsigned long size = requested_size;
66 for (i = last; i > 0 && size > 0; --i)
68 if (map[i - 1].size() >= size)
69 { // next block is sufficient
70 base = map[i - 1].end - size + 1;
71 sp_base = base & ~(Config::SUPERPAGE_SIZE - 1);
72 if ((end - sp_base + 1) > (0 - Mem_layout::Physmem))
75 { // already a single block, try to align
76 if (sp_base >= map[i - 1].start)
79 end = sp_base + size - 1;
85 { // too much virtual memory, try other blocks
87 size += map[last - 1].size();
88 end = map[last - 2].end;
90 ++i; // try same block again
98 size -= map[i - 1].size();
106 printf("Kmem_alloc: kernel memory from %014lx to %014lx\n", base, end + 1);
107 printf("Kmem_alloc: blocks %u-%u\n", i, last - 1);
110 Kip::k()->add_mem_region(Mem_desc(base, end <= map[i].end ? end : map[i].end,
111 Mem_desc::Kernel_tmp));
113 for (; i < last; ++i)
114 Kip::k()->add_mem_region(Mem_desc(map[i].start, map[i].end,
115 Mem_desc::Kernel_tmp));
117 Mem_layout::kphys_base(sp_base);
118 Mem_layout::pmem_size = (end + 1 - sp_base + Config::SUPERPAGE_SIZE - 1)
119 & ~(Config::SUPERPAGE_SIZE - 1);
120 assert(Mem_layout::pmem_size <= Config::kernel_mem_max);
126 Kmem_alloc::Kmem_alloc()
129 printf("Kmem_alloc::Kmem_alloc()\n");
130 bool initialized = false;
132 for (auto &md: Kip::k()->mem_descs_a())
137 unsigned long s = md.start(), e = md.end();
139 // Sweep out stupid descriptors (that have the end before the start)
142 md.type(Mem_desc::Undefined);
146 if (md.type() == Mem_desc::Kernel_tmp)
148 unsigned long s_v = Mem_layout::phys_to_pmem(s);
152 a->init(s_v & ~(Kmem_alloc::Alloc::Max_size - 1));
154 printf("Kmem_alloc: allocator base = %014lx\n",
155 s_v & ~(Kmem_alloc::Alloc::Max_size - 1));
158 printf(" Kmem_alloc: block %014lx(%014lx) size=%lx\n",
160 a->add_mem((void *)s_v, e - s + 1);
161 md.type(Mem_desc::Reserved);
162 _orig_free += e - s + 1;
166 printf("Kmem_alloc: construction done\n");
169 //-----------------------------------------------------------------------------
170 IMPLEMENTATION [{ia32,ux,amd64}-debug]:
176 Kmem_alloc::debug_dump()
180 unsigned long free = a->avail();
181 printf("Used %lu%%, %luKB out of %luKB of Kmem\n",
182 (unsigned long)div32(100ULL * (orig_free() - free), orig_free()),
183 (orig_free() - free + 1023) / 1024,
184 (orig_free() + 1023) / 1024);
189 Kmem_alloc::orig_free()