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

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.