Commit b50f1704e9c441c58cf6dc05e72953ca30e1d4d2

Authored by GuanXuetao
1 parent f73670e8a5

unicore32 core architecture: mm related: generic codes

This patch includes generic codes for memory management.

Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>

Showing 13 changed files with 1390 additions and 0 deletions Side-by-side Diff

arch/unicore32/include/asm/cache.h
  1 +/*
  2 + * linux/arch/unicore32/include/asm/cache.h
  3 + *
  4 + * Code specific to PKUnity SoC and UniCore ISA
  5 + *
  6 + * Copyright (C) 2001-2010 GUAN Xue-tao
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License version 2 as
  10 + * published by the Free Software Foundation.
  11 + */
  12 +#ifndef __UNICORE_CACHE_H__
  13 +#define __UNICORE_CACHE_H__
  14 +
  15 +#define L1_CACHE_SHIFT (5)
  16 +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
  17 +
  18 +/*
  19 + * Memory returned by kmalloc() may be used for DMA, so we must make
  20 + * sure that all such allocations are cache aligned. Otherwise,
  21 + * unrelated code may cause parts of the buffer to be read into the
  22 + * cache before the transfer is done, causing old data to be seen by
  23 + * the CPU.
  24 + */
  25 +#define ARCH_DMA_MINALIGN L1_CACHE_BYTES
  26 +
  27 +#endif
arch/unicore32/include/asm/memblock.h
  1 +/*
  2 + * linux/arch/unicore32/include/asm/memblock.h
  3 + *
  4 + * Code specific to PKUnity SoC and UniCore ISA
  5 + *
  6 + * Copyright (C) 2001-2010 GUAN Xue-tao
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License version 2 as
  10 + * published by the Free Software Foundation.
  11 + */
  12 +
  13 +#ifndef __UNICORE_MEMBLOCK_H__
  14 +#define __UNICORE_MEMBLOCK_H__
  15 +
  16 +/*
  17 + * Memory map description
  18 + */
  19 +# define NR_BANKS 8
  20 +
  21 +struct membank {
  22 + unsigned long start;
  23 + unsigned long size;
  24 + unsigned int highmem;
  25 +};
  26 +
  27 +struct meminfo {
  28 + int nr_banks;
  29 + struct membank bank[NR_BANKS];
  30 +};
  31 +
  32 +extern struct meminfo meminfo;
  33 +
  34 +#define for_each_bank(iter, mi) \
  35 + for (iter = 0; iter < (mi)->nr_banks; iter++)
  36 +
  37 +#define bank_pfn_start(bank) __phys_to_pfn((bank)->start)
  38 +#define bank_pfn_end(bank) __phys_to_pfn((bank)->start + (bank)->size)
  39 +#define bank_pfn_size(bank) ((bank)->size >> PAGE_SHIFT)
  40 +#define bank_phys_start(bank) ((bank)->start)
  41 +#define bank_phys_end(bank) ((bank)->start + (bank)->size)
  42 +#define bank_phys_size(bank) ((bank)->size)
  43 +
  44 +extern void uc32_memblock_init(struct meminfo *);
  45 +
  46 +#endif
arch/unicore32/include/asm/memory.h
  1 +/*
  2 + * linux/arch/unicore32/include/asm/memory.h
  3 + *
  4 + * Code specific to PKUnity SoC and UniCore ISA
  5 + *
  6 + * Copyright (C) 2001-2010 GUAN Xue-tao
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License version 2 as
  10 + * published by the Free Software Foundation.
  11 + *
  12 + * Note: this file should not be included by non-asm/.h files
  13 + */
  14 +#ifndef __UNICORE_MEMORY_H__
  15 +#define __UNICORE_MEMORY_H__
  16 +
  17 +#include <linux/compiler.h>
  18 +#include <linux/const.h>
  19 +#include <asm/sizes.h>
  20 +#include <mach/memory.h>
  21 +
  22 +/*
  23 + * Allow for constants defined here to be used from assembly code
  24 + * by prepending the UL suffix only with actual C code compilation.
  25 + */
  26 +#define UL(x) _AC(x, UL)
  27 +
  28 +/*
  29 + * PAGE_OFFSET - the virtual address of the start of the kernel image
  30 + * TASK_SIZE - the maximum size of a user space task.
  31 + * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area
  32 + */
  33 +#define PAGE_OFFSET UL(0xC0000000)
  34 +#define TASK_SIZE (PAGE_OFFSET - UL(0x41000000))
  35 +#define TASK_UNMAPPED_BASE (PAGE_OFFSET / 3)
  36 +
  37 +/*
  38 + * The module space lives between the addresses given by TASK_SIZE
  39 + * and PAGE_OFFSET - it must be within 32MB of the kernel text.
  40 + */
  41 +#define MODULES_VADDR (PAGE_OFFSET - 16*1024*1024)
  42 +#if TASK_SIZE > MODULES_VADDR
  43 +#error Top of user space clashes with start of module space
  44 +#endif
  45 +
  46 +#define MODULES_END (PAGE_OFFSET)
  47 +
  48 +/*
  49 + * Allow 16MB-aligned ioremap pages
  50 + */
  51 +#define IOREMAP_MAX_ORDER 24
  52 +
  53 +/*
  54 + * Physical vs virtual RAM address space conversion. These are
  55 + * private definitions which should NOT be used outside memory.h
  56 + * files. Use virt_to_phys/phys_to_virt/__pa/__va instead.
  57 + */
  58 +#ifndef __virt_to_phys
  59 +#define __virt_to_phys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
  60 +#define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET)
  61 +#endif
  62 +
  63 +/*
  64 + * Convert a physical address to a Page Frame Number and back
  65 + */
  66 +#define __phys_to_pfn(paddr) ((paddr) >> PAGE_SHIFT)
  67 +#define __pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT)
  68 +
  69 +/*
  70 + * Convert a page to/from a physical address
  71 + */
  72 +#define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page)))
  73 +#define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys)))
  74 +
  75 +#ifndef __ASSEMBLY__
  76 +
  77 +#ifndef arch_adjust_zones
  78 +#define arch_adjust_zones(size, holes) do { } while (0)
  79 +#endif
  80 +
  81 +/*
  82 + * PFNs are used to describe any physical page; this means
  83 + * PFN 0 == physical address 0.
  84 + *
  85 + * This is the PFN of the first RAM page in the kernel
  86 + * direct-mapped view. We assume this is the first page
  87 + * of RAM in the mem_map as well.
  88 + */
  89 +#define PHYS_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT)
  90 +
  91 +/*
  92 + * Drivers should NOT use these either.
  93 + */
  94 +#define __pa(x) __virt_to_phys((unsigned long)(x))
  95 +#define __va(x) ((void *)__phys_to_virt((unsigned long)(x)))
  96 +#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
  97 +
  98 +/*
  99 + * Conversion between a struct page and a physical address.
  100 + *
  101 + * Note: when converting an unknown physical address to a
  102 + * struct page, the resulting pointer must be validated
  103 + * using VALID_PAGE(). It must return an invalid struct page
  104 + * for any physical address not corresponding to a system
  105 + * RAM address.
  106 + *
  107 + * page_to_pfn(page) convert a struct page * to a PFN number
  108 + * pfn_to_page(pfn) convert a _valid_ PFN number to struct page *
  109 + *
  110 + * virt_to_page(k) convert a _valid_ virtual address to struct page *
  111 + * virt_addr_valid(k) indicates whether a virtual address is valid
  112 + */
  113 +#define ARCH_PFN_OFFSET PHYS_PFN_OFFSET
  114 +
  115 +#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
  116 +#define virt_addr_valid(kaddr) ((unsigned long)(kaddr) >= PAGE_OFFSET && \
  117 + (unsigned long)(kaddr) < (unsigned long)high_memory)
  118 +
  119 +#endif
  120 +
  121 +#include <asm-generic/memory_model.h>
  122 +
  123 +#endif
