diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2004-08-06 13:23:50 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2004-08-06 13:23:50 +0000 |
commit | 49b58be77a7184b158ae3c2dc857a30e9bcf8998 (patch) | |
tree | 39a3112308bb39264e791469871030b51b03b3fb /sys/arch/luna88k | |
parent | e8cff797fd0aa9299d0fea90914b6c164b05d758 (diff) |
Merge Luna88k and mvme88k M88200 management code. Features:
- simpler structures (no more redundant or easily computable information).
- split scheme configuration (for 4:1 and 8:1 designs) is only compiled in
if necessary (read: only on a mvme88k kernel configured for MVME188 support),
which speeds up CMMU operations on the Luna88k.
- will not enable bus snopping on a monoprocessor system.
Tested on Luna88k-2, MVME187 and various MVME188 by aoyama@ and I.
Diffstat (limited to 'sys/arch/luna88k')
-rw-r--r-- | sys/arch/luna88k/luna88k/m8820x.c | 1411 |
1 files changed, 45 insertions, 1366 deletions
diff --git a/sys/arch/luna88k/luna88k/m8820x.c b/sys/arch/luna88k/luna88k/m8820x.c index 02f00e3521a..1c5c17a5149 100644 --- a/sys/arch/luna88k/luna88k/m8820x.c +++ b/sys/arch/luna88k/luna88k/m8820x.c @@ -1,4 +1,4 @@ -/* $OpenBSD: m8820x.c,v 1.4 2004/08/04 15:54:35 miod Exp $ */ +/* $OpenBSD: m8820x.c,v 1.5 2004/08/06 13:23:47 miod Exp $ */ /* * Copyright (c) 2004, Miodrag Vallat. * @@ -83,189 +83,14 @@ #include <sys/param.h> #include <sys/systm.h> -#include <sys/simplelock.h> #include <machine/asm_macro.h> -#include <machine/board.h> #include <machine/cpu_number.h> #include <machine/locore.h> #include <machine/cmmu.h> #include <machine/m8820x.h> - -#include <uvm/uvm_extern.h> - -#ifdef DDB -#include <ddb/db_output.h> /* db_printf() */ -#endif /* DDB */ - -/* - * On some versions of the 88200, page size flushes don't work. I am using - * sledge hammer approach till I find for sure which ones are bad XXX nivas - */ -#define BROKEN_MMU_MASK - -#ifdef DEBUG -unsigned int m8820x_debuglevel; -#define dprintf(_X_) \ - do { \ - if (m8820x_debuglevel != 0) { \ - unsigned int psr = disable_interrupts_return_psr(); \ - printf("%d: ", cpu_number()); \ - printf _X_; \ - set_psr(psr); \ - } \ - } while (0) -#else -#define dprintf(_X_) do { } while (0) -#endif - -void m8820x_cmmu_init(void); -void m8820x_setup_board_config(void); -void m8820x_cpu_configuration_print(int); -void m8820x_cmmu_shutdown_now(void); -void m8820x_cmmu_parity_enable(void); -unsigned m8820x_cmmu_cpu_number(void); -void m8820x_cmmu_set_sapr(unsigned, unsigned); -void m8820x_cmmu_set_uapr(unsigned); -void m8820x_cmmu_flush_tlb(unsigned, unsigned, vaddr_t, vsize_t); -void m8820x_cmmu_flush_cache(int, paddr_t, psize_t); -void m8820x_cmmu_flush_inst_cache(int, paddr_t, psize_t); -void m8820x_cmmu_flush_data_cache(int, paddr_t, psize_t); -void m8820x_dma_cachectl(vaddr_t, vsize_t, int); -void m8820x_dma_cachectl_pa(paddr_t, psize_t, int); -void m8820x_cmmu_dump_config(void); -void m8820x_cmmu_show_translation(unsigned, unsigned, unsigned, int); -void m8820x_show_apr(unsigned); - -/* This is the function table for the mc8820x CMMUs */ -struct cmmu_p cmmu8820x = { - m8820x_cmmu_init, - m8820x_setup_board_config, - m8820x_cpu_configuration_print, - m8820x_cmmu_shutdown_now, - m8820x_cmmu_parity_enable, - m8820x_cmmu_cpu_number, - m8820x_cmmu_set_sapr, - m8820x_cmmu_set_uapr, - m8820x_cmmu_flush_tlb, - m8820x_cmmu_flush_cache, - m8820x_cmmu_flush_inst_cache, - m8820x_cmmu_flush_data_cache, - m8820x_dma_cachectl, - m8820x_dma_cachectl_pa, -#ifdef DDB - m8820x_cmmu_dump_config, - m8820x_cmmu_show_translation, -#else - NULL, - NULL, -#endif -#ifdef DEBUG - m8820x_show_apr, -#else - NULL, -#endif -}; - -/* - * CMMU kernel information - */ -struct m8820x_cmmu { - unsigned *volatile cmmu_regs; /* CMMU "base" area */ - unsigned int cmmu_cpu; /* cpu number it is attached to */ - unsigned int cmmu_type; -#define INST_CMMU 0 -#define DATA_CMMU 1 - unsigned int cmmu_access; -#define CMMU_ACS_USER 0 -#define CMMU_ACS_SUPER 1 -#define CMMU_ACS_BOTH 2 - unsigned int cmmu_alive; -#define CMMU_DEAD 0 /* This cmmu is not there */ -#define CMMU_AVAILABLE 1 /* It's there, but which cpu's? */ -#define CMMU_MARRIED 2 /* Know which cpu it belongs to. */ - vaddr_t cmmu_addr; /* address range */ - vaddr_t cmmu_addr_mask; /* address mask */ - int cmmu_addr_match;/* return value of address comparison */ -}; - -/* - * Structure for accessing MMUS properly - */ - -#define MAX_CMMUS (2 * MAX_CPUS) /* maximum cmmus on the board */ - -struct m8820x_cmmu m8820x_cmmu[MAX_CMMUS] = -{ - /* address, cpu, mode, access, alive, addr, mask */ - {(unsigned *volatile)CMMU_I0, -1, INST_CMMU, CMMU_ACS_BOTH, CMMU_DEAD, 0, 0}, - {(unsigned *volatile)CMMU_D0, -1, DATA_CMMU, CMMU_ACS_BOTH, CMMU_DEAD, 0, 0}, - {(unsigned *volatile)CMMU_I1, -1, INST_CMMU, CMMU_ACS_BOTH, CMMU_DEAD, 0, 0}, - {(unsigned *volatile)CMMU_D1, -1, DATA_CMMU, CMMU_ACS_BOTH, CMMU_DEAD, 0, 0}, - {(unsigned *volatile)CMMU_I2, -1, INST_CMMU, CMMU_ACS_BOTH, CMMU_DEAD, 0, 0}, - {(unsigned *volatile)CMMU_D2, -1, DATA_CMMU, CMMU_ACS_BOTH, CMMU_DEAD, 0, 0}, - {(unsigned *volatile)CMMU_I3, -1, INST_CMMU, CMMU_ACS_BOTH, CMMU_DEAD, 0, 0}, - {(unsigned *volatile)CMMU_D3, -1, DATA_CMMU, CMMU_ACS_BOTH, CMMU_DEAD, 0, 0} -}; - -struct cpu_cmmu { - struct m8820x_cmmu *pair[2]; -} cpu_cmmu[MAX_CPUS]; - -/* - * CMMU per CPU split strategies - */ - -#define CMMU_SPLIT_ADDRESS 0x00 -#define CMMU_SPLIT_SPV 0x01 -#define CMMU_SPLIT_SRAM_SPV 0x02 -#define CMMU_SPLIT_SRAM_ALL 0x03 - -#define CMMU_SPLIT_MASK 0x03 - -struct cmmu_strategy { - int inst; - int data; -} cpu_cmmu_strategy[] = { - /* inst data */ - { CMMU_SPLIT_ADDRESS, CMMU_SPLIT_ADDRESS}, /* CPU 0 */ - { CMMU_SPLIT_ADDRESS, CMMU_SPLIT_ADDRESS}, /* CPU 1 */ - { CMMU_SPLIT_ADDRESS, CMMU_SPLIT_ADDRESS}, /* CPU 2 */ - { CMMU_SPLIT_ADDRESS, CMMU_SPLIT_ADDRESS} /* CPU 3 */ -}; - -unsigned int cmmu_shift; - -/* local prototypes */ -void m8820x_cmmu_set(int, unsigned, int, int, int, int, vaddr_t); -void m8820x_cmmu_wait(int); -void m8820x_cmmu_sync_cache(paddr_t, psize_t); -void m8820x_cmmu_sync_inval_cache(paddr_t, psize_t); -void m8820x_cmmu_inval_cache(paddr_t, psize_t); - -/* Flags passed to m8820x_cmmu_set() */ -#define MODE_VAL 0x01 -#define ACCESS_VAL 0x02 -#define ADDR_VAL 0x04 - -#ifdef DEBUG -void -m8820x_show_apr(value) - unsigned value; -{ - printf("table @ 0x%x000", PG_PFNUM(value)); - if (value & CACHE_WT) - printf(", writethrough"); - if (value & CACHE_GLOBAL) - printf(", global"); - if (value & CACHE_INH) - printf(", cache inhibit"); - if (value & APR_V) - printf(", valid"); - printf("\n"); -} -#endif +#include <machine/board.h> /* * This routine sets up the CPU/CMMU configuration. @@ -273,418 +98,66 @@ m8820x_show_apr(value) void m8820x_setup_board_config() { - int num, cmmu_num; - unsigned *volatile cr; + struct m8820x_cmmu *cmmu; + int num; master_cpu = 0; /* temp to get things going */ - max_cpus = 4; - max_cmmus = 8; - cmmu_shift = ff1(max_cmmus / max_cpus); + m8820x_cmmu[0].cmmu_regs = (void *)CMMU_I0; + m8820x_cmmu[1].cmmu_regs = (void *)CMMU_D0; + m8820x_cmmu[2].cmmu_regs = (void *)CMMU_I1; + m8820x_cmmu[3].cmmu_regs = (void *)CMMU_D1; + m8820x_cmmu[4].cmmu_regs = (void *)CMMU_I2; + m8820x_cmmu[5].cmmu_regs = (void *)CMMU_D2; + m8820x_cmmu[6].cmmu_regs = (void *)CMMU_I3; + m8820x_cmmu[7].cmmu_regs = (void *)CMMU_D3; + + /* + * Probe all CMMU address to discover if the CPU slots are populated. + */ + cmmu = m8820x_cmmu; + for (max_cmmus = 0; max_cmmus < 8; max_cmmus++, cmmu++) { + if (badwordaddr((vaddr_t)cmmu->cmmu_regs) != 0) + break; + } + + max_cpus = max_cmmus >> 1; + max_cmmus = max_cpus << 1; + cmmu_shift = 1; /* fixed 2:1 configuration */ +#ifdef DEBUG /* - * Probe for available MMUs + * Check CMMU type */ - for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++) { - cr = m8820x_cmmu[cmmu_num].cmmu_regs; + for (num = 0; num < max_cmmus; num++) { + volatile unsigned *cr = m8820x_cmmu[num].cmmu_regs; if (badwordaddr((vaddr_t)cr) == 0) { int type; type = CMMU_TYPE(cr[CMMU_IDR]); -#ifdef DIAGNOSTIC if (type != M88200_ID && type != M88204_ID) { printf("WARNING: non M8820x circuit found " "at CMMU address %p\n", cr); continue; /* will probably die quickly */ } -#endif - m8820x_cmmu[cmmu_num].cmmu_alive = CMMU_AVAILABLE; - dprintf(("m8820x_setup_cmmu_config: CMMU %d found at %p\n", - cmmu_num, cr)); } } +#endif /* - * Now that we know which CMMUs are there, let's report on which - * CPU/CMMU sets seem complete (hopefully all) + * Now that we know which CMMUs are there, report every association */ for (num = 0; num < max_cpus; num++) { - int i, type; + int type; - for (i = 0; i < (1 << cmmu_shift); i++) { - dprintf(("cmmu_init: testing CMMU %d for CPU %d\n", - (num << cmmu_shift) | i, num)); -#ifdef DIAGNOSTIC - if (m8820x_cmmu[(num << cmmu_shift) | i].cmmu_alive == CMMU_DEAD) { - printf("CMMU %d attached to CPU %d is not working\n", - (num << cmmu_shift) | i, num); - continue; /* will probably die quickly */ - } -#endif - } cpu_sets[num] = 1; /* This cpu installed... */ type = CMMU_TYPE(m8820x_cmmu[num << cmmu_shift]. cmmu_regs[CMMU_IDR]); - printf("CPU%d is attached with %d MC%x CMMUs\n", - num, 1 << cmmu_shift, type == M88204_ID ? 0x88204 : 0x88200); - } - - /* - * Calculate the CMMU<->CPU connections - */ - for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++) { - m8820x_cmmu[cmmu_num].cmmu_cpu = - (cmmu_num * max_cpus) / max_cmmus; - dprintf(("m8820x_setup_cmmu_config: CMMU %d connected with CPU %d\n", - cmmu_num, m8820x_cmmu[cmmu_num].cmmu_cpu)); - } - - /* - * Now set m8820x_cmmu[].cmmu_access and addr - */ - for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++) { - /* - * We don't set up anything for the hardwired configurations. - */ - m8820x_cmmu[cmmu_num].cmmu_addr = 0; - m8820x_cmmu[cmmu_num].cmmu_addr_mask = 0; - m8820x_cmmu[cmmu_num].cmmu_addr_match = 1; - m8820x_cmmu[cmmu_num].cmmu_access = CMMU_ACS_BOTH; - } -} - -#ifdef DDB - -const char *cmmu_strat_string[] = { - "address split ", - "user/spv split", - "spv SRAM split", - "all SRAM split" -}; - -void -m8820x_cmmu_dump_config() -{ - int cmmu_num; - - db_printf("Current CPU/CMMU configuration:\n"); - - for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++) { - db_printf("CMMU #%d: %s CMMU for CPU %d:\n Strategy: %s\n %s access addr 0x%08lx mask 0x%08lx match %s\n", - cmmu_num, - (m8820x_cmmu[cmmu_num].cmmu_type == INST_CMMU) ? "inst" : "data", - m8820x_cmmu[cmmu_num].cmmu_cpu, - cmmu_strat_string[(m8820x_cmmu[cmmu_num].cmmu_type == INST_CMMU) ? - cpu_cmmu_strategy[m8820x_cmmu[cmmu_num].cmmu_cpu].inst : - cpu_cmmu_strategy[m8820x_cmmu[cmmu_num].cmmu_cpu].data], - (m8820x_cmmu[cmmu_num].cmmu_access == CMMU_ACS_BOTH) ? "User and spv" : - ((m8820x_cmmu[cmmu_num].cmmu_access == CMMU_ACS_USER) ? "User " : - "Supervisor "), - m8820x_cmmu[cmmu_num].cmmu_addr, - m8820x_cmmu[cmmu_num].cmmu_addr_mask, - m8820x_cmmu[cmmu_num].cmmu_addr_match ? "TRUE" : "FALSE"); + printf("CPU%d is associated to %d MC8820%c CMMUs\n", + num, 1 << cmmu_shift, type == M88204_ID ? '4' : '0'); } } -#endif /* DDB */ - -/* - * This function is called by the MMU module and pokes values - * into the CMMU's registers. - */ -void -m8820x_cmmu_set(reg, val, flags, num, mode, access, addr) - int reg; - unsigned val; - int flags, num, mode, access; - vaddr_t addr; -{ - int mmu; - - /* - * We scan all CMMUs to find the matching ones and store the - * values there. - */ - for (mmu = num << cmmu_shift; - mmu < (num + 1) << cmmu_shift; mmu++) { - if (((flags & MODE_VAL)) && - (m8820x_cmmu[mmu].cmmu_type != mode)) - continue; - if (((flags & ACCESS_VAL)) && - (m8820x_cmmu[mmu].cmmu_access != access) && - (m8820x_cmmu[mmu].cmmu_access != CMMU_ACS_BOTH)) - continue; - if (flags & ADDR_VAL) { - if (((addr & m8820x_cmmu[mmu].cmmu_addr_mask) == m8820x_cmmu[mmu].cmmu_addr) - != m8820x_cmmu[mmu].cmmu_addr_match) { - continue; - } - } - m8820x_cmmu[mmu].cmmu_regs[reg] = val; - } -} - -/* - * Force a read from the CMMU status register, thereby forcing execution to - * stop until all pending CMMU operations are finished. - * This is used by the various cache invalidation functions. - */ -void -m8820x_cmmu_wait(int cpu) -{ - int mmu; - - /* - * We scan all related CMMUs and read their status register. - */ - for (mmu = cpu << cmmu_shift; - mmu < (cpu + 1) << cmmu_shift; mmu++) { -#ifdef DEBUG - if (m8820x_cmmu[mmu].cmmu_regs[CMMU_SSR] & CMMU_SSR_BE) { - panic("cache flush failed!"); - } -#else - /* force the read access, but do not issue this statement... */ - __asm__ __volatile__ ("|or r0, r0, %0" :: - "r" (m8820x_cmmu[mmu].cmmu_regs[CMMU_SSR])); -#endif - } -} - -const char *mmutypes[8] = { - "Unknown (0)", - "Unknown (1)", - "Unknown (2)", - "Unknown (3)", - "Unknown (4)", - "M88200 (16K)", - "M88204 (64K)", - "Unknown (7)" -}; - -/* - * Should only be called after the calling cpus knows its cpu - * number and master/slave status . Should be called first - * by the master, before the slaves are started. -*/ -void -m8820x_cpu_configuration_print(master) - int master; -{ - int pid = read_processor_identification_register(); - int proctype = (pid & 0xff00) >> 8; - int procvers = (pid & 0xe) >> 1; - int mmu, cpu = cpu_number(); - struct simplelock print_lock; - - if (master) - simple_lock_init(&print_lock); - - simple_lock(&print_lock); - - printf("cpu%d: ", cpu); - if (proctype != 0) { - printf("unknown model arch 0x%x rev 0x%x\n", - proctype, procvers); - simple_unlock(&print_lock); - return; - } - - printf("M88100 rev 0x%x", procvers); -#if 0 /* not useful yet */ -#ifdef MVME188 - if (brdtyp == BRD_188) - printf(", %s", master ? "master" : "slave"); -#endif -#endif - printf(", %d CMMU", 1 << cmmu_shift); - - for (mmu = cpu << cmmu_shift; mmu < (cpu + 1) << cmmu_shift; - mmu++) { - int idr = m8820x_cmmu[mmu].cmmu_regs[CMMU_IDR]; - int mmuid = CMMU_TYPE(idr); - int access = m8820x_cmmu[mmu].cmmu_access; - - if (mmu % 2 == 0) - printf("\ncpu%d: ", cpu); - else - printf(", "); - - if (mmutypes[mmuid][0] == 'U') - printf("unknown model id 0x%x", mmuid); - else - printf("%s", mmutypes[mmuid]); - printf(" rev 0x%x, %s %scache", - CMMU_VERSION(idr), - access == CMMU_ACS_BOTH ? "global" : - (access == CMMU_ACS_USER ? "user" : "sup"), - m8820x_cmmu[mmu].cmmu_type == INST_CMMU ? "I" : "D"); - } - printf("\n"); - -#ifndef ERRATA__XXX_USR - { - static int errata_warn = 0; - - if (proctype != 0 && procvers < 2) { - if (!errata_warn++) - printf("WARNING: M88100 bug workaround code " - "not enabled.\nPlease recompile the kernel " - "with option ERRATA__XXX_USR !\n"); - } - } -#endif - - simple_unlock(&print_lock); -} - -/* - * CMMU initialization routine - */ -void -m8820x_cmmu_init() -{ - unsigned int line, cmmu_num; - int cssp, cpu, type; - u_int32_t apr; - unsigned *volatile cr; - - for (cpu = 0; cpu < max_cpus; cpu++) { - cpu_cmmu[cpu].pair[INST_CMMU] = 0; - cpu_cmmu[cpu].pair[DATA_CMMU] = 0; - } - - for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++) { - if (m8820x_cmmu[cmmu_num].cmmu_alive != CMMU_DEAD) { - cr = m8820x_cmmu[cmmu_num].cmmu_regs; - type = CMMU_TYPE(cr[CMMU_IDR]); - - cpu_cmmu[m8820x_cmmu[cmmu_num].cmmu_cpu]. - pair[m8820x_cmmu[cmmu_num].cmmu_type] = - &m8820x_cmmu[cmmu_num]; - - /* - * Reset cache - */ - for (cssp = type == M88204_ID ? 3 : 0; - cssp >= 0; cssp--) - for (line = 0; line <= 255; line++) { - cr[CMMU_SAR] = - line << MC88200_CACHE_SHIFT; - cr[CMMU_CSSP(cssp)] = - CMMU_CSSP_L5 | CMMU_CSSP_L4 | - CMMU_CSSP_L3 | CMMU_CSSP_L2 | - CMMU_CSSP_L1 | CMMU_CSSP_L0 | - CMMU_CSSP_VV(3, CMMU_VV_INVALID) | - CMMU_CSSP_VV(2, CMMU_VV_INVALID) | - CMMU_CSSP_VV(1, CMMU_VV_INVALID) | - CMMU_CSSP_VV(0, CMMU_VV_INVALID); - } - - /* - * Set the SCTR, SAPR, and UAPR to some known state - */ - cr[CMMU_SCTR] &= - ~(CMMU_SCTR_PE | CMMU_SCTR_SE | CMMU_SCTR_PR); - cr[CMMU_SAPR] = cr[CMMU_UAPR] = - ((0x00000 << PG_BITS) | CACHE_WT | CACHE_GLOBAL | - CACHE_INH) & ~APR_V; - - cr[CMMU_BWP0] = cr[CMMU_BWP1] = - cr[CMMU_BWP2] = cr[CMMU_BWP3] = - cr[CMMU_BWP4] = cr[CMMU_BWP5] = - cr[CMMU_BWP6] = cr[CMMU_BWP7] = 0; - cr[CMMU_SCR] = CMMU_FLUSH_CACHE_INV_ALL; - __asm__ __volatile__ ("|or r0, r0, %0" :: - "r" (cr[CMMU_SSR])); - cr[CMMU_SCR] = CMMU_FLUSH_SUPER_ALL; - cr[CMMU_SCR] = CMMU_FLUSH_USER_ALL; - } - } - - /* - * Enable snooping on MVME188 only. - * Snooping is enabled for instruction cmmus as well so that - * we can share breakpoints. - */ - - for (cpu = 0; cpu < max_cpus; cpu++) { - if (cpu_sets[cpu] == 0) - continue; - - m8820x_cmmu_set(CMMU_SCTR, CMMU_SCTR_SE, MODE_VAL, cpu, - DATA_CMMU, 0, 0); - m8820x_cmmu_set(CMMU_SCTR, CMMU_SCTR_SE, MODE_VAL, cpu, - INST_CMMU, 0, 0); - - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_SUPER_ALL, - ACCESS_VAL, cpu, 0, CMMU_ACS_SUPER, 0); - m8820x_cmmu_wait(cpu); - /* Icache gets flushed just below */ - } - - /* - * Enable instruction cache. - * Data cache can not be enabled at this point, because some device - * addresses can never be cached, and the no-caching zones are not - * set up yet. - */ - for (cpu = 0; cpu < max_cpus; cpu++) { - if (cpu_sets[cpu] == 0) - continue; - - apr = ((0x00000 << PG_BITS) | CACHE_WT | CACHE_GLOBAL) - & ~(CACHE_INH | APR_V); - - m8820x_cmmu_set(CMMU_SAPR, apr, MODE_VAL, cpu, INST_CMMU, 0, 0); - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_SUPER_ALL, - ACCESS_VAL, cpu, 0, CMMU_ACS_SUPER, 0); - m8820x_cmmu_wait(cpu); - } -} - -/* - * Just before poweroff or reset.... - */ -void -m8820x_cmmu_shutdown_now() -{ - unsigned cmmu_num; - unsigned *volatile cr; - - CMMU_LOCK; - for (cmmu_num = 0; cmmu_num < MAX_CMMUS; cmmu_num++) - if (m8820x_cmmu[cmmu_num].cmmu_alive != CMMU_DEAD) { - cr = m8820x_cmmu[cmmu_num].cmmu_regs; - - cr[CMMU_SCTR] &= - ~(CMMU_SCTR_PE | CMMU_SCTR_SE | CMMU_SCTR_PR); - cr[CMMU_SAPR] = cr[CMMU_UAPR] = - ((0x00000 << PG_BITS) | CACHE_INH) & - ~(CACHE_WT | CACHE_GLOBAL | APR_V); - } - CMMU_UNLOCK; -} - -/* - * enable parity - */ -void -m8820x_cmmu_parity_enable() -{ - unsigned cmmu_num; - unsigned *volatile cr; - - CMMU_LOCK; - - for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++) - if (m8820x_cmmu[cmmu_num].cmmu_alive != CMMU_DEAD) { - cr = m8820x_cmmu[cmmu_num].cmmu_regs; - cr[CMMU_SCTR] |= CMMU_SCTR_PE; - } - - CMMU_UNLOCK; -} /* * Find out the CPU number from accessing CMMU @@ -696,34 +169,30 @@ m8820x_cmmu_parity_enable() unsigned m8820x_cmmu_cpu_number() { - unsigned cmmu_no; - int i, cpu; + unsigned cmmu; + u_int i; CMMU_LOCK; for (i = 0; i < 10; i++) { - /* clear CMMU p-bus status registers */ - for (cmmu_no = 0; cmmu_no < MAX_CMMUS; cmmu_no++) { - if (m8820x_cmmu[cmmu_no].cmmu_alive == CMMU_AVAILABLE && - m8820x_cmmu[cmmu_no].cmmu_type == DATA_CMMU) - m8820x_cmmu[cmmu_no].cmmu_regs[CMMU_PFSR] = 0; + /* clear CMMU P-bus status registers */ + for (cmmu = 0; cmmu < max_cmmus; cmmu++) { + if (CMMU_MODE(cmmu) != INST_CMMU) + m8820x_cmmu[cmmu].cmmu_regs[CMMU_PFSR] = 0; } /* access faulting address */ badwordaddr((vaddr_t)ILLADDRESS); /* check which CMMU reporting the fault */ - for (cmmu_no = 0; cmmu_no < MAX_CMMUS; cmmu_no++) { - if (m8820x_cmmu[cmmu_no].cmmu_alive == CMMU_AVAILABLE && - m8820x_cmmu[cmmu_no].cmmu_type == DATA_CMMU && - CMMU_PFSR_FAULT(m8820x_cmmu[cmmu_no]. + for (cmmu = 0; cmmu < max_cmmus; cmmu++) { + if (CMMU_MODE(cmmu) != INST_CMMU && + CMMU_PFSR_FAULT(m8820x_cmmu[cmmu]. cmmu_regs[CMMU_PFSR]) != CMMU_PFSR_SUCCESS) { /* clean register, just in case... */ - m8820x_cmmu[cmmu_no].cmmu_regs[CMMU_PFSR] = 0; - m8820x_cmmu[cmmu_no].cmmu_alive = CMMU_MARRIED; - cpu = m8820x_cmmu[cmmu_no].cmmu_cpu; + m8820x_cmmu[cmmu].cmmu_regs[CMMU_PFSR] = 0; CMMU_UNLOCK; - return cpu; + return cmmu >> 1; } } } @@ -731,793 +200,3 @@ m8820x_cmmu_cpu_number() panic("m8820x_cmmu_cpu_number: could not determine my cpu number"); } - -void -m8820x_cmmu_set_sapr(cpu, ap) - unsigned cpu, ap; -{ - CMMU_LOCK; - m8820x_cmmu_set(CMMU_SAPR, ap, ACCESS_VAL, cpu, 0, CMMU_ACS_SUPER, 0); - CMMU_UNLOCK; -} - -void -m8820x_cmmu_set_uapr(ap) - unsigned ap; -{ - int s = splhigh(); - int cpu = cpu_number(); - - CMMU_LOCK; - m8820x_cmmu_set(CMMU_UAPR, ap, ACCESS_VAL, cpu, 0, CMMU_ACS_USER, 0); - CMMU_UNLOCK; - splx(s); -} - -/* - * Functions that invalidate TLB entries. - */ - -/* - * flush any tlb - */ -void -m8820x_cmmu_flush_tlb(unsigned cpu, unsigned kernel, vaddr_t vaddr, - vsize_t size) -{ - int s = splhigh(); - - CMMU_LOCK; - - /* - * Since segment operations are horribly expensive, don't - * do any here. Invalidations of up to three pages are performed - * as page invalidations, otherwise the entire tlb is flushed. - * - * Note that this code relies upon size being a multiple of - * a page and vaddr being page-aligned. - */ - if (size == PAGE_SIZE) { /* most frequent situation */ - m8820x_cmmu_set(CMMU_SAR, vaddr, - ADDR_VAL | ACCESS_VAL, cpu, 0, - kernel ? CMMU_ACS_SUPER : CMMU_ACS_USER, vaddr); - m8820x_cmmu_set(CMMU_SCR, - kernel ? CMMU_FLUSH_SUPER_PAGE : CMMU_FLUSH_USER_PAGE, - ADDR_VAL | ACCESS_VAL, cpu, 0, - kernel ? CMMU_ACS_SUPER : CMMU_ACS_USER, vaddr); - } else if (size > 3 * PAGE_SIZE) { - m8820x_cmmu_set(CMMU_SCR, - kernel ? CMMU_FLUSH_SUPER_ALL : CMMU_FLUSH_USER_ALL, - ACCESS_VAL, cpu, 0, - kernel ? CMMU_ACS_SUPER : CMMU_ACS_USER, 0); - } else - while (size != 0) { - m8820x_cmmu_set(CMMU_SAR, vaddr, - ADDR_VAL | ACCESS_VAL, cpu, 0, - kernel ? CMMU_ACS_SUPER : CMMU_ACS_USER, vaddr); - m8820x_cmmu_set(CMMU_SCR, - kernel ? CMMU_FLUSH_SUPER_PAGE : CMMU_FLUSH_USER_PAGE, - ADDR_VAL | ACCESS_VAL, cpu, 0, - kernel ? CMMU_ACS_SUPER : CMMU_ACS_USER, vaddr); - - size -= PAGE_SIZE; - vaddr += PAGE_SIZE; - } - - CMMU_UNLOCK; - splx(s); -} - -/* - * Functions that invalidate caches. - * - * Cache invalidates require physical addresses. Care must be exercised when - * using segment invalidates. This implies that the starting physical address - * plus the segment length should be invalidated. A typical mistake is to - * extract the first physical page of a segment from a virtual address, and - * then expecting to invalidate when the pages are not physically contiguous. - * - * We don't push Instruction Caches prior to invalidate because they are not - * snooped and never modified (I guess it doesn't matter then which form - * of the command we use then). - */ - -/* - * flush both Instruction and Data caches - */ -void -m8820x_cmmu_flush_cache(int cpu, paddr_t physaddr, psize_t size) -{ - int s = splhigh(); - CMMU_LOCK; - -#if !defined(BROKEN_MMU_MASK) - if (size > NBSG) { - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, 0, - cpu, 0, 0, 0); - } else if (size <= MC88200_CACHE_LINE) { - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, ADDR_VAL, - cpu, 0, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_LINE, ADDR_VAL, - cpu, 0, 0, (unsigned)physaddr); - } else if (size <= NBPG) { - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, ADDR_VAL, - cpu, 0, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_PAGE, ADDR_VAL, - cpu, 0, 0, (unsigned)physaddr); - } else { - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, 0, - cpu, 0, 0, 0); - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_SEGMENT, 0, - cpu, 0, 0, 0); - } -#else - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, 0, - cpu, 0, 0, 0); -#endif /* !BROKEN_MMU_MASK */ - - m8820x_cmmu_wait(cpu); - - CMMU_UNLOCK; - splx(s); -} - -/* - * flush Instruction caches - */ -void -m8820x_cmmu_flush_inst_cache(int cpu, paddr_t physaddr, psize_t size) -{ - int s = splhigh(); - CMMU_LOCK; - -#if !defined(BROKEN_MMU_MASK) - if (size > NBSG) { - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL, - cpu, INST_CMMU, 0, 0); - } else if (size <= MC88200_CACHE_LINE) { - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_LINE, - MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr); - } else if (size <= NBPG) { - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_PAGE, - MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr); - } else { - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL, cpu, INST_CMMU, 0, 0); - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_SEGMENT, - MODE_VAL, cpu, INST_CMMU, 0, 0); - } -#else - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL, - cpu, INST_CMMU, 0, 0); -#endif /* !BROKEN_MMU_MASK */ - - m8820x_cmmu_wait(cpu); - - CMMU_UNLOCK; - splx(s); -} - -void -m8820x_cmmu_flush_data_cache(int cpu, paddr_t physaddr, psize_t size) -{ - int s = splhigh(); - CMMU_LOCK; - -#if !defined(BROKEN_MMU_MASK) - if (size > NBSG) { - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL, - cpu, DATA_CMMU, 0, 0); - } else if (size <= MC88200_CACHE_LINE) { - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_LINE, - MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr); - } else if (size <= NBPG) { - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_PAGE, - MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr); - } else { - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL, cpu, DATA_CMMU, 0, 0); - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_SEGMENT, - MODE_VAL, cpu, DATA_CMMU, 0, 0); - } -#else - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL, - cpu, DATA_CMMU, 0, 0); -#endif /* !BROKEN_MMU_MASK */ - - m8820x_cmmu_wait(cpu); - - CMMU_UNLOCK; - splx(s); -} - -/* - * sync dcache (and icache too) - */ -void -m8820x_cmmu_sync_cache(paddr_t physaddr, psize_t size) -{ - int s = splhigh(); - int cpu = cpu_number(); - - CMMU_LOCK; - -#if !defined(BROKEN_MMU_MASK) - if (size > NBSG) { - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_ALL, MODE_VAL, - cpu, DATA_CMMU, 0, 0); - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_ALL, MODE_VAL, - cpu, INST_CMMU, 0, 0); - } else if (size <= MC88200_CACHE_LINE) { - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CB_LINE, - MODE_VAL, cpu, INST_CMMU, 0, 0); - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CB_LINE, - MODE_VAL, cpu, DATA_CMMU, 0, 0); - } else if (size <= NBPG) { - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CB_PAGE, - MODE_VAL, cpu, INST_CMMU, 0, 0); - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CB_PAGE, - MODE_VAL, cpu, DATA_CMMU, 0, 0); - } else { - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CB_SEGMENT, - MODE_VAL, cpu, INST_CMMU, 0, 0); - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CB_SEGMENT, - MODE_VAL, cpu, DATA_CMMU, 0, 0); - } -#else - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_ALL, MODE_VAL, - cpu, DATA_CMMU, 0, 0); - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CB_ALL, MODE_VAL, - cpu, INST_CMMU, 0, 0); -#endif /* !BROKEN_MMU_MASK */ - - m8820x_cmmu_wait(cpu); - - CMMU_UNLOCK; - splx(s); -} - -void -m8820x_cmmu_sync_inval_cache(paddr_t physaddr, psize_t size) -{ - int s = splhigh(); - int cpu = cpu_number(); - - CMMU_LOCK; - -#if !defined(BROKEN_MMU_MASK) - if (size > NBSG) { - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL, - cpu, DATA_CMMU, 0, 0); - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL, - cpu, INST_CMMU, 0, 0); - } else if (size <= MC88200_CACHE_LINE) { - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CBI_LINE, - MODE_VAL, cpu, INST_CMMU, 0, 0); - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CBI_LINE, - MODE_VAL, cpu, DATA_CMMU, 0, 0); - } else if (size <= NBPG) { - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CBI_PAGE, - MODE_VAL, cpu, INST_CMMU, 0, 0); - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CBI_PAGE, - MODE_VAL, cpu, DATA_CMMU, 0, 0); - } else { - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CBI_SEGMENT, - MODE_VAL, cpu, INST_CMMU, 0, 0); - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_CBI_SEGMENT, - MODE_VAL, cpu, DATA_CMMU, 0, 0); - } -#else - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL, - cpu, DATA_CMMU, 0, 0); - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_CBI_ALL, MODE_VAL, - cpu, INST_CMMU, 0, 0); -#endif /* !BROKEN_MMU_MASK */ - - m8820x_cmmu_wait(cpu); - - CMMU_UNLOCK; - splx(s); -} - -void -m8820x_cmmu_inval_cache(paddr_t physaddr, psize_t size) -{ - int s = splhigh(); - int cpu = cpu_number(); - - CMMU_LOCK; - -#if !defined(BROKEN_MMU_MASK) - if (size > NBSG) { - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_ALL, MODE_VAL, - cpu, DATA_CMMU, 0, 0); - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_ALL, MODE_VAL, - cpu, INST_CMMU, 0, 0); - } else if (size <= MC88200_CACHE_LINE) { - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_INV_LINE, - MODE_VAL, cpu, INST_CMMU, 0, 0); - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_INV_LINE, - MODE_VAL, cpu, DATA_CMMU, 0, 0); - } else if (size <= NBPG) { - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_INV_PAGE, - MODE_VAL, cpu, INST_CMMU, 0, 0); - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_INV_PAGE, - MODE_VAL, cpu, DATA_CMMU, 0, 0); - } else { - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, INST_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_INV_SEGMENT, - MODE_VAL, cpu, INST_CMMU, 0, 0); - m8820x_cmmu_set(CMMU_SAR, (unsigned)physaddr, - MODE_VAL | ADDR_VAL, cpu, DATA_CMMU, 0, (unsigned)physaddr); - m8820x_cmmu_set(CMMU_SAR, CMMU_FLUSH_CACHE_INV_SEGMENT, - MODE_VAL, cpu, DATA_CMMU, 0, 0); - } -#else - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_ALL, MODE_VAL, - cpu, DATA_CMMU, 0, 0); - m8820x_cmmu_set(CMMU_SCR, CMMU_FLUSH_CACHE_INV_ALL, MODE_VAL, - cpu, INST_CMMU, 0, 0); -#endif /* !BROKEN_MMU_MASK */ - - m8820x_cmmu_wait(cpu); - - CMMU_UNLOCK; - splx(s); -} - -void -m8820x_dma_cachectl(vaddr_t va, vsize_t size, int op) -{ - paddr_t pa; -#if !defined(BROKEN_MMU_MASK) - psize_t count; - - while (size != 0) { - count = NBPG - (va & PGOFSET); - - if (size < count) - count = size; - - if (pmap_extract(pmap_kernel(), va, &pa) != FALSE) { - switch (op) { - case DMA_CACHE_SYNC: - m8820x_cmmu_sync_cache(pa, count); - break; - case DMA_CACHE_SYNC_INVAL: - m8820x_cmmu_sync_inval_cache(pa, count); - break; - default: - m8820x_cmmu_inval_cache(pa, count); - break; - } - } - - va += count; - size -= count; - } -#else - /* XXX This assumes the space is also physically contiguous */ - if (pmap_extract(pmap_kernel(), va, &pa) != FALSE) { - switch (op) { - case DMA_CACHE_SYNC: - m8820x_cmmu_sync_cache(pa, size); - break; - case DMA_CACHE_SYNC_INVAL: - m8820x_cmmu_sync_inval_cache(pa, size); - break; - default: - m8820x_cmmu_inval_cache(pa, size); - break; - } - } -#endif /* !BROKEN_MMU_MASK */ -} - -void -m8820x_dma_cachectl_pa(paddr_t pa, psize_t size, int op) -{ -#if !defined(BROKEN_MMU_MASK) - psize_t count; - - while (size != 0) { - count = NBPG - (va & PGOFSET); - - if (size < count) - count = size; - - switch (op) { - case DMA_CACHE_SYNC: - m8820x_cmmu_sync_cache(pa, count); - break; - case DMA_CACHE_SYNC_INVAL: - m8820x_cmmu_sync_inval_cache(pa, count); - break; - default: - m8820x_cmmu_inval_cache(pa, count); - break; - } - - pa += count; - size -= count; - } -#else - switch (op) { - case DMA_CACHE_SYNC: - m8820x_cmmu_sync_cache(pa, size); - break; - case DMA_CACHE_SYNC_INVAL: - m8820x_cmmu_sync_inval_cache(pa, size); - break; - default: - m8820x_cmmu_inval_cache(pa, size); - break; - } -#endif /* !BROKEN_MMU_MASK */ -} - -#ifdef DDB -union ssr { - unsigned bits; - struct { - unsigned :16, - ce:1, - be:1, - :4, - wt:1, - sp:1, - g:1, - ci:1, - :1, - m:1, - u:1, - wp:1, - bh:1, - v:1; - } field; -}; - -union cssp { - unsigned bits; - struct { - unsigned : 2, - l: 6, - d3: 1, - d2: 1, - d1: 1, - d0: 1, - vv3: 2, - vv2: 2, - vv1: 2, - vv0: 2, - :12; - } field; -}; - -union batcu { - unsigned bits; - struct { /* block address translation register */ - unsigned int - lba:13, /* logical block address */ - pba:13, /* physical block address */ - s:1, /* supervisor */ - wt:4, /* write through */ - g:1, /* global */ - ci:1, /* cache inhibit */ - wp:1, /* write protect */ - v:1; /* valid */ - } field; -}; - - #define VV_EX_UNMOD 0 - #define VV_EX_MOD 1 - #define VV_SHARED_UNMOD 2 - #define VV_INVALID 3 - - #define D(UNION, LINE) \ - ((LINE) == 3 ? (UNION).field.d3 : \ - ((LINE) == 2 ? (UNION).field.d2 : \ - ((LINE) == 1 ? (UNION).field.d1 : \ - ((LINE) == 0 ? (UNION).field.d0 : ~0)))) - #define VV(UNION, LINE) \ - ((LINE) == 3 ? (UNION).field.vv3 : \ - ((LINE) == 2 ? (UNION).field.vv2 : \ - ((LINE) == 1 ? (UNION).field.vv1 : \ - ((LINE) == 0 ? (UNION).field.vv0 : ~0)))) - - #undef VEQR_ADDR - #define VEQR_ADDR 0 -/* - * Show (for debugging) how the given CMMU translates the given ADDRESS. - * If cmmu == -1, the data cmmu for the current cpu is used. - */ -void -m8820x_cmmu_show_translation(address, supervisor_flag, verbose_flag, cmmu_num) - unsigned address, supervisor_flag, verbose_flag; - int cmmu_num; -{ - /* - * A virtual address is split into three fields. Two are used as - * indicies into tables (segment and page), and one is an offset into - * a page of memory. - */ - union { - unsigned bits; - struct { - unsigned segment_table_index:SDT_BITS, - page_table_index:PDT_BITS, - page_offset:PG_BITS; - } field; - } virtual_address; - u_int32_t value; - - if (verbose_flag) - db_printf("-------------------------------------------\n"); - - - - /****** ACCESS PROPER CMMU or THREAD ***********/ - if (cmmu_num == -1) { - int cpu = cpu_number(); - if (cpu_cmmu[cpu].pair[DATA_CMMU] == 0) { - db_printf("ack! can't figure my own data cmmu number.\n"); - return; - } - cmmu_num = cpu_cmmu[cpu].pair[DATA_CMMU] - m8820x_cmmu; - if (verbose_flag) - db_printf("The data cmmu for cpu#%d is cmmu#%d.\n", - 0, cmmu_num); - } else if (cmmu_num < 0 || cmmu_num >= MAX_CMMUS) { - db_printf("invalid cpu number [%d]... must be in range [0..%d]\n", - cmmu_num, MAX_CMMUS - 1); - - return; - } - - if (m8820x_cmmu[cmmu_num].cmmu_alive == CMMU_DEAD) { - db_printf("warning: cmmu %d is not alive.\n", cmmu_num); -#if 0 - return; -#endif - } - - if (!verbose_flag) { - if (!(m8820x_cmmu[cmmu_num].cmmu_regs[CMMU_SCTR] & CMMU_SCTR_SE)) - db_printf("WARNING: snooping not enabled for CMMU#%d.\n", - cmmu_num); - } else { - int i; - for (i = 0; i < MAX_CMMUS; i++) - if ((i == cmmu_num || m8820x_cmmu[i].cmmu_alive != CMMU_DEAD) && - (verbose_flag > 1 || !(m8820x_cmmu[i].cmmu_regs[CMMU_SCTR] & CMMU_SCTR_SE))) { - db_printf("CMMU#%d (cpu %d %s) snooping %s\n", i, - m8820x_cmmu[i].cmmu_cpu, m8820x_cmmu[i].cmmu_type ? "data" : "inst", - (m8820x_cmmu[i].cmmu_regs[CMMU_SCTR] & CMMU_SCTR_SE) ? "on":"OFF"); - } - } - - if (supervisor_flag) - value = m8820x_cmmu[cmmu_num].cmmu_regs[CMMU_SAPR]; - else - value = m8820x_cmmu[cmmu_num].cmmu_regs[CMMU_UAPR]; - - /******* SEE WHAT A PROBE SAYS (if not a thread) ***********/ - { - union ssr ssr; - unsigned *volatile cmmu_regs = m8820x_cmmu[cmmu_num].cmmu_regs; - cmmu_regs[CMMU_SAR] = address; - cmmu_regs[CMMU_SCR] = supervisor_flag ? CMMU_PROBE_SUPER : CMMU_PROBE_USER; - ssr.bits = cmmu_regs[CMMU_SSR]; - if (verbose_flag > 1) - db_printf("probe of 0x%08x returns ssr=0x%08x\n", - address, ssr.bits); - if (ssr.field.v) - db_printf("PROBE of 0x%08x returns phys=0x%x", - address, cmmu_regs[CMMU_SAR]); - else - db_printf("PROBE fault at 0x%x", cmmu_regs[CMMU_PFAR]); - if (ssr.field.ce) db_printf(", copyback err"); - if (ssr.field.be) db_printf(", bus err"); - if (ssr.field.wt) db_printf(", writethrough"); - if (ssr.field.sp) db_printf(", sup prot"); - if (ssr.field.g) db_printf(", global"); - if (ssr.field.ci) db_printf(", cache inhibit"); - if (ssr.field.m) db_printf(", modified"); - if (ssr.field.u) db_printf(", used"); - if (ssr.field.wp) db_printf(", write prot"); - if (ssr.field.bh) db_printf(", BATC"); - db_printf(".\n"); - } - - /******* INTERPRET AREA DESCRIPTOR *********/ - { - if (verbose_flag > 1) { - db_printf("CMMU#%d", cmmu_num); - db_printf(" %cAPR is 0x%08x\n", - supervisor_flag ? 'S' : 'U', value); - } - db_printf("CMMU#%d", cmmu_num); - db_printf(" %cAPR: SegTbl: 0x%x000p", - supervisor_flag ? 'S' : 'U', PG_PFNUM(value)); - if (value & CACHE_WT) - db_printf(", WTHRU"); - if (value & CACHE_GLOBAL) - db_printf(", GLOBAL"); - if (value & CACHE_INH) - db_printf(", INHIBIT"); - if (value & APR_V) - db_printf(", VALID"); - db_printf("\n"); - - /* if not valid, done now */ - if ((value & APR_V) == 0) { - db_printf("<would report an error, valid bit not set>\n"); - - return; - } - - value &= PG_FRAME; /* now point to seg page */ - } - - /* translate value from physical to virtual */ - if (verbose_flag) - db_printf("[%x physical is %x virtual]\n", value, value + VEQR_ADDR); - value += VEQR_ADDR; - - virtual_address.bits = address; - - /****** ACCESS SEGMENT TABLE AND INTERPRET SEGMENT DESCRIPTOR *******/ - { - sdt_entry_t sdt; - if (verbose_flag) - db_printf("will follow to entry %d of page at 0x%x...\n", - virtual_address.field.segment_table_index, value); - value |= virtual_address.field.segment_table_index * - sizeof(sdt_entry_t); - - if (badwordaddr((vaddr_t)value)) { - db_printf("ERROR: unable to access page at 0x%08x.\n", value); - return; - } - - sdt = *(sdt_entry_t *)value; - if (verbose_flag > 1) - db_printf("SEG DESC @0x%x is 0x%08x\n", value, sdt); - db_printf("SEG DESC @0x%x: PgTbl: 0x%x000", - value, PG_PFNUM(sdt)); - if (sdt & CACHE_WT) db_printf(", WTHRU"); - else db_printf(", !wthru"); - if (sdt & SG_SO) db_printf(", S-PROT"); - else db_printf(", UserOk"); - if (sdt & CACHE_GLOBAL) db_printf(", GLOBAL"); - else db_printf(", !global"); - if (sdt & CACHE_INH) db_printf(", $INHIBIT"); - else db_printf(", $ok"); - if (sdt & SG_PROT) db_printf(", W-PROT"); - else db_printf(", WriteOk"); - if (sdt & SG_V) db_printf(", VALID"); - else db_printf(", !valid"); - db_printf(".\n"); - - /* if not valid, done now */ - if (!(sdt & SG_V)) { - db_printf("<would report an error, STD entry not valid>\n"); - return; - } - - value = ptoa(PG_PFNUM(sdt)); - } - - /* translate value from physical to virtual */ - if (verbose_flag) - db_printf("[%x physical is %x virtual]\n", value, value + VEQR_ADDR); - value += VEQR_ADDR; - - /******* PAGE TABLE *********/ - { - pt_entry_t pte; - if (verbose_flag) - db_printf("will follow to entry %d of page at 0x%x...\n", - virtual_address.field.page_table_index, value); - value |= virtual_address.field.page_table_index * - sizeof(pt_entry_t); - - if (badwordaddr((vaddr_t)value)) { - db_printf("error: unable to access page at 0x%08x.\n", value); - - return; - } - - pte = *(pt_entry_t *)value; - if (verbose_flag > 1) - db_printf("PAGE DESC @0x%x is 0x%08x.\n", value, pte); - db_printf("PAGE DESC @0x%x: page @%x000", - value, PG_PFNUM(pte)); - if (pte & PG_W) db_printf(", WIRE"); - else db_printf(", !wire"); - if (pte & CACHE_WT) db_printf(", WTHRU"); - else db_printf(", !wthru"); - if (pte & PG_SO) db_printf(", S-PROT"); - else db_printf(", UserOk"); - if (pte & CACHE_GLOBAL) db_printf(", GLOBAL"); - else db_printf(", !global"); - if (pte & CACHE_INH) db_printf(", $INHIBIT"); - else db_printf(", $ok"); - if (pte & PG_M) db_printf(", MOD"); - else db_printf(", !mod"); - if (pte & PG_U) db_printf(", USED"); - else db_printf(", !used"); - if (pte & PG_PROT) db_printf(", W-PROT"); - else db_printf(", WriteOk"); - if (pte & PG_V) db_printf(", VALID"); - else db_printf(", !valid"); - db_printf(".\n"); - - /* if not valid, done now */ - if (!(pte & PG_V)) { - db_printf("<would report an error, PTE entry not valid>\n"); - return; - } - - value = ptoa(PG_PFNUM(pte)); - if (verbose_flag) - db_printf("will follow to byte %d of page at 0x%x...\n", - virtual_address.field.page_offset, value); - value |= virtual_address.field.page_offset; - - if (badwordaddr((vaddr_t)value)) { - db_printf("error: unable to access page at 0x%08x.\n", value); - return; - } - } - - /* translate value from physical to virtual */ - if (verbose_flag) - db_printf("[%x physical is %x virtual]\n", value, value + VEQR_ADDR); - value += VEQR_ADDR; - - db_printf("WORD at 0x%x is 0x%08x.\n", value, *(unsigned *)value); - -} -#endif /* DDB */ |