|
|
1.1 ! root 1: /* $Id: stp103x.c,v 1.5 2010/06/05 18:57:04 fredette Exp $ */ ! 2: ! 3: /* ic/sparc/stp103x.c - implementation of UltraSPARC I (STP1030) and II (STP1031) emulation: */ ! 4: ! 5: /* ! 6: * Copyright (c) 2008 Matt Fredette ! 7: * All rights reserved. ! 8: * ! 9: * Redistribution and use in source and binary forms, with or without ! 10: * modification, are permitted provided that the following conditions ! 11: * are met: ! 12: * 1. Redistributions of source code must retain the above copyright ! 13: * notice, this list of conditions and the following disclaimer. ! 14: * 2. Redistributions in binary form must reproduce the above copyright ! 15: * notice, this list of conditions and the following disclaimer in the ! 16: * documentation and/or other materials provided with the distribution. ! 17: * 3. All advertising materials mentioning features or use of this software ! 18: * must display the following acknowledgement: ! 19: * This product includes software developed by Matt Fredette. ! 20: * 4. The name of the author may not be used to endorse or promote products ! 21: * derived from this software without specific prior written permission. ! 22: * ! 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ! 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ! 25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ! 26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, ! 27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ! 28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ! 29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ! 31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ! 32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ! 33: * POSSIBILITY OF SUCH DAMAGE. ! 34: */ ! 35: ! 36: #include <tme/common.h> ! 37: _TME_RCSID("$Id: stp103x.c,v 1.5 2010/06/05 18:57:04 fredette Exp $"); ! 38: ! 39: /* includes: */ ! 40: #include "sparc-impl.h" ! 41: ! 42: /* macros: */ ! 43: ! 44: /* the PSTATE extensions: */ ! 45: #define TME_STP103X_PSTATE_IG TME_BIT(11) ! 46: #define TME_STP103X_PSTATE_MG TME_BIT(10) ! 47: ! 48: /* the load/store unit control register: */ ! 49: #define TME_STP103X_LSU_IC TME_BIT(0) ! 50: #define TME_STP103X_LSU_DC TME_BIT(1) ! 51: #define TME_STP103X_LSU_IM TME_BIT(2) ! 52: #define TME_STP103X_LSU_DM TME_BIT(3) ! 53: #define TME_STP103X_LSU_FM (TME_BIT(20) - TME_BIT(4)) ! 54: #define TME_STP103X_LSU_VW TME_BIT(21) ! 55: #define TME_STP103X_LSU_VR TME_BIT(22) ! 56: #define TME_STP103X_LSU_PW TME_BIT(23) ! 57: #define TME_STP103X_LSU_PR TME_BIT(24) ! 58: ! 59: /* the E-Cache (E-state) error enable register: */ ! 60: #define TME_STP103X_ESTATE_ERROR_ENABLE_CEEN TME_BIT(0) ! 61: #define TME_STP103X_ESTATE_ERROR_ENABLE_NCEEN TME_BIT(1) ! 62: #define TME_STP103X_ESTATE_ERROR_ENABLE_ISAPEN TME_BIT(2) ! 63: ! 64: /* the start of the virtual address hole: */ ! 65: #define TME_STP103X_VA_HOLE_START (((tme_uint64_t) 1) << 43) ! 66: ! 67: /* the size of the physical address space: */ ! 68: #define TME_STP103X_PA_SIZE (((tme_uint64_t) 1) << 41) ! 69: ! 70: /* the maximum context number: */ ! 71: #define TME_STP103X_CONTEXT_MAX (8191) ! 72: ! 73: /* the different page sizes: */ ! 74: #define TME_STP103X_PAGE_SIZE_8KB (8 * 1024) ! 75: #define TME_STP103X_PAGE_SIZE_64KB (64 * 1024) ! 76: #define TME_STP103X_PAGE_SIZE_512KB (512 * 1024) ! 77: #define TME_STP103X_PAGE_SIZE_4MB (4 * 1024 * 1024) ! 78: ! 79: /* because we often deal with the tme_uint64_t TLB/TTE entry tag and ! 80: data as tme_uint32_t halves for performance, we need to easily ! 81: generate the right bitfield masks for both types. this macro ! 82: converts the constant x to the type of e, and then shifts it by ! 83: (shift mod (8 * sizeof(e))). e is only typed, never evaluated: */ ! 84: #define _TME_STP103X_TLB_X(e, x, shift) ((1 ? (x) : (e)) << ((shift) % (8 * sizeof(e)))) ! 85: ! 86: /* TLB/TTE data: */ ! 87: #define TME_STP103X_TLB_DATA_V(e) _TME_STP103X_TLB_X(e, 1, 63) ! 88: #define TME_STP103X_TLB_DATA_SIZE_MASK(e) _TME_STP103X_TLB_X(e, 0x3, 61) ! 89: #define TME_STP103X_TLB_DATA_SIZE_8KB(e) _TME_STP103X_TLB_X(e, 0x0, 61) ! 90: #define TME_STP103X_TLB_DATA_SIZE_64KB(e) _TME_STP103X_TLB_X(e, 0x1, 61) ! 91: #define TME_STP103X_TLB_DATA_SIZE_512KB(e) _TME_STP103X_TLB_X(e, 0x2, 61) ! 92: #define TME_STP103X_TLB_DATA_SIZE_4MB(e) _TME_STP103X_TLB_X(e, 0x3, 61) ! 93: #define TME_STP103X_TLB_DATA_NFO(e) _TME_STP103X_TLB_X(e, 1, 60) ! 94: #define TME_STP103X_TLB_DATA_IE(e) _TME_STP103X_TLB_X(e, 1, 59) ! 95: #define TME_STP103X_TLB_DATA_SOFT2(e) _TME_STP103X_TLB_X(e, 0x1ff, 50) ! 96: #define TME_STP103X_TLB_DATA_SIZE_CAM_MASK(e) _TME_STP103X_TLB_X(e, 0x7, 45) ! 97: #define TME_STP103X_TLB_DATA_SIZE_CAM_8KB(e) _TME_STP103X_TLB_X(e, 0x0, 45) ! 98: #define TME_STP103X_TLB_DATA_SIZE_CAM_64KB(e) _TME_STP103X_TLB_X(e, 0x1, 45) ! 99: #define TME_STP103X_TLB_DATA_SIZE_CAM_512KB(e) _TME_STP103X_TLB_X(e, 0x3, 45) ! 100: #define TME_STP103X_TLB_DATA_SIZE_CAM_4MB(e) _TME_STP103X_TLB_X(e, 0x7, 45) ! 101: #define TME_STP103X_TLB_DATA_SIZE_RAM_MASK(e) _TME_STP103X_TLB_X(e, 0x7, 42) ! 102: #define TME_STP103X_TLB_DATA_SIZE_RAM_8KB(e) _TME_STP103X_TLB_X(e, 0x0, 42) ! 103: #define TME_STP103X_TLB_DATA_SIZE_RAM_64KB(e) _TME_STP103X_TLB_X(e, 0x1, 42) ! 104: #define TME_STP103X_TLB_DATA_SIZE_RAM_512KB(e) _TME_STP103X_TLB_X(e, 0x3, 42) ! 105: #define TME_STP103X_TLB_DATA_SIZE_RAM_4MB(e) _TME_STP103X_TLB_X(e, 0x7, 42) ! 106: #define TME_STP103X_TLB_DATA_DIAG_USED(e) _TME_STP103X_TLB_X(e, 1, 41) ! 107: #define TME_STP103X_TLB_DATA_PA ((((tme_uint64_t) 1) << 41) - (1 << 13)) ! 108: #define TME_STP103X_TLB_DATA_SOFT(e) _TME_STP103X_TLB_X(e, 0x3f, 7) ! 109: #define TME_STP103X_TLB_DATA_L(e) _TME_STP103X_TLB_X(e, 1, 6) ! 110: #define TME_STP103X_TLB_DATA_CP(e) _TME_STP103X_TLB_X(e, 1, 5) ! 111: #define TME_STP103X_TLB_DATA_CV(e) _TME_STP103X_TLB_X(e, 1, 4) ! 112: #define TME_STP103X_TLB_DATA_E(e) _TME_STP103X_TLB_X(e, 1, 3) ! 113: #define TME_STP103X_TLB_DATA_P(e) _TME_STP103X_TLB_X(e, 1, 2) ! 114: #define TME_STP103X_TLB_DATA_W(e) _TME_STP103X_TLB_X(e, 1, 1) ! 115: #define TME_STP103X_TLB_DATA_G(e) _TME_STP103X_TLB_X(e, 1, 0) ! 116: ! 117: /* the DMMU and IMMU SFSR: */ ! 118: #define TME_STP103X_SFSR_ASI (0xff << 16) ! 119: #define TME_STP103X_SFSR_FT_PRIVILEGE (0x01 << 7) ! 120: #define TME_STP103X_SFSR_FT_SIDE_EFFECTS (0x02 << 7) ! 121: #define TME_STP103X_SFSR_FT_UNCACHEABLE (0x04 << 7) ! 122: #define TME_STP103X_SFSR_FT_ILLEGAL (0x08 << 7) ! 123: #define TME_STP103X_SFSR_FT_NO_FAULT_FAULT (0x10 << 7) ! 124: #define TME_STP103X_SFSR_FT_VA_RANGE (0x20 << 7) ! 125: #define TME_STP103X_SFSR_FT_VA_RANGE_NNPC (0x40 << 7) ! 126: #define TME_STP103X_SFSR_E TME_BIT(6) ! 127: #define TME_STP103X_SFSR_CT_PRIMARY (0x0 << 4) ! 128: #define TME_STP103X_SFSR_CT_SECONDARY (0x1 << 4) ! 129: #define TME_STP103X_SFSR_CT_NUCLEUS (0x2 << 4) ! 130: #define TME_STP103X_SFSR_CT_RESERVED (0x3 << 4) ! 131: #define TME_STP103X_SFSR_PR TME_BIT(3) ! 132: #define TME_STP103X_SFSR_W TME_BIT(2) ! 133: #define TME_STP103X_SFSR_OW TME_BIT(1) ! 134: #define TME_STP103X_SFSR_FV TME_BIT(0) ! 135: ! 136: /* the AFSR: */ ! 137: #define TME_STP103X_AFSR_ME (((tme_uint64_t) 1) << 32) ! 138: #define TME_STP103X_AFSR_PRIV TME_BIT(31) ! 139: #define TME_STP103X_AFSR_TO TME_BIT(27) ! 140: ! 141: /* a TSB register: */ ! 142: #define TME_STP103X_TSB_SIZE (0x7) ! 143: #define TME_STP103X_TSB_SPLIT TME_BIT(12) ! 144: ! 145: /* specific traps: */ ! 146: #define TME_STP103X_TRAP_MG _TME_SPARC_TRAP_IMPDEP(0) ! 147: #define TME_STP103X_TRAP_IG _TME_SPARC_TRAP_IMPDEP(1) ! 148: #define TME_STP103X_TRAP_interrupt_vector \ ! 149: (TME_STP103X_TRAP_IG | _TME_SPARC_TRAP(16, 0x060)) ! 150: #define TME_STP103X_TRAP_fast_instruction_access_MMU_miss \ ! 151: (TME_STP103X_TRAP_MG | _TME_SPARC_TRAP(2, 0x064)) ! 152: #define TME_STP103X_TRAP_fast_data_access_MMU_miss \ ! 153: (TME_STP103X_TRAP_MG | _TME_SPARC_TRAP(12, 0x068)) ! 154: #define TME_STP103X_TRAP_fast_data_access_protection \ ! 155: (TME_STP103X_TRAP_MG | _TME_SPARC_TRAP(12, 0x06c)) ! 156: ! 157: /* specific ASIs and flags: */ ! 158: #define TME_STP103X_ASI_LSU_CONTROL_REG (0x45) ! 159: #define TME_STP103X_ASI_DCACHE_DATA (0x46) ! 160: #define TME_STP103X_ASI_DCACHE_TAG (0x47) ! 161: #define TME_STP103X_ASI_INTR_DISPATCH_STATUS (0x48) ! 162: #define TME_STP103X_ASI_INTR_RECEIVE (0x49) ! 163: #define TME_STP103X_ASI_UPA_CONFIG_REG (0x4a) ! 164: #define TME_STP103X_ASI_ESTATE_ERROR_EN_REG (0x4b) ! 165: #define TME_STP103X_ASI_AFSR (0x4c) ! 166: #define TME_STP103X_ASI_AFAR (0x4d) ! 167: #define TME_STP103X_ASI_ECACHE_TAG_DATA (0x4e) ! 168: #define TME_STP103X_ASI_IMMU (0x50) ! 169: #define TME_STP103X_ASI_DMMU (0x58) ! 170: #define TME_STP103X_ASI_FLAG_TSB_8KB_PTR (0x1) ! 171: #define TME_STP103X_ASI_FLAG_TSB_64KB_PTR (0x2) ! 172: #define TME_STP103X_ASI_BLK_COMMIT (0xe0) ! 173: ! 174: /* the size of the IMMU and DMMU TLBs: */ ! 175: #define TME_STP103X_TLB_SIZE (64) ! 176: ! 177: /* the size of the E-Cache: */ ! 178: #define TME_STP103X_ECACHE_SIZE (512 * 1024) ! 179: ! 180: /* the block size of the I-Cache: */ ! 181: #define TME_STP103X_ICACHE_BLOCK_SIZE (32) ! 182: ! 183: /* the TICK_compare register: */ ! 184: #define TME_STP103X_TCR_INT_DIS (((tme_uint64_t) 1) << 63) ! 185: #define TME_STP103X_TCR_TICK_CMPR (TME_STP103X_TCR_INT_DIS - 1) ! 186: ! 187: /* the SIR: */ ! 188: #define TME_STP103X_SIR_SOFTINT(x) (1 << (x)) ! 189: #define TME_STP103X_SIR_TICK_INT (1 << 0) ! 190: ! 191: /* ASI_INTR_RECEIVE: */ ! 192: #define TME_STP103X_INTR_RECEIVE_BUSY (1 << 5) ! 193: ! 194: /* the block load and store sizes: */ ! 195: #define TME_STP103X_BLOCK_SIZE (64) ! 196: #define TME_STP103X_BLOCK_FPREGS_DOUBLE (TME_STP103X_BLOCK_SIZE / sizeof(tme_uint64_t)) ! 197: ! 198: /* other constants: */ ! 199: #define TME_STP103X_MAXTL (5) ! 200: ! 201: /* the UPA configuration register: */ ! 202: /* NB: this is a partial list: */ ! 203: #define TME_STP1030_UPA_CONFIG_PCON ((2 << 29) - (1 << 22)) ! 204: #define TME_STP1031_UPA_CONFIG_PCON ((((tme_uint64_t) 2) << 32) - (1 << 22)) ! 205: #define TME_STP1031_UPA_CONFIG_ELIM ((((tme_uint64_t) 2) << 35) - (((tme_uint64_t) 1) << 33)) ! 206: ! 207: /* the UPA queue depths and capabilities: */ ! 208: #define TME_STP103X_UPA_PINT_RDQ (1) ! 209: #define TME_STP103X_UPA_PREQ_DQ (0) ! 210: #define TME_STP103X_UPA_PREQ_RQ (1) ! 211: #define TME_STP103X_UPA_UPACAP \ ! 212: (TME_UPA_UPACAP_HANDLERSLAVE \ ! 213: | TME_UPA_UPACAP_INTERRUPTMASTER \ ! 214: | !TME_UPA_UPACAP_SLAVE_INT_L \ ! 215: | TME_UPA_UPACAP_CACHEMASTER \ ! 216: | TME_UPA_UPACAP_MASTER) ! 217: ! 218: /* fixed characteristics of the stp103x: */ ! 219: #undef TME_SPARC_VERSION ! 220: #define TME_SPARC_VERSION(ic) (9) ! 221: #undef TME_SPARC_NWINDOWS ! 222: #define TME_SPARC_NWINDOWS(ic) (8) ! 223: #undef TME_SPARC_MEMORY_FLAGS ! 224: #define TME_SPARC_MEMORY_FLAGS(ic) \ ! 225: (TME_SPARC_MEMORY_FLAG_HAS_NUCLEUS \ ! 226: + TME_SPARC_MEMORY_FLAG_HAS_INVERT_ENDIAN \ ! 227: + !TME_SPARC_MEMORY_FLAG_HAS_LDDF_STDF_32) ! 228: ! 229: /* this recovers the stp103x state from the generic sparc state: */ ! 230: #define TME_STP103X(ic) ((struct tme_stp103x *) (TRUE ? (ic) : (struct tme_sparc *) 0)) ! 231: ! 232: /* this evaluates to nonzero if an ASI mask from an ASI_DMMU* or ! 233: ASI_IMMU* ASI is from an ASI_DMMU* ASI: */ ! 234: #if (TME_STP103X_ASI_DMMU <= TME_STP103X_ASI_IMMU) || ((TME_STP103X_ASI_DMMU ^ TME_STP103X_ASI_IMMU) & ((TME_STP103X_ASI_DMMU ^ TME_STP103X_ASI_IMMU) - 1)) != 0 ! 235: #error "TME_STP103X_ASI_DMMU or TME_STP103X_ASI_IMMU changed" ! 236: #endif ! 237: #define TME_STP103X_ASI_MMU_MASK_IS_DMMU(asi_mask) \ ! 238: ((asi_mask) \ ! 239: & TME_SPARC_ASI_MASK_RAW(TME_STP103X_ASI_DMMU \ ! 240: ^ TME_STP103X_ASI_IMMU)) ! 241: ! 242: /* specific load/store information: */ ! 243: #define TME_STP103X_LSINFO_ASSERT_NO_FAULTS _TME_SPARC_LSINFO_X(0) ! 244: ! 245: /* specific load/store faults: */ ! 246: #define TME_STP103X_LS_FAULT_MMU_MISS _TME_SPARC64_LS_FAULT_X(0) ! 247: #define TME_STP103X_LS_FAULT_PRIVILEGE _TME_SPARC64_LS_FAULT_X(1) ! 248: #define TME_STP103X_LS_FAULT_PROTECTION _TME_SPARC64_LS_FAULT_X(2) ! 249: #define TME_STP103X_LS_FAULT_ILLEGAL _TME_SPARC64_LS_FAULT_X(3) ! 250: ! 251: /* update flags: */ ! 252: #define TME_STP103X_UPDATE_NONE (0) ! 253: #define TME_STP103X_UPDATE_DMMU TME_BIT(0) ! 254: #define TME_STP103X_UPDATE_IMMU (0) ! 255: #define TME_STP103X_UPDATE_MMU_TAG_ACCESS TME_BIT(1) ! 256: #define TME_STP103X_UPDATE_MMU_SFSR TME_BIT(2) ! 257: #define TME_STP103X_UPDATE_DMMU_SFAR TME_BIT(3) ! 258: ! 259: /* the first IMMU and DMMU TLB entry parts: */ ! 260: #define TME_STP103X_TLB_PART_0_DMMU (TME_STP103X_TLB_SIZE * 2 * 0) ! 261: #define TME_STP103X_TLB_PART_0_IMMU (TME_STP103X_TLB_SIZE * 2 * 1) ! 262: ! 263: /* this returns nonzero if this is an stp1030: */ ! 264: #define TME_STP103X_IS_1030(ic) (TME_STP103X(ic)->tme_stp103x_is_1030) ! 265: ! 266: /* types: */ ! 267: ! 268: /* the stp103x DMMU and IMMU common state: */ ! 269: struct tme_stp103x_mmu { ! 270: ! 271: /* the DMMU or IMMU synchronous fault status register: */ ! 272: tme_uint64_t tme_stp103x_mmu_sfsr; ! 273: ! 274: /* the DMMU or IMMU tag access register: */ ! 275: tme_uint64_t tme_stp103x_mmu_tag_access; ! 276: ! 277: /* the DMMU or IMMU translation storage buffer register: */ ! 278: tme_uint64_t tme_stp103x_mmu_tsb; ! 279: }; ! 280: ! 281: /* the stp103x state: */ ! 282: struct tme_stp103x { ! 283: ! 284: /* the generic sparc state: */ ! 285: struct tme_sparc tme_stp103x_sparc; ! 286: ! 287: /* the tick comparison register: */ ! 288: tme_uint64_t tme_stp103x_tcr; ! 289: ! 290: /* the softint register: */ ! 291: tme_uint16_t tme_stp103x_sir; ! 292: tme_memory_atomic_flag_t tme_stp103x_sir_tick_int; ! 293: ! 294: /* the dispatch control register: */ ! 295: tme_uint8_t tme_stp103x_dcr; ! 296: ! 297: /* this is nonzero if this is an stp1030: */ ! 298: tme_uint8_t tme_stp103x_is_1030; ! 299: ! 300: /* the performance control register: */ ! 301: tme_uint16_t tme_stp103x_pcr; ! 302: ! 303: /* the performance instrumentation counters: */ ! 304: union tme_value64 tme_stp103x_pic; ! 305: ! 306: /* the UPA configuration register: */ ! 307: tme_uint64_t tme_stp103x_upa_config; ! 308: ! 309: /* the load/store unit control register: */ ! 310: tme_uint64_t tme_stp103x_lsu; ! 311: ! 312: /* the estate error enable register: */ ! 313: tme_uint32_t tme_stp103x_estate_error_enable; ! 314: ! 315: /* the ecache tag data register: */ ! 316: tme_uint32_t tme_stp103x_ecache_tag_data; ! 317: ! 318: /* the ecache probe line: */ ! 319: tme_uint64_t tme_stp103x_ecache_data_probe; ! 320: ! 321: /* the transmit and receive interrupt vector data: */ ! 322: tme_uint64_t tme_stp103x_udb_intr_transmit[3]; ! 323: tme_shared tme_uint64_t tme_stp103x_udb_intr_receive[3]; ! 324: tme_shared tme_uint8_t tme_stp103x_intr_receive_mid; ! 325: tme_memory_atomic_flag_t tme_stp103x_intr_receive_busy; ! 326: ! 327: /* the tick compare condition and time: */ ! 328: tme_cond_t tme_stp103x_tick_compare_cond; ! 329: struct timeval tme_stp103x_tick_compare_time; ! 330: ! 331: /* the UDB low and high control registers: */ ! 332: tme_uint16_t tme_stp103x_udb_control[2]; ! 333: ! 334: /* the asynchronous fault address and status registers: */ ! 335: tme_uint64_t tme_stp103x_afar; ! 336: tme_uint64_t tme_stp103x_afsr; ! 337: ! 338: /* the DMMU and IMMU common state: */ ! 339: struct tme_stp103x_mmu tme_stp103x_immu; ! 340: struct tme_stp103x_mmu tme_stp103x_dmmu; ! 341: ! 342: /* the DMMU synchronous fault address register: */ ! 343: tme_uint64_t tme_stp103x_dmmu_sfar; ! 344: ! 345: /* this is nonzero if the last fast_data_access_protection trap was ! 346: for a 64KB page: */ ! 347: tme_uint8_t tme_stp103x_dmmu_direct_64KB; ! 348: ! 349: /* the DMMU and IMMU TLB: */ ! 350: /* NB: this single array is half IMMU TLB, half DMMU TLB, and each ! 351: entry has two parts: tag and data: */ ! 352: union { ! 353: tme_uint64_t _tme_stp103x_tlb_u_64s[2 * 2 * TME_STP103X_TLB_SIZE]; ! 354: #define tme_stp103x_tlb_64s(x) _tme_stp103x_tlb_u._tme_stp103x_tlb_u_64s[x] ! 355: tme_uint32_t _tme_stp103x_tlb_u_32s[2 * 4 * TME_STP103X_TLB_SIZE]; ! 356: #if (TME_ENDIAN_NATIVE != TME_ENDIAN_BIG) && (TME_ENDIAN_NATIVE != TME_ENDIAN_LITTLE) ! 357: #error "only big- and little-endian hosts are supported" ! 358: #endif ! 359: #define tme_stp103x_tlb_32s(x, y) _tme_stp103x_tlb_u._tme_stp103x_tlb_u_32s[((x) * 2) + ((y) ^ (TME_ENDIAN_NATIVE == TME_ENDIAN_BIG))] ! 360: } _tme_stp103x_tlb_u; ! 361: }; ! 362: ! 363: /* globals: */ ! 364: ! 365: /* the cacheable access bus router: */ ! 366: static const tme_bus_lane_t _tme_stp103x_bus_router_cacheable[1 << TME_BUS128_LOG2][1 << TME_BUS128_LOG2] = { ! 367: /* a byte access: */ ! 368: { ! 369: TME_BUS_LANE_ROUTE(0), ! 370: TME_BUS_LANE_UNDEF, ! 371: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, ! 372: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, ! 373: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, ! 374: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF ! 375: }, ! 376: /* a word access: */ ! 377: { ! 378: TME_BUS_LANE_ROUTE(1), ! 379: TME_BUS_LANE_ROUTE(0), ! 380: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, ! 381: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, ! 382: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, ! 383: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF ! 384: }, ! 385: /* a doubleword access: */ ! 386: { ! 387: TME_BUS_LANE_ROUTE(3), ! 388: TME_BUS_LANE_ROUTE(2), ! 389: TME_BUS_LANE_ROUTE(1), ! 390: TME_BUS_LANE_ROUTE(0), ! 391: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, ! 392: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, ! 393: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF ! 394: }, ! 395: /* an extended word access: */ ! 396: { ! 397: TME_BUS_LANE_ROUTE(7), ! 398: TME_BUS_LANE_ROUTE(6), ! 399: TME_BUS_LANE_ROUTE(5), ! 400: TME_BUS_LANE_ROUTE(4), ! 401: TME_BUS_LANE_ROUTE(3), ! 402: TME_BUS_LANE_ROUTE(2), ! 403: TME_BUS_LANE_ROUTE(1), ! 404: TME_BUS_LANE_ROUTE(0), ! 405: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, ! 406: TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF, TME_BUS_LANE_UNDEF ! 407: }, ! 408: /* a quadword access: */ ! 409: { ! 410: TME_BUS_LANE_ROUTE(15), ! 411: TME_BUS_LANE_ROUTE(14), ! 412: TME_BUS_LANE_ROUTE(13), ! 413: TME_BUS_LANE_ROUTE(12), ! 414: TME_BUS_LANE_ROUTE(11), ! 415: TME_BUS_LANE_ROUTE(10), ! 416: TME_BUS_LANE_ROUTE(9), ! 417: TME_BUS_LANE_ROUTE(8), ! 418: TME_BUS_LANE_ROUTE(7), ! 419: TME_BUS_LANE_ROUTE(6), ! 420: TME_BUS_LANE_ROUTE(5), ! 421: TME_BUS_LANE_ROUTE(4), ! 422: TME_BUS_LANE_ROUTE(3), ! 423: TME_BUS_LANE_ROUTE(2), ! 424: TME_BUS_LANE_ROUTE(1), ! 425: TME_BUS_LANE_ROUTE(0), ! 426: } ! 427: }; ! 428: ! 429: /* this maps a virtual address: */ ! 430: static void _tme_stp103x_ls_address_map _TME_P((struct tme_sparc *, struct tme_sparc_ls *)); ! 431: ! 432: /* this makes a never struct timeval: */ ! 433: static inline void ! 434: tme_misc_timeval_never(struct timeval *tv) ! 435: { ! 436: tv->tv_sec = 0; ! 437: tv->tv_sec--; ! 438: if (tv->tv_sec < 1) { ! 439: tv->tv_sec = 1; ! 440: tv->tv_sec <<= ((8 * sizeof(tv->tv_sec)) - 2); ! 441: tv->tv_sec += (tv->tv_sec - 1); ! 442: } ! 443: tv->tv_usec = 999999; ! 444: } ! 445: ! 446: /* this does an interrupt check: */ ! 447: /* NB: this may do a preinstruction trap: */ ! 448: static void ! 449: _tme_stp103x_interrupt_check(struct tme_sparc *ic, ! 450: int flags) ! 451: { ! 452: tme_uint32_t sir; ! 453: tme_uint32_t ipl; ! 454: tme_uint32_t trap; ! 455: ! 456: /* if we're replaying instructions, return now: */ ! 457: if (tme_sparc_recode_verify_replay_last_pc(ic) != 0) { ! 458: return; ! 459: } ! 460: ! 461: /* if PSTATE.IE is clear, return now: */ ! 462: if ((ic->tme_sparc64_ireg_pstate & TME_SPARC64_PSTATE_IE) == 0) { ! 463: return; ! 464: } ! 465: ! 466: /* if the incoming interrupt vector data is busy: */ ! 467: if (tme_memory_atomic_read_flag(&TME_STP103X(ic)->tme_stp103x_intr_receive_busy)) { ! 468: ! 469: /* start interrupt vector trap processing: */ ! 470: trap = TME_STP103X_TRAP_interrupt_vector; ! 471: } ! 472: ! 473: /* otherwise, the incoming interrupt vector data is not busy: */ ! 474: else { ! 475: ! 476: /* if no SOFTINT bits greater than PIL are set, return now: */ ! 477: sir = TME_STP103X(ic)->tme_stp103x_sir; ! 478: if (tme_memory_atomic_read_flag(&TME_STP103X(ic)->tme_stp103x_sir_tick_int)) { ! 479: sir |= TME_STP103X_SIR_SOFTINT(14); ! 480: } ! 481: ipl = ic->tme_sparc64_ireg_pil + 1; ! 482: sir >>= ipl; ! 483: if (sir == 0) { ! 484: return; ! 485: } ! 486: ! 487: /* get the greatest SOFTINT bit greater than PIL that is set: */ ! 488: for (; sir != 1; sir >>= 1, ipl++); ! 489: ! 490: /* start interrupt trap processing: */ ! 491: trap = TME_SPARC64_TRAP_interrupt_level(ipl); ! 492: } ! 493: ! 494: /* start trap processing: */ ! 495: if (flags & TME_SPARC_EXTERNAL_CHECK_MUTEX_LOCKED) { ! 496: tme_mutex_unlock(&ic->tme_sparc_external_mutex); ! 497: } ! 498: if (flags & TME_SPARC_EXTERNAL_CHECK_PCS_UPDATED) { ! 499: ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT_NEXT) = ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT); ! 500: ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT) = ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC); ! 501: #ifdef _TME_SPARC_RECODE_VERIFY ! 502: ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC) = TME_SPARC_RECODE_VERIFY_PC_NONE; ! 503: #endif /* _TME_SPARC_RECODE_VERIFY */ ! 504: } ! 505: tme_sparc64_trap_preinstruction(ic, trap); ! 506: } ! 507: ! 508: /* this updates the SIR: */ ! 509: /* NB: this may do a preinstruction trap: */ ! 510: static void ! 511: _tme_stp103x_update_sir(struct tme_sparc *ic, ! 512: tme_uint32_t sir_andn, ! 513: tme_uint32_t sir_or) ! 514: { ! 515: ! 516: /* if we're clearing SIR.TICK_INT: */ ! 517: if (sir_andn & TME_STP103X_SIR_TICK_INT) { ! 518: ! 519: /* do an interrupt check: */ ! 520: _tme_stp103x_interrupt_check(ic, TME_SPARC_EXTERNAL_CHECK_PCS_UPDATED); ! 521: ! 522: /* clear the tick interrupt atomic flag: */ ! 523: tme_memory_atomic_write_flag(&TME_STP103X(ic)->tme_stp103x_sir_tick_int, FALSE); ! 524: } ! 525: ! 526: /* if we're setting SIR.TICK_INT: */ ! 527: if (sir_or & TME_STP103X_SIR_TICK_INT) { ! 528: ! 529: /* set the tick interrupt atomic flag: */ ! 530: tme_memory_atomic_write_flag(&TME_STP103X(ic)->tme_stp103x_sir_tick_int, TRUE); ! 531: ! 532: /* we won't set SIR.TICK_INT in the normal SIR image: */ ! 533: sir_or ^= TME_STP103X_SIR_TICK_INT; ! 534: } ! 535: ! 536: /* update all other bits in SIR: */ ! 537: TME_STP103X(ic)->tme_stp103x_sir ! 538: = ((TME_STP103X(ic)->tme_stp103x_sir ! 539: & ~sir_andn) ! 540: | sir_or); ! 541: ! 542: /* do an interrupt check: */ ! 543: _tme_stp103x_interrupt_check(ic, TME_SPARC_EXTERNAL_CHECK_NULL); ! 544: } ! 545: ! 546: /* this updates the LSU control register: */ ! 547: static void ! 548: _tme_stp103x_update_lsu(struct tme_sparc *ic, tme_uint64_t lsu_new) ! 549: { ! 550: tme_uint64_t lsu_xor; ! 551: struct tme_sparc_tlb *tlb; ! 552: ! 553: /* get a change mask: */ ! 554: lsu_xor = lsu_new ^ TME_STP103X(ic)->tme_stp103x_lsu; ! 555: ! 556: /* if LSU.IC or LSU.DC are changing: */ ! 557: if (lsu_xor ! 558: & (TME_STP103X_LSU_IC ! 559: | TME_STP103X_LSU_DC)) { ! 560: ! 561: /* nothing to do, since we don't emulate the caches: */ ! 562: } ! 563: ! 564: /* if LSU.IM or LSU.DM are changing: */ ! 565: if (lsu_xor ! 566: & (TME_STP103X_LSU_IM ! 567: | TME_STP103X_LSU_DM)) { ! 568: ! 569: /* invalidate all of the sparc TLB entries: */ ! 570: tlb = &ic->tme_sparc_tlbs[0]; ! 571: do { ! 572: tme_token_invalidate_nosync(tlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token); ! 573: } while (++tlb <= &ic->tme_sparc_tlbs[TME_ARRAY_ELS(ic->tme_sparc_tlbs) - 1]); ! 574: } ! 575: ! 576: /* if LSU.FM is changing: */ ! 577: if (lsu_xor & TME_STP103X_LSU_FM) { ! 578: /* XXX FIXME WRITEME: */ ! 579: abort(); ! 580: } ! 581: ! 582: /* if any of LSU.VR, LSU.VW, LSU.PR, LSU.PW are changing: */ ! 583: if (lsu_xor ! 584: & (TME_STP103X_LSU_VR ! 585: | TME_STP103X_LSU_VW ! 586: | TME_STP103X_LSU_PR ! 587: | TME_STP103X_LSU_PW)) { ! 588: /* XXX FIXME WRITEME: */ ! 589: abort(); ! 590: } ! 591: ! 592: /* update the register: */ ! 593: TME_STP103X(ic)->tme_stp103x_lsu = lsu_new; ! 594: } ! 595: ! 596: /* this updates the UPA configuration register: */ ! 597: static void ! 598: _tme_stp103x_update_upa_config(struct tme_sparc *ic, tme_uint64_t upa_config) ! 599: { ! 600: ! 601: /* if this is an STP1030: */ ! 602: if (TME_STP103X_IS_1030(ic)) { ! 603: ! 604: /* only the PCON field is writable: */ ! 605: upa_config &= TME_STP1030_UPA_CONFIG_PCON; ! 606: } ! 607: ! 608: /* otherwise, this is an STP1031: */ ! 609: else { ! 610: ! 611: /* only the PCON and ELIM fields are writable: */ ! 612: upa_config ! 613: &= (TME_STP1031_UPA_CONFIG_PCON ! 614: | TME_STP1031_UPA_CONFIG_ELIM); ! 615: ! 616: /* all read-only STP1031-specific fields are hardwired to zero: */ ! 617: } ! 618: ! 619: /* add the MID: */ ! 620: upa_config += (ic->_tme_upa_bus_connection->tme_upa_bus_connection_mid << 17); ! 621: ! 622: /* add the PCAP fields: */ ! 623: upa_config ! 624: += ((TME_STP103X_UPA_PINT_RDQ << 15) ! 625: + (TME_STP103X_UPA_PREQ_DQ << 9) ! 626: + (TME_STP103X_UPA_PREQ_RQ << 5) ! 627: + (TME_STP103X_UPA_UPACAP << 0)); ! 628: ! 629: /* set the UPA configuration register: */ ! 630: TME_STP103X(ic)->tme_stp103x_upa_config = upa_config; ! 631: } ! 632: ! 633: /* this handles a PSTATE update: */ ! 634: /* NB: this may do a preinstruction trap: */ ! 635: static void ! 636: _tme_stp103x_update_pstate(struct tme_sparc *ic, ! 637: tme_uint32_t pstate, ! 638: tme_uint32_t trap) ! 639: { ! 640: tme_uint64_t lsu_new; ! 641: tme_uint32_t pstate_xor; ! 642: tme_uint64_t address_mask; ! 643: ! 644: /* if we are in RED_state: */ ! 645: if (pstate & TME_SPARC64_PSTATE_RED) { ! 646: ! 647: /* traps that enter RED_state, and traps in RED_state, always ! 648: clear the LSU_Control_Register. a write of one to PSTATE.RED ! 649: only clears LSU.IM: */ ! 650: lsu_new ! 651: = (trap != TME_SPARC_TRAP_none ! 652: ? 0 ! 653: : (TME_STP103X(ic)->tme_stp103x_lsu ! 654: & ~ (tme_uint64_t) TME_STP103X_LSU_IM)); ! 655: _tme_stp103x_update_lsu(ic, lsu_new); ! 656: ! 657: /* if this is a power-on reset: */ ! 658: if (trap == TME_SPARC64_TRAP_power_on_reset) { ! 659: ! 660: /* a POR clears the E-Cache (E-State) error enable register: */ ! 661: TME_STP103X(ic)->tme_stp103x_estate_error_enable = 0; ! 662: ! 663: /* a POR zeroes the writable fields in the UPA configuration ! 664: register: */ ! 665: _tme_stp103x_update_upa_config(ic, 0); ! 666: } ! 667: } ! 668: ! 669: /* if this is a trap that uses the MMU globals: */ ! 670: if (trap & TME_STP103X_TRAP_MG) { ! 671: assert (trap != TME_SPARC_TRAP_none); ! 672: pstate ! 673: = ((pstate ! 674: & ~(TME_SPARC64_PSTATE_AG ! 675: + TME_STP103X_PSTATE_MG ! 676: + TME_STP103X_PSTATE_IG)) ! 677: + TME_STP103X_PSTATE_MG); ! 678: } ! 679: ! 680: /* otherwise, if this is a trap that uses the interrupt globals: */ ! 681: else if (trap & TME_STP103X_TRAP_IG) { ! 682: assert (trap != TME_SPARC_TRAP_none); ! 683: pstate ! 684: = ((pstate ! 685: & ~(TME_SPARC64_PSTATE_AG ! 686: + TME_STP103X_PSTATE_MG ! 687: + TME_STP103X_PSTATE_IG)) ! 688: + TME_STP103X_PSTATE_IG); ! 689: } ! 690: ! 691: /* otherwise, if this is another trap: */ ! 692: else if (trap != TME_SPARC_TRAP_none) { ! 693: pstate ! 694: &= ~(TME_STP103X_PSTATE_IG ! 695: + TME_STP103X_PSTATE_MG); ! 696: assert (pstate & TME_SPARC64_PSTATE_AG); ! 697: } ! 698: ! 699: /* the global register selection can't be reserved: */ ! 700: assert ((((pstate & TME_SPARC64_PSTATE_AG) != 0) ! 701: + ((pstate & TME_STP103X_PSTATE_MG) != 0) ! 702: + ((pstate & TME_STP103X_PSTATE_IG) != 0)) < 2); ! 703: ! 704: /* update the global register offset: */ ! 705: ic->tme_sparc_reg8_offset[0] ! 706: = ((pstate & TME_SPARC64_PSTATE_AG) ! 707: #if (TME_SPARC64_IREG_AG_G0 % 8) ! 708: #error "TME_SPARC64_IREG_AG_G0 must be a multiple of eight" ! 709: #endif ! 710: ? (TME_SPARC64_IREG_AG_G0 / 8) ! 711: : (pstate & TME_STP103X_PSTATE_MG) ! 712: #if (TME_SPARC64_IREG_MG_G0 % 8) ! 713: #error "TME_SPARC64_IREG_MG_G0 must be a multiple of eight" ! 714: #endif ! 715: ? (TME_SPARC64_IREG_MG_G0 / 8) ! 716: : (pstate & TME_STP103X_PSTATE_IG) ! 717: #if (TME_SPARC64_IREG_IG_G0 % 8) ! 718: #error "TME_SPARC64_IREG_IG_G0 must be a multiple of eight" ! 719: #endif ! 720: ? (TME_SPARC64_IREG_IG_G0 / 8) ! 721: #if (TME_SPARC_IREG_G0 % 8) ! 722: #error "TME_SPARC_IREG_G0 must be a multiple of eight" ! 723: #endif ! 724: : (TME_SPARC_IREG_G0 / 8)); ! 725: _TME_SPARC_RECODE_CWP_UPDATE(ic, tme_uint64_t); ! 726: ! 727: /* make sure that %g0 is zero in the normal global register set and ! 728: the current global register set. recode instructions thunks ! 729: always refer to %g0 in the normal global register set: */ ! 730: ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_G0) = 0; ! 731: ic->tme_sparc_ireg_uint64(TME_SPARC_G0_OFFSET(ic) + TME_SPARC_IREG_G0) = 0; ! 732: ! 733: /* get the changing bits in PSTATE: */ ! 734: pstate_xor = ic->tme_sparc64_ireg_pstate ^ pstate; ! 735: ! 736: #if TME_HAVE_RECODE && TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 ! 737: ! 738: /* if PSTATE.AM and/or PSTATE.CLE are changing: */ ! 739: if (__tme_predict_false(pstate_xor ! 740: & (TME_SPARC64_PSTATE_AM ! 741: | TME_SPARC64_PSTATE_CLE ! 742: ))) { ! 743: ! 744: /* clear the return address stack, since chaining doesn't check that ! 745: PSTATE matches instructions thunks: */ ! 746: tme_recode_chain_ras_clear(ic->tme_sparc_recode_ic, ! 747: &ic->tme_sparc_ic); ! 748: } ! 749: ! 750: #endif /* TME_HAVE_RECODE && TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 */ ! 751: ! 752: /* set PSTATE: */ ! 753: ic->tme_sparc64_ireg_pstate = pstate; ! 754: ! 755: /* update the address mask: */ ! 756: address_mask ! 757: = ((0 - (tme_uint64_t) ((~pstate / TME_SPARC64_PSTATE_AM) & 1)) ! 758: | (tme_uint32_t) (0 - (tme_uint32_t) 1)); ! 759: ic->tme_sparc_address_mask = address_mask; ! 760: ! 761: /* mask the PCs: */ ! 762: ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT) &= address_mask; ! 763: ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT_NEXT) &= address_mask; ! 764: ! 765: /* if interrupts are enabled, we can't be trapping, because ! 766: _tme_stp103x_interrupt_check() might trap with an interrupt, ! 767: discarding the initial trap: */ ! 768: assert ((pstate & TME_SPARC64_PSTATE_IE) == 0 ! 769: || trap == TME_SPARC_TRAP_none); ! 770: ! 771: /* do an interrupt check: */ ! 772: _tme_stp103x_interrupt_check(ic, TME_SPARC_EXTERNAL_CHECK_NULL); ! 773: } ! 774: ! 775: /* this updates the AFSR: */ ! 776: static void ! 777: _tme_stp103x_update_afsr(struct tme_sparc *ic, tme_uint64_t afsr_reset) ! 778: { ! 779: ! 780: /* one bits in positions 20..32 clear those bits in the AFSR: */ ! 781: TME_STP103X(ic)->tme_stp103x_afsr ! 782: &= ~(afsr_reset ! 783: & ((((tme_uint64_t) 1) << (32 + 1)) - (1 << 20))); ! 784: } ! 785: ! 786: /* this updates the interrupt vector receive: */ ! 787: static void ! 788: _tme_stp103x_update_intr_receive(struct tme_sparc *ic, tme_uint64_t intr_receive) ! 789: { ! 790: tme_memory_atomic_write_flag(&TME_STP103X(ic)->tme_stp103x_intr_receive_busy, ! 791: (intr_receive & TME_STP103X_INTR_RECEIVE_BUSY) != 0); ! 792: } ! 793: ! 794: /* the stp103x rdasr: */ ! 795: static ! 796: TME_SPARC_FORMAT3(_tme_stp103x_rdasr, tme_uint64_t) ! 797: { ! 798: unsigned int reg_rs1; ! 799: tme_uint64_t value; ! 800: ! 801: /* if this is an implementation-specific ASR: */ ! 802: if (TME_SPARC_INSN & (0x10 << 14)) { ! 803: ! 804: /* get rs1: */ ! 805: reg_rs1 = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RS1); ! 806: ! 807: /* if this is an undefined implementation-specific ASR: */ ! 808: if (__tme_predict_false(reg_rs1 >= 0x18)) { ! 809: TME_SPARC_INSN_ILL(ic); ! 810: } ! 811: ! 812: /* if this is a read of GSR: */ ! 813: if (reg_rs1 == 0x13) { ! 814: if (__tme_predict_false((ic->tme_sparc64_ireg_pstate & TME_SPARC64_PSTATE_PEF) == 0 ! 815: || (ic->tme_sparc64_ireg_fprs & TME_SPARC64_FPRS_FEF) == 0)) { ! 816: tme_sparc64_trap(ic, TME_SPARC64_TRAP_fp_disabled); ! 817: } ! 818: value = ic->tme_sparc_vis_gsr; ! 819: } ! 820: ! 821: /* otherwise, this is not a read of GSR: */ ! 822: else { ! 823: ! 824: /* if this is a nonprivileged read: */ ! 825: if (__tme_predict_false(!TME_SPARC_PRIV(ic))) { ! 826: ! 827: /* if this is not a read of PIC, or if PCR.PRIV is set: */ ! 828: if (reg_rs1 != 0x11 ! 829: || (TME_STP103X(ic)->tme_stp103x_pcr & TME_BIT(0))) { ! 830: tme_sparc64_trap(ic, TME_SPARC64_TRAP_privileged_opcode); ! 831: } ! 832: } ! 833: ! 834: /* dispatch on rs1: */ ! 835: switch (reg_rs1) { ! 836: default: TME_SPARC_INSN_ILL(ic); ! 837: case 0x10: value = TME_STP103X(ic)->tme_stp103x_pcr; break; ! 838: case 0x11: value = TME_STP103X(ic)->tme_stp103x_pic.tme_value64_uint; break; ! 839: case 0x12: value = TME_STP103X(ic)->tme_stp103x_dcr; break; ! 840: case 0x16: ! 841: value = TME_STP103X(ic)->tme_stp103x_sir; ! 842: if (tme_memory_atomic_read_flag(&TME_STP103X(ic)->tme_stp103x_sir_tick_int)) { ! 843: value += TME_STP103X_SIR_TICK_INT; ! 844: } ! 845: break; ! 846: case 0x17: value = TME_STP103X(ic)->tme_stp103x_tcr; break; ! 847: } ! 848: } ! 849: TME_SPARC_FORMAT3_RD = value; ! 850: TME_SPARC_INSN_OK; ! 851: } ! 852: tme_sparc64_rdasr(ic, _rs1, _rs2, _rd); ! 853: } ! 854: ! 855: /* the stp103x rdpr: */ ! 856: static ! 857: TME_SPARC_FORMAT3(_tme_stp103x_rdpr, tme_uint64_t) ! 858: { ! 859: unsigned long offset_in_insns; ! 860: tme_uint32_t delay_factor; ! 861: tme_uint32_t insn; ! 862: const struct tme_sparc_tlb *itlb_current; ! 863: ! 864: /* the PROM (at least, SUNW,501-3082-update7.bin) calculates a delay ! 865: factor by waiting for a timer interrupt while running these two ! 866: instructions: ! 867: ! 868: f0055720: 10 80 00 00 b 0xf0055720 ! 869: f0055724: a4 04 a0 01 inc %l2 ! 870: ! 871: the PROM then does a delay by running these two instructions: ! 872: ! 873: f00557e0: 14 68 00 00 bg %xcc, 0xf00557e0 ! 874: f00557e4: a2 a4 60 01 deccc %l1 ! 875: ! 876: unfortunately, in the stp103x emulation, a deccc is more ! 877: expensive than an inc, because it must update the condition ! 878: codes. the difference is significant enough to cause what ! 879: should be a brief delay between these two PROM messages: ! 880: ! 881: Probing Memory Bank #3 0 + 0 : 0 Megabytes ! 882: Probing /sbus@1f,0 at 0,0 Nothing there ! 883: ! 884: to be very, very long. the cost difference appears to be even ! 885: worse when recode is on, and the extreme delay gives the user the ! 886: impression that the emulator is stuck. ! 887: ! 888: there's a chance that there's a cost difference between inc and ! 889: deccc even on a real stp103x; "1000 ms" on the PROM on a real ! 890: Ultra-1 delays noticeably longer than one second. ! 891: ! 892: this function is a gross hack that attempts to reduce the delay. ! 893: it modifies the original loop that calculates the delay factor to ! 894: use (for the "best" factor) an inccc instruction instead of a ! 895: inc, to make it more symmetric with the delay loop. ! 896: ! 897: it detects the original loop by this instruction that precedes it: ! 898: ! 899: f0055708: a7 51 00 00 rdpr %tick, %l3 ! 900: */ ! 901: ! 902: /* if this is a "rdpr %tick, %l3" instruction: */ ! 903: if (__tme_predict_false(TME_SPARC_INSN == 0xa7510000)) { ! 904: ! 905: /* get the offset, in units of instructions, to the next PC that ! 906: is I-Cache block aligned: */ ! 907: offset_in_insns = ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC); ! 908: offset_in_insns = ~offset_in_insns; ! 909: offset_in_insns %= TME_STP103X_ICACHE_BLOCK_SIZE; ! 910: offset_in_insns = (offset_in_insns + 1) / sizeof(TME_SPARC_INSN); ! 911: ! 912: /* if the CPU is in privileged mode, and the first two ! 913: instructions at that PC are "b ." and "inc %l2": */ ! 914: if (TME_SPARC_PRIV(ic) ! 915: && tme_sparc_fetch_nearby(ic, offset_in_insns + 0) == 0x10800000 ! 916: && tme_sparc_fetch_nearby(ic, offset_in_insns + 1) == 0xa404a001) { ! 917: ! 918: /* if the PROM delay factor is to be corrected: */ ! 919: delay_factor = ic->tme_sparc_prom_delay_factor; ! 920: if (delay_factor != TME_SPARC_PROM_DELAY_FACTOR_UNCORRECTED) { ! 921: ! 922: /* if the PROM delay factor correction is "min": */ ! 923: if (delay_factor == TME_SPARC_PROM_DELAY_FACTOR_MIN) { ! 924: ! 925: /* the delay factor is calculated by running the loop for ! 926: 64ms and then dividing the count by 64, so a raw count of ! 927: 64 will get the minimum delay: */ ! 928: delay_factor = 64; ! 929: } ! 930: ! 931: /* if the PROM delay factor correction is "best": */ ! 932: if (delay_factor == TME_SPARC_PROM_DELAY_FACTOR_BEST) { ! 933: ! 934: /* modify the "inc %l2" to be "inccc %l2": */ ! 935: insn = 0xa484a001; ! 936: } ! 937: ! 938: /* otherwise, the PROM delay factor is given directly: */ ! 939: else { ! 940: ! 941: /* modify the "inc %l2" to be "or %g0, simm13, %l2": */ ! 942: insn = 0xa4102000 + TME_MIN(delay_factor, 0xfff); ! 943: } ! 944: ! 945: /* get the current instruction TLB entry: */ ! 946: /* NB: we don't repeat the assert()s or the address-covering ! 947: checks of tme_sparc_fetch_nearby(): */ ! 948: itlb_current = tme_sparc_itlb_current(ic); ! 949: ! 950: /* modify the "inc %l2": */ ! 951: /* NB: we break const here: */ ! 952: ((tme_shared tme_uint32_t *) ! 953: (unsigned long) ! 954: (itlb_current->tme_sparc_tlb_emulator_off_read ! 955: + ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC))) ! 956: [offset_in_insns + 1] = tme_htobe_u32(insn); ! 957: ! 958: /* NB: we don't invalidate the memory page that we just modified ! 959: (in the tme_sparc_recode_cacheable_valids sense), because we ! 960: assume that the loop that calculates the delay factor hasn't ! 961: been recoded yet, and we assume that no other CPUs or other ! 962: bus masters care about the modification: */ ! 963: } ! 964: } ! 965: } ! 966: ! 967: /* do the normal rdpr: */ ! 968: tme_sparc64_rdpr(ic, _rs1, _rs2, _rd); ! 969: } ! 970: ! 971: /* the stp103x wrasr: */ ! 972: static ! 973: TME_SPARC_FORMAT3(_tme_stp103x_wrasr, tme_uint64_t) ! 974: { ! 975: tme_uint64_t value_xor; ! 976: unsigned int reg_rd; ! 977: tme_uint64_t tick; ! 978: struct timeval tick_compare_time; ! 979: tme_uint64_t cycles_scaled; ! 980: tme_uint64_t usec64; ! 981: tme_uint32_t usec32; ! 982: ! 983: /* if this is an implementation-specific ASR: */ ! 984: if (TME_SPARC_INSN & (0x10 << 25)) { ! 985: ! 986: /* get the value to write: */ ! 987: value_xor = TME_SPARC_FORMAT3_RS1 ^ TME_SPARC_FORMAT3_RS2; ! 988: ! 989: /* get rd: */ ! 990: reg_rd = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD); ! 991: ! 992: /* if this is an undefined implementation-specific ASR: */ ! 993: if (__tme_predict_false(reg_rd >= 0x18)) { ! 994: TME_SPARC_INSN_ILL(ic); ! 995: } ! 996: ! 997: /* if this is an write to GSR: */ ! 998: if (reg_rd == 0x13) { ! 999: if (__tme_predict_false((ic->tme_sparc64_ireg_pstate & TME_SPARC64_PSTATE_PEF) == 0 ! 1000: || (ic->tme_sparc64_ireg_fprs & TME_SPARC64_FPRS_FEF) == 0)) { ! 1001: tme_sparc64_trap(ic, TME_SPARC64_TRAP_fp_disabled); ! 1002: } ! 1003: ic->tme_sparc_vis_gsr = value_xor; ! 1004: } ! 1005: ! 1006: /* otherwise, this is not a write to GSR: */ ! 1007: else { ! 1008: ! 1009: /* if this is a nonprivileged write: */ ! 1010: if (__tme_predict_false(!TME_SPARC_PRIV(ic))) { ! 1011: ! 1012: /* if this is not a write to PIC, or if PCR.PRIV is set: */ ! 1013: if (reg_rd != 0x11 ! 1014: || (TME_STP103X(ic)->tme_stp103x_pcr & TME_BIT(0))) { ! 1015: tme_sparc64_trap(ic, TME_SPARC64_TRAP_privileged_action); ! 1016: } ! 1017: } ! 1018: ! 1019: /* dispatch on rd: */ ! 1020: switch (reg_rd) { ! 1021: default: assert (FALSE); ! 1022: case 0x10: TME_STP103X(ic)->tme_stp103x_pcr = value_xor; break; ! 1023: case 0x11: TME_STP103X(ic)->tme_stp103x_pic.tme_value64_uint = value_xor; break; ! 1024: case 0x12: TME_STP103X(ic)->tme_stp103x_dcr = value_xor; break; ! 1025: case 0x14: _tme_stp103x_update_sir(ic, 0, value_xor); break; ! 1026: case 0x15: _tme_stp103x_update_sir(ic, value_xor, 0); break; ! 1027: case 0x16: _tme_stp103x_update_sir(ic, 0xffff, value_xor); break; ! 1028: ! 1029: case 0x17: ! 1030: TME_STP103X(ic)->tme_stp103x_tcr = value_xor; ! 1031: ! 1032: /* if we're not replaying instructions: */ ! 1033: if (tme_sparc_recode_verify_replay_last_pc(ic) == 0) { ! 1034: ! 1035: /* if INT_DIS is set: */ ! 1036: if (__tme_predict_false(value_xor & TME_STP103X_TCR_INT_DIS)) { ! 1037: ! 1038: /* the tick compare time is never: */ ! 1039: tme_misc_timeval_never(&tick_compare_time); ! 1040: } ! 1041: ! 1042: /* otherwise, INT_DIS is clear: */ ! 1043: else { ! 1044: ! 1045: /* get the current value of TICK.counter: */ ! 1046: tick = tme_misc_cycles_scaled(&ic->tme_sparc_cycles_scaling, 0).tme_value64_uint; ! 1047: tick += ic->tme_sparc64_ireg_tick_offset; ! 1048: tick &= TME_SPARC64_TICK_COUNTER; ! 1049: ! 1050: /* get the current time: */ ! 1051: gettimeofday(&tick_compare_time, NULL); ! 1052: ! 1053: /* get the number of cycles until the compare value is ! 1054: reached: */ ! 1055: cycles_scaled = TME_STP103X(ic)->tme_stp103x_tcr - tick; ! 1056: cycles_scaled &= TME_SPARC64_TICK_COUNTER; ! 1057: ! 1058: /* if the number of cycles doesn't fit in 32 bits: */ ! 1059: if (__tme_predict_false(cycles_scaled > (tme_uint32_t) (0 - (tme_uint32_t) 1))) { ! 1060: ! 1061: /* convert cycles into microseconds: */ ! 1062: usec64 = cycles_scaled / ic->tme_sparc_cycles_scaled_per_usec; ! 1063: ! 1064: /* add in the whole seconds: */ ! 1065: tick_compare_time.tv_sec += (usec64 / 1000000); ! 1066: ! 1067: /* get the remaining microseconds: */ ! 1068: usec32 = (usec64 % 1000000); ! 1069: } ! 1070: ! 1071: /* otherwise, the number of cycles fits in 32 bits: */ ! 1072: else { ! 1073: ! 1074: /* convert cycles into microseconds: */ ! 1075: usec32 = ((tme_uint32_t) cycles_scaled) / ic->tme_sparc_cycles_scaled_per_usec; ! 1076: ! 1077: /* if there is at least one whole second: */ ! 1078: if (__tme_predict_false(usec32 >= 1000000)) { ! 1079: ! 1080: /* add in the whole seconds: */ ! 1081: tick_compare_time.tv_sec += (usec32 / 1000000); ! 1082: ! 1083: /* get the remaining microseconds: */ ! 1084: usec32 %= 1000000; ! 1085: } ! 1086: } ! 1087: ! 1088: /* add in the microseconds: */ ! 1089: usec32 += tick_compare_time.tv_usec; ! 1090: if (usec32 >= 1000000) { ! 1091: tick_compare_time.tv_sec++; ! 1092: usec32 -= 1000000; ! 1093: } ! 1094: tick_compare_time.tv_usec = usec32; ! 1095: } ! 1096: ! 1097: /* lock the external mutex: */ ! 1098: tme_mutex_lock(&ic->tme_sparc_external_mutex); ! 1099: ! 1100: /* set the tick compare time: */ ! 1101: TME_STP103X(ic)->tme_stp103x_tick_compare_time = tick_compare_time; ! 1102: ! 1103: /* notify the tick compare thread: */ ! 1104: tme_cond_notify(&TME_STP103X(ic)->tme_stp103x_tick_compare_cond, FALSE); ! 1105: ! 1106: /* unlock the external mutex: */ ! 1107: tme_mutex_unlock(&ic->tme_sparc_external_mutex); ! 1108: } ! 1109: break; ! 1110: } ! 1111: } ! 1112: TME_SPARC_INSN_OK; ! 1113: } ! 1114: tme_sparc64_wrasr(ic, _rs1, _rs2, _rd); ! 1115: } ! 1116: ! 1117: /* the stp103x impdep1: */ ! 1118: static ! 1119: TME_SPARC_FORMAT3(_tme_stp103x_impdep1, tme_uint64_t) ! 1120: { ! 1121: tme_uint32_t opf; ! 1122: tme_uint64_t rd; ! 1123: unsigned int alignaddr_off; ! 1124: ! 1125: /* extract the opf field: */ ! 1126: opf = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, (0x1ff << 5)); ! 1127: ! 1128: /* if this is a shutdown instruction: */ ! 1129: if (opf == 0x80) { ! 1130: TME_SPARC_INSN_PRIV; ! 1131: ! 1132: /* XXX WRITEME: */ ! 1133: abort(); ! 1134: } ! 1135: ! 1136: /* if this is the VIS alignaddr instruction: */ ! 1137: if ((opf | TME_BIT(1)) == 0x1a) { ! 1138: ! 1139: /* add the two registers into an address: */ ! 1140: rd = TME_SPARC_FORMAT3_RS1 + TME_SPARC_FORMAT3_RS2; ! 1141: ! 1142: /* store the alignaddr offset: */ ! 1143: alignaddr_off ! 1144: = (((opf & TME_BIT(1)) ! 1145: ? (sizeof(tme_uint64_t) - 1) ! 1146: : 0) ! 1147: ^ rd); ! 1148: TME_FIELD_MASK_DEPOSITU(ic->tme_sparc_vis_gsr, ! 1149: TME_SPARC_VIS_GSR_ALIGNADDR_OFF, ! 1150: alignaddr_off); ! 1151: ! 1152: /* truncate the address: */ ! 1153: TME_SPARC_FORMAT3_RD = rd & (0 - (tme_uint64_t) sizeof(tme_uint64_t)); ! 1154: ! 1155: TME_SPARC_INSN_OK; ! 1156: } ! 1157: ! 1158: /* otherwise, assume that this is some other VIS instruction: */ ! 1159: tme_sparc_vis(ic); ! 1160: TME_SPARC_INSN_OK; ! 1161: } ! 1162: ! 1163: /* the stp103x impdep2: */ ! 1164: static ! 1165: TME_SPARC_FORMAT3(_tme_stp103x_impdep2, tme_uint64_t) ! 1166: { ! 1167: TME_SPARC_INSN_ILL(ic); ! 1168: } ! 1169: ! 1170: /* the stp103x flush: */ ! 1171: static ! 1172: TME_SPARC_FORMAT3(_tme_stp103x_flush, tme_uint64_t) ! 1173: { ! 1174: tme_uint64_t address; ! 1175: tme_uint32_t context; ! 1176: struct tme_sparc_tlb *dtlb; ! 1177: tme_uint64_t rd; ! 1178: ! 1179: /* if we're replaying instructions, return now: */ ! 1180: if (tme_sparc_recode_verify_replay_last_pc(ic) != 0) { ! 1181: TME_SPARC_INSN_OK; ! 1182: } ! 1183: ! 1184: /* get the address: */ ! 1185: address = TME_SPARC_FORMAT3_RS1 + TME_SPARC_FORMAT3_RS2; ! 1186: address &= ic->tme_sparc_address_mask; ! 1187: ! 1188: /* get the context: */ ! 1189: context = ic->tme_sparc_memory_context_default; ! 1190: ! 1191: /* get and busy the DTLB entry: */ ! 1192: dtlb = &ic->tme_sparc_tlbs[TME_SPARC_DTLB_ENTRY(ic, TME_SPARC_TLB_HASH(ic, context, address))]; ! 1193: tme_sparc_tlb_busy(dtlb); ! 1194: ! 1195: /* a flush instruction behaves like a non-faulting load: */ ! 1196: tme_sparc64_ls(ic, ! 1197: address, ! 1198: &rd, ! 1199: (TME_SPARC_LSINFO_OP_LD ! 1200: + TME_SPARC_LSINFO_ASI_FLAGS(TME_SPARC64_ASI_FLAG_NO_FAULT) ! 1201: + sizeof(tme_uint8_t))); ! 1202: ! 1203: /* unbusy the DTLB entry: */ ! 1204: tme_sparc_tlb_unbusy(dtlb); ! 1205: ! 1206: TME_SPARC_INSN_OK; ! 1207: } ! 1208: ! 1209: /* the format three opcode map: */ ! 1210: #define _TME_SPARC_EXECUTE_OPMAP tme_sparc_opcodes_stp103x ! 1211: static const _tme_sparc64_format3 _TME_SPARC_EXECUTE_OPMAP[] = { ! 1212: ! 1213: /* op=2: arithmetic, logical, shift, and remaining: */ ! 1214: ! 1215: /* 000000 */ tme_sparc64_add, ! 1216: /* 000001 */ tme_sparc64_and, ! 1217: /* 000010 */ tme_sparc64_or, ! 1218: /* 000011 */ tme_sparc64_xor, ! 1219: /* 000100 */ tme_sparc64_sub, ! 1220: /* 000101 */ tme_sparc64_andn, ! 1221: /* 000110 */ tme_sparc64_orn, ! 1222: /* 000111 */ tme_sparc64_xnor, ! 1223: /* 001000 */ tme_sparc64_addx, ! 1224: /* 001001 */ tme_sparc64_mulx, ! 1225: /* 001010 */ tme_sparc64_umul, ! 1226: /* 001011 */ tme_sparc64_smul, ! 1227: /* 001100 */ tme_sparc64_subx, ! 1228: /* 001101 */ tme_sparc64_udivx, ! 1229: /* 001110 */ tme_sparc64_udiv, ! 1230: /* 001111 */ tme_sparc64_sdiv, ! 1231: /* 010000 */ tme_sparc64_addcc, ! 1232: /* 010001 */ tme_sparc64_andcc, ! 1233: /* 010010 */ tme_sparc64_orcc, ! 1234: /* 010011 */ tme_sparc64_xorcc, ! 1235: /* 010100 */ tme_sparc64_subcc, ! 1236: /* 010101 */ tme_sparc64_andncc, ! 1237: /* 010110 */ tme_sparc64_orncc, ! 1238: /* 010111 */ tme_sparc64_xnorcc, ! 1239: /* 011000 */ tme_sparc64_addxcc, ! 1240: /* 011001 */ NULL, ! 1241: /* 011010 */ tme_sparc64_umulcc, ! 1242: /* 011011 */ tme_sparc64_smulcc, ! 1243: /* 011100 */ tme_sparc64_subxcc, ! 1244: /* 011101 */ NULL, ! 1245: /* 011110 */ tme_sparc64_udivcc, ! 1246: /* 011111 */ tme_sparc64_sdivcc, ! 1247: /* 100000 */ tme_sparc64_taddcc, ! 1248: /* 100001 */ tme_sparc64_tsubcc, ! 1249: /* 100010 */ tme_sparc64_taddcctv, ! 1250: /* 100011 */ tme_sparc64_tsubcctv, ! 1251: /* 100100 */ tme_sparc64_mulscc, ! 1252: /* 100101 */ tme_sparc64_sll, ! 1253: /* 100110 */ tme_sparc64_srl, ! 1254: /* 100111 */ tme_sparc64_sra, ! 1255: /* 101000 */ _tme_stp103x_rdasr, ! 1256: /* 101001 */ NULL, ! 1257: /* 101010 */ _tme_stp103x_rdpr, ! 1258: /* 101011 */ tme_sparc64_flushw, ! 1259: /* 101100 */ tme_sparc64_movcc, ! 1260: /* 101101 */ tme_sparc64_sdivx, ! 1261: /* 101110 */ NULL, ! 1262: /* 101111 */ tme_sparc64_movr, ! 1263: /* 110000 */ _tme_stp103x_wrasr, ! 1264: /* 110001 */ tme_sparc64_saved_restored, ! 1265: /* 110010 */ tme_sparc64_wrpr, ! 1266: /* 110011 */ NULL, ! 1267: /* 110100 */ tme_sparc64_fpop1, ! 1268: /* 110101 */ tme_sparc64_fpop2, ! 1269: /* 110110 */ _tme_stp103x_impdep1, ! 1270: /* 110111 */ _tme_stp103x_impdep2, ! 1271: /* 111000 */ tme_sparc64_jmpl, ! 1272: /* 111001 */ tme_sparc64_return, ! 1273: /* 111010 */ tme_sparc64_tcc, ! 1274: /* 111011 */ _tme_stp103x_flush, ! 1275: /* 111100 */ tme_sparc64_save_restore, ! 1276: /* 111101 */ tme_sparc64_save_restore, ! 1277: /* 111110 */ tme_sparc64_done_retry, ! 1278: /* 111111 */ NULL, ! 1279: ! 1280: /* op=3: memory instructions: */ ! 1281: ! 1282: /* 000000 */ tme_sparc64_ld, ! 1283: /* 000001 */ tme_sparc64_ldb, ! 1284: /* 000010 */ tme_sparc64_ldh, ! 1285: /* 000011 */ tme_sparc64_ldd, ! 1286: /* 000100 */ tme_sparc64_st, ! 1287: /* 000101 */ tme_sparc64_stb, ! 1288: /* 000110 */ tme_sparc64_sth, ! 1289: /* 000111 */ tme_sparc64_std, ! 1290: /* 001000 */ tme_sparc64_ld, ! 1291: /* 001001 */ tme_sparc64_ldb, ! 1292: /* 001010 */ tme_sparc64_ldh, ! 1293: /* 001011 */ tme_sparc64_ldx, ! 1294: /* 001100 */ NULL, ! 1295: /* 001101 */ tme_sparc64_ldstub, ! 1296: /* 001110 */ tme_sparc64_stx, ! 1297: /* 001111 */ tme_sparc64_swap, ! 1298: /* 010000 */ tme_sparc64_lda, ! 1299: /* 010001 */ tme_sparc64_ldba, ! 1300: /* 010010 */ tme_sparc64_ldha, ! 1301: /* 010011 */ tme_sparc64_ldda, ! 1302: /* 010100 */ tme_sparc64_sta, ! 1303: /* 010101 */ tme_sparc64_stba, ! 1304: /* 010110 */ tme_sparc64_stha, ! 1305: /* 010111 */ tme_sparc64_stda, ! 1306: /* 011000 */ tme_sparc64_lda, ! 1307: /* 011001 */ tme_sparc64_ldba, ! 1308: /* 011010 */ tme_sparc64_ldha, ! 1309: /* 011011 */ tme_sparc64_ldxa, ! 1310: /* 011100 */ NULL, ! 1311: /* 011101 */ tme_sparc64_ldstuba, ! 1312: /* 011110 */ tme_sparc64_stxa, ! 1313: /* 011111 */ tme_sparc64_swapa, ! 1314: /* 100000 */ tme_sparc64_ldf, ! 1315: /* 100001 */ tme_sparc64_ldfsr, ! 1316: /* 100010 */ tme_sparc64_illegal_instruction, /* ldqf */ ! 1317: /* 100011 */ tme_sparc64_lddf, ! 1318: /* 100100 */ tme_sparc64_stf, ! 1319: /* 100101 */ tme_sparc64_stfsr, ! 1320: /* 100110 */ tme_sparc64_illegal_instruction, /* stqf */ ! 1321: /* 100111 */ tme_sparc64_stdf, ! 1322: /* 101000 */ NULL, ! 1323: /* 101001 */ NULL, ! 1324: /* 101010 */ NULL, ! 1325: /* 101011 */ NULL, ! 1326: /* 101100 */ NULL, ! 1327: /* 101101 */ tme_sparc64_prefetch, ! 1328: /* 101110 */ NULL, ! 1329: /* 101111 */ NULL, ! 1330: /* 110000 */ tme_sparc64_ldfa, ! 1331: /* 110001 */ NULL, ! 1332: /* 110010 */ tme_sparc64_illegal_instruction, /* ldqfa */ ! 1333: /* 110011 */ tme_sparc64_lddfa, ! 1334: /* 110100 */ tme_sparc64_stfa, ! 1335: /* 110101 */ NULL, ! 1336: /* 110110 */ tme_sparc64_illegal_instruction, /* stqfa */ ! 1337: /* 110111 */ tme_sparc64_stdfa, ! 1338: /* 111000 */ NULL, ! 1339: /* 111001 */ NULL, ! 1340: /* 111010 */ NULL, ! 1341: /* 111011 */ NULL, ! 1342: /* 111100 */ tme_sparc64_casa, ! 1343: /* 111101 */ tme_sparc64_prefetch, ! 1344: /* 111110 */ tme_sparc64_casxa, ! 1345: /* 111111 */ NULL, ! 1346: }; ! 1347: ! 1348: /* make the executor for the STP103x: */ ! 1349: #define _TME_SPARC_EXECUTE_NAME _tme_sparc_execute_stp103x ! 1350: #include "sparc-execute.c" ! 1351: ! 1352: /* this invalidates a specific valid stp103x TLB entry: */ ! 1353: static void ! 1354: _tme_stp103x_tlb_invalidate(struct tme_sparc *ic, ! 1355: signed long tlb_part_i) ! 1356: { ! 1357: tme_uint32_t tlb_data_32_63; ! 1358: struct tme_sparc_tlb *tlb; ! 1359: tme_uint32_t tlb_count; ! 1360: tme_uint32_t size; ! 1361: tme_uint64_t address; ! 1362: tme_uint32_t context; ! 1363: ! 1364: /* load bits 32..63 of the TLB entry's data: */ ! 1365: tlb_data_32_63 = TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 1); ! 1366: ! 1367: /* this TLB entry must be valid: */ ! 1368: assert (tlb_data_32_63 & TME_STP103X_TLB_DATA_V(tlb_data_32_63)); ! 1369: ! 1370: /* this TLB entry is now invalid: */ ! 1371: tlb_data_32_63 &= ~TME_STP103X_TLB_DATA_V(tlb_data_32_63); ! 1372: TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 1) = tlb_data_32_63; ! 1373: ! 1374: /* if this TLB entry is global: */ ! 1375: if (TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 0) ! 1376: & TME_STP103X_TLB_DATA_G((tme_uint32_t) 0)) { ! 1377: ! 1378: /* assume that this is an stp103x DTLB entry, and we need to ! 1379: invalidate sparc DTLB entries: */ ! 1380: tlb = &ic->tme_sparc_tlbs[0]; ! 1381: tlb_count = _TME_SPARC_DTLB_HASH_SIZE; ! 1382: ! 1383: /* if this is an stp103x ITLB entry: */ ! 1384: #if TME_STP103X_TLB_PART_0_DMMU >= TME_STP103X_TLB_PART_0_IMMU ! 1385: #error "TME_STP103X_TLB_PART_0_DMMU or TME_STP103X_TLB_PART_0_IMMU changed" ! 1386: #endif ! 1387: if (tlb_part_i >= TME_STP103X_TLB_PART_0_IMMU) { ! 1388: ! 1389: /* we need to invalidate sparc ITLB entries: */ ! 1390: tlb += _TME_SPARC_DTLB_HASH_SIZE; ! 1391: tlb_count = _TME_SPARC_ITLB_HASH_SIZE; ! 1392: } ! 1393: ! 1394: /* invalidate all of the sparc TLB entries linked to this stp103x ! 1395: TLB entry: */ ! 1396: do { ! 1397: if (tlb->tme_sparc_tlb_link == tlb_part_i) { ! 1398: tme_token_invalidate_nosync(tlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token); ! 1399: } ! 1400: tlb++; ! 1401: } while (--tlb_count); ! 1402: } ! 1403: ! 1404: /* otherwise, this TLB entry isn't global: */ ! 1405: else { ! 1406: ! 1407: /* get the size of this mapping: */ ! 1408: size ! 1409: = (TME_STP103X_PAGE_SIZE_8KB ! 1410: << (3 * TME_FIELD_MASK_EXTRACTU(tlb_data_32_63, ! 1411: TME_STP103X_TLB_DATA_SIZE_MASK(tlb_data_32_63)))); ! 1412: ! 1413: /* get the tag, and divide it into context and address: */ ! 1414: address = TME_STP103X(ic)->tme_stp103x_tlb_64s(tlb_part_i + 0); ! 1415: context = address; ! 1416: context &= TME_STP103X_CONTEXT_MAX; ! 1417: address &= (0 - (tme_uint64_t) size); ! 1418: ! 1419: /* we assume that a stride of 8KB will find all sparc TLB entries ! 1420: for this stp103x TLB entry: */ ! 1421: assert ((1 << ic->tme_sparc_tlb_page_size_log2) == TME_STP103X_PAGE_SIZE_8KB); ! 1422: ! 1423: /* if this is an stp103x DTLB entry: */ ! 1424: #if TME_STP103X_TLB_PART_0_DMMU >= TME_STP103X_TLB_PART_0_IMMU ! 1425: #error "TME_STP103X_TLB_PART_0_DMMU or TME_STP103X_TLB_PART_0_IMMU changed" ! 1426: #endif ! 1427: if (tlb_part_i < TME_STP103X_TLB_PART_0_IMMU) { ! 1428: ! 1429: /* invalidate all of the sparc DTLB entries linked to this ! 1430: stp103x DTLB entry: */ ! 1431: do { ! 1432: tlb = &ic->tme_sparc_tlbs[TME_SPARC_DTLB_ENTRY(ic, TME_SPARC_TLB_HASH(ic, context, address))]; ! 1433: if (tlb->tme_sparc_tlb_link == tlb_part_i) { ! 1434: tme_token_invalidate_nosync(tlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token); ! 1435: } ! 1436: address += TME_STP103X_PAGE_SIZE_8KB; ! 1437: } while ((size -= TME_STP103X_PAGE_SIZE_8KB) > 0); ! 1438: } ! 1439: ! 1440: /* otherwise, this is an stp103x ITLB entry: */ ! 1441: else { ! 1442: ! 1443: /* invalidate all of the sparc ITLB entries linked to this ! 1444: stp103x ITLB entry: */ ! 1445: do { ! 1446: tlb = &ic->tme_sparc_tlbs[TME_SPARC_ITLB_ENTRY(ic, TME_SPARC_TLB_HASH(ic, context, address))]; ! 1447: if (tlb->tme_sparc_tlb_link == tlb_part_i) { ! 1448: tme_token_invalidate_nosync(tlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token); ! 1449: } ! 1450: address += TME_STP103X_PAGE_SIZE_8KB; ! 1451: } while ((size -= TME_STP103X_PAGE_SIZE_8KB) > 0); ! 1452: } ! 1453: } ! 1454: } ! 1455: ! 1456: /* this handles a load/store trap: */ ! 1457: static void ! 1458: _tme_stp103x_ls_trap(struct tme_sparc *ic, ! 1459: struct tme_sparc_ls *ls) ! 1460: { ! 1461: tme_uint32_t lsinfo; ! 1462: tme_uint32_t sfsr; ! 1463: tme_uint32_t ls_faults; ! 1464: tme_uint32_t trap; ! 1465: tme_uint32_t updates; ! 1466: tme_uint32_t insn; ! 1467: tme_uint64_t afsr; ! 1468: tme_uint64_t address; ! 1469: tme_uint32_t asi_mask; ! 1470: struct tme_stp103x_mmu *mmu; ! 1471: ! 1472: /* get the information about this load/store: */ ! 1473: lsinfo = ls->tme_sparc_ls_lsinfo; ! 1474: ! 1475: /* check that we weren't supposed to fault: */ ! 1476: assert ((lsinfo & TME_STP103X_LSINFO_ASSERT_NO_FAULTS) == 0); ! 1477: ! 1478: /* if we're supposed to ignore faults: */ ! 1479: if (__tme_predict_false(lsinfo & TME_SPARC_LSINFO_NO_FAULT)) { ! 1480: ! 1481: /* clear all faults and complete the load/store: */ ! 1482: ls->tme_sparc_ls_faults = TME_SPARC_LS_FAULT_NONE; ! 1483: ls->tme_sparc_ls_size = 0; ! 1484: return; ! 1485: } ! 1486: ! 1487: /* start an SFSR value: */ ! 1488: sfsr = 0; ! 1489: ! 1490: /* get the list of faults from this load/store: */ ! 1491: ls_faults = ls->tme_sparc_ls_faults; ! 1492: ! 1493: /* there must be at least one fault: */ ! 1494: assert (ls_faults != TME_SPARC_LS_FAULT_NONE); ! 1495: ! 1496: /* we don't support generic bus faults: */ ! 1497: assert ((ls_faults ! 1498: & (TME_SPARC_LS_FAULT_BUS_FAULT)) == 0); ! 1499: ! 1500: /* if this is an IMMU miss, this must be the only fault. we rely on ! 1501: this to honor trap priorities, since we handle IMMU misses and ! 1502: DMMU misses as if they have the same priority, even though they ! 1503: don't: */ ! 1504: assert ((ls_faults & TME_STP103X_LS_FAULT_MMU_MISS) == 0 ! 1505: || (lsinfo & TME_SPARC_LSINFO_OP_FETCH) == 0 ! 1506: || ls_faults == TME_STP103X_LS_FAULT_MMU_MISS); ! 1507: ! 1508: /* if this is a instruction access error, it must happen alone. we ! 1509: rely on this to honor trap priorities, since we handle ! 1510: instruction access errors and data access errors as if they have ! 1511: the same priority, even though they don't: */ ! 1512: assert ((ls_faults & TME_SPARC_LS_FAULT_BUS_ERROR) == 0 ! 1513: || (lsinfo & TME_SPARC_LSINFO_OP_FETCH) == 0 ! 1514: || ls_faults == TME_SPARC_LS_FAULT_BUS_ERROR); ! 1515: ! 1516: /* if this is an instruction access exception, it either happens ! 1517: alone (because of a privilege violation), or it's because of a ! 1518: jmpl/return target address out-of-range. we rely on this to ! 1519: honor trap priorities, since we handle privilege violation ! 1520: instruction access exceptions and data access exceptions as if ! 1521: they have the same priority, even though they don't. (a ! 1522: jmpl/return target instruction access exception explicitly has ! 1523: the same priority as a data access exception): */ ! 1524: assert ((ls_faults ! 1525: & (TME_STP103X_LS_FAULT_PRIVILEGE ! 1526: | TME_SPARC64_LS_FAULT_SIDE_EFFECTS ! 1527: | TME_SPARC64_LS_FAULT_UNCACHEABLE ! 1528: | TME_SPARC64_LS_FAULT_NO_FAULT_NON_LOAD ! 1529: | TME_STP103X_LS_FAULT_ILLEGAL ! 1530: | TME_SPARC64_LS_FAULT_NO_FAULT_FAULT ! 1531: | TME_SPARC64_LS_FAULT_VA_RANGE ! 1532: | TME_SPARC64_LS_FAULT_VA_RANGE_NNPC)) == 0 ! 1533: || (lsinfo & TME_SPARC_LSINFO_OP_FETCH) == 0 ! 1534: || ls_faults == TME_STP103X_LS_FAULT_PRIVILEGE ! 1535: || ls_faults == TME_SPARC64_LS_FAULT_VA_RANGE_NNPC); ! 1536: ! 1537: /* these traps are sorted by priority, most important first: */ ! 1538: ! 1539: /* if this was an illegal instruction: */ ! 1540: if (ls_faults ! 1541: & (TME_SPARC_LS_FAULT_LDD_STD_RD_ODD)) { ! 1542: ! 1543: /* make an illegal_instruction trap, which doesn't update any MMU ! 1544: registers: */ ! 1545: trap = TME_SPARC64_TRAP_illegal_instruction; ! 1546: updates = TME_STP103X_UPDATE_NONE; ! 1547: } ! 1548: ! 1549: /* otherwise, if the address isn't aligned: */ ! 1550: else if (ls_faults & TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED) { ! 1551: ! 1552: /* assume that this is not an lddf or stdf instruction, or that ! 1553: the address is not even 32-bit aligned, and make the normal ! 1554: mem_address_not_aligned trap: */ ! 1555: trap = TME_SPARC64_TRAP_mem_address_not_aligned; ! 1556: ! 1557: /* if this is an lddf or stdf instruction: */ ! 1558: insn = ic->_tme_sparc_insn; ! 1559: if ((insn ! 1560: & (0x3b << 19)) ! 1561: == (0x23 << 19)) { ! 1562: ! 1563: /* if the address is 32-bit aligned, but not 64-bit aligned: */ ! 1564: if ((ls->tme_sparc_ls_address64 % sizeof(tme_uint64_t)) ! 1565: == sizeof(tme_uint32_t)) { ! 1566: ! 1567: /* make the LDDF_mem_address_not_aligned or ! 1568: STDF_mem_address_not_aligned trap: */ ! 1569: trap ! 1570: = ((insn & (4 << 19)) ! 1571: ? TME_SPARC64_TRAP_STDF_mem_address_not_aligned ! 1572: : TME_SPARC64_TRAP_LDDF_mem_address_not_aligned); ! 1573: } ! 1574: } ! 1575: ! 1576: /* these traps update the DMMU SFSR and SFAR: */ ! 1577: updates ! 1578: = (TME_STP103X_UPDATE_DMMU ! 1579: + TME_STP103X_UPDATE_MMU_SFSR ! 1580: + TME_STP103X_UPDATE_DMMU_SFAR); ! 1581: } ! 1582: ! 1583: /* otherwise, if the ASI is privileged: */ ! 1584: else if (ls_faults & TME_SPARC64_LS_FAULT_PRIVILEGED_ASI) { ! 1585: ! 1586: /* make a privileged_action trap, which updates the DMMU SFSR and ! 1587: SFAR: */ ! 1588: trap = TME_SPARC64_TRAP_privileged_action; ! 1589: updates ! 1590: = (TME_STP103X_UPDATE_DMMU ! 1591: + TME_STP103X_UPDATE_MMU_SFSR ! 1592: + TME_STP103X_UPDATE_DMMU_SFAR); ! 1593: } ! 1594: ! 1595: /* otherwise, if this is an access exception: */ ! 1596: else if (ls_faults ! 1597: & (TME_STP103X_LS_FAULT_PRIVILEGE ! 1598: | TME_SPARC64_LS_FAULT_SIDE_EFFECTS ! 1599: | TME_SPARC64_LS_FAULT_UNCACHEABLE ! 1600: | TME_SPARC64_LS_FAULT_NO_FAULT_NON_LOAD ! 1601: | TME_STP103X_LS_FAULT_ILLEGAL ! 1602: | TME_SPARC64_LS_FAULT_NO_FAULT_FAULT ! 1603: | TME_SPARC64_LS_FAULT_VA_RANGE ! 1604: | TME_SPARC64_LS_FAULT_VA_RANGE_NNPC)) { ! 1605: ! 1606: /* make the SFSR FT field: */ ! 1607: if (ls_faults & TME_STP103X_LS_FAULT_PRIVILEGE) { ! 1608: sfsr += TME_STP103X_SFSR_FT_PRIVILEGE; ! 1609: } ! 1610: if (ls_faults & TME_SPARC64_LS_FAULT_SIDE_EFFECTS) { ! 1611: sfsr += TME_STP103X_SFSR_FT_SIDE_EFFECTS; ! 1612: } ! 1613: if (ls_faults & TME_SPARC64_LS_FAULT_UNCACHEABLE) { ! 1614: /* XXX FIXME WRITEME table 6-11 hints that it's possible to do a ! 1615: casxa to DTLB_DATA_ACCESS_REG, and that a fault while doing ! 1616: so will set this bit: */ ! 1617: sfsr += TME_STP103X_SFSR_FT_UNCACHEABLE; ! 1618: } ! 1619: if (ls_faults & ! 1620: (TME_SPARC64_LS_FAULT_NO_FAULT_NON_LOAD ! 1621: | TME_STP103X_LS_FAULT_ILLEGAL)) { ! 1622: sfsr += TME_STP103X_SFSR_FT_ILLEGAL; ! 1623: } ! 1624: if (ls_faults & TME_SPARC64_LS_FAULT_NO_FAULT_FAULT) { ! 1625: sfsr += TME_STP103X_SFSR_FT_NO_FAULT_FAULT; ! 1626: } ! 1627: if (ls_faults & TME_SPARC64_LS_FAULT_VA_RANGE) { ! 1628: sfsr += TME_STP103X_SFSR_FT_VA_RANGE; ! 1629: } ! 1630: if (ls_faults & TME_SPARC64_LS_FAULT_VA_RANGE_NNPC) { ! 1631: sfsr += TME_STP103X_SFSR_FT_VA_RANGE_NNPC; ! 1632: } ! 1633: ! 1634: /* if this is an instruction fetch: */ ! 1635: if (lsinfo & TME_SPARC_LSINFO_OP_FETCH) { ! 1636: ! 1637: /* the IMMU SFSR FT field must have exactly one of the privilege ! 1638: and VA range bits set: */ ! 1639: assert (sfsr != 0 ! 1640: && (sfsr ! 1641: & ~(TME_STP103X_SFSR_FT_PRIVILEGE ! 1642: | TME_STP103X_SFSR_FT_VA_RANGE ! 1643: | TME_STP103X_SFSR_FT_VA_RANGE_NNPC)) == 0 ! 1644: && (sfsr & (sfsr - 1)) == 0); ! 1645: ! 1646: /* make an instruction_access_exception trap, which updates the ! 1647: IMMU SFSR and tag access register: */ ! 1648: trap = (TME_STP103X_TRAP_MG | TME_SPARC64_TRAP_instruction_access_exception); ! 1649: updates ! 1650: = (TME_STP103X_UPDATE_IMMU ! 1651: + TME_STP103X_UPDATE_MMU_SFSR ! 1652: + TME_STP103X_UPDATE_MMU_TAG_ACCESS); ! 1653: } ! 1654: ! 1655: /* otherwise, this is not an instruction fetch: */ ! 1656: else { ! 1657: ! 1658: /* make a data_access_exception trap, which updates the DMMU ! 1659: SFSR, SFAR, and tag access register: */ ! 1660: trap = (TME_STP103X_TRAP_MG | TME_SPARC64_TRAP_data_access_exception); ! 1661: updates ! 1662: = (TME_STP103X_UPDATE_DMMU ! 1663: + TME_STP103X_UPDATE_MMU_SFSR ! 1664: + TME_STP103X_UPDATE_DMMU_SFAR ! 1665: + TME_STP103X_UPDATE_MMU_TAG_ACCESS); ! 1666: } ! 1667: } ! 1668: ! 1669: /* otherwise, if this is an MMU miss: */ ! 1670: else if (ls_faults & TME_STP103X_LS_FAULT_MMU_MISS) { ! 1671: ! 1672: /* if this is an instruction fetch: */ ! 1673: if (lsinfo & TME_SPARC_LSINFO_OP_FETCH) { ! 1674: ! 1675: /* make an instruction_access_MMU_miss trap, which updates the ! 1676: IMMU tag access register: */ ! 1677: trap = TME_STP103X_TRAP_fast_instruction_access_MMU_miss; ! 1678: updates ! 1679: = (TME_STP103X_UPDATE_IMMU ! 1680: + TME_STP103X_UPDATE_MMU_TAG_ACCESS); ! 1681: } ! 1682: ! 1683: /* otherwise, this is not an instruction fetch: */ ! 1684: else { ! 1685: ! 1686: /* make a data_access_MMU_miss trap, which updates the DMMU tag ! 1687: access: */ ! 1688: trap = TME_STP103X_TRAP_fast_data_access_MMU_miss; ! 1689: updates ! 1690: = (TME_STP103X_UPDATE_DMMU ! 1691: + TME_STP103X_UPDATE_MMU_TAG_ACCESS); ! 1692: } ! 1693: } ! 1694: ! 1695: /* otherwise, if this is a data access protection fault: */ ! 1696: else if (ls_faults & TME_STP103X_LS_FAULT_PROTECTION) { ! 1697: ! 1698: /* make a fast_data_access_protection trap, which updates the ! 1699: DMMU SFSR, SFAR, and tag access register: */ ! 1700: trap = TME_STP103X_TRAP_fast_data_access_protection; ! 1701: updates ! 1702: = (TME_STP103X_UPDATE_DMMU ! 1703: + TME_STP103X_UPDATE_MMU_SFSR ! 1704: + TME_STP103X_UPDATE_DMMU_SFAR ! 1705: + TME_STP103X_UPDATE_MMU_TAG_ACCESS); ! 1706: } ! 1707: ! 1708: /* otherwise, this must be an access error fault: */ ! 1709: else { ! 1710: assert (ls_faults & TME_SPARC_LS_FAULT_BUS_ERROR); ! 1711: ! 1712: /* get the asynchronous fault status register bit for this ! 1713: fault: */ ! 1714: /* NB: we assume that all bus errors are timeouts: */ ! 1715: afsr = TME_STP103X_AFSR_TO; ! 1716: ! 1717: /* if no same or higher-priority asynchronous fault has already ! 1718: happened: */ ! 1719: if ((TME_STP103X(ic)->tme_stp103x_afsr ! 1720: & (TME_STP103X_AFSR_ME - afsr)) == 0) { ! 1721: ! 1722: /* update the asynchronous fault address register: */ ! 1723: assert (ls->tme_sparc_ls_tlb->tme_sparc_tlb_addr_shift == 0); ! 1724: TME_STP103X(ic)->tme_stp103x_afar ! 1725: = ((ls->tme_sparc_ls_address64 ! 1726: + (tme_uint64_t) ls->tme_sparc_ls_tlb->tme_sparc_tlb_addr_offset) ! 1727: & (0 - (tme_uint64_t) (1 << 4))); ! 1728: } ! 1729: ! 1730: /* update the asynchronous fault status register: */ ! 1731: TME_STP103X(ic)->tme_stp103x_afsr ! 1732: |= (((TME_STP103X(ic)->tme_stp103x_afsr ! 1733: & afsr) ! 1734: ? TME_STP103X_AFSR_ME ! 1735: : !TME_STP103X_AFSR_ME) ! 1736: + (TME_SPARC_PRIV(ic) ! 1737: ? TME_STP103X_AFSR_PRIV ! 1738: : !TME_STP103X_AFSR_PRIV)); ! 1739: ! 1740: /* if noncacheable errors are not enabled: */ ! 1741: if ((TME_STP103X(ic)->tme_stp103x_estate_error_enable & TME_STP103X_ESTATE_ERROR_ENABLE_NCEEN) == 0) { ! 1742: ! 1743: /* clear the fault: */ ! 1744: ls->tme_sparc_ls_faults = TME_SPARC_LS_FAULT_NONE; ! 1745: ! 1746: /* if this is a load: */ ! 1747: if (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_LD) { ! 1748: ! 1749: /* force all bytes read to be all-bits-one by filling the ! 1750: entire memory buffer with all-bits-one: */ ! 1751: /* NB: we do this even though earlier parts of the load may ! 1752: have succeeded, to keep things simple. we assume that ! 1753: nothing depends on partially successful loads: */ ! 1754: memset (ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer8s, ! 1755: 0xff, ! 1756: sizeof(ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer8s)); ! 1757: } ! 1758: ! 1759: /* stop this load or store: */ ! 1760: /* NB: we do this even though later parts of the load or store ! 1761: may succeed, to keep things simple. we assume that nothing ! 1762: depends on partially successful loads or stores: */ ! 1763: /* NB: we don't set TME_SPARC_LSINFO_LD_COMPLETED because we are ! 1764: only stopping the load or store here, not completing it. we ! 1765: still let the original load instruction function complete the ! 1766: load from the memory buffer: */ ! 1767: ls->tme_sparc_ls_size = 0; ! 1768: ! 1769: /* make no trap: */ ! 1770: trap = TME_SPARC_TRAP_none; ! 1771: } ! 1772: ! 1773: /* otherwise, if this is an instruction fetch: */ ! 1774: else if (lsinfo & TME_SPARC_LSINFO_OP_FETCH) { ! 1775: ! 1776: /* make an instruction_access_error trap: */ ! 1777: trap = TME_SPARC64_TRAP_instruction_access_error; ! 1778: } ! 1779: ! 1780: /* otherwise, this is not an instruction fetch: */ ! 1781: else { ! 1782: ! 1783: /* make a data_access_error trap: */ ! 1784: trap = TME_SPARC64_TRAP_data_access_error; ! 1785: } ! 1786: ! 1787: /* this trap doesn't update any other state: */ ! 1788: updates = TME_STP103X_UPDATE_NONE; ! 1789: } ! 1790: ! 1791: /* get the virtual address, forced to be in range: */ ! 1792: address = ls->tme_sparc_ls_address64; ! 1793: address |= (0 - (TME_STP103X_VA_HOLE_START * 2)); ! 1794: address = (address ^ TME_STP103X_VA_HOLE_START) + TME_STP103X_VA_HOLE_START; ! 1795: ! 1796: /* if this trap updates the DMMU SFAR: */ ! 1797: if (updates & TME_STP103X_UPDATE_DMMU_SFAR) { ! 1798: TME_STP103X(ic)->tme_stp103x_dmmu_sfar = address; ! 1799: } ! 1800: ! 1801: /* assume that this trap updates the IMMU: */ ! 1802: mmu = &TME_STP103X(ic)->tme_stp103x_immu; ! 1803: ! 1804: /* if this trap updates the DMMU: */ ! 1805: if ((updates ! 1806: & (TME_STP103X_UPDATE_DMMU ! 1807: | TME_STP103X_UPDATE_IMMU)) ! 1808: != TME_STP103X_UPDATE_IMMU) { ! 1809: ! 1810: /* assume that this trap updates the DMMU SFSR and define ! 1811: SFSR.E: */ ! 1812: if (ls->tme_sparc_ls_tlb->tme_sparc_tlb_asi_mask ! 1813: & TME_SPARC64_ASI_MASK_FLAG_TLB_SIDE_EFFECTS) { ! 1814: sfsr += TME_STP103X_SFSR_E; ! 1815: } ! 1816: ! 1817: /* update the common DMMU state: */ ! 1818: mmu = &TME_STP103X(ic)->tme_stp103x_dmmu; ! 1819: } ! 1820: ! 1821: /* get the ASI mask from the instruction: */ ! 1822: asi_mask = ls->tme_sparc_ls_asi_mask; ! 1823: ! 1824: /* if this trap updates the DMMU or IMMU tag access register: */ ! 1825: if (updates & TME_STP103X_UPDATE_MMU_TAG_ACCESS) { ! 1826: ! 1827: /* update the tag access: */ ! 1828: mmu->tme_stp103x_mmu_tag_access ! 1829: = ((address ! 1830: & (0 - (tme_uint64_t) (TME_STP103X_CONTEXT_MAX + 1))) ! 1831: + ((asi_mask & TME_SPARC64_ASI_MASK_FLAG_SPECIAL) ! 1832: ? 0 ! 1833: : ls->tme_sparc_ls_context)); ! 1834: } ! 1835: ! 1836: /* if this trap updates the DMMU or IMMU SFSR: */ ! 1837: if (updates & TME_STP103X_UPDATE_MMU_SFSR) { ! 1838: ! 1839: /* define SFSR.ASI: */ ! 1840: TME_FIELD_MASK_DEPOSITU(sfsr, ! 1841: TME_STP103X_SFSR_ASI, ! 1842: TME_SPARC_ASI_MASK_WHICH(asi_mask)); ! 1843: ! 1844: /* define SFSR.CT: */ ! 1845: sfsr ! 1846: += ((asi_mask & TME_SPARC64_ASI_MASK_FLAG_SPECIAL) ! 1847: ? TME_STP103X_SFSR_CT_RESERVED ! 1848: : (asi_mask & TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS) ! 1849: ? TME_STP103X_SFSR_CT_NUCLEUS ! 1850: : (asi_mask & TME_SPARC64_ASI_FLAG_SECONDARY) ! 1851: ? TME_STP103X_SFSR_CT_SECONDARY ! 1852: : TME_STP103X_SFSR_CT_PRIMARY); ! 1853: ! 1854: /* define SFSR.PR: */ ! 1855: if (TME_SPARC_PRIV(ic)) { ! 1856: sfsr += TME_STP103X_SFSR_PR; ! 1857: } ! 1858: ! 1859: /* define SFSR.W: */ ! 1860: if (lsinfo ! 1861: & (TME_SPARC_LSINFO_OP_ST ! 1862: | TME_SPARC_LSINFO_OP_ATOMIC)) { ! 1863: sfsr += TME_STP103X_SFSR_W; ! 1864: } ! 1865: ! 1866: /* define SFSR.FV: */ ! 1867: sfsr += TME_STP103X_SFSR_FV; ! 1868: ! 1869: /* define SFSR.OW: */ ! 1870: if (mmu->tme_stp103x_mmu_sfsr & TME_STP103X_SFSR_FV) { ! 1871: sfsr += TME_STP103X_SFSR_OW; ! 1872: } ! 1873: ! 1874: /* update the DMMU or IMMU SFSR: */ ! 1875: mmu->tme_stp103x_mmu_sfsr = sfsr; ! 1876: } ! 1877: ! 1878: /* if there is a trap: */ ! 1879: if (__tme_predict_true(trap != TME_SPARC_TRAP_none)) { ! 1880: ! 1881: /* trap: */ ! 1882: tme_sparc64_trap(ic, trap); ! 1883: } ! 1884: } ! 1885: ! 1886: /* this checks that the virtual address of a load/store is in range. ! 1887: if it is out of range and ic is non-NULL, it traps immediately: */ ! 1888: static tme_uint64_t ! 1889: _tme_stp103x_ls_address_check(struct tme_sparc *ic, ! 1890: struct tme_sparc_ls *ls) ! 1891: { ! 1892: tme_uint64_t address; ! 1893: tme_uint32_t address_32_63; ! 1894: ! 1895: /* get bits 32..63 of the address: */ ! 1896: address = ls->tme_sparc_ls_address64; ! 1897: address_32_63 = address >> 32; ! 1898: ! 1899: /* if this address is in the address space hole: */ ! 1900: if (__tme_predict_false((address_32_63 + (tme_uint32_t) (TME_STP103X_VA_HOLE_START >> 32)) ! 1901: >= (tme_uint32_t) ((TME_STP103X_VA_HOLE_START * 2) >> 32))) { ! 1902: ! 1903: /* note the fault: */ ! 1904: ls->tme_sparc_ls_faults |= TME_SPARC64_LS_FAULT_VA_RANGE; ! 1905: ! 1906: /* if we can, trap now: */ ! 1907: if (ic != NULL) { ! 1908: _tme_stp103x_ls_trap(ic, ls); ! 1909: abort(); ! 1910: /* NOTREACHED */ ! 1911: } ! 1912: } ! 1913: ! 1914: /* return the address: */ ! 1915: return (address); ! 1916: } ! 1917: ! 1918: /* this maps a virtual address directly into a physical address: */ ! 1919: static void ! 1920: _tme_stp103x_ls_address_map_phys(struct tme_sparc *ic, ! 1921: struct tme_sparc_ls *ls) ! 1922: { ! 1923: tme_uint64_t address; ! 1924: tme_uint32_t asi; ! 1925: tme_uint32_t asi_mask; ! 1926: ! 1927: /* check the address: */ ! 1928: address = _tme_stp103x_ls_address_check(ic, ls); ! 1929: ! 1930: /* get the original ASI: */ ! 1931: asi = TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask); ! 1932: ! 1933: /* all of the bypass ASIs behave as if the P bit were clear: */ ! 1934: asi_mask ! 1935: = (TME_SPARC64_ASI_MASK_PRIV ! 1936: + TME_SPARC64_ASI_MASK_USER); ! 1937: ! 1938: /* ASIs 0x15 and 0x1d behave as if the E bit were set and the CP bit ! 1939: were clear: */ ! 1940: if (asi & 1) { ! 1941: asi_mask ! 1942: += (TME_SPARC64_ASI_MASK_FLAG_TLB_SIDE_EFFECTS ! 1943: + TME_SPARC64_ASI_MASK_FLAG_TLB_UNCACHEABLE); ! 1944: } ! 1945: ! 1946: /* update the flags on the TLB entry: */ ! 1947: ls->tme_sparc_ls_tlb->tme_sparc_tlb_asi_mask ! 1948: |= asi_mask; ! 1949: ! 1950: /* do the truncating mapping: */ ! 1951: address &= (0 - (tme_uint64_t) TME_STP103X_PAGE_SIZE_8KB); ! 1952: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_first = address; ! 1953: address |= (TME_STP103X_PAGE_SIZE_8KB - 1); ! 1954: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_last = address; ! 1955: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_cycles_ok = (TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE); ! 1956: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_offset ! 1957: = ((address % TME_STP103X_PA_SIZE) ! 1958: - address); ! 1959: } ! 1960: ! 1961: /* this maps a virtual address: */ ! 1962: static void ! 1963: _tme_stp103x_ls_address_map(struct tme_sparc *ic, ! 1964: struct tme_sparc_ls *ls) ! 1965: { ! 1966: tme_uint64_t address; ! 1967: tme_uint32_t lsu_0_31; ! 1968: signed long tlb_part_i; ! 1969: tme_uint32_t tlb_tag_match_0_31; ! 1970: tme_uint32_t tlb_tag_match_32_63; ! 1971: tme_uint32_t tlb_tag_xor_0_31; ! 1972: tme_uint32_t tlb_data_32_63; ! 1973: tme_uint32_t size; ! 1974: tme_uint32_t tlb_data_0_31; ! 1975: struct tme_sparc_tlb *tlb; ! 1976: tme_uint32_t asi_mask; ! 1977: tme_uint32_t cycles_ok; ! 1978: ! 1979: /* check the address: */ ! 1980: address = _tme_stp103x_ls_address_check(ic, ls); ! 1981: ! 1982: /* get bits 0..31 of the load/store unit control register: */ ! 1983: lsu_0_31 = TME_STP103X(ic)->tme_stp103x_lsu; ! 1984: ! 1985: /* assume that this is not an instruction fetch, and start at the ! 1986: beginning of the DMMU TLB entries: */ ! 1987: tlb_part_i = TME_STP103X_TLB_PART_0_DMMU; ! 1988: ! 1989: /* if this is an instruction fetch: */ ! 1990: if (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_FETCH) { ! 1991: ! 1992: /* assume that LSU.IM is set, and set LSU.DM to indicate an ! 1993: enabled IMMU (!): */ ! 1994: lsu_0_31 |= TME_STP103X_LSU_DM; ! 1995: ! 1996: /* if the IMMU is disabled, or if the CPU is in RED_state: */ ! 1997: if (__tme_predict_false((lsu_0_31 & TME_STP103X_LSU_IM) == 0 ! 1998: || (ic->tme_sparc64_ireg_pstate & TME_SPARC64_PSTATE_RED))) { ! 1999: ! 2000: /* clear LSU.DM, to indicate a disabled IMMU (!): */ ! 2001: lsu_0_31 &= ~TME_STP103X_LSU_DM; ! 2002: } ! 2003: ! 2004: /* start at the beginning of the IMMU TLB entries: */ ! 2005: tlb_part_i = TME_STP103X_TLB_PART_0_IMMU; ! 2006: } ! 2007: ! 2008: /* if the MMU is disabled: */ ! 2009: if (__tme_predict_false((lsu_0_31 & TME_STP103X_LSU_DM) == 0)) { ! 2010: ! 2011: /* a disabled MMU behaves as if the E bit were set, and the P and ! 2012: CP bits were clear: */ ! 2013: ls->tme_sparc_ls_tlb->tme_sparc_tlb_asi_mask ! 2014: |= (TME_SPARC64_ASI_MASK_PRIV ! 2015: + TME_SPARC64_ASI_MASK_USER ! 2016: + TME_SPARC64_ASI_MASK_FLAG_TLB_SIDE_EFFECTS ! 2017: + TME_SPARC64_ASI_MASK_FLAG_TLB_UNCACHEABLE); ! 2018: ! 2019: /* do the truncating mapping: */ ! 2020: address &= (0 - (tme_uint64_t) TME_STP103X_PAGE_SIZE_8KB); ! 2021: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_first = address; ! 2022: address |= (TME_STP103X_PAGE_SIZE_8KB - 1); ! 2023: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_last = address; ! 2024: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_cycles_ok = (TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE); ! 2025: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_offset ! 2026: = ((address % TME_STP103X_PA_SIZE) ! 2027: - address); ! 2028: return; ! 2029: } ! 2030: ! 2031: /* make the tag to match: */ ! 2032: tlb_tag_match_32_63 = (address >> 32); ! 2033: tlb_tag_match_0_31 = address; ! 2034: tlb_tag_match_0_31 &= ~TME_STP103X_CONTEXT_MAX; ! 2035: tlb_tag_match_0_31 += ls->tme_sparc_ls_context; ! 2036: ! 2037: /* loop over TLB entries: */ ! 2038: do { ! 2039: ! 2040: /* if bits 32..63 of the tag match: */ ! 2041: if (TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 0), 1) == tlb_tag_match_32_63) { ! 2042: ! 2043: /* if bits 22..31 of the tag match: */ ! 2044: tlb_tag_xor_0_31 = TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 0), 0) ^ tlb_tag_match_0_31; ! 2045: if (tlb_tag_xor_0_31 < TME_STP103X_PAGE_SIZE_4MB) { ! 2046: ! 2047: /* load bits 32..63 of the data: */ ! 2048: tlb_data_32_63 = TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 1); ! 2049: ! 2050: /* if the data is valid: */ ! 2051: if (tlb_data_32_63 & TME_STP103X_TLB_DATA_V(tlb_data_32_63)) { ! 2052: ! 2053: /* get the size of this mapping: */ ! 2054: size ! 2055: = (TME_STP103X_PAGE_SIZE_8KB ! 2056: << (3 * TME_FIELD_MASK_EXTRACTU(tlb_data_32_63, ! 2057: TME_STP103X_TLB_DATA_SIZE_MASK(tlb_data_32_63)))); ! 2058: ! 2059: /* load bits 0..31 of the data: */ ! 2060: tlb_data_0_31 = TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 0); ! 2061: ! 2062: /* if bits 0..31 of the tag match: */ ! 2063: if ((tlb_tag_xor_0_31 ! 2064: & ((0 - size) ! 2065: + ((tlb_data_0_31 ! 2066: & TME_STP103X_TLB_DATA_G(tlb_data_0_31)) ! 2067: ? 0 ! 2068: : TME_STP103X_CONTEXT_MAX))) == 0) { ! 2069: ! 2070: /* set the used bit: */ ! 2071: tlb_data_32_63 |= TME_STP103X_TLB_DATA_DIAG_USED(tlb_data_32_63); ! 2072: TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 1) = tlb_data_32_63; ! 2073: ! 2074: /* get the sparc TLB entry: */ ! 2075: tlb = ls->tme_sparc_ls_tlb; ! 2076: ! 2077: /* if this is a global mapping, update the TLB context: */ ! 2078: if (tlb_data_0_31 & TME_STP103X_TLB_DATA_G(tlb_data_0_31)) { ! 2079: tlb->tme_sparc_tlb_context = TME_STP103X_CONTEXT_MAX + 1; ! 2080: } ! 2081: ! 2082: /* link the TLB entries: */ ! 2083: tlb->tme_sparc_tlb_link = tlb_part_i; ! 2084: ! 2085: /* start the address offset for this mapping: */ ! 2086: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_offset ! 2087: = ((tlb_data_0_31 ! 2088: & (tme_uint32_t) TME_STP103X_TLB_DATA_PA) ! 2089: + (((tme_uint64_t) ! 2090: (tlb_data_32_63 ! 2091: & (tme_uint32_t) (TME_STP103X_TLB_DATA_PA >> 32))) ! 2092: << 32)); ! 2093: ! 2094: /* copy the E, !CP, IE, and NFO bits into the TLB entry's ! 2095: ASI mask. we predict for the common case, which has CP ! 2096: set and all of the other bits clear: */ ! 2097: /* NB: we ignore the CV bit, because it's always zero in ! 2098: the IMMU, and in the DMMU it doesn't count as ! 2099: uncacheable as far as atomic instructions are ! 2100: concerned: */ ! 2101: if (__tme_predict_false((tlb_data_0_31 ! 2102: & (TME_STP103X_TLB_DATA_E(tlb_data_0_31) ! 2103: | TME_STP103X_TLB_DATA_CP(tlb_data_0_31))) ! 2104: != TME_STP103X_TLB_DATA_CP(tlb_data_0_31))) { ! 2105: asi_mask = 0; ! 2106: if (tlb_data_0_31 & TME_STP103X_TLB_DATA_E(tlb_data_0_31)) { ! 2107: asi_mask += TME_SPARC64_ASI_MASK_FLAG_TLB_SIDE_EFFECTS; ! 2108: } ! 2109: if ((tlb_data_0_31 & TME_STP103X_TLB_DATA_CP(tlb_data_0_31)) == 0) { ! 2110: asi_mask += TME_SPARC64_ASI_MASK_FLAG_TLB_UNCACHEABLE; ! 2111: } ! 2112: } ! 2113: else { ! 2114: asi_mask = 0; ! 2115: } ! 2116: if (__tme_predict_false(tlb_data_32_63 ! 2117: & (TME_STP103X_TLB_DATA_NFO(tlb_data_32_63) ! 2118: | TME_STP103X_TLB_DATA_IE(tlb_data_32_63)))) { ! 2119: if (tlb_data_32_63 & TME_STP103X_TLB_DATA_NFO(tlb_data_32_63)) { ! 2120: asi_mask += TME_SPARC64_ASI_FLAG_NO_FAULT; ! 2121: } ! 2122: if (tlb_data_32_63 & TME_STP103X_TLB_DATA_IE(tlb_data_32_63)) { ! 2123: asi_mask += TME_SPARC64_ASI_FLAG_LITTLE; ! 2124: } ! 2125: } ! 2126: ! 2127: /* if this mapping is privileged: */ ! 2128: if (tlb_data_0_31 & TME_STP103X_TLB_DATA_P(tlb_data_0_31)) { ! 2129: ! 2130: /* if this access is not privileged: */ ! 2131: if (__tme_predict_false(!TME_SPARC_PRIV(ic))) { ! 2132: ! 2133: /* trap: */ ! 2134: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_PRIVILEGE; ! 2135: _tme_stp103x_ls_trap(ic, ls); ! 2136: assert (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_NO_FAULT); ! 2137: return; ! 2138: } ! 2139: } ! 2140: ! 2141: /* otherwise, this mapping is not privileged: */ ! 2142: else { ! 2143: ! 2144: /* this TLB entry can be used for privileged and nonprivileged ! 2145: accesses: */ ! 2146: asi_mask ! 2147: += (TME_SPARC64_ASI_MASK_PRIV ! 2148: + TME_SPARC64_ASI_MASK_USER); ! 2149: } ! 2150: ! 2151: /* update the TLB entry's ASI mask: */ ! 2152: ls->tme_sparc_ls_tlb->tme_sparc_tlb_asi_mask |= asi_mask; ! 2153: ! 2154: /* if this page is writable: */ ! 2155: if (tlb_data_0_31 & TME_STP103X_TLB_DATA_W(tlb_data_0_31)) { ! 2156: ! 2157: /* this mapping can be read and written: */ ! 2158: cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE; ! 2159: } ! 2160: ! 2161: /* otherwise, this page is not writable: */ ! 2162: else { ! 2163: ! 2164: /* if this is a store or an atomic: */ ! 2165: if (__tme_predict_false(ls->tme_sparc_ls_lsinfo ! 2166: & (TME_SPARC_LSINFO_OP_ST ! 2167: | TME_SPARC_LSINFO_OP_ATOMIC))) { ! 2168: ! 2169: /* remember if this is a 64KB page: */ ! 2170: TME_STP103X(ic)->tme_stp103x_dmmu_direct_64KB = (size == TME_STP103X_PAGE_SIZE_64KB); ! 2171: ! 2172: /* trap: */ ! 2173: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_PROTECTION; ! 2174: _tme_stp103x_ls_trap(ic, ls); ! 2175: abort(); ! 2176: /* NOTREACHED */ ! 2177: } ! 2178: ! 2179: /* this mapping can only be read: */ ! 2180: cycles_ok = TME_BUS_CYCLE_READ; ! 2181: } ! 2182: ! 2183: /* set the cycles for this mapping: */ ! 2184: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_cycles_ok = cycles_ok; ! 2185: ! 2186: /* set the first and last addresses for this mapping: */ ! 2187: address = ls->tme_sparc_ls_address64; ! 2188: address |= (size - 1); ! 2189: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_last = address; ! 2190: address &= (0 - (tme_uint64_t) size); ! 2191: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_first = address; ! 2192: ! 2193: /* finish the address offset for this mapping: */ ! 2194: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_offset -= address; ! 2195: ! 2196: return; ! 2197: } ! 2198: } ! 2199: } ! 2200: } ! 2201: ! 2202: tlb_part_i += 2; ! 2203: } while (tlb_part_i % (2 * TME_STP103X_TLB_SIZE)); ! 2204: ! 2205: /* this is a miss: */ ! 2206: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_MMU_MISS; ! 2207: _tme_stp103x_ls_trap(ic, ls); ! 2208: assert (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_NO_FAULT); ! 2209: } ! 2210: ! 2211: /* the ASI handler for ASI_PHYS_USE_EC*, ASI_PHYS_BYPASS_EC_WITH_EBIT*: */ ! 2212: static void ! 2213: _tme_stp103x_ls_asi_phys(struct tme_sparc *ic, struct tme_sparc_ls *ls) ! 2214: { ! 2215: ! 2216: /* override the address map function: */ ! 2217: ls->tme_sparc_ls_address_map = _tme_stp103x_ls_address_map_phys; ! 2218: } ! 2219: ! 2220: /* the cycle handler for ASI_NUCLEUS_QUAD_LDD*: */ ! 2221: static void ! 2222: _tme_stp103x_ls_cycle_quad(struct tme_sparc *ic, struct tme_sparc_ls *ls) ! 2223: { ! 2224: struct tme_sparc_tlb *tlb; ! 2225: tme_uint32_t asi_mask; ! 2226: _tme_const tme_shared tme_uint8_t *memory; ! 2227: #if !TME_THREADS_COOPERATIVE ! 2228: #ifdef tme_memory_atomic_read128 ! 2229: tme_uint128_t quad; ! 2230: #endif /* tme_memory_atomic_read128 */ ! 2231: #endif /* !TME_THREADS_COOPERATIVE */ ! 2232: tme_uint64_t quad_64lo; ! 2233: tme_uint64_t quad_64hi; ! 2234: tme_uint64_t *_rd; ! 2235: ! 2236: /* get the TLB entry: */ ! 2237: tlb = ls->tme_sparc_ls_tlb; ! 2238: ! 2239: /* get the ASI mask: */ ! 2240: asi_mask = tlb->tme_sparc_tlb_asi_mask; ! 2241: ! 2242: /* this TLB entry must be for cacheable memory: */ ! 2243: if (__tme_predict_false(asi_mask ! 2244: & TME_SPARC64_ASI_MASK_FLAG_TLB_UNCACHEABLE)) { ! 2245: ! 2246: /* we must have caught this on the first cycle: */ ! 2247: assert (ls->tme_sparc_ls_buffer_offset == 0); ! 2248: ! 2249: /* fault: */ ! 2250: ls->tme_sparc_ls_faults |= TME_SPARC64_LS_FAULT_UNCACHEABLE; ! 2251: return; ! 2252: } ! 2253: ! 2254: /* assume that we can't do a fast transfer: */ ! 2255: memory = TME_EMULATOR_OFF_UNDEF; ! 2256: ! 2257: /* if this is the first cycle: */ ! 2258: if (ls->tme_sparc_ls_buffer_offset == 0) { ! 2259: ! 2260: /* if this TLB entry allows fast transfer of all of the addresses: */ ! 2261: if (__tme_predict_true((((tme_bus_addr64_t) tlb->tme_sparc_tlb_addr_last) ! 2262: - ls->tme_sparc_ls_address64) ! 2263: >= ((sizeof(tme_uint64_t) * 2) - 1))) { ! 2264: ! 2265: /* we may be able do a fast transfer: */ ! 2266: memory = tlb->tme_sparc_tlb_emulator_off_read; ! 2267: } ! 2268: } ! 2269: ! 2270: /* if we can't do a fast transfer: */ ! 2271: if (__tme_predict_false(memory == TME_EMULATOR_OFF_UNDEF)) { ! 2272: ! 2273: /* do a slow cycle: */ ! 2274: tme_sparc64_load(ic, ls); ! 2275: ! 2276: /* if this was not the last cycle, return now: */ ! 2277: if (ls->tme_sparc_ls_size != 0) { ! 2278: return; ! 2279: } ! 2280: ! 2281: /* fake a fast transfer from the memory buffer: */ ! 2282: memory = &ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer8s[0]; ! 2283: memory -= ls->tme_sparc_ls_address64; ! 2284: } ! 2285: ! 2286: /* finish the memory address: */ ! 2287: memory += ls->tme_sparc_ls_address64; ! 2288: ! 2289: /* if threads are cooperative: */ ! 2290: #if TME_THREADS_COOPERATIVE ! 2291: ! 2292: /* do two 64-bit loads: */ ! 2293: quad_64lo ! 2294: = tme_memory_bus_read64(((_tme_const tme_shared tme_uint64_t *) memory) + 0, ! 2295: tlb->tme_sparc_tlb_bus_rwlock, ! 2296: (sizeof(tme_uint64_t) * 2), ! 2297: sizeof(tme_uint64_t)); ! 2298: quad_64hi ! 2299: = tme_memory_bus_read64(((_tme_const tme_shared tme_uint64_t *) memory) + 1, ! 2300: tlb->tme_sparc_tlb_bus_rwlock, ! 2301: (sizeof(tme_uint64_t) * 1), ! 2302: sizeof(tme_uint64_t)); ! 2303: ! 2304: /* otherwise, threads are not cooperative: */ ! 2305: #else /* !TME_THREADS_COOPERATIVE */ ! 2306: ! 2307: /* if host supports an atomic 128-bit read: */ ! 2308: #ifdef tme_memory_atomic_read128 ! 2309: ! 2310: /* do the atomic 128-bit read: */ ! 2311: quad ! 2312: = tme_memory_atomic_read128((_tme_const tme_shared tme_uint128_t *) memory, ! 2313: tlb->tme_sparc_tlb_bus_rwlock, ! 2314: sizeof(tme_uint128_t)); ! 2315: ! 2316: /* get the two parts of the load: */ ! 2317: #if TME_ENDIAN_NATIVE == TME_ENDIAN_BIG ! 2318: quad_64lo = quad >> 64; ! 2319: quad_64hi = quad; ! 2320: #elif TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE ! 2321: quad_64lo = quad; ! 2322: quad_64hi = quad >> 64; ! 2323: #endif ! 2324: #else /* !tme_memory_atomic_read128 */ ! 2325: #error "non-cooperative threads requires an atomic 128-bit read" ! 2326: #endif /* !tme_memory_atomic_read128 */ ! 2327: #endif /* !TME_THREADS_COOPERATIVE */ ! 2328: ! 2329: /* swap the two 64-bit values as needed: */ ! 2330: if (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_ENDIAN_LITTLE) { ! 2331: quad_64lo = tme_letoh_u64(quad_64lo); ! 2332: quad_64hi = tme_letoh_u64(quad_64hi); ! 2333: } ! 2334: else { ! 2335: quad_64lo = tme_betoh_u64(quad_64lo); ! 2336: quad_64hi = tme_betoh_u64(quad_64hi); ! 2337: } ! 2338: ! 2339: /* complete the load: */ ! 2340: ls->tme_sparc_ls_size = 0; ! 2341: _rd = ls->tme_sparc_ls_rd64; ! 2342: TME_SPARC_FORMAT3_RD = quad_64lo; ! 2343: TME_SPARC_FORMAT3_RD_ODD(tme_ic_ireg_uint64) = quad_64hi; ! 2344: } ! 2345: ! 2346: /* the ASI handler for ASI_NUCLEUS_QUAD_LDD*: */ ! 2347: static void ! 2348: _tme_stp103x_ls_asi_quad(struct tme_sparc *ic, struct tme_sparc_ls *ls) ! 2349: { ! 2350: ! 2351: /* we need to do the complete load: */ ! 2352: ls->tme_sparc_ls_size = sizeof(tme_uint64_t) * 2; ! 2353: ls->tme_sparc_ls_buffer_offset = 0; ! 2354: ls->tme_sparc_ls_lsinfo ! 2355: |= (TME_SPARC_LSINFO_SLOW_CYCLES ! 2356: + TME_SPARC_LSINFO_LD_COMPLETED); ! 2357: ls->tme_sparc_ls_cycle = _tme_stp103x_ls_cycle_quad; ! 2358: ! 2359: /* an instruction other than ldda is illegal: */ ! 2360: if (__tme_predict_false((ic->_tme_sparc_insn ! 2361: & (0x3f << 19)) ! 2362: != (0x13 << 19))) { ! 2363: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL; ! 2364: } ! 2365: ! 2366: /* the address must be 128-bit aligned: */ ! 2367: if (__tme_predict_false(((tme_uint32_t) ls->tme_sparc_ls_address64) ! 2368: % (sizeof(tme_uint64_t) * 2))) { ! 2369: ls->tme_sparc_ls_faults |= TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED; ! 2370: } ! 2371: } ! 2372: ! 2373: /* the ASI handler for various infrequently-used ASIs: */ ! 2374: static void ! 2375: _tme_stp103x_ls_asi_slow(struct tme_sparc *ic, struct tme_sparc_ls *ls) ! 2376: { ! 2377: tme_uint32_t lsinfo_ops; ! 2378: int size_ok; ! 2379: int address_ok; ! 2380: tme_uint64_t value_mask; ! 2381: void (*update_write) _TME_P((struct tme_sparc *, tme_uint64_t)); ! 2382: int redispatch; ! 2383: tme_uint64_t *_value64; ! 2384: tme_uint32_t *_value32; ! 2385: tme_uint64_t value; ! 2386: tme_uint64_t value_now; ! 2387: ! 2388: /* assume that this ASI allows reads and writes: */ ! 2389: lsinfo_ops ! 2390: = (TME_SPARC_LSINFO_OP_LD ! 2391: | TME_SPARC_LSINFO_OP_ST); ! 2392: ! 2393: /* assume that this ASI allows only 64-bit accesses: */ ! 2394: size_ok = (ls->tme_sparc_ls_size == sizeof(tme_uint64_t)); ! 2395: ! 2396: /* assume that this ASI allows only accesses to address zero: */ ! 2397: address_ok = (ls->tme_sparc_ls_address64 == 0); ! 2398: ! 2399: /* assume that this ASI doesn't mask values written: */ ! 2400: value_mask = 0 - (tme_uint64_t) 1; ! 2401: ! 2402: /* assume that this ASI has no write side-effects: */ ! 2403: update_write = NULL; ! 2404: ! 2405: /* assume that a write won't need a redispatch: */ ! 2406: redispatch = FALSE; ! 2407: ! 2408: /* assume that the access is invalid: */ ! 2409: _value64 = NULL; ! 2410: _value32 = NULL; ! 2411: ! 2412: /* dispatch on the ASI: */ ! 2413: switch (TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask)) { ! 2414: ! 2415: /* all unknown ASIs: */ ! 2416: default: ! 2417: address_ok = FALSE; ! 2418: break; ! 2419: ! 2420: case TME_STP103X_ASI_LSU_CONTROL_REG: ! 2421: _value64 = &TME_STP103X(ic)->tme_stp103x_lsu; ! 2422: update_write = _tme_stp103x_update_lsu; ! 2423: break; ! 2424: ! 2425: case TME_STP103X_ASI_INTR_DISPATCH_STATUS: ! 2426: lsinfo_ops = TME_SPARC_LSINFO_OP_LD; ! 2427: /* XXX FIXME WRITEME: */ ! 2428: abort(); ! 2429: break; ! 2430: ! 2431: case TME_STP103X_ASI_INTR_RECEIVE: ! 2432: value_now ! 2433: = ((tme_memory_atomic_read_flag(&TME_STP103X(ic)->tme_stp103x_intr_receive_busy) ! 2434: ? TME_STP103X_INTR_RECEIVE_BUSY ! 2435: : 0) ! 2436: + TME_STP103X(ic)->tme_stp103x_intr_receive_mid); ! 2437: _value64 = &value_now; ! 2438: update_write = _tme_stp103x_update_intr_receive; ! 2439: break; ! 2440: ! 2441: case TME_STP103X_ASI_UPA_CONFIG_REG: ! 2442: _value64 = &TME_STP103X(ic)->tme_stp103x_upa_config; ! 2443: update_write = _tme_stp103x_update_upa_config; ! 2444: break; ! 2445: ! 2446: case TME_STP103X_ASI_ESTATE_ERROR_EN_REG: ! 2447: _value32 = &TME_STP103X(ic)->tme_stp103x_estate_error_enable; ! 2448: value_mask ! 2449: = (TME_STP103X_ESTATE_ERROR_ENABLE_CEEN ! 2450: | TME_STP103X_ESTATE_ERROR_ENABLE_NCEEN ! 2451: | TME_STP103X_ESTATE_ERROR_ENABLE_ISAPEN); ! 2452: break; ! 2453: ! 2454: case TME_STP103X_ASI_AFSR: ! 2455: _value64 = &TME_STP103X(ic)->tme_stp103x_afsr; ! 2456: update_write = _tme_stp103x_update_afsr; ! 2457: break; ! 2458: ! 2459: case TME_STP103X_ASI_AFAR: ! 2460: _value64 = &TME_STP103X(ic)->tme_stp103x_afar; ! 2461: value_mask = TME_STP103X_PA_SIZE - (1 << 4); ! 2462: break; ! 2463: ! 2464: case TME_STP103X_ASI_ECACHE_TAG_DATA: ! 2465: _value32 = &TME_STP103X(ic)->tme_stp103x_ecache_tag_data; ! 2466: break; ! 2467: } ! 2468: ! 2469: /* check the access: */ ! 2470: if (__tme_predict_false((ls->tme_sparc_ls_lsinfo & lsinfo_ops) == 0 ! 2471: || !size_ok ! 2472: || !address_ok)) { ! 2473: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL; ! 2474: } ! 2475: ! 2476: /* if there are any faults: */ ! 2477: if (__tme_predict_false(ls->tme_sparc_ls_faults |= TME_SPARC_LS_FAULT_NONE)) { ! 2478: return; ! 2479: } ! 2480: ! 2481: /* get the raw value to read or write: */ ! 2482: value ! 2483: = ((ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_ST) ! 2484: ? *ls->tme_sparc_ls_rd64 ! 2485: : _value64 != NULL ! 2486: ? *_value64 ! 2487: : *_value32); ! 2488: ! 2489: /* mask the value: */ ! 2490: value &= value_mask; ! 2491: ! 2492: /* complete the load or store: */ ! 2493: ls->tme_sparc_ls_size = 0; ! 2494: ! 2495: /* if this is a load: */ ! 2496: if (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_LD) { ! 2497: ! 2498: /* complete the load: */ ! 2499: *ls->tme_sparc_ls_rd64 = value; ! 2500: ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_LD_COMPLETED; ! 2501: } ! 2502: ! 2503: /* otherwise, this is a store: */ ! 2504: else { ! 2505: ! 2506: /* if this value has write side-effects: */ ! 2507: if (update_write != NULL) { ! 2508: ! 2509: /* do the write side-effects: */ ! 2510: (*update_write)(ic, value); ! 2511: } ! 2512: ! 2513: /* otherwise, this value has no write side-effects: */ ! 2514: else { ! 2515: ! 2516: /* complete the store: */ ! 2517: if (_value64 != NULL) { ! 2518: *_value64 = value; ! 2519: } ! 2520: else { ! 2521: *_value32 = value; ! 2522: } ! 2523: } ! 2524: ! 2525: /* if this store needs a redispatch: */ ! 2526: if (redispatch) { ! 2527: tme_bus_tlb_unbusy(&ic->tme_sparc_tlbs[ls->tme_sparc_ls_tlb_i].tme_sparc_tlb_bus_tlb); ! 2528: tme_sparc_redispatch(ic); ! 2529: } ! 2530: } ! 2531: } ! 2532: ! 2533: /* the ASI handler for ASI_DMMU and ASI_IMMU: */ ! 2534: static void ! 2535: _tme_stp103x_ls_asi_mmu(struct tme_sparc *ic, struct tme_sparc_ls *ls) ! 2536: { ! 2537: tme_uint64_t address; ! 2538: tme_uint32_t address_0_31; ! 2539: struct tme_stp103x_mmu *mmu; ! 2540: tme_uint32_t lsinfo; ! 2541: tme_uint64_t tag_target; ! 2542: tme_uint32_t context; ! 2543: tme_uint64_t *_value64; ! 2544: tme_uint32_t *_value32; ! 2545: int value_has_va; ! 2546: tme_uint64_t value_mask; ! 2547: tme_uint32_t lsinfo_ops; ! 2548: int redispatch; ! 2549: tme_uint64_t value; ! 2550: ! 2551: /* if this is a 64-bit access that hasn't faulted yet: */ ! 2552: if (__tme_predict_true(ls->tme_sparc_ls_size == sizeof(tme_uint64_t) ! 2553: && ls->tme_sparc_ls_faults == TME_SPARC_LS_FAULT_NONE)) { ! 2554: ! 2555: /* get the address: */ ! 2556: address = ls->tme_sparc_ls_address64; ! 2557: ! 2558: /* if the address fits into 32 bits: */ ! 2559: if (__tme_predict_true((address & (0 - (((tme_uint64_t) 1) << 32))) == 0)) { ! 2560: ! 2561: /* truncate the address to 32 bits: */ ! 2562: address_0_31 = address; ! 2563: ! 2564: /* get the MMU state: */ ! 2565: mmu ! 2566: = (TME_STP103X_ASI_MMU_MASK_IS_DMMU(ls->tme_sparc_ls_asi_mask) ! 2567: ? &TME_STP103X(ic)->tme_stp103x_dmmu ! 2568: : &TME_STP103X(ic)->tme_stp103x_immu); ! 2569: ! 2570: /* get the load/store information: */ ! 2571: lsinfo = ls->tme_sparc_ls_lsinfo; ! 2572: ! 2573: /* address 0x0 is the tag target register: */ ! 2574: if (address_0_31 == 0) { ! 2575: ! 2576: /* if this is a load: */ ! 2577: if (lsinfo & TME_SPARC_LSINFO_OP_LD) { ! 2578: ! 2579: /* make the value for the tag target register: */ ! 2580: tag_target = mmu->tme_stp103x_mmu_tag_access; ! 2581: context = ((tme_uint32_t) tag_target) & TME_STP103X_CONTEXT_MAX; ! 2582: tag_target >>= 22; ! 2583: tag_target |= ((tme_uint64_t) (context << (48 - 32))) << 32; ! 2584: ! 2585: /* complete the load: */ ! 2586: *ls->tme_sparc_ls_rd64 = tag_target; ! 2587: ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_LD_COMPLETED; ! 2588: ls->tme_sparc_ls_size = 0; ! 2589: return; ! 2590: } ! 2591: } ! 2592: ! 2593: else { ! 2594: ! 2595: /* assume that the register is invalid: */ ! 2596: _value64 = NULL; ! 2597: _value32 = NULL; ! 2598: ! 2599: /* assume that values for this register aren't virtual ! 2600: addresses, and don't have any masked bits: */ ! 2601: value_has_va = FALSE; ! 2602: value_mask = 0 - (tme_uint64_t) 1; ! 2603: ! 2604: /* assume that this register allows reads and writes: */ ! 2605: lsinfo_ops ! 2606: = (TME_SPARC_LSINFO_OP_LD ! 2607: | TME_SPARC_LSINFO_OP_ST); ! 2608: ! 2609: /* assume that a write to this register won't need a redispatch: */ ! 2610: redispatch = FALSE; ! 2611: ! 2612: /* address 0x18 is the synchronous fault status register: */ ! 2613: if (address_0_31 == 0x18) { ! 2614: _value64 = &mmu->tme_stp103x_mmu_sfsr; ! 2615: } ! 2616: ! 2617: /* address 0x28 is the TSB register: */ ! 2618: else if (address_0_31 == 0x28) { ! 2619: _value64 = &mmu->tme_stp103x_mmu_tsb; ! 2620: value_has_va = TRUE; ! 2621: } ! 2622: ! 2623: /* address 0x30 is the tag access register: */ ! 2624: else if (address_0_31 == 0x30) { ! 2625: _value64 = &mmu->tme_stp103x_mmu_tag_access; ! 2626: value_has_va = TRUE; ! 2627: } ! 2628: ! 2629: /* if this is ASI_DMMU: */ ! 2630: else if (mmu == &TME_STP103X(ic)->tme_stp103x_dmmu) { ! 2631: ! 2632: /* address 0x8 is the primary context register: */ ! 2633: if (address_0_31 == 0x8) { ! 2634: _value32 = &ic->tme_sparc_memory_context_primary; ! 2635: value_mask = TME_STP103X_CONTEXT_MAX; ! 2636: redispatch = TRUE; ! 2637: } ! 2638: ! 2639: /* address 0x10 is the secondary context register: */ ! 2640: else if (address_0_31 == 0x10) { ! 2641: _value32 = &ic->tme_sparc_memory_context_secondary; ! 2642: value_mask = TME_STP103X_CONTEXT_MAX; ! 2643: } ! 2644: ! 2645: /* address 0x20 is the synchronous fault address register: */ ! 2646: else if (address_0_31 == 0x20) { ! 2647: _value64 = &TME_STP103X(ic)->tme_stp103x_dmmu_sfar; ! 2648: lsinfo_ops = TME_SPARC_LSINFO_OP_LD; ! 2649: } ! 2650: ! 2651: /* address 0x38 is the VA Data Watchpoint register: */ ! 2652: else if (address_0_31 == 0x38) { ! 2653: abort(); ! 2654: } ! 2655: ! 2656: /* address 0x40 is the PA Data Watchpoint register: */ ! 2657: else if (address_0_31 == 0x38) { ! 2658: abort(); ! 2659: } ! 2660: } ! 2661: ! 2662: /* if the register valid and supports this access: */ ! 2663: if (__tme_predict_true((_value64 != NULL ! 2664: || _value32 != NULL) ! 2665: && (lsinfo & lsinfo_ops) != 0)) { ! 2666: ! 2667: /* get the raw value to read or write: */ ! 2668: value ! 2669: = (lsinfo & TME_SPARC_LSINFO_OP_ST ! 2670: ? *ls->tme_sparc_ls_rd64 ! 2671: : _value64 != NULL ! 2672: ? *_value64 ! 2673: : *_value32); ! 2674: ! 2675: /* if this value has a virtual address: */ ! 2676: if (value_has_va) { ! 2677: ! 2678: /* force the virtual address to be in range: */ ! 2679: value |= (0 - (TME_STP103X_VA_HOLE_START * 2)); ! 2680: value = (value ^ TME_STP103X_VA_HOLE_START) + TME_STP103X_VA_HOLE_START; ! 2681: } ! 2682: ! 2683: /* mask the value: */ ! 2684: value &= value_mask; ! 2685: ! 2686: /* if this is a load: */ ! 2687: if (lsinfo & TME_SPARC_LSINFO_OP_LD) { ! 2688: ! 2689: /* complete the load: */ ! 2690: *ls->tme_sparc_ls_rd64 = value; ! 2691: ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_LD_COMPLETED; ! 2692: } ! 2693: ! 2694: /* otherwise, this is a store: */ ! 2695: else { ! 2696: ! 2697: /* complete the store: */ ! 2698: if (_value64 != NULL) { ! 2699: *_value64 = value; ! 2700: } ! 2701: else { ! 2702: *_value32 = value; ! 2703: } ! 2704: ! 2705: /* if this store needs a redispatch: */ ! 2706: if (redispatch) { ! 2707: tme_bus_tlb_unbusy(&ic->tme_sparc_tlbs[ls->tme_sparc_ls_tlb_i].tme_sparc_tlb_bus_tlb); ! 2708: tme_sparc_redispatch(ic); ! 2709: } ! 2710: } ! 2711: ! 2712: /* complete the load or store: */ ! 2713: ls->tme_sparc_ls_size = 0; ! 2714: return; ! 2715: } ! 2716: } ! 2717: } ! 2718: } ! 2719: ! 2720: /* this is an illegal access: */ ! 2721: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL; ! 2722: } ! 2723: ! 2724: /* the ASI handler for: ! 2725: ASI_DMMU_TSB_8KB_PTR_REG, ASI_DMMU_TSB_64KB_PTR_REG, ! 2726: ASI_IMMU_TSB_8KB_PTR_REG, ASI_IMMU_TSB_64KB_PTR_REG, ! 2727: ASI_DMMU_TSB_DIRECT_PTR_REG: */ ! 2728: static void ! 2729: _tme_stp103x_ls_asi_tsb_ptr(struct tme_sparc *ic, struct tme_sparc_ls *ls) ! 2730: { ! 2731: tme_uint32_t asi_mask; ! 2732: struct tme_stp103x_mmu *mmu; ! 2733: tme_uint32_t pointer_0_31; ! 2734: tme_uint32_t size_64KB; ! 2735: tme_uint32_t tsb_0_31; ! 2736: tme_uint32_t tsb_size; ! 2737: ! 2738: /* if this is not a 64-bit load of address zero: */ ! 2739: if (__tme_predict_false(ls->tme_sparc_ls_size != sizeof(tme_uint64_t) ! 2740: || (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_LD) == 0 ! 2741: || ls->tme_sparc_ls_address64 != 0)) { ! 2742: ! 2743: /* this is an illegal access: */ ! 2744: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL; ! 2745: } ! 2746: ! 2747: /* if this access has faulted: */ ! 2748: if (__tme_predict_false(ls->tme_sparc_ls_faults != TME_SPARC_LS_FAULT_NONE)) { ! 2749: return; ! 2750: } ! 2751: ! 2752: /* get the ASI mask from the instruction: */ ! 2753: asi_mask = ls->tme_sparc_ls_asi_mask; ! 2754: ! 2755: /* get the common MMU state: */ ! 2756: mmu ! 2757: = (TME_STP103X_ASI_MMU_MASK_IS_DMMU(asi_mask) ! 2758: ? &TME_STP103X(ic)->tme_stp103x_dmmu ! 2759: : &TME_STP103X(ic)->tme_stp103x_immu); ! 2760: ! 2761: /* start the TSB pointer with the tag access register: */ ! 2762: pointer_0_31 = mmu->tme_stp103x_mmu_tag_access; ! 2763: ! 2764: /* if this might be a 64KB page: */ ! 2765: size_64KB = asi_mask & TME_SPARC_ASI_MASK_RAW(TME_STP103X_ASI_FLAG_TSB_64KB_PTR); ! 2766: if (size_64KB) { ! 2767: ! 2768: /* if this is ASI_DMMU_TSB_DIRECT_PTR_REG: */ ! 2769: if (asi_mask & TME_SPARC_ASI_MASK_RAW(TME_STP103X_ASI_FLAG_TSB_8KB_PTR)) { ! 2770: ! 2771: /* this is a 64KB page if the last fast_data_access_protection ! 2772: trap was for a 64KB page: */ ! 2773: size_64KB = TME_STP103X(ic)->tme_stp103x_dmmu_direct_64KB; ! 2774: } ! 2775: ! 2776: /* if this is a 64KB page, shift the TSB pointer: */ ! 2777: if (size_64KB) { ! 2778: pointer_0_31 /= (TME_STP103X_PAGE_SIZE_64KB / TME_STP103X_PAGE_SIZE_8KB); ! 2779: } ! 2780: } ! 2781: ! 2782: /* shift the tag access register in the TSB pointer down to index a ! 2783: 16-byte TSB entry: */ ! 2784: pointer_0_31 = (pointer_0_31 / (TME_STP103X_PAGE_SIZE_8KB / 16)) & (0 - (tme_uint32_t) 16); ! 2785: ! 2786: /* get bits 0..31 of the TSB register: */ ! 2787: tsb_0_31 = mmu->tme_stp103x_mmu_tsb; ! 2788: ! 2789: /* get the size of (one half of) the TSB: */ ! 2790: tsb_size = TME_STP103X_PAGE_SIZE_8KB; ! 2791: tsb_size <<= (tsb_0_31 & TME_STP103X_TSB_SIZE); ! 2792: ! 2793: /* finish the offset of the entry in (one half of) the TSB: */ ! 2794: pointer_0_31 &= (tsb_size - 1); ! 2795: ! 2796: /* if this is a split TSB: */ ! 2797: if (tsb_0_31 & TME_STP103X_TSB_SPLIT) { ! 2798: ! 2799: /* if this is a 64KB page, select the other half of the TSB: */ ! 2800: if (size_64KB) { ! 2801: pointer_0_31 += tsb_size; ! 2802: } ! 2803: ! 2804: /* the TSB is actually two halves: */ ! 2805: tsb_size *= 2; ! 2806: } ! 2807: ! 2808: /* finish bits 0..31 of the TSB pointer: */ ! 2809: pointer_0_31 += (tsb_0_31 & (0 - tsb_size)); ! 2810: ! 2811: /* complete the load: */ ! 2812: *ls->tme_sparc_ls_rd64 ! 2813: = ((mmu->tme_stp103x_mmu_tsb ! 2814: & (0 - (((tme_uint64_t) 1) << 32))) ! 2815: | pointer_0_31); ! 2816: ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_LD_COMPLETED; ! 2817: ls->tme_sparc_ls_size = 0; ! 2818: } ! 2819: ! 2820: /* the ASI handler for ASI_ITLB_DATA_IN_REG, ASI_DTLB_DATA_IN_REG: */ ! 2821: static void ! 2822: _tme_stp103x_ls_asi_tlb_data_in(struct tme_sparc *ic, struct tme_sparc_ls *ls) ! 2823: { ! 2824: signed long tlb_part_i; ! 2825: signed long tlb_part_i_invalid; ! 2826: signed long tlb_part_i_unlocked; ! 2827: signed long tlb_part_i_unlocked_unused; ! 2828: tme_uint32_t tlb_data_32_63; ! 2829: ! 2830: /* if this is not a 64-bit store of address zero: */ ! 2831: if (__tme_predict_false(ls->tme_sparc_ls_size != sizeof(tme_uint64_t) ! 2832: || (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_ST) == 0 ! 2833: || ls->tme_sparc_ls_address64 != 0)) { ! 2834: ! 2835: /* this is an illegal access: */ ! 2836: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL; ! 2837: } ! 2838: ! 2839: /* if this access has faulted: */ ! 2840: if (__tme_predict_false(ls->tme_sparc_ls_faults != TME_SPARC_LS_FAULT_NONE)) { ! 2841: return; ! 2842: } ! 2843: ! 2844: /* if this is ASI_DTLB_DATA_IN_REG, start at the last entry of the ! 2845: DTLB, otherwise start at the last entry of the ITLB: */ ! 2846: tlb_part_i ! 2847: = (TME_STP103X_ASI_MMU_MASK_IS_DMMU(ls->tme_sparc_ls_asi_mask) ! 2848: ? TME_STP103X_TLB_PART_0_DMMU + (TME_STP103X_TLB_SIZE * 2) - 2 ! 2849: : TME_STP103X_TLB_PART_0_IMMU + (TME_STP103X_TLB_SIZE * 2) - 2); ! 2850: ! 2851: /* search for invalid, unlocked, and unlocked+unused TLB entries: */ ! 2852: tlb_part_i_invalid = -1; ! 2853: tlb_part_i_unlocked = -1; ! 2854: tlb_part_i_unlocked_unused = -1; ! 2855: for (;;) { ! 2856: ! 2857: /* load bits 32..63 of the TLB entry's data: */ ! 2858: tlb_data_32_63 = TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 1); ! 2859: ! 2860: /* if this TLB entry is invalid: */ ! 2861: if ((tlb_data_32_63 & TME_STP103X_TLB_DATA_V(tlb_data_32_63)) == 0) { ! 2862: ! 2863: /* track the lowest-numbered invalid TLB entry: */ ! 2864: tlb_part_i_invalid = tlb_part_i; ! 2865: } ! 2866: ! 2867: /* if this TLB entry is not locked: */ ! 2868: if ((TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 0) ! 2869: & TME_STP103X_TLB_DATA_L((tme_uint32_t) 0)) == 0) { ! 2870: ! 2871: /* track the lowest-numbered unlocked TLB entry: */ ! 2872: tlb_part_i_unlocked = tlb_part_i; ! 2873: ! 2874: /* if the TLB entry's used bit is clear: */ ! 2875: if ((tlb_data_32_63 & TME_STP103X_TLB_DATA_DIAG_USED(tlb_data_32_63)) == 0) { ! 2876: ! 2877: /* track the lowest-numbered unlocked and unused TLB entry: */ ! 2878: tlb_part_i_unlocked_unused = tlb_part_i; ! 2879: } ! 2880: } ! 2881: ! 2882: /* if we have not exhausted the TLB: */ ! 2883: if (tlb_part_i % (TME_STP103X_TLB_SIZE * 2)) { ! 2884: tlb_part_i -= 2; ! 2885: continue; ! 2886: } ! 2887: ! 2888: /* if there is an invalid TLB entry: */ ! 2889: if (tlb_part_i_invalid >= 0) { ! 2890: tlb_part_i = tlb_part_i_invalid; ! 2891: break; ! 2892: } ! 2893: ! 2894: /* otherwise, if there is an unlocked and unused TLB entry: */ ! 2895: if (tlb_part_i_unlocked_unused >= 0) { ! 2896: tlb_part_i = tlb_part_i_unlocked_unused; ! 2897: } ! 2898: ! 2899: /* otherwise, there is no invalid TLB entry and no unlocked and ! 2900: unused TLB entry: */ ! 2901: else { ! 2902: ! 2903: /* clear the used bits on all TLB entries: */ ! 2904: do { ! 2905: TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 1) ! 2906: &= ~TME_STP103X_TLB_DATA_DIAG_USED(tlb_data_32_63); ! 2907: tlb_part_i += 2; ! 2908: } while (tlb_part_i % (TME_STP103X_TLB_SIZE * 2)); ! 2909: ! 2910: /* there must be an unlocked TLB entry: */ ! 2911: assert (tlb_part_i_unlocked >= 0); ! 2912: tlb_part_i = tlb_part_i_unlocked; ! 2913: } ! 2914: ! 2915: /* invalidate this TLB entry: */ ! 2916: _tme_stp103x_tlb_invalidate(ic, tlb_part_i); ! 2917: break; ! 2918: } ! 2919: ! 2920: /* complete the store: */ ! 2921: #if TME_STP103X_TLB_PART_0_DMMU >= TME_STP103X_TLB_PART_0_IMMU ! 2922: #error "TME_STP103X_TLB_PART_0_DMMU or TME_STP103X_TLB_PART_0_IMMU changed" ! 2923: #endif ! 2924: TME_STP103X(ic)->tme_stp103x_tlb_64s(tlb_part_i + 0) ! 2925: = (tlb_part_i < TME_STP103X_TLB_PART_0_IMMU ! 2926: ? &TME_STP103X(ic)->tme_stp103x_dmmu ! 2927: : &TME_STP103X(ic)->tme_stp103x_immu)->tme_stp103x_mmu_tag_access; ! 2928: TME_STP103X(ic)->tme_stp103x_tlb_64s(tlb_part_i + 1) = *ls->tme_sparc_ls_rd64; ! 2929: ls->tme_sparc_ls_size = 0; ! 2930: } ! 2931: ! 2932: /* ASI_ITLB_DATA_ACCESS_REG, ASI_DTLB_DATA_ACCESS_REG: */ ! 2933: static void ! 2934: _tme_stp103x_ls_asi_tlb_data_access(struct tme_sparc *ic, struct tme_sparc_ls *ls) ! 2935: { ! 2936: unsigned long tlb_part_i; ! 2937: tme_uint64_t *_tag_access; ! 2938: ! 2939: /* XXX FIXME WRITEME table 6-11 hints that it's possible to do a ! 2940: casxa to DTLB_DATA_ACCESS_REG. also see the WRITEME in ! 2941: _tme_stp103x_ls_trap(): */ ! 2942: assert ((ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_ATOMIC) == 0); ! 2943: ! 2944: /* if this is not a 64-bit load or store: */ ! 2945: if (__tme_predict_false(ls->tme_sparc_ls_size != sizeof(tme_uint64_t) ! 2946: || (ls->tme_sparc_ls_lsinfo ! 2947: & (TME_SPARC_LSINFO_OP_LD ! 2948: | TME_SPARC_LSINFO_OP_ST)) == 0)) { ! 2949: ! 2950: /* this is an illegal access: */ ! 2951: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL; ! 2952: } ! 2953: ! 2954: /* if this access has faulted: */ ! 2955: if (__tme_predict_false(ls->tme_sparc_ls_faults != TME_SPARC_LS_FAULT_NONE)) { ! 2956: return; ! 2957: } ! 2958: ! 2959: /* get the addressed TLB entry and common MMU state: */ ! 2960: tlb_part_i = ls->tme_sparc_ls_address64; ! 2961: tlb_part_i %= TME_STP103X_TLB_SIZE * sizeof(tme_uint64_t); ! 2962: tlb_part_i /= (sizeof(tme_uint64_t) / 2); ! 2963: tlb_part_i += TME_STP103X_TLB_PART_0_DMMU; ! 2964: _tag_access = &TME_STP103X(ic)->tme_stp103x_dmmu.tme_stp103x_mmu_tag_access; ! 2965: if (!TME_STP103X_ASI_MMU_MASK_IS_DMMU(ls->tme_sparc_ls_asi_mask)) { ! 2966: tlb_part_i = (tlb_part_i - TME_STP103X_TLB_PART_0_DMMU) + TME_STP103X_TLB_PART_0_IMMU; ! 2967: _tag_access = &TME_STP103X(ic)->tme_stp103x_immu.tme_stp103x_mmu_tag_access; ! 2968: } ! 2969: ! 2970: /* if this is a load: */ ! 2971: if (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_LD) { ! 2972: ! 2973: /* complete the load: */ ! 2974: *ls->tme_sparc_ls_rd64 = TME_STP103X(ic)->tme_stp103x_tlb_64s(tlb_part_i + 1); ! 2975: ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_LD_COMPLETED; ! 2976: } ! 2977: ! 2978: /* otherwise, this is a store: */ ! 2979: else { ! 2980: ! 2981: /* if the TLB entry is valid: */ ! 2982: if (TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 1) ! 2983: & TME_STP103X_TLB_DATA_V((tme_uint32_t) 0)) { ! 2984: ! 2985: /* invalidate this TLB entry: */ ! 2986: _tme_stp103x_tlb_invalidate(ic, ! 2987: tlb_part_i); ! 2988: } ! 2989: ! 2990: /* complete the store: */ ! 2991: TME_STP103X(ic)->tme_stp103x_tlb_64s(tlb_part_i + 0) = *_tag_access; ! 2992: TME_STP103X(ic)->tme_stp103x_tlb_64s(tlb_part_i + 1) = *ls->tme_sparc_ls_rd64; ! 2993: } ! 2994: ! 2995: /* we completed the load or store: */ ! 2996: ls->tme_sparc_ls_size = 0; ! 2997: } ! 2998: ! 2999: /* the ASI handler for ASI_ITLB_TAG_READ_REG, ASI_DTLB_TAG_READ_REG: */ ! 3000: static void ! 3001: _tme_stp103x_ls_asi_tlb_tag_read(struct tme_sparc *ic, struct tme_sparc_ls *ls) ! 3002: { ! 3003: unsigned long tlb_part_i; ! 3004: ! 3005: /* if this is not a 64-bit load: */ ! 3006: if (__tme_predict_false(ls->tme_sparc_ls_size != sizeof(tme_uint64_t) ! 3007: || (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_LD) == 0)) { ! 3008: ! 3009: /* this is an illegal access: */ ! 3010: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL; ! 3011: } ! 3012: ! 3013: /* if this access has faulted: */ ! 3014: if (__tme_predict_false(ls->tme_sparc_ls_faults != TME_SPARC_LS_FAULT_NONE)) { ! 3015: return; ! 3016: } ! 3017: ! 3018: /* get the addressed TLB entry and common MMU state: */ ! 3019: tlb_part_i = ls->tme_sparc_ls_address64; ! 3020: tlb_part_i %= TME_STP103X_TLB_SIZE * sizeof(tme_uint64_t); ! 3021: tlb_part_i /= (sizeof(tme_uint64_t) / 2); ! 3022: tlb_part_i += TME_STP103X_TLB_PART_0_DMMU; ! 3023: if (!TME_STP103X_ASI_MMU_MASK_IS_DMMU(ls->tme_sparc_ls_asi_mask)) { ! 3024: tlb_part_i = (tlb_part_i - TME_STP103X_TLB_PART_0_DMMU) + TME_STP103X_TLB_PART_0_IMMU; ! 3025: } ! 3026: ! 3027: /* complete the load: */ ! 3028: *ls->tme_sparc_ls_rd64 = TME_STP103X(ic)->tme_stp103x_tlb_64s(tlb_part_i + 0); ! 3029: ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_LD_COMPLETED; ! 3030: ls->tme_sparc_ls_size = 0; ! 3031: } ! 3032: ! 3033: /* the ASI handler for ASI_IMMU_DEMAP, ASI_DMMU_DEMAP: */ ! 3034: static void ! 3035: _tme_stp103x_ls_asi_mmu_demap(struct tme_sparc *ic, struct tme_sparc_ls *ls) ! 3036: { ! 3037: tme_uint64_t address; ! 3038: tme_uint32_t tlb_tag_match_32_63; ! 3039: tme_uint32_t tlb_tag_match_0_31; ! 3040: tme_uint32_t context; ! 3041: tme_uint32_t tlb_tag_mask32; ! 3042: unsigned long tlb_part_i; ! 3043: tme_uint32_t tlb_tag_xor_32_63; ! 3044: tme_uint32_t tlb_data_0_31; ! 3045: tme_uint32_t tlb_tag_xor_0_31; ! 3046: tme_uint32_t tlb_data_32_63; ! 3047: tme_uint32_t size; ! 3048: ! 3049: /* if this is not a 64-bit store: */ ! 3050: if (__tme_predict_false(ls->tme_sparc_ls_size != sizeof(tme_uint64_t) ! 3051: || (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_ST) == 0)) { ! 3052: ! 3053: /* this is an illegal access: */ ! 3054: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL; ! 3055: } ! 3056: ! 3057: /* check the address: */ ! 3058: address = _tme_stp103x_ls_address_check(NULL, ls); ! 3059: tlb_tag_match_32_63 = address >> 32; ! 3060: tlb_tag_match_0_31 = address; ! 3061: ! 3062: /* if this access has faulted: */ ! 3063: if (__tme_predict_false(ls->tme_sparc_ls_faults != TME_SPARC_LS_FAULT_NONE)) { ! 3064: return; ! 3065: } ! 3066: ! 3067: /* we will complete this store: */ ! 3068: ls->tme_sparc_ls_size = 0; ! 3069: ! 3070: /* assume that this demap uses the primary context: */ ! 3071: context = ic->tme_sparc_memory_context_primary; ! 3072: ! 3073: /* if this demap might use the secondary context: */ ! 3074: if (tlb_tag_match_0_31 & TME_BIT(4)) { ! 3075: context = ic->tme_sparc_memory_context_secondary; ! 3076: } ! 3077: ! 3078: /* if this demap uses the nucleus context: */ ! 3079: if (tlb_tag_match_0_31 & TME_BIT(5)) { ! 3080: context = 0; ! 3081: ! 3082: /* "Use of the reserved value causes the demap to be ignored" */ ! 3083: if (tlb_tag_match_0_31 & TME_BIT(4)) { ! 3084: return; ! 3085: } ! 3086: } ! 3087: ! 3088: /* if this is a demap page, we must match the VA part of a tag. if ! 3089: this is a demap context, we must ignore the VA part of a tag: */ ! 3090: tlb_tag_mask32 = 0 - (tme_uint32_t) ((tlb_tag_match_0_31 & TME_BIT(6)) == 0); ! 3091: ! 3092: /* finish the tag to match: */ ! 3093: tlb_tag_match_0_31 &= ~TME_STP103X_CONTEXT_MAX; ! 3094: tlb_tag_match_0_31 += context; ! 3095: ! 3096: /* if this is ASI_DMMU_DEMAP, start at the first entry of the DTLB, ! 3097: otherwise start at the first entry of the ITLB: */ ! 3098: tlb_part_i ! 3099: = (TME_STP103X_ASI_MMU_MASK_IS_DMMU(ls->tme_sparc_ls_asi_mask) ! 3100: ? TME_STP103X_TLB_PART_0_DMMU ! 3101: : TME_STP103X_TLB_PART_0_IMMU); ! 3102: ! 3103: /* loop over the TLB entries: */ ! 3104: do { ! 3105: ! 3106: /* if bits 32..63 of the tag match: */ ! 3107: tlb_tag_xor_32_63 = TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 0), 1) ^ tlb_tag_match_32_63; ! 3108: if ((tlb_tag_xor_32_63 & tlb_tag_mask32) == 0) { ! 3109: ! 3110: /* load bits 0..31 of the data: */ ! 3111: tlb_data_0_31 = TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 0); ! 3112: ! 3113: /* exclusive-OR bits 0..31 of the tag with bits 0..31 of the tag ! 3114: to match: */ ! 3115: tlb_tag_xor_0_31 = TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 0), 0) ^ tlb_tag_match_0_31; ! 3116: ! 3117: /* if this is a global entry: */ ! 3118: if (tlb_data_0_31 & TME_STP103X_TLB_DATA_G(tlb_data_0_31)) { ! 3119: ! 3120: /* assume that this is a demap page, which can match a global ! 3121: page, and force a match of the context field of the tag: */ ! 3122: tlb_tag_xor_0_31 &= ~TME_STP103X_CONTEXT_MAX; ! 3123: ! 3124: /* if this a demap context: */ ! 3125: if (tlb_tag_mask32 == 0) { ! 3126: ! 3127: /* a demap context never matches a global page. force a ! 3128: mismatch of the context field of the tag: */ ! 3129: tlb_tag_xor_0_31 += 1; ! 3130: } ! 3131: } ! 3132: ! 3133: /* load bits 32..63 of the data: */ ! 3134: tlb_data_32_63 = TME_STP103X(ic)->tme_stp103x_tlb_32s((tlb_part_i + 1), 1); ! 3135: ! 3136: /* if this TLB entry is valid: */ ! 3137: if (tlb_data_32_63 & TME_STP103X_TLB_DATA_V(tlb_data_32_63)) { ! 3138: ! 3139: /* get the size of this mapping: */ ! 3140: size ! 3141: = (TME_STP103X_PAGE_SIZE_8KB ! 3142: << (3 * TME_FIELD_MASK_EXTRACTU(tlb_data_32_63, ! 3143: TME_STP103X_TLB_DATA_SIZE_MASK(tlb_data_32_63)))); ! 3144: ! 3145: /* if bits 0..31 of the tag match: */ ! 3146: if ((tlb_tag_xor_0_31 ! 3147: & (((0 - size) ! 3148: & tlb_tag_mask32) ! 3149: + TME_STP103X_CONTEXT_MAX)) == 0) { ! 3150: ! 3151: /* invalidate this TLB entry: */ ! 3152: _tme_stp103x_tlb_invalidate(ic, tlb_part_i); ! 3153: } ! 3154: } ! 3155: } ! 3156: ! 3157: tlb_part_i += 2; ! 3158: } while (tlb_part_i % (2 * TME_STP103X_TLB_SIZE)); ! 3159: } ! 3160: ! 3161: /* the ASI handler for ASI_ECACHE_W and ASI_ECACHE_R: */ ! 3162: static void ! 3163: _tme_stp103x_ls_asi_ecache(struct tme_sparc *ic, struct tme_sparc_ls *ls) ! 3164: { ! 3165: tme_uint64_t address; ! 3166: tme_uint32_t address_0_31; ! 3167: tme_uint32_t address_32_63; ! 3168: unsigned int ecache_what; ! 3169: int is_write; ! 3170: ! 3171: /* get the address: */ ! 3172: address = ls->tme_sparc_ls_address64; ! 3173: address_32_63 = (address >> 32); ! 3174: address_0_31 = address; ! 3175: ! 3176: /* see if this is an E-Cache data access, or a tag/state/parity ! 3177: access: */ ! 3178: ecache_what = (address_32_63 >> (39 - 32)) & 0x3; ! 3179: ! 3180: /* truncate the E-Cache address to the cache size, and 64-bit align ! 3181: it: */ ! 3182: address_0_31 &= (TME_STP103X_ECACHE_SIZE - sizeof(tme_uint64_t)); ! 3183: ! 3184: /* see if this is ASI_ECACHE_W or ASI_ECACHE_R: */ ! 3185: is_write = (TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask) == 0x76); ! 3186: assert (is_write || TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask) == 0x7e); ! 3187: ! 3188: /* check the access: */ ! 3189: if (__tme_predict_false((ls->tme_sparc_ls_lsinfo ! 3190: & (is_write ! 3191: ? TME_SPARC_LSINFO_OP_ST ! 3192: : TME_SPARC_LSINFO_OP_LD)) == 0 ! 3193: || ls->tme_sparc_ls_size != sizeof(tme_uint64_t) ! 3194: || (ecache_what != 0x1 ! 3195: && ecache_what != 0x2))) { ! 3196: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL; ! 3197: } ! 3198: ! 3199: /* if the access has faulted: */ ! 3200: if (__tme_predict_false(ls->tme_sparc_ls_faults != TME_SPARC_LS_FAULT_NONE)) { ! 3201: return; ! 3202: } ! 3203: ! 3204: /* if this is a data access: */ ! 3205: if (ecache_what == 0x1) { ! 3206: ! 3207: /* the PROM probes the size of the E-Cache by writing power-of-two ! 3208: sizes to those same addresses in the E-Cache, from high sizes ! 3209: to low sizes. then it reads address zero to see the last size ! 3210: that got truncated to address zero. we don't emulate the ! 3211: E-Cache, but we do emulate a single line at address zero, so we ! 3212: appear to the probe as having the smallest E-Cache size ! 3213: (512KB): */ ! 3214: #if TME_STP103X_ECACHE_SIZE != (512 * 1024) ! 3215: #error "TME_STP103X_ECACHE_SIZE changed" ! 3216: #endif ! 3217: if (address_0_31 == 0) { ! 3218: if (is_write) { ! 3219: TME_STP103X(ic)->tme_stp103x_ecache_data_probe = *ls->tme_sparc_ls_rd64; ! 3220: } ! 3221: else { ! 3222: *ls->tme_sparc_ls_rd64 = TME_STP103X(ic)->tme_stp103x_ecache_data_probe; ! 3223: } ! 3224: } ! 3225: else { ! 3226: abort(); ! 3227: } ! 3228: } ! 3229: ! 3230: /* otherwise, this must be a tag access: */ ! 3231: else { ! 3232: assert (ecache_what == 0x2); ! 3233: ! 3234: /* the PROM initializes all tags in the E-Cache. we don't emulate ! 3235: the E-Cache, but we do support initializing any tag: */ ! 3236: if (is_write ! 3237: && ((TME_STP103X(ic)->tme_stp103x_ecache_tag_data % (2 << 28)) ! 3238: == (0x00000 /* a EC_tag of zero */ ! 3239: + (0x0 << 22) /* an EC_state of Invalid */ ! 3240: + (0xf << 25)))) { /* correct odd EC_parity */ ! 3241: /* nothing to do */ ! 3242: } ! 3243: else { ! 3244: abort(); ! 3245: } ! 3246: } ! 3247: ! 3248: /* complete the load or store: */ ! 3249: if (!is_write) { ! 3250: ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_LD_COMPLETED; ! 3251: } ! 3252: ls->tme_sparc_ls_size = 0; ! 3253: } ! 3254: ! 3255: /* the ASI handler for ASI_DCACHE_DATA and ASI_DCACHE_TAG: */ ! 3256: static void ! 3257: _tme_stp103x_ls_asi_dcache(struct tme_sparc *ic, struct tme_sparc_ls *ls) ! 3258: { ! 3259: tme_uint32_t address_0_31; ! 3260: tme_uint64_t value; ! 3261: ! 3262: /* get the address: */ ! 3263: address_0_31 = ls->tme_sparc_ls_address64 % (16 * 1024); ! 3264: ! 3265: /* check the access: */ ! 3266: if (__tme_predict_false((ls->tme_sparc_ls_lsinfo ! 3267: & (TME_SPARC_LSINFO_OP_ST ! 3268: | TME_SPARC_LSINFO_OP_LD)) == 0 ! 3269: || ls->tme_sparc_ls_size != sizeof(tme_uint64_t))) { ! 3270: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL; ! 3271: } ! 3272: ! 3273: /* if the access has faulted: */ ! 3274: if (__tme_predict_false(ls->tme_sparc_ls_faults != TME_SPARC_LS_FAULT_NONE)) { ! 3275: return; ! 3276: } ! 3277: ! 3278: /* if this is a store: */ ! 3279: if (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_ST) { ! 3280: ! 3281: /* get the value being stored: */ ! 3282: value = *ls->tme_sparc_ls_rd64; ! 3283: ! 3284: /* we support writing zeros to tags - the PROM does this to ! 3285: initialize all tags in the D-cache, and kernels do this to ! 3286: flush the D-cache: */ ! 3287: if (__tme_predict_true(TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask) == TME_STP103X_ASI_DCACHE_TAG ! 3288: && value == 0)) { ! 3289: ! 3290: /* complete this store: */ ! 3291: ls->tme_sparc_ls_size = 0; ! 3292: return; ! 3293: } ! 3294: ! 3295: /* soon after POR, the PROM writes 0xdeadbeef to address zero in ! 3296: both ASI_DCACHE_DATA and ASI_DCACHE_TAG. we support these ! 3297: writes: */ ! 3298: if (address_0_31 == 0 ! 3299: && value == 0xdeadbeef) { ! 3300: ! 3301: /* complete this store: */ ! 3302: ls->tme_sparc_ls_size = 0; ! 3303: return; ! 3304: } ! 3305: } ! 3306: ! 3307: /* otherwise, this is a load: */ ! 3308: else { ! 3309: ! 3310: /* we support reading tags, which always read as zeroes. kernels ! 3311: may read tags when flushing the D-cache: */ ! 3312: if (__tme_predict_true(TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask) == TME_STP103X_ASI_DCACHE_TAG)) { ! 3313: ! 3314: /* complete this load: */ ! 3315: *ls->tme_sparc_ls_rd64 = 0; ! 3316: ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_LD_COMPLETED; ! 3317: ls->tme_sparc_ls_size = 0; ! 3318: return; ! 3319: } ! 3320: } ! 3321: ! 3322: /* XXX FIXME WRITEME: */ ! 3323: abort(); ! 3324: } ! 3325: ! 3326: /* the ASI handler for ASI_ICACHE_INSTR, ASI_ICACHE_TAG, ! 3327: ASI_ICACHE_PRE_DECODE, ASI_ICACHE_NEXT_FIELD: */ ! 3328: static void ! 3329: _tme_stp103x_ls_asi_icache(struct tme_sparc *ic, struct tme_sparc_ls *ls) ! 3330: { ! 3331: tme_uint32_t address_0_31; ! 3332: tme_uint64_t value; ! 3333: ! 3334: /* get the address: */ ! 3335: address_0_31 = ls->tme_sparc_ls_address64 % (16 * 1024); ! 3336: ! 3337: /* check the access: */ ! 3338: if (__tme_predict_false((ls->tme_sparc_ls_lsinfo ! 3339: & (TME_SPARC_LSINFO_OP_ST ! 3340: | TME_SPARC_LSINFO_OP_LD)) == 0 ! 3341: || ls->tme_sparc_ls_size != sizeof(tme_uint64_t))) { ! 3342: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL; ! 3343: } ! 3344: ! 3345: /* if the access has faulted: */ ! 3346: if (__tme_predict_false(ls->tme_sparc_ls_faults != TME_SPARC_LS_FAULT_NONE)) { ! 3347: return; ! 3348: } ! 3349: ! 3350: /* if this is a store: */ ! 3351: if (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_ST) { ! 3352: ! 3353: /* get the value being stored: */ ! 3354: value = *ls->tme_sparc_ls_rd64; ! 3355: ! 3356: /* soon after POR, the PROM writes 0xdeadbeef to address zero in ! 3357: both ASI_ICACHE_DATA and ASI_ICACHE_TAG. later, the PROM ! 3358: initializes all tags in the I-cache. we don't emulate the ! 3359: I-cache, but we do support these writes: */ ! 3360: if ((address_0_31 == 0 ! 3361: && value == 0xdeadbeef) ! 3362: || (TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask) == 0x67 ! 3363: && value == 0)) { ! 3364: ! 3365: /* complete this store: */ ! 3366: ls->tme_sparc_ls_size = 0; ! 3367: return; ! 3368: } ! 3369: } ! 3370: ! 3371: /* XXX FIXME WRITEME: */ ! 3372: abort(); ! 3373: } ! 3374: ! 3375: /* this swaps double-precision floating-point register values in the ! 3376: memory buffer for the block transfer ASIs: */ ! 3377: static void ! 3378: _tme_stp103x_block_buffer_bswap(struct tme_sparc *ic, ! 3379: const struct tme_sparc_ls *ls) ! 3380: { ! 3381: const struct tme_sparc_tlb *tlb; ! 3382: tme_uint32_t endian_little; ! 3383: signed int value_i; ! 3384: ! 3385: /* get the TLB entry: */ ! 3386: tlb = ls->tme_sparc_ls_tlb; ! 3387: ! 3388: /* get the byte order of the memory: */ ! 3389: endian_little = ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_ENDIAN_LITTLE; ! 3390: ! 3391: /* if the host and memory byte orders don't match: */ ! 3392: if (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE ! 3393: ? !endian_little ! 3394: : TME_ENDIAN_NATIVE == TME_ENDIAN_BIG ! 3395: ? endian_little ! 3396: : TRUE) { ! 3397: ! 3398: /* if the host is big- or little-endian: */ ! 3399: if (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE ! 3400: || TME_ENDIAN_NATIVE == TME_ENDIAN_BIG) { ! 3401: ! 3402: /* swap the values in the memory buffer: */ ! 3403: value_i = TME_STP103X_BLOCK_FPREGS_DOUBLE - 1; ! 3404: do { ! 3405: ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer64s[value_i] ! 3406: = tme_bswap_u64(ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer64s[value_i]); ! 3407: } while (--value_i >= 0); ! 3408: } ! 3409: ! 3410: /* otherwise, the host has an unusual byte order: */ ! 3411: else { ! 3412: abort(); ! 3413: } ! 3414: } ! 3415: } ! 3416: ! 3417: /* the cycle handler for loads with ASI_BLOCK_AS_IF_USER*, ! 3418: ASI_BLK_COMMIT*, and ASI_BLOCK*: */ ! 3419: static void ! 3420: _tme_stp103x_ls_cycle_block_ld(struct tme_sparc *ic, struct tme_sparc_ls *ls) ! 3421: { ! 3422: unsigned int fpreg_number; ! 3423: ! 3424: /* do a load cycle: */ ! 3425: tme_sparc64_load(ic, ls); ! 3426: ! 3427: /* if this was not the last cycle, return now: */ ! 3428: if (ls->tme_sparc_ls_size != 0) { ! 3429: return; ! 3430: } ! 3431: ! 3432: /* swap the memory buffer: */ ! 3433: _tme_stp103x_block_buffer_bswap(ic, ls); ! 3434: ! 3435: /* save the block load for verification: */ ! 3436: tme_sparc_recode_verify_mem_block(ic, TME_SPARC_RECODE_VERIFY_MEM_LOAD); ! 3437: ! 3438: /* decode rd: */ ! 3439: fpreg_number ! 3440: = tme_sparc_fpu_fpreg_decode(ic, ! 3441: TME_FIELD_MASK_EXTRACTU(ic->_tme_sparc_insn, ! 3442: TME_SPARC_FORMAT3_MASK_RD), ! 3443: TME_IEEE754_FPREG_FORMAT_DOUBLE); ! 3444: ! 3445: /* loop over a block's worth of double-precision floating-point ! 3446: registers: */ ! 3447: do { ! 3448: ! 3449: /* make sure the floating-point register is double-precision: */ ! 3450: tme_sparc_fpu_fpreg_format(ic, ! 3451: fpreg_number, ! 3452: (TME_IEEE754_FPREG_FORMAT_DOUBLE ! 3453: | TME_IEEE754_FPREG_FORMAT_BUILTIN)); ! 3454: ! 3455: /* copy the double-precision value from the memory buffer: */ ! 3456: ic->tme_sparc_fpu_fpregs[fpreg_number].tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE; ! 3457: ic->tme_sparc_fpu_fpregs[fpreg_number].tme_float_value_ieee754_double.tme_value64_uint ! 3458: = (ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer64s ! 3459: [(fpreg_number / 2) ! 3460: % TME_STP103X_BLOCK_FPREGS_DOUBLE]); ! 3461: ! 3462: /* NB: tme_sparc64_lddfa() will eventually use ! 3463: TME_SPARC_FPU_DIRTY() to mark the right half of the FPU ! 3464: dirty: */ ! 3465: ! 3466: /* log the value loaded, except for the first, which will be ! 3467: logged eventually by tme_sparc64_ldxa(): */ ! 3468: if (((fpreg_number / 2) % TME_STP103X_BLOCK_FPREGS_DOUBLE) != 0) { ! 3469: tme_sparc_log(ic, 1000, TME_OK, ! 3470: (TME_SPARC_LOG_HANDLE(ic), ! 3471: _("ldxa 0x%02x:0x%016" TME_PRIx64 ": 0x%016" TME_PRIx64), ! 3472: TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask), ! 3473: ((ls->tme_sparc_ls_address64 ! 3474: - TME_STP103X_BLOCK_SIZE) ! 3475: + (sizeof(tme_uint64_t) ! 3476: * ((fpreg_number / 2) ! 3477: % TME_STP103X_BLOCK_FPREGS_DOUBLE))), ! 3478: ic->tme_sparc_fpu_fpregs[fpreg_number].tme_float_value_ieee754_double.tme_value64_uint)); ! 3479: } ! 3480: ! 3481: } while ((fpreg_number += 2) ! 3482: % (TME_STP103X_BLOCK_FPREGS_DOUBLE * 2)); ! 3483: ! 3484: /* complete this load for the lddfa function: */ ! 3485: assert (ls->tme_sparc_ls_rd64 ! 3486: == &ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_FPX)); ! 3487: ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_FPX) ! 3488: = ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer64s[0]; ! 3489: } ! 3490: ! 3491: /* the cycle handler for stores with ASI_BLOCK_AS_IF_USER*, ! 3492: ASI_BLK_COMMIT*, and ASI_BLOCK*: */ ! 3493: static void ! 3494: _tme_stp103x_ls_cycle_block_st(struct tme_sparc *ic, struct tme_sparc_ls *ls) ! 3495: { ! 3496: unsigned int fpreg_number; ! 3497: union tme_value64 value_double_buffer; ! 3498: ! 3499: /* this must be the first cycle: */ ! 3500: assert (ls->tme_sparc_ls_buffer_offset == 0); ! 3501: ! 3502: /* decode rd: */ ! 3503: fpreg_number ! 3504: = tme_sparc_fpu_fpreg_decode(ic, ! 3505: TME_FIELD_MASK_EXTRACTU(ic->_tme_sparc_insn, ! 3506: TME_SPARC_FORMAT3_MASK_RD), ! 3507: TME_IEEE754_FPREG_FORMAT_DOUBLE); ! 3508: ! 3509: /* loop over a block's worth of double-precision floating-point ! 3510: registers: */ ! 3511: do { ! 3512: ! 3513: /* make sure the floating-point register is double-precision: */ ! 3514: tme_sparc_fpu_fpreg_format(ic, ! 3515: fpreg_number, ! 3516: (TME_IEEE754_FPREG_FORMAT_DOUBLE ! 3517: | TME_IEEE754_FPREG_FORMAT_BUILTIN)); ! 3518: ! 3519: /* copy the double-precision value into the memory buffer: */ ! 3520: ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer64s ! 3521: [(fpreg_number / 2) ! 3522: % TME_STP103X_BLOCK_FPREGS_DOUBLE] ! 3523: = (tme_ieee754_double_value_get(&ic->tme_sparc_fpu_fpregs[fpreg_number], ! 3524: &value_double_buffer) ! 3525: ->tme_value64_uint); ! 3526: ! 3527: /* log the value stored, except for the first, which was already ! 3528: logged by tme_sparc64_stxa(): */ ! 3529: if (((fpreg_number / 2) % TME_STP103X_BLOCK_FPREGS_DOUBLE) != 0) { ! 3530: tme_sparc_log(ic, 1000, TME_OK, ! 3531: (TME_SPARC_LOG_HANDLE(ic), ! 3532: _("stxa 0x%02x:0x%016" TME_PRIx64 ": 0x%016" TME_PRIx64), ! 3533: TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask), ! 3534: (ls->tme_sparc_ls_address64 ! 3535: + (sizeof(tme_uint64_t) ! 3536: * ((fpreg_number / 2) ! 3537: % TME_STP103X_BLOCK_FPREGS_DOUBLE))), ! 3538: ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer64s ! 3539: [(fpreg_number / 2) ! 3540: % TME_STP103X_BLOCK_FPREGS_DOUBLE])); ! 3541: } ! 3542: ! 3543: } while ((fpreg_number += 2) ! 3544: % (TME_STP103X_BLOCK_FPREGS_DOUBLE * 2)); ! 3545: ! 3546: /* save the block store for verification: */ ! 3547: tme_sparc_recode_verify_mem_block(ic, TME_SPARC_RECODE_VERIFY_MEM_STORE); ! 3548: ! 3549: /* swap the memory buffer: */ ! 3550: _tme_stp103x_block_buffer_bswap(ic, ls); ! 3551: ! 3552: /* do any leftover store cycles directly: */ ! 3553: ls->tme_sparc_ls_cycle = tme_sparc64_store; ! 3554: ! 3555: /* do a store cycle: */ ! 3556: tme_sparc64_store(ic, ls); ! 3557: } ! 3558: ! 3559: /* the ASI handler for ASI_BLOCK_AS_IF_USER*, ASI_BLK_COMMIT*, and ! 3560: ASI_BLOCK*: */ ! 3561: static void ! 3562: _tme_stp103x_ls_asi_block(struct tme_sparc *ic, struct tme_sparc_ls *ls) ! 3563: { ! 3564: tme_uint32_t insn; ! 3565: ! 3566: /* NB: tme_sparc64_lddfa() or tme_sparc64_stdfa() has already done ! 3567: an TME_SPARC_INSN_FPU: */ ! 3568: ! 3569: /* we need to do the complete transfer: */ ! 3570: /* NB: even if this is an stdfa, the TME_SPARC_LSINFO_LD_COMPLETED ! 3571: won't cause any problems: */ ! 3572: assert (sizeof(ic->tme_sparc_memory_buffer) >= TME_STP103X_BLOCK_SIZE); ! 3573: ls->tme_sparc_ls_size = TME_STP103X_BLOCK_SIZE; ! 3574: ls->tme_sparc_ls_buffer_offset = 0; ! 3575: ls->tme_sparc_ls_lsinfo ! 3576: |= (TME_SPARC_LSINFO_SLOW_CYCLES ! 3577: | TME_SPARC_LSINFO_LD_COMPLETED); ! 3578: ! 3579: /* an instruction other than lddfa or stdfa, or an lddfa with an ! 3580: ASI_BLK_COMMIT*, or with an rd that isn't a multiple of 16 is ! 3581: illegal: */ ! 3582: insn = ic->_tme_sparc_insn; ! 3583: /* NB: we flip the stdfa op3 bits, and check that the whole op3 ! 3584: field becomes zero (for ASI_BLK_COMMIT*) or that all op3 bits ! 3585: except the one that differentiates stdfa from lddfa become zero ! 3586: (for all other ASIs): */ ! 3587: /* NB: we only need to test bits 1, 2, and 3 in the double-precision ! 3588: encoded rd, since bit 0 is the encoded bit 5: */ ! 3589: insn ^= (0x37 << 19); ! 3590: if (__tme_predict_false((insn ! 3591: & ((((TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask) ! 3592: ^ TME_STP103X_ASI_BLK_COMMIT) ! 3593: & ~TME_SPARC64_ASI_FLAG_SECONDARY) ! 3594: ? (0x3b << 19) ! 3595: : (0x3f << 19)) ! 3596: | TME_BIT(3 + 25) ! 3597: | TME_BIT(2 + 25) ! 3598: | TME_BIT(1 + 25))))) { ! 3599: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL; ! 3600: } ! 3601: ! 3602: /* the address must be block-aligned: */ ! 3603: else if (__tme_predict_false(((tme_uint32_t) ls->tme_sparc_ls_address64) ! 3604: % TME_STP103X_BLOCK_SIZE)) { ! 3605: ls->tme_sparc_ls_faults |= TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED; ! 3606: } ! 3607: ! 3608: /* set the cycle function: */ ! 3609: /* NB: we flipped the stdfa op3 bits in insn above, so bit two of ! 3610: op3 is now set for an lddfa, and clear for an stdfa: */ ! 3611: ls->tme_sparc_ls_cycle ! 3612: = ((insn & (4 << 19)) ! 3613: ? _tme_stp103x_ls_cycle_block_ld ! 3614: : _tme_stp103x_ls_cycle_block_st); ! 3615: } ! 3616: ! 3617: /* the ASI handler for the UDB registers: */ ! 3618: static void ! 3619: _tme_stp103x_ls_asi_udb(struct tme_sparc *ic, struct tme_sparc_ls *ls) ! 3620: { ! 3621: tme_uint32_t address_0_31; ! 3622: int is_write; ! 3623: tme_uint16_t value16; ! 3624: unsigned int intr_reg; ! 3625: ! 3626: /* get the address: */ ! 3627: address_0_31 = ls->tme_sparc_ls_address64; ! 3628: ! 3629: /* see if this is should be a write or a read: */ ! 3630: is_write = (TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask) == 0x77); ! 3631: assert (is_write || TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask) == 0x7f); ! 3632: ! 3633: /* check the access type and size, and that the address fits in 32 ! 3634: bits: */ ! 3635: if (__tme_predict_false((ls->tme_sparc_ls_lsinfo ! 3636: & (is_write ! 3637: ? TME_SPARC_LSINFO_OP_ST ! 3638: : TME_SPARC_LSINFO_OP_LD)) == 0 ! 3639: || ls->tme_sparc_ls_size != sizeof(tme_uint64_t) ! 3640: || ls->tme_sparc_ls_address64 > (tme_uint32_t) (0 - (tme_uint32_t) 1))) { ! 3641: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL; ! 3642: } ! 3643: ! 3644: /* if the access hasn't faulted yet: */ ! 3645: if (__tme_predict_true(ls->tme_sparc_ls_faults == TME_SPARC_LS_FAULT_NONE)) { ! 3646: ! 3647: /* dispatch on the address: */ ! 3648: switch (address_0_31) { ! 3649: ! 3650: /* the low and high UDB error registers: */ ! 3651: case 0x00: ! 3652: case 0x18: ! 3653: /* we never generate ECC errors, so these registers ! 3654: always read as zero, and writes are ignored: */ ! 3655: if (!is_write) { ! 3656: *ls->tme_sparc_ls_rd64 = 0; ! 3657: } ! 3658: break; ! 3659: ! 3660: /* the low and high UDB control registers: */ ! 3661: case 0x20: ! 3662: case 0x38: ! 3663: if (is_write) { ! 3664: value16 = *ls->tme_sparc_ls_rd64; ! 3665: if (value16 & TME_BIT(8)) { /* F_MODE */ ! 3666: abort(); ! 3667: } ! 3668: TME_STP103X(ic)->tme_stp103x_udb_control[(address_0_31 & 8) == 0] = value16; ! 3669: } ! 3670: else { ! 3671: *ls->tme_sparc_ls_rd64 ! 3672: = ((0x00 << 9) /* UDB version number */ ! 3673: + (TME_STP103X(ic)->tme_stp103x_udb_control[(address_0_31 & 8) == 0] ! 3674: % (2 << 8))); /* F_MODE, FCBV */ ! 3675: } ! 3676: break; ! 3677: ! 3678: /* the UDB transmit and receive interrupt vector data: */ ! 3679: case 0x40: ! 3680: case 0x50: ! 3681: case 0x60: ! 3682: intr_reg = (address_0_31 - 0x40) / sizeof(tme_uint64_t); ! 3683: if (is_write) { ! 3684: TME_STP103X(ic)->tme_stp103x_udb_intr_transmit[intr_reg] ! 3685: = *ls->tme_sparc_ls_rd64; ! 3686: } ! 3687: else { ! 3688: *ls->tme_sparc_ls_rd64 ! 3689: = TME_STP103X(ic)->tme_stp103x_udb_intr_receive[intr_reg]; ! 3690: } ! 3691: break; ! 3692: ! 3693: default: ! 3694: ! 3695: /* if this isn't a write of the UDB interrupt vector dispatch: */ ! 3696: if (!is_write ! 3697: || (address_0_31 & ~((2 << 18) - (1 << 14))) != 0x70) { ! 3698: ! 3699: /* this is an illegal access: */ ! 3700: ls->tme_sparc_ls_faults |= TME_STP103X_LS_FAULT_ILLEGAL; ! 3701: break; ! 3702: } ! 3703: ! 3704: abort(); ! 3705: break; ! 3706: } ! 3707: } ! 3708: ! 3709: /* if the access has faulted: */ ! 3710: if (__tme_predict_false(ls->tme_sparc_ls_faults != TME_SPARC_LS_FAULT_NONE)) { ! 3711: return; ! 3712: } ! 3713: ! 3714: /* complete the load or store: */ ! 3715: if (!is_write) { ! 3716: ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_LD_COMPLETED; ! 3717: } ! 3718: ls->tme_sparc_ls_size = 0; ! 3719: } ! 3720: ! 3721: /* the ASI handlers: */ ! 3722: static const _tme_sparc_ls_asi_handler _tme_stp103x_ls_asi_handlers[] = { ! 3723: NULL, ! 3724: _tme_stp103x_ls_asi_mmu, ! 3725: _tme_stp103x_ls_asi_tsb_ptr, ! 3726: _tme_stp103x_ls_asi_quad, ! 3727: _tme_stp103x_ls_asi_tlb_data_in, ! 3728: _tme_stp103x_ls_asi_mmu_demap, ! 3729: _tme_stp103x_ls_asi_slow, ! 3730: _tme_stp103x_ls_asi_phys, ! 3731: _tme_stp103x_ls_asi_dcache, ! 3732: _tme_stp103x_ls_asi_ecache, ! 3733: _tme_stp103x_ls_asi_tlb_data_access, ! 3734: _tme_stp103x_ls_asi_tlb_tag_read, ! 3735: _tme_stp103x_ls_asi_icache, ! 3736: _tme_stp103x_ls_asi_block, ! 3737: _tme_stp103x_ls_asi_udb, ! 3738: tme_sparc64_vis_ls_asi_pst, ! 3739: tme_sparc64_vis_ls_asi_fl, ! 3740: }; ! 3741: ! 3742: /* the tick compare register thread: */ ! 3743: static void ! 3744: _tme_stp103x_tick_compare_th(void *_ic) ! 3745: { ! 3746: struct tme_sparc *ic; ! 3747: struct timeval now; ! 3748: unsigned long now_tv_sec; ! 3749: unsigned long now_tv_usec; ! 3750: unsigned long tick_compare_time_tv_sec; ! 3751: unsigned long tick_compare_time_tv_usec; ! 3752: struct timeval sleep; ! 3753: ! 3754: /* recover our data structure: */ ! 3755: ic = (struct tme_sparc *) _ic; ! 3756: ! 3757: /* lock the external mutex: */ ! 3758: tme_mutex_lock(&ic->tme_sparc_external_mutex); ! 3759: ! 3760: /* loop forever: */ ! 3761: for (;;) { ! 3762: ! 3763: /* get the current time: */ ! 3764: tme_gettimeofday(&now); ! 3765: ! 3766: /* if the current time is greater than or equal to the tick compare time: */ ! 3767: now_tv_sec = now.tv_sec; ! 3768: now_tv_usec = now.tv_usec; ! 3769: tick_compare_time_tv_sec = TME_STP103X(ic)->tme_stp103x_tick_compare_time.tv_sec; ! 3770: tick_compare_time_tv_usec = TME_STP103X(ic)->tme_stp103x_tick_compare_time.tv_usec; ! 3771: if (now_tv_sec > tick_compare_time_tv_sec ! 3772: || (now_tv_sec == tick_compare_time_tv_sec ! 3773: && now_tv_usec >= tick_compare_time_tv_usec)) { ! 3774: ! 3775: /* set the tick interrupt atomic flag: */ ! 3776: tme_memory_atomic_write_flag(&TME_STP103X(ic)->tme_stp103x_sir_tick_int, TRUE); ! 3777: ! 3778: /* set the external flag: */ ! 3779: tme_memory_atomic_write_flag(&ic->tme_sparc_external_flag, TRUE); ! 3780: ! 3781: /* notify any thread waiting on the external condition: */ ! 3782: tme_cond_notify(&ic->tme_sparc_external_cond, FALSE); ! 3783: ! 3784: /* wait on the tick compare condition: */ ! 3785: tme_cond_wait_yield(&TME_STP103X(ic)->tme_stp103x_tick_compare_cond, ! 3786: &ic->tme_sparc_external_mutex); ! 3787: } ! 3788: ! 3789: /* otherwise, the current time is less than the tick compare ! 3790: time: */ ! 3791: else { ! 3792: ! 3793: /* make the sleep time, but don't sleep more than a minute at a time: */ ! 3794: if (tick_compare_time_tv_usec < now_tv_usec) { ! 3795: tick_compare_time_tv_sec--; ! 3796: tick_compare_time_tv_usec += 1000000; ! 3797: } ! 3798: sleep.tv_sec = TME_MIN(tick_compare_time_tv_sec - now_tv_sec, 60); ! 3799: sleep.tv_usec = tick_compare_time_tv_usec - now_tv_usec; ! 3800: ! 3801: /* sleep on the tick compare condition: */ ! 3802: tme_cond_sleep_yield(&TME_STP103X(ic)->tme_stp103x_tick_compare_cond, ! 3803: &ic->tme_sparc_external_mutex, ! 3804: &sleep); ! 3805: } ! 3806: } ! 3807: /* NOTREACHED */ ! 3808: } ! 3809: ! 3810: /* this checks for external signals: */ ! 3811: /* NB: this may do a preinstruction trap: */ ! 3812: static void ! 3813: _tme_stp103x_external_check(struct tme_sparc *ic, ! 3814: int flags) ! 3815: { ! 3816: ! 3817: /* if RESET_L has been negated since the last check: */ ! 3818: if (__tme_predict_false(tme_memory_atomic_read_flag(&ic->tme_sparc_external_reset_negated))) { ! 3819: ! 3820: /* clear the XIR and RESET_L asserted flags, then clear the ! 3821: RESET_L negated flag: */ ! 3822: tme_memory_atomic_write_flag(&ic->tme_sparc_external_halt_asserted, FALSE); ! 3823: tme_memory_atomic_write_flag(&ic->tme_sparc_external_reset_asserted, FALSE); ! 3824: tme_memory_barrier(ic, sizeof(*ic), TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE); ! 3825: tme_memory_atomic_write_flag(&ic->tme_sparc_external_reset_negated, FALSE); ! 3826: ! 3827: /* start POR trap processing: */ ! 3828: if (flags & TME_SPARC_EXTERNAL_CHECK_MUTEX_LOCKED) { ! 3829: tme_mutex_unlock(&ic->tme_sparc_external_mutex); ! 3830: } ! 3831: tme_sparc64_trap_preinstruction(ic, TME_SPARC64_TRAP_power_on_reset); ! 3832: } ! 3833: ! 3834: /* if RESET_L is asserted: */ ! 3835: if (__tme_predict_false(tme_memory_atomic_read_flag(&ic->tme_sparc_external_reset_asserted))) { ! 3836: ! 3837: /* halt: */ ! 3838: if (flags & TME_SPARC_EXTERNAL_CHECK_MUTEX_LOCKED) { ! 3839: tme_mutex_unlock(&ic->tme_sparc_external_mutex); ! 3840: } ! 3841: ic->_tme_sparc_mode = TME_SPARC_MODE_HALT; ! 3842: tme_sparc_redispatch(ic); ! 3843: } ! 3844: ! 3845: /* if XIR has been asserted since the last check: */ ! 3846: if (__tme_predict_false(tme_memory_atomic_read_flag(&ic->tme_sparc_external_halt_asserted))) { ! 3847: ! 3848: /* clear the XIR asserted flag: */ ! 3849: tme_memory_atomic_write_flag(&ic->tme_sparc_external_halt_asserted, FALSE); ! 3850: ! 3851: /* start XIR trap processing: */ ! 3852: if (flags & TME_SPARC_EXTERNAL_CHECK_MUTEX_LOCKED) { ! 3853: tme_mutex_unlock(&ic->tme_sparc_external_mutex); ! 3854: } ! 3855: tme_sparc64_trap_preinstruction(ic, TME_SPARC64_TRAP_externally_initiated_reset); ! 3856: } ! 3857: ! 3858: /* do an interrupt check: */ ! 3859: _tme_stp103x_interrupt_check(ic, flags); ! 3860: } ! 3861: ! 3862: /* the bus cycle function: */ ! 3863: static void ! 3864: _tme_stp103x_ls_bus_cycle(const struct tme_sparc *ic, ! 3865: struct tme_sparc_ls *ls) ! 3866: { ! 3867: tme_uint32_t asi_mask; ! 3868: unsigned int cycle_size_log2; ! 3869: ! 3870: /* NB: we provide the old sparc32 bus routing information when ! 3871: emulating stp103x noncached read and write transactions on the ! 3872: UPA bus. ! 3873: ! 3874: this is a bad hack that we do only to save duplicating that same ! 3875: information in the stp2220 emulation, which needs it for cycles ! 3876: that pass through it onto its SBus. ! 3877: ! 3878: since the old sparc32 bus routing information doesn't have ! 3879: anything to do with how the UPA bus works, we assume that all TLB ! 3880: fills for noncacheable accesses that don't allow fast transfers ! 3881: will either end up at another CPU (which will know about the ! 3882: disagreement and ignore the bus routing information), or end up ! 3883: at an I/O bridge, which will either rely on the sparc32 bus ! 3884: routing information (stp2220), or replace it with its own bus ! 3885: routing information (stp2222), before running the cycle on its ! 3886: I/O bus. if the cycle is for an I/O bridge's internal registers, ! 3887: like a CPU it will know about the disagreement and ignore the bus ! 3888: routing information. ! 3889: ! 3890: we assume that all TLB fills for cacheable accesses target main ! 3891: memory, which we assume will tolerate any bus routing: */ ! 3892: ! 3893: /* get the ASI mask for this TLB entry: */ ! 3894: asi_mask = ls->tme_sparc_ls_tlb->tme_sparc_tlb_asi_mask; ! 3895: ! 3896: /* if the TLB entry is for noncacheable accesses: */ ! 3897: if (asi_mask & TME_SPARC64_ASI_MASK_FLAG_TLB_UNCACHEABLE) { ! 3898: ! 3899: /* call the default sparc32 bus cycle function: */ ! 3900: tme_sparc32_ls_bus_cycle(ic, ls); ! 3901: return; ! 3902: } ! 3903: ! 3904: /* provide a simple bus routing for cacheable accesses: */ ! 3905: cycle_size_log2 = TME_BUS8_LOG2; ! 3906: for (; (1 << cycle_size_log2) != ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_size; ) { ! 3907: assert (cycle_size_log2 < TME_BUS128_LOG2); ! 3908: cycle_size_log2++; ! 3909: } ! 3910: ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS128_LOG2); ! 3911: ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_lane_routing ! 3912: = (&(_tme_stp103x_bus_router_cacheable ! 3913: [cycle_size_log2] ! 3914: [0]) ! 3915: - TME_BUS_ROUTER_INDEX(TME_BUS128_LOG2, TME_BUS128_LOG2, 0)); ! 3916: } ! 3917: ! 3918: /* this fills a TLB for the CPU: */ ! 3919: static int ! 3920: _tme_stp103x_tlb_fill(struct tme_bus_connection *conn_bus, ! 3921: struct tme_bus_tlb *tlb, ! 3922: tme_bus_addr_t address, ! 3923: unsigned int cycle_type) ! 3924: { ! 3925: abort(); ! 3926: } ! 3927: ! 3928: /* this handles an interrupt: */ ! 3929: static void ! 3930: _tme_stp103x_interrupt(struct tme_upa_bus_connection *conn_upa, ! 3931: tme_uint32_t master_mid, ! 3932: const tme_uint64_t *data, ! 3933: struct tme_completion *completion) ! 3934: { ! 3935: struct tme_sparc *ic; ! 3936: ! 3937: /* recover our data structure: */ ! 3938: ic = conn_upa->tme_upa_bus_connection.tme_bus_connection.tme_connection_element->tme_element_private; ! 3939: ! 3940: /* if the receive interrupt vector data is already busy: */ ! 3941: if (tme_memory_atomic_read_flag(&TME_STP103X(ic)->tme_stp103x_intr_receive_busy)) { ! 3942: ! 3943: /* NACK this interrupt: */ ! 3944: completion->tme_completion_error = EAGAIN; ! 3945: tme_memory_barrier(completion, sizeof(*completion), TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE); ! 3946: } ! 3947: ! 3948: /* otherwise, the incoming data isn't busy: */ ! 3949: else { ! 3950: ! 3951: /* save the interrupt data and ACK this interrupt: */ ! 3952: /* NB: the interrupt data is an array of eight big-endian ! 3953: tme_uint64_t, since an interrupt packet is four 128-bit values. ! 3954: the even indices are the least-significant halves of the ! 3955: 128-bit values: */ ! 3956: TME_STP103X(ic)->tme_stp103x_intr_receive_mid = master_mid; ! 3957: TME_STP103X(ic)->tme_stp103x_udb_intr_receive[0] = tme_betoh_u64(data[2 * 0]); ! 3958: TME_STP103X(ic)->tme_stp103x_udb_intr_receive[1] = tme_betoh_u64(data[2 * 1]); ! 3959: TME_STP103X(ic)->tme_stp103x_udb_intr_receive[2] = tme_betoh_u64(data[2 * 2]); ! 3960: completion->tme_completion_error = TME_OK; ! 3961: tme_memory_barrier(0, 0, TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE); ! 3962: tme_memory_atomic_write_flag(&TME_STP103X(ic)->tme_stp103x_intr_receive_busy, 1); ! 3963: tme_memory_barrier(ic, sizeof(*ic), TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE); ! 3964: tme_memory_atomic_write_flag(&ic->tme_sparc_external_flag, 1); ! 3965: tme_cond_notify(&ic->tme_sparc_external_cond, FALSE); ! 3966: } ! 3967: ! 3968: /* validate this completion: */ ! 3969: tme_completion_validate(completion); ! 3970: } ! 3971: ! 3972: /* this returns the version of an FPU for an stp103x: */ ! 3973: static tme_uint32_t ! 3974: _tme_sparc_fpu_ver_stp103x(struct tme_sparc *ic, const char *fpu_name, char **_output) ! 3975: { ! 3976: tme_uint32_t ver; ! 3977: ! 3978: /* if we're returning a usage: */ ! 3979: if (_output != NULL) { ! 3980: tme_output_append_error(_output, ! 3981: "builtin"); ! 3982: return (TME_SPARC_FSR_VER_missing); ! 3983: } ! 3984: ! 3985: if (TME_ARG_IS(fpu_name, "builtin")) { ! 3986: /* XXX FIXME - the stp1030 has an FSR_version of zero. we assume ! 3987: that the stp1031 does too: */ ! 3988: ver = 0; ! 3989: } ! 3990: else { ! 3991: return (TME_SPARC_FSR_VER_missing); ! 3992: } ! 3993: ! 3994: ic->tme_sparc_fpu_flags ! 3995: = (!TME_SPARC_FPU_FLAG_OK_REG_MISALIGNED); ! 3996: return (ver * _TME_FIELD_MASK_FACTOR(TME_SPARC_FSR_VER)); ! 3997: } ! 3998: ! 3999: /* this creates and returns a new stp103x: */ ! 4000: static int ! 4001: _tme_stp103x_new(struct tme_element *element, ! 4002: const char * const *args, ! 4003: const void *extra, ! 4004: char **_output, ! 4005: int is_1030) ! 4006: { ! 4007: struct tme_sparc *ic; ! 4008: tme_uint32_t psr; ! 4009: tme_uint32_t asi; ! 4010: tme_uint32_t asi_mask_flags; ! 4011: void (*handler) _TME_P((struct tme_sparc *, struct tme_sparc_ls *)); ! 4012: tme_uint32_t handler_i; ! 4013: ! 4014: /* allocate the stp103x structure: */ ! 4015: ic = &tme_new0(struct tme_stp103x, 1)->tme_stp103x_sparc; ! 4016: ic->tme_sparc_element = element; ! 4017: ! 4018: /* set the type: */ ! 4019: is_1030 = !!is_1030; ! 4020: TME_STP103X(ic)->tme_stp103x_is_1030 = is_1030; ! 4021: if (TME_STP103X_IS_1030(ic) != is_1030) { ! 4022: tme_free(ic); ! 4023: return (ENXIO); ! 4024: } ! 4025: ! 4026: /* initialize the synchronization parts of the structure: */ ! 4027: tme_sparc_sync_init(ic); ! 4028: ! 4029: /* initialize the stp103x private structure: */ ! 4030: TME_STP103X(ic)->tme_stp103x_tcr = TME_STP103X_TCR_INT_DIS; ! 4031: tme_cond_init(&TME_STP103X(ic)->tme_stp103x_tick_compare_cond); ! 4032: tme_misc_timeval_never(&TME_STP103X(ic)->tme_stp103x_tick_compare_time); ! 4033: tme_memory_atomic_init_flag(&TME_STP103X(ic)->tme_stp103x_sir_tick_int, FALSE); ! 4034: tme_memory_atomic_init_flag(&TME_STP103X(ic)->tme_stp103x_intr_receive_busy, FALSE); ! 4035: ! 4036: /* start the tick compare thread: */ ! 4037: tme_thread_create((tme_thread_t) _tme_stp103x_tick_compare_th, ic); ! 4038: ! 4039: /* fill in the stp103x-specific parts of the structure: */ ! 4040: psr = 0; ! 4041: TME_FIELD_MASK_DEPOSITU(psr, TME_SPARC32_PSR_IMPL, 1); ! 4042: TME_FIELD_MASK_DEPOSITU(psr, TME_SPARC32_PSR_VER, 1); ! 4043: ic->tme_sparc32_ireg_psr = psr; ! 4044: ic->tme_sparc_version = TME_SPARC_VERSION(ic); ! 4045: ic->tme_sparc_nwindows = TME_SPARC_NWINDOWS(ic); ! 4046: ic->tme_sparc_memory_flags = TME_SPARC_MEMORY_FLAGS(ic); ! 4047: ic->tme_sparc64_maxtl = TME_STP103X_MAXTL; ! 4048: ic->tme_sparc_tlb_page_size_log2 = 13; /* log2(TME_STP103X_PAGE_SIZE_8KB) */ ! 4049: ic->tme_sparc_memory_context_max = TME_STP103X_CONTEXT_MAX; ! 4050: ic->_tme_sparc64_execute_opmap = _TME_SPARC_EXECUTE_OPMAP; ! 4051: ic->tme_sparc64_rstvaddr = 0 - (tme_uint64_t) (1 << 28); ! 4052: ic->tme_sparc64_ireg_va_hole_start = TME_STP103X_VA_HOLE_START; ! 4053: ic->tme_sparc64_ireg_ver ! 4054: = ((0x0017 * _TME_FIELD_MASK_FACTOR(TME_SPARC64_VER_MANUF)) ! 4055: + (0x0010 * _TME_FIELD_MASK_FACTOR(TME_SPARC64_VER_IMPL)) ! 4056: + (0x40 * _TME_FIELD_MASK_FACTOR(TME_SPARC64_VER_MASK)) ! 4057: + (ic->tme_sparc64_maxtl * _TME_FIELD_MASK_FACTOR(TME_SPARC64_VER_MAXTL)) ! 4058: + ((TME_SPARC_NWINDOWS(ic) - 1) * _TME_FIELD_MASK_FACTOR(TME_SPARC64_VER_MAXWIN))); ! 4059: ic->tme_sparc64_ireg_winstates_mask ! 4060: = (TME_SPARC64_WINSTATES_CWP(TME_SPARC_NWINDOWS(ic) - 1) ! 4061: + TME_SPARC64_WINSTATES_CANRESTORE(TME_SPARC_NWINDOWS(ic) - 1) ! 4062: + TME_SPARC64_WINSTATES_CANSAVE(TME_SPARC_NWINDOWS(ic) - 1) ! 4063: + TME_SPARC64_WINSTATES_OTHERWIN(TME_SPARC_NWINDOWS(ic) - 1)); ! 4064: ic->_tme_sparc_execute = _tme_sparc_execute_stp103x; ! 4065: ic->_tme_sparc_fpu_ver = _tme_sparc_fpu_ver_stp103x; ! 4066: ic->_tme_sparc_external_check = _tme_stp103x_external_check; ! 4067: ic->_tme_sparc_tlb_fill = _tme_stp103x_tlb_fill; ! 4068: ic->_tme_sparc_upa_interrupt = _tme_stp103x_interrupt; ! 4069: ic->_tme_sparc_ls_asi_misaligned = tme_sparc64_vis_ls_asi_misaligned; ! 4070: ic->_tme_sparc_ls_asi_handlers = _tme_stp103x_ls_asi_handlers; ! 4071: ic->_tme_sparc_ls_address_map = _tme_stp103x_ls_address_map; ! 4072: ic->_tme_sparc_ls_bus_cycle = _tme_stp103x_ls_bus_cycle; ! 4073: ic->_tme_sparc_ls_bus_fault = tme_sparc_ls_bus_fault; ! 4074: ic->_tme_sparc_ls_trap = _tme_stp103x_ls_trap; ! 4075: ic->_tme_sparc64_update_pstate = _tme_stp103x_update_pstate; ! 4076: ic->tme_sparc_vis_ls_fault_illegal = TME_STP103X_LS_FAULT_ILLEGAL; ! 4077: ic->tme_sparc_timing_loop_cycles_each = 1; ! 4078: #ifdef _TME_SPARC_RECODE_VERIFY ! 4079: /* NB: struct tme_stp103x has been deliberately laid out to have all ! 4080: of the verifiable contents first, followed by everything that ! 4081: isn't verifiable (basically, anything that is accessed using ! 4082: loads and stores, since replay only simulates them): */ ! 4083: ic->tme_sparc_recode_verify_ic_size ! 4084: = (((char *) &((struct tme_stp103x *) 0)->tme_stp103x_upa_config) ! 4085: - (char *) ((struct tme_stp103x *) 0)); ! 4086: ic->tme_sparc_recode_verify_ic_size_total = sizeof(struct tme_stp103x); ! 4087: #endif /* _TME_SPARC_RECODE_VERIFY */ ! 4088: ! 4089: /* initialize the ASIs: */ ! 4090: for (asi = 0; asi < TME_ARRAY_ELS(ic->tme_sparc_asis); asi++) { ! 4091: ! 4092: /* dispatch on this ASI: */ ! 4093: switch (asi) { ! 4094: ! 4095: /* ASI_PHYS_USE_EC*, ASI_PHYS_BYPASS_EC_WITH_EBIT*: */ ! 4096: case (0x14): ! 4097: case (0x14 ! 4098: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4099: case (0x15): ! 4100: case (0x15 ! 4101: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4102: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL; ! 4103: handler = _tme_stp103x_ls_asi_phys; ! 4104: break; ! 4105: ! 4106: /* ASI_NUCLEUS_QUAD_LDD*: */ ! 4107: case (0x24): ! 4108: case (0x24 ! 4109: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4110: asi_mask_flags ! 4111: = (TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS ! 4112: + (asi ! 4113: & TME_SPARC64_ASI_FLAG_LITTLE)); ! 4114: handler = _tme_stp103x_ls_asi_quad; ! 4115: break; ! 4116: ! 4117: /* ASI_DCACHE_DATA, ASI_DCACHE_TAG: */ ! 4118: case TME_STP103X_ASI_DCACHE_DATA: ! 4119: case TME_STP103X_ASI_DCACHE_TAG: ! 4120: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL; ! 4121: handler = _tme_stp103x_ls_asi_dcache; ! 4122: break; ! 4123: ! 4124: /* ASI_ECACHE_W, ASI_ECACHE_R: */ ! 4125: case 0x76: ! 4126: case 0x7e: ! 4127: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL; ! 4128: handler = _tme_stp103x_ls_asi_ecache; ! 4129: break; ! 4130: ! 4131: /* ASI_IMMU, ASI_DMMU: */ ! 4132: case TME_STP103X_ASI_IMMU: ! 4133: case TME_STP103X_ASI_DMMU: ! 4134: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL; ! 4135: handler = _tme_stp103x_ls_asi_mmu; ! 4136: break; ! 4137: ! 4138: /* ASI_IMMU_TSB_8KB_PTR_REG, ASI_IMMU_TSB_64KB_PTR_REG, ! 4139: ASI_DMMU_TSB_8KB_PTR_REG, ASI_DMMU_TSB_64KB_PTR_REG, ! 4140: ASI_DMMU_TSB_DIRECT_PTR_REG: */ ! 4141: case (TME_STP103X_ASI_IMMU ! 4142: + TME_STP103X_ASI_FLAG_TSB_8KB_PTR): ! 4143: case (TME_STP103X_ASI_IMMU ! 4144: + TME_STP103X_ASI_FLAG_TSB_64KB_PTR): ! 4145: case (TME_STP103X_ASI_DMMU ! 4146: + TME_STP103X_ASI_FLAG_TSB_8KB_PTR): ! 4147: case (TME_STP103X_ASI_DMMU ! 4148: + TME_STP103X_ASI_FLAG_TSB_64KB_PTR): ! 4149: case (TME_STP103X_ASI_DMMU ! 4150: + (TME_STP103X_ASI_FLAG_TSB_8KB_PTR ! 4151: | TME_STP103X_ASI_FLAG_TSB_64KB_PTR)): ! 4152: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL; ! 4153: handler = _tme_stp103x_ls_asi_tsb_ptr; ! 4154: break; ! 4155: ! 4156: /* ASI_ITLB_DATA_IN_REG, ASI_DTLB_DATA_IN_REG: */ ! 4157: case (TME_STP103X_ASI_IMMU + 0x4): ! 4158: case (TME_STP103X_ASI_DMMU + 0x4): ! 4159: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL; ! 4160: handler = _tme_stp103x_ls_asi_tlb_data_in; ! 4161: break; ! 4162: ! 4163: /* ASI_ITLB_DATA_ACCESS_REG, ASI_DTLB_DATA_ACCESS_REG: */ ! 4164: case (TME_STP103X_ASI_IMMU + 0x5): ! 4165: case (TME_STP103X_ASI_DMMU + 0x5): ! 4166: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL; ! 4167: handler = _tme_stp103x_ls_asi_tlb_data_access; ! 4168: break; ! 4169: ! 4170: /* ASI_ITLB_TAG_READ_REG, ASI_DTLB_TAG_READ_REG: */ ! 4171: case (TME_STP103X_ASI_IMMU + 0x6): ! 4172: case (TME_STP103X_ASI_DMMU + 0x6): ! 4173: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL; ! 4174: handler = _tme_stp103x_ls_asi_tlb_tag_read; ! 4175: break; ! 4176: ! 4177: /* ASI_IMMU_DEMAP, ASI_DMMU_DEMAP: */ ! 4178: case (TME_STP103X_ASI_IMMU + 0x7): ! 4179: case (TME_STP103X_ASI_DMMU + 0x7): ! 4180: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL; ! 4181: handler = _tme_stp103x_ls_asi_mmu_demap; ! 4182: break; ! 4183: ! 4184: /* ASI_ICACHE_INSTR: */ ! 4185: /* ASI_ICACHE_TAG: */ ! 4186: /* ASI_ICACHE_PRE_DECODE: */ ! 4187: /* ASI_ICACHE_NEXT_FIELD: */ ! 4188: case 0x66: ! 4189: case 0x67: ! 4190: case 0x6e: ! 4191: case 0x6f: ! 4192: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL; ! 4193: handler = _tme_stp103x_ls_asi_icache; ! 4194: break; ! 4195: ! 4196: /* ASI_BLOCK_AS_IF_USER*: */ ! 4197: case (0x70): ! 4198: case (0x70 ! 4199: + TME_SPARC64_ASI_FLAG_SECONDARY): ! 4200: case (0x70 ! 4201: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4202: case (0x70 ! 4203: + TME_SPARC64_ASI_FLAG_SECONDARY ! 4204: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4205: asi_mask_flags ! 4206: = (TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER ! 4207: + (asi ! 4208: & (TME_SPARC64_ASI_FLAG_SECONDARY ! 4209: | TME_SPARC64_ASI_FLAG_LITTLE))); ! 4210: handler = _tme_stp103x_ls_asi_block; ! 4211: break; ! 4212: ! 4213: /* ASI_UDB*: */ ! 4214: case 0x77: ! 4215: case 0x7f: ! 4216: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL; ! 4217: handler = _tme_stp103x_ls_asi_udb; ! 4218: break; ! 4219: ! 4220: /* the mandatory v9 ASIs: */ ! 4221: #if TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS != 4 ! 4222: #error "TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS changed" ! 4223: #endif ! 4224: case (TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS): ! 4225: case (TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS ! 4226: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4227: #if TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER != 0x10 ! 4228: #error "TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER changed" ! 4229: #endif ! 4230: case (TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER): ! 4231: case (TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER ! 4232: + TME_SPARC64_ASI_FLAG_SECONDARY): ! 4233: case (TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER ! 4234: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4235: case (TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER ! 4236: + TME_SPARC64_ASI_FLAG_SECONDARY ! 4237: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4238: case (TME_SPARC64_ASI_FLAG_UNRESTRICTED): ! 4239: case (TME_SPARC64_ASI_FLAG_UNRESTRICTED ! 4240: + TME_SPARC64_ASI_FLAG_SECONDARY): ! 4241: case (TME_SPARC64_ASI_FLAG_UNRESTRICTED ! 4242: + TME_SPARC64_ASI_FLAG_NO_FAULT): ! 4243: case (TME_SPARC64_ASI_FLAG_UNRESTRICTED ! 4244: + TME_SPARC64_ASI_FLAG_SECONDARY ! 4245: + TME_SPARC64_ASI_FLAG_NO_FAULT): ! 4246: case (TME_SPARC64_ASI_FLAG_UNRESTRICTED ! 4247: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4248: case (TME_SPARC64_ASI_FLAG_UNRESTRICTED ! 4249: + TME_SPARC64_ASI_FLAG_SECONDARY ! 4250: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4251: case (TME_SPARC64_ASI_FLAG_UNRESTRICTED ! 4252: + TME_SPARC64_ASI_FLAG_NO_FAULT ! 4253: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4254: case (TME_SPARC64_ASI_FLAG_UNRESTRICTED ! 4255: + TME_SPARC64_ASI_FLAG_SECONDARY ! 4256: + TME_SPARC64_ASI_FLAG_NO_FAULT ! 4257: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4258: ! 4259: /* the mandatory v9 ASIs are all normal and have no handlers: */ ! 4260: asi_mask_flags = asi; ! 4261: handler = NULL; ! 4262: assert ((asi_mask_flags & TME_SPARC64_ASI_MASK_FLAG_SPECIAL) == 0); ! 4263: assert (_tme_stp103x_ls_asi_handlers[0] == handler); ! 4264: break; ! 4265: ! 4266: /* ASI_PST*: */ ! 4267: case (TME_SPARC_VIS_ASI_PST8): ! 4268: case (TME_SPARC_VIS_ASI_PST8 ! 4269: + TME_SPARC64_ASI_FLAG_SECONDARY): ! 4270: case (TME_SPARC_VIS_ASI_PST8 ! 4271: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4272: case (TME_SPARC_VIS_ASI_PST8 ! 4273: + TME_SPARC64_ASI_FLAG_SECONDARY ! 4274: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4275: case (TME_SPARC_VIS_ASI_PST16): ! 4276: case (TME_SPARC_VIS_ASI_PST16 ! 4277: + TME_SPARC64_ASI_FLAG_SECONDARY): ! 4278: case (TME_SPARC_VIS_ASI_PST16 ! 4279: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4280: case (TME_SPARC_VIS_ASI_PST16 ! 4281: + TME_SPARC64_ASI_FLAG_SECONDARY ! 4282: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4283: case (TME_SPARC_VIS_ASI_PST32): ! 4284: case (TME_SPARC_VIS_ASI_PST32 ! 4285: + TME_SPARC64_ASI_FLAG_SECONDARY): ! 4286: case (TME_SPARC_VIS_ASI_PST32 ! 4287: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4288: case (TME_SPARC_VIS_ASI_PST32 ! 4289: + TME_SPARC64_ASI_FLAG_SECONDARY ! 4290: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4291: asi_mask_flags ! 4292: = (asi ! 4293: & (TME_SPARC64_ASI_FLAG_SECONDARY ! 4294: | TME_SPARC64_ASI_FLAG_LITTLE)); ! 4295: handler = tme_sparc64_vis_ls_asi_pst; ! 4296: break; ! 4297: ! 4298: /* ASI_FL*: */ ! 4299: case (TME_SPARC_VIS_ASI_FL8): ! 4300: case (TME_SPARC_VIS_ASI_FL8 ! 4301: + TME_SPARC64_ASI_FLAG_SECONDARY): ! 4302: case (TME_SPARC_VIS_ASI_FL8 ! 4303: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4304: case (TME_SPARC_VIS_ASI_FL8 ! 4305: + TME_SPARC64_ASI_FLAG_SECONDARY ! 4306: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4307: case (TME_SPARC_VIS_ASI_FL16): ! 4308: case (TME_SPARC_VIS_ASI_FL16 ! 4309: + TME_SPARC64_ASI_FLAG_SECONDARY): ! 4310: case (TME_SPARC_VIS_ASI_FL16 ! 4311: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4312: case (TME_SPARC_VIS_ASI_FL16 ! 4313: + TME_SPARC64_ASI_FLAG_SECONDARY ! 4314: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4315: asi_mask_flags ! 4316: = (asi ! 4317: & (TME_SPARC64_ASI_FLAG_SECONDARY ! 4318: | TME_SPARC64_ASI_FLAG_LITTLE)); ! 4319: handler = tme_sparc64_vis_ls_asi_fl; ! 4320: break; ! 4321: ! 4322: /* ASI_BLK_COMMIT*: */ ! 4323: case (TME_STP103X_ASI_BLK_COMMIT): ! 4324: case (TME_STP103X_ASI_BLK_COMMIT ! 4325: + TME_SPARC64_ASI_FLAG_SECONDARY): ! 4326: asi_mask_flags ! 4327: = (asi ! 4328: & (TME_SPARC64_ASI_FLAG_SECONDARY)); ! 4329: handler = _tme_stp103x_ls_asi_block; ! 4330: break; ! 4331: ! 4332: /* ASI_BLOCK*: */ ! 4333: case (0xf0): ! 4334: case (0xf0 ! 4335: + TME_SPARC64_ASI_FLAG_SECONDARY): ! 4336: case (0xf0 ! 4337: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4338: case (0xf0 ! 4339: + TME_SPARC64_ASI_FLAG_SECONDARY ! 4340: + TME_SPARC64_ASI_FLAG_LITTLE): ! 4341: asi_mask_flags ! 4342: = (asi ! 4343: & (TME_SPARC64_ASI_FLAG_SECONDARY ! 4344: | TME_SPARC64_ASI_FLAG_LITTLE)); ! 4345: handler = _tme_stp103x_ls_asi_block; ! 4346: break; ! 4347: ! 4348: case TME_STP103X_ASI_LSU_CONTROL_REG: ! 4349: case TME_STP103X_ASI_INTR_DISPATCH_STATUS: ! 4350: case TME_STP103X_ASI_INTR_RECEIVE: ! 4351: case TME_STP103X_ASI_UPA_CONFIG_REG: ! 4352: case TME_STP103X_ASI_ESTATE_ERROR_EN_REG: ! 4353: case TME_STP103X_ASI_AFSR: ! 4354: case TME_STP103X_ASI_AFAR: ! 4355: case TME_STP103X_ASI_ECACHE_TAG_DATA: ! 4356: default: ! 4357: asi_mask_flags = TME_SPARC64_ASI_MASK_FLAG_SPECIAL; ! 4358: handler = _tme_stp103x_ls_asi_slow; ! 4359: break; ! 4360: } ! 4361: ! 4362: /* get any ASI handler index: */ ! 4363: for (handler_i = 0; _tme_stp103x_ls_asi_handlers[handler_i] != handler; handler_i++) { ! 4364: assert (handler_i < (TME_ARRAY_ELS(_tme_stp103x_ls_asi_handlers) - 1)); ! 4365: } ! 4366: ! 4367: /* initialize this ASI: */ ! 4368: ic->tme_sparc_asis[asi].tme_sparc_asi_mask_flags = asi_mask_flags; ! 4369: ic->tme_sparc_asis[asi].tme_sparc_asi_handler = handler_i; ! 4370: } ! 4371: ! 4372: /* call the common sparc new function: */ ! 4373: return (tme_sparc_new(ic, args, extra, _output)); ! 4374: } ! 4375: ! 4376: /* this creates and returns a new stp1030: */ ! 4377: TME_ELEMENT_X_NEW_DECL(tme_ic_,sparc,stp1030) { ! 4378: return (_tme_stp103x_new(element, args, extra, _output, TRUE)); ! 4379: } ! 4380: ! 4381: #undef TME_SPARC_VERSION ! 4382: #define TME_SPARC_VERSION(ic) _TME_SPARC_VERSION(ic) ! 4383: #undef TME_SPARC_NWINDOWS ! 4384: #define TME_SPARC_NWINDOWS(ic) _TME_SPARC_NWINDOWS(ic) ! 4385: #undef _TME_SPARC_EXECUTE_NAME ! 4386: #undef _TME_SPARC_EXECUTE_OPMAP
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.