summaryrefslogtreecommitdiff
path: root/arch/m68k/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k/mm')
-rw-r--r--arch/m68k/mm/fault.c16
-rw-r--r--arch/m68k/mm/fault.h7
-rw-r--r--arch/m68k/mm/hwtest.c2
-rw-r--r--arch/m68k/mm/init.c7
-rw-r--r--arch/m68k/mm/mcfmmu.c68
-rw-r--r--arch/m68k/mm/motorola.c93
-rw-r--r--arch/m68k/mm/sun3kmap.c6
-rw-r--r--arch/m68k/mm/sun3mmu.c14
8 files changed, 105 insertions, 108 deletions
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c
index 4d2837eb3e2a..fa3c5f38d989 100644
--- a/arch/m68k/mm/fault.c
+++ b/arch/m68k/mm/fault.c
@@ -17,6 +17,8 @@
#include <asm/setup.h>
#include <asm/traps.h>
+#include "fault.h"
+
extern void die_if_kernel(char *, struct pt_regs *, long);
int send_fault_sig(struct pt_regs *regs)
@@ -105,8 +107,9 @@ retry:
if (address + 256 < rdusp())
goto map_err;
}
- if (expand_stack(vma, address))
- goto map_err;
+ vma = expand_stack(mm, address);
+ if (!vma)
+ goto map_err_nosemaphore;
/*
* Ok, we have a good vm_area for this memory access, so
@@ -138,8 +141,11 @@ good_area:
fault = handle_mm_fault(vma, address, flags, regs);
pr_debug("handle_mm_fault returns %x\n", fault);
- if (fault_signal_pending(fault, regs))
+ if (fault_signal_pending(fault, regs)) {
+ if (!user_mode(regs))
+ goto no_context;
return 0;
+ }
/* The fault is fully completed (including releasing mmap lock) */
if (fault & VM_FAULT_COMPLETED)
@@ -193,10 +199,12 @@ bus_err:
goto send_sig;
map_err:
+ mmap_read_unlock(mm);
+map_err_nosemaphore:
current->thread.signo = SIGSEGV;
current->thread.code = SEGV_MAPERR;
current->thread.faddr = address;
- goto send_sig;
+ return send_fault_sig(regs);
acc_err:
current->thread.signo = SIGSEGV;
diff --git a/arch/m68k/mm/fault.h b/arch/m68k/mm/fault.h
new file mode 100644
index 000000000000..dab14ef7d4a1
--- /dev/null
+++ b/arch/m68k/mm/fault.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+struct pt_regs;
+
+int do_page_fault(struct pt_regs *regs, unsigned long address,
+ unsigned long error_code);
+int send_fault_sig(struct pt_regs *regs);
diff --git a/arch/m68k/mm/hwtest.c b/arch/m68k/mm/hwtest.c
index fe99aa99987e..8ee7a3368688 100644
--- a/arch/m68k/mm/hwtest.c
+++ b/arch/m68k/mm/hwtest.c
@@ -26,6 +26,8 @@
#include <linux/module.h>
+#include <asm/hwtest.h>
+
int hwreg_present(volatile void *regp)
{
int ret = 0;
diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
index 1b47bec15832..488411af1b3f 100644
--- a/arch/m68k/mm/init.c
+++ b/arch/m68k/mm/init.c
@@ -68,10 +68,7 @@ void __init paging_init(void)
high_memory = (void *) end_mem;
- empty_zero_page = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
- if (!empty_zero_page)
- panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
- __func__, PAGE_SIZE, PAGE_SIZE);
+ empty_zero_page = memblock_alloc_or_panic(PAGE_SIZE, PAGE_SIZE);
max_zone_pfn[ZONE_DMA] = end_mem >> PAGE_SHIFT;
free_area_init(max_zone_pfn);
}
@@ -124,7 +121,5 @@ static inline void init_pointer_tables(void)
void __init mem_init(void)
{
- /* this will put all memory onto the freelists */
- memblock_free_all();
init_pointer_tables();
}
diff --git a/arch/m68k/mm/mcfmmu.c b/arch/m68k/mm/mcfmmu.c
index 70aa0979e027..19a75029036c 100644
--- a/arch/m68k/mm/mcfmmu.c
+++ b/arch/m68k/mm/mcfmmu.c
@@ -38,26 +38,19 @@ void __init paging_init(void)
pgd_t *pg_dir;
pte_t *pg_table;
unsigned long address, size;
- unsigned long next_pgtable, bootmem_end;
+ unsigned long next_pgtable;
unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0 };
int i;
- empty_zero_page = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
- if (!empty_zero_page)
- panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
- __func__, PAGE_SIZE, PAGE_SIZE);
+ empty_zero_page = memblock_alloc_or_panic(PAGE_SIZE, PAGE_SIZE);
pg_dir = swapper_pg_dir;
memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir));
size = num_pages * sizeof(pte_t);
size = (size + PAGE_SIZE) & ~(PAGE_SIZE-1);
- next_pgtable = (unsigned long) memblock_alloc(size, PAGE_SIZE);
- if (!next_pgtable)
- panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
- __func__, size, PAGE_SIZE);
+ next_pgtable = (unsigned long) memblock_alloc_or_panic(size, PAGE_SIZE);
- bootmem_end = (next_pgtable + size + PAGE_SIZE) & PAGE_MASK;
pg_dir += PAGE_OFFSET >> PGDIR_SHIFT;
address = PAGE_OFFSET;
@@ -69,7 +62,8 @@ void __init paging_init(void)
/* now change pg_table to kernel virtual addresses */
for (i = 0; i < PTRS_PER_PTE; ++i, ++pg_table) {
- pte_t pte = pfn_pte(virt_to_pfn(address), PAGE_INIT);
+ pte_t pte = pfn_pte(virt_to_pfn((void *)address),
+ PAGE_INIT);
if (address >= (unsigned long) high_memory)
pte_val(pte) = 0;
@@ -91,7 +85,8 @@ int cf_tlb_miss(struct pt_regs *regs, int write, int dtlb, int extension_word)
p4d_t *p4d;
pud_t *pud;
pmd_t *pmd;
- pte_t *pte;
+ pte_t *pte = NULL;
+ int ret = -1;
int asid;
local_irq_save(flags);
@@ -100,47 +95,33 @@ int cf_tlb_miss(struct pt_regs *regs, int write, int dtlb, int extension_word)
regs->pc + (extension_word * sizeof(long));
mm = (!user_mode(regs) && KMAPAREA(mmuar)) ? &init_mm : current->mm;
- if (!mm) {
- local_irq_restore(flags);
- return -1;
- }
+ if (!mm)
+ goto out;
pgd = pgd_offset(mm, mmuar);
- if (pgd_none(*pgd)) {
- local_irq_restore(flags);
- return -1;
- }
+ if (pgd_none(*pgd))
+ goto out;
p4d = p4d_offset(pgd, mmuar);
- if (p4d_none(*p4d)) {
- local_irq_restore(flags);
- return -1;
- }
+ if (p4d_none(*p4d))
+ goto out;
pud = pud_offset(p4d, mmuar);
- if (pud_none(*pud)) {
- local_irq_restore(flags);
- return -1;
- }
+ if (pud_none(*pud))
+ goto out;
pmd = pmd_offset(pud, mmuar);
- if (pmd_none(*pmd)) {
- local_irq_restore(flags);
- return -1;
- }
+ if (pmd_none(*pmd))
+ goto out;
pte = (KMAPAREA(mmuar)) ? pte_offset_kernel(pmd, mmuar)
: pte_offset_map(pmd, mmuar);
- if (pte_none(*pte) || !pte_present(*pte)) {
- local_irq_restore(flags);
- return -1;
- }
+ if (!pte || pte_none(*pte) || !pte_present(*pte))
+ goto out;
if (write) {
- if (!pte_write(*pte)) {
- local_irq_restore(flags);
- return -1;
- }
+ if (!pte_write(*pte))
+ goto out;
set_pte(pte, pte_mkdirty(*pte));
}
@@ -161,9 +142,12 @@ int cf_tlb_miss(struct pt_regs *regs, int write, int dtlb, int extension_word)
mmu_write(MMUOR, MMUOR_ACC | MMUOR_UAA);
else
mmu_write(MMUOR, MMUOR_ITLB | MMUOR_ACC | MMUOR_UAA);
-
+ ret = 0;
+out:
+ if (pte && !KMAPAREA(mmuar))
+ pte_unmap(pte);
local_irq_restore(flags);
- return 0;
+ return ret;
}
void __init cf_bootmem_alloc(void)
diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c
index 2a375637e007..62283bc2ed79 100644
--- a/arch/m68k/mm/motorola.c
+++ b/arch/m68k/mm/motorola.c
@@ -81,7 +81,7 @@ static inline void cache_page(void *vaddr)
void mmu_page_ctor(void *page)
{
- __flush_page_to_ram(page);
+ __flush_pages_to_ram(page, 1);
flush_tlb_kernel_page(page);
nocache_page(page);
}
@@ -92,22 +92,24 @@ void mmu_page_dtor(void *page)
}
/* ++andreas: {get,free}_pointer_table rewritten to use unused fields from
- struct page instead of separately kmalloced struct. Stolen from
+ struct ptdesc instead of separately kmalloced struct. Stolen from
arch/sparc/mm/srmmu.c ... */
typedef struct list_head ptable_desc;
-static struct list_head ptable_list[2] = {
+static struct list_head ptable_list[3] = {
LIST_HEAD_INIT(ptable_list[0]),
LIST_HEAD_INIT(ptable_list[1]),
+ LIST_HEAD_INIT(ptable_list[2]),
};
-#define PD_PTABLE(page) ((ptable_desc *)&(virt_to_page(page)->lru))
-#define PD_PAGE(ptable) (list_entry(ptable, struct page, lru))
-#define PD_MARKBITS(dp) (*(unsigned int *)&PD_PAGE(dp)->index)
+#define PD_PTABLE(ptdesc) ((ptable_desc *)&(virt_to_ptdesc((void *)(ptdesc))->pt_list))
+#define PD_PTDESC(ptable) (list_entry(ptable, struct ptdesc, pt_list))
+#define PD_MARKBITS(dp) (*(unsigned int *)&PD_PTDESC(dp)->pt_index)
-static const int ptable_shift[2] = {
- 7+2, /* PGD, PMD */
+static const int ptable_shift[3] = {
+ 7+2, /* PGD */
+ 7+2, /* PMD */
6+2, /* PTE */
};
@@ -118,10 +120,10 @@ void __init init_pointer_table(void *table, int type)
{
ptable_desc *dp;
unsigned long ptable = (unsigned long)table;
- unsigned long page = ptable & PAGE_MASK;
- unsigned int mask = 1U << ((ptable - page)/ptable_size(type));
+ unsigned long pt_addr = ptable & PAGE_MASK;
+ unsigned int mask = 1U << ((ptable - pt_addr)/ptable_size(type));
- dp = PD_PTABLE(page);
+ dp = PD_PTABLE(pt_addr);
if (!(PD_MARKBITS(dp) & mask)) {
PD_MARKBITS(dp) = ptable_mask(type);
list_add(dp, &ptable_list[type]);
@@ -130,14 +132,14 @@ void __init init_pointer_table(void *table, int type)
PD_MARKBITS(dp) &= ~mask;
pr_debug("init_pointer_table: %lx, %x\n", ptable, PD_MARKBITS(dp));
- /* unreserve the page so it's possible to free that page */
- __ClearPageReserved(PD_PAGE(dp));
- init_page_count(PD_PAGE(dp));
+ /* unreserve the ptdesc so it's possible to free that ptdesc */
+ __ClearPageReserved(ptdesc_page(PD_PTDESC(dp)));
+ init_page_count(ptdesc_page(PD_PTDESC(dp)));
return;
}
-void *get_pointer_table(int type)
+void *get_pointer_table(struct mm_struct *mm, int type)
{
ptable_desc *dp = ptable_list[type].next;
unsigned int mask = list_empty(&ptable_list[type]) ? 0 : PD_MARKBITS(dp);
@@ -145,32 +147,44 @@ void *get_pointer_table(int type)
/*
* 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
+ * table is taken from a ptdesc allocated for the purpose. Each
+ * ptdesc can hold 8 pointer tables. The ptdesc is remapped in
* virtual address space to be noncacheable.
*/
if (mask == 0) {
- void *page;
+ struct ptdesc *ptdesc;
ptable_desc *new;
+ void *pt_addr;
- if (!(page = (void *)get_zeroed_page(GFP_KERNEL)))
+ ptdesc = pagetable_alloc(GFP_KERNEL | __GFP_ZERO, 0);
+ if (!ptdesc)
return NULL;
- if (type == TABLE_PTE) {
+ pt_addr = ptdesc_address(ptdesc);
+
+ switch (type) {
+ case TABLE_PTE:
/*
* m68k doesn't have SPLIT_PTE_PTLOCKS for not having
* SMP.
*/
- pgtable_pte_page_ctor(virt_to_page(page));
+ pagetable_pte_ctor(mm, ptdesc);
+ break;
+ case TABLE_PMD:
+ pagetable_pmd_ctor(mm, ptdesc);
+ break;
+ case TABLE_PGD:
+ pagetable_pgd_ctor(ptdesc);
+ break;
}
- mmu_page_ctor(page);
+ mmu_page_ctor(pt_addr);
- new = PD_PTABLE(page);
+ new = PD_PTABLE(pt_addr);
PD_MARKBITS(new) = ptable_mask(type) - 1;
list_add_tail(new, dp);
- return (pmd_t *)page;
+ return (pmd_t *)pt_addr;
}
for (tmp = 1, off = 0; (mask & tmp) == 0; tmp <<= 1, off += ptable_size(type))
@@ -180,29 +194,27 @@ void *get_pointer_table(int type)
/* move to end of list */
list_move_tail(dp, &ptable_list[type]);
}
- return page_address(PD_PAGE(dp)) + off;
+ return ptdesc_address(PD_PTDESC(dp)) + off;
}
int free_pointer_table(void *table, int type)
{
ptable_desc *dp;
unsigned long ptable = (unsigned long)table;
- unsigned long page = ptable & PAGE_MASK;
- unsigned int mask = 1U << ((ptable - page)/ptable_size(type));
+ unsigned long pt_addr = ptable & PAGE_MASK;
+ unsigned int mask = 1U << ((ptable - pt_addr)/ptable_size(type));
- dp = PD_PTABLE(page);
+ dp = PD_PTABLE(pt_addr);
if (PD_MARKBITS (dp) & mask)
panic ("table already free!");
PD_MARKBITS (dp) |= mask;
if (PD_MARKBITS(dp) == ptable_mask(type)) {
- /* all tables in page are free, free page */
+ /* all tables in ptdesc are free, free ptdesc */
list_del(dp);
- mmu_page_dtor((void *)page);
- if (type == TABLE_PTE)
- pgtable_pte_page_dtor(virt_to_page(page));
- free_page (page);
+ mmu_page_dtor((void *)pt_addr);
+ pagetable_dtor_free(virt_to_ptdesc((void *)pt_addr));
return 1;
} else if (ptable_list[type].next != dp) {
/*
@@ -437,7 +449,7 @@ void __init paging_init(void)
}
min_addr = m68k_memory[0].addr;
- max_addr = min_addr + m68k_memory[0].size;
+ max_addr = min_addr + m68k_memory[0].size - 1;
memblock_add_node(m68k_memory[0].addr, m68k_memory[0].size, 0,
MEMBLOCK_NONE);
for (i = 1; i < m68k_num_memory;) {
@@ -452,21 +464,21 @@ void __init paging_init(void)
}
memblock_add_node(m68k_memory[i].addr, m68k_memory[i].size, i,
MEMBLOCK_NONE);
- addr = m68k_memory[i].addr + m68k_memory[i].size;
+ addr = m68k_memory[i].addr + m68k_memory[i].size - 1;
if (addr > max_addr)
max_addr = addr;
i++;
}
m68k_memoffset = min_addr - PAGE_OFFSET;
- m68k_virt_to_node_shift = fls(max_addr - min_addr - 1) - 6;
+ m68k_virt_to_node_shift = fls(max_addr - min_addr) - 6;
module_fixup(NULL, __start_fixup, __stop_fixup);
flush_icache();
- high_memory = phys_to_virt(max_addr);
+ high_memory = phys_to_virt(max_addr) + 1;
min_low_pfn = availmem >> PAGE_SHIFT;
- max_pfn = max_low_pfn = max_addr >> PAGE_SHIFT;
+ max_pfn = max_low_pfn = (max_addr >> PAGE_SHIFT) + 1;
/* Reserve kernel text/data/bss and the memory allocated in head.S */
memblock_reserve(m68k_memory[0].addr, availmem - m68k_memory[0].addr);
@@ -491,10 +503,7 @@ void __init paging_init(void)
* initialize the bad page table and bad page to point
* to a couple of allocated pages
*/
- empty_zero_page = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
- if (!empty_zero_page)
- panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
- __func__, PAGE_SIZE, PAGE_SIZE);
+ empty_zero_page = memblock_alloc_or_panic(PAGE_SIZE, PAGE_SIZE);
/*
* Set up SFC/DFC registers
diff --git a/arch/m68k/mm/sun3kmap.c b/arch/m68k/mm/sun3kmap.c
index 4f2a7ef8348b..ac091892d82f 100644
--- a/arch/m68k/mm/sun3kmap.c
+++ b/arch/m68k/mm/sun3kmap.c
@@ -18,11 +18,9 @@
#include <asm/io.h>
#include <asm/sun3mmu.h>
-#undef SUN3_KMAP_DEBUG
+#include "../sun3/sun3.h"
-#ifdef SUN3_KMAP_DEBUG
-extern void print_pte_vaddr(unsigned long vaddr);
-#endif
+#undef SUN3_KMAP_DEBUG
extern void mmu_emu_map_pmeg (int context, int vaddr);
diff --git a/arch/m68k/mm/sun3mmu.c b/arch/m68k/mm/sun3mmu.c
index b619d0d4319c..1ecf6bdd08bf 100644
--- a/arch/m68k/mm/sun3mmu.c
+++ b/arch/m68k/mm/sun3mmu.c
@@ -24,7 +24,7 @@
#include <asm/machdep.h>
#include <asm/io.h>
-extern void mmu_emu_init (unsigned long bootmem_end);
+#include "../sun3/sun3.h"
const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
@@ -44,10 +44,7 @@ void __init paging_init(void)
unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0, };
unsigned long size;
- empty_zero_page = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
- if (!empty_zero_page)
- panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
- __func__, PAGE_SIZE, PAGE_SIZE);
+ empty_zero_page = memblock_alloc_or_panic(PAGE_SIZE, PAGE_SIZE);
address = PAGE_OFFSET;
pg_dir = swapper_pg_dir;
@@ -57,10 +54,7 @@ void __init paging_init(void)
size = num_pages * sizeof(pte_t);
size = (size + PAGE_SIZE) & ~(PAGE_SIZE-1);
- next_pgtable = (unsigned long)memblock_alloc(size, PAGE_SIZE);
- if (!next_pgtable)
- panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
- __func__, size, PAGE_SIZE);
+ next_pgtable = (unsigned long)memblock_alloc_or_panic(size, PAGE_SIZE);
bootmem_end = (next_pgtable + size + PAGE_SIZE) & PAGE_MASK;
/* Map whole memory from PAGE_OFFSET (0x0E000000) */
@@ -75,7 +69,7 @@ void __init paging_init(void)
/* now change pg_table to kernel virtual addresses */
pg_table = (pte_t *) __va ((unsigned long) pg_table);
for (i=0; i<PTRS_PER_PTE; ++i, ++pg_table) {
- pte_t pte = pfn_pte(virt_to_pfn(address), PAGE_INIT);
+ pte_t pte = pfn_pte(virt_to_pfn((void *)address), PAGE_INIT);
if (address >= (unsigned long)high_memory)
pte_val (pte) = 0;
set_pte (pg_table, pte);