arch/unicore32/include/asm/page.h
  1 +/*
  2 + * linux/arch/unicore32/include/asm/page.h
  3 + *
  4 + * Code specific to PKUnity SoC and UniCore ISA
  5 + *
  6 + * Copyright (C) 2001-2010 GUAN Xue-tao
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License version 2 as
  10 + * published by the Free Software Foundation.
  11 + */
  12 +#ifndef __UNICORE_PAGE_H__
  13 +#define __UNICORE_PAGE_H__
  14 +
  15 +/* PAGE_SHIFT determines the page size */
  16 +#define PAGE_SHIFT 12
  17 +#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
  18 +#define PAGE_MASK (~(PAGE_SIZE-1))
  19 +
  20 +#ifndef __ASSEMBLY__
  21 +
  22 +struct page;
  23 +struct vm_area_struct;
  24 +
  25 +#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
  26 +extern void copy_page(void *to, const void *from);
  27 +
  28 +#define clear_user_page(page, vaddr, pg) clear_page(page)
  29 +#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
  30 +
  31 +#undef STRICT_MM_TYPECHECKS
  32 +
  33 +#ifdef STRICT_MM_TYPECHECKS
  34 +/*
  35 + * These are used to make use of C type-checking..
  36 + */
  37 +typedef struct { unsigned long pte; } pte_t;
  38 +typedef struct { unsigned long pgd; } pgd_t;
  39 +typedef struct { unsigned long pgprot; } pgprot_t;
  40 +
  41 +#define pte_val(x) ((x).pte)
  42 +#define pgd_val(x) ((x).pgd)
  43 +#define pgprot_val(x) ((x).pgprot)
  44 +
  45 +#define __pte(x) ((pte_t) { (x) })
  46 +#define __pgd(x) ((pgd_t) { (x) })
  47 +#define __pgprot(x) ((pgprot_t) { (x) })
  48 +
  49 +#else
  50 +/*
  51 + * .. while these make it easier on the compiler
  52 + */
  53 +typedef unsigned long pte_t;
  54 +typedef unsigned long pgd_t;
  55 +typedef unsigned long pgprot_t;
  56 +
  57 +#define pte_val(x) (x)
  58 +#define pgd_val(x) (x)
  59 +#define pgprot_val(x) (x)
  60 +
  61 +#define __pte(x) (x)
  62 +#define __pgd(x) (x)
  63 +#define __pgprot(x) (x)
  64 +
  65 +#endif /* STRICT_MM_TYPECHECKS */
  66 +
  67 +typedef struct page *pgtable_t;
  68 +
  69 +extern int pfn_valid(unsigned long);
  70 +
  71 +#include <asm/memory.h>
  72 +
  73 +#endif /* !__ASSEMBLY__ */
  74 +
  75 +#define VM_DATA_DEFAULT_FLAGS \
  76 + (VM_READ | VM_WRITE | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
  77 +
  78 +#include <asm-generic/getorder.h>
  79 +
  80 +#endif
arch/unicore32/include/asm/tlb.h
  1 +/*
  2 + * linux/arch/unicore32/include/asm/tlb.h
  3 + *
  4 + * Code specific to PKUnity SoC and UniCore ISA
  5 + *
  6 + * Copyright (C) 2001-2010 GUAN Xue-tao
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License version 2 as
  10 + * published by the Free Software Foundation.
  11 + */
  12 +#ifndef __UNICORE_TLB_H__
  13 +#define __UNICORE_TLB_H__
  14 +
  15 +#include <asm/cacheflush.h>
  16 +#include <asm/tlbflush.h>
  17 +#include <asm/pgalloc.h>
  18 +
  19 +/*
  20 + * TLB handling. This allows us to remove pages from the page
  21 + * tables, and efficiently handle the TLB issues.
  22 + */
  23 +struct mmu_gather {
  24 + struct mm_struct *mm;
  25 + unsigned int fullmm;
  26 + unsigned long range_start;
  27 + unsigned long range_end;
  28 +};
  29 +
  30 +DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
  31 +
  32 +static inline struct mmu_gather *
  33 +tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
  34 +{
  35 + struct mmu_gather *tlb = &get_cpu_var(mmu_gathers);
  36 +
  37 + tlb->mm = mm;
  38 + tlb->fullmm = full_mm_flush;
  39 +
  40 + return tlb;
  41 +}
  42 +
  43 +static inline void
  44 +tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
  45 +{
  46 + if (tlb->fullmm)
  47 + flush_tlb_mm(tlb->mm);
  48 +
  49 + /* keep the page table cache within bounds */
  50 + check_pgt_cache();
  51 +
  52 + put_cpu_var(mmu_gathers);
  53 +}
  54 +
  55 +/*
  56 + * Memorize the range for the TLB flush.
  57 + */
  58 +static inline void
  59 +tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long addr)
  60 +{
  61 + if (!tlb->fullmm) {
  62 + if (addr < tlb->range_start)
  63 + tlb->range_start = addr;
  64 + if (addr + PAGE_SIZE > tlb->range_end)
  65 + tlb->range_end = addr + PAGE_SIZE;
  66 + }
  67 +}
  68 +
  69 +/*
  70 + * In the case of tlb vma handling, we can optimise these away in the
  71 + * case where we're doing a full MM flush. When we're doing a munmap,
  72 + * the vmas are adjusted to only cover the region to be torn down.
  73 + */
  74 +static inline void
  75 +tlb_start_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
  76 +{
  77 + if (!tlb->fullmm) {
  78 + flush_cache_range(vma, vma->vm_start, vma->vm_end);
  79 + tlb->range_start = TASK_SIZE;
  80 + tlb->range_end = 0;
  81 + }
  82 +}
  83 +
  84 +static inline void
  85 +tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
  86 +{
  87 + if (!tlb->fullmm && tlb->range_end > 0)
  88 + flush_tlb_range(vma, tlb->range_start, tlb->range_end);
  89 +}
  90 +
  91 +#define tlb_remove_page(tlb, page) free_page_and_swap_cache(page)
  92 +#define pte_free_tlb(tlb, ptep, addr) pte_free((tlb)->mm, ptep)
  93 +#define pmd_free_tlb(tlb, pmdp, addr) pmd_free((tlb)->mm, pmdp)
  94 +#define pud_free_tlb(tlb, x, addr) do { } while (0)
  95 +
  96 +#define tlb_migrate_finish(mm) do { } while (0)
  97 +
  98 +#endif
