linux-bk/arch/mips/mm/r5432.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * r5432.c: NEC Vr5432 processor.  We cannot use r4xx0.c because of
   7 *      its unique way-selection method for indexed operations.
   8 *
   9 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  10 * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle (ralf@gnu.org)
  11 * Copyright (C) 2000 Jun Sun (jsun@mvista.com)
  12 *
  13 */
  14
  15/*
  16 * [jsun]
  17 * In a sense, this is really silly.  We cannot re-use r4xx0.c because
  18 * the lowest-level indexed cache operation does not take way-selection
  19 * into account.  So all what I am doing here is to copy all the funcs
  20 * and macros (in r4kcache.h) relavent to R5432 to this file, and then
  21 * modify a few indexed cache operations.  *sigh*
  22 */
  23
  24#include <linux/init.h>
  25#include <linux/kernel.h>
  26#include <linux/sched.h>
  27#include <linux/mm.h>
  28
  29#include <asm/bcache.h>
  30#include <asm/io.h>
  31#include <asm/page.h>
  32#include <asm/pgtable.h>
  33#include <asm/system.h>
  34#include <asm/bootinfo.h>
  35#include <asm/mmu_context.h>
  36
  37/* CP0 hazard avoidance. */
  38#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
  39                                     "nop; nop; nop; nop; nop; nop;\n\t" \
  40                                     ".set reorder\n\t")
  41
  42#include <asm/asm.h>
  43#include <asm/cacheops.h>
  44
  45#undef DEBUG_CACHE
  46
  47/* Primary cache parameters. */
  48static int icache_size, dcache_size; /* Size in bytes */
  49static int ic_lsize, dc_lsize;       /* LineSize in bytes */
  50
  51
  52/* -------------------------------------------------------------------- */
  53/* #include <asm/r4kcache.h> */
  54
  55extern inline void flush_icache_line_indexed(unsigned long addr)
  56{
  57        __asm__ __volatile__(
  58                ".set noreorder\n\t"
  59                ".set mips3\n\t"
  60                "cache %1, (%0)\n\t"
  61                "cache %1, 1(%0)\n\t"
  62                ".set mips0\n\t"
  63                ".set reorder"
  64                :
  65                : "r" (addr),
  66                  "i" (Index_Invalidate_I));
  67}
  68
  69extern inline void flush_dcache_line_indexed(unsigned long addr)
  70{
  71        __asm__ __volatile__(
  72                ".set noreorder\n\t"
  73                ".set mips3\n\t"
  74                "cache %1, (%0)\n\t"
  75                "cache %1, 1(%0)\n\t"
  76                ".set mips0\n\t"
  77                ".set reorder"
  78                :
  79                : "r" (addr),
  80                  "i" (Index_Writeback_Inv_D));
  81}
  82
  83extern inline void flush_icache_line(unsigned long addr)
  84{
  85        __asm__ __volatile__(
  86                ".set noreorder\n\t"
  87                ".set mips3\n\t"
  88                "cache %1, (%0)\n\t"
  89                ".set mips0\n\t"
  90                ".set reorder"
  91                :
  92                : "r" (addr),
  93                  "i" (Hit_Invalidate_I));
  94}
  95
  96extern inline void flush_dcache_line(unsigned long addr)
  97{
  98        __asm__ __volatile__(
  99                ".set noreorder\n\t"
 100                ".set mips3\n\t"
 101                "cache %1, (%0)\n\t"
 102                ".set mips0\n\t"
 103                ".set reorder"
 104                :
 105                : "r" (addr),
 106                  "i" (Hit_Writeback_Inv_D));
 107}
 108
 109extern inline void invalidate_dcache_line(unsigned long addr)
 110{
 111        __asm__ __volatile__(
 112                ".set noreorder\n\t"
 113                ".set mips3\n\t"
 114                "cache %1, (%0)\n\t"
 115                ".set mips0\n\t"
 116                ".set reorder"
 117                :
 118                : "r" (addr),
 119                  "i" (Hit_Invalidate_D));
 120}
 121
 122
 123/*
 124 * The next two are for badland addresses like signal trampolines.
 125 */
 126extern inline void protected_flush_icache_line(unsigned long addr)
 127{
 128        __asm__ __volatile__(
 129                ".set noreorder\n\t"
 130                ".set mips3\n"
 131                "1:\tcache %1,(%0)\n"
 132                "2:\t.set mips0\n\t"
 133                ".set reorder\n\t"
 134                ".section\t__ex_table,\"a\"\n\t"
 135                STR(PTR)"\t1b,2b\n\t"
 136                ".previous"
 137                :
 138                : "r" (addr),
 139                  "i" (Hit_Invalidate_I));
 140}
 141
 142extern inline void protected_writeback_dcache_line(unsigned long addr)
 143{
 144        __asm__ __volatile__(
 145                ".set noreorder\n\t"
 146                ".set mips3\n"
 147                "1:\tcache %1,(%0)\n"
 148                "2:\t.set mips0\n\t"
 149                ".set reorder\n\t"
 150                ".section\t__ex_table,\"a\"\n\t"
 151                STR(PTR)"\t1b,2b\n\t"
 152                ".previous"
 153                :
 154                : "r" (addr),
 155                  "i" (Hit_Writeback_D));
 156}
 157
 158
 159#define cache32_unroll32(base,op)                               \
 160        __asm__ __volatile__("                                  \
 161                .set noreorder;                                 \
 162                .set mips3;                                     \
 163                cache %1, 0x000(%0); cache %1, 0x020(%0);       \
 164                cache %1, 0x040(%0); cache %1, 0x060(%0);       \
 165                cache %1, 0x080(%0); cache %1, 0x0a0(%0);       \
 166                cache %1, 0x0c0(%0); cache %1, 0x0e0(%0);       \
 167                cache %1, 0x100(%0); cache %1, 0x120(%0);       \
 168                cache %1, 0x140(%0); cache %1, 0x160(%0);       \
 169                cache %1, 0x180(%0); cache %1, 0x1a0(%0);       \
 170                cache %1, 0x1c0(%0); cache %1, 0x1e0(%0);       \
 171                cache %1, 0x200(%0); cache %1, 0x220(%0);       \
 172                cache %1, 0x240(%0); cache %1, 0x260(%0);       \
 173                cache %1, 0x280(%0); cache %1, 0x2a0(%0);       \
 174                cache %1, 0x2c0(%0); cache %1, 0x2e0(%0);       \
 175                cache %1, 0x300(%0); cache %1, 0x320(%0);       \
 176                cache %1, 0x340(%0); cache %1, 0x360(%0);       \
 177                cache %1, 0x380(%0); cache %1, 0x3a0(%0);       \
 178                cache %1, 0x3c0(%0); cache %1, 0x3e0(%0);       \
 179                .set mips0;                                     \
 180                .set reorder"                                   \
 181                :                                               \
 182                : "r" (base),                                   \
 183                  "i" (op));
 184
 185extern inline void blast_dcache32(void)
 186{
 187        unsigned long start = KSEG0;
 188        unsigned long end = (start + dcache_size/2);
 189
 190        while(start < end) {
 191                cache32_unroll32(start,Index_Writeback_Inv_D);
 192                cache32_unroll32(start+1,Index_Writeback_Inv_D);
 193                start += 0x400;
 194        }
 195}
 196
 197extern inline void blast_dcache32_page(unsigned long page)
 198{
 199        unsigned long start = page;
 200        unsigned long end = (start + PAGE_SIZE);
 201
 202        while(start < end) {
 203                cache32_unroll32(start,Hit_Writeback_Inv_D);
 204                start += 0x400;
 205        }
 206}
 207
 208extern inline void blast_dcache32_page_indexed(unsigned long page)
 209{
 210        unsigned long start = page;
 211        unsigned long end = (start + PAGE_SIZE);
 212
 213        while(start < end) {
 214                cache32_unroll32(start,Index_Writeback_Inv_D);
 215                cache32_unroll32(start+1,Index_Writeback_Inv_D);
 216                start += 0x400;
 217        }
 218}
 219
 220extern inline void blast_icache32(void)
 221{
 222        unsigned long start = KSEG0;
 223        unsigned long end = (start + icache_size/2);
 224
 225        while(start < end) {
 226                cache32_unroll32(start,Index_Invalidate_I);
 227                cache32_unroll32(start+1,Index_Invalidate_I);
 228                start += 0x400;
 229        }
 230}
 231
 232extern inline void blast_icache32_page(unsigned long page)
 233{
 234        unsigned long start = page;
 235        unsigned long end = (start + PAGE_SIZE);
 236
 237        while(start < end) {
 238                cache32_unroll32(start,Hit_Invalidate_I);
 239                start += 0x400;
 240        }
 241}
 242
 243extern inline void blast_icache32_page_indexed(unsigned long page)
 244{
 245        unsigned long start = page;
 246        unsigned long end = (start + PAGE_SIZE);
 247
 248        while(start < end) {
 249                cache32_unroll32(start,Index_Invalidate_I);
 250                cache32_unroll32(start+1,Index_Invalidate_I);
 251                start += 0x400;
 252        }
 253}
 254
 255/* -------------------------------------------------------------------- */
 256
 257static void r5432_clear_page_d32(void * page)
 258{
 259        __asm__ __volatile__(
 260                ".set\tnoreorder\n\t"
 261                ".set\tnoat\n\t"
 262                ".set\tmips3\n\t"
 263                "daddiu\t$1,%0,%2\n"
 264                "1:\tcache\t%3,(%0)\n\t"
 265                "sd\t$0,(%0)\n\t"
 266                "sd\t$0,8(%0)\n\t"
 267                "sd\t$0,16(%0)\n\t"
 268                "sd\t$0,24(%0)\n\t"
 269                "daddiu\t%0,64\n\t"
 270                "cache\t%3,-32(%0)\n\t"
 271                "sd\t$0,-32(%0)\n\t"
 272                "sd\t$0,-24(%0)\n\t"
 273                "sd\t$0,-16(%0)\n\t"
 274                "bne\t$1,%0,1b\n\t"
 275                "sd\t$0,-8(%0)\n\t"
 276                ".set\tmips0\n\t"
 277                ".set\tat\n\t"
 278                ".set\treorder"
 279                :"=r" (page)
 280                :"0" (page),
 281                 "I" (PAGE_SIZE),
 282                 "i" (Create_Dirty_Excl_D)
 283                :"$1","memory");
 284}
 285
 286
 287
 288/*
 289 * This is still inefficient.  We only can do better if we know the
 290 * virtual address where the copy will be accessed.
 291 */
 292
 293static void r5432_copy_page_d32(void * to, void * from)
 294{
 295        unsigned long dummy1, dummy2;
 296        unsigned long reg1, reg2, reg3, reg4;
 297
 298        __asm__ __volatile__(
 299                ".set\tnoreorder\n\t"
 300                ".set\tnoat\n\t"
 301                ".set\tmips3\n\t"
 302                "daddiu\t$1,%0,%8\n"
 303                "1:\tcache\t%9,(%0)\n\t"
 304                "lw\t%2,(%1)\n\t"
 305                "lw\t%3,4(%1)\n\t"
 306                "lw\t%4,8(%1)\n\t"
 307                "lw\t%5,12(%1)\n\t"
 308                "sw\t%2,(%0)\n\t"
 309                "sw\t%3,4(%0)\n\t"
 310                "sw\t%4,8(%0)\n\t"
 311                "sw\t%5,12(%0)\n\t"
 312                "lw\t%2,16(%1)\n\t"
 313                "lw\t%3,20(%1)\n\t"
 314                "lw\t%4,24(%1)\n\t"
 315                "lw\t%5,28(%1)\n\t"
 316                "sw\t%2,16(%0)\n\t"
 317                "sw\t%3,20(%0)\n\t"
 318                "sw\t%4,24(%0)\n\t"
 319                "sw\t%5,28(%0)\n\t"
 320                "cache\t%9,32(%0)\n\t"
 321                "daddiu\t%0,64\n\t"
 322                "daddiu\t%1,64\n\t"
 323                "lw\t%2,-32(%1)\n\t"
 324                "lw\t%3,-28(%1)\n\t"
 325                "lw\t%4,-24(%1)\n\t"
 326                "lw\t%5,-20(%1)\n\t"
 327                "sw\t%2,-32(%0)\n\t"
 328                "sw\t%3,-28(%0)\n\t"
 329                "sw\t%4,-24(%0)\n\t"
 330                "sw\t%5,-20(%0)\n\t"
 331                "lw\t%2,-16(%1)\n\t"
 332                "lw\t%3,-12(%1)\n\t"
 333                "lw\t%4,-8(%1)\n\t"
 334                "lw\t%5,-4(%1)\n\t"
 335                "sw\t%2,-16(%0)\n\t"
 336                "sw\t%3,-12(%0)\n\t"
 337                "sw\t%4,-8(%0)\n\t"
 338                "bne\t$1,%0,1b\n\t"
 339                "sw\t%5,-4(%0)\n\t"
 340                ".set\tmips0\n\t"
 341                ".set\tat\n\t"
 342                ".set\treorder"
 343                :"=r" (dummy1), "=r" (dummy2),
 344                 "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
 345                :"0" (to), "1" (from),
 346                 "I" (PAGE_SIZE),
 347                 "i" (Create_Dirty_Excl_D));
 348}
 349
 350
 351/*
 352 * If you think for one second that this stuff coming up is a lot
 353 * of bulky code eating too many kernel cache lines.  Think _again_.
 354 *
 355 * Consider:
 356 * 1) Taken branches have a 3 cycle penalty on R4k
 357 * 2) The branch itself is a real dead cycle on even R4600/R5000.
 358 * 3) Only one of the following variants of each type is even used by
 359 *    the kernel based upon the cache parameters we detect at boot time.
 360 *
 361 * QED.
 362 */
 363
 364static inline void r5432_flush_cache_all_d32i32(void)
 365{
 366        blast_dcache32(); blast_icache32();
 367}
 368
 369static void r5432_flush_cache_range_d32i32(struct vm_area_struct *vma,
 370                                         unsigned long start,
 371                                         unsigned long end)
 372{
 373        struct mm_struct *mm = vma->vm_mm;
 374
 375        if (mm->context != 0) {
 376#ifdef DEBUG_CACHE
 377                printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
 378#endif
 379                blast_dcache32(); blast_icache32();
 380        }
 381}
 382
 383/*
 384 * On architectures like the Sparc, we could get rid of lines in
 385 * the cache created only by a certain context, but on the MIPS
 386 * (and actually certain Sparc's) we cannot.
 387 */
 388static void r5432_flush_cache_mm_d32i32(struct mm_struct *mm)
 389{
 390        if (mm->context != 0) {
 391#ifdef DEBUG_CACHE
 392                printk("cmm[%d]", (int)mm->context);
 393#endif
 394                r5432_flush_cache_all_d32i32();
 395        }
 396}
 397
 398static void r5432_flush_cache_page_d32i32(struct vm_area_struct *vma,
 399                                        unsigned long page)
 400{
 401        struct mm_struct *mm = vma->vm_mm;
 402        pgd_t *pgdp;
 403        pmd_t *pmdp;
 404        pte_t *ptep;
 405
 406        /*
 407         * If ownes no valid ASID yet, cannot possibly have gotten
 408         * this page into the cache.
 409         */
 410        if (mm->context == 0)
 411                return;
 412
 413#ifdef DEBUG_CACHE
 414        printk("cpage[%d,%08lx]", (int)mm->context, page);
 415#endif
 416        page &= PAGE_MASK;
 417        pgdp = pgd_offset(mm, page);
 418        pmdp = pmd_offset(pgdp, page);
 419        ptep = pte_offset(pmdp, page);
 420
 421        /*
 422         * If the page isn't marked valid, the page cannot possibly be
 423         * in the cache.
 424         */
 425        if (!(pte_val(*ptep) & _PAGE_PRESENT))
 426                return;
 427
 428        /*
 429         * Doing flushes for another ASID than the current one is
 430         * too difficult since stupid R4k caches do a TLB translation
 431         * for every cache flush operation.  So we do indexed flushes
 432         * in that case, which doesn't overly flush the cache too much.
 433         */
 434        if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) {
 435                blast_dcache32_page(page);
 436        } else {
 437                /*
 438                 * Do indexed flush, too much work to get the (possible)
 439                 * tlb refills to work correctly.
 440                 */
 441                page = (KSEG0 + (page & (dcache_size - 1)));
 442                blast_dcache32_page_indexed(page);
 443        }
 444}
 445
 446
 447/* If the addresses passed to these routines are valid, they are
 448 * either:
 449 *
 450 * 1) In KSEG0, so we can do a direct flush of the page.
 451 * 2) In KSEG2, and since every process can translate those
 452 *    addresses all the time in kernel mode we can do a direct
 453 *    flush.
 454 * 3) In KSEG1, no flush necessary.
 455 */
 456static void r5432_flush_page_to_ram_d32(struct page *page)
 457{
 458        blast_dcache32_page((unsigned long)page_address(page));
 459}
 460
 461static void 
 462r5432_flush_icache_range(unsigned long start, unsigned long end)
 463{
 464        r5432_flush_cache_all_d32i32();
 465}
 466
 467/*
 468 * Ok, this seriously sucks.  We use them to flush a user page but don't
 469 * know the virtual address, so we have to blast away the whole icache
 470 * which is significantly more expensive than the real thing.
 471 */
 472static void
 473r5432_flush_icache_page_i32(struct vm_area_struct *vma, struct page *page)
 474{
 475        if (!(vma->vm_flags & VM_EXEC))
 476                return;
 477
 478        r5432_flush_cache_all_d32i32();
 479}
 480
 481/*
 482 * Writeback and invalidate the primary cache dcache before DMA.
 483 */
 484static void
 485r5432_dma_cache_wback_inv_pc(unsigned long addr, unsigned long size)
 486{
 487        unsigned long end, a;
 488
 489        if (size >= dcache_size) {
 490                flush_cache_all();
 491        } else {
 492                a = addr & ~(dc_lsize - 1);
 493                end = (addr + size) & ~(dc_lsize - 1);
 494                while (1) {
 495                        flush_dcache_line(a); /* Hit_Writeback_Inv_D */
 496                        if (a == end) break;
 497                        a += dc_lsize;
 498                }
 499        }
 500        bc_wback_inv(addr, size);
 501}
 502
 503static void
 504r5432_dma_cache_inv_pc(unsigned long addr, unsigned long size)
 505{
 506        unsigned long end, a;
 507
 508        if (size >= dcache_size) {
 509                flush_cache_all();
 510        } else {
 511                a = addr & ~(dc_lsize - 1);
 512                end = (addr + size) & ~(dc_lsize - 1);
 513                while (1) {
 514                        flush_dcache_line(a); /* Hit_Writeback_Inv_D */
 515                        if (a == end) break;
 516                        a += dc_lsize;
 517                }
 518        }
 519
 520        bc_inv(addr, size);
 521}
 522
 523static void
 524r5432_dma_cache_wback(unsigned long addr, unsigned long size)
 525{
 526        panic("r5432_dma_cache called - should not happen.\n");
 527}
 528
 529/*
 530 * While we're protected against bad userland addresses we don't care
 531 * very much about what happens in that case.  Usually a segmentation
 532 * fault will dump the process later on anyway ...
 533 */
 534static void r5432_flush_cache_sigtramp(unsigned long addr)
 535{
 536        protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
 537        protected_flush_icache_line(addr & ~(ic_lsize - 1));
 538}
 539
 540#undef DEBUG_TLB
 541#undef DEBUG_TLBUPDATE
 542
 543#define NTLB_ENTRIES       48  /* Fixed on all R4XX0 variants... */
 544
 545#define NTLB_ENTRIES_HALF  24  /* Fixed on all R4XX0 variants... */
 546
 547void flush_tlb_all(void)
 548{
 549        unsigned long old_ctx;
 550        int entry;
 551        unsigned long flags;
 552
 553#ifdef DEBUG_TLB
 554        printk("[tlball]");
 555#endif
 556
 557        local_irq_save(flags);
 558        /* Save old context and create impossible VPN2 value */
 559        old_ctx = (get_entryhi() & 0xff);
 560        set_entryhi(KSEG0);
 561        set_entrylo0(0);
 562        set_entrylo1(0);
 563        BARRIER;
 564
 565        entry = get_wired();
 566
 567        /* Blast 'em all away. */
 568        while(entry < NTLB_ENTRIES) {
 569                set_index(entry);
 570                BARRIER;
 571                tlb_write_indexed();
 572                BARRIER;
 573                entry++;
 574        }
 575        BARRIER;
 576        set_entryhi(old_ctx);
 577        local_irq_restore(flags);
 578}
 579
 580void flush_tlb_mm(struct mm_struct *mm)
 581{
 582        if (mm->context != 0) {
 583                unsigned long flags;
 584
 585#ifdef DEBUG_TLB
 586                printk("[tlbmm<%d>]", mm->context);
 587#endif
 588                local_irq_save(flags);
 589                get_new_mmu_context(mm, asid_cache);
 590                if (mm == current->active_mm)
 591                        set_entryhi(mm->context & 0xff);
 592                local_irq_restore(flags);
 593        }
 594}
 595
 596void flush_tlb_range(struct mm_struct *mm, unsigned long start,
 597                                unsigned long end)
 598{
 599        if(mm->context != 0) {
 600                unsigned long flags;
 601                int size;
 602
 603#ifdef DEBUG_TLB
 604                printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff),
 605                       start, end);
 606#endif
 607                local_irq_save(flags);
 608                size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
 609                size = (size + 1) >> 1;
 610                if(size <= NTLB_ENTRIES_HALF) {
 611                        int oldpid = (get_entryhi() & 0xff);
 612                        int newpid = (mm->context & 0xff);
 613
 614                        start &= (PAGE_MASK << 1);
 615                        end += ((PAGE_SIZE << 1) - 1);
 616                        end &= (PAGE_MASK << 1);
 617                        while(start < end) {
 618                                int idx;
 619
 620                                set_entryhi(start | newpid);
 621                                start += (PAGE_SIZE << 1);
 622                                BARRIER;
 623                                tlb_probe();
 624                                BARRIER;
 625                                idx = get_index();
 626                                set_entrylo0(0);
 627                                set_entrylo1(0);
 628                                set_entryhi(KSEG0);
 629                                BARRIER;
 630                                if(idx < 0)
 631                                        continue;
 632                                tlb_write_indexed();
 633                                BARRIER;
 634                        }
 635                        set_entryhi(oldpid);
 636                } else {
 637                        get_new_mmu_context(mm, asid_cache);
 638                        if (mm == current->active_mm)
 639                                set_entryhi(mm->context & 0xff);
 640                }
 641                local_irq_restore(flags);
 642        }
 643}
 644
 645void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 646{
 647        if (vma->vm_mm->context != 0) {
 648                unsigned long flags;
 649                int oldpid, newpid, idx;
 650
 651#ifdef DEBUG_TLB
 652                printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page);
 653#endif
 654                newpid = (vma->vm_mm->context & 0xff);
 655                page &= (PAGE_MASK << 1);
 656                local_irq_save(flags);
 657                oldpid = (get_entryhi() & 0xff);
 658                set_entryhi(page | newpid);
 659                BARRIER;
 660                tlb_probe();
 661                BARRIER;
 662                idx = get_index();
 663                set_entrylo0(0);
 664                set_entrylo1(0);
 665                set_entryhi(KSEG0);
 666                if(idx < 0)
 667                        goto finish;
 668                BARRIER;
 669                tlb_write_indexed();
 670
 671        finish:
 672                BARRIER;
 673                set_entryhi(oldpid);
 674                local_irq_restore(flags);
 675        }
 676}
 677
 678void pgd_init(unsigned long page)
 679{
 680        unsigned long *p = (unsigned long *) page;
 681        int i;
 682
 683        for(i = 0; i < USER_PTRS_PER_PGD; i+=8) {
 684                p[i + 0] = (unsigned long) invalid_pte_table;
 685                p[i + 1] = (unsigned long) invalid_pte_table;
 686                p[i + 2] = (unsigned long) invalid_pte_table;
 687                p[i + 3] = (unsigned long) invalid_pte_table;
 688                p[i + 4] = (unsigned long) invalid_pte_table;
 689                p[i + 5] = (unsigned long) invalid_pte_table;
 690                p[i + 6] = (unsigned long) invalid_pte_table;
 691                p[i + 7] = (unsigned long) invalid_pte_table;
 692        }
 693}
 694
 695/* We will need multiple versions of update_mmu_cache(), one that just
 696 * updates the TLB with the new pte(s), and another which also checks
 697 * for the R4k "end of page" hardware bug and does the needy.
 698 */
 699void update_mmu_cache(struct vm_area_struct * vma,
 700                                 unsigned long address, pte_t pte)
 701{
 702        unsigned long flags;
 703        pgd_t *pgdp;
 704        pmd_t *pmdp;
 705        pte_t *ptep;
 706        int idx, pid;
 707
 708        /*
 709         * Handle debugger faulting in for debugee.
 710         */
 711        if (current->active_mm != vma->vm_mm)
 712                return;
 713
 714        pid = get_entryhi() & 0xff;
 715
 716#ifdef DEBUG_TLB
 717        if((pid != (vma->vm_mm->context & 0xff)) || (vma->vm_mm->context == 0)) {
 718                printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n",
 719                       (int) (vma->vm_mm->context & 0xff), pid);
 720        }
 721#endif
 722
 723        local_irq_save(flags);
 724        address &= (PAGE_MASK << 1);
 725        set_entryhi(address | (pid));
 726        pgdp = pgd_offset(vma->vm_mm, address);
 727        BARRIER;
 728        tlb_probe();
 729        BARRIER;
 730        pmdp = pmd_offset(pgdp, address);
 731        idx = get_index();
 732        ptep = pte_offset(pmdp, address);
 733        BARRIER;
 734        set_entrylo0(pte_val(*ptep++) >> 6);
 735        set_entrylo1(pte_val(*ptep) >> 6);
 736        set_entryhi(address | (pid));
 737        BARRIER;
 738        if(idx < 0) {
 739                tlb_write_random();
 740        } else {
 741                tlb_write_indexed();
 742        }
 743        BARRIER;
 744        set_entryhi(pid);
 745        BARRIER;
 746        local_irq_restore(flags);
 747}
 748
 749void show_regs(struct pt_regs * regs)
 750{
 751        /* Saved main processor registers. */
 752        printk("$0 : %08lx %08lx %08lx %08lx\n",
 753               0UL, regs->regs[1], regs->regs[2], regs->regs[3]);
 754        printk("$4 : %08lx %08lx %08lx %08lx\n",
 755               regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]);
 756        printk("$8 : %08lx %08lx %08lx %08lx\n",
 757               regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11]);
 758        printk("$12: %08lx %08lx %08lx %08lx\n",
 759               regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]);
 760        printk("$16: %08lx %08lx %08lx %08lx\n",
 761               regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19]);
 762        printk("$20: %08lx %08lx %08lx %08lx\n",
 763               regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]);
 764        printk("$24: %08lx %08lx\n",
 765               regs->regs[24], regs->regs[25]);
 766        printk("$28: %08lx %08lx %08lx %08lx\n",
 767               regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]);
 768
 769        /* Saved cp0 registers. */
 770        printk("epc   : %08lx    %s\nStatus: %08lx\nCause : %08lx\n",
 771               regs->cp0_epc, print_tainted(), regs->cp0_status, regs->cp0_cause);
 772}
 773                        
 774void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
 775                     unsigned long entryhi, unsigned long pagemask)
 776{
 777        unsigned long flags;
 778        unsigned long wired;
 779        unsigned long old_pagemask;
 780        unsigned long old_ctx;
 781
 782        local_irq_save(flags);
 783        /* Save old context and create impossible VPN2 value */
 784        old_ctx = (get_entryhi() & 0xff);
 785        old_pagemask = get_pagemask();
 786        wired = get_wired();
 787        set_wired (wired + 1);
 788        set_index (wired);
 789        BARRIER;    
 790        set_pagemask (pagemask);
 791        set_entryhi(entryhi);
 792        set_entrylo0(entrylo0);
 793        set_entrylo1(entrylo1);
 794        BARRIER;    
 795        tlb_write_indexed();
 796        BARRIER;    
 797    
 798        set_entryhi(old_ctx);
 799        BARRIER;    
 800        set_pagemask (old_pagemask);
 801        flush_tlb_all();    
 802        local_irq_restore(flags);
 803}
 804
 805/* Detect and size the various r4k caches. */
 806static void __init probe_icache(unsigned long config)
 807{
 808        icache_size = 1 << (12 + ((config >> 9) & 7));
 809        ic_lsize = 16 << ((config >> 5) & 1);
 810
 811        printk("Primary instruction cache %dkb, linesize %d bytes.\n",
 812               icache_size >> 10, ic_lsize);
 813}
 814
 815static void __init probe_dcache(unsigned long config)
 816{
 817        dcache_size = 1 << (12 + ((config >> 6) & 7));
 818        dc_lsize = 16 << ((config >> 4) & 1);
 819
 820        printk("Primary data cache %dkb, linesize %d bytes.\n",
 821               dcache_size >> 10, dc_lsize);
 822}
 823
 824
 825void __init ld_mmu_r5432(void)
 826{
 827        unsigned long config = read_32bit_cp0_register(CP0_CONFIG);
 828
 829        printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID));
 830
 831        change_cp0_config(CONF_CM_CMASK, CONF_CM_CACHABLE_NONCOHERENT);
 832
 833        probe_icache(config);
 834        probe_dcache(config);
 835
 836        _clear_page = r5432_clear_page_d32;
 837        _copy_page = r5432_copy_page_d32;
 838        _flush_cache_all = r5432_flush_cache_all_d32i32;
 839        ___flush_cache_all = r5432_flush_cache_all_d32i32;
 840        _flush_page_to_ram = r5432_flush_page_to_ram_d32;
 841        _flush_cache_mm = r5432_flush_cache_mm_d32i32;
 842        _flush_cache_range = r5432_flush_cache_range_d32i32;
 843        _flush_cache_page = r5432_flush_cache_page_d32i32;
 844        _flush_icache_page = r5432_flush_icache_page_i32;
 845        _dma_cache_wback_inv = r5432_dma_cache_wback_inv_pc;
 846        _dma_cache_wback = r5432_dma_cache_wback;
 847        _dma_cache_inv = r5432_dma_cache_inv_pc;
 848
 849        _flush_cache_sigtramp = r5432_flush_cache_sigtramp;
 850        _flush_icache_range = r5432_flush_icache_range; /* Ouch */
 851
 852        __flush_cache_all();
 853        write_32bit_cp0_register(CP0_WIRED, 0);
 854
 855        /*
 856         * You should never change this register:
 857         *   - On R4600 1.7 the tlbp never hits for pages smaller than
 858         *     the value in the c0_pagemask register.
 859         *   - The entire mm handling assumes the c0_pagemask register to
 860         *     be set for 4kb pages.
 861         */
 862        write_32bit_cp0_register(CP0_PAGEMASK, PM_4K);
 863        flush_tlb_all();
 864}
 865
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.