summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips64/kernel/head.S1
-rw-r--r--arch/mips64/mm/init.c62
-rw-r--r--arch/mips64/sgi-ip27/ip27-memory.c4
-rw-r--r--include/asm-mips64/pgtable.h25
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);