arch/unicore32/include/mach/map.h
  1 +/*
  2 + * linux/arch/unicore32/include/mach/map.h
  3 + *
  4 + * Code specific to PKUnity SoC and UniCore ISA
  5 + *
  6 + * Copyright (C) 2001-2010 GUAN Xue-tao
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License version 2 as
  10 + * published by the Free Software Foundation.
  11 + *
  12 + * Page table mapping constructs and function prototypes
  13 + */
  14 +#define MT_DEVICE 0
  15 +#define MT_DEVICE_CACHED 2
  16 +#define MT_KUSER 7
  17 +#define MT_HIGH_VECTORS 8
  18 +#define MT_MEMORY 9
  19 +#define MT_ROM 10
arch/unicore32/include/mach/memory.h
  1 +/*
  2 + * linux/arch/unicore32/include/mach/memory.h
  3 + *
  4 + * Code specific to PKUnity SoC and UniCore ISA
  5 + *
  6 + * Copyright (C) 2001-2010 GUAN Xue-tao
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License version 2 as
  10 + * published by the Free Software Foundation.
  11 + */
  12 +#ifndef __MACH_PUV3_MEMORY_H__
  13 +#define __MACH_PUV3_MEMORY_H__
  14 +
  15 +#include <mach/hardware.h>
  16 +
  17 +/* Physical DRAM offset. */
  18 +#define PHYS_OFFSET UL(0x00000000)
  19 +/* The base address of exception vectors. */
  20 +#define VECTORS_BASE UL(0xffff0000)
  21 +/* The base address of kuser area. */
  22 +#define KUSER_BASE UL(0x80000000)
  23 +
  24 +#ifdef __ASSEMBLY__
  25 +/* The byte offset of the kernel image in RAM from the start of RAM. */
  26 +#define KERNEL_IMAGE_START 0x00408000
  27 +#endif
  28 +
  29 +#if !defined(__ASSEMBLY__) && defined(CONFIG_PCI)
  30 +
  31 +void puv3_pci_adjust_zones(unsigned long *size, unsigned long *holes);
  32 +
  33 +#define arch_adjust_zones(size, holes) \
  34 + puv3_pci_adjust_zones(size, holes)
  35 +
  36 +#endif
  37 +
  38 +/*
  39 + * PCI controller in PKUnity-3 masks highest 5-bit for upstream channel,
  40 + * so we must limit the DMA allocation within 128M physical memory for
  41 + * supporting PCI devices.
  42 + */
  43 +#define PCI_DMA_THRESHOLD (PHYS_OFFSET + SZ_128M - 1)
  44 +
  45 +#define is_pcibus_device(dev) (dev && \
  46 + (strncmp(dev->bus->name, "pci", 3) == 0))
  47 +
  48 +#define __virt_to_pcibus(x) (__virt_to_phys(x) + PKUNITY_PCIAHB_BASE)
  49 +#define __pcibus_to_virt(x) __phys_to_virt((x) - PKUNITY_PCIAHB_BASE)
  50 +
  51 +/* kuser area */
  52 +#define KUSER_VECPAGE_BASE (KUSER_BASE + UL(0x3fff0000))
  53 +#define KUSER_UNIGFX_BASE (KUSER_BASE + PKUNITY_UNIGFX_MMAP_BASE)
  54 +/* kuser_vecpage (0xbfff0000) is ro, and vectors page (0xffff0000) is rw */
  55 +#define kuser_vecpage_to_vectors(x) ((x) - (KUSER_VECPAGE_BASE) \
  56 + + (VECTORS_BASE))
  57 +
  58 +#endif
arch/unicore32/mm/Kconfig
  1 +comment "Processor Type"
  2 +
  3 +# Select CPU types depending on the architecture selected. This selects
  4 +# which CPUs we support in the kernel image, and the compiler instruction
  5 +# optimiser behaviour.
  6 +
  7 +config CPU_UCV2
  8 + def_bool y
  9 +
  10 +comment "Processor Features"
  11 +
  12 +config CPU_ICACHE_DISABLE
  13 + bool "Disable I-Cache (I-bit)"
  14 + help
  15 + Say Y here to disable the processor instruction cache. Unless
  16 + you have a reason not to or are unsure, say N.
  17 +
  18 +config CPU_DCACHE_DISABLE
  19 + bool "Disable D-Cache (D-bit)"
  20 + help
  21 + Say Y here to disable the processor data cache. Unless
  22 + you have a reason not to or are unsure, say N.
  23 +
  24 +config CPU_DCACHE_WRITETHROUGH
  25 + bool "Force write through D-cache"
  26 + help
  27 + Say Y here to use the data cache in writethrough mode. Unless you
  28 + specifically require this or are unsure, say N.
  29 +
  30 +config CPU_DCACHE_LINE_DISABLE
  31 + bool "Disable D-cache line ops"
  32 + default y
  33 + help
  34 + Say Y here to disable the data cache line operations.
  35 +
  36 +config CPU_TLB_SINGLE_ENTRY_DISABLE
  37 + bool "Disable TLB single entry ops"
  38 + default y
  39 + help
  40 + Say Y here to disable the TLB single entry operations.
  41 +
  42 +config SWIOTLB
  43 + def_bool y
  44 +
  45 +config IOMMU_HELPER
  46 + def_bool SWIOTLB
  47 +
  48 +config NEED_SG_DMA_LENGTH
  49 + def_bool SWIOTLB
arch/unicore32/mm/Makefile
  1 +#
  2 +# Makefile for the linux unicore-specific parts of the memory manager.
  3 +#
  4 +
  5 +obj-y := extable.o fault.o init.o pgd.o mmu.o
  6 +obj-y += iomap.o flush.o ioremap.o
  7 +
  8 +obj-$(CONFIG_SWIOTLB) += dma-swiotlb.o
  9 +
  10 +obj-$(CONFIG_MODULES) += proc-syms.o
  11 +
  12 +obj-$(CONFIG_ALIGNMENT_TRAP) += alignment.o
  13 +
  14 +obj-$(CONFIG_CPU_UCV2) += cache-ucv2.o tlb-ucv2.o proc-ucv2.o
