Annotation of sys/arch/m88k/m88k/m8820x_machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: m8820x_machdep.c,v 1.26 2007/05/20 20:12:32 miod Exp $ */
! 2: /*
! 3: * Copyright (c) 2004, Miodrag Vallat.
! 4: *
! 5: * Redistribution and use in source and binary forms, with or without
! 6: * modification, are permitted provided that the following conditions
! 7: * are met:
! 8: * 1. Redistributions of source code must retain the above copyright
! 9: * notice, this list of conditions and the following disclaimer.
! 10: * 2. Redistributions in binary form must reproduce the above copyright
! 11: * notice, this list of conditions and the following disclaimer in the
! 12: * documentation and/or other materials provided with the distribution.
! 13: *
! 14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 15: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 16: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
! 17: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
! 18: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 19: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 20: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 21: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 22: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
! 23: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 24: * POSSIBILITY OF SUCH DAMAGE.
! 25: */
! 26: /*
! 27: * Copyright (c) 2001 Steve Murphree, Jr.
! 28: * Copyright (c) 1996 Nivas Madhur
! 29: * All rights reserved.
! 30: *
! 31: * Redistribution and use in source and binary forms, with or without
! 32: * modification, are permitted provided that the following conditions
! 33: * are met:
! 34: * 1. Redistributions of source code must retain the above copyright
! 35: * notice, this list of conditions and the following disclaimer.
! 36: * 2. Redistributions in binary form must reproduce the above copyright
! 37: * notice, this list of conditions and the following disclaimer in the
! 38: * documentation and/or other materials provided with the distribution.
! 39: * 3. All advertising materials mentioning features or use of this software
! 40: * must display the following acknowledgement:
! 41: * This product includes software developed by Nivas Madhur.
! 42: * 4. The name of the author may not be used to endorse or promote products
! 43: * derived from this software without specific prior written permission
! 44: *
! 45: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 46: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 47: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 48: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 49: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 50: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 51: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 52: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 53: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 54: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 55: *
! 56: */
! 57: /*
! 58: * Mach Operating System
! 59: * Copyright (c) 1993-1991 Carnegie Mellon University
! 60: * Copyright (c) 1991 OMRON Corporation
! 61: * All Rights Reserved.
! 62: *
! 63: * Permission to use, copy, modify and distribute this software and its
! 64: * documentation is hereby granted, provided that both the copyright
! 65: * notice and this permission notice appear in all copies of the
! 66: * software, derivative works or modified versions, and any portions
! 67: * thereof, and that both notices appear in supporting documentation.
! 68: *
! 69: * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
! 70: * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
! 71: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
! 72: *
! 73: * Carnegie Mellon requests users of this software to return to
! 74: *
! 75: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
! 76: * School of Computer Science
! 77: * Carnegie Mellon University
! 78: * Pittsburgh PA 15213-3890
! 79: *
! 80: * any improvements or extensions that they make and grant Carnegie the
! 81: * rights to redistribute these changes.
! 82: */
! 83:
! 84: #include <sys/param.h>
! 85: #include <sys/systm.h>
! 86:
! 87: #include <uvm/uvm_extern.h>
! 88:
! 89: #include <machine/asm_macro.h>
! 90: #include <machine/cmmu.h>
! 91: #include <machine/cpu.h>
! 92: #include <machine/lock.h>
! 93: #include <machine/m8820x.h>
! 94: #include <machine/psl.h>
! 95:
! 96: cpuid_t m8820x_init(void);
! 97: void m8820x_cpu_configuration_print(int);
! 98: void m8820x_shutdown(void);
! 99: void m8820x_set_sapr(cpuid_t, apr_t);
! 100: void m8820x_set_uapr(apr_t);
! 101: void m8820x_flush_tlb(cpuid_t, u_int, vaddr_t, u_int);
! 102: void m8820x_flush_cache(cpuid_t, paddr_t, psize_t);
! 103: void m8820x_flush_inst_cache(cpuid_t, paddr_t, psize_t);
! 104: void m8820x_flush_data_page(cpuid_t, paddr_t);
! 105: void m8820x_dma_cachectl(pmap_t, vaddr_t, vsize_t, int);
! 106: void m8820x_dma_cachectl_pa(paddr_t, psize_t, int);
! 107: void m8820x_initialize_cpu(cpuid_t);
! 108:
! 109: /* This is the function table for the MC8820x CMMUs */
! 110: struct cmmu_p cmmu8820x = {
! 111: m8820x_init,
! 112: m8820x_setup_board_config,
! 113: m8820x_cpu_configuration_print,
! 114: m8820x_shutdown,
! 115: m8820x_cpu_number,
! 116: m8820x_set_sapr,
! 117: m8820x_set_uapr,
! 118: m8820x_flush_tlb,
! 119: m8820x_flush_cache,
! 120: m8820x_flush_inst_cache,
! 121: m8820x_flush_data_page,
! 122: m8820x_dma_cachectl,
! 123: m8820x_dma_cachectl_pa,
! 124: #ifdef MULTIPROCESSOR
! 125: m8820x_initialize_cpu,
! 126: #endif
! 127: };
! 128:
! 129: /*
! 130: * Systems with more than 2 CMMUs per CPU use programmable split schemes.
! 131: *
! 132: * The following schemes are available on MVME188 boards:
! 133: * - split on A12 address bit (A14 for 88204)
! 134: * - split on supervisor/user access
! 135: * - split on SRAM/non-SRAM addresses, with either supervisor-only or all
! 136: * access to SRAM.
! 137: *
! 138: * MVME188 configuration 6, with 4 CMMUs par CPU, also forces a split on
! 139: * A14 address bit (A16 for 88204).
! 140: *
! 141: * Under OpenBSD, we will only split on A12 and A14 address bits, since we
! 142: * do not want to waste CMMU resources on the SRAM, and user/supervisor
! 143: * splits seem less efficient.
! 144: *
! 145: * The really nasty part of this choice is in the exception handling code,
! 146: * when it needs to get error information from up to 4 CMMUs. See eh.S on
! 147: * mvme88k for the gory details, luna88k is more sane.
! 148: */
! 149:
! 150: struct m8820x_cmmu m8820x_cmmu[MAX_CMMUS];
! 151: u_int max_cmmus;
! 152: u_int cmmu_shift;
! 153:
! 154: /* local prototypes */
! 155: void m8820x_cmmu_set_reg(int, u_int, int, int, int);
! 156: void m8820x_cmmu_set_cmd(u_int, int, int, int, vaddr_t);
! 157: void m8820x_cmmu_wait(int);
! 158: void m8820x_cmmu_sync_cache(int, paddr_t, psize_t);
! 159: void m8820x_cmmu_sync_inval_cache(int, paddr_t, psize_t);
! 160: void m8820x_cmmu_inval_cache(int, paddr_t, psize_t);
! 161:
! 162: /* Flags passed to m8820x_cmmu_set() */
! 163: #define MODE_VAL 0x01
! 164: #define ADDR_VAL 0x02
! 165:
! 166: /*
! 167: * Helper functions to poke values into the appropriate CMMU registers.
! 168: */
! 169:
! 170: void
! 171: m8820x_cmmu_set_reg(int reg, u_int val, int flags, int cpu, int mode)
! 172: {
! 173: struct m8820x_cmmu *cmmu;
! 174: int mmu, cnt;
! 175:
! 176: mmu = cpu << cmmu_shift;
! 177: cmmu = m8820x_cmmu + mmu;
! 178:
! 179: /*
! 180: * We scan all CMMUs to find the matching ones and store the
! 181: * values there.
! 182: */
! 183: for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, mmu++, cmmu++) {
! 184: if ((flags & MODE_VAL) != 0) {
! 185: if (CMMU_MODE(mmu) != mode)
! 186: continue;
! 187: }
! 188: cmmu->cmmu_regs[reg] = val;
! 189: }
! 190: }
! 191:
! 192: void
! 193: m8820x_cmmu_set_cmd(u_int cmd, int flags, int cpu, int mode, vaddr_t addr)
! 194: {
! 195: struct m8820x_cmmu *cmmu;
! 196: int mmu, cnt;
! 197:
! 198: mmu = cpu << cmmu_shift;
! 199: cmmu = m8820x_cmmu + mmu;
! 200:
! 201: /*
! 202: * We scan all CMMUs to find the matching ones and store the
! 203: * values there.
! 204: */
! 205: for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, mmu++, cmmu++) {
! 206: if ((flags & MODE_VAL) != 0) {
! 207: if (CMMU_MODE(mmu) != mode)
! 208: continue;
! 209: }
! 210: #ifdef M88200_HAS_SPLIT_ADDRESS
! 211: if ((flags & ADDR_VAL) != 0 && cmmu->cmmu_addr_mask != 0) {
! 212: if ((addr & cmmu->cmmu_addr_mask) != cmmu->cmmu_addr)
! 213: continue;
! 214: }
! 215: #endif
! 216: cmmu->cmmu_regs[CMMU_SAR] = addr;
! 217: cmmu->cmmu_regs[CMMU_SCR] = cmd;
! 218: }
! 219: }
! 220:
! 221: /*
! 222: * Force a read from the CMMU status register, thereby forcing execution to
! 223: * stop until all pending CMMU operations are finished.
! 224: * This is used by the various cache invalidation functions.
! 225: */
! 226: void
! 227: m8820x_cmmu_wait(int cpu)
! 228: {
! 229: struct m8820x_cmmu *cmmu;
! 230: int mmu, cnt;
! 231:
! 232: mmu = cpu << cmmu_shift;
! 233: cmmu = m8820x_cmmu + mmu;
! 234:
! 235: /*
! 236: * We scan all related CMMUs and read their status register.
! 237: */
! 238: for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, mmu++, cmmu++) {
! 239: #ifdef DEBUG
! 240: if (cmmu->cmmu_regs[CMMU_SSR] & CMMU_SSR_BE) {
! 241: panic("cache flush failed!");
! 242: }
! 243: #else
! 244: /* force the read access, but do not issue this statement... */
! 245: __asm__ __volatile__ ("|or r0, r0, %0" ::
! 246: "r" (cmmu->cmmu_regs[CMMU_SSR]));
! 247: #endif
! 248: }
! 249: }
! 250:
! 251: /*
! 252: * Should only be called after the calling cpus knows its cpu
! 253: * number and main/secondary status. Should be called first
! 254: * by the main processor, before the others are started.
! 255: */
! 256: void
! 257: m8820x_cpu_configuration_print(int main)
! 258: {
! 259: struct m8820x_cmmu *cmmu;
! 260: int pid = get_cpu_pid();
! 261: int proctype = (pid & PID_ARN) >> ARN_SHIFT;
! 262: int procvers = (pid & PID_VN) >> VN_SHIFT;
! 263: int mmu, cnt, cpu = cpu_number();
! 264: #ifdef M88200_HAS_SPLIT_ADDRESS
! 265: int aline, abit, amask;
! 266: #endif
! 267:
! 268: printf("cpu%d: ", cpu);
! 269: switch (proctype) {
! 270: default:
! 271: printf("unknown model arch 0x%x rev 0x%x",
! 272: proctype, procvers);
! 273: break;
! 274: case ARN_88100:
! 275: printf("M88100 rev 0x%x", procvers);
! 276: #ifdef MULTIPROCESSOR
! 277: if (main == 0)
! 278: printf(", secondary");
! 279: #endif
! 280: printf(", %d CMMU", 1 << cmmu_shift);
! 281:
! 282: mmu = cpu << cmmu_shift;
! 283: cmmu = m8820x_cmmu + mmu;
! 284: for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, mmu++, cmmu++) {
! 285: int idr = cmmu->cmmu_regs[CMMU_IDR];
! 286: int mmuid = CMMU_TYPE(idr);
! 287:
! 288: if (mmu % 2 == 0)
! 289: printf("\ncpu%d: ", cpu);
! 290: else
! 291: printf(", ");
! 292:
! 293: switch (mmuid) {
! 294: case M88200_ID:
! 295: printf("M88200 (16K)");
! 296: break;
! 297: case M88204_ID:
! 298: printf("M88204 (64K)");
! 299: break;
! 300: default:
! 301: printf("unknown CMMU id 0x%x", mmuid);
! 302: break;
! 303: }
! 304: printf(" rev 0x%x,", CMMU_VERSION(idr));
! 305: #ifdef M88200_HAS_SPLIT_ADDRESS
! 306: /*
! 307: * Print address lines
! 308: */
! 309: amask = cmmu->cmmu_addr_mask;
! 310: if (amask != 0) {
! 311: aline = 0;
! 312: while (amask != 0) {
! 313: abit = ff1(amask);
! 314: if ((cmmu->cmmu_addr &
! 315: (1 << abit)) != 0)
! 316: printf("%cA%02d",
! 317: aline != 0 ? '/' : ' ',
! 318: abit);
! 319: else
! 320: printf("%cA%02d*",
! 321: aline != 0 ? '/' : ' ',
! 322: abit);
! 323: amask ^= 1 << abit;
! 324: }
! 325: } else
! 326: #endif
! 327: printf(" full");
! 328: printf(" %ccache",
! 329: CMMU_MODE(mmu) == INST_CMMU ? 'I' : 'D');
! 330: }
! 331: break;
! 332: }
! 333: printf("\n");
! 334:
! 335: #ifndef ERRATA__XXX_USR
! 336: {
! 337: static int errata_warn = 0;
! 338:
! 339: if (proctype == ARN_88100 && procvers <= 10) {
! 340: if (!errata_warn++)
! 341: printf("WARNING: M88100 bug workaround code "
! 342: "not enabled.\nPlease recompile the kernel "
! 343: "with option ERRATA__XXX_USR !\n");
! 344: }
! 345: }
! 346: #endif
! 347: }
! 348:
! 349: /*
! 350: * CMMU initialization routine
! 351: */
! 352: cpuid_t
! 353: m8820x_init()
! 354: {
! 355: cpuid_t cpu;
! 356:
! 357: cpu = m8820x_cpu_number();
! 358: m8820x_initialize_cpu(cpu);
! 359: return (cpu);
! 360: }
! 361:
! 362: /*
! 363: * Initialize the set of CMMUs tied to a particular CPU.
! 364: */
! 365: void
! 366: m8820x_initialize_cpu(cpuid_t cpu)
! 367: {
! 368: struct cpu_info *ci;
! 369: struct m8820x_cmmu *cmmu;
! 370: u_int line, cnt;
! 371: int cssp, sctr, type;
! 372: apr_t apr;
! 373:
! 374: apr = ((0x00000 << PG_BITS) | CACHE_WT | CACHE_GLOBAL | CACHE_INH) &
! 375: ~APR_V;
! 376:
! 377: cmmu = m8820x_cmmu + (cpu << cmmu_shift);
! 378:
! 379: /*
! 380: * Setup CMMU pointers for faster exception processing.
! 381: * This relies on the board-dependent code putting instruction
! 382: * CMMUs and data CMMUs interleaved with instruction CMMUs first.
! 383: */
! 384: ci = &m88k_cpus[cpu];
! 385: switch (cmmu_shift) {
! 386: default:
! 387: /* exception code does not use ci_pfsr_* fields */
! 388: break;
! 389: case 2:
! 390: ci->ci_pfsr_d1 = (u_int)cmmu[3].cmmu_regs + CMMU_PFSR * 4;
! 391: ci->ci_pfsr_i1 = (u_int)cmmu[2].cmmu_regs + CMMU_PFSR * 4;
! 392: /* FALLTHROUGH */
! 393: case 1:
! 394: ci->ci_pfsr_d0 = (u_int)cmmu[1].cmmu_regs + CMMU_PFSR * 4;
! 395: ci->ci_pfsr_i0 = (u_int)cmmu[0].cmmu_regs + CMMU_PFSR * 4;
! 396: break;
! 397: }
! 398:
! 399: for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, cmmu++) {
! 400: type = CMMU_TYPE(cmmu->cmmu_regs[CMMU_IDR]);
! 401:
! 402: /*
! 403: * Reset cache
! 404: */
! 405: for (cssp = type == M88204_ID ? 3 : 0; cssp >= 0; cssp--)
! 406: for (line = 0; line <= 255; line++) {
! 407: cmmu->cmmu_regs[CMMU_SAR] =
! 408: line << MC88200_CACHE_SHIFT;
! 409: cmmu->cmmu_regs[CMMU_CSSP(cssp)] =
! 410: CMMU_CSSP_L5 | CMMU_CSSP_L4 |
! 411: CMMU_CSSP_L3 | CMMU_CSSP_L2 |
! 412: CMMU_CSSP_L1 | CMMU_CSSP_L0 |
! 413: CMMU_CSSP_VV(3, CMMU_VV_INVALID) |
! 414: CMMU_CSSP_VV(2, CMMU_VV_INVALID) |
! 415: CMMU_CSSP_VV(1, CMMU_VV_INVALID) |
! 416: CMMU_CSSP_VV(0, CMMU_VV_INVALID);
! 417: }
! 418:
! 419: /*
! 420: * Set the SCTR, SAPR, and UAPR to some known state.
! 421: * Snooping is enabled on multiprocessor systems; for
! 422: * instruction CMMUs as well so that we can share breakpoints.
! 423: * XXX Investigate why enabling parity at this point
! 424: * doesn't work.
! 425: */
! 426: sctr = cmmu->cmmu_regs[CMMU_SCTR] &
! 427: ~(CMMU_SCTR_PE | CMMU_SCTR_SE | CMMU_SCTR_PR);
! 428: #ifdef MULTIPROCESSOR
! 429: if (max_cpus > 1)
! 430: sctr |= CMMU_SCTR_SE;
! 431: #endif
! 432: cmmu->cmmu_regs[CMMU_SCTR] = sctr;
! 433:
! 434: cmmu->cmmu_regs[CMMU_SAPR] = cmmu->cmmu_regs[CMMU_UAPR] = apr;
! 435:
! 436: cmmu->cmmu_regs[CMMU_BWP0] = cmmu->cmmu_regs[CMMU_BWP1] =
! 437: cmmu->cmmu_regs[CMMU_BWP2] = cmmu->cmmu_regs[CMMU_BWP3] =
! 438: cmmu->cmmu_regs[CMMU_BWP4] = cmmu->cmmu_regs[CMMU_BWP5] =
! 439: cmmu->cmmu_regs[CMMU_BWP6] = cmmu->cmmu_regs[CMMU_BWP7] = 0;
! 440: cmmu->cmmu_regs[CMMU_SCR] = CMMU_FLUSH_CACHE_INV_ALL;
! 441: __asm__ __volatile__ ("|or r0, r0, %0" ::
! 442: "r" (cmmu->cmmu_regs[CMMU_SSR]));
! 443: cmmu->cmmu_regs[CMMU_SCR] = CMMU_FLUSH_SUPER_ALL;
! 444: cmmu->cmmu_regs[CMMU_SCR] = CMMU_FLUSH_USER_ALL;
! 445: }
! 446:
! 447: /*
! 448: * Enable instruction cache.
! 449: * Data cache will be enabled later.
! 450: */
! 451: apr &= ~CACHE_INH;
! 452: m8820x_cmmu_set_reg(CMMU_SAPR, apr, MODE_VAL, cpu, INST_CMMU);
! 453: }
! 454:
! 455: /*
! 456: * Just before poweroff or reset....
! 457: */
! 458: void
! 459: m8820x_shutdown()
! 460: {
! 461: unsigned cmmu_num;
! 462: struct m8820x_cmmu *cmmu;
! 463:
! 464: CMMU_LOCK;
! 465:
! 466: cmmu = m8820x_cmmu;
! 467: for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++, cmmu++) {
! 468: cmmu->cmmu_regs[CMMU_SCTR] &=
! 469: ~(CMMU_SCTR_PE | CMMU_SCTR_SE | CMMU_SCTR_PR);
! 470: cmmu->cmmu_regs[CMMU_SAPR] = cmmu->cmmu_regs[CMMU_UAPR] =
! 471: ((0x00000 << PG_BITS) | CACHE_INH) &
! 472: ~(CACHE_WT | CACHE_GLOBAL | APR_V);
! 473: }
! 474:
! 475: CMMU_UNLOCK;
! 476: }
! 477:
! 478: void
! 479: m8820x_set_sapr(cpuid_t cpu, apr_t ap)
! 480: {
! 481: CMMU_LOCK;
! 482:
! 483: m8820x_cmmu_set_reg(CMMU_SAPR, ap, 0, cpu, 0);
! 484:
! 485: CMMU_UNLOCK;
! 486: }
! 487:
! 488: void
! 489: m8820x_set_uapr(apr_t ap)
! 490: {
! 491: u_int32_t psr;
! 492: int cpu = cpu_number();
! 493:
! 494: disable_interrupt(psr);
! 495: CMMU_LOCK;
! 496:
! 497: m8820x_cmmu_set_reg(CMMU_UAPR, ap, 0, cpu, 0);
! 498:
! 499: CMMU_UNLOCK;
! 500: set_psr(psr);
! 501: }
! 502:
! 503: /*
! 504: * Functions that invalidate TLB entries.
! 505: */
! 506:
! 507: /*
! 508: * flush any tlb
! 509: */
! 510: void
! 511: m8820x_flush_tlb(cpuid_t cpu, unsigned kernel, vaddr_t vaddr, u_int count)
! 512: {
! 513: u_int32_t psr;
! 514:
! 515: disable_interrupt(psr);
! 516: CMMU_LOCK;
! 517:
! 518: /*
! 519: * Since segment operations are horribly expensive, don't
! 520: * do any here. Invalidations of up to three pages are performed
! 521: * as page invalidations, otherwise the entire tlb is flushed.
! 522: *
! 523: * Note that this code relies upon vaddr being page-aligned.
! 524: */
! 525: switch (count) {
! 526: default:
! 527: m8820x_cmmu_set_reg(CMMU_SCR,
! 528: kernel ? CMMU_FLUSH_SUPER_ALL : CMMU_FLUSH_USER_ALL,
! 529: 0, cpu, 0);
! 530: break;
! 531: case 3:
! 532: m8820x_cmmu_set_cmd(
! 533: kernel ? CMMU_FLUSH_SUPER_PAGE : CMMU_FLUSH_USER_PAGE,
! 534: ADDR_VAL, cpu, 0, vaddr);
! 535: vaddr += PAGE_SIZE;
! 536: /* FALLTHROUGH */
! 537: case 2:
! 538: m8820x_cmmu_set_cmd(
! 539: kernel ? CMMU_FLUSH_SUPER_PAGE : CMMU_FLUSH_USER_PAGE,
! 540: ADDR_VAL, cpu, 0, vaddr);
! 541: vaddr += PAGE_SIZE;
! 542: /* FALLTHROUGH */
! 543: case 1: /* most frequent situation */
! 544: case 0:
! 545: m8820x_cmmu_set_cmd(
! 546: kernel ? CMMU_FLUSH_SUPER_PAGE : CMMU_FLUSH_USER_PAGE,
! 547: ADDR_VAL, cpu, 0, vaddr);
! 548: break;
! 549: }
! 550:
! 551: CMMU_UNLOCK;
! 552: set_psr(psr);
! 553: }
! 554:
! 555: /*
! 556: * Functions that invalidate caches.
! 557: *
! 558: * Cache invalidates require physical addresses.
! 559: *
! 560: * We don't push Instruction Caches prior to invalidate because they are not
! 561: * snooped and never modified (I guess it doesn't matter then which form
! 562: * of the command we use then).
! 563: *
! 564: * XXX On systems with more than two CMMUs per CPU, we do not honor the
! 565: * address split - this does not work...
! 566: */
! 567:
! 568: #define trunc_cache_line(a) ((a) & ~(MC88200_CACHE_LINE - 1))
! 569: #define round_cache_line(a) trunc_cache_line((a) + MC88200_CACHE_LINE - 1)
! 570:
! 571: /*
! 572: * flush both Instruction and Data caches
! 573: */
! 574: void
! 575: m8820x_flush_cache(cpuid_t cpu, paddr_t pa, psize_t size)
! 576: {
! 577: u_int32_t psr;
! 578: psize_t count;
! 579:
! 580: size = round_cache_line(pa + size) - trunc_cache_line(pa);
! 581: pa = trunc_cache_line(pa);
! 582:
! 583: disable_interrupt(psr);
! 584: CMMU_LOCK;
! 585:
! 586: while (size != 0) {
! 587: count = (pa & PAGE_MASK) == 0 && size >= PAGE_SIZE ?
! 588: PAGE_SIZE : MC88200_CACHE_LINE;
! 589:
! 590: if (count <= MC88200_CACHE_LINE)
! 591: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_CBI_LINE,
! 592: 0 /* ADDR_VAL */, cpu, 0, pa);
! 593: else
! 594: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_CBI_PAGE,
! 595: 0 /* ADDR_VAL */, cpu, 0, pa);
! 596:
! 597: pa += count;
! 598: size -= count;
! 599: }
! 600: m8820x_cmmu_wait(cpu);
! 601:
! 602: CMMU_UNLOCK;
! 603: set_psr(psr);
! 604: }
! 605:
! 606: /*
! 607: * flush Instruction caches
! 608: */
! 609: void
! 610: m8820x_flush_inst_cache(cpuid_t cpu, paddr_t pa, psize_t size)
! 611: {
! 612: u_int32_t psr;
! 613: psize_t count;
! 614:
! 615: size = round_cache_line(pa + size) - trunc_cache_line(pa);
! 616: pa = trunc_cache_line(pa);
! 617:
! 618: disable_interrupt(psr);
! 619: CMMU_LOCK;
! 620:
! 621: while (size != 0) {
! 622: count = (pa & PAGE_MASK) == 0 && size >= PAGE_SIZE ?
! 623: PAGE_SIZE : MC88200_CACHE_LINE;
! 624:
! 625: if (count <= MC88200_CACHE_LINE)
! 626: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_INV_LINE,
! 627: MODE_VAL /* | ADDR_VAL */, cpu, INST_CMMU, pa);
! 628: else
! 629: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_INV_PAGE,
! 630: MODE_VAL /* | ADDR_VAL */, cpu, INST_CMMU, pa);
! 631:
! 632: pa += count;
! 633: size -= count;
! 634: }
! 635: m8820x_cmmu_wait(cpu);
! 636:
! 637: CMMU_UNLOCK;
! 638: set_psr(psr);
! 639: }
! 640:
! 641: void
! 642: m8820x_flush_data_page(cpuid_t cpu, paddr_t pa)
! 643: {
! 644: u_int32_t psr;
! 645:
! 646: disable_interrupt(psr);
! 647: CMMU_LOCK;
! 648:
! 649: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_CBI_PAGE,
! 650: MODE_VAL /* | ADDR_VAL */, cpu, DATA_CMMU, pa);
! 651: m8820x_cmmu_wait(cpu);
! 652:
! 653: CMMU_UNLOCK;
! 654: set_psr(psr);
! 655: }
! 656:
! 657: /*
! 658: * sync dcache - icache is never dirty but needs to be invalidated as well.
! 659: */
! 660: void
! 661: m8820x_cmmu_sync_cache(int cpu, paddr_t pa, psize_t size)
! 662: {
! 663: if (size <= MC88200_CACHE_LINE) {
! 664: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_CB_LINE,
! 665: MODE_VAL /* | ADDR_VAL */, cpu, DATA_CMMU, pa);
! 666: } else {
! 667: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_CB_PAGE,
! 668: MODE_VAL /* | ADDR_VAL */, cpu, DATA_CMMU, pa);
! 669: }
! 670: m8820x_cmmu_wait(cpu);
! 671: }
! 672:
! 673: void
! 674: m8820x_cmmu_sync_inval_cache(int cpu, paddr_t pa, psize_t size)
! 675: {
! 676: if (size <= MC88200_CACHE_LINE) {
! 677: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_INV_LINE,
! 678: MODE_VAL /* | ADDR_VAL */, cpu, INST_CMMU, pa);
! 679: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_CBI_LINE,
! 680: MODE_VAL /* | ADDR_VAL */, cpu, DATA_CMMU, pa);
! 681: } else {
! 682: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_INV_PAGE,
! 683: MODE_VAL /* | ADDR_VAL */, cpu, INST_CMMU, pa);
! 684: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_CBI_PAGE,
! 685: MODE_VAL /* | ADDR_VAL */, cpu, DATA_CMMU, pa);
! 686: }
! 687: m8820x_cmmu_wait(cpu);
! 688: }
! 689:
! 690: void
! 691: m8820x_cmmu_inval_cache(int cpu, paddr_t pa, psize_t size)
! 692: {
! 693: if (size <= MC88200_CACHE_LINE) {
! 694: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_INV_LINE,
! 695: 0 /* ADDR_VAL */, cpu, 0, pa);
! 696: } else {
! 697: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_INV_PAGE,
! 698: 0 /* ADDR_VAL */, cpu, 0, pa);
! 699: }
! 700: m8820x_cmmu_wait(cpu);
! 701: }
! 702:
! 703: void
! 704: m8820x_dma_cachectl(pmap_t pmap, vaddr_t _va, vsize_t _size, int op)
! 705: {
! 706: u_int32_t psr;
! 707: int cpu = cpu_number();
! 708: vaddr_t va;
! 709: paddr_t pa;
! 710: psize_t size, count;
! 711: void (*flusher)(int, paddr_t, psize_t);
! 712:
! 713: va = trunc_cache_line(_va);
! 714: size = round_cache_line(_va + _size) - va;
! 715:
! 716: switch (op) {
! 717: case DMA_CACHE_SYNC:
! 718: flusher = m8820x_cmmu_sync_cache;
! 719: break;
! 720: case DMA_CACHE_SYNC_INVAL:
! 721: flusher = m8820x_cmmu_sync_inval_cache;
! 722: break;
! 723: default:
! 724: if (va != _va || size != _size)
! 725: flusher = m8820x_cmmu_sync_inval_cache;
! 726: else
! 727: flusher = m8820x_cmmu_inval_cache;
! 728: break;
! 729: }
! 730:
! 731: disable_interrupt(psr);
! 732: CMMU_LOCK;
! 733:
! 734: while (size != 0) {
! 735: count = (va & PAGE_MASK) == 0 && size >= PAGE_SIZE ?
! 736: PAGE_SIZE : MC88200_CACHE_LINE;
! 737:
! 738: if (pmap_extract(pmap, va, &pa) != FALSE)
! 739: (*flusher)(cpu, pa, count);
! 740:
! 741: va += count;
! 742: size -= count;
! 743: }
! 744:
! 745: CMMU_UNLOCK;
! 746: set_psr(psr);
! 747: }
! 748:
! 749: void
! 750: m8820x_dma_cachectl_pa(paddr_t _pa, psize_t _size, int op)
! 751: {
! 752: u_int32_t psr;
! 753: int cpu = cpu_number();
! 754: paddr_t pa;
! 755: psize_t size, count;
! 756: void (*flusher)(int, paddr_t, psize_t);
! 757:
! 758: pa = trunc_cache_line(_pa);
! 759: size = round_cache_line(_pa + _size) - pa;
! 760:
! 761: switch (op) {
! 762: case DMA_CACHE_SYNC:
! 763: flusher = m8820x_cmmu_sync_cache;
! 764: break;
! 765: case DMA_CACHE_SYNC_INVAL:
! 766: flusher = m8820x_cmmu_sync_inval_cache;
! 767: break;
! 768: default:
! 769: if (pa != _pa || size != _size)
! 770: flusher = m8820x_cmmu_sync_inval_cache;
! 771: else
! 772: flusher = m8820x_cmmu_inval_cache;
! 773: break;
! 774: }
! 775:
! 776: disable_interrupt(psr);
! 777: CMMU_LOCK;
! 778:
! 779: while (size != 0) {
! 780: count = (pa & PAGE_MASK) == 0 && size >= PAGE_SIZE ?
! 781: PAGE_SIZE : MC88200_CACHE_LINE;
! 782:
! 783: (*flusher)(cpu, pa, count);
! 784:
! 785: pa += count;
! 786: size -= count;
! 787: }
! 788:
! 789: CMMU_UNLOCK;
! 790: set_psr(psr);
! 791: }
CVSweb