static pte_t * __init kernel_page_table(void) { pte_t *ptablep; ptablep = (pte_t *)alloc_bootmem_low_pages(PAGE_SIZE); clear_page(ptablep); __flush_page_to_ram(ptablep); flush_tlb_kernel_page(ptablep); nocache_page(ptablep); return ptablep; }
static pmd_t * __init kernel_ptr_table(void) { if (!last_pgtable) { unsigned long pmd, last; int i; /* Find the last ptr table that was used in head.S and * reuse the remaining space in that page for further * ptr tables. */ last = (unsigned long)kernel_pg_dir; for (i = 0; i < PTRS_PER_PGD; i++) { if (!pgd_present(kernel_pg_dir[i])) continue; pmd = __pgd_page(kernel_pg_dir[i]); if (pmd > last) last = pmd; } last_pgtable = (pmd_t *)last; #ifdef DEBUG printk("kernel_ptr_init: %p\n", last_pgtable); #endif } last_pgtable += PTRS_PER_PMD; if (((unsigned long)last_pgtable & ~PAGE_MASK) == 0) { last_pgtable = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE); clear_page(last_pgtable); __flush_page_to_ram(last_pgtable); flush_tlb_kernel_page(last_pgtable); nocache_page(last_pgtable); } return last_pgtable; }
pmd_t *get_pointer_table (void) { pmd_t *pmdp = NULL; unsigned long flags; struct ptable_desc *dp = ptable_list.next; int i; /* * For a pointer table for a user process address space, a * table is taken from a page allocated for the purpose. Each * page can hold 8 pointer tables. The page is remapped in * virtual address space to be noncacheable. */ if (PD_NONEFREE (dp)) { if (!(dp = kmalloc (sizeof(struct ptable_desc),GFP_KERNEL))) { return 0; } if (!(dp->page = __get_free_page (GFP_KERNEL))) { kfree (dp); return 0; } nocache_page (dp->page); dp->alloced = 0; /* put at head of list */ save_flags(flags); cli(); dp->next = ptable_list.next; dp->prev = ptable_list.next->prev; ptable_list.next->prev = dp; ptable_list.next = dp; restore_flags(flags); } for (i = 0; i < 8; i++) if (PD_TABLEFREE (dp, i)) { PD_MARKUSED (dp, i); pmdp = (pmd_t *)(dp->page + PTABLE_SIZE*i); break; } if (PD_NONEFREE (dp)) { /* move to end of list */ save_flags(flags); cli(); dp->prev->next = dp->next; dp->next->prev = dp->prev; dp->next = ptable_list.next->prev; dp->prev = ptable_list.prev; ptable_list.prev->next = dp; ptable_list.prev = dp; restore_flags(flags); } memset (pmdp, 0, PTABLE_SIZE); return pmdp; }