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

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
1.1.1.2 ! root       18:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
1.1       root       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
1.1.1.2 ! root       58: /* One must explicitly check that the TB is valid and the FOE bit is reset */
        !            59: static void update_itb (void)
1.1       root       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: 
1.1.1.2 ! root       68: static void update_dtb (void);
1.1       root       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: 
1.1.1.2 ! root     1001: #if defined(CONFIG_USER_ONLY)
1.1       root     1002:         ret = 2;
1.1.1.2 ! root     1003: #else
1.1       root     1004:         ret = virtual_to_physical(env, &physical, &zbits, &prot,
                   1005:                                   address, mmu_idx, rw);
1.1.1.2 ! root     1006: #endif
1.1       root     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: {
1.1.1.2 ! root     1062:     target_long ret;
1.1       root     1063: 
1.1.1.2 ! root     1064:     qemu_log("%s: palcode %02x\n", __func__, palcode);
1.1       root     1065:     switch (palcode) {
                   1066:     case 0x83:
                   1067:         /* CALLSYS */
1.1.1.2 ! root     1068:         qemu_log("CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]);
1.1       root     1069:         ret = do_syscall(env, env->ir[IR_V0], env->ir[IR_A0], env->ir[IR_A1],
                   1070:                          env->ir[IR_A2], env->ir[IR_A3], env->ir[IR_A4],
                   1071:                          env->ir[IR_A5]);
1.1.1.2 ! root     1072:         if (ret >= 0) {
        !          1073:             env->ir[IR_A3] = 0;
        !          1074:             env->ir[IR_V0] = ret;
1.1       root     1075:         } else {
1.1.1.2 ! root     1076:             env->ir[IR_A3] = 1;
        !          1077:             env->ir[IR_V0] = -ret;
1.1       root     1078:         }
                   1079:         break;
                   1080:     case 0x9E:
                   1081:         /* RDUNIQUE */
                   1082:         env->ir[IR_V0] = env->unique;
1.1.1.2 ! root     1083:         qemu_log("RDUNIQUE: " TARGET_FMT_lx "\n", env->unique);
1.1       root     1084:         break;
                   1085:     case 0x9F:
                   1086:         /* WRUNIQUE */
                   1087:         env->unique = env->ir[IR_A0];
1.1.1.2 ! root     1088:         qemu_log("WRUNIQUE: " TARGET_FMT_lx "\n", env->unique);
1.1       root     1089:         break;
                   1090:     default:
1.1.1.2 ! root     1091:         qemu_log("%s: unhandled palcode %02x\n",
1.1       root     1092:                     __func__, palcode);
                   1093:         exit(1);
                   1094:     }
                   1095: }
                   1096: #endif

unix.superglobalmegacorp.com