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

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

unix.superglobalmegacorp.com

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