linux/arch/ppc/mm/init.c
<<
>>
Prefs
   1/*
   2 *  PowerPC version
   3 *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
   4 *
   5 *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
   6 *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
   7 *    Copyright (C) 1996 Paul Mackerras
   8 *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
   9 *  PPC44x/36-bit changes by Matt Porter (mporter@mvista.com)
  10 *
  11 *  Derived from "arch/i386/mm/init.c"
  12 *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
  13 *
  14 *  This program is free software; you can redistribute it and/or
  15 *  modify it under the terms of the GNU General Public License
  16 *  as published by the Free Software Foundation; either version
  17 *  2 of the License, or (at your option) any later version.
  18 *
  19 */
  20
  21#include <linux/module.h>
  22#include <linux/sched.h>
  23#include <linux/kernel.h>
  24#include <linux/errno.h>
  25#include <linux/string.h>
  26#include <linux/types.h>
  27#include <linux/mm.h>
  28#include <linux/stddef.h>
  29#include <linux/init.h>
  30#include <linux/bootmem.h>
  31#include <linux/highmem.h>
  32#include <linux/initrd.h>
  33#include <linux/pagemap.h>
  34
  35#include <asm/pgalloc.h>
  36#include <asm/prom.h>
  37#include <asm/io.h>
  38#include <asm/mmu_context.h>
  39#include <asm/pgtable.h>
  40#include <asm/mmu.h>
  41#include <asm/smp.h>
  42#include <asm/machdep.h>
  43#include <asm/btext.h>
  44#include <asm/tlb.h>
  45#include <asm/bootinfo.h>
  46
  47#include "mem_pieces.h"
  48#include "mmu_decl.h"
  49
  50#if defined(CONFIG_KERNEL_START_BOOL) || defined(CONFIG_LOWMEM_SIZE_BOOL)
  51/* The amount of lowmem must be within 0xF0000000 - KERNELBASE. */
  52#if (CONFIG_LOWMEM_SIZE > (0xF0000000 - KERNELBASE))
  53#error "You must adjust CONFIG_LOWMEM_SIZE or CONFIG_START_KERNEL"
  54#endif
  55#endif
  56#define MAX_LOW_MEM     CONFIG_LOWMEM_SIZE
  57
  58DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
  59
  60unsigned long total_memory;
  61unsigned long total_lowmem;
  62
  63unsigned long ppc_memstart;
  64unsigned long ppc_memoffset = PAGE_OFFSET;
  65
  66int mem_init_done;
  67int init_bootmem_done;
  68int boot_mapsize;
  69
  70extern char _end[];
  71extern char etext[], _stext[];
  72extern char __init_begin, __init_end;
  73
  74#ifdef CONFIG_HIGHMEM
  75pte_t *kmap_pte;
  76pgprot_t kmap_prot;
  77
  78EXPORT_SYMBOL(kmap_prot);
  79EXPORT_SYMBOL(kmap_pte);
  80#endif
  81
  82void MMU_init(void);
  83void set_phys_avail(unsigned long total_ram);
  84
  85/* XXX should be in current.h  -- paulus */
  86extern struct task_struct *current_set[NR_CPUS];
  87
  88char *klimit = _end;
  89struct mem_pieces phys_avail;
  90
  91/*
  92 * this tells the system to map all of ram with the segregs
  93 * (i.e. page tables) instead of the bats.
  94 * -- Cort
  95 */
  96int __map_without_bats;
  97int __map_without_ltlbs;
  98
  99/* max amount of RAM to use */
 100unsigned long __max_memory;
 101/* max amount of low RAM to map in */
 102unsigned long __max_low_memory = MAX_LOW_MEM;
 103
 104void show_mem(void)
 105{
 106        int i,free = 0,total = 0,reserved = 0;
 107        int shared = 0, cached = 0;
 108        int highmem = 0;
 109
 110        printk("Mem-info:\n");
 111        show_free_areas();
 112        printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 113        i = max_mapnr;
 114        while (i-- > 0) {
 115                total++;
 116                if (PageHighMem(mem_map+i))
 117                        highmem++;
 118                if (PageReserved(mem_map+i))
 119                        reserved++;
 120                else if (PageSwapCache(mem_map+i))
 121                        cached++;
 122                else if (!page_count(mem_map+i))
 123                        free++;
 124                else
 125                        shared += page_count(mem_map+i) - 1;
 126        }
 127        printk("%d pages of RAM\n",total);
 128        printk("%d pages of HIGHMEM\n", highmem);
 129        printk("%d free pages\n",free);
 130        printk("%d reserved pages\n",reserved);
 131        printk("%d pages shared\n",shared);
 132        printk("%d pages swap cached\n",cached);
 133}
 134
 135/* Free up now-unused memory */
 136static void free_sec(unsigned long start, unsigned long end, const char *name)
 137{
 138        unsigned long cnt = 0;
 139
 140        while (start < end) {
 141                ClearPageReserved(virt_to_page(start));
 142                init_page_count(virt_to_page(start));
 143                free_page(start);
 144                cnt++;
 145                start += PAGE_SIZE;
 146        }
 147        if (cnt) {
 148                printk(" %ldk %s", cnt << (PAGE_SHIFT - 10), name);
 149                totalram_pages += cnt;
 150        }
 151}
 152
 153void free_initmem(void)
 154{
 155#define FREESEC(TYPE) \
 156        free_sec((unsigned long)(&__ ## TYPE ## _begin), \
 157                 (unsigned long)(&__ ## TYPE ## _end), \
 158                 #TYPE);
 159
 160        printk ("Freeing unused kernel memory:");
 161        FREESEC(init);
 162        printk("\n");
 163        ppc_md.progress = NULL;
 164#undef FREESEC
 165}
 166
 167#ifdef CONFIG_BLK_DEV_INITRD
 168void free_initrd_mem(unsigned long start, unsigned long end)
 169{
 170        printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
 171
 172        for (; start < end; start += PAGE_SIZE) {
 173                ClearPageReserved(virt_to_page(start));
 174                init_page_count(virt_to_page(start));
 175                free_page(start);
 176                totalram_pages++;
 177        }
 178}
 179#endif
 180
 181/*
 182 * Check for command-line options that affect what MMU_init will do.
 183 */
 184void MMU_setup(void)
 185{
 186        /* Check for nobats option (used in mapin_ram). */
 187        if (strstr(cmd_line, "nobats")) {
 188                __map_without_bats = 1;
 189        }
 190
 191        if (strstr(cmd_line, "noltlbs")) {
 192                __map_without_ltlbs = 1;
 193        }
 194
 195        /* Look for mem= option on command line */
 196        if (strstr(cmd_line, "mem=")) {
 197                char *p, *q;
 198                unsigned long maxmem = 0;
 199
 200                for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
 201                        q = p + 4;
 202                        if (p > cmd_line && p[-1] != ' ')
 203                                continue;
 204                        maxmem = simple_strtoul(q, &q, 0);
 205                        if (*q == 'k' || *q == 'K') {
 206                                maxmem <<= 10;
 207                                ++q;
 208                        } else if (*q == 'm' || *q == 'M') {
 209                                maxmem <<= 20;
 210                                ++q;
 211                        }
 212                }
 213                __max_memory = maxmem;
 214        }
 215}
 216
 217/*
 218 * MMU_init sets up the basic memory mappings for the kernel,
 219 * including both RAM and possibly some I/O regions,
 220 * and sets up the page tables and the MMU hardware ready to go.
 221 */
 222void __init MMU_init(void)
 223{
 224        if (ppc_md.progress)
 225                ppc_md.progress("MMU:enter", 0x111);
 226
 227        /* parse args from command line */
 228        MMU_setup();
 229
 230        /*
 231         * Figure out how much memory we have, how much
 232         * is lowmem, and how much is highmem.  If we were
 233         * passed the total memory size from the bootloader,
 234         * just use it.
 235         */
 236        if (boot_mem_size)
 237                total_memory = boot_mem_size;
 238        else
 239                total_memory = ppc_md.find_end_of_memory();
 240
 241        if (__max_memory && total_memory > __max_memory)
 242                total_memory = __max_memory;
 243        total_lowmem = total_memory;
 244        if (total_lowmem > __max_low_memory) {
 245                total_lowmem = __max_low_memory;
 246#ifndef CONFIG_HIGHMEM
 247                total_memory = total_lowmem;
 248#endif /* CONFIG_HIGHMEM */
 249        }
 250        set_phys_avail(total_lowmem);
 251
 252        /* Initialize the MMU hardware */
 253        if (ppc_md.progress)
 254                ppc_md.progress("MMU:hw init", 0x300);
 255        MMU_init_hw();
 256
 257        /* Map in all of RAM starting at KERNELBASE */
 258        if (ppc_md.progress)
 259                ppc_md.progress("MMU:mapin", 0x301);
 260        mapin_ram();
 261
 262#ifdef CONFIG_HIGHMEM
 263        ioremap_base = PKMAP_BASE;
 264#else
 265        ioremap_base = 0xfe000000UL;    /* for now, could be 0xfffff000 */
 266#endif /* CONFIG_HIGHMEM */
 267        ioremap_bot = ioremap_base;
 268
 269        /* Map in I/O resources */
 270        if (ppc_md.progress)
 271                ppc_md.progress("MMU:setio", 0x302);
 272        if (ppc_md.setup_io_mappings)
 273                ppc_md.setup_io_mappings();
 274
 275        /* Initialize the context management stuff */
 276        mmu_context_init();
 277
 278        if (ppc_md.progress)
 279                ppc_md.progress("MMU:exit", 0x211);
 280
 281#ifdef CONFIG_BOOTX_TEXT
 282        /* By default, we are no longer mapped */
 283        boot_text_mapped = 0;
 284        /* Must be done last, or ppc_md.progress will die. */
 285        map_boot_text();
 286#endif
 287}
 288
 289/* This is only called until mem_init is done. */
 290void __init *early_get_page(void)
 291{
 292        void *p;
 293
 294        if (init_bootmem_done) {
 295                p = alloc_bootmem_pages(PAGE_SIZE);
 296        } else {
 297                p = mem_pieces_find(PAGE_SIZE, PAGE_SIZE);
 298        }
 299        return p;
 300}
 301
 302/*
 303 * Initialize the bootmem system and give it all the memory we
 304 * have available.
 305 */
 306void __init do_init_bootmem(void)
 307{
 308        unsigned long start, size;
 309        int i;
 310
 311        /*
 312         * Find an area to use for the bootmem bitmap.
 313         * We look for the first area which is at least
 314         * 128kB in length (128kB is enough for a bitmap
 315         * for 4GB of memory, using 4kB pages), plus 1 page
 316         * (in case the address isn't page-aligned).
 317         */
 318        start = 0;
 319        size = 0;
 320        for (i = 0; i < phys_avail.n_regions; ++i) {
 321                unsigned long a = phys_avail.regions[i].address;
 322                unsigned long s = phys_avail.regions[i].size;
 323                if (s <= size)
 324                        continue;
 325                start = a;
 326                size = s;
 327                if (s >= 33 * PAGE_SIZE)
 328                        break;
 329        }
 330        start = PAGE_ALIGN(start);
 331
 332        min_low_pfn = start >> PAGE_SHIFT;
 333        max_low_pfn = (PPC_MEMSTART + total_lowmem) >> PAGE_SHIFT;
 334        max_pfn = (PPC_MEMSTART + total_memory) >> PAGE_SHIFT;
 335        boot_mapsize = init_bootmem_node(&contig_page_data, min_low_pfn,
 336                                         PPC_MEMSTART >> PAGE_SHIFT,
 337                                         max_low_pfn);
 338
 339        /* remove the bootmem bitmap from the available memory */
 340        mem_pieces_remove(&phys_avail, start, boot_mapsize, 1);
 341
 342        /* add everything in phys_avail into the bootmem map */
 343        for (i = 0; i < phys_avail.n_regions; ++i)
 344                free_bootmem(phys_avail.regions[i].address,
 345                             phys_avail.regions[i].size);
 346
 347        init_bootmem_done = 1;
 348}
 349
 350/*
 351 * paging_init() sets up the page tables - in fact we've already done this.
 352 */
 353void __init paging_init(void)
 354{
 355        unsigned long start_pfn, end_pfn;
 356        unsigned long max_zone_pfns[MAX_NR_ZONES];
 357#ifdef CONFIG_HIGHMEM
 358        map_page(PKMAP_BASE, 0, 0);     /* XXX gross */
 359        pkmap_page_table = pte_offset_kernel(pmd_offset(pgd_offset_k
 360                        (PKMAP_BASE), PKMAP_BASE), PKMAP_BASE);
 361        map_page(KMAP_FIX_BEGIN, 0, 0); /* XXX gross */
 362        kmap_pte = pte_offset_kernel(pmd_offset(pgd_offset_k
 363                        (KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN);
 364        kmap_prot = PAGE_KERNEL;
 365#endif /* CONFIG_HIGHMEM */
 366        /* All pages are DMA-able so we put them all in the DMA zone. */
 367        start_pfn = __pa(PAGE_OFFSET) >> PAGE_SHIFT;
 368        end_pfn = start_pfn + (total_memory >> PAGE_SHIFT);
 369        add_active_range(0, start_pfn, end_pfn);
 370
 371        memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
 372#ifdef CONFIG_HIGHMEM
 373        max_zone_pfns[ZONE_DMA] = total_lowmem >> PAGE_SHIFT;
 374        max_zone_pfns[ZONE_HIGHMEM] = total_memory >> PAGE_SHIFT;
 375#else
 376        max_zone_pfns[ZONE_DMA] = total_memory >> PAGE_SHIFT;
 377#endif /* CONFIG_HIGHMEM */
 378        free_area_init_nodes(max_zone_pfns);
 379}
 380
 381void __init mem_init(void)
 382{
 383        unsigned long addr;
 384        int codepages = 0;
 385        int datapages = 0;
 386        int initpages = 0;
 387#ifdef CONFIG_HIGHMEM
 388        unsigned long highmem_mapnr;
 389
 390        highmem_mapnr = total_lowmem >> PAGE_SHIFT;
 391#endif /* CONFIG_HIGHMEM */
 392        max_mapnr = total_memory >> PAGE_SHIFT;
 393
 394        high_memory = (void *) __va(PPC_MEMSTART + total_lowmem);
 395        num_physpages = max_mapnr;      /* RAM is assumed contiguous */
 396
 397        totalram_pages += free_all_bootmem();
 398
 399#ifdef CONFIG_BLK_DEV_INITRD
 400        /* if we are booted from BootX with an initial ramdisk,
 401           make sure the ramdisk pages aren't reserved. */
 402        if (initrd_start) {
 403                for (addr = initrd_start; addr < initrd_end; addr += PAGE_SIZE)
 404                        ClearPageReserved(virt_to_page(addr));
 405        }
 406#endif /* CONFIG_BLK_DEV_INITRD */
 407
 408        for (addr = PAGE_OFFSET; addr < (unsigned long)high_memory;
 409             addr += PAGE_SIZE) {
 410                if (!PageReserved(virt_to_page(addr)))
 411                        continue;
 412                if (addr < (ulong) etext)
 413                        codepages++;
 414                else if (addr >= (unsigned long)&__init_begin
 415                         && addr < (unsigned long)&__init_end)
 416                        initpages++;
 417                else if (addr < (ulong) klimit)
 418                        datapages++;
 419        }
 420
 421#ifdef CONFIG_HIGHMEM
 422        {
 423                unsigned long pfn;
 424
 425                for (pfn = highmem_mapnr; pfn < max_mapnr; ++pfn) {
 426                        struct page *page = mem_map + pfn;
 427
 428                        ClearPageReserved(page);
 429                        init_page_count(page);
 430                        __free_page(page);
 431                        totalhigh_pages++;
 432                }
 433                totalram_pages += totalhigh_pages;
 434        }
 435#endif /* CONFIG_HIGHMEM */
 436
 437        printk("Memory: %luk available (%dk kernel code, %dk data, %dk init, %ldk highmem)\n",
 438               (unsigned long)nr_free_pages()<< (PAGE_SHIFT-10),
 439               codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10),
 440               initpages<< (PAGE_SHIFT-10),
 441               (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
 442
 443        mem_init_done = 1;
 444}
 445
 446/*
 447 * Set phys_avail to the amount of physical memory,
 448 * less the kernel text/data/bss.
 449 */
 450void __init
 451set_phys_avail(unsigned long total_memory)
 452{
 453        unsigned long kstart, ksize;
 454
 455        /*
 456         * Initially, available physical memory is equivalent to all
 457         * physical memory.
 458         */
 459
 460        phys_avail.regions[0].address = PPC_MEMSTART;
 461        phys_avail.regions[0].size = total_memory;
 462        phys_avail.n_regions = 1;
 463
 464        /*
 465         * Map out the kernel text/data/bss from the available physical
 466         * memory.
 467         */
 468
 469        kstart = __pa(_stext);  /* should be 0 */
 470        ksize = PAGE_ALIGN(klimit - _stext);
 471
 472        mem_pieces_remove(&phys_avail, kstart, ksize, 0);
 473        mem_pieces_remove(&phys_avail, 0, 0x4000, 0);
 474
 475#if defined(CONFIG_BLK_DEV_INITRD)
 476        /* Remove the init RAM disk from the available memory. */
 477        if (initrd_start) {
 478                mem_pieces_remove(&phys_avail, __pa(initrd_start),
 479                                  initrd_end - initrd_start, 1);
 480        }
 481#endif /* CONFIG_BLK_DEV_INITRD */
 482}
 483
 484/* Mark some memory as reserved by removing it from phys_avail. */
 485void __init reserve_phys_mem(unsigned long start, unsigned long size)
 486{
 487        mem_pieces_remove(&phys_avail, start, size, 1);
 488}
 489
 490/*
 491 * This is called when a page has been modified by the kernel.
 492 * It just marks the page as not i-cache clean.  We do the i-cache
 493 * flush later when the page is given to a user process, if necessary.
 494 */
 495void flush_dcache_page(struct page *page)
 496{
 497        clear_bit(PG_arch_1, &page->flags);
 498}
 499
 500void flush_dcache_icache_page(struct page *page)
 501{
 502#ifdef CONFIG_BOOKE
 503        void *start = kmap_atomic(page, KM_PPC_SYNC_ICACHE);
 504        __flush_dcache_icache(start);
 505        kunmap_atomic(start, KM_PPC_SYNC_ICACHE);
 506#elif defined(CONFIG_8xx)
 507        /* On 8xx there is no need to kmap since highmem is not supported */
 508        __flush_dcache_icache(page_address(page)); 
 509#else
 510        __flush_dcache_icache_phys(page_to_pfn(page) << PAGE_SHIFT);
 511#endif
 512
 513}
 514void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
 515{
 516        clear_page(page);
 517        clear_bit(PG_arch_1, &pg->flags);
 518}
 519
 520void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
 521                    struct page *pg)
 522{
 523        copy_page(vto, vfrom);
 524        clear_bit(PG_arch_1, &pg->flags);
 525}
 526
 527void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
 528                             unsigned long addr, int len)
 529{
 530        unsigned long maddr;
 531
 532        maddr = (unsigned long) kmap(page) + (addr & ~PAGE_MASK);
 533        flush_icache_range(maddr, maddr + len);
 534        kunmap(page);
 535}
 536
 537/*
 538 * This is called at the end of handling a user page fault, when the
 539 * fault has been handled by updating a PTE in the linux page tables.
 540 * We use it to preload an HPTE into the hash table corresponding to
 541 * the updated linux PTE.
 542 */
 543void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
 544                      pte_t pte)
 545{
 546        /* handle i-cache coherency */
 547        unsigned long pfn = pte_pfn(pte);
 548
 549        if (pfn_valid(pfn)) {
 550                struct page *page = pfn_to_page(pfn);
 551#ifdef CONFIG_8xx
 552                /* On 8xx, the TLB handlers work in 2 stages:
 553                 * First, a zeroed entry is loaded by TLBMiss handler,
 554                 * which causes the TLBError handler to be triggered.
 555                 * That means the zeroed TLB has to be invalidated
 556                 * whenever a page miss occurs.
 557                 */
 558                _tlbie(address, 0 /* 8xx doesn't care about PID */);
 559#endif
 560                if (!PageReserved(page)
 561                    && !test_bit(PG_arch_1, &page->flags)) {
 562                        if (vma->vm_mm == current->active_mm)
 563                                __flush_dcache_icache((void *) address);
 564                        else
 565                                flush_dcache_icache_page(page);
 566                        set_bit(PG_arch_1, &page->flags);
 567                }
 568        }
 569
 570#ifdef CONFIG_PPC_STD_MMU
 571        /* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */
 572        if (Hash != 0 && pte_young(pte)) {
 573                struct mm_struct *mm;
 574                pmd_t *pmd;
 575
 576                mm = (address < TASK_SIZE)? vma->vm_mm: &init_mm;
 577                pmd = pmd_offset(pgd_offset(mm, address), address);
 578                if (!pmd_none(*pmd))
 579                        add_hash_page(mm->context.id, address, pmd_val(*pmd));
 580        }
 581#endif
 582}
 583
 584/*
 585 * This is called by /dev/mem to know if a given address has to
 586 * be mapped non-cacheable or not
 587 */
 588int page_is_ram(unsigned long pfn)
 589{
 590        return pfn < max_pfn;
 591}
 592
 593pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 594                              unsigned long size, pgprot_t vma_prot)
 595{
 596        if (ppc_md.phys_mem_access_prot)
 597                return ppc_md.phys_mem_access_prot(file, pfn, size, vma_prot);
 598
 599        if (!page_is_ram(pfn))
 600                vma_prot = __pgprot(pgprot_val(vma_prot)
 601                                    | _PAGE_GUARDED | _PAGE_NO_CACHE);
 602        return vma_prot;
 603}
 604EXPORT_SYMBOL(phys_mem_access_prot);
 605
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.