m68k: merge m68k and m68knommu arch directories

There is a lot of common code that could be shared between the m68k
and m68knommu arch branches. It makes sense to merge the two branches
into a single directory structure so that we can more easily share
that common code.

This is a brute force merge, based on a script from Stephen King
<sfking@fdwdc.com>, which was originally written by Arnd Bergmann
<arnd@arndb.de>.

> The script was inspired by the script Sam Ravnborg used to merge the
> includes from m68knommu. For those files common to both arches but
> differing in content, the m68k version of the file is renamed to
> <file>_mm.<ext> and the m68knommu version of the file is moved into the
> corresponding m68k directory and renamed <file>_no.<ext> and a small
> wrapper file <file>.<ext> is used to select between the two version. Files
> that are common to both but don't differ are removed from the m68knommu
> tree and files and directories that are unique to the m68knommu tree are
> moved to the m68k tree. Finally, the arch/m68knommu tree is removed.
>
> To select between the the versions of the files, the wrapper uses
>
> #ifdef CONFIG_MMU
> #include <file>_mm.<ext>
> #else
> #include <file>_no.<ext>
> #endif

On top of this file merge I have done a simplistic merge of m68k and
m68knommu Kconfig, which primarily attempts to keep existing options and
menus in place. Other than a handful of options being moved it produces
identical .config outputs on m68k and m68knommu targets I tested it on.

With this in place there is now quite a bit of scope for merge cleanups
in future patches.

Signed-off-by: Greg Ungerer <gerg@uclinux.org>
Tento commit je obsažen v:
Greg Ungerer
2011-03-22 13:39:27 +10:00
rodič d39dd11c3e
revize 66d857b08b
170 změnil soubory, kde provedl 6916 přidání a 7131 odebrání

Zobrazit soubor

@@ -1,8 +1,5 @@
#
# Makefile for the linux m68k-specific parts of the memory manager.
#
obj-y := cache.o init.o fault.o hwtest.o
obj-$(CONFIG_MMU_MOTOROLA) += kmap.o memory.o motorola.o
obj-$(CONFIG_MMU_SUN3) += sun3kmap.o sun3mmu.o
ifdef CONFIG_MMU
include arch/m68k/mm/Makefile_mm
else
include arch/m68k/mm/Makefile_no
endif

8
arch/m68k/mm/Makefile_mm Normální soubor
Zobrazit soubor

@@ -0,0 +1,8 @@
#
# Makefile for the linux m68k-specific parts of the memory manager.
#
obj-y := cache.o init.o fault.o hwtest.o
obj-$(CONFIG_MMU_MOTOROLA) += kmap.o memory.o motorola.o
obj-$(CONFIG_MMU_SUN3) += sun3kmap.o sun3mmu.o

5
arch/m68k/mm/Makefile_no Normální soubor
Zobrazit soubor

@@ -0,0 +1,5 @@
#
# Makefile for the linux m68knommu specific parts of the memory manager.
#
obj-y += init.o kmap.o

Zobrazit soubor

