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()
26 //printf("Kmem_alloc::base_init(): kip=%p\n", Kip::k());
27 unsigned long available_size = 0;
28 unsigned long requested_size;
30 Mem_region_map<64> map;
31 //Kip::k()->add_mem_region(Mem_desc(0xc7ed000, 0xfeecfff, Mem_desc::Reserved));
32 //Kip::k()->add_mem_region(Mem_desc(0xea00000, 0xfeecfff, Mem_desc::Reserved));
34 available_size = create_free_map(Kip::k(), &map);
36 requested_size = Koptions::o()->kmemsize << 10;
39 requested_size = available_size / 100 * Config::kernel_mem_per_cent;
40 if (requested_size > Config::kernel_mem_max)
41 requested_size = Config::kernel_mem_max;
44 if (requested_size > (0-Mem_layout::Physmem))
45 requested_size = 0-Mem_layout::Physmem; // maximum mappable memory
47 requested_size = (requested_size + Config::PAGE_SIZE - 1)
48 & ~(Config::PAGE_SIZE - 1);
50 //printf("Kmem_alloc: available_memory=%lu KB requested_size=%lu\n",
51 // available_size / 1024, requested_size / 1024);
53 //printf("Kmem_alloc:: available blocks:\n");
54 //for (unsigned i = 0; i < map.length(); ++i)
55 // printf(" %2u [%014lx; %014lx)\n", i, map[i].start, map[i].end+1);
57 unsigned long base = 0;
58 unsigned long sp_base = 0;
59 unsigned long end = map[map.length()-1].end;
60 unsigned last = map.length();
62 unsigned long size = requested_size;
63 for (i = last; i > 0 && size > 0; --i)
65 if (map[i-1].size() >= size)
66 { // next block is sufficient
67 base = map[i-1].end - size + 1;
68 sp_base = base & ~(Config::SUPERPAGE_SIZE-1);
69 if ((end - sp_base + 1) > (0-Mem_layout::Physmem))
72 { // already a single block, try to align
73 if (sp_base >= map[i-1].start)
76 end = sp_base + size -1;
82 { // too much virtual memory, try other blocks
84 size += map[last-1].size();
85 end = map[last-2].end;
87 ++i; // try same block again
95 size -= map[i-1].size();
101 //printf("Kmem_alloc: kernel memory from %014lx to %014lx\n", base, end+1);
102 //printf("Kmem_alloc: blocks %u-%u\n", i, last-1);
104 Kip::k()->add_mem_region(Mem_desc(base,
105 end <= map[i].end ? end : map[i].end, Mem_desc::Kernel_tmp));
107 for (; i < last; ++i)
108 Kip::k()->add_mem_region(Mem_desc(map[i].start, map[i].end, Mem_desc::Kernel_tmp));
110 Mem_layout::kphys_base(sp_base);
111 Mem_layout::pmem_size = (end + 1 - sp_base + Config::SUPERPAGE_SIZE - 1) & ~(Config::SUPERPAGE_SIZE-1);
116 Kmem_alloc::Kmem_alloc()
118 //printf("Kmem_alloc::Kmem_alloc()\n");
119 Mem_desc *md = Kip::k()->mem_descs();
120 Mem_desc const *const md_end = md + Kip::k()->num_mem_descs();
121 bool initialized = false;
123 for (; md < md_end; ++md)
125 if (md->is_virtual())
128 unsigned long s = md->start(), e = md->end();
130 // Speep out stupid descriptors (that have the end before the start)
133 md->type(Mem_desc::Undefined);
137 if (md->type() == Mem_desc::Kernel_tmp)
139 unsigned long s_v = Mem_layout::phys_to_pmem(s);
143 a->init(s_v & ~(Kmem_alloc::Alloc::Max_size - 1));
144 //printf("Kmem_alloc: allocator base = %014lx\n", s_v & ~(Kmem_alloc::Alloc::Max_size - 1));
146 //printf(" Kmem_alloc: block %014lx(%014lx) size=%lx\n", s_v, s, e - s + 1);
147 a->add_mem((void*)s_v, e - s + 1);
148 md->type(Mem_desc::Reserved);
149 _orig_free += e - s + 1;
152 //printf("Kmem_alloc: construction done\n");
155 //-----------------------------------------------------------------------------
156 IMPLEMENTATION [{ia32,ux,amd64}-debug]:
162 Kmem_alloc::debug_dump()
166 unsigned long free = a->avail();
167 printf("Used %ld%%, %ldKB out of %ldKB of Kmem\n",
168 (unsigned long) div32(100ULL * (orig_free() - free), orig_free()),
169 (orig_free() - free + 1023)/1024,
170 (orig_free() + 1023)/1024);
175 Kmem_alloc::orig_free()