[BACK]Return to m8820x_machdep.c CVS log [TXT][DIR] Up to [local] / sys / arch / m88k / m88k

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