Annotation of qemu/hw/alpha_palcode.c, revision 1.1.1.4

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

unix.superglobalmegacorp.com