@@ -1,150 +1,5 @@
/*
* linux/arch/m68k/mm/init.c
*
* Copyright (C) 1995 Hamish Macdonald
*
* Contains common initialization routines, specific init code moved
* to motorola.c and sun3mmu.c
*/
#include <linux/module.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/gfp.h>
#include <asm/setup.h>
#include <asm/uaccess.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/system.h>
#include <asm/machdep.h>
#include <asm/io.h>
#ifdef CONFIG_ATARI
#include <asm/atari_stram.h>
#endif
#include <asm/sections.h>
#include <asm/tlb.h>
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
pg_data_t pg_data_map[MAX_NUMNODES];
EXPORT_SYMBOL(pg_data_map);
int m68k_virt_to_node_shift;
#ifndef CONFIG_SINGLE_MEMORY_CHUNK
pg_data_t *pg_data_table[65];
EXPORT_SYMBOL(pg_data_table);
#endif
void __init m68k_setup_node(int node)
{
#ifndef CONFIG_SINGLE_MEMORY_CHUNK
struct mem_info *info = m68k_memory + node;
int i, end;
i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift();
for (; i <= end; i++) {
if (pg_data_table[i])
printk("overlap at %u for chunk %u\n", i, node);
pg_data_table[i] = pg_data_map + node;
}
#endif
pg_data_map[node].bdata = bootmem_node_data + node;
node_set_online(node);
}
/*
* ZERO_PAGE is a special page that is used for zero-initialized
* data and COW.
*/
void *empty_zero_page;
EXPORT_SYMBOL(empty_zero_page);
extern void init_pointer_table(unsigned long ptable);
/* References to section boundaries */
extern pmd_t *zero_pgtable;
void __init mem_init(void)
{
pg_data_t *pgdat;
int codepages = 0;
int datapages = 0;
int initpages = 0;
int i;
#ifdef CONFIG_ATARI
if (MACH_IS_ATARI)
atari_stram_mem_init_hook();
#endif
/* this will put all memory onto the freelists */
totalram_pages = num_physpages = 0;
for_each_online_pgdat(pgdat) {
num_physpages += pgdat->node_present_pages;
totalram_pages += free_all_bootmem_node(pgdat);
for (i = 0; i < pgdat->node_spanned_pages; i++) {
struct page *page = pgdat->node_mem_map + i;
char *addr = page_to_virt(page);
if (!PageReserved(page))
continue;
if (addr >= _text &&
addr < _etext)
codepages++;
else if (addr >= __init_begin &&
addr < __init_end)
initpages++;
else
datapages++;
}
}
#ifndef CONFIG_SUN3
/* insert pointer tables allocated so far into the tablelist */
init_pointer_table((unsigned long)kernel_pg_dir);
for (i = 0; i < PTRS_PER_PGD; i++) {
if (pgd_present(kernel_pg_dir[i]))
init_pointer_table(__pgd_page(kernel_pg_dir[i]));
}
/* insert also pointer table that we used to unmap the zero page */
if (zero_pgtable)
init_pointer_table((unsigned long)zero_pgtable);
#endif
printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
nr_free_pages() << (PAGE_SHIFT-10),
totalram_pages << (PAGE_SHIFT-10),
codepages << (PAGE_SHIFT-10),
datapages << (PAGE_SHIFT-10),
initpages << (PAGE_SHIFT-10));
}
#ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end)
{
int pages = 0;
for (; start < end; start += PAGE_SIZE) {
ClearPageReserved(virt_to_page(start));
init_page_count(virt_to_page(start));
free_page(start);
totalram_pages++;
pages++;
}
printk ("Freeing initrd memory: %dk freed\n", pages);
}
#ifdef CONFIG_MMU
#include "init_mm.c"
#else
#include "init_no.c"
#endif

150
arch/m68k/mm/init_mm.c Normální soubor
Zobrazit soubor

@@ -0,0 +1,150 @@
/*
* linux/arch/m68k/mm/init.c
*
* Copyright (C) 1995 Hamish Macdonald
*
* Contains common initialization routines, specific init code moved
* to motorola.c and sun3mmu.c
*/
#include <linux/module.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/gfp.h>
#include <asm/setup.h>
#include <asm/uaccess.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/system.h>
#include <asm/machdep.h>
#include <asm/io.h>
#ifdef CONFIG_ATARI
#include <asm/atari_stram.h>
#endif
#include <asm/sections.h>
#include <asm/tlb.h>
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
pg_data_t pg_data_map[MAX_NUMNODES];
EXPORT_SYMBOL(pg_data_map);
int m68k_virt_to_node_shift;
#ifndef CONFIG_SINGLE_MEMORY_CHUNK
pg_data_t *pg_data_table[65];
EXPORT_SYMBOL(pg_data_table);
#endif
void __init m68k_setup_node(int node)
{
#ifndef CONFIG_SINGLE_MEMORY_CHUNK
struct mem_info *info = m68k_memory + node;
int i, end;
i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift();
for (; i <= end; i++) {
if (pg_data_table[i])
printk("overlap at %u for chunk %u\n", i, node);
pg_data_table[i] = pg_data_map + node;
}
#endif
pg_data_map[node].bdata = bootmem_node_data + node;
node_set_online(node);
}
/*
* ZERO_PAGE is a special page that is used for zero-initialized
* data and COW.
*/
void *empty_zero_page;
EXPORT_SYMBOL(empty_zero_page);
extern void init_pointer_table(unsigned long ptable);
/* References to section boundaries */
extern pmd_t *zero_pgtable;
void __init mem_init(void)
{
pg_data_t *pgdat;
int codepages = 0;
int datapages = 0;
int initpages = 0;
int i;
#ifdef CONFIG_ATARI
if (MACH_IS_ATARI)
atari_stram_mem_init_hook();
#endif
/* this will put all memory onto the freelists */
totalram_pages = num_physpages = 0;
for_each_online_pgdat(pgdat) {
num_physpages += pgdat->node_present_pages;
totalram_pages += free_all_bootmem_node(pgdat);
for (i = 0; i < pgdat->node_spanned_pages; i++) {
struct page *page = pgdat->node_mem_map + i;
char *addr = page_to_virt(page);
if (!PageReserved(page))
continue;
if (addr >= _text &&
addr < _etext)
codepages++;
else if (addr >= __init_begin &&
addr < __init_end)
initpages++;
else
datapages++;
}
}
#ifndef CONFIG_SUN3
/* insert pointer tables allocated so far into the tablelist */
init_pointer_table((unsigned long)kernel_pg_dir);
for (i = 0; i < PTRS_PER_PGD; i++) {
if (pgd_present(kernel_pg_dir[i]))
init_pointer_table(__pgd_page(kernel_pg_dir[i]));
}
/* insert also pointer table that we used to unmap the zero page */
if (zero_pgtable)
init_pointer_table((unsigned long)zero_pgtable);
#endif
printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
nr_free_pages() << (PAGE_SHIFT-10),
totalram_pages << (PAGE_SHIFT-10),
codepages << (PAGE_SHIFT-10),
datapages << (PAGE_SHIFT-10),
initpages << (PAGE_SHIFT-10));
}
#ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end)
{
int pages = 0;
for (; start < end; start += PAGE_SIZE) {
ClearPageReserved(virt_to_page(start));
init_page_count(virt_to_page(start));
free_page(start);
totalram_pages++;
pages++;
}
printk ("Freeing initrd memory: %dk freed\n", pages);
}
#endif

