diff options
-rw-r--r-- | arch/mips64/kernel/head.S | 1 | ||||
-rw-r--r-- | arch/mips64/mm/init.c | 62 | ||||
-rw-r--r-- | arch/mips64/sgi-ip27/ip27-memory.c | 4 | ||||
-rw-r--r-- | include/asm-mips64/pgtable.h | 25 |
4 files changed, 29 insertions, 63 deletions
diff --git a/arch/mips64/kernel/head.S b/arch/mips64/kernel/head.S index f13bd9290..946bd98b3 100644 --- a/arch/mips64/kernel/head.S +++ b/arch/mips64/kernel/head.S @@ -171,4 +171,3 @@ NESTED(bootstrap, 16, sp) page invalid_pmd_table, 1 page empty_bad_page_table, 0 page empty_bad_pmd_table, 1 - page empty_bad_page diff --git a/arch/mips64/mm/init.c b/arch/mips64/mm/init.c index c6b301e14..c518f96b4 100644 --- a/arch/mips64/mm/init.c +++ b/arch/mips64/mm/init.c @@ -56,7 +56,7 @@ void __bad_pte(pmd_t *pmd) void __bad_pmd(pgd_t *pgd) { printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd)); - pgd_set(pgd, (pmd_t *) BAD_PAGETABLE); + pgd_set(pgd, empty_bad_pmd_table); } void pgd_init(unsigned long page) @@ -93,7 +93,7 @@ pgd_t *get_pgd_slow(void) return ret; } -void pmd_init(unsigned long addr) +void pmd_init(unsigned long addr, unsigned long pagetable) { unsigned long *p, *end; @@ -101,14 +101,14 @@ void pmd_init(unsigned long addr) end = p + PTRS_PER_PMD; while (p < end) { - p[0] = (unsigned long) invalid_pte_table; - p[1] = (unsigned long) invalid_pte_table; - p[2] = (unsigned long) invalid_pte_table; - p[3] = (unsigned long) invalid_pte_table; - p[4] = (unsigned long) invalid_pte_table; - p[5] = (unsigned long) invalid_pte_table; - p[6] = (unsigned long) invalid_pte_table; - p[7] = (unsigned long) invalid_pte_table; + p[0] = (unsigned long)pagetable; + p[1] = (unsigned long)pagetable; + p[2] = (unsigned long)pagetable; + p[3] = (unsigned long)pagetable; + p[4] = (unsigned long)pagetable; + p[5] = (unsigned long)pagetable; + p[6] = (unsigned long)pagetable; + p[7] = (unsigned long)pagetable; p += 8; } } @@ -120,7 +120,7 @@ pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset) pmd = (pmd_t *) __get_free_pages(GFP_KERNEL, 1); if (pgd_none(*pgd)) { if (pmd) { - pmd_init((unsigned long)pmd); + pmd_init((unsigned long)pmd, (unsigned long)invalid_pte_table); pgd_set(pgd, pmd); return pmd + offset; } @@ -246,21 +246,6 @@ unsigned long setup_zero_pages(void) return 1UL << order; } -extern inline void pte_init(unsigned long page) -{ - unsigned long *p, *end, bp; - - bp = pte_val(BAD_PAGE); - p = (unsigned long *) page; - end = p + (2 * PTRS_PER_PTE); - - while (p < end) { - p[0] = p[1] = p[2] = p[3] = - p[4] = p[5] = p[6] = p[7] = bp; - p += 8; - } -} - /* * BAD_PAGE is the page that is used for page faults when linux * is out-of-memory. Older versions of linux just did a @@ -276,32 +261,17 @@ extern inline void pte_init(unsigned long page) */ pmd_t * __bad_pmd_table(void) { - extern pmd_t invalid_pmd_table[PTRS_PER_PMD]; - unsigned long page; - - page = (unsigned long) invalid_pmd_table; - pmd_init(page); - - return (pmd_t *) page; + return empty_bad_pmd_table; } pte_t * __bad_pagetable(void) { - unsigned long page; - - page = (unsigned long) empty_bad_page_table; - pte_init(page); - - return (pte_t *) page; + return empty_bad_page_table; } pte_t __bad_page(void) { - extern char empty_bad_page[PAGE_SIZE]; - unsigned long page = (unsigned long) empty_bad_page; - - clear_page((void *)page); - return pte_mkdirty(mk_pte_phys(__pa(page), PAGE_SHARED)); + return __pte(0); } void show_mem(void) @@ -346,8 +316,10 @@ void __init paging_init(void) /* Initialize the entire pgd. */ pgd_init((unsigned long)swapper_pg_dir); - pmd_init((unsigned long)invalid_pmd_table); + pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table); memset((void *)invalid_pte_table, 0, sizeof(pte_t) * PTRS_PER_PTE); + pmd_init((unsigned long)empty_bad_pmd_table, (unsigned long)empty_bad_page_table); + memset((void *)empty_bad_page_table, 0, sizeof(pte_t) * PTRS_PER_PTE); max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; low = max_low_pfn; diff --git a/arch/mips64/sgi-ip27/ip27-memory.c b/arch/mips64/sgi-ip27/ip27-memory.c index ddc01c1f1..afa900313 100644 --- a/arch/mips64/sgi-ip27/ip27-memory.c +++ b/arch/mips64/sgi-ip27/ip27-memory.c @@ -248,8 +248,10 @@ void __init paging_init(void) /* Initialize the entire pgd. */ pgd_init((unsigned long)swapper_pg_dir); - pmd_init((unsigned long)invalid_pmd_table); + pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table); memset((void *)invalid_pte_table, 0, sizeof(pte_t) * PTRS_PER_PTE); + pmd_init((unsigned long)empty_bad_pmd_table, (unsigned long)empty_bad_page_table); + memset((void *)empty_bad_page_table, 0, sizeof(pte_t) * PTRS_PER_PTE); for (node = 0; node < numnodes; node++) { pfn_t start_pfn = slot_getbasepfn(node, 0); diff --git a/include/asm-mips64/pgtable.h b/include/asm-mips64/pgtable.h index 9ba68add9..3d25fcf43 100644 --- a/include/asm-mips64/pgtable.h +++ b/include/asm-mips64/pgtable.h @@ -53,7 +53,12 @@ extern void (*_flush_page_to_ram)(struct page * page); * page tables. Each page table is a single 4K page, giving 512 (== * PTRS_PER_PTE) 8 byte ptes. Each pgde is initialized to point to * invalid_pmd_table, each pmde is initialized to point to - * invalid_pte_table, each pte is initialized to 0. + * invalid_pte_table, each pte is initialized to 0. When memory is low, + * and a pmd table or a page table allocation fails, empty_bad_pmd_table + * and empty_bad_page_table is returned back to higher layer code, so + * that the failure is recognized later on. Linux does not seem to + * handle these failures very well though. The empty_bad_page_table has + * invalid pte entries in it, to force page faults. */ #endif /* !defined (_LANGUAGE_ASSEMBLY) */ @@ -275,13 +280,7 @@ extern inline int pmd_none(pmd_t pmd) extern inline int pmd_bad(pmd_t pmd) { - return ((pmd_page(pmd) > (unsigned long) high_memory) || - (pmd_page(pmd) < PAGE_OFFSET)); -} - -extern inline int pmd_present(pmd_t pmd) -{ - return pmd_val(pmd) != (unsigned long) invalid_pte_table; + return pmd_val(pmd) == (unsigned long) empty_bad_page_table; } extern inline void pmd_clear(pmd_t *pmdp) @@ -299,13 +298,7 @@ extern inline int pgd_none(pgd_t pgd) extern inline int pgd_bad(pgd_t pgd) { - return ((pgd_page(pgd) > (unsigned long) high_memory) || - (pgd_page(pgd) < PAGE_OFFSET)); -} - -extern inline int pgd_present(pgd_t pgd) -{ - return pgd_val(pgd) != (unsigned long) invalid_pmd_table; + return pgd_val(pgd) == (unsigned long) empty_bad_pmd_table; } extern inline void pgd_clear(pgd_t *pgdp) @@ -470,7 +463,7 @@ extern inline pte_t *pte_offset(pmd_t * dir, unsigned long address) * Initialize a new pgd / pmd table with invalid pointers. */ extern void pgd_init(unsigned long page); -extern void pmd_init(unsigned long page); +extern void pmd_init(unsigned long page, unsigned long pagetable); extern pgd_t swapper_pg_dir[1024]; extern void paging_init(void); |