|
|
1.1 ! root 1: /* ! 2: * Alpha emulation - PALcode emulation for qemu. ! 3: * ! 4: * Copyright (c) 2007 Jocelyn Mayer ! 5: * ! 6: * This library is free software; you can redistribute it and/or ! 7: * modify it under the terms of the GNU Lesser General Public ! 8: * License as published by the Free Software Foundation; either ! 9: * version 2 of the License, or (at your option) any later version. ! 10: * ! 11: * This library is distributed in the hope that it will be useful, ! 12: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 14: * Lesser General Public License for more details. ! 15: * ! 16: * You should have received a copy of the GNU Lesser General Public ! 17: * License along with this library; if not, write to the Free Software ! 18: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! 19: */ ! 20: ! 21: #include <stdint.h> ! 22: #include <stdlib.h> ! 23: #include <stdio.h> ! 24: ! 25: #include "qemu.h" ! 26: #include "cpu.h" ! 27: #include "exec-all.h" ! 28: ! 29: #if !defined (CONFIG_USER_ONLY) ! 30: /* Shared handlers */ ! 31: static void pal_reset (CPUState *env); ! 32: /* Console handlers */ ! 33: static void pal_console_call (CPUState *env, uint32_t palcode); ! 34: /* OpenVMS handlers */ ! 35: static void pal_openvms_call (CPUState *env, uint32_t palcode); ! 36: /* UNIX / Linux handlers */ ! 37: static void pal_unix_call (CPUState *env, uint32_t palcode); ! 38: ! 39: pal_handler_t pal_handlers[] = { ! 40: /* Console handler */ ! 41: { ! 42: .reset = &pal_reset, ! 43: .call_pal = &pal_console_call, ! 44: }, ! 45: /* OpenVMS handler */ ! 46: { ! 47: .reset = &pal_reset, ! 48: .call_pal = &pal_openvms_call, ! 49: }, ! 50: /* UNIX / Linux handler */ ! 51: { ! 52: .reset = &pal_reset, ! 53: .call_pal = &pal_unix_call, ! 54: }, ! 55: }; ! 56: ! 57: #if 0 ! 58: /* One must explicitely check that the TB is valid and the FOE bit is reset */ ! 59: static void update_itb () ! 60: { ! 61: /* This writes into a temp register, not the actual one */ ! 62: mtpr(TB_TAG); ! 63: mtpr(TB_CTL); ! 64: /* This commits the TB update */ ! 65: mtpr(ITB_PTE); ! 66: } ! 67: ! 68: static void update_dtb (); ! 69: { ! 70: mtpr(TB_CTL); ! 71: /* This write into a temp register, not the actual one */ ! 72: mtpr(TB_TAG); ! 73: /* This commits the TB update */ ! 74: mtpr(DTB_PTE); ! 75: } ! 76: #endif ! 77: ! 78: static void pal_reset (CPUState *env) ! 79: { ! 80: } ! 81: ! 82: static void do_swappal (CPUState *env, uint64_t palid) ! 83: { ! 84: pal_handler_t *pal_handler; ! 85: int status; ! 86: ! 87: status = 0; ! 88: switch (palid) { ! 89: case 0 ... 2: ! 90: pal_handler = &pal_handlers[palid]; ! 91: env->pal_handler = pal_handler; ! 92: env->ipr[IPR_PAL_BASE] = -1ULL; ! 93: (*pal_handler->reset)(env); ! 94: break; ! 95: case 3 ... 255: ! 96: /* Unknown identifier */ ! 97: env->ir[0] = 1; ! 98: return; ! 99: default: ! 100: /* We were given the entry point address */ ! 101: env->pal_handler = NULL; ! 102: env->ipr[IPR_PAL_BASE] = palid; ! 103: env->pc = env->ipr[IPR_PAL_BASE]; ! 104: cpu_loop_exit(); ! 105: } ! 106: } ! 107: ! 108: static void pal_console_call (CPUState *env, uint32_t palcode) ! 109: { ! 110: uint64_t palid; ! 111: ! 112: if (palcode < 0x00000080) { ! 113: /* Privileged palcodes */ ! 114: if (!(env->ps >> 3)) { ! 115: /* TODO: generate privilege exception */ ! 116: } ! 117: } ! 118: switch (palcode) { ! 119: case 0x00000000: ! 120: /* HALT */ ! 121: /* REQUIRED */ ! 122: break; ! 123: case 0x00000001: ! 124: /* CFLUSH */ ! 125: break; ! 126: case 0x00000002: ! 127: /* DRAINA */ ! 128: /* REQUIRED */ ! 129: /* Implemented as no-op */ ! 130: break; ! 131: case 0x00000009: ! 132: /* CSERVE */ ! 133: /* REQUIRED */ ! 134: break; ! 135: case 0x0000000A: ! 136: /* SWPPAL */ ! 137: /* REQUIRED */ ! 138: palid = env->ir[16]; ! 139: do_swappal(env, palid); ! 140: break; ! 141: case 0x00000080: ! 142: /* BPT */ ! 143: /* REQUIRED */ ! 144: break; ! 145: case 0x00000081: ! 146: /* BUGCHK */ ! 147: /* REQUIRED */ ! 148: break; ! 149: case 0x00000086: ! 150: /* IMB */ ! 151: /* REQUIRED */ ! 152: /* Implemented as no-op */ ! 153: break; ! 154: case 0x0000009E: ! 155: /* RDUNIQUE */ ! 156: /* REQUIRED */ ! 157: break; ! 158: case 0x0000009F: ! 159: /* WRUNIQUE */ ! 160: /* REQUIRED */ ! 161: break; ! 162: case 0x000000AA: ! 163: /* GENTRAP */ ! 164: /* REQUIRED */ ! 165: break; ! 166: default: ! 167: break; ! 168: } ! 169: } ! 170: ! 171: static void pal_openvms_call (CPUState *env, uint32_t palcode) ! 172: { ! 173: uint64_t palid, val, oldval; ! 174: ! 175: if (palcode < 0x00000080) { ! 176: /* Privileged palcodes */ ! 177: if (!(env->ps >> 3)) { ! 178: /* TODO: generate privilege exception */ ! 179: } ! 180: } ! 181: switch (palcode) { ! 182: case 0x00000000: ! 183: /* HALT */ ! 184: /* REQUIRED */ ! 185: break; ! 186: case 0x00000001: ! 187: /* CFLUSH */ ! 188: break; ! 189: case 0x00000002: ! 190: /* DRAINA */ ! 191: /* REQUIRED */ ! 192: /* Implemented as no-op */ ! 193: break; ! 194: case 0x00000003: ! 195: /* LDQP */ ! 196: break; ! 197: case 0x00000004: ! 198: /* STQP */ ! 199: break; ! 200: case 0x00000005: ! 201: /* SWPCTX */ ! 202: break; ! 203: case 0x00000006: ! 204: /* MFPR_ASN */ ! 205: if (cpu_alpha_mfpr(env, IPR_ASN, &val) == 0) ! 206: env->ir[0] = val; ! 207: break; ! 208: case 0x00000007: ! 209: /* MTPR_ASTEN */ ! 210: val = env->ir[16]; ! 211: if (cpu_alpha_mtpr(env, IPR_ASTEN, val, &oldval) == 1) ! 212: env->ir[0] = val; ! 213: break; ! 214: case 0x00000008: ! 215: /* MTPR_ASTSR */ ! 216: val = env->ir[16]; ! 217: if (cpu_alpha_mtpr(env, IPR_ASTSR, val, &oldval) == 1) ! 218: env->ir[0] = val; ! 219: break; ! 220: case 0x00000009: ! 221: /* CSERVE */ ! 222: /* REQUIRED */ ! 223: break; ! 224: case 0x0000000A: ! 225: /* SWPPAL */ ! 226: /* REQUIRED */ ! 227: palid = env->ir[16]; ! 228: do_swappal(env, palid); ! 229: break; ! 230: case 0x0000000B: ! 231: /* MFPR_FEN */ ! 232: if (cpu_alpha_mfpr(env, IPR_FEN, &val) == 0) ! 233: env->ir[0] = val; ! 234: break; ! 235: case 0x0000000C: ! 236: /* MTPR_FEN */ ! 237: val = env->ir[16]; ! 238: if (cpu_alpha_mtpr(env, IPR_FEN, val, &oldval) == 1) ! 239: env->ir[0] = val; ! 240: break; ! 241: case 0x0000000D: ! 242: /* MTPR_IPIR */ ! 243: val = env->ir[16]; ! 244: if (cpu_alpha_mtpr(env, IPR_IPIR, val, &oldval) == 1) ! 245: env->ir[0] = val; ! 246: break; ! 247: case 0x0000000E: ! 248: /* MFPR_IPL */ ! 249: if (cpu_alpha_mfpr(env, IPR_IPL, &val) == 0) ! 250: env->ir[0] = val; ! 251: break; ! 252: case 0x0000000F: ! 253: /* MTPR_IPL */ ! 254: val = env->ir[16]; ! 255: if (cpu_alpha_mtpr(env, IPR_IPL, val, &oldval) == 1) ! 256: env->ir[0] = val; ! 257: break; ! 258: case 0x00000010: ! 259: /* MFPR_MCES */ ! 260: if (cpu_alpha_mfpr(env, IPR_MCES, &val) == 0) ! 261: env->ir[0] = val; ! 262: break; ! 263: case 0x00000011: ! 264: /* MTPR_MCES */ ! 265: val = env->ir[16]; ! 266: if (cpu_alpha_mtpr(env, IPR_MCES, val, &oldval) == 1) ! 267: env->ir[0] = val; ! 268: break; ! 269: case 0x00000012: ! 270: /* MFPR_PCBB */ ! 271: if (cpu_alpha_mfpr(env, IPR_PCBB, &val) == 0) ! 272: env->ir[0] = val; ! 273: break; ! 274: case 0x00000013: ! 275: /* MFPR_PRBR */ ! 276: if (cpu_alpha_mfpr(env, IPR_PRBR, &val) == 0) ! 277: env->ir[0] = val; ! 278: break; ! 279: case 0x00000014: ! 280: /* MTPR_PRBR */ ! 281: val = env->ir[16]; ! 282: if (cpu_alpha_mtpr(env, IPR_PRBR, val, &oldval) == 1) ! 283: env->ir[0] = val; ! 284: break; ! 285: case 0x00000015: ! 286: /* MFPR_PTBR */ ! 287: if (cpu_alpha_mfpr(env, IPR_PTBR, &val) == 0) ! 288: env->ir[0] = val; ! 289: break; ! 290: case 0x00000016: ! 291: /* MFPR_SCBB */ ! 292: if (cpu_alpha_mfpr(env, IPR_SCBB, &val) == 0) ! 293: env->ir[0] = val; ! 294: break; ! 295: case 0x00000017: ! 296: /* MTPR_SCBB */ ! 297: val = env->ir[16]; ! 298: if (cpu_alpha_mtpr(env, IPR_SCBB, val, &oldval) == 1) ! 299: env->ir[0] = val; ! 300: break; ! 301: case 0x00000018: ! 302: /* MTPR_SIRR */ ! 303: val = env->ir[16]; ! 304: if (cpu_alpha_mtpr(env, IPR_SIRR, val, &oldval) == 1) ! 305: env->ir[0] = val; ! 306: break; ! 307: case 0x00000019: ! 308: /* MFPR_SISR */ ! 309: if (cpu_alpha_mfpr(env, IPR_SISR, &val) == 0) ! 310: env->ir[0] = val; ! 311: break; ! 312: case 0x0000001A: ! 313: /* MFPR_TBCHK */ ! 314: if (cpu_alpha_mfpr(env, IPR_TBCHK, &val) == 0) ! 315: env->ir[0] = val; ! 316: break; ! 317: case 0x0000001B: ! 318: /* MTPR_TBIA */ ! 319: val = env->ir[16]; ! 320: if (cpu_alpha_mtpr(env, IPR_TBIA, val, &oldval) == 1) ! 321: env->ir[0] = val; ! 322: break; ! 323: case 0x0000001C: ! 324: /* MTPR_TBIAP */ ! 325: val = env->ir[16]; ! 326: if (cpu_alpha_mtpr(env, IPR_TBIAP, val, &oldval) == 1) ! 327: env->ir[0] = val; ! 328: break; ! 329: case 0x0000001D: ! 330: /* MTPR_TBIS */ ! 331: val = env->ir[16]; ! 332: if (cpu_alpha_mtpr(env, IPR_TBIS, val, &oldval) == 1) ! 333: env->ir[0] = val; ! 334: break; ! 335: case 0x0000001E: ! 336: /* MFPR_ESP */ ! 337: if (cpu_alpha_mfpr(env, IPR_ESP, &val) == 0) ! 338: env->ir[0] = val; ! 339: break; ! 340: case 0x0000001F: ! 341: /* MTPR_ESP */ ! 342: val = env->ir[16]; ! 343: if (cpu_alpha_mtpr(env, IPR_ESP, val, &oldval) == 1) ! 344: env->ir[0] = val; ! 345: break; ! 346: case 0x00000020: ! 347: /* MFPR_SSP */ ! 348: if (cpu_alpha_mfpr(env, IPR_SSP, &val) == 0) ! 349: env->ir[0] = val; ! 350: break; ! 351: case 0x00000021: ! 352: /* MTPR_SSP */ ! 353: val = env->ir[16]; ! 354: if (cpu_alpha_mtpr(env, IPR_SSP, val, &oldval) == 1) ! 355: env->ir[0] = val; ! 356: break; ! 357: case 0x00000022: ! 358: /* MFPR_USP */ ! 359: if (cpu_alpha_mfpr(env, IPR_USP, &val) == 0) ! 360: env->ir[0] = val; ! 361: break; ! 362: case 0x00000023: ! 363: /* MTPR_USP */ ! 364: val = env->ir[16]; ! 365: if (cpu_alpha_mtpr(env, IPR_USP, val, &oldval) == 1) ! 366: env->ir[0] = val; ! 367: break; ! 368: case 0x00000024: ! 369: /* MTPR_TBISD */ ! 370: val = env->ir[16]; ! 371: if (cpu_alpha_mtpr(env, IPR_TBISD, val, &oldval) == 1) ! 372: env->ir[0] = val; ! 373: break; ! 374: case 0x00000025: ! 375: /* MTPR_TBISI */ ! 376: val = env->ir[16]; ! 377: if (cpu_alpha_mtpr(env, IPR_TBISI, val, &oldval) == 1) ! 378: env->ir[0] = val; ! 379: break; ! 380: case 0x00000026: ! 381: /* MFPR_ASTEN */ ! 382: if (cpu_alpha_mfpr(env, IPR_ASTEN, &val) == 0) ! 383: env->ir[0] = val; ! 384: break; ! 385: case 0x00000027: ! 386: /* MFPR_ASTSR */ ! 387: if (cpu_alpha_mfpr(env, IPR_ASTSR, &val) == 0) ! 388: env->ir[0] = val; ! 389: break; ! 390: case 0x00000029: ! 391: /* MFPR_VPTB */ ! 392: if (cpu_alpha_mfpr(env, IPR_VPTB, &val) == 0) ! 393: env->ir[0] = val; ! 394: break; ! 395: case 0x0000002A: ! 396: /* MTPR_VPTB */ ! 397: val = env->ir[16]; ! 398: if (cpu_alpha_mtpr(env, IPR_VPTB, val, &oldval) == 1) ! 399: env->ir[0] = val; ! 400: break; ! 401: case 0x0000002B: ! 402: /* MTPR_PERFMON */ ! 403: val = env->ir[16]; ! 404: if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1) ! 405: env->ir[0] = val; ! 406: break; ! 407: case 0x0000002E: ! 408: /* MTPR_DATFX */ ! 409: val = env->ir[16]; ! 410: if (cpu_alpha_mtpr(env, IPR_DATFX, val, &oldval) == 1) ! 411: env->ir[0] = val; ! 412: break; ! 413: case 0x0000003E: ! 414: /* WTINT */ ! 415: break; ! 416: case 0x0000003F: ! 417: /* MFPR_WHAMI */ ! 418: if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0) ! 419: env->ir[0] = val; ! 420: break; ! 421: case 0x00000080: ! 422: /* BPT */ ! 423: /* REQUIRED */ ! 424: break; ! 425: case 0x00000081: ! 426: /* BUGCHK */ ! 427: /* REQUIRED */ ! 428: break; ! 429: case 0x00000082: ! 430: /* CHME */ ! 431: break; ! 432: case 0x00000083: ! 433: /* CHMK */ ! 434: break; ! 435: case 0x00000084: ! 436: /* CHMS */ ! 437: break; ! 438: case 0x00000085: ! 439: /* CHMU */ ! 440: break; ! 441: case 0x00000086: ! 442: /* IMB */ ! 443: /* REQUIRED */ ! 444: /* Implemented as no-op */ ! 445: break; ! 446: case 0x00000087: ! 447: /* INSQHIL */ ! 448: break; ! 449: case 0x00000088: ! 450: /* INSQTIL */ ! 451: break; ! 452: case 0x00000089: ! 453: /* INSQHIQ */ ! 454: break; ! 455: case 0x0000008A: ! 456: /* INSQTIQ */ ! 457: break; ! 458: case 0x0000008B: ! 459: /* INSQUEL */ ! 460: break; ! 461: case 0x0000008C: ! 462: /* INSQUEQ */ ! 463: break; ! 464: case 0x0000008D: ! 465: /* INSQUEL/D */ ! 466: break; ! 467: case 0x0000008E: ! 468: /* INSQUEQ/D */ ! 469: break; ! 470: case 0x0000008F: ! 471: /* PROBER */ ! 472: break; ! 473: case 0x00000090: ! 474: /* PROBEW */ ! 475: break; ! 476: case 0x00000091: ! 477: /* RD_PS */ ! 478: break; ! 479: case 0x00000092: ! 480: /* REI */ ! 481: break; ! 482: case 0x00000093: ! 483: /* REMQHIL */ ! 484: break; ! 485: case 0x00000094: ! 486: /* REMQTIL */ ! 487: break; ! 488: case 0x00000095: ! 489: /* REMQHIQ */ ! 490: break; ! 491: case 0x00000096: ! 492: /* REMQTIQ */ ! 493: break; ! 494: case 0x00000097: ! 495: /* REMQUEL */ ! 496: break; ! 497: case 0x00000098: ! 498: /* REMQUEQ */ ! 499: break; ! 500: case 0x00000099: ! 501: /* REMQUEL/D */ ! 502: break; ! 503: case 0x0000009A: ! 504: /* REMQUEQ/D */ ! 505: break; ! 506: case 0x0000009B: ! 507: /* SWASTEN */ ! 508: break; ! 509: case 0x0000009C: ! 510: /* WR_PS_SW */ ! 511: break; ! 512: case 0x0000009D: ! 513: /* RSCC */ ! 514: break; ! 515: case 0x0000009E: ! 516: /* READ_UNQ */ ! 517: /* REQUIRED */ ! 518: break; ! 519: case 0x0000009F: ! 520: /* WRITE_UNQ */ ! 521: /* REQUIRED */ ! 522: break; ! 523: case 0x000000A0: ! 524: /* AMOVRR */ ! 525: break; ! 526: case 0x000000A1: ! 527: /* AMOVRM */ ! 528: break; ! 529: case 0x000000A2: ! 530: /* INSQHILR */ ! 531: break; ! 532: case 0x000000A3: ! 533: /* INSQTILR */ ! 534: break; ! 535: case 0x000000A4: ! 536: /* INSQHIQR */ ! 537: break; ! 538: case 0x000000A5: ! 539: /* INSQTIQR */ ! 540: break; ! 541: case 0x000000A6: ! 542: /* REMQHILR */ ! 543: break; ! 544: case 0x000000A7: ! 545: /* REMQTILR */ ! 546: break; ! 547: case 0x000000A8: ! 548: /* REMQHIQR */ ! 549: break; ! 550: case 0x000000A9: ! 551: /* REMQTIQR */ ! 552: break; ! 553: case 0x000000AA: ! 554: /* GENTRAP */ ! 555: /* REQUIRED */ ! 556: break; ! 557: case 0x000000AE: ! 558: /* CLRFEN */ ! 559: break; ! 560: default: ! 561: break; ! 562: } ! 563: } ! 564: ! 565: static void pal_unix_call (CPUState *env, uint32_t palcode) ! 566: { ! 567: uint64_t palid, val, oldval; ! 568: ! 569: if (palcode < 0x00000080) { ! 570: /* Privileged palcodes */ ! 571: if (!(env->ps >> 3)) { ! 572: /* TODO: generate privilege exception */ ! 573: } ! 574: } ! 575: switch (palcode) { ! 576: case 0x00000000: ! 577: /* HALT */ ! 578: /* REQUIRED */ ! 579: break; ! 580: case 0x00000001: ! 581: /* CFLUSH */ ! 582: break; ! 583: case 0x00000002: ! 584: /* DRAINA */ ! 585: /* REQUIRED */ ! 586: /* Implemented as no-op */ ! 587: break; ! 588: case 0x00000009: ! 589: /* CSERVE */ ! 590: /* REQUIRED */ ! 591: break; ! 592: case 0x0000000A: ! 593: /* SWPPAL */ ! 594: /* REQUIRED */ ! 595: palid = env->ir[16]; ! 596: do_swappal(env, palid); ! 597: break; ! 598: case 0x0000000D: ! 599: /* WRIPIR */ ! 600: val = env->ir[16]; ! 601: if (cpu_alpha_mtpr(env, IPR_IPIR, val, &oldval) == 1) ! 602: env->ir[0] = val; ! 603: break; ! 604: case 0x00000010: ! 605: /* RDMCES */ ! 606: if (cpu_alpha_mfpr(env, IPR_MCES, &val) == 0) ! 607: env->ir[0] = val; ! 608: break; ! 609: case 0x00000011: ! 610: /* WRMCES */ ! 611: val = env->ir[16]; ! 612: if (cpu_alpha_mtpr(env, IPR_MCES, val, &oldval) == 1) ! 613: env->ir[0] = val; ! 614: break; ! 615: case 0x0000002B: ! 616: /* WRFEN */ ! 617: val = env->ir[16]; ! 618: if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1) ! 619: env->ir[0] = val; ! 620: break; ! 621: case 0x0000002D: ! 622: /* WRVPTPTR */ ! 623: break; ! 624: case 0x00000030: ! 625: /* SWPCTX */ ! 626: break; ! 627: case 0x00000031: ! 628: /* WRVAL */ ! 629: break; ! 630: case 0x00000032: ! 631: /* RDVAL */ ! 632: break; ! 633: case 0x00000033: ! 634: /* TBI */ ! 635: val = env->ir[16]; ! 636: if (cpu_alpha_mtpr(env, IPR_TBIS, val, &oldval) == 1) ! 637: env->ir[0] = val; ! 638: break; ! 639: case 0x00000034: ! 640: /* WRENT */ ! 641: break; ! 642: case 0x00000035: ! 643: /* SWPIPL */ ! 644: break; ! 645: case 0x00000036: ! 646: /* RDPS */ ! 647: break; ! 648: case 0x00000037: ! 649: /* WRKGP */ ! 650: break; ! 651: case 0x00000038: ! 652: /* WRUSP */ ! 653: val = env->ir[16]; ! 654: if (cpu_alpha_mtpr(env, IPR_USP, val, &oldval) == 1) ! 655: env->ir[0] = val; ! 656: break; ! 657: case 0x00000039: ! 658: /* WRPERFMON */ ! 659: val = env->ir[16]; ! 660: if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1) ! 661: env->ir[0] = val; ! 662: break; ! 663: case 0x0000003A: ! 664: /* RDUSP */ ! 665: if (cpu_alpha_mfpr(env, IPR_USP, &val) == 0) ! 666: env->ir[0] = val; ! 667: break; ! 668: case 0x0000003C: ! 669: /* WHAMI */ ! 670: if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0) ! 671: env->ir[0] = val; ! 672: break; ! 673: case 0x0000003D: ! 674: /* RETSYS */ ! 675: break; ! 676: case 0x0000003E: ! 677: /* WTINT */ ! 678: break; ! 679: case 0x0000003F: ! 680: /* RTI */ ! 681: if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0) ! 682: env->ir[0] = val; ! 683: break; ! 684: case 0x00000080: ! 685: /* BPT */ ! 686: /* REQUIRED */ ! 687: break; ! 688: case 0x00000081: ! 689: /* BUGCHK */ ! 690: /* REQUIRED */ ! 691: break; ! 692: case 0x00000083: ! 693: /* CALLSYS */ ! 694: break; ! 695: case 0x00000086: ! 696: /* IMB */ ! 697: /* REQUIRED */ ! 698: /* Implemented as no-op */ ! 699: break; ! 700: case 0x00000092: ! 701: /* URTI */ ! 702: break; ! 703: case 0x0000009E: ! 704: /* RDUNIQUE */ ! 705: /* REQUIRED */ ! 706: break; ! 707: case 0x0000009F: ! 708: /* WRUNIQUE */ ! 709: /* REQUIRED */ ! 710: break; ! 711: case 0x000000AA: ! 712: /* GENTRAP */ ! 713: /* REQUIRED */ ! 714: break; ! 715: case 0x000000AE: ! 716: /* CLRFEN */ ! 717: break; ! 718: default: ! 719: break; ! 720: } ! 721: } ! 722: ! 723: void call_pal (CPUState *env) ! 724: { ! 725: pal_handler_t *pal_handler = env->pal_handler; ! 726: ! 727: switch (env->exception_index) { ! 728: case EXCP_RESET: ! 729: (*pal_handler->reset)(env); ! 730: break; ! 731: case EXCP_MCHK: ! 732: (*pal_handler->machine_check)(env); ! 733: break; ! 734: case EXCP_ARITH: ! 735: (*pal_handler->arithmetic)(env); ! 736: break; ! 737: case EXCP_INTERRUPT: ! 738: (*pal_handler->interrupt)(env); ! 739: break; ! 740: case EXCP_DFAULT: ! 741: (*pal_handler->dfault)(env); ! 742: break; ! 743: case EXCP_DTB_MISS_PAL: ! 744: (*pal_handler->dtb_miss_pal)(env); ! 745: break; ! 746: case EXCP_DTB_MISS_NATIVE: ! 747: (*pal_handler->dtb_miss_native)(env); ! 748: break; ! 749: case EXCP_UNALIGN: ! 750: (*pal_handler->unalign)(env); ! 751: break; ! 752: case EXCP_ITB_MISS: ! 753: (*pal_handler->itb_miss)(env); ! 754: break; ! 755: case EXCP_ITB_ACV: ! 756: (*pal_handler->itb_acv)(env); ! 757: break; ! 758: case EXCP_OPCDEC: ! 759: (*pal_handler->opcdec)(env); ! 760: break; ! 761: case EXCP_FEN: ! 762: (*pal_handler->fen)(env); ! 763: break; ! 764: default: ! 765: if (env->exception_index >= EXCP_CALL_PAL && ! 766: env->exception_index < EXCP_CALL_PALP) { ! 767: /* Unprivileged PAL call */ ! 768: (*pal_handler->call_pal) ! 769: (env, (env->exception_index - EXCP_CALL_PAL) >> 6); ! 770: } else if (env->exception_index >= EXCP_CALL_PALP && ! 771: env->exception_index < EXCP_CALL_PALE) { ! 772: /* Privileged PAL call */ ! 773: (*pal_handler->call_pal) ! 774: (env, ((env->exception_index - EXCP_CALL_PALP) >> 6) + 0x80); ! 775: } else { ! 776: /* Should never happen */ ! 777: } ! 778: break; ! 779: } ! 780: env->ipr[IPR_EXC_ADDR] &= ~1; ! 781: } ! 782: ! 783: void pal_init (CPUState *env) ! 784: { ! 785: do_swappal(env, 0); ! 786: } ! 787: ! 788: #if 0 ! 789: static uint64_t get_ptebase (CPUState *env, uint64_t vaddr) ! 790: { ! 791: uint64_t virbnd, ptbr; ! 792: ! 793: if ((env->features & FEATURE_VIRBND)) { ! 794: cpu_alpha_mfpr(env, IPR_VIRBND, &virbnd); ! 795: if (vaddr >= virbnd) ! 796: cpu_alpha_mfpr(env, IPR_SYSPTBR, &ptbr); ! 797: else ! 798: cpu_alpha_mfpr(env, IPR_PTBR, &ptbr); ! 799: } else { ! 800: cpu_alpha_mfpr(env, IPR_PTBR, &ptbr); ! 801: } ! 802: ! 803: return ptbr; ! 804: } ! 805: ! 806: static int get_page_bits (CPUState *env) ! 807: { ! 808: /* XXX */ ! 809: return 13; ! 810: } ! 811: ! 812: static int get_pte (uint64_t *pfnp, int *zbitsp, int *protp, ! 813: uint64_t ptebase, int page_bits, uint64_t level, ! 814: int mmu_idx, int rw) ! 815: { ! 816: uint64_t pteaddr, pte, pfn; ! 817: uint8_t gh; ! 818: int ure, uwe, kre, kwe, foE, foR, foW, v, ret, ar, is_user; ! 819: ! 820: /* XXX: TOFIX */ ! 821: is_user = mmu_idx == MMU_USER_IDX; ! 822: pteaddr = (ptebase << page_bits) + (8 * level); ! 823: pte = ldq_raw(pteaddr); ! 824: /* Decode all interresting PTE fields */ ! 825: pfn = pte >> 32; ! 826: uwe = (pte >> 13) & 1; ! 827: kwe = (pte >> 12) & 1; ! 828: ure = (pte >> 9) & 1; ! 829: kre = (pte >> 8) & 1; ! 830: gh = (pte >> 5) & 3; ! 831: foE = (pte >> 3) & 1; ! 832: foW = (pte >> 2) & 1; ! 833: foR = (pte >> 1) & 1; ! 834: v = pte & 1; ! 835: ret = 0; ! 836: if (!v) ! 837: ret = 0x1; ! 838: /* Check access rights */ ! 839: ar = 0; ! 840: if (is_user) { ! 841: if (ure) ! 842: ar |= PAGE_READ; ! 843: if (uwe) ! 844: ar |= PAGE_WRITE; ! 845: if (rw == 1 && !uwe) ! 846: ret |= 0x2; ! 847: if (rw != 1 && !ure) ! 848: ret |= 0x2; ! 849: } else { ! 850: if (kre) ! 851: ar |= PAGE_READ; ! 852: if (kwe) ! 853: ar |= PAGE_WRITE; ! 854: if (rw == 1 && !kwe) ! 855: ret |= 0x2; ! 856: if (rw != 1 && !kre) ! 857: ret |= 0x2; ! 858: } ! 859: if (rw == 0 && foR) ! 860: ret |= 0x4; ! 861: if (rw == 2 && foE) ! 862: ret |= 0x8; ! 863: if (rw == 1 && foW) ! 864: ret |= 0xC; ! 865: *pfnp = pfn; ! 866: if (zbitsp != NULL) ! 867: *zbitsp = page_bits + (3 * gh); ! 868: if (protp != NULL) ! 869: *protp = ar; ! 870: ! 871: return ret; ! 872: } ! 873: ! 874: static int paddr_from_pte (uint64_t *paddr, int *zbitsp, int *prot, ! 875: uint64_t ptebase, int page_bits, ! 876: uint64_t vaddr, int mmu_idx, int rw) ! 877: { ! 878: uint64_t pfn, page_mask, lvl_mask, level1, level2, level3; ! 879: int lvl_bits, ret; ! 880: ! 881: page_mask = (1ULL << page_bits) - 1ULL; ! 882: lvl_bits = page_bits - 3; ! 883: lvl_mask = (1ULL << lvl_bits) - 1ULL; ! 884: level3 = (vaddr >> page_bits) & lvl_mask; ! 885: level2 = (vaddr >> (page_bits + lvl_bits)) & lvl_mask; ! 886: level1 = (vaddr >> (page_bits + (2 * lvl_bits))) & lvl_mask; ! 887: /* Level 1 PTE */ ! 888: ret = get_pte(&pfn, NULL, NULL, ptebase, page_bits, level1, 0, 0); ! 889: switch (ret) { ! 890: case 3: ! 891: /* Access violation */ ! 892: return 2; ! 893: case 2: ! 894: /* translation not valid */ ! 895: return 1; ! 896: default: ! 897: /* OK */ ! 898: break; ! 899: } ! 900: /* Level 2 PTE */ ! 901: ret = get_pte(&pfn, NULL, NULL, pfn, page_bits, level2, 0, 0); ! 902: switch (ret) { ! 903: case 3: ! 904: /* Access violation */ ! 905: return 2; ! 906: case 2: ! 907: /* translation not valid */ ! 908: return 1; ! 909: default: ! 910: /* OK */ ! 911: break; ! 912: } ! 913: /* Level 3 PTE */ ! 914: ret = get_pte(&pfn, zbitsp, prot, pfn, page_bits, level3, mmu_idx, rw); ! 915: if (ret & 0x1) { ! 916: /* Translation not valid */ ! 917: ret = 1; ! 918: } else if (ret & 2) { ! 919: /* Access violation */ ! 920: ret = 2; ! 921: } else { ! 922: switch (ret & 0xC) { ! 923: case 0: ! 924: /* OK */ ! 925: ret = 0; ! 926: break; ! 927: case 0x4: ! 928: /* Fault on read */ ! 929: ret = 3; ! 930: break; ! 931: case 0x8: ! 932: /* Fault on execute */ ! 933: ret = 4; ! 934: break; ! 935: case 0xC: ! 936: /* Fault on write */ ! 937: ret = 5; ! 938: break; ! 939: } ! 940: } ! 941: *paddr = (pfn << page_bits) | (vaddr & page_mask); ! 942: ! 943: return 0; ! 944: } ! 945: ! 946: static int virtual_to_physical (CPUState *env, uint64_t *physp, ! 947: int *zbitsp, int *protp, ! 948: uint64_t virtual, int mmu_idx, int rw) ! 949: { ! 950: uint64_t sva, ptebase; ! 951: int seg, page_bits, ret; ! 952: ! 953: sva = ((int64_t)(virtual << (64 - VA_BITS))) >> (64 - VA_BITS); ! 954: if (sva != virtual) ! 955: seg = -1; ! 956: else ! 957: seg = sva >> (VA_BITS - 2); ! 958: virtual &= ~(0xFFFFFC0000000000ULL << (VA_BITS - 43)); ! 959: ptebase = get_ptebase(env, virtual); ! 960: page_bits = get_page_bits(env); ! 961: ret = 0; ! 962: switch (seg) { ! 963: case 0: ! 964: /* seg1: 3 levels of PTE */ ! 965: ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits, ! 966: virtual, mmu_idx, rw); ! 967: break; ! 968: case 1: ! 969: /* seg1: 2 levels of PTE */ ! 970: ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits, ! 971: virtual, mmu_idx, rw); ! 972: break; ! 973: case 2: ! 974: /* kernel segment */ ! 975: if (mmu_idx != 0) { ! 976: ret = 2; ! 977: } else { ! 978: *physp = virtual; ! 979: } ! 980: break; ! 981: case 3: ! 982: /* seg1: TB mapped */ ! 983: ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits, ! 984: virtual, mmu_idx, rw); ! 985: break; ! 986: default: ! 987: ret = 1; ! 988: break; ! 989: } ! 990: ! 991: return ret; ! 992: } ! 993: ! 994: /* XXX: code provision */ ! 995: int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw, ! 996: int mmu_idx, int is_softmmu) ! 997: { ! 998: uint64_t physical, page_size, end; ! 999: int prot, zbits, ret; ! 1000: ! 1001: if (env->user_mode_only) { ! 1002: ret = 2; ! 1003: } else { ! 1004: ret = virtual_to_physical(env, &physical, &zbits, &prot, ! 1005: address, mmu_idx, rw); ! 1006: } ! 1007: switch (ret) { ! 1008: case 0: ! 1009: /* No fault */ ! 1010: page_size = 1ULL << zbits; ! 1011: address &= ~(page_size - 1); ! 1012: for (end = physical + page_size; physical < end; physical += 0x1000) { ! 1013: ret = tlb_set_page(env, address, physical, prot, ! 1014: mmu_idx, is_softmmu); ! 1015: address += 0x1000; ! 1016: } ! 1017: break; ! 1018: #if 0 ! 1019: case 1: ! 1020: env->exception_index = EXCP_DFAULT; ! 1021: env->ipr[IPR_EXC_ADDR] = address; ! 1022: ret = 1; ! 1023: break; ! 1024: case 2: ! 1025: env->exception_index = EXCP_ACCESS_VIOLATION; ! 1026: env->ipr[IPR_EXC_ADDR] = address; ! 1027: ret = 1; ! 1028: break; ! 1029: case 3: ! 1030: env->exception_index = EXCP_FAULT_ON_READ; ! 1031: env->ipr[IPR_EXC_ADDR] = address; ! 1032: ret = 1; ! 1033: break; ! 1034: case 4: ! 1035: env->exception_index = EXCP_FAULT_ON_EXECUTE; ! 1036: env->ipr[IPR_EXC_ADDR] = address; ! 1037: ret = 1; ! 1038: case 5: ! 1039: env->exception_index = EXCP_FAULT_ON_WRITE; ! 1040: env->ipr[IPR_EXC_ADDR] = address; ! 1041: ret = 1; ! 1042: #endif ! 1043: default: ! 1044: /* Should never happen */ ! 1045: env->exception_index = EXCP_MCHK; ! 1046: env->ipr[IPR_EXC_ADDR] = address; ! 1047: ret = 1; ! 1048: break; ! 1049: } ! 1050: ! 1051: return ret; ! 1052: } ! 1053: #endif ! 1054: ! 1055: #else /* !defined (CONFIG_USER_ONLY) */ ! 1056: void pal_init (CPUState *env) ! 1057: { ! 1058: } ! 1059: ! 1060: void call_pal (CPUState *env, int palcode) ! 1061: { ! 1062: target_ulong ret; ! 1063: ! 1064: printf("%s: palcode %02x\n", __func__, palcode); ! 1065: if (logfile != NULL) ! 1066: fprintf(logfile, "%s: palcode %02x\n", __func__, palcode); ! 1067: switch (palcode) { ! 1068: case 0x83: ! 1069: /* CALLSYS */ ! 1070: printf("CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]); ! 1071: if (logfile != NULL) ! 1072: fprintf(logfile, "CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]); ! 1073: ret = do_syscall(env, env->ir[IR_V0], env->ir[IR_A0], env->ir[IR_A1], ! 1074: env->ir[IR_A2], env->ir[IR_A3], env->ir[IR_A4], ! 1075: env->ir[IR_A5]); ! 1076: env->ir[IR_A3] = ret; ! 1077: if (ret > (target_ulong)(-515)) { ! 1078: env->ir[IR_V0] = 1; ! 1079: } else { ! 1080: env->ir[IR_V0] = 0; ! 1081: } ! 1082: break; ! 1083: case 0x9E: ! 1084: /* RDUNIQUE */ ! 1085: env->ir[IR_V0] = env->unique; ! 1086: printf("RDUNIQUE: " TARGET_FMT_lx "\n", env->unique); ! 1087: break; ! 1088: case 0x9F: ! 1089: /* WRUNIQUE */ ! 1090: env->unique = env->ir[IR_A0]; ! 1091: printf("WRUNIQUE: " TARGET_FMT_lx "\n", env->unique); ! 1092: break; ! 1093: default: ! 1094: printf("%s: unhandled palcode %02x\n", __func__, palcode); ! 1095: if (logfile != NULL) ! 1096: fprintf(logfile, "%s: unhandled palcode %02x\n", ! 1097: __func__, palcode); ! 1098: exit(1); ! 1099: } ! 1100: } ! 1101: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.