arch/unicore32/mm/init.c
  1 +/*
  2 + * linux/arch/unicore32/mm/init.c
  3 + *
  4 + * Copyright (C) 2010 GUAN Xue-tao
  5 + *
  6 + * This program is free software; you can redistribute it and/or modify
  7 + * it under the terms of the GNU General Public License version 2 as
  8 + * published by the Free Software Foundation.
  9 + */
  10 +#include <linux/kernel.h>
  11 +#include <linux/errno.h>
  12 +#include <linux/swap.h>
  13 +#include <linux/init.h>
  14 +#include <linux/bootmem.h>
  15 +#include <linux/mman.h>
  16 +#include <linux/nodemask.h>
  17 +#include <linux/initrd.h>
  18 +#include <linux/highmem.h>
  19 +#include <linux/gfp.h>
  20 +#include <linux/memblock.h>
  21 +#include <linux/sort.h>
  22 +#include <linux/dma-mapping.h>
  23 +
  24 +#include <asm/sections.h>
  25 +#include <asm/setup.h>
  26 +#include <asm/sizes.h>
  27 +#include <asm/tlb.h>
  28 +#include <mach/map.h>
  29 +
  30 +#include "mm.h"
  31 +
  32 +static unsigned long phys_initrd_start __initdata = 0x01000000;
  33 +static unsigned long phys_initrd_size __initdata = SZ_8M;
  34 +
  35 +static int __init early_initrd(char *p)
  36 +{
  37 + unsigned long start, size;
  38 + char *endp;
  39 +
  40 + start = memparse(p, &endp);
  41 + if (*endp == ',') {
  42 + size = memparse(endp + 1, NULL);
  43 +
  44 + phys_initrd_start = start;
  45 + phys_initrd_size = size;
  46 + }
  47 + return 0;
  48 +}
  49 +early_param("initrd", early_initrd);
  50 +
  51 +/*
  52 + * This keeps memory configuration data used by a couple memory
  53 + * initialization functions, as well as show_mem() for the skipping
  54 + * of holes in the memory map. It is populated by uc32_add_memory().
  55 + */
  56 +struct meminfo meminfo;
  57 +
  58 +void show_mem(void)
  59 +{
  60 + int free = 0, total = 0, reserved = 0;
  61 + int shared = 0, cached = 0, slab = 0, i;
  62 + struct meminfo *mi = &meminfo;
  63 +
  64 + printk(KERN_DEFAULT "Mem-info:\n");
  65 + show_free_areas();
  66 +
  67 + for_each_bank(i, mi) {
  68 + struct membank *bank = &mi->bank[i];
  69 + unsigned int pfn1, pfn2;
  70 + struct page *page, *end;
  71 +
  72 + pfn1 = bank_pfn_start(bank);
  73 + pfn2 = bank_pfn_end(bank);
  74 +
  75 + page = pfn_to_page(pfn1);
  76 + end = pfn_to_page(pfn2 - 1) + 1;
  77 +
  78 + do {
  79 + total++;
  80 + if (PageReserved(page))
  81 + reserved++;
  82 + else if (PageSwapCache(page))
  83 + cached++;
  84 + else if (PageSlab(page))
  85 + slab++;
  86 + else if (!page_count(page))
  87 + free++;
  88 + else
  89 + shared += page_count(page) - 1;
  90 + page++;
  91 + } while (page < end);
  92 + }
  93 +
  94 + printk(KERN_DEFAULT "%d pages of RAM\n", total);
  95 + printk(KERN_DEFAULT "%d free pages\n", free);
  96 + printk(KERN_DEFAULT "%d reserved pages\n", reserved);
  97 + printk(KERN_DEFAULT "%d slab pages\n", slab);
  98 + printk(KERN_DEFAULT "%d pages shared\n", shared);
  99 + printk(KERN_DEFAULT "%d pages swap cached\n", cached);
  100 +}
  101 +
  102 +static void __init find_limits(unsigned long *min, unsigned long *max_low,
  103 + unsigned long *max_high)
  104 +{
  105 + struct meminfo *mi = &meminfo;
  106 + int i;
  107 +
  108 + *min = -1UL;
  109 + *max_low = *max_high = 0;
  110 +
  111 + for_each_bank(i, mi) {
  112 + struct membank *bank = &mi->bank[i];
  113 + unsigned long start, end;
  114 +
  115 + start = bank_pfn_start(bank);
  116 + end = bank_pfn_end(bank);
  117 +
  118 + if (*min > start)
  119 + *min = start;
  120 + if (*max_high < end)
  121 + *max_high = end;
  122 + if (bank->highmem)
  123 + continue;
  124 + if (*max_low < end)
  125 + *max_low = end;
  126 + }
  127 +}
  128 +
  129 +static void __init uc32_bootmem_init(unsigned long start_pfn,
  130 + unsigned long end_pfn)
  131 +{
  132 + struct memblock_region *reg;
  133 + unsigned int boot_pages;
  134 + phys_addr_t bitmap;
  135 + pg_data_t *pgdat;
  136 +
  137 + /*
  138 + * Allocate the bootmem bitmap page. This must be in a region
  139 + * of memory which has already been mapped.
  140 + */
  141 + boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
  142 + bitmap = memblock_alloc_base(boot_pages << PAGE_SHIFT, L1_CACHE_BYTES,
  143 + __pfn_to_phys(end_pfn));
  144 +
  145 + /*
  146 + * Initialise the bootmem allocator, handing the
  147 + * memory banks over to bootmem.
  148 + */
  149 + node_set_online(0);
  150 + pgdat = NODE_DATA(0);
  151 + init_bootmem_node(pgdat, __phys_to_pfn(bitmap), start_pfn, end_pfn);
  152 +
  153 + /* Free the lowmem regions from memblock into bootmem. */
  154 + for_each_memblock(memory, reg) {
  155 + unsigned long start = memblock_region_memory_base_pfn(reg);
  156 + unsigned long end = memblock_region_memory_end_pfn(reg);
  157 +
  158 + if (end >= end_pfn)
  159 + end = end_pfn;
  160 + if (start >= end)
  161 + break;
  162 +
  163 + free_bootmem(__pfn_to_phys(start), (end - start) << PAGE_SHIFT);
  164 + }
  165 +
  166 + /* Reserve the lowmem memblock reserved regions in bootmem. */
  167 + for_each_memblock(reserved, reg) {
  168 + unsigned long start = memblock_region_reserved_base_pfn(reg);
  169 + unsigned long end = memblock_region_reserved_end_pfn(reg);
  170 +
  171 + if (end >= end_pfn)
  172 + end = end_pfn;
  173 + if (start >= end)
  174 + break;
  175 +
  176 + reserve_bootmem(__pfn_to_phys(start),
  177 + (end - start) << PAGE_SHIFT, BOOTMEM_DEFAULT);
  178 + }
  179 +}
  180 +
  181 +static void __init uc32_bootmem_free(unsigned long min, unsigned long max_low,
  182 + unsigned long max_high)
  183 +{
  184 + unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
  185 + struct memblock_region *reg;
  186 +
  187 + /*
  188 + * initialise the zones.
  189 + */
  190 + memset(zone_size, 0, sizeof(zone_size));
  191 +
  192 + /*
  193 + * The memory size has already been determined. If we need
  194 + * to do anything fancy with the allocation of this memory
  195 + * to the zones, now is the time to do it.
  196 + */
  197 + zone_size[0] = max_low - min;
  198 +
  199 + /*
  200 + * Calculate the size of the holes.
  201 + * holes = node_size - sum(bank_sizes)
  202 + */
  203 + memcpy(zhole_size, zone_size, sizeof(zhole_size));
  204 + for_each_memblock(memory, reg) {
  205 + unsigned long start = memblock_region_memory_base_pfn(reg);
  206 + unsigned long end = memblock_region_memory_end_pfn(reg);
  207 +
  208 + if (start < max_low) {
  209 + unsigned long low_end = min(end, max_low);
  210 + zhole_size[0] -= low_end - start;
  211 + }
  212 + }
  213 +
  214 + /*
  215 + * Adjust the sizes according to any special requirements for
  216 + * this machine type.
  217 + */
  218 + arch_adjust_zones(zone_size, zhole_size);
  219 +
  220 + free_area_init_node(0, zone_size, min, zhole_size);
  221 +}
  222 +
  223 +int pfn_valid(unsigned long pfn)
  224 +{
  225 + return memblock_is_memory(pfn << PAGE_SHIFT);
  226 +}
  227 +EXPORT_SYMBOL(pfn_valid);
  228 +
  229 +static void uc32_memory_present(void)
  230 +{
  231 +}
  232 +
  233 +static int __init meminfo_cmp(const void *_a, const void *_b)
  234 +{
  235 + const struct membank *a = _a, *b = _b;
  236 + long cmp = bank_pfn_start(a) - bank_pfn_start(b);
  237 + return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
  238 +}
  239 +
  240 +void __init uc32_memblock_init(struct meminfo *mi)
  241 +{
  242 + int i;
  243 +
  244 + sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]),
  245 + meminfo_cmp, NULL);
  246 +
  247 + memblock_init();
  248 + for (i = 0; i < mi->nr_banks; i++)
  249 + memblock_add(mi->bank[i].start, mi->bank[i].size);
  250 +
  251 + /* Register the kernel text, kernel data and initrd with memblock. */
  252 + memblock_reserve(__pa(_text), _end - _text);
  253 +
  254 +#ifdef CONFIG_BLK_DEV_INITRD
  255 + if (phys_initrd_size) {
  256 + memblock_reserve(phys_initrd_start, phys_initrd_size);
  257 +
  258 + /* Now convert initrd to virtual addresses */
  259 + initrd_start = __phys_to_virt(phys_initrd_start);
  260 + initrd_end = initrd_start + phys_initrd_size;
  261 + }
  262 +#endif
  263 +
  264 + uc32_mm_memblock_reserve();
  265 +
  266 + memblock_analyze();
  267 + memblock_dump_all();
  268 +}
  269 +
  270 +void __init bootmem_init(void)
  271 +{
  272 + unsigned long min, max_low, max_high;
  273 +
  274 + max_low = max_high = 0;
  275 +
  276 + find_limits(&min, &max_low, &max_high);
  277 +
  278 + uc32_bootmem_init(min, max_low);
  279 +
  280 +#ifdef CONFIG_SWIOTLB
  281 + swiotlb_init(1);
  282 +#endif
  283 + /*
  284 + * Sparsemem tries to allocate bootmem in memory_present(),
  285 + * so must be done after the fixed reservations
  286 + */
  287 + uc32_memory_present();
  288 +
  289 + /*
  290 + * sparse_init() needs the bootmem allocator up and running.
  291 + */
  292 + sparse_init();
  293 +
  294 + /*
  295 + * Now free the memory - free_area_init_node needs
  296 + * the sparse mem_map arrays initialized by sparse_init()
  297 + * for memmap_init_zone(), otherwise all PFNs are invalid.
  298 + */
  299 + uc32_bootmem_free(min, max_low, max_high);
  300 +
  301 + high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1;
  302 +
  303 + /*
  304 + * This doesn't seem to be used by the Linux memory manager any
  305 + * more, but is used by ll_rw_block. If we can get rid of it, we
  306 + * also get rid of some of the stuff above as well.
  307 + *
  308 + * Note: max_low_pfn and max_pfn reflect the number of _pages_ in
  309 + * the system, not the maximum PFN.
  310 + */
  311 + max_low_pfn = max_low - PHYS_PFN_OFFSET;
  312 + max_pfn = max_high - PHYS_PFN_OFFSET;
  313 +}
  314 +
  315 +static inline int free_area(unsigned long pfn, unsigned long end, char *s)
  316 +{
  317 + unsigned int pages = 0, size = (end - pfn) << (PAGE_SHIFT - 10);
  318 +
  319 + for (; pfn < end; pfn++) {
  320 + struct page *page = pfn_to_page(pfn);
  321 + ClearPageReserved(page);
  322 + init_page_count(page);
  323 + __free_page(page);
  324 + pages++;
  325 + }
  326 +
  327 + if (size && s)
  328 + printk(KERN_INFO "Freeing %s memory: %dK\n", s, size);
  329 +
  330 + return pages;
  331 +}
  332 +
  333 +static inline void
  334 +free_memmap(unsigned long start_pfn, unsigned long end_pfn)
  335 +{
  336 + struct page *start_pg, *end_pg;
  337 + unsigned long pg, pgend;
  338 +
  339 + /*
  340 + * Convert start_pfn/end_pfn to a struct page pointer.
  341 + */
  342 + start_pg = pfn_to_page(start_pfn - 1) + 1;
  343 + end_pg = pfn_to_page(end_pfn);
  344 +
  345 + /*
  346 + * Convert to physical addresses, and
  347 + * round start upwards and end downwards.
  348 + */
  349 + pg = PAGE_ALIGN(__pa(start_pg));
  350 + pgend = __pa(end_pg) & PAGE_MASK;
  351 +
  352 + /*
  353 + * If there are free pages between these,
  354 + * free the section of the memmap array.
  355 + */
  356 + if (pg < pgend)
  357 + free_bootmem(pg, pgend - pg);
  358 +}
  359 +
  360 +/*
  361 + * The mem_map array can get very big. Free the unused area of the memory map.
  362 + */
  363 +static void __init free_unused_memmap(struct meminfo *mi)
  364 +{
  365 + unsigned long bank_start, prev_bank_end = 0;
  366 + unsigned int i;
  367 +
  368 + /*
  369 + * This relies on each bank being in address order.
  370 + * The banks are sorted previously in bootmem_init().
  371 + */
  372 + for_each_bank(i, mi) {
  373 + struct membank *bank = &mi->bank[i];
  374 +
  375 + bank_start = bank_pfn_start(bank);
  376 +
  377 + /*
  378 + * If we had a previous bank, and there is a space
  379 + * between the current bank and the previous, free it.
  380 + */
  381 + if (prev_bank_end && prev_bank_end < bank_start)
  382 + free_memmap(prev_bank_end, bank_start);
  383 +
  384 + /*
  385 + * Align up here since the VM subsystem insists that the
  386 + * memmap entries are valid from the bank end aligned to
  387 + * MAX_ORDER_NR_PAGES.
  388 + */
  389 + prev_bank_end = ALIGN(bank_pfn_end(bank), MAX_ORDER_NR_PAGES);
  390 + }
  391 +}
  392 +
  393 +/*
  394 + * mem_init() marks the free areas in the mem_map and tells us how much
  395 + * memory is free. This is done after various parts of the system have
  396 + * claimed their memory after the kernel image.
  397 + */
  398 +void __init mem_init(void)
  399 +{
  400 + unsigned long reserved_pages, free_pages;
  401 + struct memblock_region *reg;
  402 + int i;
  403 +
  404 + max_mapnr = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map;
  405 +
  406 + /* this will put all unused low memory onto the freelists */
  407 + free_unused_memmap(&meminfo);
  408 +
  409 + totalram_pages += free_all_bootmem();
  410 +
  411 + reserved_pages = free_pages = 0;
  412 +
  413 + for_each_bank(i, &meminfo) {
  414 + struct membank *bank = &meminfo.bank[i];
  415 + unsigned int pfn1, pfn2;
  416 + struct page *page, *end;
  417 +
  418 + pfn1 = bank_pfn_start(bank);
  419 + pfn2 = bank_pfn_end(bank);
  420 +
  421 + page = pfn_to_page(pfn1);
  422 + end = pfn_to_page(pfn2 - 1) + 1;
  423 +
  424 + do {
  425 + if (PageReserved(page))
  426 + reserved_pages++;
  427 + else if (!page_count(page))
  428 + free_pages++;
  429 + page++;
  430 + } while (page < end);
  431 + }
  432 +
  433 + /*
  434 + * Since our memory may not be contiguous, calculate the
  435 + * real number of pages we have in this system
  436 + */
  437 + printk(KERN_INFO "Memory:");
  438 + num_physpages = 0;
  439 + for_each_memblock(memory, reg) {
  440 + unsigned long pages = memblock_region_memory_end_pfn(reg) -
  441 + memblock_region_memory_base_pfn(reg);
  442 + num_physpages += pages;
  443 + printk(" %ldMB", pages >> (20 - PAGE_SHIFT));
  444 + }
  445 + printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT));
  446 +
  447 + printk(KERN_NOTICE "Memory: %luk/%luk available, %luk reserved, %luK highmem\n",
  448 + nr_free_pages() << (PAGE_SHIFT-10),
  449 + free_pages << (PAGE_SHIFT-10),
  450 + reserved_pages << (PAGE_SHIFT-10),
  451 + totalhigh_pages << (PAGE_SHIFT-10));
  452 +
  453 + printk(KERN_NOTICE "Virtual kernel memory layout:\n"
  454 + " vector : 0x%08lx - 0x%08lx (%4ld kB)\n"
  455 + " vmalloc : 0x%08lx - 0x%08lx (%4ld MB)\n"
  456 + " lowmem : 0x%08lx - 0x%08lx (%4ld MB)\n"
  457 + " modules : 0x%08lx - 0x%08lx (%4ld MB)\n"
  458 + " .init : 0x%p" " - 0x%p" " (%4d kB)\n"
  459 + " .text : 0x%p" " - 0x%p" " (%4d kB)\n"
  460 + " .data : 0x%p" " - 0x%p" " (%4d kB)\n",
  461 +
  462 + VECTORS_BASE, VECTORS_BASE + PAGE_SIZE,
  463 + DIV_ROUND_UP(PAGE_SIZE, SZ_1K),
  464 + VMALLOC_START, VMALLOC_END,
  465 + DIV_ROUND_UP((VMALLOC_END - VMALLOC_START), SZ_1M),
  466 + PAGE_OFFSET, (unsigned long)high_memory,
  467 + DIV_ROUND_UP(((unsigned long)high_memory - PAGE_OFFSET), SZ_1M),
  468 + MODULES_VADDR, MODULES_END,
  469 + DIV_ROUND_UP((MODULES_END - MODULES_VADDR), SZ_1M),
  470 +
  471 + __init_begin, __init_end,
  472 + DIV_ROUND_UP((__init_end - __init_begin), SZ_1K),
  473 + _stext, _etext,
  474 + DIV_ROUND_UP((_etext - _stext), SZ_1K),
  475 + _sdata, _edata,
  476 + DIV_ROUND_UP((_edata - _sdata), SZ_1K));
  477 +
  478 + BUILD_BUG_ON(TASK_SIZE > MODULES_VADDR);
  479 + BUG_ON(TASK_SIZE > MODULES_VADDR);
  480 +
  481 + if (PAGE_SIZE >= 16384 && num_physpages <= 128) {
  482 + /*
  483 + * On a machine this small we won't get
  484 + * anywhere without overcommit, so turn
  485 + * it on by default.
  486 + */
  487 + sysctl_overcommit_memory = OVERCOMMIT_ALWAYS;
  488 + }
  489 +}
  490 +
  491 +void free_initmem(void)
  492 +{
  493 + totalram_pages += free_area(__phys_to_pfn(__pa(__init_begin)),
  494 + __phys_to_pfn(__pa(__init_end)),
  495 + "init");
  496 +}
  497 +
  498 +#ifdef CONFIG_BLK_DEV_INITRD
  499 +
  500 +static int keep_initrd;
  501 +
  502 +void free_initrd_mem(unsigned long start, unsigned long end)
  503 +{
  504 + if (!keep_initrd)
  505 + totalram_pages += free_area(__phys_to_pfn(__pa(start)),
  506 + __phys_to_pfn(__pa(end)),
  507 + "initrd");
  508 +}
  509 +
  510 +static int __init keepinitrd_setup(char *__unused)
  511 +{
  512 + keep_initrd = 1;
  513 + return 1;
  514 +}
  515 +
  516 +__setup("keepinitrd", keepinitrd_setup);
  517 +#endif
