linux/arch/sparc64/mm/init.c
<<
>>
Prefs
   1/*  $Id: init.c,v 1.209 2002/02/09 19:49:31 davem Exp $
   2 *  arch/sparc64/mm/init.c
   3 *
   4 *  Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
   5 *  Copyright (C) 1997-1999 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
   6 */
   7 
   8#include <linux/config.h>
   9#include <linux/kernel.h>
  10#include <linux/sched.h>
  11#include <linux/string.h>
  12#include <linux/init.h>
  13#include <linux/bootmem.h>
  14#include <linux/mm.h>
  15#include <linux/hugetlb.h>
  16#include <linux/slab.h>
  17#include <linux/initrd.h>
  18#include <linux/swap.h>
  19#include <linux/pagemap.h>
  20#include <linux/fs.h>
  21#include <linux/seq_file.h>
  22
  23#include <asm/head.h>
  24#include <asm/system.h>
  25#include <asm/page.h>
  26#include <asm/pgalloc.h>
  27#include <asm/pgtable.h>
  28#include <asm/oplib.h>
  29#include <asm/iommu.h>
  30#include <asm/io.h>
  31#include <asm/uaccess.h>
  32#include <asm/mmu_context.h>
  33#include <asm/tlbflush.h>
  34#include <asm/dma.h>
  35#include <asm/starfire.h>
  36#include <asm/tlb.h>
  37#include <asm/spitfire.h>
  38#include <asm/sections.h>
  39
  40extern void device_scan(void);
  41
  42struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
  43
  44unsigned long *sparc64_valid_addr_bitmap;
  45
  46/* Ugly, but necessary... -DaveM */
  47unsigned long phys_base;
  48unsigned long kern_base;
  49unsigned long kern_size;
  50unsigned long pfn_base;
  51
  52/* This is even uglier. We have a problem where the kernel may not be
  53 * located at phys_base. However, initial __alloc_bootmem() calls need to
  54 * be adjusted to be within the 4-8Megs that the kernel is mapped to, else
  55 * those page mappings wont work. Things are ok after inherit_prom_mappings
  56 * is called though. Dave says he'll clean this up some other time.
  57 * -- BenC
  58 */
  59static unsigned long bootmap_base;
  60
  61/* get_new_mmu_context() uses "cache + 1".  */
  62DEFINE_SPINLOCK(ctx_alloc_lock);
  63unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1;
  64#define CTX_BMAP_SLOTS (1UL << (CTX_VERSION_SHIFT - 6))
  65unsigned long mmu_context_bmap[CTX_BMAP_SLOTS];
  66
  67/* References to special section boundaries */
  68extern char  _start[], _end[];
  69
  70/* Initial ramdisk setup */
  71extern unsigned long sparc_ramdisk_image64;
  72extern unsigned int sparc_ramdisk_image;
  73extern unsigned int sparc_ramdisk_size;
  74
  75struct page *mem_map_zero;
  76
  77int bigkernel = 0;
  78
  79/* XXX Tune this... */
  80#define PGT_CACHE_LOW   25
  81#define PGT_CACHE_HIGH  50
  82
  83void check_pgt_cache(void)
  84{
  85        preempt_disable();
  86        if (pgtable_cache_size > PGT_CACHE_HIGH) {
  87                do {
  88#ifdef CONFIG_SMP
  89                        if (pgd_quicklist)
  90                                free_pgd_slow(get_pgd_fast());
  91#endif
  92                        if (pte_quicklist[0])
  93                                free_pte_slow(pte_alloc_one_fast(NULL, 0));
  94                        if (pte_quicklist[1])
  95                                free_pte_slow(pte_alloc_one_fast(NULL, 1 << (PAGE_SHIFT + 10)));
  96                } while (pgtable_cache_size > PGT_CACHE_LOW);
  97        }
  98#ifndef CONFIG_SMP
  99        if (pgd_cache_size > PGT_CACHE_HIGH / 4) {
 100                struct page *page, *page2;
 101                for (page2 = NULL, page = (struct page *)pgd_quicklist; page;) {
 102                        if ((unsigned long)page->lru.prev == 3) {
 103                                if (page2)
 104                                        page2->lru.next = page->lru.next;
 105                                else
 106                                        pgd_quicklist = (void *) page->lru.next;
 107                                pgd_cache_size -= 2;
 108                                __free_page(page);
 109                                if (page2)
 110                                        page = (struct page *)page2->lru.next;
 111                                else
 112                                        page = (struct page *)pgd_quicklist;
 113                                if (pgd_cache_size <= PGT_CACHE_LOW / 4)
 114                                        break;
 115                                continue;
 116                        }
 117                        page2 = page;
 118                        page = (struct page *)page->lru.next;
 119                }
 120        }
 121#endif
 122        preempt_enable();
 123}
 124
 125#ifdef CONFIG_DEBUG_DCFLUSH
 126atomic_t dcpage_flushes = ATOMIC_INIT(0);
 127#ifdef CONFIG_SMP
 128atomic_t dcpage_flushes_xcall = ATOMIC_INIT(0);
 129#endif
 130#endif
 131
 132__inline__ void flush_dcache_page_impl(struct page *page)
 133{
 134#ifdef CONFIG_DEBUG_DCFLUSH
 135        atomic_inc(&dcpage_flushes);
 136#endif
 137
 138#if (L1DCACHE_SIZE > PAGE_SIZE)
 139        __flush_dcache_page(page_address(page),
 140                            ((tlb_type == spitfire) &&
 141                             page_mapping(page) != NULL));
 142#else
 143        if (page_mapping(page) != NULL &&
 144            tlb_type == spitfire)
 145                __flush_icache_page(__pa(page_address(page)));
 146#endif
 147}
 148
 149#define PG_dcache_dirty         PG_arch_1
 150
 151#define dcache_dirty_cpu(page) \
 152        (((page)->flags >> 24) & (NR_CPUS - 1UL))
 153
 154static __inline__ void set_dcache_dirty(struct page *page, int this_cpu)
 155{
 156        unsigned long mask = this_cpu;
 157        unsigned long non_cpu_bits = ~((NR_CPUS - 1UL) << 24UL);
 158        mask = (mask << 24) | (1UL << PG_dcache_dirty);
 159        __asm__ __volatile__("1:\n\t"
 160                             "ldx       [%2], %%g7\n\t"
 161                             "and       %%g7, %1, %%g5\n\t"
 162                             "or        %%g5, %0, %%g5\n\t"
 163                             "casx      [%2], %%g7, %%g5\n\t"
 164                             "cmp       %%g7, %%g5\n\t"
 165                             "bne,pn    %%xcc, 1b\n\t"
 166                             " membar   #StoreLoad | #StoreStore"
 167                             : /* no outputs */
 168                             : "r" (mask), "r" (non_cpu_bits), "r" (&page->flags)
 169                             : "g5", "g7");
 170}
 171
 172static __inline__ void clear_dcache_dirty_cpu(struct page *page, unsigned long cpu)
 173{
 174        unsigned long mask = (1UL << PG_dcache_dirty);
 175
 176        __asm__ __volatile__("! test_and_clear_dcache_dirty\n"
 177                             "1:\n\t"
 178                             "ldx       [%2], %%g7\n\t"
 179                             "srlx      %%g7, 24, %%g5\n\t"
 180                             "and       %%g5, %3, %%g5\n\t"
 181                             "cmp       %%g5, %0\n\t"
 182                             "bne,pn    %%icc, 2f\n\t"
 183                             " andn     %%g7, %1, %%g5\n\t"
 184                             "casx      [%2], %%g7, %%g5\n\t"
 185                             "cmp       %%g7, %%g5\n\t"
 186                             "bne,pn    %%xcc, 1b\n\t"
 187                             " membar   #StoreLoad | #StoreStore\n"
 188                             "2:"
 189                             : /* no outputs */
 190                             : "r" (cpu), "r" (mask), "r" (&page->flags),
 191                               "i" (NR_CPUS - 1UL)
 192                             : "g5", "g7");
 193}
 194
 195extern void __update_mmu_cache(unsigned long mmu_context_hw, unsigned long address, pte_t pte, int code);
 196
 197void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 198{
 199        struct page *page;
 200        unsigned long pfn;
 201        unsigned long pg_flags;
 202
 203        pfn = pte_pfn(pte);
 204        if (pfn_valid(pfn) &&
 205            (page = pfn_to_page(pfn), page_mapping(page)) &&
 206            ((pg_flags = page->flags) & (1UL << PG_dcache_dirty))) {
 207                int cpu = ((pg_flags >> 24) & (NR_CPUS - 1UL));
 208                int this_cpu = get_cpu();
 209
 210                /* This is just to optimize away some function calls
 211                 * in the SMP case.
 212                 */
 213                if (cpu == this_cpu)
 214                        flush_dcache_page_impl(page);
 215                else
 216                        smp_flush_dcache_page_impl(page, cpu);
 217
 218                clear_dcache_dirty_cpu(page, cpu);
 219
 220                put_cpu();
 221        }
 222        if (get_thread_fault_code())
 223                __update_mmu_cache(vma->vm_mm->context & TAG_CONTEXT_BITS,
 224                                   address, pte, get_thread_fault_code());
 225}
 226
 227void flush_dcache_page(struct page *page)
 228{
 229        struct address_space *mapping = page_mapping(page);
 230        int dirty = test_bit(PG_dcache_dirty, &page->flags);
 231        int dirty_cpu = dcache_dirty_cpu(page);
 232        int this_cpu = get_cpu();
 233
 234        if (mapping && !mapping_mapped(mapping)) {
 235                if (dirty) {
 236                        if (dirty_cpu == this_cpu)
 237                                goto out;
 238                        smp_flush_dcache_page_impl(page, dirty_cpu);
 239                }
 240                set_dcache_dirty(page, this_cpu);
 241        } else {
 242                /* We could delay the flush for the !page_mapping
 243                 * case too.  But that case is for exec env/arg
 244                 * pages and those are %99 certainly going to get
 245                 * faulted into the tlb (and thus flushed) anyways.
 246                 */
 247                flush_dcache_page_impl(page);
 248        }
 249
 250out:
 251        put_cpu();
 252}
 253
 254void flush_icache_range(unsigned long start, unsigned long end)
 255{
 256        /* Cheetah has coherent I-cache. */
 257        if (tlb_type == spitfire) {
 258                unsigned long kaddr;
 259
 260                for (kaddr = start; kaddr < end; kaddr += PAGE_SIZE)
 261                        __flush_icache_page(__get_phys(kaddr));
 262        }
 263}
 264
 265unsigned long page_to_pfn(struct page *page)
 266{
 267        return (unsigned long) ((page - mem_map) + pfn_base);
 268}
 269
 270struct page *pfn_to_page(unsigned long pfn)
 271{
 272        return (mem_map + (pfn - pfn_base));
 273}
 274
 275void show_mem(void)
 276{
 277        printk("Mem-info:\n");
 278        show_free_areas();
 279        printk("Free swap:       %6ldkB\n",
 280               nr_swap_pages << (PAGE_SHIFT-10));
 281        printk("%ld pages of RAM\n", num_physpages);
 282        printk("%d free pages\n", nr_free_pages());
 283        printk("%d pages in page table cache\n",pgtable_cache_size);
 284#ifndef CONFIG_SMP
 285        printk("%d entries in page dir cache\n",pgd_cache_size);
 286#endif  
 287}
 288
 289void mmu_info(struct seq_file *m)
 290{
 291        if (tlb_type == cheetah)
 292                seq_printf(m, "MMU Type\t: Cheetah\n");
 293        else if (tlb_type == cheetah_plus)
 294                seq_printf(m, "MMU Type\t: Cheetah+\n");
 295        else if (tlb_type == spitfire)
 296                seq_printf(m, "MMU Type\t: Spitfire\n");
 297        else
 298                seq_printf(m, "MMU Type\t: ???\n");
 299
 300#ifdef CONFIG_DEBUG_DCFLUSH
 301        seq_printf(m, "DCPageFlushes\t: %d\n",
 302                   atomic_read(&dcpage_flushes));
 303#ifdef CONFIG_SMP
 304        seq_printf(m, "DCPageFlushesXC\t: %d\n",
 305                   atomic_read(&dcpage_flushes_xcall));
 306#endif /* CONFIG_SMP */
 307#endif /* CONFIG_DEBUG_DCFLUSH */
 308}
 309
 310struct linux_prom_translation {
 311        unsigned long virt;
 312        unsigned long size;
 313        unsigned long data;
 314};
 315
 316extern unsigned long prom_boot_page;
 317extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle);
 318extern int prom_get_mmu_ihandle(void);
 319extern void register_prom_callbacks(void);
 320
 321/* Exported for SMP bootup purposes. */
 322unsigned long kern_locked_tte_data;
 323
 324void __init early_pgtable_allocfail(char *type)
 325{
 326        prom_printf("inherit_prom_mappings: Cannot alloc kernel %s.\n", type);
 327        prom_halt();
 328}
 329
 330#define BASE_PAGE_SIZE 8192
 331static pmd_t *prompmd;
 332
 333/*
 334 * Translate PROM's mapping we capture at boot time into physical address.
 335 * The second parameter is only set from prom_callback() invocations.
 336 */
 337unsigned long prom_virt_to_phys(unsigned long promva, int *error)
 338{
 339        pmd_t *pmdp = prompmd + ((promva >> 23) & 0x7ff);
 340        pte_t *ptep;
 341        unsigned long base;
 342
 343        if (pmd_none(*pmdp)) {
 344                if (error)
 345                        *error = 1;
 346                return(0);
 347        }
 348        ptep = (pte_t *)__pmd_page(*pmdp) + ((promva >> 13) & 0x3ff);
 349        if (!pte_present(*ptep)) {
 350                if (error)
 351                        *error = 1;
 352                return(0);
 353        }
 354        if (error) {
 355                *error = 0;
 356                return(pte_val(*ptep));
 357        }
 358        base = pte_val(*ptep) & _PAGE_PADDR;
 359        return(base + (promva & (BASE_PAGE_SIZE - 1)));
 360}
 361
 362static void inherit_prom_mappings(void)
 363{
 364        struct linux_prom_translation *trans;
 365        unsigned long phys_page, tte_vaddr, tte_data;
 366        void (*remap_func)(unsigned long, unsigned long, int);
 367        pmd_t *pmdp;
 368        pte_t *ptep;
 369        int node, n, i, tsz;
 370        extern unsigned int obp_iaddr_patch[2], obp_daddr_patch[2];
 371
 372        node = prom_finddevice("/virtual-memory");
 373        n = prom_getproplen(node, "translations");
 374        if (n == 0 || n == -1) {
 375                prom_printf("Couldn't get translation property\n");
 376                prom_halt();
 377        }
 378        n += 5 * sizeof(struct linux_prom_translation);
 379        for (tsz = 1; tsz < n; tsz <<= 1)
 380                /* empty */;
 381        trans = __alloc_bootmem(tsz, SMP_CACHE_BYTES, bootmap_base);
 382        if (trans == NULL) {
 383                prom_printf("inherit_prom_mappings: Cannot alloc translations.\n");
 384                prom_halt();
 385        }
 386        memset(trans, 0, tsz);
 387
 388        if ((n = prom_getproperty(node, "translations", (char *)trans, tsz)) == -1) {
 389                prom_printf("Couldn't get translation property\n");
 390                prom_halt();
 391        }
 392        n = n / sizeof(*trans);
 393
 394        /*
 395         * The obp translations are saved based on 8k pagesize, since obp can use
 396         * a mixture of pagesizes. Misses to the 0xf0000000 - 0x100000000, ie obp 
 397         * range, are handled in entry.S and do not use the vpte scheme (see rant
 398         * in inherit_locked_prom_mappings()).
 399         */
 400#define OBP_PMD_SIZE 2048
 401        prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, bootmap_base);
 402        if (prompmd == NULL)
 403                early_pgtable_allocfail("pmd");
 404        memset(prompmd, 0, OBP_PMD_SIZE);
 405        for (i = 0; i < n; i++) {
 406                unsigned long vaddr;
 407
 408                if (trans[i].virt >= LOW_OBP_ADDRESS && trans[i].virt < HI_OBP_ADDRESS) {
 409                        for (vaddr = trans[i].virt;
 410                             ((vaddr < trans[i].virt + trans[i].size) && 
 411                             (vaddr < HI_OBP_ADDRESS));
 412                             vaddr += BASE_PAGE_SIZE) {
 413                                unsigned long val;
 414
 415                                pmdp = prompmd + ((vaddr >> 23) & 0x7ff);
 416                                if (pmd_none(*pmdp)) {
 417                                        ptep = __alloc_bootmem(BASE_PAGE_SIZE,
 418                                                               BASE_PAGE_SIZE,
 419                                                               bootmap_base);
 420                                        if (ptep == NULL)
 421                                                early_pgtable_allocfail("pte");
 422                                        memset(ptep, 0, BASE_PAGE_SIZE);
 423                                        pmd_set(pmdp, ptep);
 424                                }
 425                                ptep = (pte_t *)__pmd_page(*pmdp) +
 426                                                ((vaddr >> 13) & 0x3ff);
 427
 428                                val = trans[i].data;
 429
 430                                /* Clear diag TTE bits. */
 431                                if (tlb_type == spitfire)
 432                                        val &= ~0x0003fe0000000000UL;
 433
 434                                set_pte (ptep, __pte(val | _PAGE_MODIFIED));
 435                                trans[i].data += BASE_PAGE_SIZE;
 436                        }
 437                }
 438        }
 439        phys_page = __pa(prompmd);
 440        obp_iaddr_patch[0] |= (phys_page >> 10);
 441        obp_iaddr_patch[1] |= (phys_page & 0x3ff);
 442        flushi((long)&obp_iaddr_patch[0]);
 443        obp_daddr_patch[0] |= (phys_page >> 10);
 444        obp_daddr_patch[1] |= (phys_page & 0x3ff);
 445        flushi((long)&obp_daddr_patch[0]);
 446
 447        /* Now fixup OBP's idea about where we really are mapped. */
 448        prom_printf("Remapping the kernel... ");
 449
 450        /* Spitfire Errata #32 workaround */
 451        __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
 452                             "flush     %%g6"
 453                             : /* No outputs */
 454                             : "r" (0),
 455                             "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
 456
 457        switch (tlb_type) {
 458        default:
 459        case spitfire:
 460                phys_page = spitfire_get_dtlb_data(sparc64_highest_locked_tlbent());
 461                break;
 462
 463        case cheetah:
 464        case cheetah_plus:
 465                phys_page = cheetah_get_litlb_data(sparc64_highest_locked_tlbent());
 466                break;
 467        };
 468
 469        phys_page &= _PAGE_PADDR;
 470        phys_page += ((unsigned long)&prom_boot_page -
 471                      (unsigned long)KERNBASE);
 472
 473        if (tlb_type == spitfire) {
 474                /* Lock this into i/d tlb entry 59 */
 475                __asm__ __volatile__(
 476                        "stxa   %%g0, [%2] %3\n\t"
 477                        "stxa   %0, [%1] %4\n\t"
 478                        "membar #Sync\n\t"
 479                        "flush  %%g6\n\t"
 480                        "stxa   %%g0, [%2] %5\n\t"
 481                        "stxa   %0, [%1] %6\n\t"
 482                        "membar #Sync\n\t"
 483                        "flush  %%g6"
 484                        : : "r" (phys_page | _PAGE_VALID | _PAGE_SZ8K | _PAGE_CP |
 485                                 _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W),
 486                        "r" (59 << 3), "r" (TLB_TAG_ACCESS),
 487                        "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS),
 488                        "i" (ASI_IMMU), "i" (ASI_ITLB_DATA_ACCESS)
 489                        : "memory");
 490        } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
 491                /* Lock this into i/d tlb-0 entry 11 */
 492                __asm__ __volatile__(
 493                        "stxa   %%g0, [%2] %3\n\t"
 494                        "stxa   %0, [%1] %4\n\t"
 495                        "membar #Sync\n\t"
 496                        "flush  %%g6\n\t"
 497                        "stxa   %%g0, [%2] %5\n\t"
 498                        "stxa   %0, [%1] %6\n\t"
 499                        "membar #Sync\n\t"
 500                        "flush  %%g6"
 501                        : : "r" (phys_page | _PAGE_VALID | _PAGE_SZ8K | _PAGE_CP |
 502                                 _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W),
 503                        "r" ((0 << 16) | (11 << 3)), "r" (TLB_TAG_ACCESS),
 504                        "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS),
 505                        "i" (ASI_IMMU), "i" (ASI_ITLB_DATA_ACCESS)
 506                        : "memory");
 507        } else {
 508                /* Implement me :-) */
 509                BUG();
 510        }
 511
 512        tte_vaddr = (unsigned long) KERNBASE;
 513
 514        /* Spitfire Errata #32 workaround */
 515        __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
 516                             "flush     %%g6"
 517                             : /* No outputs */
 518                             : "r" (0),
 519                             "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
 520
 521        if (tlb_type == spitfire)
 522                tte_data = spitfire_get_dtlb_data(sparc64_highest_locked_tlbent());
 523        else
 524                tte_data = cheetah_get_ldtlb_data(sparc64_highest_locked_tlbent());
 525
 526        kern_locked_tte_data = tte_data;
 527
 528        remap_func = (void *)  ((unsigned long) &prom_remap -
 529                                (unsigned long) &prom_boot_page);
 530
 531
 532        /* Spitfire Errata #32 workaround */
 533        __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
 534                             "flush     %%g6"
 535                             : /* No outputs */
 536                             : "r" (0),
 537                             "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
 538
 539        remap_func((tlb_type == spitfire ?
 540                    (spitfire_get_dtlb_data(sparc64_highest_locked_tlbent()) & _PAGE_PADDR) :
 541                    (cheetah_get_litlb_data(sparc64_highest_locked_tlbent()) & _PAGE_PADDR)),
 542                   (unsigned long) KERNBASE,
 543                   prom_get_mmu_ihandle());
 544
 545        if (bigkernel)
 546                remap_func(((tte_data + 0x400000) & _PAGE_PADDR),
 547                        (unsigned long) KERNBASE + 0x400000, prom_get_mmu_ihandle());
 548
 549        /* Flush out that temporary mapping. */
 550        spitfire_flush_dtlb_nucleus_page(0x0);
 551        spitfire_flush_itlb_nucleus_page(0x0);
 552
 553        /* Now lock us back into the TLBs via OBP. */
 554        prom_dtlb_load(sparc64_highest_locked_tlbent(), tte_data, tte_vaddr);
 555        prom_itlb_load(sparc64_highest_locked_tlbent(), tte_data, tte_vaddr);
 556        if (bigkernel) {
 557                prom_dtlb_load(sparc64_highest_locked_tlbent()-1, tte_data + 0x400000, 
 558                                                                tte_vaddr + 0x400000);
 559                prom_itlb_load(sparc64_highest_locked_tlbent()-1, tte_data + 0x400000, 
 560                                                                tte_vaddr + 0x400000);
 561        }
 562
 563        /* Re-read translations property. */
 564        if ((n = prom_getproperty(node, "translations", (char *)trans, tsz)) == -1) {
 565                prom_printf("Couldn't get translation property\n");
 566                prom_halt();
 567        }
 568        n = n / sizeof(*trans);
 569
 570        for (i = 0; i < n; i++) {
 571                unsigned long vaddr = trans[i].virt;
 572                unsigned long size = trans[i].size;
 573
 574                if (vaddr < 0xf0000000UL) {
 575                        unsigned long avoid_start = (unsigned long) KERNBASE;
 576                        unsigned long avoid_end = avoid_start + (4 * 1024 * 1024);
 577
 578                        if (bigkernel)
 579                                avoid_end += (4 * 1024 * 1024);
 580                        if (vaddr < avoid_start) {
 581                                unsigned long top = vaddr + size;
 582
 583                                if (top > avoid_start)
 584                                        top = avoid_start;
 585                                prom_unmap(top - vaddr, vaddr);
 586                        }
 587                        if ((vaddr + size) > avoid_end) {
 588                                unsigned long bottom = vaddr;
 589
 590                                if (bottom < avoid_end)
 591                                        bottom = avoid_end;
 592                                prom_unmap((vaddr + size) - bottom, bottom);
 593                        }
 594                }
 595        }
 596
 597        prom_printf("done.\n");
 598
 599        register_prom_callbacks();
 600}
 601
 602/* The OBP specifications for sun4u mark 0xfffffffc00000000 and
 603 * upwards as reserved for use by the firmware (I wonder if this
 604 * will be the same on Cheetah...).  We use this virtual address
 605 * range for the VPTE table mappings of the nucleus so we need
 606 * to zap them when we enter the PROM.  -DaveM
 607 */
 608static void __flush_nucleus_vptes(void)
 609{
 610        unsigned long prom_reserved_base = 0xfffffffc00000000UL;
 611        int i;
 612
 613        /* Only DTLB must be checked for VPTE entries. */
 614        if (tlb_type == spitfire) {
 615                for (i = 0; i < 63; i++) {
 616                        unsigned long tag;
 617
 618                        /* Spitfire Errata #32 workaround */
 619                        __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
 620                                             "flush     %%g6"
 621                                             : /* No outputs */
 622                                             : "r" (0),
 623                                             "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
 624
 625                        tag = spitfire_get_dtlb_tag(i);
 626                        if (((tag & ~(PAGE_MASK)) == 0) &&
 627                            ((tag &  (PAGE_MASK)) >= prom_reserved_base)) {
 628                                __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
 629                                                     "membar #Sync"
 630                                                     : /* no outputs */
 631                                                     : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU));
 632                                spitfire_put_dtlb_data(i, 0x0UL);
 633                        }
 634                }
 635        } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
 636                for (i = 0; i < 512; i++) {
 637                        unsigned long tag = cheetah_get_dtlb_tag(i, 2);
 638
 639                        if ((tag & ~PAGE_MASK) == 0 &&
 640                            (tag & PAGE_MASK) >= prom_reserved_base) {
 641                                __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
 642                                                     "membar #Sync"
 643                                                     : /* no outputs */
 644                                                     : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU));
 645                                cheetah_put_dtlb_data(i, 0x0UL, 2);
 646                        }
 647
 648                        if (tlb_type != cheetah_plus)
 649                                continue;
 650
 651                        tag = cheetah_get_dtlb_tag(i, 3);
 652
 653                        if ((tag & ~PAGE_MASK) == 0 &&
 654                            (tag & PAGE_MASK) >= prom_reserved_base) {
 655                                __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
 656                                                     "membar #Sync"
 657                                                     : /* no outputs */
 658                                                     : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU));
 659                                cheetah_put_dtlb_data(i, 0x0UL, 3);
 660                        }
 661                }
 662        } else {
 663                /* Implement me :-) */
 664                BUG();
 665        }
 666}
 667
 668static int prom_ditlb_set;
 669struct prom_tlb_entry {
 670        int             tlb_ent;
 671        unsigned long   tlb_tag;
 672        unsigned long   tlb_data;
 673};
 674struct prom_tlb_entry prom_itlb[16], prom_dtlb[16];
 675
 676void prom_world(int enter)
 677{
 678        unsigned long pstate;
 679        int i;
 680
 681        if (!enter)
 682                set_fs((mm_segment_t) { get_thread_current_ds() });
 683
 684        if (!prom_ditlb_set)
 685                return;
 686
 687        /* Make sure the following runs atomically. */
 688        __asm__ __volatile__("flushw\n\t"
 689                             "rdpr      %%pstate, %0\n\t"
 690                             "wrpr      %0, %1, %%pstate"
 691                             : "=r" (pstate)
 692                             : "i" (PSTATE_IE));
 693
 694        if (enter) {
 695                /* Kick out nucleus VPTEs. */
 696                __flush_nucleus_vptes();
 697
 698                /* Install PROM world. */
 699                for (i = 0; i < 16; i++) {
 700                        if (prom_dtlb[i].tlb_ent != -1) {
 701                                __asm__ __volatile__("stxa %0, [%1] %2\n\t"
 702                                                     "membar #Sync"
 703                                        : : "r" (prom_dtlb[i].tlb_tag), "r" (TLB_TAG_ACCESS),
 704                                        "i" (ASI_DMMU));
 705                                if (tlb_type == spitfire)
 706                                        spitfire_put_dtlb_data(prom_dtlb[i].tlb_ent,
 707                                                               prom_dtlb[i].tlb_data);
 708                                else if (tlb_type == cheetah || tlb_type == cheetah_plus)
 709                                        cheetah_put_ldtlb_data(prom_dtlb[i].tlb_ent,
 710                                                               prom_dtlb[i].tlb_data);
 711                        }
 712                        if (prom_itlb[i].tlb_ent != -1) {
 713                                __asm__ __volatile__("stxa %0, [%1] %2\n\t"
 714                                                     "membar #Sync"
 715                                                     : : "r" (prom_itlb[i].tlb_tag),
 716                                                     "r" (TLB_TAG_ACCESS),
 717                                                     "i" (ASI_IMMU));
 718                                if (tlb_type == spitfire)
 719                                        spitfire_put_itlb_data(prom_itlb[i].tlb_ent,
 720                                                               prom_itlb[i].tlb_data);
 721                                else if (tlb_type == cheetah || tlb_type == cheetah_plus)
 722                                        cheetah_put_litlb_data(prom_itlb[i].tlb_ent,
 723                                                               prom_itlb[i].tlb_data);
 724                        }
 725                }
 726        } else {
 727                for (i = 0; i < 16; i++) {
 728                        if (prom_dtlb[i].tlb_ent != -1) {
 729                                __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
 730                                                     "membar #Sync"
 731                                        : : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU));
 732                                if (tlb_type == spitfire)
 733                                        spitfire_put_dtlb_data(prom_dtlb[i].tlb_ent, 0x0UL);
 734                                else
 735                                        cheetah_put_ldtlb_data(prom_dtlb[i].tlb_ent, 0x0UL);
 736                        }
 737                        if (prom_itlb[i].tlb_ent != -1) {
 738                                __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
 739                                                     "membar #Sync"
 740                                                     : : "r" (TLB_TAG_ACCESS),
 741                                                     "i" (ASI_IMMU));
 742                                if (tlb_type == spitfire)
 743                                        spitfire_put_itlb_data(prom_itlb[i].tlb_ent, 0x0UL);
 744                                else
 745                                        cheetah_put_litlb_data(prom_itlb[i].tlb_ent, 0x0UL);
 746                        }
 747                }
 748        }
 749        __asm__ __volatile__("wrpr      %0, 0, %%pstate"
 750                             : : "r" (pstate));
 751}
 752
 753void inherit_locked_prom_mappings(int save_p)
 754{
 755        int i;
 756        int dtlb_seen = 0;
 757        int itlb_seen = 0;
 758
 759        /* Fucking losing PROM has more mappings in the TLB, but
 760         * it (conveniently) fails to mention any of these in the
 761         * translations property.  The only ones that matter are
 762         * the locked PROM tlb entries, so we impose the following
 763         * irrecovable rule on the PROM, it is allowed 8 locked
 764         * entries in the ITLB and 8 in the DTLB.
 765         *
 766         * Supposedly the upper 16GB of the address space is
 767         * reserved for OBP, BUT I WISH THIS WAS DOCUMENTED
 768         * SOMEWHERE!!!!!!!!!!!!!!!!!  Furthermore the entire interface
 769         * used between the client program and the firmware on sun5
 770         * systems to coordinate mmu mappings is also COMPLETELY
 771         * UNDOCUMENTED!!!!!! Thanks S(t)un!
 772         */
 773        if (save_p) {
 774                for (i = 0; i < 16; i++) {
 775                        prom_itlb[i].tlb_ent = -1;
 776                        prom_dtlb[i].tlb_ent = -1;
 777                }
 778        }
 779        if (tlb_type == spitfire) {
 780                int high = SPITFIRE_HIGHEST_LOCKED_TLBENT - bigkernel;
 781                for (i = 0; i < high; i++) {
 782                        unsigned long data;
 783
 784                        /* Spitfire Errata #32 workaround */
 785                        __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
 786                                             "flush     %%g6"
 787                                             : /* No outputs */
 788                                             : "r" (0),
 789                                             "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
 790
 791                        data = spitfire_get_dtlb_data(i);
 792                        if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) {
 793                                unsigned long tag;
 794
 795                                /* Spitfire Errata #32 workaround */
 796                                __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
 797                                                     "flush     %%g6"
 798                                                     : /* No outputs */
 799                                                     : "r" (0),
 800                                                     "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
 801
 802                                tag = spitfire_get_dtlb_tag(i);
 803                                if (save_p) {
 804                                        prom_dtlb[dtlb_seen].tlb_ent = i;
 805                                        prom_dtlb[dtlb_seen].tlb_tag = tag;
 806                                        prom_dtlb[dtlb_seen].tlb_data = data;
 807                                }
 808                                __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
 809                                                     "membar #Sync"
 810                                                     : : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU));
 811                                spitfire_put_dtlb_data(i, 0x0UL);
 812
 813                                dtlb_seen++;
 814                                if (dtlb_seen > 15)
 815                                        break;
 816                        }
 817                }
 818
 819                for (i = 0; i < high; i++) {
 820                        unsigned long data;
 821
 822                        /* Spitfire Errata #32 workaround */
 823                        __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
 824                                             "flush     %%g6"
 825                                             : /* No outputs */
 826                                             : "r" (0),
 827                                             "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
 828
 829                        data = spitfire_get_itlb_data(i);
 830                        if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) {
 831                                unsigned long tag;
 832
 833                                /* Spitfire Errata #32 workaround */
 834                                __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
 835                                                     "flush     %%g6"
 836                                                     : /* No outputs */
 837                                                     : "r" (0),
 838                                                     "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
 839
 840                                tag = spitfire_get_itlb_tag(i);
 841                                if (save_p) {
 842                                        prom_itlb[itlb_seen].tlb_ent = i;
 843                                        prom_itlb[itlb_seen].tlb_tag = tag;
 844                                        prom_itlb[itlb_seen].tlb_data = data;
 845                                }
 846                                __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
 847                                                     "membar #Sync"
 848                                                     : : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU));
 849                                spitfire_put_itlb_data(i, 0x0UL);
 850
 851                                itlb_seen++;
 852                                if (itlb_seen > 15)
 853                                        break;
 854                        }
 855                }
 856        } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
 857                int high = CHEETAH_HIGHEST_LOCKED_TLBENT - bigkernel;
 858
 859                for (i = 0; i < high; i++) {
 860                        unsigned long data;
 861
 862                        data = cheetah_get_ldtlb_data(i);
 863                        if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) {
 864                                unsigned long tag;
 865
 866                                tag = cheetah_get_ldtlb_tag(i);
 867                                if (save_p) {
 868                                        prom_dtlb[dtlb_seen].tlb_ent = i;
 869                                        prom_dtlb[dtlb_seen].tlb_tag = tag;
 870                                        prom_dtlb[dtlb_seen].tlb_data = data;
 871                                }
 872                                __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
 873                                                     "membar #Sync"
 874                                                     : : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU));
 875                                cheetah_put_ldtlb_data(i, 0x0UL);
 876
 877                                dtlb_seen++;
 878                                if (dtlb_seen > 15)
 879                                        break;
 880                        }
 881                }
 882
 883                for (i = 0; i < high; i++) {
 884                        unsigned long data;
 885
 886                        data = cheetah_get_litlb_data(i);
 887                        if ((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) {
 888                                unsigned long tag;
 889
 890                                tag = cheetah_get_litlb_tag(i);
 891                                if (save_p) {
 892                                        prom_itlb[itlb_seen].tlb_ent = i;
 893                                        prom_itlb[itlb_seen].tlb_tag = tag;
 894                                        prom_itlb[itlb_seen].tlb_data = data;
 895                                }
 896                                __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
 897                                                     "membar #Sync"
 898                                                     : : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU));
 899                                cheetah_put_litlb_data(i, 0x0UL);
 900
 901                                itlb_seen++;
 902                                if (itlb_seen > 15)
 903                                        break;
 904                        }
 905                }
 906        } else {
 907                /* Implement me :-) */
 908                BUG();
 909        }
 910        if (save_p)
 911                prom_ditlb_set = 1;
 912}
 913
 914/* Give PROM back his world, done during reboots... */
 915void prom_reload_locked(void)
 916{
 917        int i;
 918
 919        for (i = 0; i < 16; i++) {
 920                if (prom_dtlb[i].tlb_ent != -1) {
 921                        __asm__ __volatile__("stxa %0, [%1] %2\n\t"
 922                                             "membar #Sync"
 923                                : : "r" (prom_dtlb[i].tlb_tag), "r" (TLB_TAG_ACCESS),
 924                                "i" (ASI_DMMU));
 925                        if (tlb_type == spitfire)
 926                                spitfire_put_dtlb_data(prom_dtlb[i].tlb_ent,
 927                                                       prom_dtlb[i].tlb_data);
 928                        else if (tlb_type == cheetah || tlb_type == cheetah_plus)
 929                                cheetah_put_ldtlb_data(prom_dtlb[i].tlb_ent,
 930                                                      prom_dtlb[i].tlb_data);
 931                }
 932
 933                if (prom_itlb[i].tlb_ent != -1) {
 934                        __asm__ __volatile__("stxa %0, [%1] %2\n\t"
 935                                             "membar #Sync"
 936                                             : : "r" (prom_itlb[i].tlb_tag),
 937                                             "r" (TLB_TAG_ACCESS),
 938                                             "i" (ASI_IMMU));
 939                        if (tlb_type == spitfire)
 940                                spitfire_put_itlb_data(prom_itlb[i].tlb_ent,
 941                                                       prom_itlb[i].tlb_data);
 942                        else
 943                                cheetah_put_litlb_data(prom_itlb[i].tlb_ent,
 944                                                       prom_itlb[i].tlb_data);
 945                }
 946        }
 947}
 948
 949void __flush_dcache_range(unsigned long start, unsigned long end)
 950{
 951        unsigned long va;
 952
 953        if (tlb_type == spitfire) {
 954                int n = 0;
 955
 956                for (va = start; va < end; va += 32) {
 957                        spitfire_put_dcache_tag(va & 0x3fe0, 0x0);
 958                        if (++n >= 512)
 959                                break;
 960                }
 961        } else {
 962                start = __pa(start);
 963                end = __pa(end);
 964                for (va = start; va < end; va += 32)
 965                        __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
 966                                             "membar #Sync"
 967                                             : /* no outputs */
 968                                             : "r" (va),
 969                                               "i" (ASI_DCACHE_INVALIDATE));
 970        }
 971}
 972
 973/* If not locked, zap it. */
 974void __flush_tlb_all(void)
 975{
 976        unsigned long pstate;
 977        int i;
 978
 979        __asm__ __volatile__("flushw\n\t"
 980                             "rdpr      %%pstate, %0\n\t"
 981                             "wrpr      %0, %1, %%pstate"
 982                             : "=r" (pstate)
 983                             : "i" (PSTATE_IE));
 984        if (tlb_type == spitfire) {
 985                for (i = 0; i < 64; i++) {
 986                        /* Spitfire Errata #32 workaround */
 987                        __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
 988                                             "flush     %%g6"
 989                                             : /* No outputs */
 990                                             : "r" (0),
 991                                             "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
 992
 993                        if (!(spitfire_get_dtlb_data(i) & _PAGE_L)) {
 994                                __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
 995                                                     "membar #Sync"
 996                                                     : /* no outputs */
 997                                                     : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU));
 998                                spitfire_put_dtlb_data(i, 0x0UL);
 999                        }
1000
1001                        /* Spitfire Errata #32 workaround */
1002                        __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
1003                                             "flush     %%g6"
1004                                             : /* No outputs */
1005                                             : "r" (0),
1006                                             "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
1007
1008                        if (!(spitfire_get_itlb_data(i) & _PAGE_L)) {
1009                                __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
1010                                                     "membar #Sync"
1011                                                     : /* no outputs */
1012                                                     : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU));
1013                                spitfire_put_itlb_data(i, 0x0UL);
1014                        }
1015                }
1016        } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
1017                cheetah_flush_dtlb_all();
1018                cheetah_flush_itlb_all();
1019        }
1020        __asm__ __volatile__("wrpr      %0, 0, %%pstate"
1021                             : : "r" (pstate));
1022}
1023
1024/* Caller does TLB context flushing on local CPU if necessary.
1025 * The caller also ensures that CTX_VALID(mm->context) is false.
1026 *
1027 * We must be careful about boundary cases so that we never
1028 * let the user have CTX 0 (nucleus) or we ever use a CTX
1029 * version of zero (and thus NO_CONTEXT would not be caught
1030 * by version mis-match tests in mmu_context.h).
1031 */
1032void get_new_mmu_context(struct mm_struct *mm)
1033{
1034        unsigned long ctx, new_ctx;
1035        
1036        spin_lock(&ctx_alloc_lock);
1037        ctx = CTX_HWBITS(tlb_context_cache + 1);
1038        new_ctx = find_next_zero_bit(mmu_context_bmap, 1UL << CTX_VERSION_SHIFT, ctx);
1039        if (new_ctx >= (1UL << CTX_VERSION_SHIFT)) {
1040                new_ctx = find_next_zero_bit(mmu_context_bmap, ctx, 1);
1041                if (new_ctx >= ctx) {
1042                        int i;
1043                        new_ctx = (tlb_context_cache & CTX_VERSION_MASK) +
1044                                CTX_FIRST_VERSION;
1045                        if (new_ctx == 1)
1046                                new_ctx = CTX_FIRST_VERSION;
1047
1048                        /* Don't call memset, for 16 entries that's just
1049                         * plain silly...
1050                         */
1051                        mmu_context_bmap[0] = 3;
1052                        mmu_context_bmap[1] = 0;
1053                        mmu_context_bmap[2] = 0;
1054                        mmu_context_bmap[3] = 0;
1055                        for (i = 4; i < CTX_BMAP_SLOTS; i += 4) {
1056                                mmu_context_bmap[i + 0] = 0;
1057                                mmu_context_bmap[i + 1] = 0;
1058                                mmu_context_bmap[i + 2] = 0;
1059                                mmu_context_bmap[i + 3] = 0;
1060                        }
1061                        goto out;
1062                }
1063        }
1064        mmu_context_bmap[new_ctx>>6] |= (1UL << (new_ctx & 63));
1065        new_ctx |= (tlb_context_cache & CTX_VERSION_MASK);
1066out:
1067        tlb_context_cache = new_ctx;
1068        spin_unlock(&ctx_alloc_lock);
1069
1070        mm->context = new_ctx;
1071}
1072
1073#ifndef CONFIG_SMP
1074struct pgtable_cache_struct pgt_quicklists;
1075#endif
1076
1077/* OK, we have to color these pages. The page tables are accessed
1078 * by non-Dcache enabled mapping in the VPTE area by the dtlb_backend.S
1079 * code, as well as by PAGE_OFFSET range direct-mapped addresses by 
1080 * other parts of the kernel. By coloring, we make sure that the tlbmiss 
1081 * fast handlers do not get data from old/garbage dcache lines that 
1082 * correspond to an old/stale virtual address (user/kernel) that 
1083 * previously mapped the pagetable page while accessing vpte range 
1084 * addresses. The idea is that if the vpte color and PAGE_OFFSET range 
1085 * color is the same, then when the kernel initializes the pagetable 
1086 * using the later address range, accesses with the first address
1087 * range will see the newly initialized data rather than the garbage.
1088 */
1089#if (L1DCACHE_SIZE > PAGE_SIZE)                 /* is there D$ aliasing problem */
1090#define DC_ALIAS_SHIFT  1
1091#else
1092#define DC_ALIAS_SHIFT  0
1093#endif
1094pte_t *__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
1095{
1096        struct page *page;
1097        unsigned long color;
1098
1099        {
1100                pte_t *ptep = pte_alloc_one_fast(mm, address);
1101
1102                if (ptep)
1103                        return ptep;
1104        }
1105
1106        color = VPTE_COLOR(address);
1107        page = alloc_pages(GFP_KERNEL|__GFP_REPEAT, DC_ALIAS_SHIFT);
1108        if (page) {
1109                unsigned long *to_free;
1110                unsigned long paddr;
1111                pte_t *pte;
1112
1113#if (L1DCACHE_SIZE > PAGE_SIZE)                 /* is there D$ aliasing problem */
1114                set_page_count(page, 1);
1115                ClearPageCompound(page);
1116
1117                set_page_count((page + 1), 1);
1118                ClearPageCompound(page + 1);
1119#endif
1120                paddr = (unsigned long) page_address(page);
1121                memset((char *)paddr, 0, (PAGE_SIZE << DC_ALIAS_SHIFT));
1122
1123                if (!color) {
1124                        pte = (pte_t *) paddr;
1125                        to_free = (unsigned long *) (paddr + PAGE_SIZE);
1126                } else {
1127                        pte = (pte_t *) (paddr + PAGE_SIZE);
1128                        to_free = (unsigned long *) paddr;
1129                }
1130
1131#if (L1DCACHE_SIZE > PAGE_SIZE)                 /* is there D$ aliasing problem */
1132                /* Now free the other one up, adjust cache size. */
1133                preempt_disable();
1134                *to_free = (unsigned long) pte_quicklist[color ^ 0x1];
1135                pte_quicklist[color ^ 0x1] = to_free;
1136                pgtable_cache_size++;
1137                preempt_enable();
1138#endif
1139
1140                return pte;
1141        }
1142        return NULL;
1143}
1144
1145void sparc_ultra_dump_itlb(void)
1146{
1147        int slot;
1148
1149        if (tlb_type == spitfire) {
1150                printk ("Contents of itlb: ");
1151                for (slot = 0; slot < 14; slot++) printk ("    ");
1152                printk ("%2x:%016lx,%016lx\n",
1153                        0,
1154                        spitfire_get_itlb_tag(0), spitfire_get_itlb_data(0));
1155                for (slot = 1; slot < 64; slot+=3) {
1156                        printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx %2x:%016lx,%016lx\n", 
1157                                slot,
1158                                spitfire_get_itlb_tag(slot), spitfire_get_itlb_data(slot),
1159                                slot+1,
1160                                spitfire_get_itlb_tag(slot+1), spitfire_get_itlb_data(slot+1),
1161                                slot+2,
1162                                spitfire_get_itlb_tag(slot+2), spitfire_get_itlb_data(slot+2));
1163                }
1164        } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
1165                printk ("Contents of itlb0:\n");
1166                for (slot = 0; slot < 16; slot+=2) {
1167                        printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n",
1168                                slot,
1169                                cheetah_get_litlb_tag(slot), cheetah_get_litlb_data(slot),
1170                                slot+1,
1171                                cheetah_get_litlb_tag(slot+1), cheetah_get_litlb_data(slot+1));
1172                }
1173                printk ("Contents of itlb2:\n");
1174                for (slot = 0; slot < 128; slot+=2) {
1175                        printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n",
1176                                slot,
1177                                cheetah_get_itlb_tag(slot), cheetah_get_itlb_data(slot),
1178                                slot+1,
1179                                cheetah_get_itlb_tag(slot+1), cheetah_get_itlb_data(slot+1));
1180                }
1181        }
1182}
1183
1184void sparc_ultra_dump_dtlb(void)
1185{
1186        int slot;
1187
1188        if (tlb_type == spitfire) {
1189                printk ("Contents of dtlb: ");
1190                for (slot = 0; slot < 14; slot++) printk ("    ");
1191                printk ("%2x:%016lx,%016lx\n", 0,
1192                        spitfire_get_dtlb_tag(0), spitfire_get_dtlb_data(0));
1193                for (slot = 1; slot < 64; slot+=3) {
1194                        printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx %2x:%016lx,%016lx\n", 
1195                                slot,
1196                                spitfire_get_dtlb_tag(slot), spitfire_get_dtlb_data(slot),
1197                                slot+1,
1198                                spitfire_get_dtlb_tag(slot+1), spitfire_get_dtlb_data(slot+1),
1199                                slot+2,
1200                                spitfire_get_dtlb_tag(slot+2), spitfire_get_dtlb_data(slot+2));
1201                }
1202        } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
1203                printk ("Contents of dtlb0:\n");
1204                for (slot = 0; slot < 16; slot+=2) {
1205                        printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n",
1206                                slot,
1207                                cheetah_get_ldtlb_tag(slot), cheetah_get_ldtlb_data(slot),
1208                                slot+1,
1209                                cheetah_get_ldtlb_tag(slot+1), cheetah_get_ldtlb_data(slot+1));
1210                }
1211                printk ("Contents of dtlb2:\n");
1212                for (slot = 0; slot < 512; slot+=2) {
1213                        printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n",
1214                                slot,
1215                                cheetah_get_dtlb_tag(slot, 2), cheetah_get_dtlb_data(slot, 2),
1216                                slot+1,
1217                                cheetah_get_dtlb_tag(slot+1, 2), cheetah_get_dtlb_data(slot+1, 2));
1218                }
1219                if (tlb_type == cheetah_plus) {
1220                        printk ("Contents of dtlb3:\n");
1221                        for (slot = 0; slot < 512; slot+=2) {
1222                                printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx\n",
1223                                        slot,
1224                                        cheetah_get_dtlb_tag(slot, 3), cheetah_get_dtlb_data(slot, 3),
1225                                        slot+1,
1226                                        cheetah_get_dtlb_tag(slot+1, 3), cheetah_get_dtlb_data(slot+1, 3));
1227                        }
1228                }
1229        }
1230}
1231
1232extern unsigned long cmdline_memory_size;
1233
1234unsigned long __init bootmem_init(unsigned long *pages_avail)
1235{
1236        unsigned long bootmap_size, start_pfn, end_pfn;
1237        unsigned long end_of_phys_memory = 0UL;
1238        unsigned long bootmap_pfn, bytes_avail, size;
1239        int i;
1240
1241#ifdef CONFIG_DEBUG_BOOTMEM
1242        prom_printf("bootmem_init: Scan sp_banks, ");
1243#endif
1244
1245        bytes_avail = 0UL;
1246        for (i = 0; sp_banks[i].num_bytes != 0; i++) {
1247                end_of_phys_memory = sp_banks[i].base_addr +
1248                        sp_banks[i].num_bytes;
1249                bytes_avail += sp_banks[i].num_bytes;
1250                if (cmdline_memory_size) {
1251                        if (bytes_avail > cmdline_memory_size) {
1252                                unsigned long slack = bytes_avail - cmdline_memory_size;
1253
1254                                bytes_avail -= slack;
1255                                end_of_phys_memory -= slack;
1256
1257                                sp_banks[i].num_bytes -= slack;
1258                                if (sp_banks[i].num_bytes == 0) {
1259                                        sp_banks[i].base_addr = 0xdeadbeef;
1260                                } else {
1261                                        sp_banks[i+1].num_bytes = 0;
1262                                        sp_banks[i+1].base_addr = 0xdeadbeef;
1263                                }
1264                                break;
1265                        }
1266                }
1267        }
1268
1269        *pages_avail = bytes_avail >> PAGE_SHIFT;
1270
1271        /* Start with page aligned address of last symbol in kernel
1272         * image.  The kernel is hard mapped below PAGE_OFFSET in a
1273         * 4MB locked TLB translation.
1274         */
1275        start_pfn = PAGE_ALIGN(kern_base + kern_size) >> PAGE_SHIFT;
1276
1277        bootmap_pfn = start_pfn;
1278
1279        end_pfn = end_of_phys_memory >> PAGE_SHIFT;
1280
1281#ifdef CONFIG_BLK_DEV_INITRD
1282        /* Now have to check initial ramdisk, so that bootmap does not overwrite it */
1283        if (sparc_ramdisk_image || sparc_ramdisk_image64) {
1284                unsigned long ramdisk_image = sparc_ramdisk_image ?
1285                        sparc_ramdisk_image : sparc_ramdisk_image64;
1286                if (ramdisk_image >= (unsigned long)_end - 2 * PAGE_SIZE)
1287                        ramdisk_image -= KERNBASE;
1288                initrd_start = ramdisk_image + phys_base;
1289                initrd_end = initrd_start + sparc_ramdisk_size;
1290                if (initrd_end > end_of_phys_memory) {
1291                        printk(KERN_CRIT "initrd extends beyond end of memory "
1292                                         "(0x%016lx > 0x%016lx)\ndisabling initrd\n",
1293                               initrd_end, end_of_phys_memory);
1294                        initrd_start = 0;
1295                }
1296                if (initrd_start) {
1297                        if (initrd_start >= (start_pfn << PAGE_SHIFT) &&
1298                            initrd_start < (start_pfn << PAGE_SHIFT) + 2 * PAGE_SIZE)
1299                                bootmap_pfn = PAGE_ALIGN (initrd_end) >> PAGE_SHIFT;
1300                }
1301        }
1302#endif  
1303        /* Initialize the boot-time allocator. */
1304        max_pfn = max_low_pfn = end_pfn;
1305        min_low_pfn = pfn_base;
1306
1307#ifdef CONFIG_DEBUG_BOOTMEM
1308        prom_printf("init_bootmem(min[%lx], bootmap[%lx], max[%lx])\n",
1309                    min_low_pfn, bootmap_pfn, max_low_pfn);
1310#endif
1311        bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, pfn_base, end_pfn);
1312
1313        bootmap_base = bootmap_pfn << PAGE_SHIFT;
1314
1315        /* Now register the available physical memory with the
1316         * allocator.
1317         */
1318        for (i = 0; sp_banks[i].num_bytes != 0; i++) {
1319#ifdef CONFIG_DEBUG_BOOTMEM
1320                prom_printf("free_bootmem(sp_banks:%d): base[%lx] size[%lx]\n",
1321                            i, sp_banks[i].base_addr, sp_banks[i].num_bytes);
1322#endif
1323                free_bootmem(sp_banks[i].base_addr, sp_banks[i].num_bytes);
1324        }
1325
1326#ifdef CONFIG_BLK_DEV_INITRD
1327        if (initrd_start) {
1328                size = initrd_end - initrd_start;
1329
1330                /* Resert the initrd image area. */
1331#ifdef CONFIG_DEBUG_BOOTMEM
1332                prom_printf("reserve_bootmem(initrd): base[%llx] size[%lx]\n",
1333                        initrd_start, initrd_end);
1334#endif
1335                reserve_bootmem(initrd_start, size);
1336                *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
1337
1338                initrd_start += PAGE_OFFSET;
1339                initrd_end += PAGE_OFFSET;
1340        }
1341#endif
1342        /* Reserve the kernel text/data/bss. */
1343#ifdef CONFIG_DEBUG_BOOTMEM
1344        prom_printf("reserve_bootmem(kernel): base[%lx] size[%lx]\n", kern_base, kern_size);
1345#endif
1346        reserve_bootmem(kern_base, kern_size);
1347        *pages_avail -= PAGE_ALIGN(kern_size) >> PAGE_SHIFT;
1348
1349        /* Reserve the bootmem map.   We do not account for it
1350         * in pages_avail because we will release that memory
1351         * in free_all_bootmem.
1352         */
1353        size = bootmap_size;
1354#ifdef CONFIG_DEBUG_BOOTMEM
1355        prom_printf("reserve_bootmem(bootmap): base[%lx] size[%lx]\n",
1356                    (bootmap_pfn << PAGE_SHIFT), size);
1357#endif
1358        reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size);
1359        *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
1360
1361        return end_pfn;
1362}
1363
1364/* paging_init() sets up the page tables */
1365
1366extern void cheetah_ecache_flush_init(void);
1367
1368static unsigned long last_valid_pfn;
1369
1370void __init paging_init(void)
1371{
1372        extern pmd_t swapper_pmd_dir[1024];
1373        extern unsigned int sparc64_vpte_patchme1[1];
1374        extern unsigned int sparc64_vpte_patchme2[1];
1375        unsigned long alias_base = kern_base + PAGE_OFFSET;
1376        unsigned long second_alias_page = 0;
1377        unsigned long pt, flags, end_pfn, pages_avail;
1378        unsigned long shift = alias_base - ((unsigned long)KERNBASE);
1379        unsigned long real_end;
1380
1381        set_bit(0, mmu_context_bmap);
1382
1383        real_end = (unsigned long)_end;
1384        if ((real_end > ((unsigned long)KERNBASE + 0x400000)))
1385                bigkernel = 1;
1386#ifdef CONFIG_BLK_DEV_INITRD
1387        if (sparc_ramdisk_image || sparc_ramdisk_image64)
1388                real_end = (PAGE_ALIGN(real_end) + PAGE_ALIGN(sparc_ramdisk_size));
1389#endif
1390
1391        /* We assume physical memory starts at some 4mb multiple,
1392         * if this were not true we wouldn't boot up to this point
1393         * anyways.
1394         */
1395        pt  = kern_base | _PAGE_VALID | _PAGE_SZ4MB;
1396        pt |= _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W;
1397        local_irq_save(flags);
1398        if (tlb_type == spitfire) {
1399                __asm__ __volatile__(
1400        "       stxa    %1, [%0] %3\n"
1401        "       stxa    %2, [%5] %4\n"
1402        "       membar  #Sync\n"
1403        "       flush   %%g6\n"
1404        "       nop\n"
1405        "       nop\n"
1406        "       nop\n"
1407                : /* No outputs */
1408                : "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt),
1409                  "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (61 << 3)
1410                : "memory");
1411                if (real_end >= KERNBASE + 0x340000) {
1412                        second_alias_page = alias_base + 0x400000;
1413                        __asm__ __volatile__(
1414                "       stxa    %1, [%0] %3\n"
1415                "       stxa    %2, [%5] %4\n"
1416                "       membar  #Sync\n"
1417                "       flush   %%g6\n"
1418                "       nop\n"
1419                "       nop\n"
1420                "       nop\n"
1421                        : /* No outputs */
1422                        : "r" (TLB_TAG_ACCESS), "r" (second_alias_page), "r" (pt + 0x400000),
1423                          "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (60 << 3)
1424                        : "memory");
1425                }
1426        } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
1427                __asm__ __volatile__(
1428        "       stxa    %1, [%0] %3\n"
1429        "       stxa    %2, [%5] %4\n"
1430        "       membar  #Sync\n"
1431        "       flush   %%g6\n"
1432        "       nop\n"
1433        "       nop\n"
1434        "       nop\n"
1435                : /* No outputs */
1436                : "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt),
1437                  "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" ((0<<16) | (13<<3))
1438                : "memory");
1439                if (real_end >= KERNBASE + 0x340000) {
1440                        second_alias_page = alias_base + 0x400000;
1441                        __asm__ __volatile__(
1442                "       stxa    %1, [%0] %3\n"
1443                "       stxa    %2, [%5] %4\n"
1444                "       membar  #Sync\n"
1445                "       flush   %%g6\n"
1446                "       nop\n"
1447                "       nop\n"
1448                "       nop\n"
1449                        : /* No outputs */
1450                        : "r" (TLB_TAG_ACCESS), "r" (second_alias_page), "r" (pt + 0x400000),
1451                          "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" ((0<<16) | (12<<3))
1452                        : "memory");
1453                }
1454        }
1455        local_irq_restore(flags);
1456        
1457        /* Now set kernel pgd to upper alias so physical page computations
1458         * work.
1459         */
1460        init_mm.pgd += ((shift) / (sizeof(pgd_t)));
1461        
1462        memset(swapper_pmd_dir, 0, sizeof(swapper_pmd_dir));
1463
1464        /* Now can init the kernel/bad page tables. */
1465        pud_set(pud_offset(&swapper_pg_dir[0], 0),
1466                swapper_pmd_dir + (shift / sizeof(pgd_t)));
1467        
1468        sparc64_vpte_patchme1[0] |=
1469                (((unsigned long)pgd_val(init_mm.pgd[0])) >> 10);
1470        sparc64_vpte_patchme2[0] |=
1471                (((unsigned long)pgd_val(init_mm.pgd[0])) & 0x3ff);
1472        flushi((long)&sparc64_vpte_patchme1[0]);
1473        
1474        /* Setup bootmem... */
1475        pages_avail = 0;
1476        last_valid_pfn = end_pfn = bootmem_init(&pages_avail);
1477
1478        /* Inherit non-locked OBP mappings. */
1479        inherit_prom_mappings();
1480        
1481        /* Ok, we can use our TLB miss and window trap handlers safely.
1482         * We need to do a quick peek here to see if we are on StarFire
1483         * or not, so setup_tba can setup the IRQ globals correctly (it
1484         * needs to get the hard smp processor id correctly).
1485         */
1486        {
1487                extern void setup_tba(int);
1488                setup_tba(this_is_starfire);
1489        }
1490
1491        inherit_locked_prom_mappings(1);
1492
1493        /* We only created DTLB mapping of this stuff. */
1494        spitfire_flush_dtlb_nucleus_page(alias_base);
1495        if (second_alias_page)
1496                spitfire_flush_dtlb_nucleus_page(second_alias_page);
1497
1498        __flush_tlb_all();
1499
1500        {
1501                unsigned long zones_size[MAX_NR_ZONES];
1502                unsigned long zholes_size[MAX_NR_ZONES];
1503                unsigned long npages;
1504                int znum;
1505
1506                for (znum = 0; znum < MAX_NR_ZONES; znum++)
1507                        zones_size[znum] = zholes_size[znum] = 0;
1508
1509                npages = end_pfn - pfn_base;
1510                zones_size[ZONE_DMA] = npages;
1511                zholes_size[ZONE_DMA] = npages - pages_avail;
1512
1513                free_area_init_node(0, &contig_page_data, zones_size,
1514                                    phys_base >> PAGE_SHIFT, zholes_size);
1515                mem_map = contig_page_data.node_mem_map;
1516        }
1517
1518        device_scan();
1519}
1520
1521/* Ok, it seems that the prom can allocate some more memory chunks
1522 * as a side effect of some prom calls we perform during the
1523 * boot sequence.  My most likely theory is that it is from the
1524 * prom_set_traptable() call, and OBP is allocating a scratchpad
1525 * for saving client program register state etc.
1526 */
1527static void __init sort_memlist(struct linux_mlist_p1275 *thislist)
1528{
1529        int swapi = 0;
1530        int i, mitr;
1531        unsigned long tmpaddr, tmpsize;
1532        unsigned long lowest;
1533
1534        for (i = 0; thislist[i].theres_more != 0; i++) {
1535                lowest = thislist[i].start_adr;
1536                for (mitr = i+1; thislist[mitr-1].theres_more != 0; mitr++)
1537                        if (thislist[mitr].start_adr < lowest) {
1538                                lowest = thislist[mitr].start_adr;
1539                                swapi = mitr;
1540                        }
1541                if (lowest == thislist[i].start_adr)
1542                        continue;
1543                tmpaddr = thislist[swapi].start_adr;
1544                tmpsize = thislist[swapi].num_bytes;
1545                for (mitr = swapi; mitr > i; mitr--) {
1546                        thislist[mitr].start_adr = thislist[mitr-1].start_adr;
1547                        thislist[mitr].num_bytes = thislist[mitr-1].num_bytes;
1548                }
1549                thislist[i].start_adr = tmpaddr;
1550                thislist[i].num_bytes = tmpsize;
1551        }
1552}
1553
1554void __init rescan_sp_banks(void)
1555{
1556        struct linux_prom64_registers memlist[64];
1557        struct linux_mlist_p1275 avail[64], *mlist;
1558        unsigned long bytes, base_paddr;
1559        int num_regs, node = prom_finddevice("/memory");
1560        int i;
1561
1562        num_regs = prom_getproperty(node, "available",
1563                                    (char *) memlist, sizeof(memlist));
1564        num_regs = (num_regs / sizeof(struct linux_prom64_registers));
1565        for (i = 0; i < num_regs; i++) {
1566                avail[i].start_adr = memlist[i].phys_addr;
1567                avail[i].num_bytes = memlist[i].reg_size;
1568                avail[i].theres_more = &avail[i + 1];
1569        }
1570        avail[i - 1].theres_more = NULL;
1571        sort_memlist(avail);
1572
1573        mlist = &avail[0];
1574        i = 0;
1575        bytes = mlist->num_bytes;
1576        base_paddr = mlist->start_adr;
1577  
1578        sp_banks[0].base_addr = base_paddr;
1579        sp_banks[0].num_bytes = bytes;
1580
1581        while (mlist->theres_more != NULL){
1582                i++;
1583                mlist = mlist->theres_more;
1584                bytes = mlist->num_bytes;
1585                if (i >= SPARC_PHYS_BANKS-1) {
1586                        printk ("The machine has more banks than "
1587                                "this kernel can support\n"
1588                                "Increase the SPARC_PHYS_BANKS "
1589                                "setting (currently %d)\n",
1590                                SPARC_PHYS_BANKS);
1591                        i = SPARC_PHYS_BANKS-1;
1592                        break;
1593                }
1594    
1595                sp_banks[i].base_addr = mlist->start_adr;
1596                sp_banks[i].num_bytes = mlist->num_bytes;
1597        }
1598
1599        i++;
1600        sp_banks[i].base_addr = 0xdeadbeefbeefdeadUL;
1601        sp_banks[i].num_bytes = 0;
1602
1603        for (i = 0; sp_banks[i].num_bytes != 0; i++)
1604                sp_banks[i].num_bytes &= PAGE_MASK;
1605}
1606
1607static void __init taint_real_pages(void)
1608{
1609        struct sparc_phys_banks saved_sp_banks[SPARC_PHYS_BANKS];
1610        int i;
1611
1612        for (i = 0; i < SPARC_PHYS_BANKS; i++) {
1613                saved_sp_banks[i].base_addr =
1614                        sp_banks[i].base_addr;
1615                saved_sp_banks[i].num_bytes =
1616                        sp_banks[i].num_bytes;
1617        }
1618
1619        rescan_sp_banks();
1620
1621        /* Find changes discovered in the sp_bank rescan and
1622         * reserve the lost portions in the bootmem maps.
1623         */
1624        for (i = 0; saved_sp_banks[i].num_bytes; i++) {
1625                unsigned long old_start, old_end;
1626
1627                old_start = saved_sp_banks[i].base_addr;
1628                old_end = old_start +
1629                        saved_sp_banks[i].num_bytes;
1630                while (old_start < old_end) {
1631                        int n;
1632
1633                        for (n = 0; sp_banks[n].num_bytes; n++) {
1634                                unsigned long new_start, new_end;
1635
1636                                new_start = sp_banks[n].base_addr;
1637                                new_end = new_start + sp_banks[n].num_bytes;
1638
1639                                if (new_start <= old_start &&
1640                                    new_end >= (old_start + PAGE_SIZE)) {
1641                                        set_bit (old_start >> 22,
1642                                                 sparc64_valid_addr_bitmap);
1643                                        goto do_next_page;
1644                                }
1645                        }
1646                        reserve_bootmem(old_start, PAGE_SIZE);
1647
1648                do_next_page:
1649                        old_start += PAGE_SIZE;
1650                }
1651        }
1652}
1653
1654void __init mem_init(void)
1655{
1656        unsigned long codepages, datapages, initpages;
1657        unsigned long addr, last;
1658        int i;
1659
1660        i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6);
1661        i += 1;
1662        sparc64_valid_addr_bitmap = (unsigned long *)
1663                __alloc_bootmem(i << 3, SMP_CACHE_BYTES, bootmap_base);
1664        if (sparc64_valid_addr_bitmap == NULL) {
1665                prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n");
1666                prom_halt();
1667        }
1668        memset(sparc64_valid_addr_bitmap, 0, i << 3);
1669
1670        addr = PAGE_OFFSET + kern_base;
1671        last = PAGE_ALIGN(kern_size) + addr;
1672        while (addr < last) {
1673                set_bit(__pa(addr) >> 22, sparc64_valid_addr_bitmap);
1674                addr += PAGE_SIZE;
1675        }
1676
1677        taint_real_pages();
1678
1679        max_mapnr = last_valid_pfn - pfn_base;
1680        high_memory = __va(last_valid_pfn << PAGE_SHIFT);
1681
1682#ifdef CONFIG_DEBUG_BOOTMEM
1683        prom_printf("mem_init: Calling free_all_bootmem().\n");
1684#endif
1685        totalram_pages = num_physpages = free_all_bootmem() - 1;
1686
1687        /*
1688         * Set up the zero page, mark it reserved, so that page count
1689         * is not manipulated when freeing the page from user ptes.
1690         */
1691        mem_map_zero = alloc_pages(GFP_KERNEL|__GFP_ZERO, 0);
1692        if (mem_map_zero == NULL) {
1693                prom_printf("paging_init: Cannot alloc zero page.\n");
1694                prom_halt();
1695        }
1696        SetPageReserved(mem_map_zero);
1697
1698        codepages = (((unsigned long) _etext) - ((unsigned long) _start));
1699        codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT;
1700        datapages = (((unsigned long) _edata) - ((unsigned long) _etext));
1701        datapages = PAGE_ALIGN(datapages) >> PAGE_SHIFT;
1702        initpages = (((unsigned long) __init_end) - ((unsigned long) __init_begin));
1703        initpages = PAGE_ALIGN(initpages) >> PAGE_SHIFT;
1704
1705#ifndef CONFIG_SMP
1706        {
1707                /* Put empty_pg_dir on pgd_quicklist */
1708                extern pgd_t empty_pg_dir[1024];
1709                unsigned long addr = (unsigned long)empty_pg_dir;
1710                unsigned long alias_base = kern_base + PAGE_OFFSET -
1711                        (long)(KERNBASE);
1712                
1713                memset(empty_pg_dir, 0, sizeof(empty_pg_dir));
1714                addr += alias_base;
1715                free_pgd_fast((pgd_t *)addr);
1716                num_physpages++;
1717                totalram_pages++;
1718        }
1719#endif
1720
1721        printk("Memory: %uk available (%ldk kernel code, %ldk data, %ldk init) [%016lx,%016lx]\n",
1722               nr_free_pages() << (PAGE_SHIFT-10),
1723               codepages << (PAGE_SHIFT-10),
1724               datapages << (PAGE_SHIFT-10), 
1725               initpages << (PAGE_SHIFT-10), 
1726               PAGE_OFFSET, (last_valid_pfn << PAGE_SHIFT));
1727
1728        if (tlb_type == cheetah || tlb_type == cheetah_plus)
1729                cheetah_ecache_flush_init();
1730}
1731
1732void free_initmem (void)
1733{
1734        unsigned long addr, initend;
1735
1736        /*
1737         * The init section is aligned to 8k in vmlinux.lds. Page align for >8k pagesizes.
1738         */
1739        addr = PAGE_ALIGN((unsigned long)(__init_begin));
1740        initend = (unsigned long)(__init_end) & PAGE_MASK;
1741        for (; addr < initend; addr += PAGE_SIZE) {
1742                unsigned long page;
1743                struct page *p;
1744
1745                page = (addr +
1746                        ((unsigned long) __va(kern_base)) -
1747                        ((unsigned long) KERNBASE));
1748                memset((void *)addr, 0xcc, PAGE_SIZE);
1749                p = virt_to_page(page);
1750
1751                ClearPageReserved(p);
1752                set_page_count(p, 1);
1753                __free_page(p);
1754                num_physpages++;
1755                totalram_pages++;
1756        }
1757}
1758
1759#ifdef CONFIG_BLK_DEV_INITRD
1760void free_initrd_mem(unsigned long start, unsigned long end)
1761{
1762        if (start < end)
1763                printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
1764        for (; start < end; start += PAGE_SIZE) {
1765                struct page *p = virt_to_page(start);
1766
1767                ClearPageReserved(p);
1768                set_page_count(p, 1);
1769                __free_page(p);
1770                num_physpages++;
1771                totalram_pages++;
1772        }
1773}
1774#endif
1775
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.