|
|
1.1.1.2 ! root 1: /* $Id: sparc-misc.c,v 1.14 2010/06/05 16:17:19 fredette Exp $ */ 1.1 root 2: 3: /* ic/sparc/sparc-misc.c - miscellaneous things for the SPARC emulator: */ 4: 5: /* 6: * Copyright (c) 2005 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: /* includes: */ 37: #include "sparc-impl.h" 38: 1.1.1.2 ! root 39: _TME_RCSID("$Id: sparc-misc.c,v 1.14 2010/06/05 16:17:19 fredette Exp $"); ! 40: ! 41: #include "sparc-bus-auto.c" 1.1 root 42: 43: /* our bus signal handler: */ 44: static int 45: _tme_sparc_bus_signal(struct tme_bus_connection *conn_bus, unsigned int signal) 46: { 47: struct tme_sparc *ic; 1.1.1.2 ! root 48: unsigned int level; 1.1 root 49: 50: /* recover our IC: */ 51: ic = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private; 52: 1.1.1.2 ! root 53: /* get the level. this must be an edge: */ ! 54: assert (signal & TME_BUS_SIGNAL_EDGE); ! 55: level = signal - TME_BUS_SIGNAL_EDGE; 1.1 root 56: signal = TME_BUS_SIGNAL_WHICH(signal); 1.1.1.2 ! root 57: level ^= signal; 1.1 root 58: 59: /* lock the external mutex: */ 60: tme_mutex_lock(&ic->tme_sparc_external_mutex); 61: 1.1.1.2 ! root 62: /* if the signal is asserted: */ ! 63: if (level == TME_BUS_SIGNAL_LEVEL_ASSERTED) { 1.1 root 64: 1.1.1.2 ! root 65: /* update the asserted flags for these signals: */ ! 66: if (__tme_predict_true(signal == TME_BUS_SIGNAL_BG)) { ! 67: tme_memory_atomic_write_flag(&ic->tme_sparc_external_bg_asserted, TRUE); ! 68: } ! 69: else if (signal == TME_BUS_SIGNAL_RESET) { ! 70: tme_memory_atomic_write_flag(&ic->tme_sparc_external_reset_asserted, TRUE); ! 71: } ! 72: else { ! 73: tme_memory_atomic_write_flag(&ic->tme_sparc_external_halt_asserted, TRUE); ! 74: } 1.1 root 75: } 76: 1.1.1.2 ! root 77: /* otherwise, the signal must be negated: */ 1.1 root 78: else { 1.1.1.2 ! root 79: assert (level == TME_BUS_SIGNAL_LEVEL_NEGATED); ! 80: ! 81: /* update the asserted or negated flags for these signals: */ ! 82: if (__tme_predict_true(signal == TME_BUS_SIGNAL_BG)) { ! 83: tme_memory_atomic_write_flag(&ic->tme_sparc_external_bg_asserted, FALSE); ! 84: } ! 85: else if (signal == TME_BUS_SIGNAL_RESET) { ! 86: tme_memory_atomic_write_flag(&ic->tme_sparc_external_reset_negated, TRUE); ! 87: } ! 88: else { ! 89: tme_memory_atomic_write_flag(&ic->tme_sparc_external_halt_negated, TRUE); ! 90: } 1.1 root 91: } 92: 1.1.1.2 ! root 93: /* write the external flag before any earlier signal flag write: */ ! 94: tme_memory_barrier(ic, sizeof(*ic), TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE); ! 95: tme_memory_atomic_write_flag(&ic->tme_sparc_external_flag, TRUE); ! 96: ! 97: /* notify any thread waiting on the external condition: */ ! 98: tme_cond_notify(&ic->tme_sparc_external_cond, FALSE); ! 99: 1.1 root 100: /* unlock the external mutex: */ 101: tme_mutex_unlock(&ic->tme_sparc_external_mutex); 102: return (TME_OK); 103: } 104: 105: /* our interrupt handler: */ 106: static int 107: _tme_sparc_bus_interrupt(struct tme_sparc_bus_connection *conn_sparc, unsigned int ipl) 108: { 109: struct tme_sparc *ic; 110: 111: /* recover our IC: */ 112: ic = conn_sparc->tme_sparc_bus_connection.tme_bus_connection.tme_connection_element->tme_element_private; 113: 114: /* lock the external mutex: */ 115: tme_mutex_lock(&ic->tme_sparc_external_mutex); 116: 117: /* set the interrupt line: */ 1.1.1.2 ! root 118: tme_memory_atomic_write8(&ic->tme_sparc_external_ipl, ! 119: ipl, ! 120: &ic->tme_sparc_external_ipl_rwlock, ! 121: sizeof(tme_uint8_t)); ! 122: ! 123: /* write the external flag before the earlier ipl write: */ ! 124: tme_memory_barrier(ic, sizeof(*ic), TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE); ! 125: tme_memory_atomic_write_flag(&ic->tme_sparc_external_flag, TRUE); ! 126: ! 127: /* notify any thread waiting on the external condition: */ ! 128: tme_cond_notify(&ic->tme_sparc_external_cond, FALSE); 1.1 root 129: 130: /* unlock the external mutex: */ 131: tme_mutex_unlock(&ic->tme_sparc_external_mutex); 132: return (TME_OK); 133: } 134: 135: /* the idle function, used when the processor is halted or stopped: */ 136: static void 137: tme_sparc_idle(struct tme_sparc *ic) 138: { 139: /* lock the external mutex: */ 140: tme_mutex_lock(&ic->tme_sparc_external_mutex); 141: 142: /* loop forever: */ 143: for (;;) { 144: 145: /* check for any external signal: */ 1.1.1.2 ! root 146: (*ic->_tme_sparc_external_check)(ic, TME_SPARC_EXTERNAL_CHECK_MUTEX_LOCKED); 1.1 root 147: 148: /* await an external condition: */ 149: tme_cond_wait_yield(&ic->tme_sparc_external_cond, &ic->tme_sparc_external_mutex); 150: } 151: } 152: 1.1.1.2 ! root 153: /* this resets idle detection: */ ! 154: static void ! 155: _tme_sparc_idle_reset(struct tme_sparc *ic) ! 156: { ! 157: ! 158: /* reset the main idle PC to state one, and assume that the idle ! 159: type has an idle PC range and zero the idle PC range upper ! 160: bound: */ ! 161: if (TME_SPARC_VERSION(ic) >= 9) { ! 162: #ifdef TME_HAVE_INT64_T ! 163: ic->tme_sparc_idle_pcs_64[0] = TME_SPARC_IDLE_TYPE_PC_STATE(1); ! 164: ic->tme_sparc_idle_pcs_64[1] = 0; ! 165: #endif /* TME_HAVE_INT64_T */ ! 166: } ! 167: else { ! 168: ic->tme_sparc_idle_pcs_32[0] = TME_SPARC_IDLE_TYPE_PC_STATE(1); ! 169: ic->tme_sparc_idle_pcs_32[1] = 0; ! 170: } ! 171: } ! 172: 1.1 root 173: /* the sparc thread: */ 174: static void 175: tme_sparc_thread(struct tme_sparc *ic) 176: { 177: 178: /* we use longjmp to redispatch: */ 179: do { } while (setjmp(ic->_tme_sparc_dispatcher)); 180: 181: /* we must not have a busy instruction TLB entry: */ 1.1.1.2 ! root 182: assert (ic->_tme_sparc_itlb_current_token == NULL); 1.1 root 183: 184: /* dispatch on the current mode: */ 185: switch (ic->_tme_sparc_mode) { 186: 187: case TME_SPARC_MODE_EXECUTION: 1.1.1.2 ! root 188: ! 189: /* if we may update the runlength with this instruction burst, ! 190: note its start time: */ ! 191: if (ic->tme_sparc_runlength_update_next == 0 ! 192: && (ic->_tme_sparc_instruction_burst_remaining ! 193: == ic->_tme_sparc_instruction_burst)) { ! 194: ic->tme_sparc_runlength.tme_runlength_cycles_start = tme_misc_cycles(); ! 195: } ! 196: 1.1 root 197: (*ic->_tme_sparc_execute)(ic); 198: /* NOTREACHED */ 199: 200: case TME_SPARC_MODE_STOP: 201: case TME_SPARC_MODE_HALT: 1.1.1.2 ! root 202: case TME_SPARC_MODE_OFF: 1.1 root 203: tme_sparc_idle(ic); 204: /* NOTREACHED */ 205: 1.1.1.2 ! root 206: case TME_SPARC_MODE_TIMING_LOOP: ! 207: tme_sparc_timing_loop_finish(ic); ! 208: /* NOTREACHED */ ! 209: 1.1 root 210: default: 211: abort(); 212: } 213: /* NOTREACHED */ 214: } 215: 216: /* the TLB filler for when we are on a generic bus: */ 217: static int 218: _tme_sparc_generic_tlb_fill(struct tme_sparc_bus_connection *conn_sparc, 219: struct tme_sparc_tlb *tlb, 1.1.1.2 ! root 220: tme_uint32_t asi_mask, 1.1 root 221: tme_bus_addr_t external_address, 222: unsigned int cycles) 223: { 224: struct tme_sparc *ic; 225: 226: /* recover our IC: */ 227: ic = conn_sparc->tme_sparc_bus_connection.tme_bus_connection.tme_connection_element->tme_element_private; 228: 229: /* call the generic bus TLB filler: */ 230: (ic->_tme_sparc_bus_generic->tme_bus_tlb_fill) 231: (ic->_tme_sparc_bus_generic, 232: &tlb->tme_sparc_tlb_bus_tlb, 233: external_address, 234: cycles); 235: 236: return (TME_OK); 237: } 238: 1.1.1.2 ! root 239: /* this sets the run length: */ ! 240: static void ! 241: _tme_sparc_runlength(struct tme_sparc *ic, ! 242: tme_uint32_t instruction_burst_msec) ! 243: { ! 244: union tme_value64 runlength_target_cycles; ! 245: unsigned int runlength_update_hz; ! 246: ! 247: /* set the run length target cycles: */ ! 248: runlength_target_cycles.tme_value64_uint32_lo ! 249: = (tme_misc_cycles_per_ms() ! 250: * instruction_burst_msec); ! 251: runlength_target_cycles.tme_value64_uint32_hi = 0; ! 252: tme_runlength_target_cycles(&ic->tme_sparc_runlength, runlength_target_cycles); ! 253: ! 254: /* set the run length update period: */ ! 255: runlength_update_hz = 50; ! 256: ic->tme_sparc_runlength_update_period ! 257: = (((1000 ! 258: + (instruction_burst_msec - 1) ! 259: / instruction_burst_msec) ! 260: + (runlength_update_hz - 1)) ! 261: / runlength_update_hz); ! 262: } ! 263: 1.1 root 264: /* the sparc command function: */ 265: static int 266: _tme_sparc_command(struct tme_element *element, const char * const * args, char **_output) 267: { 268: struct tme_sparc *ic; 269: unsigned int idle_type_saved; 1.1.1.2 ! root 270: tme_uint32_t instruction_burst_msec; ! 271: int usage; ! 272: tme_uint32_t prom_delay_factor; 1.1 root 273: 274: /* recover our IC: */ 275: ic = (struct tme_sparc *) element->tme_element_private; 276: 277: /* the "idle-type" command: */ 278: if (TME_ARG_IS(args[1], "idle-type")) { 279: 280: /* save the current idle type and set it to none: */ 281: idle_type_saved = ic->tme_sparc_idle_type; 282: ic->tme_sparc_idle_type = TME_SPARC_IDLE_TYPE_NULL; 283: 284: /* if we're not setting the idle type to none: */ 285: if (!TME_ARG_IS(args[2], "none")) { 286: 287: /* check for a supported idle type: */ 288: #define _TME_SPARC_IDLE_TYPE(x, s) \ 289: do { \ 1.1.1.2 ! root 290: if (TME_SPARC_IDLE_TYPE_IS_SUPPORTED(ic, x) \ 1.1 root 291: && TME_ARG_IS(args[2], s)) { \ 292: ic->tme_sparc_idle_type = (x); \ 293: } \ 294: } while (/* CONSTCOND */ 0) 295: _TME_SPARC_IDLE_TYPE(TME_SPARC_IDLE_TYPE_NETBSD32_TYPE_0, "netbsd32-type-0"); 296: _TME_SPARC_IDLE_TYPE(TME_SPARC_IDLE_TYPE_SUNOS32_TYPE_0, "sunos32-type-0"); 1.1.1.2 ! root 297: _TME_SPARC_IDLE_TYPE(TME_SPARC_IDLE_TYPE_NETBSD32_TYPE_1, "netbsd32-type-1"); ! 298: _TME_SPARC_IDLE_TYPE(TME_SPARC_IDLE_TYPE_NETBSD64_TYPE_0, "netbsd64-type-0"); ! 299: _TME_SPARC_IDLE_TYPE(TME_SPARC_IDLE_TYPE_NETBSD64_TYPE_1, "netbsd64-type-1"); ! 300: _TME_SPARC_IDLE_TYPE(TME_SPARC_IDLE_TYPE_SUNOS64_TYPE_0, "sunos64-type-0"); 1.1 root 301: #undef _TME_SPARC_IDLE_TYPE 302: 303: /* if the idle type isn't supported: */ 304: if (ic->tme_sparc_idle_type == TME_SPARC_IDLE_TYPE_NULL) { 305: 306: /* restore the idle type and return a usage: */ 307: ic->tme_sparc_idle_type = idle_type_saved; 308: 309: tme_output_append_error(_output, 310: "%s %s idle-type { none", 311: _("usage:"), 312: args[0]); 313: 314: /* add in the supported idle types: */ 315: #define _TME_SPARC_IDLE_TYPE(x, s) \ 316: do { \ 1.1.1.2 ! root 317: if (TME_SPARC_IDLE_TYPE_IS_SUPPORTED(ic, x)) {\ 1.1 root 318: tme_output_append_error(_output, " | %s", \ 319: s); \ 320: } \ 321: } while (/* CONSTCOND */ 0) 322: _TME_SPARC_IDLE_TYPE(TME_SPARC_IDLE_TYPE_NETBSD32_TYPE_0, "netbsd32-type-0"); 323: _TME_SPARC_IDLE_TYPE(TME_SPARC_IDLE_TYPE_SUNOS32_TYPE_0, "sunos32-type-0"); 1.1.1.2 ! root 324: _TME_SPARC_IDLE_TYPE(TME_SPARC_IDLE_TYPE_NETBSD32_TYPE_1, "netbsd32-type-1"); ! 325: _TME_SPARC_IDLE_TYPE(TME_SPARC_IDLE_TYPE_NETBSD64_TYPE_0, "netbsd64-type-0"); ! 326: _TME_SPARC_IDLE_TYPE(TME_SPARC_IDLE_TYPE_NETBSD64_TYPE_1, "netbsd64-type-1"); ! 327: _TME_SPARC_IDLE_TYPE(TME_SPARC_IDLE_TYPE_SUNOS64_TYPE_0, "sunos64-type-0"); 1.1 root 328: #undef _TME_SPARC_IDLE_TYPE 329: 330: tme_output_append_error(_output, " }"); 331: return (EINVAL); 332: } 333: } 334: 335: /* poison all idle type state: */ 1.1.1.2 ! root 336: _tme_sparc_idle_reset(ic); ! 337: } ! 338: ! 339: /* the run-length command: */ ! 340: else if (TME_ARG_IS(args[1], "run-length")) { ! 341: ! 342: /* get the run length, in milliseconds: */ ! 343: instruction_burst_msec = tme_misc_unumber_parse(args[2], 0); ! 344: ! 345: /* if this command is bad: */ ! 346: if (instruction_burst_msec == 0 ! 347: || args[3] != NULL) { ! 348: tme_output_append_error(_output, ! 349: "%s run-length %s", ! 350: _("usage:"), ! 351: _("MILLISECONDS")); ! 352: } ! 353: ! 354: /* otherwise, set the run length: */ ! 355: else { ! 356: _tme_sparc_runlength(ic, ! 357: instruction_burst_msec); ! 358: } ! 359: } ! 360: ! 361: /* the prom-delay-factor command: */ ! 362: else if (TME_ARG_IS(args[1], "prom-delay-factor")) { ! 363: ! 364: /* get the PROM delay factor: */ ! 365: usage = FALSE; ! 366: if (TME_ARG_IS(args[2], "best")) { ! 367: prom_delay_factor = TME_SPARC_PROM_DELAY_FACTOR_BEST; ! 368: } ! 369: else if (TME_ARG_IS(args[2], "uncorrected")) { ! 370: prom_delay_factor = TME_SPARC_PROM_DELAY_FACTOR_UNCORRECTED; ! 371: } ! 372: else if (TME_ARG_IS(args[2], "min")) { ! 373: prom_delay_factor = TME_SPARC_PROM_DELAY_FACTOR_MIN; ! 374: } ! 375: else { ! 376: prom_delay_factor = tme_misc_unumber_parse_any(args[2], &usage); ! 377: } ! 378: if (usage) { ! 379: tme_output_append_error(_output, ! 380: "%s prom-delay-factor { best | uncorrected | min | %s }", ! 381: _("usage:"), ! 382: _("FACTOR")); ! 383: } ! 384: else { ! 385: ic->tme_sparc_prom_delay_factor = prom_delay_factor; ! 386: } 1.1 root 387: } 388: 389: /* any other command: */ 390: else { 391: if (args[1] != NULL) { 392: tme_output_append_error(_output, 393: "%s '%s', ", 394: _("unknown command"), 395: args[1]); 396: } 397: tme_output_append_error(_output, 1.1.1.2 ! root 398: _("available %s commands:%s run-length"), 1.1 root 399: args[0], 1.1.1.2 ! root 400: (TME_SPARC_IDLE_TYPE_IS_SUPPORTED(ic, (0 - (unsigned int) 1)) 1.1 root 401: ? " idle-type" 402: : "")); 403: return (EINVAL); 404: } 405: 406: return (TME_OK); 407: } 408: 409: /* the connection scorer: */ 410: static int 411: _tme_sparc_connection_score(struct tme_connection *conn, unsigned int *_score) 412: { 413: struct tme_sparc_bus_connection *conn_sparc; 1.1.1.2 ! root 414: struct tme_upa_bus_connection *conn_upa; 1.1 root 415: struct tme_bus_connection *conn_bus; 416: unsigned int score; 417: 418: /* assume that this connection is useless: */ 419: score = 0; 420: 421: /* dispatch on the connection type: */ 422: switch (conn->tme_connection_type) { 423: 424: /* this must be a bus, and not another sparc chip: */ 425: case TME_CONNECTION_BUS_SPARC: 1.1.1.2 ! root 426: conn_sparc = (struct tme_sparc_bus_connection *) conn->tme_connection_other; ! 427: conn_bus = &conn_sparc->tme_sparc_bus_connection; ! 428: if (conn_bus->tme_bus_tlb_set_add != NULL 1.1 root 429: && conn_sparc->tme_sparc_bus_tlb_fill != NULL 430: && conn_sparc->tme_sparc_bus_fpu_strict == NULL) { 431: score = 10; 432: } 433: break; 434: 1.1.1.2 ! root 435: /* this must be a controller, and not another agent: */ ! 436: case TME_CONNECTION_BUS_UPA: ! 437: conn_upa = (struct tme_upa_bus_connection *) conn->tme_connection_other; ! 438: conn_bus = &conn_upa->tme_upa_bus_connection; ! 439: if (conn_upa->tme_upa_bus_interrupt != NULL ! 440: && conn_bus->tme_bus_tlb_set_add != NULL ! 441: && conn_bus->tme_bus_tlb_fill != NULL) { ! 442: score = 10; ! 443: } ! 444: break; ! 445: 1.1 root 446: /* this must be a bus, and not another chip: */ 447: case TME_CONNECTION_BUS_GENERIC: 1.1.1.2 ! root 448: conn_bus = (struct tme_bus_connection *) conn->tme_connection_other; ! 449: if (conn_bus->tme_bus_tlb_set_add != NULL 1.1 root 450: && conn_bus->tme_bus_tlb_fill != NULL) { 451: score = 1; 452: } 453: break; 454: 455: default: abort(); 456: } 457: 458: *_score = score; 459: return (TME_OK); 460: } 461: 462: /* this makes a new connection: */ 463: static int 464: _tme_sparc_connection_make(struct tme_connection *conn, unsigned int state) 465: { 466: struct tme_sparc *ic; 1.1.1.2 ! root 467: struct tme_upa_bus_connection *conn_upa; 1.1 root 468: struct tme_sparc_bus_connection *conn_sparc; 469: struct tme_bus_connection *conn_bus; 470: struct tme_connection *conn_other; 1.1.1.2 ! root 471: struct tme_bus_tlb_set_info tlb_set_info; ! 472: struct tme_sparc_tlb *tlb; ! 473: struct tme_token *token; ! 474: int rc; 1.1 root 475: 476: /* since the CPU is halted, it won't be making any connection calls, 477: so we only have to do work when the connection is fully made: */ 478: if (state == TME_CONNECTION_FULL) { 479: 480: /* recover our IC: */ 481: ic = conn->tme_connection_element->tme_element_private; 482: 483: /* dispatch on the connection type: */ 484: conn_other = conn->tme_connection_other; 485: switch (conn->tme_connection_type) { 486: 487: case TME_CONNECTION_BUS_SPARC: 1.1.1.2 ! root 488: conn_sparc = (struct tme_sparc_bus_connection *) conn_other; 1.1 root 489: ic->_tme_sparc_bus_connection = conn_sparc; 1.1.1.2 ! root 490: conn_bus = &conn_sparc->tme_sparc_bus_connection; 1.1 root 491: break; 492: 1.1.1.2 ! root 493: case TME_CONNECTION_BUS_UPA: ! 494: conn_upa = (struct tme_upa_bus_connection *) conn_other; ! 495: ic->_tme_upa_bus_connection = conn_upa; ! 496: assert (&conn_upa->tme_upa_bus_connection == (struct tme_bus_connection *) conn_other); ! 497: /* FALLTHROUGH */ ! 498: 1.1 root 499: /* we need an adaptation layer: */ 500: case TME_CONNECTION_BUS_GENERIC: 1.1.1.2 ! root 501: conn_bus = (struct tme_bus_connection *) conn_other; 1.1 root 502: conn_sparc = tme_new0(struct tme_sparc_bus_connection, 1); 503: conn_sparc->tme_sparc_bus_connection.tme_bus_connection.tme_connection_element = conn->tme_connection_element; 504: conn_sparc->tme_sparc_bus_tlb_fill = _tme_sparc_generic_tlb_fill; 505: ic->_tme_sparc_bus_connection = conn_sparc; 506: ic->_tme_sparc_bus_generic = conn_bus; 507: break; 508: 509: default: abort(); 510: } 511: 1.1.1.2 ! root 512: /* make the TLB set information: */ ! 513: memset(&tlb_set_info, 0, sizeof(tlb_set_info)); ! 514: tlb_set_info.tme_bus_tlb_set_info_token0 = &ic->tme_sparc_tlb_tokens[0]; ! 515: tlb_set_info.tme_bus_tlb_set_info_token_stride = sizeof(struct tme_token); ! 516: tlb_set_info.tme_bus_tlb_set_info_token_count = TME_ARRAY_ELS(ic->tme_sparc_tlbs); ! 517: tlb_set_info.tme_bus_tlb_set_info_bus_context = &ic->tme_sparc_memory_context_default; ! 518: ! 519: #if TME_HAVE_RECODE ! 520: ! 521: /* if this is a v9 CPU, and we have 64-bit recode support: */ ! 522: if (TME_SPARC_VERSION(ic) >= 9) { ! 523: #if TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 ! 524: ! 525: /* we will use the tokens in the 64-bit recode TLBs: */ ! 526: tlb_set_info.tme_bus_tlb_set_info_token0 = &ic->tme_sparc_recode_tlb64s[0].tme_recode_tlb_c16_a64_token; ! 527: tlb_set_info.tme_bus_tlb_set_info_token_stride = sizeof(ic->tme_sparc_recode_tlb64s[0]); ! 528: #endif /* TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 */ ! 529: } ! 530: ! 531: /* otherwise, this is a v7 or v8 CPU: */ ! 532: else { ! 533: ! 534: /* we will use the tokens in the 32-bit recode TLBs: */ ! 535: tlb_set_info.tme_bus_tlb_set_info_token0 = &ic->tme_sparc_recode_tlb32s[0].tme_recode_tlb_c16_a32_token; ! 536: tlb_set_info.tme_bus_tlb_set_info_token_stride = sizeof(ic->tme_sparc_recode_tlb32s[0]); ! 537: } ! 538: ! 539: #endif /* TME_HAVE_RECODE */ ! 540: ! 541: /* initialize the TLBs in the set: */ ! 542: tlb = &ic->tme_sparc_tlbs[0]; ! 543: token = tlb_set_info.tme_bus_tlb_set_info_token0; ! 544: do { ! 545: ! 546: /* initialize this token: */ ! 547: tme_token_init(token); ! 548: ! 549: /* connect this token with this TLB: */ ! 550: tlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token = token; ! 551: ! 552: /* advance: */ ! 553: token = (struct tme_token *) (tlb_set_info.tme_bus_tlb_set_info_token_stride + (tme_uint8_t *) token); ! 554: } while (++tlb <= &ic->tme_sparc_tlbs[TME_ARRAY_ELS(ic->tme_sparc_tlbs) - 1]); ! 555: ! 556: /* add the TLB set: */ ! 557: rc = ((*conn_bus->tme_bus_tlb_set_add) ! 558: (conn_bus, ! 559: &tlb_set_info)); ! 560: assert (rc == TME_OK); ! 561: ! 562: /* if this is a v7 cpu: */ ! 563: if (TME_SPARC_VERSION(ic) == 7) { ! 564: ! 565: /* get the maximum bus context from the bus: */ ! 566: ic->tme_sparc_memory_context_max = tlb_set_info.tme_bus_tlb_set_info_bus_context_max; ! 567: } ! 568: ! 569: #ifdef TME_HAVE_RECODE ! 570: ! 571: /* the maximum bus context must fit in 16 bits: */ ! 572: assert (ic->tme_sparc_memory_context_max <= 0xffff); ! 573: ! 574: #endif /* TME_HAVE_RECODE */ 1.1 root 575: } 576: 577: /* NB: the machine needs to issue a reset to bring the CPU out of halt. */ 578: return (TME_OK); 579: } 580: 581: /* this breaks a connection: */ 582: static int 583: _tme_sparc_connection_break(struct tme_connection *conn, unsigned int state) 584: { 585: abort(); 586: return (0); 587: } 588: 589: /* this makes new connection sides: */ 590: static int 591: _tme_sparc_connections_new(struct tme_element *element, const char * const *args, struct tme_connection **_conns, char **_output) 592: { 1.1.1.2 ! root 593: struct tme_sparc *ic; ! 594: struct tme_upa_bus_connection *conn_upa; 1.1 root 595: struct tme_sparc_bus_connection *conn_sparc; 596: struct tme_bus_connection *conn_bus; 597: struct tme_connection *conn; 598: 1.1.1.2 ! root 599: /* recover our data structure: */ ! 600: ic = element->tme_element_private; ! 601: 1.1 root 602: /* if we already have a bus connection, we can take no more connections: */ 1.1.1.2 ! root 603: if (ic->_tme_sparc_bus_connection != NULL) { 1.1 root 604: return (TME_OK); 605: } 606: 1.1.1.2 ! root 607: /* if this is a v9 CPU: */ ! 608: if (TME_SPARC_VERSION(ic) >= 9) { 1.1 root 609: 1.1.1.2 ! root 610: /* create our side of a UPA bus connection: */ ! 611: conn_upa = tme_new0(struct tme_upa_bus_connection, 1); ! 612: conn_upa->tme_upa_bus_connection.tme_bus_connection.tme_connection_type = TME_CONNECTION_BUS_UPA; ! 613: #ifdef TME_HAVE_INT64_T ! 614: conn_upa->tme_upa_bus_interrupt = ic->_tme_sparc_upa_interrupt; ! 615: #endif /* TME_HAVE_INT64_T */ ! 616: conn_bus = &conn_upa->tme_upa_bus_connection; ! 617: conn_bus->tme_bus_tlb_fill = ic->_tme_sparc_tlb_fill; ! 618: } 1.1 root 619: 1.1.1.2 ! root 620: /* otherwise, this is a v7 or v8 CPU: */ ! 621: else { 1.1 root 622: 1.1.1.2 ! root 623: /* create our side of a generic bus connection: */ ! 624: conn_bus = tme_new0(struct tme_bus_connection, 1); ! 625: conn_bus->tme_bus_connection.tme_connection_type = TME_CONNECTION_BUS_GENERIC; ! 626: conn_bus->tme_bus_signal = _tme_sparc_bus_signal; ! 627: conn_bus->tme_bus_tlb_set_add = NULL; ! 628: conn_bus->tme_bus_tlb_fill = NULL; ! 629: conn = &conn_bus->tme_bus_connection; ! 630: conn->tme_connection_next = *_conns; ! 631: conn->tme_connection_score = _tme_sparc_connection_score; ! 632: conn->tme_connection_make = _tme_sparc_connection_make; ! 633: conn->tme_connection_break = _tme_sparc_connection_break; ! 634: ! 635: /* add this connection to the set of possibilities: */ ! 636: *_conns = conn; ! 637: ! 638: /* create our side of a sparc bus connection: */ ! 639: conn_sparc = tme_new0(struct tme_sparc_bus_connection, 1); ! 640: conn_sparc->tme_sparc_bus_connection.tme_bus_connection.tme_connection_type = TME_CONNECTION_BUS_SPARC; ! 641: conn_sparc->tme_sparc_bus_interrupt = _tme_sparc_bus_interrupt; ! 642: conn_sparc->tme_sparc_bus_tlb_fill = NULL; ! 643: conn_sparc->tme_sparc_bus_fpu_strict = tme_sparc_fpu_strict; ! 644: conn_bus = &conn_sparc->tme_sparc_bus_connection; ! 645: conn_bus->tme_bus_tlb_fill = NULL; ! 646: } 1.1 root 647: 1.1.1.2 ! root 648: /* finish the preferred bus connection: */ ! 649: conn_bus->tme_bus_signal = _tme_sparc_bus_signal; ! 650: conn_bus->tme_bus_tlb_set_add = NULL; 1.1 root 651: conn = &conn_bus->tme_bus_connection; 652: conn->tme_connection_next = *_conns; 653: conn->tme_connection_score = _tme_sparc_connection_score; 654: conn->tme_connection_make = _tme_sparc_connection_make; 655: conn->tme_connection_break = _tme_sparc_connection_break; 656: 657: /* add this connection to the set of possibilities: */ 658: *_conns = conn; 659: 660: /* done: */ 661: return (TME_OK); 662: } 663: 1.1.1.2 ! root 664: /* the common sparc synchronization initialization: */ ! 665: void ! 666: tme_sparc_sync_init(struct tme_sparc *ic) ! 667: { ! 668: ! 669: /* initialize the external mutex: */ ! 670: tme_mutex_init(&ic->tme_sparc_external_mutex); ! 671: ! 672: /* initialize the external condition: */ ! 673: tme_cond_init(&ic->tme_sparc_external_cond); ! 674: } ! 675: 1.1 root 676: /* the common sparc new function: */ 677: int 678: tme_sparc_new(struct tme_sparc *ic, const char * const *args, const void *extra, char **_output) 679: { 680: struct tme_element *element; 681: int arg_i; 682: int usage; 1.1.1.2 ! root 683: tme_uint32_t cycles_per_ms; ! 684: tme_uint32_t cycles_scaled_per_ms; ! 685: const char *cycles_scaled_per_ms_arg; ! 686: unsigned int cwp; ! 687: unsigned int cwp_offset; ! 688: tme_uint32_t asi; 1.1 root 689: 690: /* assume that we have no FPU: */ 691: ic->tme_sparc_fpu_fsr = TME_SPARC_FSR_VER_missing; 692: 1.1.1.2 ! root 693: /* if we don't have a tlb page size: */ ! 694: if (ic->tme_sparc_tlb_page_size_log2 == 0) { ! 695: ! 696: /* assume that we are in a machine with a 4K page size: */ ! 697: /* XXX FIXME - we never attempt to discover the machine's actual ! 698: page size. however, using the wrong page size doesn't affect ! 699: correctness, only performance. using a smaller page size means ! 700: that accesses to different parts of the same true page can be ! 701: spread over multiple DTLB entries. using a larger page size ! 702: means that accesses to adjacent true pages can collide in one ! 703: DTLB entry. we assume that using a smaller page size hurts ! 704: performance less than using a larger page size: */ ! 705: ic->tme_sparc_tlb_page_size_log2 = 12; /* log2(4096) */ ! 706: } ! 707: 1.1 root 708: /* check our arguments: */ 709: arg_i = 1; 710: usage = FALSE; 1.1.1.2 ! root 711: cycles_per_ms = tme_misc_cycles_per_ms(); ! 712: cycles_scaled_per_ms = cycles_per_ms; ! 713: cycles_scaled_per_ms_arg = NULL; ! 714: ic->tme_sparc_prom_delay_factor = TME_SPARC_PROM_DELAY_FACTOR_BEST; 1.1 root 715: for (;;) { 716: 1.1.1.2 ! root 717: /* if this is a cycles scaling argument: */ ! 718: if (TME_ARG_IS(args[arg_i + 0], "tick-frequency")) { ! 719: cycles_scaled_per_ms_arg = args[arg_i + 0]; ! 720: cycles_scaled_per_ms = tme_misc_unumber_parse_any(args[arg_i + 1], &usage) / 1000; ! 721: if (usage) { ! 722: break; ! 723: } ! 724: arg_i += 2; 1.1 root 725: } 726: 727: /* if we've run out of arguments: */ 728: else if (args[arg_i + 0] == NULL) { 729: break; 730: } 731: 732: /* this is either a bad argument or an FPU argument: */ 733: else { 734: 735: /* if this is not an FPU argument: */ 736: if (!tme_sparc_fpu_new(ic, args, &arg_i, &usage, _output)) { 737: tme_output_append_error(_output, 738: "%s %s, ", 739: args[arg_i], 740: _("unexpected")); 741: usage = TRUE; 742: } 743: 744: if (usage) { 745: break; 746: } 747: } 748: } 749: 1.1.1.2 ! root 750: /* set the cycles scaling: */ ! 751: if (cycles_scaled_per_ms == 0) { ! 752: if (!usage) { ! 753: tme_output_append_error(_output, ! 754: "tick-frequency %s %s, ", ! 755: cycles_scaled_per_ms_arg, ! 756: _("too small")); ! 757: usage = TRUE; ! 758: } ! 759: } ! 760: else { ! 761: tme_misc_cycles_scaling(&ic->tme_sparc_cycles_scaling, ! 762: cycles_scaled_per_ms, ! 763: cycles_per_ms); ! 764: tme_misc_cycles_scaling(&ic->tme_sparc_cycles_unscaling, ! 765: cycles_per_ms, ! 766: cycles_scaled_per_ms); ! 767: ic->tme_sparc_cycles_scaled_per_usec = (cycles_scaled_per_ms + 999) / 1000; ! 768: } ! 769: 1.1 root 770: if (usage) { 771: tme_output_append_error(_output, 1.1.1.2 ! root 772: "%s %s [ tick-frequency %s ]", 1.1 root 773: _("usage:"), 1.1.1.2 ! root 774: args[0], ! 775: _("TICK-FREQUENCY")); 1.1 root 776: tme_sparc_fpu_usage(ic, _output); 777: tme_free(ic); 778: return (EINVAL); 779: } 780: 781: /* we have no bus connection yet: */ 782: ic->_tme_sparc_bus_connection = NULL; 783: 784: /* fill the element: */ 785: element = ic->tme_sparc_element; 786: element->tme_element_private = ic; 787: element->tme_element_connections_new = _tme_sparc_connections_new; 788: element->tme_element_command = _tme_sparc_command; 789: 1.1.1.2 ! root 790: /* initialize the instruction burst runlength state: */ 1.1 root 791: ic->_tme_sparc_instruction_burst = 800; 1.1.1.2 ! root 792: ic->tme_sparc_runlength.tme_runlength_history_count = 64; ! 793: tme_runlength_init(&ic->tme_sparc_runlength); ! 794: _tme_sparc_runlength(ic, 2); ! 795: ic->tme_sparc_runlength_update_next = ic->tme_sparc_runlength_update_period; ! 796: ! 797: /* set the idle instruction burst size: */ ! 798: ic->_tme_sparc_instruction_burst_idle = 10; ! 799: ! 800: /* start the first instruction burst: */ 1.1 root 801: ic->_tme_sparc_instruction_burst_remaining 802: = ic->_tme_sparc_instruction_burst; 1.1.1.2 ! root 803: ic->_tme_sparc_instruction_burst_other = TRUE; 1.1 root 804: 1.1.1.2 ! root 805: /* force the processor to be off: */ ! 806: ic->_tme_sparc_mode = TME_SPARC_MODE_OFF; ! 807: ! 808: /* initialize the external state: */ ! 809: tme_memory_atomic_init_flag(&ic->tme_sparc_external_flag, FALSE); ! 810: tme_memory_atomic_init_flag(&ic->tme_sparc_external_reset_asserted, TRUE); ! 811: tme_memory_atomic_init_flag(&ic->tme_sparc_external_reset_negated, FALSE); ! 812: tme_memory_atomic_init_flag(&ic->tme_sparc_external_halt_asserted, FALSE); ! 813: tme_memory_atomic_init_flag(&ic->tme_sparc_external_halt_negated, FALSE); ! 814: tme_memory_atomic_init_flag(&ic->tme_sparc_external_bg_asserted, FALSE); ! 815: ic->tme_sparc_external_ipl = TME_SPARC_IPL_NONE; ! 816: tme_rwlock_init(&ic->tme_sparc_external_ipl_rwlock); ! 817: ! 818: /* update the CWP offset: */ ! 819: if (TME_SPARC_VERSION(ic) >= 9) { ! 820: cwp = ic->tme_sparc64_ireg_cwp; ! 821: TME_SPARC64_CWP_UPDATE(ic, cwp, cwp_offset); ! 822: } ! 823: else { ! 824: cwp = TME_FIELD_MASK_EXTRACTU(ic->tme_sparc32_ireg_psr, TME_SPARC32_PSR_CWP); ! 825: TME_SPARC32_CWP_UPDATE(ic, cwp, cwp_offset); ! 826: } ! 827: ! 828: /* if the specific CPU doesn't provide any ASI handlers: */ ! 829: if (ic->_tme_sparc_ls_asi_handlers == NULL) { ! 830: ! 831: if (TME_SPARC_VERSION(ic) >= 9) { ! 832: ! 833: /* this shouldn't happen: */ ! 834: abort(); ! 835: } ! 836: ! 837: else { ! 838: ! 839: /* by default, all sparc32 ASIs are special, except for the ! 840: required ASIs: */ ! 841: for (asi = 0; asi < TME_ARRAY_ELS(ic->tme_sparc_asis); asi++) { ! 842: ic->tme_sparc_asis[asi].tme_sparc_asi_mask_flags = TME_SPARC32_ASI_MASK_FLAG_SPECIAL; ! 843: } ! 844: ic->tme_sparc_asis[TME_SPARC32_ASI_UI].tme_sparc_asi_mask_flags = !TME_SPARC32_ASI_MASK_FLAG_SPECIAL; ! 845: ic->tme_sparc_asis[TME_SPARC32_ASI_SI].tme_sparc_asi_mask_flags = !TME_SPARC32_ASI_MASK_FLAG_SPECIAL; ! 846: ic->tme_sparc_asis[TME_SPARC32_ASI_UD].tme_sparc_asi_mask_flags = !TME_SPARC32_ASI_MASK_FLAG_SPECIAL; ! 847: ic->tme_sparc_asis[TME_SPARC32_ASI_SD].tme_sparc_asi_mask_flags = !TME_SPARC32_ASI_MASK_FLAG_SPECIAL; ! 848: } ! 849: } 1.1 root 850: 851: /* poison all idle type state: */ 1.1.1.2 ! root 852: _tme_sparc_idle_reset(ic); ! 853: ! 854: /* initialize recoding: */ ! 855: tme_sparc_recode_init(ic); 1.1 root 856: 857: /* start the sparc thread: */ 858: tme_thread_create((tme_thread_t) tme_sparc_thread, ic); 859: 860: return (TME_OK); 861: } 862: 863: /* this redispatches: */ 864: void 865: tme_sparc_redispatch(struct tme_sparc *ic) 866: { 1.1.1.2 ! root 867: struct tme_token *token; ! 868: ! 869: /* end any recode verifying: */ ! 870: tme_sparc_recode_verify_end(ic, TME_SPARC_TRAP_none); 1.1 root 871: 872: /* if we have a busy instruction TLB entry: */ 1.1.1.2 ! root 873: token = ic->_tme_sparc_itlb_current_token; ! 874: if (__tme_predict_true(token != NULL)) { 1.1 root 875: 876: /* unbusy and forget the instruction TLB entry: */ 1.1.1.2 ! root 877: tme_token_unbusy(token); ! 878: ic->_tme_sparc_itlb_current_token = NULL; 1.1 root 879: } 880: 881: /* do the redispatch: */ 882: #ifdef _TME_SPARC_STATS 883: ic->tme_sparc_stats.tme_sparc_stats_redispatches++; 884: #endif /* _TME_SPARC_STATS */ 885: longjmp(ic->_tme_sparc_dispatcher, 1); 886: } 887: 888: /* our global verify hook function: */ 889: #undef tme_sparc_verify_hook 890: void 891: tme_sparc_verify_hook(void) 892: { 893: } 894: 895: /* the common sparc reset function: */ 896: void 897: tme_sparc_do_reset(struct tme_sparc *ic) 898: { 899: 900: /* if this is a v7 or v8 CPU: */ 901: if (ic->tme_sparc_version < 9) { 902: 903: /* set the initial PCs: */ 904: ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT) = 0; 905: ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT_NEXT) = sizeof(tme_uint32_t); 906: 907: /* force supervisor mode, traps disabled: */ 908: ic->tme_sparc32_ireg_psr 909: = ((ic->tme_sparc32_ireg_psr 910: & ~TME_SPARC32_PSR_ET) 911: | TME_SPARC32_PSR_S); 912: } 913: 914: /* otherwise, this is a v9 CPU: */ 915: else { 916: 917: /* XXX WRITEME */ 918: abort(); 919: } 920: 921: /* reset the FPU: */ 922: tme_sparc_fpu_reset(ic); 923: 924: /* poison all idle type state, to force the idle type to retrain: */ 1.1.1.2 ! root 925: _tme_sparc_idle_reset(ic); 1.1 root 926: 927: /* start execution: */ 928: ic->_tme_sparc_mode = TME_SPARC_MODE_EXECUTION; 929: tme_sparc_redispatch(ic); 930: } 931: 932: /* the common sparc idle function: */ 933: void 934: tme_sparc_do_idle(struct tme_sparc *ic) 935: { 936: 937: /* NB: since the interrupt that causes us to leave stop mode will 938: call tme_sparc32_trap_preinstruction(), this function can only be 939: called on a preinstruction boundary (i.e., while PC still points 940: to the (completed!) instruction that triggered the idle 941: condition): */ 942: 1.1.1.2 ! root 943: /* this will not be a full instruction burst: */ ! 944: ic->_tme_sparc_instruction_burst_other = TRUE; ! 945: 1.1 root 946: /* redispatch into stop mode: */ 947: ic->_tme_sparc_mode = TME_SPARC_MODE_STOP; 948: tme_sparc_redispatch(ic); 949: } 950: 1.1.1.2 ! root 951: /* this checks for external signals: */ 1.1 root 952: void 1.1.1.2 ! root 953: tme_sparc32_external_check(struct tme_sparc *ic, ! 954: int flags) 1.1 root 955: { 956: unsigned int ipl; 957: 1.1.1.2 ! root 958: /* if RESET has been negated since the last check: */ ! 959: if (__tme_predict_false(tme_memory_atomic_read_flag(&ic->tme_sparc_external_reset_negated))) { ! 960: ! 961: /* clear the RESET asserted flag, then clear the RESET negated ! 962: flag: */ ! 963: tme_memory_atomic_write_flag(&ic->tme_sparc_external_reset_asserted, FALSE); ! 964: tme_memory_barrier(ic, sizeof(*ic), TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE); ! 965: tme_memory_atomic_write_flag(&ic->tme_sparc_external_reset_negated, FALSE); ! 966: ! 967: /* start reset trap processing: */ ! 968: if (flags & TME_SPARC_EXTERNAL_CHECK_MUTEX_LOCKED) { ! 969: tme_mutex_unlock(&ic->tme_sparc_external_mutex); ! 970: } ! 971: tme_sparc32_trap_preinstruction(ic, TME_SPARC32_TRAP_reset); 1.1 root 972: } 973: 1.1.1.2 ! root 974: /* if RESET is asserted: */ ! 975: if (__tme_predict_false(tme_memory_atomic_read_flag(&ic->tme_sparc_external_reset_asserted))) { ! 976: ! 977: /* halt: */ ! 978: if (flags & TME_SPARC_EXTERNAL_CHECK_MUTEX_LOCKED) { ! 979: tme_mutex_unlock(&ic->tme_sparc_external_mutex); ! 980: } 1.1 root 981: ic->_tme_sparc_mode = TME_SPARC_MODE_HALT; 982: tme_sparc_redispatch(ic); 983: } 984: 1.1.1.2 ! root 985: /* if an interrupt needs service: */ ! 986: ipl = tme_memory_atomic_read8(&ic->tme_sparc_external_ipl, ! 987: &ic->tme_sparc_external_ipl_rwlock, ! 988: sizeof(tme_uint8_t)); ! 989: assert (ipl <= TME_SPARC_IPL_MAX); ! 990: if (ipl >= TME_SPARC_IPL_MIN) { ! 991: ! 992: /* if we can't service this interrupt now, we need to set the ! 993: external flag again so we keep coming back to try again. ! 994: ! 995: even if we do service this interrupt now, we still need to set ! 996: the external flag again - because we may not service all of the ! 997: devices interrupting at this level, and the bus won't bother to ! 998: make another interrupt level callout if the level isn't ! 999: actually changing. we need to set the external flag again so ! 1000: we keep coming back to try again: */ ! 1001: tme_memory_atomic_write_flag(&ic->tme_sparc_external_flag, TRUE); ! 1002: ! 1003: /* if we are not halted and an interrupt can be serviced, start ! 1004: interrupt trap processing: */ ! 1005: if (ic->_tme_sparc_mode != TME_SPARC_MODE_HALT ! 1006: && (ic->tme_sparc32_ireg_psr & TME_SPARC32_PSR_ET) ! 1007: && (ipl == TME_SPARC_IPL_NMI ! 1008: || ipl > TME_FIELD_MASK_EXTRACTU(ic->tme_sparc32_ireg_psr, TME_SPARC32_PSR_PIL))) { 1.1 root 1009: 1.1.1.2 ! root 1010: if (flags & TME_SPARC_EXTERNAL_CHECK_MUTEX_LOCKED) { ! 1011: tme_mutex_unlock(&ic->tme_sparc_external_mutex); ! 1012: } 1.1 root 1013: 1.1.1.2 ! root 1014: /* dispatch the trap: */ ! 1015: tme_sparc32_trap_preinstruction(ic, TME_SPARC32_TRAP_interrupt_level(ipl)); ! 1016: } 1.1 root 1017: } 1018: 1019: /* there are no traps to process: */ 1020: } 1021: 1022: /* this triggers sparc32 trap processing on a preinstruction boundary: */ 1023: void 1024: tme_sparc32_trap_preinstruction(struct tme_sparc *ic, tme_uint32_t trap) 1025: { 1026: 1.1.1.2 ! root 1027: /* end any recode verifying: */ ! 1028: tme_sparc_recode_verify_end(ic, TME_SPARC_TRAP_none); ! 1029: 1.1 root 1030: /* shift the next instruction's PC and next-next PC up: */ 1031: ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC) = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT); 1032: ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT) = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT_NEXT); 1033: 1034: /* do the rest of the sparc32 trap processing: */ 1035: tme_sparc32_trap(ic, trap); 1036: } 1037: 1038: /* this triggers sparc32 trap processing by an instruction: */ 1039: void 1040: tme_sparc32_trap(struct tme_sparc *ic, tme_uint32_t trap) 1041: { 1042: unsigned int cwp; 1043: unsigned int cwp_offset; 1.1.1.2 ! root 1044: unsigned int reg_17; ! 1045: ! 1046: /* end any recode verifying: */ ! 1047: tme_sparc_recode_verify_end(ic, trap); ! 1048: ! 1049: /* stop idling: */ ! 1050: TME_SPARC_IDLE_STOP(ic); 1.1 root 1051: 1052: /* reset traps are handled specially: */ 1.1.1.2 ! root 1053: if (__tme_predict_false(trap == TME_SPARC32_TRAP_reset)) { 1.1 root 1054: tme_sparc_do_reset(ic); 1055: /* NOTREACHED */ 1056: } 1057: 1058: /* "The processor enters error_mode state when a trap occurs while 1059: ET = 0. An implementation should preserve as much processor state 1060: as possible when this happens. Standard trap actions (such as 1061: decrementing CWP and saving state information in locals) should 1062: not occur when entering error_mode. In particular, the tt field 1063: of the TBR is only written during a transition into error_mode 1064: state in the singular case of a RETT instruction that traps while 1065: ET = 0. In this case, tt is written to indicate the type of 1066: exception that was induced by the RETT instruction. 1067: 1068: What occurs after error_mode is entered is 1069: implementation-dependent; typically the processor triggers an 1070: external reset, causing a reset trap (see below). */ 1071: if (__tme_predict_false((ic->tme_sparc32_ireg_psr & TME_SPARC32_PSR_ET) == 0)) { 1072: 1073: /* if we were executing a RETT instruction: */ 1074: assert (ic->_tme_sparc_mode == TME_SPARC_MODE_EXECUTION); 1075: if ((ic->_tme_sparc_insn 1076: & ((3 << 30) | (0x3f << 19))) 1077: == ((tme_uint32_t) (2 << 30) | (0x39 << 19))) { 1078: 1079: /* update the TBR register: */ 1080: TME_FIELD_MASK_DEPOSITU(ic->tme_sparc32_ireg_tbr, 0xff, trap); 1081: } 1082: 1083: /* reset the processor: */ 1084: tme_log(TME_SPARC_LOG_HANDLE(ic), 0, EPERM, 1085: (TME_SPARC_LOG_HANDLE(ic), 1086: _("took a trap while traps disabled, processor reset"))); 1.1.1.2 ! root 1087: tme_sparc32_trap(ic, TME_SPARC32_TRAP_reset); 1.1 root 1088: } 1089: 1090: /* "Traps are disabled: ET <- 0. 1091: The existing user/supervisor mode is preserved: PS <- S. 1092: The user/supervisor mode is changed to supervisor: S <- 1." */ 1093: ic->tme_sparc32_ireg_psr 1094: = ((ic->tme_sparc32_ireg_psr 1095: & ~(TME_SPARC32_PSR_ET 1096: | TME_SPARC32_PSR_PS)) 1097: | ((ic->tme_sparc32_ireg_psr 1098: & TME_SPARC32_PSR_S) 1099: / (TME_SPARC32_PSR_S 1100: / TME_SPARC32_PSR_PS)) 1101: | TME_SPARC32_PSR_S); 1102: 1103: /* "The register window is advanced to a new window: 1104: CWP <- ((CWP - 1) modulo NWINDOWS) 1105: [note: without test for window overflow]." */ 1106: cwp = TME_FIELD_MASK_EXTRACTU(ic->tme_sparc32_ireg_psr, TME_SPARC32_PSR_CWP); 1107: cwp -= 1; 1108: cwp %= ic->tme_sparc_nwindows; 1109: TME_FIELD_MASK_DEPOSITU(ic->tme_sparc32_ireg_psr, TME_SPARC32_PSR_CWP, cwp); 1.1.1.2 ! root 1110: TME_SPARC32_CWP_UPDATE(ic, cwp, cwp_offset); ! 1111: reg_17 = 17; ! 1112: TME_SPARC_REG_INDEX(ic, reg_17); 1.1 root 1113: 1114: /* "The trapped program counters are saved in local registers 1 and 1115: 2 of the new window: r[17] <- PC, r[18] <- nPC." */ 1.1.1.2 ! root 1116: ic->tme_sparc_ireg_uint32(reg_17 + 0) = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC); ! 1117: ic->tme_sparc_ireg_uint32(reg_17 + 1) = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT); 1.1 root 1118: 1119: /* "The tt field is written to the particular value that identifies 1120: the exception or interrupt request, except as defined for `Reset 1121: Trap' and `Error Mode' above." */ 1122: TME_FIELD_MASK_DEPOSITU(ic->tme_sparc32_ireg_tbr, 0x00000ff0, trap); 1123: 1124: /* "If the trap is not a reset trap, control is transferred into the 1125: trap table: PC <- TBR, nPC <- TBR + 4." */ 1126: ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT) = ic->tme_sparc32_ireg_tbr; 1127: ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT_NEXT) = ic->tme_sparc32_ireg_tbr + sizeof(tme_uint32_t); 1128: 1.1.1.2 ! root 1129: /* log the trap: */ ! 1130: tme_sparc_log(ic, 250, TME_OK, ! 1131: (TME_SPARC_LOG_HANDLE(ic), ! 1132: _("trap tt 0x%03" TME_PRIx32 " handler-%%pc 0x%08" TME_PRIx32), ! 1133: TME_SPARC_TRAP_TT(trap), ! 1134: ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT))); ! 1135: 1.1 root 1136: /* redispatch: */ 1137: ic->_tme_sparc_mode = TME_SPARC_MODE_EXECUTION; 1138: tme_sparc_redispatch(ic); 1139: } 1140: 1.1.1.2 ! root 1141: /* the default sparc32 load/store bus cycle functions: */ ! 1142: void ! 1143: tme_sparc32_ls_bus_cycle(const struct tme_sparc *ic, ! 1144: struct tme_sparc_ls *ls) 1.1 root 1145: { 1.1.1.2 ! root 1146: ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS32_LOG2); ! 1147: ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_lane_routing ! 1148: = &(tme_sparc32_router ! 1149: [TME_SPARC_BUS_ROUTER_INDEX(TME_BUS32_LOG2, ! 1150: ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_size, ! 1151: (tme_uint32_t) ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_address)]); ! 1152: } ! 1153: ! 1154: /* the default sparc32 load/store direct address map function: */ ! 1155: void ! 1156: tme_sparc32_ls_address_map(struct tme_sparc *ic, ! 1157: struct tme_sparc_ls *ls) ! 1158: { ! 1159: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_first = 0; ! 1160: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_last = 0 - (tme_bus_addr_t) 1; ! 1161: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE; ! 1162: ls->tme_sparc_ls_tlb_map.tme_bus_tlb_addr_offset = 0; ! 1163: } ! 1164: ! 1165: /* the default sparc32 load/store trap function: */ ! 1166: void ! 1167: tme_sparc32_ls_trap(struct tme_sparc *ic, ! 1168: struct tme_sparc_ls *ls) ! 1169: { ! 1170: tme_uint32_t lsinfo; ! 1171: tme_uint32_t ls_faults; ! 1172: tme_uint32_t trap; ! 1173: tme_uint32_t fault_trap; ! 1174: ! 1175: /* get the information about this load/store: */ ! 1176: lsinfo = ls->tme_sparc_ls_lsinfo; ! 1177: ! 1178: /* get the list of faults from this load/store: */ ! 1179: ls_faults = ls->tme_sparc_ls_faults; ! 1180: ! 1181: /* we only support the sparc32 load/store faults: */ ! 1182: assert ((ls_faults ! 1183: & ~(TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED ! 1184: | TME_SPARC_LS_FAULT_LDD_STD_RD_ODD ! 1185: | TME_SPARC_LS_FAULT_BUS_FAULT ! 1186: | TME_SPARC_LS_FAULT_BUS_ERROR)) == 0); ! 1187: ! 1188: /* start with no fault: */ ! 1189: trap = TME_SPARC_TRAP_none; ! 1190: ! 1191: /* convert the faults into the highest-priority trap: */ ! 1192: if (ls_faults & TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED) { ! 1193: trap = TME_MIN(trap, TME_SPARC32_TRAP_mem_address_not_aligned); ! 1194: } ! 1195: if (ls_faults & TME_SPARC_LS_FAULT_LDD_STD_RD_ODD) { ! 1196: trap = TME_MIN(trap, TME_SPARC32_TRAP_illegal_instruction); ! 1197: } ! 1198: if (ls_faults ! 1199: & (TME_SPARC_LS_FAULT_BUS_FAULT ! 1200: | TME_SPARC_LS_FAULT_BUS_ERROR)) { ! 1201: fault_trap ! 1202: = ((lsinfo & TME_SPARC_LSINFO_OP_FETCH) ! 1203: ? TME_SPARC32_TRAP_instruction_access_exception ! 1204: : TME_SPARC32_TRAP_data_access_exception); ! 1205: trap = TME_MIN(trap, fault_trap); ! 1206: } 1.1 root 1207: 1.1.1.2 ! root 1208: /* there must be some fault: */ ! 1209: assert (trap != TME_SPARC_TRAP_none); 1.1 root 1210: 1.1.1.2 ! root 1211: /* trap: */ ! 1212: tme_sparc32_trap(ic, trap); ! 1213: } 1.1 root 1214: 1.1.1.2 ! root 1215: /* the default sparc nnPC trap function: */ ! 1216: void ! 1217: tme_sparc_nnpc_trap(struct tme_sparc *ic, ! 1218: tme_uint32_t ls_faults) ! 1219: { ! 1220: struct tme_sparc_ls ls; ! 1221: struct tme_sparc_tlb tlb_dummy; 1.1 root 1222: 1.1.1.2 ! root 1223: /* make a limited load/store structure: */ ! 1224: ls.tme_sparc_ls_faults = ls_faults; ! 1225: ls.tme_sparc_ls_lsinfo = TME_SPARC_LSINFO_OP_FETCH; ! 1226: ls.tme_sparc_ls_asi_mask = ic->tme_sparc_asi_mask_insn; ! 1227: ls.tme_sparc_ls_tlb = &tlb_dummy; ! 1228: tlb_dummy.tme_sparc_tlb_asi_mask ! 1229: = (!TME_SPARC64_ASI_MASK_FLAG_TLB_SIDE_EFFECTS ! 1230: ); ! 1231: if (sizeof(tme_sparc_ireg_umax_t) > sizeof(tme_uint32_t) ! 1232: && TME_SPARC_VERSION(ic) >= 9) { ! 1233: #ifdef TME_HAVE_INT64_T ! 1234: ls.tme_sparc_ls_context = ic->tme_sparc_memory_context_primary; ! 1235: ls.tme_sparc_ls_address64 = ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT_NEXT); ! 1236: #endif /* TME_HAVE_INT64_T */ 1.1 root 1237: } 1238: else { 1.1.1.2 ! root 1239: ls.tme_sparc_ls_context = ic->tme_sparc_memory_context_default; ! 1240: ls.tme_sparc_ls_address32 = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT_NEXT); 1.1 root 1241: } 1242: 1.1.1.2 ! root 1243: /* trap: */ ! 1244: (*ic->_tme_sparc_ls_trap)(ic, &ls); 1.1 root 1245: } 1246: 1.1.1.2 ! root 1247: /* the default load/store bus fault function: */ ! 1248: void ! 1249: tme_sparc_ls_bus_fault(struct tme_sparc *ic, ! 1250: struct tme_sparc_ls *ls, ! 1251: int err) ! 1252: { ! 1253: tme_uint32_t lsinfo; ! 1254: tme_uint32_t cycle_size; ! 1255: tme_uint32_t ls_fault; ! 1256: ! 1257: /* get the information about this load/store: */ ! 1258: lsinfo = ls->tme_sparc_ls_lsinfo; ! 1259: ! 1260: /* if this load/store ignores all bus faults: */ ! 1261: if (lsinfo & TME_SPARC_LSINFO_NO_FAULT) { ! 1262: ! 1263: /* update the load/store to get past the fault: */ ! 1264: cycle_size = ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_size; ! 1265: if (TME_SPARC_VERSION(ic) >= 9) { ! 1266: #ifdef TME_HAVE_INT64_T ! 1267: ls->tme_sparc_ls_address64 += cycle_size; ! 1268: #endif /* TME_HAVE_INT64_T */ ! 1269: } ! 1270: else { ! 1271: ls->tme_sparc_ls_address32 += cycle_size; ! 1272: } ! 1273: ls->tme_sparc_ls_buffer_offset += cycle_size; ! 1274: ls->tme_sparc_ls_size -= cycle_size; ! 1275: return; ! 1276: } ! 1277: ! 1278: /* convert the bus error code into a fault: */ 1.1 root 1279: switch (err) { 1280: case EFAULT: 1.1.1.2 ! root 1281: ls_fault = TME_SPARC_LS_FAULT_BUS_FAULT; ! 1282: break; 1.1 root 1283: case ENOENT: 1284: case EIO: 1.1.1.2 ! root 1285: ls_fault = TME_SPARC_LS_FAULT_BUS_ERROR; ! 1286: break; 1.1 root 1287: default: abort(); 1288: } 1.1.1.2 ! root 1289: ! 1290: /* add in this fault: */ ! 1291: ls->tme_sparc_ls_faults |= ls_fault; ! 1292: } ! 1293: ! 1294: #ifdef TME_HAVE_INT64_T ! 1295: ! 1296: /* this triggers sparc64 trap processing on a preinstruction boundary: */ ! 1297: void ! 1298: tme_sparc64_trap_preinstruction(struct tme_sparc *ic, tme_uint32_t trap) ! 1299: { ! 1300: ! 1301: /* end any recode verifying: */ ! 1302: tme_sparc_recode_verify_end(ic, TME_SPARC_TRAP_none); ! 1303: ! 1304: /* shift the next instruction's PC and next-next PC up: */ ! 1305: ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC) = ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT); ! 1306: ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT) = ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT_NEXT); ! 1307: ! 1308: /* do the rest of the sparc64 trap processing: */ ! 1309: tme_sparc64_trap(ic, trap); 1.1 root 1310: } 1311: 1312: /* this triggers sparc64 trap processing by an instruction: */ 1313: void 1314: tme_sparc64_trap(struct tme_sparc *ic, tme_uint32_t trap) 1315: { 1.1.1.2 ! root 1316: tme_uint32_t tt; ! 1317: unsigned int tl; ! 1318: tme_uint32_t pstate; ! 1319: tme_uint32_t tstate_0_31; ! 1320: tme_int32_t cwp_addend; ! 1321: tme_uint32_t cwp; ! 1322: unsigned int cwp_offset; ! 1323: unsigned int wstate; ! 1324: tme_uint64_t pc; ! 1325: ! 1326: /* end any recode verifying: */ ! 1327: tme_sparc_recode_verify_end(ic, trap); ! 1328: ! 1329: /* stop idling: */ ! 1330: TME_SPARC_IDLE_STOP(ic); ! 1331: ! 1332: /* get this trap's tt value: */ ! 1333: tt = TME_SPARC_TRAP_TT(trap); ! 1334: ! 1335: /* get the current TL: */ ! 1336: tl = ic->tme_sparc64_ireg_tl; ! 1337: ! 1338: /* if this is some kind of reset: */ ! 1339: #if (TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_power_on_reset) + 1) != TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_watchdog_reset) ! 1340: #error "TME_SPARC64_TRAP_ values changed" ! 1341: #endif ! 1342: #if (TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_power_on_reset) + 2) != TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_externally_initiated_reset) ! 1343: #error "TME_SPARC64_TRAP_ values changed" ! 1344: #endif ! 1345: #if (TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_power_on_reset) + 3) != TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_software_initiated_reset) ! 1346: #error "TME_SPARC64_TRAP_ values changed" ! 1347: #endif ! 1348: if (__tme_predict_false((tt >= TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_power_on_reset) ! 1349: && tt <= TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_software_initiated_reset)) ! 1350: || (trap & TME_SPARC_TRAP_IMPDEP_RESET))) { ! 1351: ! 1352: /* if this is an SIR at TL == MAXTL: */ ! 1353: if (tt == TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_software_initiated_reset) ! 1354: && tl == ic->tme_sparc64_maxtl) { ! 1355: ! 1356: /* enter error_state: */ ! 1357: tme_sparc64_trap_error_state(ic); ! 1358: /* NOTREACHED */ ! 1359: } ! 1360: ! 1361: /* enter RED_state, if we're not there already, at min(TL + 1, ! 1362: MAXTL): */ ! 1363: pstate = ic->tme_sparc64_ireg_pstate; ! 1364: pstate |= TME_SPARC64_PSTATE_RED; ! 1365: tl = tl + 1; ! 1366: tl = TME_MIN(tl, ic->tme_sparc64_maxtl); ! 1367: ! 1368: /* if this is a POR: */ ! 1369: if (tt == TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_power_on_reset)) { ! 1370: ! 1371: /* reset the FPU: */ ! 1372: tme_sparc_fpu_reset(ic); ! 1373: ! 1374: /* poison all idle type state, to force the idle type to retrain: */ ! 1375: _tme_sparc_idle_reset(ic); ! 1376: ! 1377: /* clear PSTATE.TLE, which will be copied into PSTATE.CLE: */ ! 1378: pstate &= ~TME_SPARC64_PSTATE_TLE; ! 1379: ! 1380: /* set TICK.NPT: */ ! 1381: ic->tme_sparc64_ireg_tick_npt = TRUE; ! 1382: ! 1383: /* zero TICK.counter: */ ! 1384: ic->tme_sparc64_ireg_tick_offset ! 1385: = (0 - tme_misc_cycles_scaled(&ic->tme_sparc_cycles_scaling, 0).tme_value64_uint); ! 1386: ! 1387: /* enter RED_state at MAXTL: */ ! 1388: tl = ic->tme_sparc64_maxtl; ! 1389: } ! 1390: ! 1391: /* if this is an XIR: */ ! 1392: else if (tt == TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_externally_initiated_reset)) { ! 1393: ! 1394: /* zero TICK.counter: */ ! 1395: ic->tme_sparc64_ireg_tick_offset ! 1396: = (0 - tme_misc_cycles_scaled(&ic->tme_sparc_cycles_scaling, 0).tme_value64_uint); ! 1397: } ! 1398: } ! 1399: ! 1400: /* otherwise, this is a normal trap or interrupt: */ ! 1401: else { ! 1402: ! 1403: /* increment TL: */ ! 1404: tl = tl + 1; ! 1405: ! 1406: /* if we were already at MAXTL: */ ! 1407: if (__tme_predict_false(tl > ic->tme_sparc64_maxtl)) { ! 1408: ! 1409: /* enter error_state: */ ! 1410: tme_sparc64_trap_error_state(ic); ! 1411: /* NOTREACHED */ ! 1412: } ! 1413: ! 1414: /* get PSTATE: */ ! 1415: pstate = ic->tme_sparc64_ireg_pstate; ! 1416: ! 1417: /* if we are now at MAXTL: */ ! 1418: if (tl == ic->tme_sparc64_maxtl) { ! 1419: ! 1420: /* enter RED_state, if we're not there already: */ ! 1421: pstate |= TME_SPARC64_PSTATE_RED; ! 1422: } ! 1423: } ! 1424: ! 1425: /* save ASI: */ ! 1426: tstate_0_31 = ic->tme_sparc64_ireg_asi; ! 1427: tstate_0_31 ! 1428: *= (_TME_FIELD_MASK_FACTOR(TME_SPARC64_TSTATE_MASK_ASI) ! 1429: / _TME_FIELD_MASK_FACTOR(TME_SPARC64_TSTATE_MASK_PSTATE)); ! 1430: ! 1431: /* save PSTATE: */ ! 1432: assert (ic->tme_sparc64_ireg_pstate ! 1433: <= (TME_SPARC64_TSTATE_MASK_PSTATE ! 1434: / _TME_FIELD_MASK_FACTOR(TME_SPARC64_TSTATE_MASK_PSTATE))); ! 1435: tstate_0_31 += ic->tme_sparc64_ireg_pstate; ! 1436: tstate_0_31 ! 1437: *= (_TME_FIELD_MASK_FACTOR(TME_SPARC64_TSTATE_MASK_PSTATE) ! 1438: / _TME_FIELD_MASK_FACTOR(TME_SPARC64_TSTATE_MASK_CWP)); ! 1439: ! 1440: /* save CWP: */ ! 1441: tstate_0_31 += ic->tme_sparc64_ireg_cwp; ! 1442: ! 1443: /* store the least-significant 32 bits of TSTATE[TL]: */ ! 1444: ic->tme_sparc64_ireg_tstate(tl) = tstate_0_31; ! 1445: ! 1446: /* save CCR directly into TSTATE[TL]: */ ! 1447: ic->tme_sparc64_ireg_tstate_ccr(tl) = ic->tme_sparc64_ireg_ccr; ! 1448: ! 1449: /* save TPC[TL] and TNPC[TL]: */ ! 1450: ic->tme_sparc64_ireg_tpc(tl) = ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC); ! 1451: ic->tme_sparc64_ireg_tnpc(tl) = ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT); ! 1452: ! 1453: /* finish the normal PSTATE update: */ ! 1454: pstate ! 1455: &= ~(TME_SPARC64_PSTATE_AM ! 1456: + TME_SPARC64_PSTATE_IE ! 1457: + TME_SPARC64_PSTATE_CLE); ! 1458: if (__tme_predict_false(pstate & TME_SPARC64_PSTATE_RED)) { ! 1459: pstate &= ~TME_SPARC64_PSTATE_MM; ! 1460: } ! 1461: pstate ! 1462: |= (TME_SPARC64_PSTATE_PEF ! 1463: + TME_SPARC64_PSTATE_PRIV ! 1464: + TME_SPARC64_PSTATE_AG ! 1465: + ((pstate ! 1466: & TME_SPARC64_PSTATE_TLE) ! 1467: * (TME_SPARC64_PSTATE_CLE ! 1468: / TME_SPARC64_PSTATE_TLE))); ! 1469: ! 1470: /* call the implementation-specific PSTATE update function to set ! 1471: the final value for PSTATE: */ ! 1472: (*ic->_tme_sparc64_update_pstate)(ic, pstate, trap); ! 1473: ! 1474: /* if this is a clean_window trap: */ ! 1475: if (tt == TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_clean_window)) { ! 1476: cwp_addend = 1; ! 1477: } ! 1478: ! 1479: /* otherwise, if this is a window spill trap: */ ! 1480: else if (tt == TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_spill_normal(0))) { ! 1481: cwp_addend = ic->tme_sparc64_ireg_cansave + 2; ! 1482: } ! 1483: ! 1484: /* otherwise, if this is a window fill trap: */ ! 1485: else if (tt == TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_fill_normal(0))) { ! 1486: cwp_addend = -1; ! 1487: } ! 1488: ! 1489: /* otherwise, this trap does not update CWP: */ ! 1490: else { ! 1491: cwp_addend = 0; ! 1492: } ! 1493: ! 1494: /* if this trap updates CWP: */ ! 1495: if (cwp_addend != 0) { ! 1496: ! 1497: /* update CWP: */ ! 1498: cwp = ic->tme_sparc64_ireg_cwp; ! 1499: cwp += cwp_addend; ! 1500: assert (ic->tme_sparc64_ireg_winstates_mask != 0); ! 1501: cwp &= ic->tme_sparc64_ireg_winstates_mask; ! 1502: cwp = (tme_uint8_t) cwp; ! 1503: ic->tme_sparc64_ireg_cwp = cwp; ! 1504: TME_SPARC64_CWP_UPDATE(ic, cwp, cwp_offset); ! 1505: ! 1506: /* if this is a window spill or fill trap: */ ! 1507: if (tt != TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_clean_window)) { ! 1508: ! 1509: /* make the exact trap vector: */ ! 1510: wstate = ic->tme_sparc64_ireg_wstate; ! 1511: if (ic->tme_sparc64_ireg_otherwin) { ! 1512: #if (TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_spill_other(0)) - TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_spill_normal(0))) != (TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_fill_other(0)) - TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_fill_normal(0))) ! 1513: #error "TME_SPARC64_TRAP_ values changed" ! 1514: #endif ! 1515: tt += (TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_spill_other(0)) ! 1516: - TME_SPARC_TRAP_TT(TME_SPARC64_TRAP_spill_normal(0))); ! 1517: wstate /= (TME_SPARC64_WSTATE_OTHER / TME_SPARC64_WSTATE_NORMAL); ! 1518: } ! 1519: tt += (4 * (wstate & TME_SPARC64_WSTATE_NORMAL)); ! 1520: } ! 1521: } ! 1522: ! 1523: /* if we are in RED_state: */ ! 1524: if (__tme_predict_false(ic->tme_sparc64_ireg_pstate & TME_SPARC64_PSTATE_RED)) { ! 1525: ! 1526: /* transfer control into the RED_state_trap_vector table: */ ! 1527: pc = ic->tme_sparc64_rstvaddr; ! 1528: } ! 1529: ! 1530: /* otherwise, we are not in RED_state: */ ! 1531: else { ! 1532: ! 1533: /* transfer control into the normal trap vector table: */ ! 1534: pc = (ic->tme_sparc64_ireg_tl == 0 ? 0 : TME_BIT(14)); ! 1535: pc |= ic->tme_sparc64_ireg_tba; ! 1536: } ! 1537: ! 1538: /* save the trap type: */ ! 1539: ic->tme_sparc64_ireg_tt(tl) = tt; ! 1540: ! 1541: /* update TL: */ ! 1542: ic->tme_sparc64_ireg_tl = tl; ! 1543: ! 1544: /* transfer control to the trap vector table: */ ! 1545: pc += (tt * 0x20); ! 1546: ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT) = pc; ! 1547: ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT_NEXT) = pc | sizeof(tme_uint32_t); ! 1548: ! 1549: /* log the trap: */ ! 1550: tme_sparc_log(ic, 250, TME_OK, ! 1551: (TME_SPARC_LOG_HANDLE(ic), ! 1552: _("trap tl %u tt 0x%03" TME_PRIx32 " handler-%%pc 0x%016" TME_PRIx64), ! 1553: tl, ! 1554: tt, ! 1555: pc)); ! 1556: ! 1557: /* redispatch: */ ! 1558: ic->_tme_sparc_mode = TME_SPARC_MODE_EXECUTION; ! 1559: tme_sparc_redispatch(ic); ! 1560: } ! 1561: ! 1562: /* this enters the sparc64 error_state: */ ! 1563: void ! 1564: tme_sparc64_trap_error_state(struct tme_sparc *ic) ! 1565: { 1.1 root 1566: abort(); 1567: } 1568: 1.1.1.2 ! root 1569: #endif /* TME_HAVE_INT64_T */ ! 1570: ! 1571: /* this returns the current instruction TLB entry: */ ! 1572: struct tme_sparc_tlb * ! 1573: tme_sparc_itlb_current(struct tme_sparc *ic) 1.1 root 1574: { 1.1.1.2 ! root 1575: struct tme_token *token; ! 1576: tme_uint32_t tlb_i; 1.1 root 1577: struct tme_sparc_tlb *itlb_current; 1.1.1.2 ! root 1578: ! 1579: /* there must be a current instruction TLB entry: */ ! 1580: token = ic->_tme_sparc_itlb_current_token; ! 1581: assert (token != NULL); ! 1582: ! 1583: /* recover the index of the instruction TLB entry: */ ! 1584: tlb_i ! 1585: = ( ! 1586: #ifdef TME_HAVE_INT64_T ! 1587: TME_SPARC_VERSION(ic) >= 9 ! 1588: ? ! 1589: #if TME_HAVE_RECODE && TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 ! 1590: (((struct tme_recode_tlb_c16_a64 *) ! 1591: (((char *) token) ! 1592: - (((char *) &(((struct tme_recode_tlb_c16_a64 *) 0)->tme_recode_tlb_c16_a64_token)) ! 1593: - (char *) 0))) ! 1594: - &ic->tme_sparc_recode_tlb64s[0]) ! 1595: #else /* !TME_HAVE_RECODE || TME_RECODE_SIZE_GUEST_MAX <= TME_RECODE_SIZE_32 */ ! 1596: (token - &ic->tme_sparc_tlb_tokens[0]) ! 1597: #endif /* !TME_HAVE_RECODE || TME_RECODE_SIZE_GUEST_MAX <= TME_RECODE_SIZE_32 */ ! 1598: : ! 1599: #endif /* TME_HAVE_INT64_T */ ! 1600: #if TME_HAVE_RECODE ! 1601: (((struct tme_recode_tlb_c16_a32 *) ! 1602: (((char *) token) ! 1603: - (((char *) &(((struct tme_recode_tlb_c16_a32 *) 0)->tme_recode_tlb_c16_a32_token)) ! 1604: - (char *) 0))) ! 1605: - &ic->tme_sparc_recode_tlb32s[0]) ! 1606: #else /* !TME_HAVE_RECODE */ ! 1607: (token - &ic->tme_sparc_tlb_tokens[0]) ! 1608: #endif /* !TME_HAVE_RECODE */ ! 1609: ); ! 1610: #if TME_HAVE_RECODE ! 1611: if (TME_SPARC_VERSION(ic) >= 9) { ! 1612: #if TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 ! 1613: assert (token == &ic->tme_sparc_recode_tlb64s[tlb_i].tme_recode_tlb_c16_a64_token); ! 1614: #endif /* TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 */ ! 1615: } ! 1616: else { ! 1617: assert (token == &ic->tme_sparc_recode_tlb32s[tlb_i].tme_recode_tlb_c16_a32_token); ! 1618: } ! 1619: #endif /* TME_HAVE_RECODE */ ! 1620: ! 1621: /* get the current instruction TLB entry: */ ! 1622: itlb_current = &ic->tme_sparc_tlbs[tlb_i]; ! 1623: assert (itlb_current->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token == token); ! 1624: ! 1625: return (itlb_current); ! 1626: } ! 1627: ! 1628: /* this peeks at an instruction. it returns all-bits-one if there is ! 1629: no valid instruction TLB entry that allows fast reading and applies ! 1630: to the address: */ ! 1631: tme_uint32_t ! 1632: tme_sparc_insn_peek(struct tme_sparc *ic, ! 1633: tme_sparc_ireg_umax_t pc_unmasked) ! 1634: { ! 1635: tme_sparc_ireg_umax_t pc; ! 1636: tme_uint32_t tlb_hash; ! 1637: const struct tme_sparc_tlb *itlb; 1.1 root 1638: tme_uint32_t insn; 1.1.1.2 ! root 1639: const struct tme_sparc_tlb *itlb_current; 1.1 root 1640: 1.1.1.2 ! root 1641: /* mask the address: */ ! 1642: pc = pc_unmasked; 1.1 root 1643: #ifdef TME_HAVE_INT64_T 1.1.1.2 ! root 1644: if (TME_SPARC_VERSION(ic) >= 9) { ! 1645: pc &= ic->tme_sparc_address_mask; ! 1646: } 1.1 root 1647: #endif /* TME_HAVE_INT64_T */ 1648: 1.1.1.2 ! root 1649: /* the address must be 32-bit aligned: */ ! 1650: assert ((pc % sizeof(tme_uint32_t)) == 0); 1.1 root 1651: 1.1.1.2 ! root 1652: /* NB: we don't have to check if the PC is in any virtual address ! 1653: hole, because we never make valid instruction TLB entries for ! 1654: addresses in a hole: */ ! 1655: ! 1656: /* hash the instruction TLB entry: */ ! 1657: tlb_hash = TME_SPARC_TLB_HASH(ic, ic->tme_sparc_memory_context_default, pc); ! 1658: itlb = &ic->tme_sparc_tlbs[TME_SPARC_ITLB_ENTRY(ic, tlb_hash)]; ! 1659: ! 1660: /* if this instruction TLB entry is valid, covers this ASI and ! 1661: address, and allows fast reading: */ ! 1662: if (tme_bus_tlb_is_valid(&itlb->tme_sparc_tlb_bus_tlb) ! 1663: && TME_SPARC_TLB_ASI_MASK_OK(itlb, ic->tme_sparc_asi_mask_insn) ! 1664: && itlb->tme_sparc_tlb_addr_first <= pc ! 1665: && pc <= itlb->tme_sparc_tlb_addr_last ! 1666: && itlb->tme_sparc_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF) { ! 1667: ! 1668: /* fetch the instruction: */ ! 1669: insn = tme_memory_bus_read32((const tme_shared tme_uint32_t *) (itlb->tme_sparc_tlb_emulator_off_read + pc), ! 1670: itlb->tme_sparc_tlb_bus_rwlock, ! 1671: sizeof(tme_uint32_t), ! 1672: (TME_SPARC_VERSION(ic) < 9 ! 1673: ? sizeof(tme_uint32_t) ! 1674: : sizeof(tme_uint32_t) * 2)); ! 1675: insn = tme_betoh_u32(insn); ! 1676: return (insn); ! 1677: } ! 1678: ! 1679: /* if there is recode support: */ ! 1680: if (TME_SPARC_HAVE_RECODE(ic)) { 1.1 root 1681: 1.1.1.2 ! root 1682: /* return failure. if the PC doesn't hash to the current ! 1683: instruction TLB entry, the current instruction TLB entry won't ! 1684: cover it (because tme_sparc_recode_chain_tlb_update() limits ! 1685: instruction TLB entries to covering just one page). if the PC ! 1686: does hash to the current instruction TLB entry, we just checked ! 1687: that above: */ ! 1688: return (0xffffffff); ! 1689: } 1.1 root 1690: 1.1.1.2 ! root 1691: /* assume that we can't fetch the nearby instruction: */ ! 1692: insn = 0xffffffff; ! 1693: ! 1694: /* if the current instruction TLB entry is valid and covers the address: */ ! 1695: itlb_current = tme_sparc_itlb_current(ic); 1.1 root 1696: if (tme_bus_tlb_is_valid(&itlb_current->tme_sparc_tlb_bus_tlb) 1697: && itlb_current->tme_sparc_tlb_addr_first <= pc 1698: && pc <= itlb_current->tme_sparc_tlb_addr_last) { 1699: 1.1.1.2 ! root 1700: /* the current instruction TLB entry must cover this ASI and allow ! 1701: fast reading: */ ! 1702: assert (TME_SPARC_TLB_ASI_MASK_OK(itlb_current, ic->tme_sparc_asi_mask_insn)); ! 1703: assert (itlb_current->tme_sparc_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF); ! 1704: 1.1 root 1705: /* fetch the nearby instruction: */ 1706: insn = tme_memory_bus_read32((const tme_shared tme_uint32_t *) (itlb_current->tme_sparc_tlb_emulator_off_read + pc), 1707: itlb_current->tme_sparc_tlb_bus_rwlock, 1708: sizeof(tme_uint32_t), 1709: (TME_SPARC_VERSION(ic) < 9 1710: ? sizeof(tme_uint32_t) 1711: : sizeof(tme_uint32_t) * 2)); 1712: insn = tme_betoh_u32(insn); 1713: } 1714: 1715: return (insn); 1716: } 1717: 1.1.1.2 ! root 1718: /* this peeks at an instruction at some offset from the current PC. ! 1719: it returns all-bits-one if there is no valid instruction TLB entry ! 1720: that allows fast reading and applies to the address: */ ! 1721: tme_uint32_t ! 1722: tme_sparc_fetch_nearby(struct tme_sparc *ic, long offset_in_insns) ! 1723: { ! 1724: tme_sparc_ireg_umax_t pc_unmasked; ! 1725: ! 1726: /* get the PC: */ ! 1727: pc_unmasked ! 1728: = ( ! 1729: #ifdef TME_HAVE_INT64_T ! 1730: TME_SPARC_VERSION(ic) >= 9 ! 1731: ? ((tme_uint64_t) ! 1732: (ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC) ! 1733: + (tme_int64_t) (offset_in_insns * (long) sizeof(tme_uint32_t)))) ! 1734: : ! 1735: #endif /* TME_HAVE_INT64_T */ ! 1736: ((tme_uint32_t) ! 1737: (ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC) ! 1738: + (tme_int32_t) (offset_in_insns * (long) sizeof(tme_uint32_t))))); ! 1739: ! 1740: /* peek at the instruction: */ ! 1741: return (tme_sparc_insn_peek(ic, pc_unmasked)); ! 1742: } ! 1743: 1.1 root 1744: /* this unlocks data structures before a callout: */ 1745: void 1746: tme_sparc_callout_unlock(struct tme_sparc *ic) 1747: { 1.1.1.2 ! root 1748: struct tme_token *token; 1.1 root 1749: 1750: assert ((ic->_tme_sparc_mode == TME_SPARC_MODE_EXECUTION) 1.1.1.2 ! root 1751: || (ic->_tme_sparc_itlb_current_token == NULL)); 1.1 root 1752: 1753: /* if we have a busy instruction TLB entry: */ 1.1.1.2 ! root 1754: token = ic->_tme_sparc_itlb_current_token; ! 1755: if (__tme_predict_true(token != NULL)) { 1.1 root 1756: 1757: /* unbusy the instruction TLB entry: */ 1.1.1.2 ! root 1758: tme_token_unbusy(token); 1.1 root 1759: } 1760: } 1761: 1762: /* this relocks data structures after a callout: */ 1763: void 1764: tme_sparc_callout_relock(struct tme_sparc *ic) 1765: { 1.1.1.2 ! root 1766: struct tme_token *token; 1.1 root 1767: struct tme_sparc_tlb *tlb; 1768: 1769: assert ((ic->_tme_sparc_mode == TME_SPARC_MODE_EXECUTION) 1.1.1.2 ! root 1770: || (ic->_tme_sparc_itlb_current_token == NULL)); 1.1 root 1771: 1772: /* if we have a busy instruction TLB entry: */ 1.1.1.2 ! root 1773: token = ic->_tme_sparc_itlb_current_token; ! 1774: if (__tme_predict_true(token != NULL)) { 1.1 root 1775: 1776: /* rebusy the instruction TLB entry: */ 1.1.1.2 ! root 1777: tme_token_busy(token); ! 1778: tlb = tme_sparc_itlb_current(ic); 1.1 root 1779: 1.1.1.2 ! root 1780: /* if this instruction TLB entry is invalid, or isn't ! 1781: for the current context: */ ! 1782: if (tme_bus_tlb_is_invalid(&tlb->tme_sparc_tlb_bus_tlb) ! 1783: || (tlb->tme_sparc_tlb_context <= ic->tme_sparc_memory_context_max ! 1784: && tlb->tme_sparc_tlb_context != ic->tme_sparc_memory_context_default)) { 1.1 root 1785: 1786: /* poison this instruction TLB entry, so we won't try to do any 1787: fast fetches with it: */ 1788: tlb->tme_sparc_tlb_addr_first = 1; 1789: tlb->tme_sparc_tlb_addr_last = 0; 1790: } 1791: } 1.1.1.2 ! root 1792: ! 1793: /* if we need to do an external check: */ ! 1794: if (tme_memory_atomic_read_flag(&ic->tme_sparc_external_flag)) { ! 1795: ! 1796: /* after the currently executing instruction finishes, check for ! 1797: external resets, halts, or interrupts: */ ! 1798: ic->_tme_sparc_instruction_burst_remaining = 0; ! 1799: ic->_tme_sparc_instruction_burst_other = TRUE; ! 1800: } 1.1 root 1801: } 1802: 1803: #if 0 1804: #include <stdio.h> 1805: 1806: /* this dumps out the sparc state: */ 1807: void 1808: tme_sparc32_dump(const struct tme_sparc *ic) 1809: { 1810: unsigned int cwp_first; 1811: unsigned int cwp; 1812: unsigned int reg_i; 1813: unsigned int reg_base; 1814: unsigned int ireg; 1815: 1816: /* dump out the windowed integer registers, finishing with the 1817: current window: */ 1818: cwp_first = TME_FIELD_MASK_EXTRACTU(ic->tme_sparc32_ireg_psr, TME_SPARC32_PSR_CWP); 1819: cwp_first += TME_SPARC_NWINDOWS(ic) - 1; 1820: cwp_first %= TME_SPARC_NWINDOWS(ic); 1821: cwp = cwp_first; 1822: do { 1823: for (reg_i = 0; reg_i < 8; reg_i++) { 1824: for (reg_base = 24; reg_base > 8; reg_base -= 8) { 1825: 1.1.1.2 ! root 1826: ireg = reg_base + reg_i + (cwp * 16); ! 1827: if (ireg > ((TME_SPARC_NWINDOWS(ic) * 16) + 7)) { ! 1828: ireg -= (TME_SPARC_NWINDOWS(ic) * 16); 1.1 root 1829: } 1830: 1831: fprintf(stderr, 1832: "w%u.%%%c%u[%p] = 0x%08x ", 1833: cwp, 1834: (reg_base == 24 1835: ? 'i' 1836: : 'l'), 1837: reg_i, 1838: &ic->tme_sparc_ireg_uint32(ireg), 1839: ic->tme_sparc_ireg_uint32(ireg)); 1840: } 1841: fprintf(stderr, "\n"); 1842: } 1843: cwp--; 1844: cwp %= TME_SPARC_NWINDOWS(ic); 1845: } while (cwp != cwp_first); 1846: 1847: /* dump out the global registers and the current window's output 1848: registers: */ 1849: cwp = TME_FIELD_MASK_EXTRACTU(ic->tme_sparc32_ireg_psr, TME_SPARC32_PSR_CWP); 1850: for (reg_i = 0; reg_i < 8; reg_i++) { 1851: 1852: ireg = reg_i; 1853: fprintf(stderr, 1854: " %%g%u[%p] = 0x%08x ", 1855: ireg, 1856: &ic->tme_sparc_ireg_uint32(ireg), 1857: ic->tme_sparc_ireg_uint32(ireg)); 1858: 1.1.1.2 ! root 1859: ireg = 8 + reg_i + (cwp * 16); ! 1860: if (ireg > ((TME_SPARC_NWINDOWS(ic) * 16) + 7)) { ! 1861: ireg -= (TME_SPARC_NWINDOWS(ic) * 16); 1.1 root 1862: } 1863: 1864: fprintf(stderr, 1865: "w%u.%%o%u[%p] = 0x%08x ", 1866: cwp, 1867: reg_i, 1868: &ic->tme_sparc_ireg_uint32(ireg), 1869: ic->tme_sparc_ireg_uint32(ireg)); 1870: fprintf(stderr, "\n"); 1871: } 1872: 1873: /* dump out the PCs: */ 1874: fprintf(stderr, "%%pc = 0x%08x %%pc_next = 0x%08x %%pc_next_next = 0x%08x\n", 1875: ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC), 1876: ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT), 1877: ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT_NEXT)); 1878: 1879: /* dump out the PSR: */ 1880: fprintf(stderr, "%%psr = 0x%08x", ic->tme_sparc32_ireg_psr); 1881: fprintf(stderr, " cwp = %u", 1882: TME_FIELD_MASK_EXTRACTU(ic->tme_sparc32_ireg_psr, TME_SPARC32_PSR_CWP)); 1883: fprintf(stderr, " pil = 0x%x", 1884: TME_FIELD_MASK_EXTRACTU(ic->tme_sparc32_ireg_psr, TME_SPARC32_PSR_PIL)); 1885: if (ic->tme_sparc32_ireg_psr & TME_SPARC32_PSR_ET) { 1886: fprintf(stderr, " ET"); 1887: } 1888: fprintf(stderr, " %c", 1889: (ic->tme_sparc32_ireg_psr & TME_SPARC32_PSR_S 1890: ? 'S' 1891: : 'U')); 1892: fprintf(stderr, " flags:"); 1893: if (ic->tme_sparc32_ireg_psr & TME_SPARC32_PSR_ICC_N) { 1894: fprintf(stderr, " N"); 1895: } 1896: if (ic->tme_sparc32_ireg_psr & TME_SPARC32_PSR_ICC_Z) { 1897: fprintf(stderr, " Z"); 1898: } 1899: if (ic->tme_sparc32_ireg_psr & TME_SPARC32_PSR_ICC_V) { 1900: fprintf(stderr, " V"); 1901: } 1902: if (ic->tme_sparc32_ireg_psr & TME_SPARC32_PSR_ICC_C) { 1903: fprintf(stderr, " C"); 1904: } 1905: fprintf(stderr, "\n"); 1906: 1907: /* dump out the instruction and the WIM: */ 1908: fprintf(stderr, "insn = 0x%08x %%wim = 0x%08x\n", 1909: ic->_tme_sparc_insn, 1910: ic->tme_sparc32_ireg_wim); 1911: } 1912: 1913: void 1.1.1.2 ! root 1914: tme_sparc64_dump_memory(struct tme_sparc *ic, tme_uint64_t address, tme_uint32_t resid) 1.1 root 1915: { 1.1.1.2 ! root 1916: tme_uint64_t address_display; ! 1917: tme_uint32_t tlb_hash; 1.1 root 1918: struct tme_sparc_tlb *dtlb; 1919: tme_memory_atomic_flag_t tlb_busy_old; 1920: const tme_shared tme_uint8_t *memory; 1921: tme_uint32_t count; 1922: tme_uint32_t byte_i; 1923: 1924: /* we always display aligned rows: */ 1925: address_display = address & (((tme_uint32_t) 0) - (sizeof(tme_uint32_t) * 2)); 1926: resid += (address - address_display); 1927: 1928: /* while we have memory to dump: */ 1929: for (; resid > 0; ) { 1930: 1931: /* get the DTLB entry, and busy it if it isn't already: */ 1.1.1.2 ! root 1932: tlb_hash = TME_SPARC_TLB_HASH(ic, ic->tme_sparc_memory_context_default, address_display); ! 1933: dtlb = &ic->tme_sparc_tlbs[TME_SPARC_DTLB_ENTRY(ic, tlb_hash)]; ! 1934: tlb_busy_old = dtlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token->tme_token_busy; ! 1935: dtlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token->tme_token_busy = TRUE; 1.1 root 1936: 1937: /* read more data: */ 1938: count = TME_MIN(resid, sizeof(tme_uint32_t) * 2); 1939: memory 1.1.1.2 ! root 1940: = (TME_SPARC_VERSION(ic) < 9 ! 1941: ? tme_sparc32_ls(ic, ! 1942: address_display, ! 1943: (tme_uint32_t *) NULL, ! 1944: (TME_SPARC_LSINFO_SIZE(sizeof(tme_uint32_t) * 2) ! 1945: + TME_SPARC_LSINFO_OP_LD ! 1946: + TME_SPARC_LSINFO_NO_FAULT)) ! 1947: : tme_sparc64_ls(ic, ! 1948: address_display, ! 1949: (tme_uint64_t *) NULL, ! 1950: (TME_SPARC_LSINFO_SIZE(sizeof(tme_uint32_t) * 2) ! 1951: + TME_SPARC_LSINFO_OP_LD ! 1952: + TME_SPARC_LSINFO_NO_FAULT))); 1.1 root 1953: 1954: /* restore the DTLB busy flag: */ 1.1.1.2 ! root 1955: dtlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token->tme_token_busy = tlb_busy_old; 1.1 root 1956: 1957: /* display the row: */ 1.1.1.2 ! root 1958: fprintf(stderr, "0x%0*" TME_PRIx64 " ", (8 << (TME_SPARC_VERSION(ic) >= 9)), address_display); 1.1 root 1959: for (byte_i = 0; 1960: byte_i < count; 1961: byte_i++, address_display++) { 1962: if (address_display < address) { 1963: fprintf(stderr, " "); 1964: } 1965: else { 1966: fprintf(stderr, " %02x", 1967: memory[address_display]); 1968: address++; 1969: } 1970: resid--; 1971: } 1972: fputc('\n', stderr); 1973: } 1974: } 1.1.1.2 ! root 1975: ! 1976: #undef TME_SPARC_VERSION ! 1977: #define TME_SPARC_VERSION(ic) (9) ! 1978: #include "sparc-kgdb.c" ! 1979: #undef TME_SPARC_VERSION ! 1980: 1.1 root 1981: #endif /* 1 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.