arch/unicore32/mm/iomap.c
  1 +/*
  2 + * linux/arch/unicore32/mm/iomap.c
  3 + *
  4 + * Code specific to PKUnity SoC and UniCore ISA
  5 + *
  6 + * Copyright (C) 2001-2010 GUAN Xue-tao
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License version 2 as
  10 + * published by the Free Software Foundation.
  11 + *
  12 + * Map IO port and PCI memory spaces so that {read,write}[bwl] can
  13 + * be used to access this memory.
  14 + */
  15 +#include <linux/module.h>
  16 +#include <linux/pci.h>
  17 +#include <linux/ioport.h>
  18 +#include <linux/io.h>
  19 +
  20 +#ifdef __io
  21 +void __iomem *ioport_map(unsigned long port, unsigned int nr)
  22 +{
  23 + /* we map PC lagcy 64K IO port to PCI IO space 0x80030000 */
  24 + return (void __iomem *) (unsigned long)
  25 + io_p2v((port & 0xffff) + PKUNITY_PCILIO_BASE);
  26 +}
  27 +EXPORT_SYMBOL(ioport_map);
  28 +
  29 +void ioport_unmap(void __iomem *addr)
  30 +{
  31 +}
  32 +EXPORT_SYMBOL(ioport_unmap);
  33 +#endif
  34 +
  35 +#ifdef CONFIG_PCI
  36 +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
  37 +{
  38 + resource_size_t start = pci_resource_start(dev, bar);
  39 + resource_size_t len = pci_resource_len(dev, bar);
  40 + unsigned long flags = pci_resource_flags(dev, bar);
  41 +
  42 + if (!len || !start)
  43 + return NULL;
  44 + if (maxlen && len > maxlen)
  45 + len = maxlen;
  46 + if (flags & IORESOURCE_IO)
  47 + return ioport_map(start, len);
  48 + if (flags & IORESOURCE_MEM) {
  49 + if (flags & IORESOURCE_CACHEABLE)
  50 + return ioremap(start, len);
  51 + return ioremap_nocache(start, len);
  52 + }
  53 + return NULL;
  54 +}
  55 +EXPORT_SYMBOL(pci_iomap);
  56 +#endif