193
arch/m68k/mm/init_no.c Normální soubor
Zobrazit soubor

@@ -0,0 +1,193 @@
/*
* linux/arch/m68knommu/mm/init.c
*
* Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
* Kenneth Albanowski <kjahds@kjahds.com>,
* Copyright (C) 2000 Lineo, Inc. (www.lineo.com)
*
* Based on:
*
* linux/arch/m68k/mm/init.c
*
* Copyright (C) 1995 Hamish Macdonald
*
* JAN/1999 -- hacked to support ColdFire (gerg@snapgear.com)
* DEC/2000 -- linux 2.4 support <davidm@snapgear.com>
*/
#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/init.h>
#include <linux/highmem.h>
#include <linux/pagemap.h>
#include <linux/bootmem.h>
#include <linux/gfp.h>
#include <asm/setup.h>
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/machdep.h>
#undef DEBUG
extern void die_if_kernel(char *,struct pt_regs *,long);
extern void free_initmem(void);
/*
* BAD_PAGE is the page that is used for page faults when linux
* is out-of-memory. Older versions of linux just did a
* do_exit(), but using this instead means there is less risk
* for a process dying in kernel mode, possibly leaving a inode
* unused etc..
*
* BAD_PAGETABLE is the accompanying page-table: it is initialized
* to point to BAD_PAGE entries.
*
* ZERO_PAGE is a special page that is used for zero-initialized
* data and COW.
*/
static unsigned long empty_bad_page_table;
static unsigned long empty_bad_page;
unsigned long empty_zero_page;
extern unsigned long memory_start;
extern unsigned long memory_end;
/*
* paging_init() continues the virtual memory environment setup which
* was begun by the code in arch/head.S.
* The parameters are pointers to where to stick the starting and ending
* addresses of available kernel virtual memory.
*/
void __init paging_init(void)
{
/*
* Make sure start_mem is page aligned, otherwise bootmem and
* page_alloc get different views of the world.
*/
#ifdef DEBUG
unsigned long start_mem = PAGE_ALIGN(memory_start);
#endif
unsigned long end_mem = memory_end & PAGE_MASK;
#ifdef DEBUG
printk (KERN_DEBUG "start_mem is %#lx\nvirtual_end is %#lx\n",
start_mem, end_mem);
#endif
/*
* Initialize the bad page table and bad page to point
* to a couple of allocated pages.
*/
empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
memset((void *)empty_zero_page, 0, PAGE_SIZE);
/*
* Set up SFC/DFC registers (user data space).
*/
set_fs (USER_DS);
#ifdef DEBUG
printk (KERN_DEBUG "before free_area_init\n");
printk (KERN_DEBUG "free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n",
start_mem, end_mem);
#endif
{
unsigned long zones_size[MAX_NR_ZONES] = {0, };
zones_size[ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
free_area_init(zones_size);
}
}
void __init mem_init(void)
{
int codek = 0, datak = 0, initk = 0;
unsigned long tmp;
extern char _etext, _stext, _sdata, _ebss, __init_begin, __init_end;
extern unsigned int _ramend, _rambase;
unsigned long len = _ramend - _rambase;
unsigned long start_mem = memory_start; /* DAVIDM - these must start at end of kernel */
unsigned long end_mem = memory_end; /* DAVIDM - this must not include kernel stack at top */
pr_debug("Mem_init: start=%lx, end=%lx\n", start_mem, end_mem);
end_mem &= PAGE_MASK;
high_memory = (void *) end_mem;
start_mem = PAGE_ALIGN(start_mem);
max_mapnr = num_physpages = (((unsigned long) high_memory) - PAGE_OFFSET) >> PAGE_SHIFT;
/* this will put all memory onto the freelists */
totalram_pages = free_all_bootmem();
codek = (&_etext - &_stext) >> 10;
datak = (&_ebss - &_sdata) >> 10;
initk = (&__init_begin - &__init_end) >> 10;
tmp = nr_free_pages() << PAGE_SHIFT;
printk(KERN_INFO "Memory available: %luk/%luk RAM, (%dk kernel code, %dk data)\n",
tmp >> 10,
len >> 10,
codek,
datak
);
}
#ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end)
{
int pages = 0;
for (; start < end; start += PAGE_SIZE) {
ClearPageReserved(virt_to_page(start));
init_page_count(virt_to_page(start));
free_page(start);
totalram_pages++;
pages++;
}
printk (KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages * (PAGE_SIZE / 1024));
}
#endif
void
free_initmem()
{
#ifdef CONFIG_RAMKERNEL
unsigned long addr;
extern char __init_begin, __init_end;
/*
* The following code should be cool even if these sections
* are not page aligned.
*/
addr = PAGE_ALIGN((unsigned long)(&__init_begin));
/* next to check that the page we free is not a partial page */
for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) {
ClearPageReserved(virt_to_page(addr));
init_page_count(virt_to_page(addr));
free_page(addr);
totalram_pages++;
}
printk(KERN_NOTICE "Freeing unused kernel memory: %ldk freed (0x%x - 0x%x)\n",
(addr - PAGE_ALIGN((long) &__init_begin)) >> 10,
(int)(PAGE_ALIGN((unsigned long)(&__init_begin))),
(int)(addr - PAGE_SIZE));
#endif
}

