unsigned long bootmem_max_pfn();
unsigned long bootmem_page_state(unsigned long pfn);
-#define bootmem_alloc_pages(n) alloc_bootmem((n)*PAGE_SIZE, PAGE_SIZE)
-
kmem_cache_t *kmem_cache_create(const char *name, size_t size, size_t align);
void *kmem_cache_alloc(kmem_cache_t *cache, gfp_t gfpflags);
bootmem_data.max_pfn = max_support_pfn;
printk("memory > 1G, only support to 1G.\n");
}
+
printk("pfn_min: %d pfn_max: %d\n", bootmem_data.min_pfn, bootmem_data.max_pfn);
+
+ bootmem_data.last_hit_pfn = bootmem_data.min_pfn;
}
void register_bootmem_pages() {
}
void reserve_kernel_pages() {
- // reserve_bootmem(PFN_DW(va2pa(&kernel_begin)), PFN_UP(va2pa(&kernel_end)));
- reserve_bootmem(0, PFN_UP(va2pa(&kernel_end)));
+ reserve_bootmem(PFN_DW(va2pa(&kernel_begin)), PFN_UP(va2pa(&kernel_end)));
+ // reserve_bootmem(0, PFN_UP(va2pa(&kernel_end)));
}
void reserve_bootmem_pages() {
reserve_kernel_pages();
reserve_bootmem_pages();
+
+ // 强制保留最开始的一页
+ // 免得alloc的时候分不清是失败,还是分配的第0页
+ reserve_bootmem(0, 1);
}
void init_bootmem() {
#endif
}
+// 由于只有在构建buddy system的时候才会用到
+// 所以这里就简单实现
+void *alloc_from_bootmem(unsigned long size, char *title) {
+ void *region = NULL;
+ unsigned long pfn_cnt = PFN_UP(size);
+ printk("%s alloc bootmem size: %x pfn: %d\n", title, size, pfn_cnt);
+
+ bootmem_data_t *pbd = &bootmem_data;
+
+ // 从该处开始查找空闲区间
+ unsigned long search_bgn_pfn = pbd->min_pfn;
+
+find_next_block:
+ // 先找到第一个空闲的pfn
+ unsigned long free_pfn = pbd->max_pfn;
+ for (unsigned long pfn = search_bgn_pfn; pfn < pbd->max_pfn; pfn++) {
+ if (bootmem_page_state(pfn) == BOOTMEM_PAGE_FREE) {
+ free_pfn = pfn;
+ break;
+ }
+ // printk("pfn %d alloced\n", pfn);
+ }
+
+ // 检验接下来是否有足够的size
+ unsigned long bgn_pfn = free_pfn;
+ unsigned long end_pfn = bgn_pfn + pfn_cnt;
+
+ // printk("free_pfn: %d end_pfn:%d max_pfn:%d \n", free_pfn, end_pfn, pbd->max_pfn);
+
+ // 剩余空间不足
+ if (bgn_pfn >= pbd->max_pfn || end_pfn >= pbd->max_pfn) {
+ return region;
+ }
+
+ //
+ for (unsigned long pfn = bgn_pfn; pfn < end_pfn; pfn++) {
+ if (bootmem_page_state(pfn) != BOOTMEM_PAGE_FREE) {
+ search_bgn_pfn = pfn + 1;
+ goto find_next_block;
+ }
+ }
+
+ reserve_bootmem(bgn_pfn, end_pfn);
+ region = pfn2va(bgn_pfn);
+
+ return region;
+}
+
void *alloc_bootmem(unsigned long size, unsigned long align) {
bootmem_data_t *pbd = &bootmem_data;
assert(page >= buddy_system.page_map);
// assert(page < buddy_system.page_map_end);
if (page >= buddy_system.page_map_end) {
- printk("buddy_system.page_map %08x buddy_system.page_map_end %08x\n", buddy_system.page_map, buddy_system.page_map_end);
+ printk("buddy_system.page_map %08x buddy_system.page_map_end %08x\n", buddy_system.page_map,
+ buddy_system.page_map_end);
printk("error %s page %08x addr %08x\n", __func__, page, addr);
panic("error");
}
// init page map
unsigned long page_map_size = pfn_cnt * sizeof(page_t);
- buddy_system.page_map = alloc_bootmem(page_map_size, PAGE_SIZE);
+ buddy_system.page_map = alloc_from_bootmem(page_map_size, "buddy");
if (0 == buddy_system.page_map) {
printk("can not go on playing...\n");
while (1)
}
buddy_system.page_map_end = buddy_system.page_map + pfn_cnt + 1;
- printk("page_map begin %08x end %08x pfncnt %u page_t size %u\n", buddy_system.page_map, buddy_system.page_map_end, pfn_cnt, sizeof(page_t));
+ printk("page_map begin %08x end %08x pfncnt %u page_t size %u\n", buddy_system.page_map, buddy_system.page_map_end,
+ pfn_cnt, sizeof(page_t));
for (i = 0; i < pfn_cnt; ++i) {
page = buddy_system.page_map + i;
memset((void *)page, 0, sizeof(page_t));
unsigned long ti = pfn % PAGE_PTE_CNT;
unsigned long page_addr = pfn2pa(pfn);
if (ti == 0) {
- pgtb_addr = (unsigned long)va2pa(bootmem_alloc_pages(1));
+ pgtb_addr = (unsigned long)va2pa(alloc_from_bootmem(PAGE_SIZE, "paging"));
if (0 == pgtb_addr) panic("No Pages for Paging...");
memset((void *)pgtb_addr, 0, PAGE_SIZE);
printk("init bootmem alloc...\n");
init_bootmem();
printk("init global paging...\n");
+
init_paging();
printk("init buddy system...\n");