arch/unicore32/mm/ioremap.c
  1 +/*
  2 + * linux/arch/unicore32/mm/ioremap.c
  3 + *
  4 + * Code specific to PKUnity SoC and UniCore ISA
  5 + *
  6 + * Copyright (C) 2001-2010 GUAN Xue-tao
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License version 2 as
  10 + * published by the Free Software Foundation.
  11 + *
  12 + *
  13 + * Re-map IO memory to kernel address space so that we can access it.
  14 + *
  15 + * This allows a driver to remap an arbitrary region of bus memory into
  16 + * virtual space. One should *only* use readl, writel, memcpy_toio and
  17 + * so on with such remapped areas.
  18 + *
  19 + * Because UniCore only has a 32-bit address space we can't address the
  20 + * whole of the (physical) PCI space at once. PCI huge-mode addressing
  21 + * allows us to circumvent this restriction by splitting PCI space into
  22 + * two 2GB chunks and mapping only one at a time into processor memory.
  23 + * We use MMU protection domains to trap any attempt to access the bank
  24 + * that is not currently mapped. (This isn't fully implemented yet.)
  25 + */
  26 +#include <linux/module.h>
  27 +#include <linux/errno.h>
  28 +#include <linux/mm.h>
  29 +#include <linux/vmalloc.h>
  30 +#include <linux/io.h>
  31 +
  32 +#include <asm/cputype.h>
  33 +#include <asm/cacheflush.h>
  34 +#include <asm/mmu_context.h>
  35 +#include <asm/pgalloc.h>
  36 +#include <asm/tlbflush.h>
  37 +#include <asm/sizes.h>
  38 +
  39 +#include <mach/map.h>
  40 +#include "mm.h"
  41 +
  42 +/*
  43 + * Used by ioremap() and iounmap() code to mark (super)section-mapped
  44 + * I/O regions in vm_struct->flags field.
  45 + */
  46 +#define VM_UNICORE_SECTION_MAPPING 0x80000000
  47 +
  48 +int ioremap_page(unsigned long virt, unsigned long phys,
  49 + const struct mem_type *mtype)
  50 +{
  51 + return ioremap_page_range(virt, virt + PAGE_SIZE, phys,
  52 + __pgprot(mtype->prot_pte));
  53 +}
  54 +EXPORT_SYMBOL(ioremap_page);
  55 +
  56 +/*
  57 + * Section support is unsafe on SMP - If you iounmap and ioremap a region,
  58 + * the other CPUs will not see this change until their next context switch.
  59 + * Meanwhile, (eg) if an interrupt comes in on one of those other CPUs
  60 + * which requires the new ioremap'd region to be referenced, the CPU will
  61 + * reference the _old_ region.
  62 + *
  63 + * Note that get_vm_area_caller() allocates a guard 4K page, so we need to
  64 + * mask the size back to 4MB aligned or we will overflow in the loop below.
  65 + */
  66 +static void unmap_area_sections(unsigned long virt, unsigned long size)
  67 +{
  68 + unsigned long addr = virt, end = virt + (size & ~(SZ_4M - 1));
  69 + pgd_t *pgd;
  70 +
  71 + flush_cache_vunmap(addr, end);
  72 + pgd = pgd_offset_k(addr);
  73 + do {
  74 + pmd_t pmd, *pmdp = pmd_offset((pud_t *)pgd, addr);
  75 +
  76 + pmd = *pmdp;
  77 + if (!pmd_none(pmd)) {
  78 + /*
  79 + * Clear the PMD from the page table, and
  80 + * increment the kvm sequence so others
  81 + * notice this change.
  82 + *
  83 + * Note: this is still racy on SMP machines.
  84 + */
  85 + pmd_clear(pmdp);
  86 +
  87 + /*
  88 + * Free the page table, if there was one.
  89 + */
  90 + if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE)
  91 + pte_free_kernel(&init_mm, pmd_page_vaddr(pmd));
  92 + }
  93 +
  94 + addr += PGDIR_SIZE;
  95 + pgd++;
  96 + } while (addr < end);
  97 +
  98 + flush_tlb_kernel_range(virt, end);
  99 +}
  100 +
  101 +static int
  102 +remap_area_sections(unsigned long virt, unsigned long pfn,
  103 + size_t size, const struct mem_type *type)
  104 +{
  105 + unsigned long addr = virt, end = virt + size;
  106 + pgd_t *pgd;
  107 +
  108 + /*
  109 + * Remove and free any PTE-based mapping, and
  110 + * sync the current kernel mapping.
  111 + */
  112 + unmap_area_sections(virt, size);
  113 +
  114 + pgd = pgd_offset_k(addr);
  115 + do {
  116 + pmd_t *pmd = pmd_offset((pud_t *)pgd, addr);
  117 +
  118 + set_pmd(pmd, __pmd(__pfn_to_phys(pfn) | type->prot_sect));
  119 + pfn += SZ_4M >> PAGE_SHIFT;
  120 + flush_pmd_entry(pmd);
  121 +
  122 + addr += PGDIR_SIZE;
  123 + pgd++;
  124 + } while (addr < end);
  125 +
  126 + return 0;
  127 +}
  128 +
  129 +void __iomem *__uc32_ioremap_pfn_caller(unsigned long pfn,
  130 + unsigned long offset, size_t size, unsigned int mtype, void *caller)
  131 +{
  132 + const struct mem_type *type;
  133 + int err;
  134 + unsigned long addr;
  135 + struct vm_struct *area;
  136 +
  137 + /*
  138 + * High mappings must be section aligned
  139 + */
  140 + if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SECTION_MASK))
  141 + return NULL;
  142 +
  143 + /*
  144 + * Don't allow RAM to be mapped
  145 + */
  146 + if (pfn_valid(pfn)) {
  147 + printk(KERN_WARNING "BUG: Your driver calls ioremap() on\n"
  148 + "system memory. This leads to architecturally\n"
  149 + "unpredictable behaviour, and ioremap() will fail in\n"
  150 + "the next kernel release. Please fix your driver.\n");
  151 + WARN_ON(1);
  152 + }
  153 +
  154 + type = get_mem_type(mtype);
  155 + if (!type)
  156 + return NULL;
  157 +
  158 + /*
  159 + * Page align the mapping size, taking account of any offset.
  160 + */
  161 + size = PAGE_ALIGN(offset + size);
  162 +
  163 + area = get_vm_area_caller(size, VM_IOREMAP, caller);
  164 + if (!area)
  165 + return NULL;
  166 + addr = (unsigned long)area->addr;
  167 +
  168 + if (!((__pfn_to_phys(pfn) | size | addr) & ~PMD_MASK)) {
  169 + area->flags |= VM_UNICORE_SECTION_MAPPING;
  170 + err = remap_area_sections(addr, pfn, size, type);
  171 + } else
  172 + err = ioremap_page_range(addr, addr + size, __pfn_to_phys(pfn),
  173 + __pgprot(type->prot_pte));
  174 +
  175 + if (err) {
  176 + vunmap((void *)addr);
  177 + return NULL;
  178 + }
  179 +
  180 + flush_cache_vmap(addr, addr + size);
  181 + return (void __iomem *) (offset + addr);
  182 +}
  183 +
  184 +void __iomem *__uc32_ioremap_caller(unsigned long phys_addr, size_t size,
  185 + unsigned int mtype, void *caller)
  186 +{
  187 + unsigned long last_addr;
  188 + unsigned long offset = phys_addr & ~PAGE_MASK;
  189 + unsigned long pfn = __phys_to_pfn(phys_addr);
  190 +
  191 + /*
  192 + * Don't allow wraparound or zero size
  193 + */
  194 + last_addr = phys_addr + size - 1;
  195 + if (!size || last_addr < phys_addr)
  196 + return NULL;
  197 +
  198 + return __uc32_ioremap_pfn_caller(pfn, offset, size, mtype, caller);
  199 +}
  200 +
  201 +/*
  202 + * Remap an arbitrary physical address space into the kernel virtual
  203 + * address space. Needed when the kernel wants to access high addresses
  204 + * directly.
  205 + *
  206 + * NOTE! We need to allow non-page-aligned mappings too: we will obviously
  207 + * have to convert them into an offset in a page-aligned mapping, but the
  208 + * caller shouldn't need to know that small detail.
  209 + */
  210 +void __iomem *
  211 +__uc32_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
  212 + unsigned int mtype)
  213 +{
  214 + return __uc32_ioremap_pfn_caller(pfn, offset, size, mtype,
  215 + __builtin_return_address(0));
  216 +}
  217 +EXPORT_SYMBOL(__uc32_ioremap_pfn);
  218 +
  219 +void __iomem *
  220 +__uc32_ioremap(unsigned long phys_addr, size_t size)
  221 +{
  222 + return __uc32_ioremap_caller(phys_addr, size, MT_DEVICE,
  223 + __builtin_return_address(0));
  224 +}
  225 +EXPORT_SYMBOL(__uc32_ioremap);
  226 +
  227 +void __iomem *
  228 +__uc32_ioremap_cached(unsigned long phys_addr, size_t size)
  229 +{
  230 + return __uc32_ioremap_caller(phys_addr, size, MT_DEVICE_CACHED,
  231 + __builtin_return_address(0));
  232 +}
  233 +EXPORT_SYMBOL(__uc32_ioremap_cached);
  234 +
  235 +void __uc32_iounmap(volatile void __iomem *io_addr)
  236 +{
  237 + void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
  238 + struct vm_struct **p, *tmp;
  239 +
  240 + /*
  241 + * If this is a section based mapping we need to handle it
  242 + * specially as the VM subsystem does not know how to handle
  243 + * such a beast. We need the lock here b/c we need to clear
  244 + * all the mappings before the area can be reclaimed
  245 + * by someone else.
  246 + */
  247 + write_lock(&vmlist_lock);
  248 + for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
  249 + if ((tmp->flags & VM_IOREMAP) && (tmp->addr == addr)) {
  250 + if (tmp->flags & VM_UNICORE_SECTION_MAPPING) {
  251 + unmap_area_sections((unsigned long)tmp->addr,
  252 + tmp->size);
  253 + }
  254 + break;
  255 + }
  256 + }
  257 + write_unlock(&vmlist_lock);
  258 +
  259 + vunmap(addr);
  260 +}
  261 +EXPORT_SYMBOL(__uc32_iounmap);
