linux-bk/arch/mips/mm/mips32.c
<<
>>
Prefs
   1/*
   2 * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
   3 * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
   4 *
   5 * This program is free software; you can distribute it and/or modify it
   6 * under the terms of the GNU General Public License (Version 2) as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12 * for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License along
  15 * with this program; if not, write to the Free Software Foundation, Inc.,
  16 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  17 *
  18 * MIPS32 CPU variant specific MMU/Cache routines.
  19 */
  20#include <linux/init.h>
  21#include <linux/kernel.h>
  22#include <linux/sched.h>
  23#include <linux/mm.h>
  24
  25#include <asm/bootinfo.h>
  26#include <asm/cpu.h>
  27#include <asm/bcache.h>
  28#include <asm/io.h>
  29#include <asm/page.h>
  30#include <asm/pgtable.h>
  31#include <asm/system.h>
  32#include <asm/mmu_context.h>
  33
  34/* CP0 hazard avoidance. */
  35#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
  36                                     "nop; nop; nop; nop; nop; nop;\n\t" \
  37                                     ".set reorder\n\t")
  38
  39/* Primary cache parameters. */
  40static int icache_size, dcache_size; /* Size in bytes */
  41static int ic_lsize, dc_lsize;       /* LineSize in bytes */
  42
  43/* Secondary cache (if present) parameters. */
  44static unsigned int scache_size, sc_lsize;      /* Again, in bytes */
  45
  46#include <asm/cacheops.h>
  47#include <asm/mips32_cache.h>
  48
  49#undef DEBUG_CACHE
  50
  51/*
  52 * Dummy cache handling routines for machines without boardcaches
  53 */
  54static void no_sc_noop(void) {}
  55
  56static struct bcache_ops no_sc_ops = {
  57        (void *)no_sc_noop, (void *)no_sc_noop,
  58        (void *)no_sc_noop, (void *)no_sc_noop
  59};
  60
  61struct bcache_ops *bcops = &no_sc_ops;
  62
  63
  64/*
  65 * Zero an entire page.
  66 */
  67
  68static void mips32_clear_page_dc(unsigned long page)
  69{
  70        unsigned long i;
  71
  72        if (mips_cpu.options & MIPS_CPU_CACHE_CDEX) {
  73                for (i=page; i<page+PAGE_SIZE; i+=dc_lsize) {
  74                        __asm__ __volatile__(
  75                                ".set\tnoreorder\n\t"
  76                                ".set\tnoat\n\t"
  77                                ".set\tmips3\n\t"
  78                                "cache\t%2,(%0)\n\t"
  79                                ".set\tmips0\n\t"
  80                                ".set\tat\n\t"
  81                                ".set\treorder"
  82                                :"=r" (i)
  83                                :"0" (i),
  84                                "I" (Create_Dirty_Excl_D));
  85                }
  86        }
  87        for (i=page; i<page+PAGE_SIZE; i+=4)
  88                *(unsigned long *)(i) = 0;
  89}
  90
  91static void mips32_clear_page_sc(unsigned long page)
  92{
  93        unsigned long i;
  94
  95        if (mips_cpu.options & MIPS_CPU_CACHE_CDEX) {
  96                for (i=page; i<page+PAGE_SIZE; i+=sc_lsize) {
  97                        __asm__ __volatile__(
  98                                ".set\tnoreorder\n\t"
  99                                ".set\tnoat\n\t"
 100                                ".set\tmips3\n\t"
 101                                "cache\t%2,(%0)\n\t"
 102                                ".set\tmips0\n\t"
 103                                ".set\tat\n\t"
 104                                ".set\treorder"
 105                                :"=r" (i)
 106                                :"0" (i),
 107                                "I" (Create_Dirty_Excl_SD));
 108                }
 109        }
 110        for (i=page; i<page+PAGE_SIZE; i+=4)
 111                *(unsigned long *)(i) = 0;
 112}
 113
 114static void mips32_copy_page_dc(unsigned long to, unsigned long from)
 115{
 116        unsigned long i;
 117
 118        if (mips_cpu.options & MIPS_CPU_CACHE_CDEX) {
 119                for (i=to; i<to+PAGE_SIZE; i+=dc_lsize) {
 120                        __asm__ __volatile__(
 121                                ".set\tnoreorder\n\t"
 122                                ".set\tnoat\n\t"
 123                                ".set\tmips3\n\t"
 124                                "cache\t%2,(%0)\n\t"
 125                                ".set\tmips0\n\t"
 126                                ".set\tat\n\t"
 127                                ".set\treorder"
 128                                :"=r" (i)
 129                                :"0" (i),
 130                                "I" (Create_Dirty_Excl_D));
 131                }
 132        }
 133        for (i=0; i<PAGE_SIZE; i+=4)
 134                *(unsigned long *)(to+i) = *(unsigned long *)(from+i);
 135}
 136
 137static void mips32_copy_page_sc(unsigned long to, unsigned long from)
 138{
 139        unsigned long i;
 140
 141        if (mips_cpu.options & MIPS_CPU_CACHE_CDEX) {
 142                for (i=to; i<to+PAGE_SIZE; i+=sc_lsize) {
 143                        __asm__ __volatile__(
 144                                ".set\tnoreorder\n\t"
 145                                ".set\tnoat\n\t"
 146                                ".set\tmips3\n\t"
 147                                "cache\t%2,(%0)\n\t"
 148                                ".set\tmips0\n\t"
 149                                ".set\tat\n\t"
 150                                ".set\treorder"
 151                                :"=r" (i)
 152                                :"0" (i),
 153                                "I" (Create_Dirty_Excl_SD));
 154                }
 155        }
 156        for (i=0; i<PAGE_SIZE; i+=4)
 157                *(unsigned long *)(to+i) = *(unsigned long *)(from+i);
 158}
 159
 160static inline void mips32_flush_cache_all_sc(void)
 161{
 162        unsigned long flags;
 163
 164        local_irq_save(flags);
 165        blast_dcache(); blast_icache(); blast_scache();
 166        local_irq_restore(flags);
 167}
 168
 169static inline void mips32_flush_cache_all_pc(void)
 170{
 171        unsigned long flags;
 172
 173        local_irq_save(flags);
 174        blast_dcache(); blast_icache();
 175        local_irq_restore(flags);
 176}
 177
 178static void
 179mips32_flush_cache_range_sc(struct vm_area_struct *vma,
 180                         unsigned long start,
 181                         unsigned long end)
 182{
 183        struct mm_struct *mm = vma->vm_mm;
 184        unsigned long flags;
 185
 186        if(mm->context == 0)
 187                return;
 188
 189        start &= PAGE_MASK;
 190#ifdef DEBUG_CACHE
 191        printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
 192#endif
 193        if (vma) {
 194                if(mm->context != current->mm->context) {
 195                        mips32_flush_cache_all_sc();
 196                } else {
 197                        pgd_t *pgd;
 198                        pmd_t *pmd;
 199                        pte_t *pte;
 200
 201                        local_irq_save(flags);
 202                        while(start < end) {
 203                                pgd = pgd_offset(mm, start);
 204                                pmd = pmd_offset(pgd, start);
 205                                pte = pte_offset(pmd, start);
 206
 207                                if(pte_val(*pte) & _PAGE_VALID)
 208                                        blast_scache_page(start);
 209                                start += PAGE_SIZE;
 210                        }
 211                        local_irq_restore(flags);
 212                }
 213        }
 214}
 215
 216static void mips32_flush_cache_range_pc(struct vm_area_struct *vma,
 217                                     unsigned long start,
 218                                     unsigned long end)
 219{
 220        struct mm_struct *mm = vma->vm_mm;
 221
 222        if(mm->context != 0) {
 223                unsigned long flags;
 224
 225#ifdef DEBUG_CACHE
 226                printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
 227#endif
 228                local_irq_save(flags);
 229                blast_dcache(); blast_icache();
 230                local_irq_restore(flags);
 231        }
 232}
 233
 234/*
 235 * On architectures like the Sparc, we could get rid of lines in
 236 * the cache created only by a certain context, but on the MIPS
 237 * (and actually certain Sparc's) we cannot.
 238 */
 239static void mips32_flush_cache_mm_sc(struct mm_struct *mm)
 240{
 241        if(mm->context != 0) {
 242#ifdef DEBUG_CACHE
 243                printk("cmm[%d]", (int)mm->context);
 244#endif
 245                mips32_flush_cache_all_sc();
 246        }
 247}
 248
 249static void mips32_flush_cache_mm_pc(struct mm_struct *mm)
 250{
 251        if(mm->context != 0) {
 252#ifdef DEBUG_CACHE
 253                printk("cmm[%d]", (int)mm->context);
 254#endif
 255                mips32_flush_cache_all_pc();
 256        }
 257}
 258
 259
 260
 261
 262
 263static void mips32_flush_cache_page_sc(struct vm_area_struct *vma,
 264                                    unsigned long page)
 265{
 266        struct mm_struct *mm = vma->vm_mm;
 267        unsigned long flags;
 268        pgd_t *pgdp;
 269        pmd_t *pmdp;
 270        pte_t *ptep;
 271
 272        /*
 273         * If ownes no valid ASID yet, cannot possibly have gotten
 274         * this page into the cache.
 275         */
 276        if (mm->context == 0)
 277                return;
 278
 279#ifdef DEBUG_CACHE
 280        printk("cpage[%d,%08lx]", (int)mm->context, page);
 281#endif
 282        local_irq_save(flags);
 283        page &= PAGE_MASK;
 284        pgdp = pgd_offset(mm, page);
 285        pmdp = pmd_offset(pgdp, page);
 286        ptep = pte_offset(pmdp, page);
 287
 288        /*
 289         * If the page isn't marked valid, the page cannot possibly be
 290         * in the cache.
 291         */
 292        if (!(pte_val(*ptep) & _PAGE_VALID))
 293                goto out;
 294
 295        /*
 296         * Doing flushes for another ASID than the current one is
 297         * too difficult since R4k caches do a TLB translation
 298         * for every cache flush operation.  So we do indexed flushes
 299         * in that case, which doesn't overly flush the cache too much.
 300         */
 301        if (mm->context != current->active_mm->context) {
 302                /*
 303                 * Do indexed flush, too much work to get the (possible)
 304                 * tlb refills to work correctly.
 305                 */
 306                page = (KSEG0 + (page & (scache_size - 1)));
 307                blast_dcache_page_indexed(page);
 308                blast_scache_page_indexed(page);
 309        } else
 310                blast_scache_page(page);
 311out:
 312        local_irq_restore(flags);
 313}
 314
 315static void mips32_flush_cache_page_pc(struct vm_area_struct *vma,
 316                                    unsigned long page)
 317{
 318        struct mm_struct *mm = vma->vm_mm;
 319        unsigned long flags;
 320        pgd_t *pgdp;
 321        pmd_t *pmdp;
 322        pte_t *ptep;
 323
 324        /*
 325         * If ownes no valid ASID yet, cannot possibly have gotten
 326         * this page into the cache.
 327         */
 328        if (mm->context == 0)
 329                return;
 330
 331#ifdef DEBUG_CACHE
 332        printk("cpage[%d,%08lx]", (int)mm->context, page);
 333#endif
 334        local_irq_save(flags);
 335        page &= PAGE_MASK;
 336        pgdp = pgd_offset(mm, page);
 337        pmdp = pmd_offset(pgdp, page);
 338        ptep = pte_offset(pmdp, page);
 339
 340        /*
 341         * If the page isn't marked valid, the page cannot possibly be
 342         * in the cache.
 343         */
 344        if (!(pte_val(*ptep) & _PAGE_VALID))
 345                goto out;
 346
 347        /*
 348         * Doing flushes for another ASID than the current one is
 349         * too difficult since Mips32 caches do a TLB translation
 350         * for every cache flush operation.  So we do indexed flushes
 351         * in that case, which doesn't overly flush the cache too much.
 352         */
 353        if (mm == current->active_mm) {
 354                blast_dcache_page(page);
 355        } else {
 356                /* Do indexed flush, too much work to get the (possible)
 357                 * tlb refills to work correctly.
 358                 */
 359                page = (KSEG0 + (page & (dcache_size - 1)));
 360                blast_dcache_page_indexed(page);
 361        }
 362out:
 363        local_irq_restore(flags);
 364}
 365
 366/* If the addresses passed to these routines are valid, they are
 367 * either:
 368 *
 369 * 1) In KSEG0, so we can do a direct flush of the page.
 370 * 2) In KSEG2, and since every process can translate those
 371 *    addresses all the time in kernel mode we can do a direct
 372 *    flush.
 373 * 3) In KSEG1, no flush necessary.
 374 */
 375static void mips32_flush_page_to_ram_sc(struct page *page)
 376{
 377        blast_scache_page((unsigned long)page_address(page));
 378}
 379
 380static void mips32_flush_page_to_ram_pc(struct page *page)
 381{
 382        blast_dcache_page((unsigned long)page_address(page));
 383}
 384
 385static void
 386mips32_flush_icache_page_s(struct vm_area_struct *vma, struct page *page)
 387{
 388        /*
 389         * We did an scache flush therefore PI is already clean.
 390         */
 391}
 392
 393static void
 394mips32_flush_icache_range(unsigned long start, unsigned long end)
 395{
 396        flush_cache_all();
 397}
 398
 399static void
 400mips32_flush_icache_page(struct vm_area_struct *vma, struct page *page)
 401{
 402        int address;
 403
 404        if (!(vma->vm_flags & VM_EXEC))
 405                return;
 406
 407        address = KSEG0 + ((unsigned long)page_address(page) & PAGE_MASK & (dcache_size - 1));
 408        blast_icache_page_indexed(address);
 409}
 410
 411/*
 412 * Writeback and invalidate the primary cache dcache before DMA.
 413 */
 414static void
 415mips32_dma_cache_wback_inv_pc(unsigned long addr, unsigned long size)
 416{
 417        unsigned long end, a;
 418        unsigned int flags;
 419
 420        if (size >= dcache_size) {
 421                flush_cache_all();
 422        } else {
 423                local_irq_save(flags);
 424                a = addr & ~(dc_lsize - 1);
 425                end = (addr + size) & ~(dc_lsize - 1);
 426                while (1) {
 427                        flush_dcache_line(a); /* Hit_Writeback_Inv_D */
 428                        if (a == end) break;
 429                        a += dc_lsize;
 430                }
 431                local_irq_restore(flags);
 432        }
 433        bc_wback_inv(addr, size);
 434}
 435
 436static void
 437mips32_dma_cache_wback_inv_sc(unsigned long addr, unsigned long size)
 438{
 439        unsigned long end, a;
 440
 441        if (size >= scache_size) {
 442                flush_cache_all();
 443                return;
 444        }
 445
 446        a = addr & ~(sc_lsize - 1);
 447        end = (addr + size) & ~(sc_lsize - 1);
 448        while (1) {
 449                flush_scache_line(a);   /* Hit_Writeback_Inv_SD */
 450                if (a == end) break;
 451                a += sc_lsize;
 452        }
 453}
 454
 455static void
 456mips32_dma_cache_inv_pc(unsigned long addr, unsigned long size)
 457{
 458        unsigned long end, a;
 459        unsigned int flags;
 460
 461        if (size >= dcache_size) {
 462                flush_cache_all();
 463        } else {
 464                local_irq_save(flags);
 465                a = addr & ~(dc_lsize - 1);
 466                end = (addr + size) & ~(dc_lsize - 1);
 467                while (1) {
 468                        flush_dcache_line(a); /* Hit_Writeback_Inv_D */
 469                        if (a == end) break;
 470                        a += dc_lsize;
 471                }
 472                local_irq_restore(flags);
 473        }
 474
 475        bc_inv(addr, size);
 476}
 477
 478static void
 479mips32_dma_cache_inv_sc(unsigned long addr, unsigned long size)
 480{
 481        unsigned long end, a;
 482
 483        if (size >= scache_size) {
 484                flush_cache_all();
 485                return;
 486        }
 487
 488        a = addr & ~(sc_lsize - 1);
 489        end = (addr + size) & ~(sc_lsize - 1);
 490        while (1) {
 491                flush_scache_line(a); /* Hit_Writeback_Inv_SD */
 492                if (a == end) break;
 493                a += sc_lsize;
 494        }
 495}
 496
 497static void
 498mips32_dma_cache_wback(unsigned long addr, unsigned long size)
 499{
 500        panic("mips32_dma_cache called - should not happen.\n");
 501}
 502
 503/*
 504 * While we're protected against bad userland addresses we don't care
 505 * very much about what happens in that case.  Usually a segmentation
 506 * fault will dump the process later on anyway ...
 507 */
 508static void mips32_flush_cache_sigtramp(unsigned long addr)
 509{
 510        protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
 511        protected_flush_icache_line(addr & ~(ic_lsize - 1));
 512}
 513
 514#undef DEBUG_TLB
 515#undef DEBUG_TLBUPDATE
 516
 517void flush_tlb_all(void)
 518{
 519        unsigned long flags;
 520        unsigned long old_ctx;
 521        int entry;
 522
 523#ifdef DEBUG_TLB
 524        printk("[tlball]");
 525#endif
 526
 527        local_irq_save(flags);
 528        /* Save old context and create impossible VPN2 value */
 529        old_ctx = (get_entryhi() & 0xff);
 530        set_entryhi(KSEG0);
 531        set_entrylo0(0);
 532        set_entrylo1(0);
 533        BARRIER;
 534
 535        entry = get_wired();
 536
 537        /* Blast 'em all away. */
 538        while(entry < mips_cpu.tlbsize) {
 539                /* Make sure all entries differ. */  
 540                set_entryhi(KSEG0+entry*0x2000);
 541                set_index(entry);
 542                BARRIER;
 543                tlb_write_indexed();
 544                BARRIER;
 545                entry++;
 546        }
 547        BARRIER;
 548        set_entryhi(old_ctx);
 549        local_irq_restore(flags);
 550}
 551
 552void flush_tlb_mm(struct mm_struct *mm)
 553{
 554        if (mm->context != 0) {
 555                unsigned long flags;
 556
 557#ifdef DEBUG_TLB
 558                printk("[tlbmm<%d>]", mm->context);
 559#endif
 560                local_irq_save(flags);
 561                get_new_mmu_context(mm, asid_cache);
 562                if (mm == current->active_mm)
 563                        set_entryhi(mm->context & 0xff);
 564                local_irq_restore(flags);
 565        }
 566}
 567
 568void flush_tlb_range(struct mm_struct *mm, unsigned long start,
 569                                unsigned long end)
 570{
 571        if(mm->context != 0) {
 572                unsigned long flags;
 573                int size;
 574
 575#ifdef DEBUG_TLB
 576                printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff),
 577                       start, end);
 578#endif
 579                local_irq_save(flags);
 580                size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
 581                size = (size + 1) >> 1;
 582                if(size <= mips_cpu.tlbsize/2) {
 583                        int oldpid = (get_entryhi() & 0xff);
 584                        int newpid = (mm->context & 0xff);
 585
 586                        start &= (PAGE_MASK << 1);
 587                        end += ((PAGE_SIZE << 1) - 1);
 588                        end &= (PAGE_MASK << 1);
 589                        while(start < end) {
 590                                int idx;
 591
 592                                set_entryhi(start | newpid);
 593                                start += (PAGE_SIZE << 1);
 594                                BARRIER;
 595                                tlb_probe();
 596                                BARRIER;
 597                                idx = get_index();
 598                                set_entrylo0(0);
 599                                set_entrylo1(0);
 600                                if(idx < 0)
 601                                        continue;
 602                                /* Make sure all entries differ. */
 603                                set_entryhi(KSEG0+idx*0x2000);
 604                                BARRIER;
 605                                tlb_write_indexed();
 606                                BARRIER;
 607                        }
 608                        set_entryhi(oldpid);
 609                } else {
 610                        get_new_mmu_context(mm, asid_cache);
 611                        if (mm == current->active_mm)
 612                                set_entryhi(mm->context & 0xff);
 613                }
 614                local_irq_restore(flags);
 615        }
 616}
 617
 618void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 619{
 620        if (vma->vm_mm->context != 0) {
 621                unsigned long flags;
 622                int oldpid, newpid, idx;
 623
 624#ifdef DEBUG_TLB
 625                printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page);
 626#endif
 627                newpid = (vma->vm_mm->context & 0xff);
 628                page &= (PAGE_MASK << 1);
 629                local_irq_save(flags);
 630                oldpid = (get_entryhi() & 0xff);
 631                set_entryhi(page | newpid);
 632                BARRIER;
 633                tlb_probe();
 634                BARRIER;
 635                idx = get_index();
 636                set_entrylo0(0);
 637                set_entrylo1(0);
 638                if(idx < 0)
 639                        goto finish;
 640                /* Make sure all entries differ. */  
 641                set_entryhi(KSEG0+idx*0x2000);
 642                BARRIER;
 643                tlb_write_indexed();
 644
 645        finish:
 646                BARRIER;
 647                set_entryhi(oldpid);
 648                local_irq_restore(flags);
 649        }
 650}
 651
 652void pgd_init(unsigned long page)
 653{
 654        unsigned long *p = (unsigned long *) page;
 655        int i;
 656
 657        for(i = 0; i < USER_PTRS_PER_PGD; i+=8) {
 658                p[i + 0] = (unsigned long) invalid_pte_table;
 659                p[i + 1] = (unsigned long) invalid_pte_table;
 660                p[i + 2] = (unsigned long) invalid_pte_table;
 661                p[i + 3] = (unsigned long) invalid_pte_table;
 662                p[i + 4] = (unsigned long) invalid_pte_table;
 663                p[i + 5] = (unsigned long) invalid_pte_table;
 664                p[i + 6] = (unsigned long) invalid_pte_table;
 665                p[i + 7] = (unsigned long) invalid_pte_table;
 666        }
 667}
 668
 669/* 
 670 * Updates the TLB with the new pte(s).
 671 */
 672void update_mmu_cache(struct vm_area_struct * vma,
 673                      unsigned long address, pte_t pte)
 674{
 675        unsigned long flags;
 676        pgd_t *pgdp;
 677        pmd_t *pmdp;
 678        pte_t *ptep;
 679        int idx, pid;
 680
 681        /*
 682         * Handle debugger faulting in for debugee.
 683         */
 684        if (current->active_mm != vma->vm_mm)
 685                return;
 686
 687        pid = get_entryhi() & 0xff;
 688
 689#ifdef DEBUG_TLB
 690        if((pid != (vma->vm_mm->context & 0xff)) || (vma->vm_mm->context == 0)) {
 691                printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n",
 692                       (int) (vma->vm_mm->context & 0xff), pid);
 693        }
 694#endif
 695
 696        local_irq_save(flags);
 697        address &= (PAGE_MASK << 1);
 698        set_entryhi(address | (pid));
 699        pgdp = pgd_offset(vma->vm_mm, address);
 700        BARRIER;
 701        tlb_probe();
 702        BARRIER;
 703        pmdp = pmd_offset(pgdp, address);
 704        idx = get_index();
 705        ptep = pte_offset(pmdp, address);
 706        BARRIER;
 707        set_entrylo0(pte_val(*ptep++) >> 6);
 708        set_entrylo1(pte_val(*ptep) >> 6);
 709        set_entryhi(address | (pid));
 710        BARRIER;
 711        if(idx < 0) {
 712                tlb_write_random();
 713        } else {
 714                tlb_write_indexed();
 715        }
 716        BARRIER;
 717        set_entryhi(pid);
 718        BARRIER;
 719        local_irq_restore(flags);
 720}
 721
 722void show_regs(struct pt_regs * regs)
 723{
 724        /* Saved main processor registers. */
 725        printk("$0 : %08lx %08lx %08lx %08lx\n",
 726               0UL, regs->regs[1], regs->regs[2], regs->regs[3]);
 727        printk("$4 : %08lx %08lx %08lx %08lx\n",
 728               regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]);
 729        printk("$8 : %08lx %08lx %08lx %08lx\n",
 730               regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11]);
 731        printk("$12: %08lx %08lx %08lx %08lx\n",
 732               regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]);
 733        printk("$16: %08lx %08lx %08lx %08lx\n",
 734               regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19]);
 735        printk("$20: %08lx %08lx %08lx %08lx\n",
 736               regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]);
 737        printk("$24: %08lx %08lx\n",
 738               regs->regs[24], regs->regs[25]);
 739        printk("$28: %08lx %08lx %08lx %08lx\n",
 740               regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]);
 741
 742        /* Saved cp0 registers. */
 743        printk("epc   : %08lx    %s\nStatus: %08lx\nCause : %08lx\n",
 744               regs->cp0_epc, print_tainted(), regs->cp0_status, regs->cp0_cause);
 745}
 746                        
 747void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
 748                                      unsigned long entryhi, unsigned long pagemask)
 749{
 750        unsigned long flags;
 751        unsigned long wired;
 752        unsigned long old_pagemask;
 753        unsigned long old_ctx;
 754
 755        local_irq_save(flags);
 756        /* Save old context and create impossible VPN2 value */
 757        old_ctx = (get_entryhi() & 0xff);
 758        old_pagemask = get_pagemask();
 759        wired = get_wired();
 760        set_wired (wired + 1);
 761        set_index (wired);
 762        BARRIER;    
 763        set_pagemask (pagemask);
 764        set_entryhi(entryhi);
 765        set_entrylo0(entrylo0);
 766        set_entrylo1(entrylo1);
 767        BARRIER;    
 768        tlb_write_indexed();
 769        BARRIER;    
 770    
 771        set_entryhi(old_ctx);
 772        BARRIER;    
 773        set_pagemask (old_pagemask);
 774        flush_tlb_all();    
 775        local_irq_restore(flags);
 776}
 777
 778/* Detect and size the various caches. */
 779static void __init probe_icache(unsigned long config)
 780{
 781        unsigned long config1;
 782        unsigned int lsize;
 783
 784        if (!(config & (1 << 31))) {
 785                /* 
 786                 * Not a MIPS32 complainant CPU. 
 787                 * Config 1 register not supported, we assume R4k style.
 788                 */
 789                icache_size = 1 << (12 + ((config >> 9) & 7));
 790                ic_lsize = 16 << ((config >> 5) & 1);
 791                mips_cpu.icache.linesz = ic_lsize;
 792                
 793                /* 
 794                 * We cannot infer associativity - assume direct map
 795                 * unless probe template indicates otherwise
 796                 */
 797                if(!mips_cpu.icache.ways) mips_cpu.icache.ways = 1;
 798                mips_cpu.icache.sets = 
 799                        (icache_size / ic_lsize) / mips_cpu.icache.ways;
 800        } else {
 801               config1 = read_mips32_cp0_config1(); 
 802
 803               if ((lsize = ((config1 >> 19) & 7)))
 804                       mips_cpu.icache.linesz = 2 << lsize;
 805               else 
 806                       mips_cpu.icache.linesz = lsize;
 807               mips_cpu.icache.sets = 64 << ((config1 >> 22) & 7);
 808               mips_cpu.icache.ways = 1 + ((config1 >> 16) & 7);
 809
 810               ic_lsize = mips_cpu.icache.linesz;
 811               icache_size = mips_cpu.icache.sets * mips_cpu.icache.ways * 
 812                             ic_lsize;
 813        }
 814        printk("Primary instruction cache %dkb, linesize %d bytes (%d ways)\n",
 815               icache_size >> 10, ic_lsize, mips_cpu.icache.ways);
 816}
 817
 818static void __init probe_dcache(unsigned long config)
 819{
 820        unsigned long config1;
 821        unsigned int lsize;
 822
 823        if (!(config & (1 << 31))) {
 824                /* 
 825                 * Not a MIPS32 complainant CPU. 
 826                 * Config 1 register not supported, we assume R4k style.
 827                 */  
 828                dcache_size = 1 << (12 + ((config >> 6) & 7));
 829                dc_lsize = 16 << ((config >> 4) & 1);
 830                mips_cpu.dcache.linesz = dc_lsize;
 831                /* 
 832                 * We cannot infer associativity - assume direct map
 833                 * unless probe template indicates otherwise
 834                 */
 835                if(!mips_cpu.dcache.ways) mips_cpu.dcache.ways = 1;
 836                mips_cpu.dcache.sets = 
 837                        (dcache_size / dc_lsize) / mips_cpu.dcache.ways;
 838        } else {
 839                config1 = read_mips32_cp0_config1();
 840
 841                if ((lsize = ((config1 >> 10) & 7)))
 842                        mips_cpu.dcache.linesz = 2 << lsize;
 843                else 
 844                        mips_cpu.dcache.linesz= lsize;
 845                mips_cpu.dcache.sets = 64 << ((config1 >> 13) & 7);
 846                mips_cpu.dcache.ways = 1 + ((config1 >> 7) & 7);
 847
 848                dc_lsize = mips_cpu.dcache.linesz;
 849                dcache_size = 
 850                        mips_cpu.dcache.sets * mips_cpu.dcache.ways
 851                        * dc_lsize;
 852        }
 853        printk("Primary data cache %dkb, linesize %d bytes (%d ways)\n",
 854               dcache_size >> 10, dc_lsize, mips_cpu.dcache.ways);
 855}
 856
 857
 858/* If you even _breathe_ on this function, look at the gcc output
 859 * and make sure it does not pop things on and off the stack for
 860 * the cache sizing loop that executes in KSEG1 space or else
 861 * you will crash and burn badly.  You have been warned.
 862 */
 863static int __init probe_scache(unsigned long config)
 864{
 865        extern unsigned long stext;
 866        unsigned long flags, addr, begin, end, pow2;
 867        int tmp;
 868
 869        if (mips_cpu.scache.flags == MIPS_CACHE_NOT_PRESENT)
 870                return 0;
 871
 872        tmp = ((config >> 17) & 1);
 873        if(tmp)
 874                return 0;
 875        tmp = ((config >> 22) & 3);
 876        switch(tmp) {
 877        case 0:
 878                sc_lsize = 16;
 879                break;
 880        case 1:
 881                sc_lsize = 32;
 882                break;
 883        case 2:
 884                sc_lsize = 64;
 885                break;
 886        case 3:
 887                sc_lsize = 128;
 888                break;
 889        }
 890
 891        begin = (unsigned long) &stext;
 892        begin &= ~((4 * 1024 * 1024) - 1);
 893        end = begin + (4 * 1024 * 1024);
 894
 895        /* This is such a bitch, you'd think they would make it
 896         * easy to do this.  Away you daemons of stupidity!
 897         */
 898        local_irq_save(flags);
 899
 900        /* Fill each size-multiple cache line with a valid tag. */
 901        pow2 = (64 * 1024);
 902        for(addr = begin; addr < end; addr = (begin + pow2)) {
 903                unsigned long *p = (unsigned long *) addr;
 904                __asm__ __volatile__("nop" : : "r" (*p)); /* whee... */
 905                pow2 <<= 1;
 906        }
 907
 908        /* Load first line with zero (therefore invalid) tag. */
 909        set_taglo(0);
 910        set_taghi(0);
 911        __asm__ __volatile__("nop; nop; nop; nop;"); /* avoid the hazard */
 912        __asm__ __volatile__("\n\t.set noreorder\n\t"
 913                             ".set mips3\n\t"
 914                             "cache 8, (%0)\n\t"
 915                             ".set mips0\n\t"
 916                             ".set reorder\n\t" : : "r" (begin));
 917        __asm__ __volatile__("\n\t.set noreorder\n\t"
 918                             ".set mips3\n\t"
 919                             "cache 9, (%0)\n\t"
 920                             ".set mips0\n\t"
 921                             ".set reorder\n\t" : : "r" (begin));
 922        __asm__ __volatile__("\n\t.set noreorder\n\t"
 923                             ".set mips3\n\t"
 924                             "cache 11, (%0)\n\t"
 925                             ".set mips0\n\t"
 926                             ".set reorder\n\t" : : "r" (begin));
 927
 928        /* Now search for the wrap around point. */
 929        pow2 = (128 * 1024);
 930        tmp = 0;
 931        for(addr = (begin + (128 * 1024)); addr < (end); addr = (begin + pow2)) {
 932                __asm__ __volatile__("\n\t.set noreorder\n\t"
 933                                     ".set mips3\n\t"
 934                                     "cache 7, (%0)\n\t"
 935                                     ".set mips0\n\t"
 936                                     ".set reorder\n\t" : : "r" (addr));
 937                __asm__ __volatile__("nop; nop; nop; nop;"); /* hazard... */
 938                if(!get_taglo())
 939                        break;
 940                pow2 <<= 1;
 941        }
 942        local_irq_restore(flags);
 943        addr -= begin;
 944        printk("Secondary cache sized at %dK linesize %d bytes.\n",
 945               (int) (addr >> 10), sc_lsize);
 946        scache_size = addr;
 947        return 1;
 948}
 949
 950static void __init setup_noscache_funcs(void)
 951{
 952        _clear_page = (void *)mips32_clear_page_dc;
 953        _copy_page = (void *)mips32_copy_page_dc;
 954        _flush_cache_all = mips32_flush_cache_all_pc;
 955        ___flush_cache_all = mips32_flush_cache_all_pc;
 956        _flush_cache_mm = mips32_flush_cache_mm_pc;
 957        _flush_cache_range = mips32_flush_cache_range_pc;
 958        _flush_cache_page = mips32_flush_cache_page_pc;
 959        _flush_page_to_ram = mips32_flush_page_to_ram_pc;
 960
 961        _flush_icache_page = mips32_flush_icache_page;
 962
 963        _dma_cache_wback_inv = mips32_dma_cache_wback_inv_pc;
 964        _dma_cache_wback = mips32_dma_cache_wback;
 965        _dma_cache_inv = mips32_dma_cache_inv_pc;
 966}
 967
 968static void __init setup_scache_funcs(void)
 969{
 970        _flush_cache_all = mips32_flush_cache_all_sc;
 971        ___flush_cache_all = mips32_flush_cache_all_sc;
 972        _flush_cache_mm = mips32_flush_cache_mm_sc;
 973        _flush_cache_range = mips32_flush_cache_range_sc;
 974        _flush_cache_page = mips32_flush_cache_page_sc;
 975        _flush_page_to_ram = mips32_flush_page_to_ram_sc;
 976        _clear_page = (void *)mips32_clear_page_sc;
 977        _copy_page = (void *)mips32_copy_page_sc;
 978
 979        _flush_icache_page = mips32_flush_icache_page_s;
 980
 981        _dma_cache_wback_inv = mips32_dma_cache_wback_inv_sc;
 982        _dma_cache_wback = mips32_dma_cache_wback;
 983        _dma_cache_inv = mips32_dma_cache_inv_sc;
 984}
 985
 986typedef int (*probe_func_t)(unsigned long);
 987
 988static inline void __init setup_scache(unsigned int config)
 989{
 990        probe_func_t probe_scache_kseg1;
 991        int sc_present = 0;
 992
 993        /* Maybe the cpu knows about a l2 cache? */
 994        probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache));
 995        sc_present = probe_scache_kseg1(config);
 996
 997        if (sc_present) {
 998                mips_cpu.scache.linesz = sc_lsize;
 999                /* 
1000                 * We cannot infer associativity - assume direct map
1001                 * unless probe template indicates otherwise
1002                 */
1003                if(!mips_cpu.scache.ways) mips_cpu.scache.ways = 1;
1004                mips_cpu.scache.sets = 
1005                  (scache_size / sc_lsize) / mips_cpu.scache.ways;
1006
1007                setup_scache_funcs();
1008                return;
1009        }
1010
1011        setup_noscache_funcs();
1012}
1013
1014static void __init probe_tlb(unsigned long config)
1015{
1016        unsigned long config1;
1017
1018        if (!(config & (1 << 31))) {
1019                /* 
1020                 * Not a MIPS32 complainant CPU. 
1021                 * Config 1 register not supported, we assume R4k style.
1022                 */  
1023                mips_cpu.tlbsize = 48;
1024        } else {
1025                config1 = read_mips32_cp0_config1();
1026                if (!((config >> 7) & 3))
1027                        panic("No MMU present");
1028                else
1029                        mips_cpu.tlbsize = ((config1 >> 25) & 0x3f) + 1;
1030        }       
1031
1032        printk("Number of TLB entries %d.\n", mips_cpu.tlbsize);
1033}
1034
1035void __init ld_mmu_mips32(void)
1036{
1037        unsigned long config = read_32bit_cp0_register(CP0_CONFIG);
1038
1039        printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID));
1040
1041#ifdef CONFIG_MIPS_UNCACHED
1042        change_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
1043#else
1044        change_cp0_config(CONF_CM_CMASK, CONF_CM_CACHABLE_NONCOHERENT);
1045#endif
1046
1047        probe_icache(config);
1048        probe_dcache(config);
1049        setup_scache(config);
1050        probe_tlb(config);
1051
1052        _flush_cache_sigtramp = mips32_flush_cache_sigtramp;
1053        _flush_icache_range = mips32_flush_icache_range;        /* Ouch */
1054
1055        __flush_cache_all();
1056        write_32bit_cp0_register(CP0_WIRED, 0);
1057
1058        /*
1059         * You should never change this register:
1060         *   - The entire mm handling assumes the c0_pagemask register to
1061         *     be set for 4kb pages.
1062         */
1063        write_32bit_cp0_register(CP0_PAGEMASK, PM_4K);
1064        flush_tlb_all();
1065}
1066
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.