diff options
Diffstat (limited to 'arch/m68k/mm')
| -rw-r--r-- | arch/m68k/mm/fault.c | 16 | ||||
| -rw-r--r-- | arch/m68k/mm/fault.h | 7 | ||||
| -rw-r--r-- | arch/m68k/mm/hwtest.c | 2 | ||||
| -rw-r--r-- | arch/m68k/mm/init.c | 7 | ||||
| -rw-r--r-- | arch/m68k/mm/mcfmmu.c | 68 | ||||
| -rw-r--r-- | arch/m68k/mm/motorola.c | 93 | ||||
| -rw-r--r-- | arch/m68k/mm/sun3kmap.c | 6 | ||||
| -rw-r--r-- | arch/m68k/mm/sun3mmu.c | 14 |
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); |