arch/unicore32/mm/mm.h
  1 +/*
  2 + * linux/arch/unicore32/mm/mm.h
  3 + *
  4 + * Code specific to PKUnity SoC and UniCore ISA
  5 + *
  6 + * Copyright (C) 2001-2010 GUAN Xue-tao
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License version 2 as
  10 + * published by the Free Software Foundation.
  11 + */
  12 +/* the upper-most page table pointer */
  13 +extern pmd_t *top_pmd;
  14 +extern int sysctl_overcommit_memory;
  15 +
  16 +#define TOP_PTE(x) pte_offset_kernel(top_pmd, x)
  17 +
  18 +static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
  19 +{
  20 + return pmd_offset((pud_t *)pgd, virt);
  21 +}
  22 +
  23 +static inline pmd_t *pmd_off_k(unsigned long virt)
  24 +{
  25 + return pmd_off(pgd_offset_k(virt), virt);
  26 +}
  27 +
  28 +struct mem_type {
  29 + unsigned int prot_pte;
  30 + unsigned int prot_l1;
  31 + unsigned int prot_sect;
  32 +};
  33 +
  34 +const struct mem_type *get_mem_type(unsigned int type);
  35 +
  36 +extern void __flush_dcache_page(struct address_space *, struct page *);
  37 +
  38 +void __init bootmem_init(void);
  39 +void uc32_mm_memblock_reserve(void);