Zobrazit soubor

@@ -1,367 +1,5 @@
/*
* linux/arch/m68k/mm/kmap.c
*
* Copyright (C) 1997 Roman Hodek
*
* 10/01/99 cleaned up the code and changing to the same interface
* used by other architectures /Roman Zippel
*/
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <asm/setup.h>
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/io.h>
#include <asm/system.h>
#undef DEBUG
#define PTRTREESIZE (256*1024)
/*
* For 040/060 we can use the virtual memory area like other architectures,
* but for 020/030 we want to use early termination page descriptor and we
* can't mix this with normal page descriptors, so we have to copy that code
* (mm/vmalloc.c) and return appriorate aligned addresses.
*/
#ifdef CPU_M68040_OR_M68060_ONLY
#define IO_SIZE PAGE_SIZE
static inline struct vm_struct *get_io_area(unsigned long size)
{
return get_vm_area(size, VM_IOREMAP);
}
static inline void free_io_area(void *addr)
{
vfree((void *)(PAGE_MASK & (unsigned long)addr));
}
#ifdef CONFIG_MMU
#include "kmap_mm.c"
#else
#define IO_SIZE (256*1024)
static struct vm_struct *iolist;
static struct vm_struct *get_io_area(unsigned long size)
{
unsigned long addr;
struct vm_struct **p, *tmp, *area;
area = kmalloc(sizeof(*area), GFP_KERNEL);
if (!area)
return NULL;
addr = KMAP_START;
for (p = &iolist; (tmp = *p) ; p = &tmp->next) {
if (size + addr < (unsigned long)tmp->addr)
break;
if (addr > KMAP_END-size) {
kfree(area);
return NULL;
}
addr = tmp->size + (unsigned long)tmp->addr;
}
area->addr = (void *)addr;
area->size = size + IO_SIZE;
area->next = *p;
*p = area;
return area;
}
static inline void free_io_area(void *addr)
{
struct vm_struct **p, *tmp;
if (!addr)
return;
addr = (void *)((unsigned long)addr & -IO_SIZE);
for (p = &iolist ; (tmp = *p) ; p = &tmp->next) {
if (tmp->addr == addr) {
*p = tmp->next;
__iounmap(tmp->addr, tmp->size);
kfree(tmp);
return;
}
}
}
#include "kmap_no.c"
#endif
/*
* Map some physical address range into the kernel address space.
*/
/* Rewritten by Andreas Schwab to remove all races. */
void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
{
struct vm_struct *area;
unsigned long virtaddr, retaddr;
long offset;
pgd_t *pgd_dir;
pmd_t *pmd_dir;
pte_t *pte_dir;
/*
* Don't allow mappings that wrap..
*/
if (!size || physaddr > (unsigned long)(-size))
return NULL;
#ifdef CONFIG_AMIGA
if (MACH_IS_AMIGA) {
if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000)
&& (cacheflag == IOMAP_NOCACHE_SER))
return (void __iomem *)physaddr;
}
#endif
#ifdef DEBUG
printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag);
#endif
/*
* Mappings have to be aligned
*/
offset = physaddr & (IO_SIZE - 1);
physaddr &= -IO_SIZE;
size = (size + offset + IO_SIZE - 1) & -IO_SIZE;
/*
* Ok, go for it..
*/
area = get_io_area(size);
if (!area)
return NULL;
virtaddr = (unsigned long)area->addr;
retaddr = virtaddr + offset;
#ifdef DEBUG
printk("0x%lx,0x%lx,0x%lx", physaddr, virtaddr, retaddr);
#endif
/*
* add cache and table flags to physical address
*/
if (CPU_IS_040_OR_060) {
physaddr |= (_PAGE_PRESENT | _PAGE_GLOBAL040 |
_PAGE_ACCESSED | _PAGE_DIRTY);
switch (cacheflag) {
case IOMAP_FULL_CACHING:
physaddr |= _PAGE_CACHE040;
break;
case IOMAP_NOCACHE_SER:
default:
physaddr |= _PAGE_NOCACHE_S;
break;
case IOMAP_NOCACHE_NONSER:
physaddr |= _PAGE_NOCACHE;
break;
case IOMAP_WRITETHROUGH:
physaddr |= _PAGE_CACHE040W;
break;
}
} else {
physaddr |= (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
switch (cacheflag) {
case IOMAP_NOCACHE_SER:
case IOMAP_NOCACHE_NONSER:
default:
physaddr |= _PAGE_NOCACHE030;
break;
case IOMAP_FULL_CACHING:
case IOMAP_WRITETHROUGH:
break;
}
}
while ((long)size > 0) {
#ifdef DEBUG
if (!(virtaddr & (PTRTREESIZE-1)))
printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr);
#endif
pgd_dir = pgd_offset_k(virtaddr);
pmd_dir = pmd_alloc(&init_mm, pgd_dir, virtaddr);
if (!pmd_dir) {
printk("ioremap: no mem for pmd_dir\n");
return NULL;
}
if (CPU_IS_020_OR_030) {
pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr;
physaddr += PTRTREESIZE;
virtaddr += PTRTREESIZE;
size -= PTRTREESIZE;
} else {
pte_dir = pte_alloc_kernel(pmd_dir, virtaddr);
if (!pte_dir) {
printk("ioremap: no mem for pte_dir\n");
return NULL;
}
pte_val(*pte_dir) = physaddr;
virtaddr += PAGE_SIZE;
physaddr += PAGE_SIZE;
size -= PAGE_SIZE;
}
}
#ifdef DEBUG
printk("\n");
#endif
flush_tlb_all();
return (void __iomem *)retaddr;
}
EXPORT_SYMBOL(__ioremap);
/*
* Unmap a ioremap()ed region again
*/
void iounmap(void __iomem *addr)
{
#ifdef CONFIG_AMIGA
if ((!MACH_IS_AMIGA) ||
(((unsigned long)addr < 0x40000000) ||
((unsigned long)addr > 0x60000000)))
free_io_area((__force void *)addr);
#else
free_io_area((__force void *)addr);
#endif
}
EXPORT_SYMBOL(iounmap);
/*
* __iounmap unmaps nearly everything, so be careful
* it doesn't free currently pointer/page tables anymore but it
* wans't used anyway and might be added later.
*/
void __iounmap(void *addr, unsigned long size)
{
unsigned long virtaddr = (unsigned long)addr;
pgd_t *pgd_dir;
pmd_t *pmd_dir;
pte_t *pte_dir;
while ((long)size > 0) {
pgd_dir = pgd_offset_k(virtaddr);
if (pgd_bad(*pgd_dir)) {
printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
pgd_clear(pgd_dir);
return;
}
pmd_dir = pmd_offset(pgd_dir, virtaddr);
if (CPU_IS_020_OR_030) {
int pmd_off = (virtaddr/PTRTREESIZE) & 15;
int pmd_type = pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK;
if (pmd_type == _PAGE_PRESENT) {
pmd_dir->pmd[pmd_off] = 0;
virtaddr += PTRTREESIZE;
size -= PTRTREESIZE;
continue;
} else if (pmd_type == 0)
continue;
}
if (pmd_bad(*pmd_dir)) {
printk("iounmap: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
pmd_clear(pmd_dir);
return;
}
pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
pte_val(*pte_dir) = 0;
virtaddr += PAGE_SIZE;
size -= PAGE_SIZE;
}
flush_tlb_all();
}
/*
* Set new cache mode for some kernel address space.
* The caller must push data for that range itself, if such data may already
* be in the cache.
*/
void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
{
unsigned long virtaddr = (unsigned long)addr;
pgd_t *pgd_dir;
pmd_t *pmd_dir;
pte_t *pte_dir;
if (CPU_IS_040_OR_060) {
switch (cmode) {
case IOMAP_FULL_CACHING:
cmode = _PAGE_CACHE040;
break;
case IOMAP_NOCACHE_SER:
default:
cmode = _PAGE_NOCACHE_S;
break;
case IOMAP_NOCACHE_NONSER:
cmode = _PAGE_NOCACHE;
break;
case IOMAP_WRITETHROUGH:
cmode = _PAGE_CACHE040W;
break;
}
} else {
switch (cmode) {
case IOMAP_NOCACHE_SER:
case IOMAP_NOCACHE_NONSER:
default:
cmode = _PAGE_NOCACHE030;
break;
case IOMAP_FULL_CACHING:
case IOMAP_WRITETHROUGH:
cmode = 0;
}
}
while ((long)size > 0) {
pgd_dir = pgd_offset_k(virtaddr);
if (pgd_bad(*pgd_dir)) {
printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
pgd_clear(pgd_dir);
return;
}
pmd_dir = pmd_offset(pgd_dir, virtaddr);
if (CPU_IS_020_OR_030) {
int pmd_off = (virtaddr/PTRTREESIZE) & 15;
if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
pmd_dir->pmd[pmd_off] = (pmd_dir->pmd[pmd_off] &
_CACHEMASK040) | cmode;
virtaddr += PTRTREESIZE;
size -= PTRTREESIZE;
continue;
}
}
if (pmd_bad(*pmd_dir)) {
printk("iocachemode: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
pmd_clear(pmd_dir);
return;
}
pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
pte_val(*pte_dir) = (pte_val(*pte_dir) & _CACHEMASK040) | cmode;
virtaddr += PAGE_SIZE;
size -= PAGE_SIZE;
}
flush_tlb_all();
}
EXPORT_SYMBOL(kernel_set_cachemode);

367
arch/m68k/mm/kmap_mm.c Normální soubor
Zobrazit soubor

@@ -0,0 +1,367 @@
/*
* linux/arch/m68k/mm/kmap.c
*
* Copyright (C) 1997 Roman Hodek
*
* 10/01/99 cleaned up the code and changing to the same interface
* used by other architectures /Roman Zippel
*/
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <asm/setup.h>
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/io.h>
#include <asm/system.h>
#undef DEBUG
#define PTRTREESIZE (256*1024)
/*
* For 040/060 we can use the virtual memory area like other architectures,
* but for 020/030 we want to use early termination page descriptor and we
* can't mix this with normal page descriptors, so we have to copy that code
* (mm/vmalloc.c) and return appriorate aligned addresses.
*/
#ifdef CPU_M68040_OR_M68060_ONLY
#define IO_SIZE PAGE_SIZE
static inline struct vm_struct *get_io_area(unsigned long size)
{
return get_vm_area(size, VM_IOREMAP);
}
static inline void free_io_area(void *addr)
{
vfree((void *)(PAGE_MASK & (unsigned long)addr));
}
#else
#define IO_SIZE (256*1024)
static struct vm_struct *iolist;
static struct vm_struct *get_io_area(unsigned long size)
{
unsigned long addr;
struct vm_struct **p, *tmp, *area;
area = kmalloc(sizeof(*area), GFP_KERNEL);
if (!area)
return NULL;
addr = KMAP_START;
for (p = &iolist; (tmp = *p) ; p = &tmp->next) {
if (size + addr < (unsigned long)tmp->addr)
break;
if (addr > KMAP_END-size) {
kfree(area);
return NULL;
}
addr = tmp->size + (unsigned long)tmp->addr;
}
area->addr = (void *)addr;
area->size = size + IO_SIZE;
area->next = *p;
*p = area;
return area;
}
static inline void free_io_area(void *addr)
{
struct vm_struct **p, *tmp;
if (!addr)
return;
addr = (void *)((unsigned long)addr & -IO_SIZE);
for (p = &iolist ; (tmp = *p) ; p = &tmp->next) {
if (tmp->addr == addr) {
*p = tmp->next;
__iounmap(tmp->addr, tmp->size);
kfree(tmp);
return;
}
}
}
#endif
/*
* Map some physical address range into the kernel address space.
*/
/* Rewritten by Andreas Schwab to remove all races. */
void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
{
struct vm_struct *area;
unsigned long virtaddr, retaddr;
long offset;
pgd_t *pgd_dir;
pmd_t *pmd_dir;
pte_t *pte_dir;
/*
* Don't allow mappings that wrap..
*/
if (!size || physaddr > (unsigned long)(-size))
return NULL;
#ifdef CONFIG_AMIGA
if (MACH_IS_AMIGA) {
if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000)
&& (cacheflag == IOMAP_NOCACHE_SER))
return (void __iomem *)physaddr;
}
#endif
#ifdef DEBUG
printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag);
#endif
/*
* Mappings have to be aligned
*/
offset = physaddr & (IO_SIZE - 1);
physaddr &= -IO_SIZE;
size = (size + offset + IO_SIZE - 1) & -IO_SIZE;
/*
* Ok, go for it..
*/
area = get_io_area(size);
if (!area)
return NULL;
virtaddr = (unsigned long)area->addr;
retaddr = virtaddr + offset;
#ifdef DEBUG
printk("0x%lx,0x%lx,0x%lx", physaddr, virtaddr, retaddr);
#endif
/*
* add cache and table flags to physical address
*/
if (CPU_IS_040_OR_060) {
physaddr |= (_PAGE_PRESENT | _PAGE_GLOBAL040 |
_PAGE_ACCESSED | _PAGE_DIRTY);
switch (cacheflag) {
case IOMAP_FULL_CACHING:
physaddr |= _PAGE_CACHE040;
break;
case IOMAP_NOCACHE_SER:
default:
physaddr |= _PAGE_NOCACHE_S;
break;
case IOMAP_NOCACHE_NONSER:
physaddr |= _PAGE_NOCACHE;
break;
case IOMAP_WRITETHROUGH:
physaddr |= _PAGE_CACHE040W;
break;
}
} else {
physaddr |= (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
switch (cacheflag) {
case IOMAP_NOCACHE_SER:
case IOMAP_NOCACHE_NONSER:
default:
physaddr |= _PAGE_NOCACHE030;
break;
case IOMAP_FULL_CACHING:
case IOMAP_WRITETHROUGH:
break;
}
}
while ((long)size > 0) {
#ifdef DEBUG
if (!(virtaddr & (PTRTREESIZE-1)))
printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr);
#endif
pgd_dir = pgd_offset_k(virtaddr);
pmd_dir = pmd_alloc(&init_mm, pgd_dir, virtaddr);
if (!pmd_dir) {
printk("ioremap: no mem for pmd_dir\n");
return NULL;
}
if (CPU_IS_020_OR_030) {
pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr;
physaddr += PTRTREESIZE;
virtaddr += PTRTREESIZE;
size -= PTRTREESIZE;
} else {
pte_dir = pte_alloc_kernel(pmd_dir, virtaddr);
if (!pte_dir) {
printk("ioremap: no mem for pte_dir\n");
return NULL;
}
pte_val(*pte_dir) = physaddr;
virtaddr += PAGE_SIZE;
physaddr += PAGE_SIZE;
size -= PAGE_SIZE;
}
}
#ifdef DEBUG
printk("\n");
#endif
flush_tlb_all();
return (void __iomem *)retaddr;
}
EXPORT_SYMBOL(__ioremap);
/*
* Unmap a ioremap()ed region again
*/
void iounmap(void __iomem *addr)
{
#ifdef CONFIG_AMIGA
if ((!MACH_IS_AMIGA) ||
(((unsigned long)addr < 0x40000000) ||
((unsigned long)addr > 0x60000000)))
free_io_area((__force void *)addr);
#else
free_io_area((__force void *)addr);
#endif
}
EXPORT_SYMBOL(iounmap);
/*
* __iounmap unmaps nearly everything, so be careful
* it doesn't free currently pointer/page tables anymore but it
* wans't used anyway and might be added later.
*/
void __iounmap(void *addr, unsigned long size)
{
unsigned long virtaddr = (unsigned long)addr;
pgd_t *pgd_dir;
pmd_t *pmd_dir;
pte_t *pte_dir;
while ((long)size > 0) {
pgd_dir = pgd_offset_k(virtaddr);
if (pgd_bad(*pgd_dir)) {
printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
pgd_clear(pgd_dir);
return;
}
pmd_dir = pmd_offset(pgd_dir, virtaddr);
if (CPU_IS_020_OR_030) {
int pmd_off = (virtaddr/PTRTREESIZE) & 15;
int pmd_type = pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK;
if (pmd_type == _PAGE_PRESENT) {
pmd_dir->pmd[pmd_off] = 0;
virtaddr += PTRTREESIZE;
size -= PTRTREESIZE;
continue;
} else if (pmd_type == 0)
continue;
}
if (pmd_bad(*pmd_dir)) {
printk("iounmap: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
pmd_clear(pmd_dir);
return;
}
pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
pte_val(*pte_dir) = 0;
virtaddr += PAGE_SIZE;
size -= PAGE_SIZE;
}
flush_tlb_all();
}
/*
* Set new cache mode for some kernel address space.
* The caller must push data for that range itself, if such data may already
* be in the cache.
*/
void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
{
unsigned long virtaddr = (unsigned long)addr;
pgd_t *pgd_dir;
pmd_t *pmd_dir;
pte_t *pte_dir;
if (CPU_IS_040_OR_060) {
switch (cmode) {
case IOMAP_FULL_CACHING:
cmode = _PAGE_CACHE040;
break;
case IOMAP_NOCACHE_SER:
default:
cmode = _PAGE_NOCACHE_S;
break;
case IOMAP_NOCACHE_NONSER:
cmode = _PAGE_NOCACHE;
break;
case IOMAP_WRITETHROUGH:
cmode = _PAGE_CACHE040W;
break;
}
} else {
switch (cmode) {
case IOMAP_NOCACHE_SER:
case IOMAP_NOCACHE_NONSER:
default:
cmode = _PAGE_NOCACHE030;
break;
case IOMAP_FULL_CACHING:
case IOMAP_WRITETHROUGH:
cmode = 0;
}
}
while ((long)size > 0) {
pgd_dir = pgd_offset_k(virtaddr);
if (pgd_bad(*pgd_dir)) {
printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
pgd_clear(pgd_dir);
return;
}
pmd_dir = pmd_offset(pgd_dir, virtaddr);
if (CPU_IS_020_OR_030) {
int pmd_off = (virtaddr/PTRTREESIZE) & 15;
if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
pmd_dir->pmd[pmd_off] = (pmd_dir->pmd[pmd_off] &
_CACHEMASK040) | cmode;
virtaddr += PTRTREESIZE;
size -= PTRTREESIZE;
continue;
}
}
if (pmd_bad(*pmd_dir)) {
printk("iocachemode: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
pmd_clear(pmd_dir);
return;
}
pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
pte_val(*pte_dir) = (pte_val(*pte_dir) & _CACHEMASK040) | cmode;
virtaddr += PAGE_SIZE;
size -= PAGE_SIZE;
}
flush_tlb_all();
}
EXPORT_SYMBOL(kernel_set_cachemode);

45
arch/m68k/mm/kmap_no.c Normální soubor
Zobrazit soubor

@@ -0,0 +1,45 @@
/*
* linux/arch/m68knommu/mm/kmap.c
*
* Copyright (C) 2000 Lineo, <davidm@snapgear.com>
* Copyright (C) 2000-2002 David McCullough <davidm@snapgear.com>
*/
#include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/vmalloc.h>
#include <asm/setup.h>
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/io.h>
#include <asm/system.h>
#undef DEBUG
/*
* Map some physical address range into the kernel address space.
*/
void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
{
return (void *)physaddr;
}
/*
* Unmap a ioremap()ed region again.
*/
void iounmap(void *addr)
{
}
/*
* Set new cache mode for some kernel address space.
* The caller must push data for that range itself, if such data may already
* be in the cache.
*/
void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
{
}