#include #include #include #include static char __attribute__((aligned (4096))) mapped_page[4096]; static char map[NPAGES / 8]; static pdir_t kpdir; ptab_t ktab; void *alloc_physical_page(void) { int i, j; for(i = 32; i < sizeof(map); i++) { if(map[i] == -1) continue; for(j = 0; j < 8; j++) { if(!((map[i] >> j) & 1)) break; } map[i] |= 1 << j; return (void*) (((i << 3) + j) << 12); } return NULL; } int free_physical_page(void *page) { char tmp; uint32_t p = (uint32_t) page >> 12; if(p > NPAGES) return -1; tmp = map[p >> 3]; map[p >> 3] &= ~(1 << (p & 7)); if((tmp & (1 << (p & 7)))) return 0; return -1; } void *alloc_physical_pages(unsigned int n) { void *p = NULL; void *last = NULL; void **page; while(n--) { p = alloc_physical_page(); if(p == NULL) { page = &last; while(*page) { free_physical_page(*page); page = *page; } return NULL; } map_page(p); *((void**) mapped_page) = last; last = p; } return p; } void *map_page(void *page) { uint32_t p = (uint32_t) mapped_page; /* enforce 4KB page alignment */ page = (void*) ((uint32_t) page & ~0xFFF); ktab[(p >> 12) & 0x3FF] = (uint32_t) page | 0x003; invlpg(mapped_page); return mapped_page; } void paging_init(void) { int i; /* empty the page directory */ for(i = 0; i < PGENT; i++) kpdir[i] = 0; /* populate the kernel's page table */ for(i = 0; i < PGENT; i++) { ktab[i] = 0; if(i < 256) ktab[i] = (i << 12) | 0x003; } /* populate the kernel's page directory */ kpdir[0] = ((pde_t) ktab) | 0x007; __asm__ ( "mov %%eax, %%cr3\n" "mov %%cr0, %%eax\n" "or $0x80000000, %%eax\n" "mov %%eax, %%cr0\n" :: "a" (&kpdir) ); }