[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

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