summaryrefslogtreecommitdiffstats
path: root/arch/arm26/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm26/mm')
-rw-r--r--arch/arm26/mm/Makefile6
-rw-r--r--arch/arm26/mm/extable.c24
-rw-r--r--arch/arm26/mm/fault.c312
-rw-r--r--arch/arm26/mm/fault.h5
-rw-r--r--arch/arm26/mm/init.c403
-rw-r--r--arch/arm26/mm/memc.c184
-rw-r--r--arch/arm26/mm/proc-funcs.S359
-rw-r--r--arch/arm26/mm/small_page.c192
8 files changed, 0 insertions, 1485 deletions
diff --git a/arch/arm26/mm/Makefile b/arch/arm26/mm/Makefile
deleted file mode 100644
index a8fb166..0000000
--- a/arch/arm26/mm/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for the linux arm26-specific parts of the memory manager.
-#
-
-obj-y := init.o extable.o proc-funcs.o memc.o fault.o \
- small_page.o
diff --git a/arch/arm26/mm/extable.c b/arch/arm26/mm/extable.c
deleted file mode 100644
index 38e1958..0000000
--- a/arch/arm26/mm/extable.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * linux/arch/arm26/mm/extable.c
- */
-
-#include <linux/module.h>
-#include <asm/uaccess.h>
-
-int fixup_exception(struct pt_regs *regs)
-{
- const struct exception_table_entry *fixup;
-
- fixup = search_exception_tables(instruction_pointer(regs));
-
- /*
- * The kernel runs in SVC mode - make sure we keep running in SVC mode
- * by frobbing the PSR appropriately (PSR and PC are in the same reg.
- * on ARM26)
- */
- if (fixup)
- regs->ARM_pc = fixup->fixup | PSR_I_BIT | MODE_SVC26;
-
- return fixup != NULL;
-}
-
diff --git a/arch/arm26/mm/fault.c b/arch/arm26/mm/fault.c
deleted file mode 100644
index dec638a..0000000
--- a/arch/arm26/mm/fault.c
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * linux/arch/arm26/mm/fault.c
- *
- * Copyright (C) 1995 Linus Torvalds
- * Modifications for ARM processor (c) 1995-2001 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/uaccess.h> //FIXME this header may be bogusly included
-
-#include "fault.h"
-
-#define FAULT_CODE_LDRSTRPOST 0x80
-#define FAULT_CODE_LDRSTRPRE 0x40
-#define FAULT_CODE_LDRSTRREG 0x20
-#define FAULT_CODE_LDMSTM 0x10
-#define FAULT_CODE_LDCSTC 0x08
-#define FAULT_CODE_PREFETCH 0x04
-#define FAULT_CODE_WRITE 0x02
-#define FAULT_CODE_FORCECOW 0x01
-
-#define DO_COW(m) ((m) & (FAULT_CODE_WRITE|FAULT_CODE_FORCECOW))
-#define READ_FAULT(m) (!((m) & FAULT_CODE_WRITE))
-#define DEBUG
-/*
- * This is useful to dump out the page tables associated with
- * 'addr' in mm 'mm'.
- */
-void show_pte(struct mm_struct *mm, unsigned long addr)
-{
- pgd_t *pgd;
-
- if (!mm)
- mm = &init_mm;
-
- printk(KERN_ALERT "pgd = %p\n", mm->pgd);
- pgd = pgd_offset(mm, addr);
- printk(KERN_ALERT "[%08lx] *pgd=%08lx", addr, pgd_val(*pgd));
-
- do {
- pmd_t *pmd;
- pte_t *pte;
-
- pmd = pmd_offset(pgd, addr);
-
- if (pmd_none(*pmd))
- break;
-
- if (pmd_bad(*pmd)) {
- printk("(bad)");
- break;
- }
-
- /* We must not map this if we have highmem enabled */
- /* FIXME */
- pte = pte_offset_map(pmd, addr);
- printk(", *pte=%08lx", pte_val(*pte));
- pte_unmap(pte);
- } while(0);
-
- printk("\n");
-}
-
-/*
- * Oops. The kernel tried to access some page that wasn't present.
- */
-static void
-__do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
- struct pt_regs *regs)
-{
- /*
- * Are we prepared to handle this kernel fault?
- */
- if (fixup_exception(regs))
- return;
-
- /*
- * No handler, we'll have to terminate things with extreme prejudice.
- */
- bust_spinlocks(1);
- printk(KERN_ALERT
- "Unable to handle kernel %s at virtual address %08lx\n",
- (addr < PAGE_SIZE) ? "NULL pointer dereference" :
- "paging request", addr);
-
- show_pte(mm, addr);
- die("Oops", regs, fsr);
- bust_spinlocks(0);
- do_exit(SIGKILL);
-}
-
-/*
- * Something tried to access memory that isn't in our memory map..
- * User mode accesses just cause a SIGSEGV
- */
-static void
-__do_user_fault(struct task_struct *tsk, unsigned long addr,
- unsigned int fsr, int code, struct pt_regs *regs)
-{
- struct siginfo si;
-
-#ifdef CONFIG_DEBUG_USER
- printk("%s: unhandled page fault at 0x%08lx, code 0x%03x\n",
- tsk->comm, addr, fsr);
- show_pte(tsk->mm, addr);
- show_regs(regs);
- //dump_backtrace(regs, tsk); // FIXME ARM32 dropped this - why?
- while(1); //FIXME - hack to stop debug going nutso
-#endif
-
- tsk->thread.address = addr;
- tsk->thread.error_code = fsr;
- tsk->thread.trap_no = 14;
- si.si_signo = SIGSEGV;
- si.si_errno = 0;
- si.si_code = code;
- si.si_addr = (void *)addr;
- force_sig_info(SIGSEGV, &si, tsk);
-}
-
-static int
-__do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
- struct task_struct *tsk)
-{
- struct vm_area_struct *vma;
- int fault, mask;
-
- vma = find_vma(mm, addr);
- fault = -2; /* bad map area */
- if (!vma)
- goto out;
- if (vma->vm_start > addr)
- goto check_stack;
-
- /*
- * Ok, we have a good vm_area for this
- * memory access, so we can handle it.
- */
-good_area:
- if (READ_FAULT(fsr)) /* read? */
- mask = VM_READ|VM_EXEC|VM_WRITE;
- else
- mask = VM_WRITE;
-
- fault = -1; /* bad access type */
- if (!(vma->vm_flags & mask))
- goto out;
-
- /*
- * If for any reason at all we couldn't handle
- * the fault, make sure we exit gracefully rather
- * than endlessly redo the fault.
- */
-survive:
- fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(fsr));
- if (unlikely(fault & VM_FAULT_ERROR)) {
- if (fault & VM_FAULT_OOM)
- goto out_of_memory;
- else if (fault & VM_FAULT_SIGBUS)
- return fault;
- BUG();
- }
- if (fault & VM_FAULT_MAJOR)
- tsk->maj_flt++;
- else
- tsk->min_flt++;
- return fault;
-
-out_of_memory:
- fault = -3; /* out of memory */
- if (!is_init(tsk))
- goto out;
-
- /*
- * If we are out of memory for pid1,
- * sleep for a while and retry
- */
- yield();
- goto survive;
-
-check_stack:
- if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr))
- goto good_area;
-out:
- return fault;
-}
-
-int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
-{
- struct task_struct *tsk;
- struct mm_struct *mm;
- int fault;
-
- tsk = current;
- mm = tsk->mm;
-
- /*
- * If we're in an interrupt or have no user
- * context, we must not take the fault..
- */
- if (in_atomic() || !mm)
- goto no_context;
-
- down_read(&mm->mmap_sem);
- fault = __do_page_fault(mm, addr, fsr, tsk);
- up_read(&mm->mmap_sem);
-
- /*
- * Handle the "normal" case first
- */
- if (likely(!(fault & VM_FAULT_ERROR)))
- return 0;
- if (fault & VM_FAULT_SIGBUS)
- goto do_sigbus;
- /* else VM_FAULT_OOM */
-
- /*
- * If we are in kernel mode at this point, we
- * have no context to handle this fault with.
- * FIXME - is this test right?
- */
- if (!user_mode(regs)){
- goto no_context;
- }
-
- if (fault == -3) {
- /*
- * We ran out of memory, or some other thing happened to
- * us that made us unable to handle the page fault gracefully.
- */
- printk("VM: killing process %s\n", tsk->comm);
- do_exit(SIGKILL);
- }
- else{
- __do_user_fault(tsk, addr, fsr, fault == -1 ? SEGV_ACCERR : SEGV_MAPERR, regs);
- }
-
- return 0;
-
-
-/*
- * We ran out of memory, or some other thing happened to us that made
- * us unable to handle the page fault gracefully.
- */
-do_sigbus:
- /*
- * Send a sigbus, regardless of whether we were in kernel
- * or user mode.
- */
- tsk->thread.address = addr; //FIXME - need other bits setting?
- tsk->thread.error_code = fsr;
- tsk->thread.trap_no = 14;
- force_sig(SIGBUS, tsk);
-#ifdef CONFIG_DEBUG_USER
- printk(KERN_DEBUG "%s: sigbus at 0x%08lx, pc=0x%08lx\n",
- current->comm, addr, instruction_pointer(regs));
-#endif
-
- /* Kernel mode? Handle exceptions or die */
- if (user_mode(regs))
- return 0;
-
-no_context:
- __do_kernel_fault(mm, addr, fsr, regs);
- return 0;
-}
-
-/*
- * Handle a data abort. Note that we have to handle a range of addresses
- * on ARM2/3 for ldm. If both pages are zero-mapped, then we have to force
- * a copy-on-write. However, on the second page, we always force COW.
- */
-asmlinkage void
-do_DataAbort(unsigned long min_addr, unsigned long max_addr, int mode, struct pt_regs *regs)
-{
- do_page_fault(min_addr, mode, regs);
-
- if ((min_addr ^ max_addr) >> PAGE_SHIFT){
- do_page_fault(max_addr, mode | FAULT_CODE_FORCECOW, regs);
- }
-}
-
-asmlinkage int
-do_PrefetchAbort(unsigned long addr, struct pt_regs *regs)
-{
-#if 0
- if (the memc mapping for this page exists) {
- printk ("Page in, but got abort (undefined instruction?)\n");
- return 0;
- }
-#endif
- do_page_fault(addr, FAULT_CODE_PREFETCH, regs);
- return 1;
-}
-
diff --git a/arch/arm26/mm/fault.h b/arch/arm26/mm/fault.h
deleted file mode 100644
index 4442d00..0000000
--- a/arch/arm26/mm/fault.h
+++ /dev/null
@@ -1,5 +0,0 @@
-void show_pte(struct mm_struct *mm, unsigned long addr);
-
-int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
-
-unsigned long search_extable(unsigned long addr); //FIXME - is it right?
diff --git a/arch/arm26/mm/init.c b/arch/arm26/mm/init.c
deleted file mode 100644
index 36e7ee3..0000000
--- a/arch/arm26/mm/init.c
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- * linux/arch/arm26/mm/init.c
- *
- * Copyright (C) 1995-2002 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/smp.h>
-#include <linux/init.h>
-#include <linux/initrd.h>
-#include <linux/bootmem.h>
-#include <linux/blkdev.h>
-#include <linux/pfn.h>
-
-#include <asm/segment.h>
-#include <asm/mach-types.h>
-#include <asm/dma.h>
-#include <asm/hardware.h>
-#include <asm/setup.h>
-#include <asm/tlb.h>
-
-#include <asm/map.h>
-
-struct mmu_gather mmu_gathers[NR_CPUS];
-
-extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
-extern char _stext, _text, _etext, _end, __init_begin, __init_end;
-#ifdef CONFIG_XIP_KERNEL
-extern char _endtext, _sdata;
-#endif
-extern unsigned long phys_initrd_start;
-extern unsigned long phys_initrd_size;
-
-/*
- * The sole use of this is to pass memory configuration
- * data from paging_init to mem_init.
- */
-static struct meminfo meminfo __initdata = { 0, };
-
-/*
- * empty_zero_page is a special page that is used for
- * zero-initialized data and COW.
- */
-struct page *empty_zero_page;
-
-void show_mem(void)
-{
- int free = 0, total = 0, reserved = 0;
- int shared = 0, cached = 0, slab = 0;
- struct page *page, *end;
-
- printk("Mem-info:\n");
- show_free_areas();
- printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
-
-
- page = NODE_MEM_MAP(0);
- end = page + NODE_DATA(0)->node_spanned_pages;
-
- do {
- total++;
- if (PageReserved(page))
- reserved++;
- else if (PageSwapCache(page))
- cached++;
- else if (PageSlab(page))
- slab++;
- else if (!page_count(page))
- free++;
- else
- shared += page_count(page) - 1;
- page++;
- } while (page < end);
-
- printk("%d pages of RAM\n", total);
- printk("%d free pages\n", free);
- printk("%d reserved pages\n", reserved);
- printk("%d slab pages\n", slab);
- printk("%d pages shared\n", shared);
- printk("%d pages swap cached\n", cached);
-}
-
-struct node_info {
- unsigned int start;
- unsigned int end;
- int bootmap_pages;
-};
-
-/*
- * FIXME: We really want to avoid allocating the bootmap bitmap
- * over the top of the initrd. Hopefully, this is located towards
- * the start of a bank, so if we allocate the bootmap bitmap at
- * the end, we won't clash.
- */
-static unsigned int __init
-find_bootmap_pfn(struct meminfo *mi, unsigned int bootmap_pages)
-{
- unsigned int start_pfn, bootmap_pfn;
- unsigned int start, end;
-
- start_pfn = PFN_UP((unsigned long)&_end);
- bootmap_pfn = 0;
-
- /* ARM26 machines only have one node */
- if (mi->bank->node != 0)
- BUG();
-
- start = PFN_UP(mi->bank->start);
- end = PFN_DOWN(mi->bank->size + mi->bank->start);
-
- if (start < start_pfn)
- start = start_pfn;
-
- if (end <= start)
- BUG();
-
- if (end - start >= bootmap_pages)
- bootmap_pfn = start;
- else
- BUG();
-
- return bootmap_pfn;
-}
-
-/*
- * Scan the memory info structure and pull out:
- * - the end of memory
- * - the number of nodes
- * - the pfn range of each node
- * - the number of bootmem bitmap pages
- */
-static void __init
-find_memend_and_nodes(struct meminfo *mi, struct node_info *np)
-{
- unsigned int memend_pfn = 0;
-
- nodes_clear(node_online_map);
- node_set_online(0);
-
- np->bootmap_pages = 0;
-
- if (mi->bank->size == 0) {
- BUG();
- }
-
- /*
- * Get the start and end pfns for this bank
- */
- np->start = PFN_UP(mi->bank->start);
- np->end = PFN_DOWN(mi->bank->start + mi->bank->size);
-
- if (memend_pfn < np->end)
- memend_pfn = np->end;
-
- /*
- * Calculate the number of pages we require to
- * store the bootmem bitmaps.
- */
- np->bootmap_pages = bootmem_bootmap_pages(np->end - np->start);
-
- /*
- * This doesn't seem to be used by the Linux memory
- * manager any more. If we can get rid of it, we
- * also get rid of some of the stuff above as well.
- */
- max_low_pfn = memend_pfn - PFN_DOWN(PHYS_OFFSET);
- max_pfn = memend_pfn - PFN_DOWN(PHYS_OFFSET);
- mi->end = memend_pfn << PAGE_SHIFT;
-
-}
-
-/*
- * Initialise the bootmem allocator for all nodes. This is called
- * early during the architecture specific initialisation.
- */
-void __init bootmem_init(struct meminfo *mi)
-{
- struct node_info node_info;
- unsigned int bootmap_pfn;
- pg_data_t *pgdat = NODE_DATA(0);
-
- find_memend_and_nodes(mi, &node_info);
-
- bootmap_pfn = find_bootmap_pfn(mi, node_info.bootmap_pages);
-
- /*
- * Note that node 0 must always have some pages.
- */
- if (node_info.end == 0)
- BUG();
-
- /*
- * Initialise the bootmem allocator.
- */
- init_bootmem_node(pgdat, bootmap_pfn, node_info.start, node_info.end);
-
- /*
- * Register all available RAM in this node with the bootmem allocator.
- */
- free_bootmem_node(pgdat, mi->bank->start, mi->bank->size);
-
- /*
- * Register the kernel text and data with bootmem.
- * Note: with XIP we dont register .text since
- * its in ROM.
- */
-#ifdef CONFIG_XIP_KERNEL
- reserve_bootmem_node(pgdat, __pa(&_sdata), &_end - &_sdata);
-#else
- reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext);
-#endif
-
- /*
- * And don't forget to reserve the allocator bitmap,
- * which will be freed later.
- */
- reserve_bootmem_node(pgdat, bootmap_pfn << PAGE_SHIFT,
- node_info.bootmap_pages << PAGE_SHIFT);
-
- /*
- * These should likewise go elsewhere. They pre-reserve
- * the screen memory region at the start of main system
- * memory. FIXME - screen RAM is not 512K!
- */
- reserve_bootmem_node(pgdat, 0x02000000, 0x00080000);
-
-#ifdef CONFIG_BLK_DEV_INITRD
- initrd_start = phys_initrd_start;
- initrd_end = initrd_start + phys_initrd_size;
-
- /* Achimedes machines only have one node, so initrd is in node 0 */
-#ifdef CONFIG_XIP_KERNEL
- /* Only reserve initrd space if it is in RAM */
- if(initrd_start && initrd_start < 0x03000000){
-#else
- if(initrd_start){
-#endif
- reserve_bootmem_node(pgdat, __pa(initrd_start),
- initrd_end - initrd_start);
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
-
-
-}
-
-/*
- * paging_init() sets up the page tables, initialises the zone memory
- * maps, and sets up the zero page, bad page and bad page tables.
- */
-void __init paging_init(struct meminfo *mi)
-{
- void *zero_page;
- unsigned long zone_size[MAX_NR_ZONES];
- unsigned long zhole_size[MAX_NR_ZONES];
- struct bootmem_data *bdata;
- pg_data_t *pgdat;
- int i;
-
- memcpy(&meminfo, mi, sizeof(meminfo));
-
- /*
- * allocate the zero page. Note that we count on this going ok.
- */
- zero_page = alloc_bootmem_low_pages(PAGE_SIZE);
-
- /*
- * initialise the page tables.
- */
- memtable_init(mi);
- flush_tlb_all();
-
- /*
- * initialise the zones in node 0 (archimedes have only 1 node)
- */
-
- for (i = 0; i < MAX_NR_ZONES; i++) {
- zone_size[i] = 0;
- zhole_size[i] = 0;
- }
-
- pgdat = NODE_DATA(0);
- bdata = pgdat->bdata;
- zone_size[0] = bdata->node_low_pfn -
- (bdata->node_boot_start >> PAGE_SHIFT);
- if (!zone_size[0])
- BUG();
- pgdat->node_mem_map = NULL;
- free_area_init_node(0, pgdat, zone_size,
- bdata->node_boot_start >> PAGE_SHIFT, zhole_size);
-
- /*
- * finish off the bad pages once
- * the mem_map is initialised
- */
- memzero(zero_page, PAGE_SIZE);
- empty_zero_page = virt_to_page(zero_page);
-}
-
-static inline void free_area(unsigned long addr, unsigned long end, char *s)
-{
- unsigned int size = (end - addr) >> 10;
-
- for (; addr < end; addr += PAGE_SIZE) {
- struct page *page = virt_to_page(addr);
- ClearPageReserved(page);
- init_page_count(page);
- free_page(addr);
- totalram_pages++;
- }
-
- if (size && s)
- printk(KERN_INFO "Freeing %s memory: %dK\n", s, size);
-}
-
-/*
- * mem_init() marks the free areas in the mem_map and tells us how much
- * memory is free. This is done after various parts of the system have
- * claimed their memory after the kernel image.
- */
-void __init mem_init(void)
-{
- unsigned int codepages, datapages, initpages;
- pg_data_t *pgdat = NODE_DATA(0);
- extern int sysctl_overcommit_memory;
-
-
- /* Note: data pages includes BSS */
-#ifdef CONFIG_XIP_KERNEL
- codepages = &_endtext - &_text;
- datapages = &_end - &_sdata;
-#else
- codepages = &_etext - &_text;
- datapages = &_end - &_etext;
-#endif
- initpages = &__init_end - &__init_begin;
-
- high_memory = (void *)__va(meminfo.end);
- max_mapnr = virt_to_page(high_memory) - mem_map;
-
- /* this will put all unused low memory onto the freelists */
- if (pgdat->node_spanned_pages != 0)
- totalram_pages += free_all_bootmem_node(pgdat);
-
- num_physpages = meminfo.bank[0].size >> PAGE_SHIFT;
-
- printk(KERN_INFO "Memory: %luMB total\n", num_physpages >> (20 - PAGE_SHIFT));
- printk(KERN_NOTICE "Memory: %luKB available (%dK code, "
- "%dK data, %dK init)\n",
- (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
- codepages >> 10, datapages >> 10, initpages >> 10);
-
- /*
- * Turn on overcommit on tiny machines
- */
- if (PAGE_SIZE >= 16384 && num_physpages <= 128) {
- sysctl_overcommit_memory = OVERCOMMIT_ALWAYS;
- printk("Turning on overcommit\n");
- }
-}
-
-void free_initmem(void){
-#ifndef CONFIG_XIP_KERNEL
- free_area((unsigned long)(&__init_begin),
- (unsigned long)(&__init_end),
- "init");
-#endif
-}
-
-#ifdef CONFIG_BLK_DEV_INITRD
-
-static int keep_initrd;
-
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-#ifdef CONFIG_XIP_KERNEL
- /* Only bin initrd if it is in RAM... */
- if(!keep_initrd && start < 0x03000000)
-#else
- if (!keep_initrd)
-#endif
- free_area(start, end, "initrd");
-}
-
-static int __init keepinitrd_setup(char *__unused)
-{
- keep_initrd = 1;
- return 1;
-}
-
-__setup("keepinitrd", keepinitrd_setup);
-#endif
diff --git a/arch/arm26/mm/memc.c b/arch/arm26/mm/memc.c
deleted file mode 100644
index ffecd85..0000000
--- a/arch/arm26/mm/memc.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * linux/arch/arm26/mm/memc.c
- *
- * Copyright (C) 1998-2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Page table sludge for older ARM processor architectures.
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-
-#include <asm/pgtable.h>
-#include <asm/pgalloc.h>
-#include <asm/page.h>
-#include <asm/memory.h>
-#include <asm/hardware.h>
-
-#include <asm/map.h>
-
-#define MEMC_TABLE_SIZE (256*sizeof(unsigned long))
-
-struct kmem_cache *pte_cache, *pgd_cache;
-int page_nr;
-
-/*
- * Allocate space for a page table and a MEMC table.
- * Note that we place the MEMC
- * table before the page directory. This means we can
- * easily get to both tightly-associated data structures
- * with a single pointer.
- */
-static inline pgd_t *alloc_pgd_table(void)
-{
- void *pg2k = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
-
- if (pg2k)
- pg2k += MEMC_TABLE_SIZE;
-
- return (pgd_t *)pg2k;
-}
-
-/*
- * Free a page table. this function is the counterpart to get_pgd_slow
- * below, not alloc_pgd_table above.
- */
-void free_pgd_slow(pgd_t *pgd)
-{
- unsigned long tbl = (unsigned long)pgd;
-
- tbl -= MEMC_TABLE_SIZE;
-
- kmem_cache_free(pgd_cache, (void *)tbl);
-}
-
-/*
- * Allocate a new pgd and fill it in ready for use
- *
- * A new tasks pgd is completely empty (all pages !present) except for:
- *
- * o The machine vectors at virtual address 0x0
- * o The vmalloc region at the top of address space
- *
- */
-#define FIRST_KERNEL_PGD_NR (FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
-
-pgd_t *get_pgd_slow(struct mm_struct *mm)
-{
- pgd_t *new_pgd, *init_pgd;
- pmd_t *new_pmd, *init_pmd;
- pte_t *new_pte, *init_pte;
-
- new_pgd = alloc_pgd_table();
- if (!new_pgd)
- goto no_pgd;
-
- /*
- * On ARM, first page must always be allocated since it contains
- * the machine vectors.
- */
- new_pmd = pmd_alloc(mm, new_pgd, 0);
- if (!new_pmd)
- goto no_pmd;
-
- new_pte = pte_alloc_map(mm, new_pmd, 0);
- if (!new_pte)
- goto no_pte;
-
- init_pgd = pgd_offset(&init_mm, 0);
- init_pmd = pmd_offset(init_pgd, 0);
- init_pte = pte_offset(init_pmd, 0);
-
- set_pte(new_pte, *init_pte);
- pte_unmap(new_pte);
-
- /*
- * the page table entries are zeroed
- * when the table is created. (see the cache_ctor functions below)
- * Now we need to plonk the kernel (vmalloc) area at the end of
- * the address space. We copy this from the init thread, just like
- * the init_pte we copied above...
- */
- memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
- (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
-
- /* update MEMC tables */
- cpu_memc_update_all(new_pgd);
- return new_pgd;
-
-no_pte:
- pmd_free(new_pmd);
-no_pmd:
- free_pgd_slow(new_pgd);
-no_pgd:
- return NULL;
-}
-
-/*
- * No special code is required here.
- */
-void setup_mm_for_reboot(char mode)
-{
-}
-
-/*
- * This contains the code to setup the memory map on an ARM2/ARM250/ARM3
- * o swapper_pg_dir = 0x0207d000
- * o kernel proper starts at 0x0208000
- * o create (allocate) a pte to contain the machine vectors
- * o populate the pte (points to 0x02078000) (FIXME - is it zeroed?)
- * o populate the init tasks page directory (pgd) with the new pte
- * o zero the rest of the init tasks pgdir (FIXME - what about vmalloc?!)
- */
-void __init memtable_init(struct meminfo *mi)
-{
- pte_t *pte;
- int i;
-
- page_nr = max_low_pfn;
-
- pte = alloc_bootmem_low_pages(PTRS_PER_PTE * sizeof(pte_t));
- pte[0] = mk_pte_phys(PAGE_OFFSET + SCREEN_SIZE, PAGE_READONLY);
- pmd_populate(&init_mm, pmd_offset(swapper_pg_dir, 0), pte);
-
- for (i = 1; i < PTRS_PER_PGD; i++)
- pgd_val(swapper_pg_dir[i]) = 0;
-}
-
-void __init iotable_init(struct map_desc *io_desc)
-{
- /* nothing to do */
-}
-
-/*
- * We never have holes in the memmap
- */
-void __init create_memmap_holes(struct meminfo *mi)
-{
-}
-
-static void pte_cache_ctor(void *pte, struct kmem_cache *cache, unsigned long flags)
-{
- memzero(pte, sizeof(pte_t) * PTRS_PER_PTE);
-}
-
-static void pgd_cache_ctor(void *pgd, struct kmem_cache *cache, unsigned long flags)
-{
- memzero(pgd + MEMC_TABLE_SIZE, USER_PTRS_PER_PGD * sizeof(pgd_t));
-}
-
-void __init pgtable_cache_init(void)
-{
- pte_cache = kmem_cache_create("pte-cache",
- sizeof(pte_t) * PTRS_PER_PTE,
- 0, SLAB_PANIC, pte_cache_ctor);
-
- pgd_cache = kmem_cache_create("pgd-cache", MEMC_TABLE_SIZE +
- sizeof(pgd_t) * PTRS_PER_PGD,
- 0, SLAB_PANIC, pgd_cache_ctor);
-}
diff --git a/arch/arm26/mm/proc-funcs.S b/arch/arm26/mm/proc-funcs.S
deleted file mode 100644
index f9fca52..0000000
--- a/arch/arm26/mm/proc-funcs.S
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * linux/arch/arm26/mm/proc-arm2,3.S
- *
- * Copyright (C) 1997-1999 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * MMU functions for ARM2,3
- *
- * These are the low level assembler for performing cache
- * and memory functions on ARM2, ARM250 and ARM3 processors.
- */
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-#include <asm/asm-offsets.h>
-#include <asm/procinfo.h>
-#include <asm/ptrace.h>
-
-/*
- * MEMC workhorse code. It's both a horse which things it's a pig.
- */
-/*
- * Function: cpu_memc_update_entry(pgd_t *pgd, unsigned long phys_pte, unsigned long addr)
- * Params : pgd Page tables/MEMC mapping
- * : phys_pte physical address, or PTE
- * : addr virtual address
- */
-ENTRY(cpu_memc_update_entry)
- tst r1, #PAGE_PRESENT @ is the page present
- orreq r1, r1, #PAGE_OLD | PAGE_CLEAN
- moveq r2, #0x01f00000
- mov r3, r1, lsr #13 @ convert to physical page nr
- and r3, r3, #0x3fc
- adr ip, memc_phys_table_32
- ldr r3, [ip, r3]
- tst r1, #PAGE_OLD | PAGE_NOT_USER
- biceq r3, r3, #0x200
- tsteq r1, #PAGE_READONLY | PAGE_CLEAN
- biceq r3, r3, #0x300
- mov r2, r2, lsr #15 @ virtual -> nr
- orr r3, r3, r2, lsl #15
- and r2, r2, #0x300
- orr r3, r3, r2, lsl #2
- and r2, r3, #255
- sub r0, r0, #256 * 4
- str r3, [r0, r2, lsl #2]
- strb r3, [r3]
- movs pc, lr
-/*
- * Params : r0 = preserved
- * : r1 = memc table base (preserved)
- * : r2 = page table entry
- * : r3 = preserved
- * : r4 = unused
- * : r5 = memc physical address translation table
- * : ip = virtual address (preserved)
- */
-update_pte:
- mov r4, r2, lsr #13
- and r4, r4, #0x3fc
- ldr r4, [r5, r4] @ covert to MEMC page
-
- tst r2, #PAGE_OLD | PAGE_NOT_USER @ check for MEMC read
- biceq r4, r4, #0x200
- tsteq r2, #PAGE_READONLY | PAGE_CLEAN @ check for MEMC write
- biceq r4, r4, #0x300
-
- orr r4, r4, ip
- and r2, ip, #0x01800000
- orr r4, r4, r2, lsr #13
-
- and r2, r4, #255
- str r4, [r1, r2, lsl #2]
- movs pc, lr
-
-/*
- * Params : r0 = preserved
- * : r1 = memc table base (preserved)
- * : r2 = page table base
- * : r3 = preserved
- * : r4 = unused
- * : r5 = memc physical address translation table
- * : ip = virtual address (updated)
- */
-update_pte_table:
- stmfd sp!, {r0, lr}
- bic r0, r2, #3
-1: ldr r2, [r0], #4 @ get entry
- tst r2, #PAGE_PRESENT @ page present
- blne update_pte @ process pte
- add ip, ip, #32768 @ increment virt addr
- ldr r2, [r0], #4 @ get entry
- tst r2, #PAGE_PRESENT @ page present
- blne update_pte @ process pte
- add ip, ip, #32768 @ increment virt addr
- ldr r2, [r0], #4 @ get entry
- tst r2, #PAGE_PRESENT @ page present
- blne update_pte @ process pte
- add ip, ip, #32768 @ increment virt addr
- ldr r2, [r0], #4 @ get entry
- tst r2, #PAGE_PRESENT @ page present
- blne update_pte @ process pte
- add ip, ip, #32768 @ increment virt addr
- tst ip, #32768 * 31 @ finished?
- bne 1b
- ldmfd sp!, {r0, pc}^
-
-/*
- * Function: cpu_memc_update_all(pgd_t *pgd)
- * Params : pgd Page tables/MEMC mapping
- * Notes : this is optimised for 32k pages
- */
-ENTRY(cpu_memc_update_all)
- stmfd sp!, {r4, r5, lr}
- bl clear_tables
- sub r1, r0, #256 * 4 @ start of MEMC tables
- adr r5, memc_phys_table_32 @ Convert to logical page number
- mov ip, #0 @ virtual address
-1: ldmia r0!, {r2, r3} @ load two pgd entries
- tst r2, #PAGE_PRESENT @ is pgd entry present?
- addeq ip, ip, #1048576 @FIXME - PAGE_PRESENT is for PTEs technically...
- blne update_pte_table
- mov r2, r3
- tst r2, #PAGE_PRESENT @ is pgd entry present?
- addeq ip, ip, #1048576
- blne update_pte_table
- teq ip, #32 * 1048576
- bne 1b
- ldmfd sp!, {r4, r5, pc}^
-
-/*
- * Build the table to map from physical page number to memc page number
- */
- .type memc_phys_table_32, #object
-memc_phys_table_32:
- .irp b7, 0x00, 0x80
- .irp b6, 0x00, 0x02
- .irp b5, 0x00, 0x04
- .irp b4, 0x00, 0x01
-
- .irp b3, 0x00, 0x40
- .irp b2, 0x00, 0x20
- .irp b1, 0x00, 0x10
- .irp b0, 0x00, 0x08
- .long 0x03800300 + \b7 + \b6 + \b5 + \b4 + \b3 + \b2 + \b1 + \b0
- .endr
- .endr
- .endr
- .endr
-
- .endr
- .endr
- .endr
- .endr
- .size memc_phys_table_32, . - memc_phys_table_32
-
-/*
- * helper for cpu_memc_update_all, this clears out all
- * mappings, setting them close to the top of memory,
- * and inaccessible (0x01f00000).
- * Params : r0 = page table pointer
- */
-clear_tables: ldr r1, _arm3_set_pgd - 4
- ldr r2, [r1]
- sub r1, r0, #256 * 4 @ start of MEMC tables
- add r2, r1, r2, lsl #2 @ end of tables
- mov r3, #0x03f00000 @ Default mapping (null mapping)
- orr r3, r3, #0x00000f00
- orr r4, r3, #1
- orr r5, r3, #2
- orr ip, r3, #3
-1: stmia r1!, {r3, r4, r5, ip}
- add r3, r3, #4
- add r4, r4, #4
- add r5, r5, #4
- add ip, ip, #4
- stmia r1!, {r3, r4, r5, ip}
- add r3, r3, #4
- add r4, r4, #4
- add r5, r5, #4
- add ip, ip, #4
- teq r1, r2
- bne 1b
- mov pc, lr
-
-/*
- * Function: *_set_pgd(pgd_t *pgd)
- * Params : pgd New page tables/MEMC mapping
- * Purpose : update MEMC hardware with new mapping
- */
- .word page_nr @ extern - declared in mm-memc.c
-_arm3_set_pgd: mcr p15, 0, r1, c1, c0, 0 @ flush cache
-_arm2_set_pgd: stmfd sp!, {lr}
- ldr r1, _arm3_set_pgd - 4
- ldr r2, [r1]
- sub r0, r0, #256 * 4 @ start of MEMC tables
- add r1, r0, r2, lsl #2 @ end of tables
-1: ldmia r0!, {r2, r3, ip, lr}
- strb r2, [r2]
- strb r3, [r3]
- strb ip, [ip]
- strb lr, [lr]
- ldmia r0!, {r2, r3, ip, lr}
- strb r2, [r2]
- strb r3, [r3]
- strb ip, [ip]
- strb lr, [lr]
- teq r0, r1
- bne 1b
- ldmfd sp!, {pc}^
-
-/*
- * Function: *_proc_init (void)
- * Purpose : Initialise the cache control registers
- */
-_arm3_proc_init:
- mov r0, #0x001f0000
- orr r0, r0, #0x0000ff00
- orr r0, r0, #0x000000ff
- mcr p15, 0, r0, c3, c0 @ ARM3 Cacheable
- mcr p15, 0, r0, c4, c0 @ ARM3 Updateable
- mov r0, #0
- mcr p15, 0, r0, c5, c0 @ ARM3 Disruptive
- mcr p15, 0, r0, c1, c0 @ ARM3 Flush
- mov r0, #3
- mcr p15, 0, r0, c2, c0 @ ARM3 Control
-_arm2_proc_init:
- movs pc, lr
-
-/*
- * Function: *_proc_fin (void)
- * Purpose : Finalise processor (disable caches)
- */
-_arm3_proc_fin: mov r0, #2
- mcr p15, 0, r0, c2, c0
-_arm2_proc_fin: orrs pc, lr, #PSR_I_BIT|PSR_F_BIT
-
-/*
- * Function: *_xchg_1 (int new, volatile void *ptr)
- * Params : new New value to store at...
- * : ptr pointer to byte-wide location
- * Purpose : Performs an exchange operation
- * Returns : Original byte data at 'ptr'
- */
-_arm2_xchg_1: mov r2, pc
- orr r2, r2, #PSR_I_BIT
- teqp r2, #0
- ldrb r2, [r1]
- strb r0, [r1]
- mov r0, r2
- movs pc, lr
-
-_arm3_xchg_1: swpb r0, r0, [r1]
- movs pc, lr
-
-/*
- * Function: *_xchg_4 (int new, volatile void *ptr)
- * Params : new New value to store at...
- * : ptr pointer to word-wide location
- * Purpose : Performs an exchange operation
- * Returns : Original word data at 'ptr'
- */
-_arm2_xchg_4: mov r2, pc
- orr r2, r2, #PSR_I_BIT
- teqp r2, #0
- ldr r2, [r1]
- str r0, [r1]
- mov r0, r2
- movs pc, lr
-
-_arm3_xchg_4: swp r0, r0, [r1]
- movs pc, lr
-
-_arm2_3_check_bugs:
- bics pc, lr, #PSR_F_BIT @ Clear FIQ disable bit
-
-armvlsi_name: .asciz "ARM/VLSI"
-_arm2_name: .asciz "ARM 2"
-_arm250_name: .asciz "ARM 250"
-_arm3_name: .asciz "ARM 3"
-
- .section ".init.text", #alloc, #execinstr
-/*
- * Purpose : Function pointers used to access above functions - all calls
- * come through these
- */
- .globl arm2_processor_functions
-arm2_processor_functions:
- .word _arm2_3_check_bugs
- .word _arm2_proc_init
- .word _arm2_proc_fin
- .word _arm2_set_pgd
- .word _arm2_xchg_1
- .word _arm2_xchg_4
-
-cpu_arm2_info:
- .long armvlsi_name
- .long _arm2_name
-
- .globl arm250_processor_functions
-arm250_processor_functions:
- .word _arm2_3_check_bugs
- .word _arm2_proc_init
- .word _arm2_proc_fin
- .word _arm2_set_pgd
- .word _arm3_xchg_1
- .word _arm3_xchg_4
-
-cpu_arm250_info:
- .long armvlsi_name
- .long _arm250_name
-
- .globl arm3_processor_functions
-arm3_processor_functions:
- .word _arm2_3_check_bugs
- .word _arm3_proc_init
- .word _arm3_proc_fin
- .word _arm3_set_pgd
- .word _arm3_xchg_1
- .word _arm3_xchg_4
-
-cpu_arm3_info:
- .long armvlsi_name
- .long _arm3_name
-
-arm2_arch_name: .asciz "armv1"
-arm3_arch_name: .asciz "armv2"
-arm2_elf_name: .asciz "v1"
-arm3_elf_name: .asciz "v2"
- .align
-
- .section ".proc.info", #alloc, #execinstr
-
- .long 0x41560200
- .long 0xfffffff0
- .long arm2_arch_name
- .long arm2_elf_name
- .long 0
- .long cpu_arm2_info
- .long arm2_processor_functions
-
- .long 0x41560250
- .long 0xfffffff0
- .long arm3_arch_name
- .long arm3_elf_name
- .long 0
- .long cpu_arm250_info
- .long arm250_processor_functions
-
- .long 0x41560300
- .long 0xfffffff0
- .long arm3_arch_name
- .long arm3_elf_name
- .long 0
- .long cpu_arm3_info
- .long arm3_processor_functions
-
diff --git a/arch/arm26/mm/small_page.c b/arch/arm26/mm/small_page.c
deleted file mode 100644
index 3044710..0000000
--- a/arch/arm26/mm/small_page.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * linux/arch/arm26/mm/small_page.c
- *
- * Copyright (C) 1996 Russell King
- * Copyright (C) 2003 Ian Molton
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Changelog:
- * 26/01/1996 RMK Cleaned up various areas to make little more generic
- * 07/02/1999 RMK Support added for 16K and 32K page sizes
- * containing 8K blocks
- * 23/05/2004 IM Fixed to use struct page->lru (thanks wli)
- *
- */
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/smp.h>
-#include <linux/bitops.h>
-
-#include <asm/pgtable.h>
-
-#define PEDANTIC
-
-/*
- * Requirement:
- * We need to be able to allocate naturally aligned memory of finer
- * granularity than the page size. This is typically used for the
- * second level page tables on 32-bit ARMs.
- *
- * FIXME - this comment is *out of date*
- * Theory:
- * We "misuse" the Linux memory management system. We use alloc_page
- * to allocate a page and then mark it as reserved. The Linux memory
- * management system will then ignore the "offset", "next_hash" and
- * "pprev_hash" entries in the mem_map for this page.
- *
- * We then use a bitstring in the "offset" field to mark which segments
- * of the page are in use, and manipulate this as required during the
- * allocation and freeing of these small pages.
- *
- * We also maintain a queue of pages being used for this purpose using
- * the "next_hash" and "pprev_hash" entries of mem_map;
- */
-
-struct order {
- struct list_head queue;
- unsigned int mask; /* (1 << shift) - 1 */
- unsigned int shift; /* (1 << shift) size of page */
- unsigned int block_mask; /* nr_blocks - 1 */
- unsigned int all_used; /* (1 << nr_blocks) - 1 */
-};
-
-
-static struct order orders[] = {
-#if PAGE_SIZE == 32768
- { LIST_HEAD_INIT(orders[0].queue), 2047, 11, 15, 0x0000ffff },
- { LIST_HEAD_INIT(orders[1].queue), 8191, 13, 3, 0x0000000f }
-#else
-#error unsupported page size (ARGH!)
-#endif
-};
-
-#define USED_MAP(pg) ((pg)->index)
-#define TEST_AND_CLEAR_USED(pg,off) (test_and_clear_bit(off, &USED_MAP(pg)))
-#define SET_USED(pg,off) (set_bit(off, &USED_MAP(pg)))
-
-static DEFINE_SPINLOCK(small_page_lock);
-
-static unsigned long __get_small_page(int priority, struct order *order)
-{
- unsigned long flags;
- struct page *page;
- int offset;
-
- do {
- spin_lock_irqsave(&small_page_lock, flags);
-
- if (list_empty(&order->queue))
- goto need_new_page;
-
- page = list_entry(order->queue.next, struct page, lru);
-again:
-#ifdef PEDANTIC
- BUG_ON(USED_MAP(page) & ~order->all_used);
-#endif
- offset = ffz(USED_MAP(page));
- SET_USED(page, offset);
- if (USED_MAP(page) == order->all_used)
- list_del_init(&page->lru);
- spin_unlock_irqrestore(&small_page_lock, flags);
-
- return (unsigned long) page_address(page) + (offset << order->shift);
-
-need_new_page:
- spin_unlock_irqrestore(&small_page_lock, flags);
- page = alloc_page(priority);
- spin_lock_irqsave(&small_page_lock, flags);
-
- if (list_empty(&order->queue)) {
- if (!page)
- goto no_page;
- SetPageReserved(page);
- USED_MAP(page) = 0;
- list_add(&page->lru, &order->queue);
- goto again;
- }
-
- spin_unlock_irqrestore(&small_page_lock, flags);
- __free_page(page);
- } while (1);
-
-no_page:
- spin_unlock_irqrestore(&small_page_lock, flags);
- return 0;
-}
-
-static void __free_small_page(unsigned long spage, struct order *order)
-{
- unsigned long flags;
- struct page *page;
-
- if (virt_addr_valid(spage)) {
- page = virt_to_page(spage);
-
- /*
- * The container-page must be marked Reserved
- */
- if (!PageReserved(page) || spage & order->mask)
- goto non_small;
-
-#ifdef PEDANTIC
- BUG_ON(USED_MAP(page) & ~order->all_used);
-#endif
-
- spage = spage >> order->shift;
- spage &= order->block_mask;
-
- /*
- * the following must be atomic wrt get_page
- */
- spin_lock_irqsave(&small_page_lock, flags);
-
- if (USED_MAP(page) == order->all_used)
- list_add(&page->lru, &order->queue);
-
- if (!TEST_AND_CLEAR_USED(page, spage))
- goto already_free;
-
- if (USED_MAP(page) == 0)
- goto free_page;
-
- spin_unlock_irqrestore(&small_page_lock, flags);
- }
- return;
-
-free_page:
- /*
- * unlink the page from the small page queue and free it
- */
- list_del_init(&page->lru);
- spin_unlock_irqrestore(&small_page_lock, flags);
- ClearPageReserved(page);
- __free_page(page);
- return;
-
-non_small:
- printk("Trying to free non-small page from %p\n", __builtin_return_address(0));
- return;
-already_free:
- printk("Trying to free free small page from %p\n", __builtin_return_address(0));
-}
-
-unsigned long get_page_8k(int priority)
-{
- return __get_small_page(priority, orders+1);
-}
-
-void free_page_8k(unsigned long spage)
-{
- __free_small_page(spage, orders+1);
-}
OpenPOWER on IntegriCloud