Commit c62db10577295ed4dc26fa9acd6e6f30cea7ffd0

Authored by j_mayer
1 parent 636aaad7

Support for PowerPC BookE exception model.

No need to requeue timer exceptions.
Fix nip saving for 64 bits PowerPC.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2556 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 92 additions and 49 deletions
target-ppc/helper.c
@@ -1340,11 +1340,12 @@ void ppc_store_msr_32 (CPUPPCState *env, uint32_t value) @@ -1340,11 +1340,12 @@ void ppc_store_msr_32 (CPUPPCState *env, uint32_t value)
1340 void do_compute_hflags (CPUPPCState *env) 1340 void do_compute_hflags (CPUPPCState *env)
1341 { 1341 {
1342 /* Compute current hflags */ 1342 /* Compute current hflags */
1343 - env->hflags = (msr_pr << MSR_PR) | (msr_le << MSR_LE) |  
1344 - (msr_fp << MSR_FP) | (msr_fe0 << MSR_FE0) | (msr_fe1 << MSR_FE1) |  
1345 - (msr_vr << MSR_VR) | (msr_ap << MSR_AP) | (msr_sa << MSR_SA) |  
1346 - (msr_se << MSR_SE) | (msr_be << MSR_BE); 1343 + env->hflags = (msr_cm << MSR_CM) | (msr_vr << MSR_VR) |
  1344 + (msr_ap << MSR_AP) | (msr_sa << MSR_SA) | (msr_pr << MSR_PR) |
  1345 + (msr_fp << MSR_FP) | (msr_fe0 << MSR_FE0) | (msr_se << MSR_SE) |
  1346 + (msr_be << MSR_BE) | (msr_fe1 << MSR_FE1) | (msr_le << MSR_LE);
1347 #if defined (TARGET_PPC64) 1347 #if defined (TARGET_PPC64)
  1348 + /* No care here: PowerPC 64 MSR_SF means the same as MSR_CM for BookE */
1348 env->hflags |= (msr_sf << (MSR_SF - 32)) | (msr_hv << (MSR_HV - 32)); 1349 env->hflags |= (msr_sf << (MSR_SF - 32)) | (msr_hv << (MSR_HV - 32));
1349 #endif 1350 #endif
1350 } 1351 }
@@ -1374,14 +1375,16 @@ static void dump_syscall(CPUState *env) @@ -1374,14 +1375,16 @@ static void dump_syscall(CPUState *env)
1374 1375
1375 void do_interrupt (CPUState *env) 1376 void do_interrupt (CPUState *env)
1376 { 1377 {
1377 - target_ulong msr, *srr_0, *srr_1;  
1378 - int excp; 1378 + target_ulong msr, *srr_0, *srr_1, *asrr_0, *asrr_1;
  1379 + int excp, idx;
1379 1380
1380 excp = env->exception_index; 1381 excp = env->exception_index;
1381 msr = do_load_msr(env); 1382 msr = do_load_msr(env);
1382 /* The default is to use SRR0 & SRR1 to save the exception context */ 1383 /* The default is to use SRR0 & SRR1 to save the exception context */
1383 srr_0 = &env->spr[SPR_SRR0]; 1384 srr_0 = &env->spr[SPR_SRR0];
1384 srr_1 = &env->spr[SPR_SRR1]; 1385 srr_1 = &env->spr[SPR_SRR1];
  1386 + asrr_0 = NULL;
  1387 + asrr_1 = NULL;
1385 #if defined (DEBUG_EXCEPTIONS) 1388 #if defined (DEBUG_EXCEPTIONS)
1386 if ((excp == EXCP_PROGRAM || excp == EXCP_DSI) && msr_pr == 1) { 1389 if ((excp == EXCP_PROGRAM || excp == EXCP_DSI) && msr_pr == 1) {
1387 if (loglevel != 0) { 1390 if (loglevel != 0) {
@@ -1397,26 +1400,44 @@ void do_interrupt (CPUState *env) @@ -1397,26 +1400,44 @@ void do_interrupt (CPUState *env)
1397 env->nip, excp, env->error_code); 1400 env->nip, excp, env->error_code);
1398 } 1401 }
1399 msr_pow = 0; 1402 msr_pow = 0;
  1403 + idx = -1;
1400 /* Generate informations in save/restore registers */ 1404 /* Generate informations in save/restore registers */
1401 switch (excp) { 1405 switch (excp) {
1402 /* Generic PowerPC exceptions */ 1406 /* Generic PowerPC exceptions */
1403 case EXCP_RESET: /* 0x0100 */ 1407 case EXCP_RESET: /* 0x0100 */
1404 - if (PPC_EXCP(env) != PPC_FLAGS_EXCP_40x) { 1408 + switch (PPC_EXCP(env)) {
  1409 + case PPC_FLAGS_EXCP_40x:
  1410 + srr_0 = &env->spr[SPR_40x_SRR2];
  1411 + srr_1 = &env->spr[SPR_40x_SRR3];
  1412 + break;
  1413 + case PPC_FLAGS_EXCP_BOOKE:
  1414 + idx = 0;
  1415 + srr_0 = &env->spr[SPR_BOOKE_CSRR0];
  1416 + srr_1 = &env->spr[SPR_BOOKE_CSRR1];
  1417 + break;
  1418 + default:
1405 if (msr_ip) 1419 if (msr_ip)
1406 excp += 0xFFC00; 1420 excp += 0xFFC00;
1407 excp |= 0xFFC00000; 1421 excp |= 0xFFC00000;
1408 - } else {  
1409 - srr_0 = &env->spr[SPR_40x_SRR2];  
1410 - srr_1 = &env->spr[SPR_40x_SRR3]; 1422 + break;
1411 } 1423 }
1412 goto store_next; 1424 goto store_next;
1413 case EXCP_MACHINE_CHECK: /* 0x0200 */ 1425 case EXCP_MACHINE_CHECK: /* 0x0200 */
1414 - if (msr_me == 0) {  
1415 - cpu_abort(env, "Machine check exception while not allowed\n");  
1416 - }  
1417 - if (unlikely(PPC_EXCP(env) == PPC_FLAGS_EXCP_40x)) { 1426 + switch (PPC_EXCP(env)) {
  1427 + case PPC_FLAGS_EXCP_40x:
1418 srr_0 = &env->spr[SPR_40x_SRR2]; 1428 srr_0 = &env->spr[SPR_40x_SRR2];
1419 srr_1 = &env->spr[SPR_40x_SRR3]; 1429 srr_1 = &env->spr[SPR_40x_SRR3];
  1430 + break;
  1431 + case PPC_FLAGS_EXCP_BOOKE:
  1432 + idx = 1;
  1433 + srr_0 = &env->spr[SPR_BOOKE_MCSRR0];
  1434 + srr_1 = &env->spr[SPR_BOOKE_MCSRR1];
  1435 + asrr_0 = &env->spr[SPR_BOOKE_CSRR0];
  1436 + asrr_1 = &env->spr[SPR_BOOKE_CSRR1];
  1437 + msr_ce = 0;
  1438 + break;
  1439 + default:
  1440 + break;
1420 } 1441 }
1421 msr_me = 0; 1442 msr_me = 0;
1422 break; 1443 break;
@@ -1425,6 +1446,7 @@ void do_interrupt (CPUState *env) @@ -1425,6 +1446,7 @@ void do_interrupt (CPUState *env)
1425 /* data location address has been stored 1446 /* data location address has been stored
1426 * when the fault has been detected 1447 * when the fault has been detected
1427 */ 1448 */
  1449 + idx = 2;
1428 msr &= ~0xFFFF0000; 1450 msr &= ~0xFFFF0000;
1429 #if defined (DEBUG_EXCEPTIONS) 1451 #if defined (DEBUG_EXCEPTIONS)
1430 if (loglevel) { 1452 if (loglevel) {
@@ -1438,6 +1460,7 @@ void do_interrupt (CPUState *env) @@ -1438,6 +1460,7 @@ void do_interrupt (CPUState *env)
1438 goto store_next; 1460 goto store_next;
1439 case EXCP_ISI: /* 0x0400 */ 1461 case EXCP_ISI: /* 0x0400 */
1440 /* Store exception cause */ 1462 /* Store exception cause */
  1463 + idx = 3;
1441 msr &= ~0xFFFF0000; 1464 msr &= ~0xFFFF0000;
1442 msr |= env->error_code; 1465 msr |= env->error_code;
1443 #if defined (DEBUG_EXCEPTIONS) 1466 #if defined (DEBUG_EXCEPTIONS)
@@ -1448,20 +1471,12 @@ void do_interrupt (CPUState *env) @@ -1448,20 +1471,12 @@ void do_interrupt (CPUState *env)
1448 #endif 1471 #endif
1449 goto store_next; 1472 goto store_next;
1450 case EXCP_EXTERNAL: /* 0x0500 */ 1473 case EXCP_EXTERNAL: /* 0x0500 */
1451 - if (msr_ee == 0) {  
1452 -#if defined (DEBUG_EXCEPTIONS)  
1453 - if (loglevel > 0) {  
1454 - fprintf(logfile, "Skipping hardware interrupt\n");  
1455 - }  
1456 -#endif  
1457 - /* Requeue it */  
1458 - env->interrupt_request |= CPU_INTERRUPT_HARD;  
1459 - return;  
1460 - } 1474 + idx = 4;
1461 goto store_next; 1475 goto store_next;
1462 case EXCP_ALIGN: /* 0x0600 */ 1476 case EXCP_ALIGN: /* 0x0600 */
1463 if (likely(PPC_EXCP(env) != PPC_FLAGS_EXCP_601)) { 1477 if (likely(PPC_EXCP(env) != PPC_FLAGS_EXCP_601)) {
1464 /* Store exception cause */ 1478 /* Store exception cause */
  1479 + idx = 5;
1465 /* Get rS/rD and rA from faulting opcode */ 1480 /* Get rS/rD and rA from faulting opcode */
1466 env->spr[SPR_DSISR] |= 1481 env->spr[SPR_DSISR] |=
1467 (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16; 1482 (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
@@ -1476,6 +1491,7 @@ void do_interrupt (CPUState *env) @@ -1476,6 +1491,7 @@ void do_interrupt (CPUState *env)
1476 } 1491 }
1477 goto store_current; 1492 goto store_current;
1478 case EXCP_PROGRAM: /* 0x0700 */ 1493 case EXCP_PROGRAM: /* 0x0700 */
  1494 + idx = 6;
1479 msr &= ~0xFFFF0000; 1495 msr &= ~0xFFFF0000;
1480 switch (env->error_code & ~0xF) { 1496 switch (env->error_code & ~0xF) {
1481 case EXCP_FP: 1497 case EXCP_FP:
@@ -1501,6 +1517,7 @@ void do_interrupt (CPUState *env) @@ -1501,6 +1517,7 @@ void do_interrupt (CPUState *env)
1501 msr |= 0x00040000; 1517 msr |= 0x00040000;
1502 break; 1518 break;
1503 case EXCP_TRAP: 1519 case EXCP_TRAP:
  1520 + idx = 15;
1504 msr |= 0x00020000; 1521 msr |= 0x00020000;
1505 break; 1522 break;
1506 default: 1523 default:
@@ -1510,18 +1527,13 @@ void do_interrupt (CPUState *env) @@ -1510,18 +1527,13 @@ void do_interrupt (CPUState *env)
1510 msr |= 0x00010000; 1527 msr |= 0x00010000;
1511 goto store_current; 1528 goto store_current;
1512 case EXCP_NO_FP: /* 0x0800 */ 1529 case EXCP_NO_FP: /* 0x0800 */
  1530 + idx = 7;
1513 msr &= ~0xFFFF0000; 1531 msr &= ~0xFFFF0000;
1514 goto store_current; 1532 goto store_current;
1515 case EXCP_DECR: 1533 case EXCP_DECR:
1516 - if (msr_ee == 0) {  
1517 -#if 1  
1518 - /* Requeue it */  
1519 - env->interrupt_request |= CPU_INTERRUPT_TIMER;  
1520 -#endif  
1521 - return;  
1522 - }  
1523 goto store_next; 1534 goto store_next;
1524 case EXCP_SYSCALL: /* 0x0C00 */ 1535 case EXCP_SYSCALL: /* 0x0C00 */
  1536 + idx = 8;
1525 /* NOTE: this is a temporary hack to support graphics OSI 1537 /* NOTE: this is a temporary hack to support graphics OSI
1526 calls from the MOL driver */ 1538 calls from the MOL driver */
1527 if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b && 1539 if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b &&
@@ -1557,13 +1569,6 @@ void do_interrupt (CPUState *env) @@ -1557,13 +1569,6 @@ void do_interrupt (CPUState *env)
1557 "Instruction segment exception is not implemented yet !\n"); 1569 "Instruction segment exception is not implemented yet !\n");
1558 goto store_next; 1570 goto store_next;
1559 case EXCP_HDECR: /* 0x0980 */ 1571 case EXCP_HDECR: /* 0x0980 */
1560 - if (msr_ee == 0) {  
1561 -#if 1  
1562 - /* Requeue it */  
1563 - env->interrupt_request |= CPU_INTERRUPT_TIMER;  
1564 -#endif  
1565 - return;  
1566 - }  
1567 /* XXX: TODO */ 1572 /* XXX: TODO */
1568 cpu_abort(env, "Hypervisor decrementer exception is not implemented " 1573 cpu_abort(env, "Hypervisor decrementer exception is not implemented "
1569 "yet !\n"); 1574 "yet !\n");
@@ -1581,6 +1586,7 @@ void do_interrupt (CPUState *env) @@ -1581,6 +1586,7 @@ void do_interrupt (CPUState *env)
1581 } 1586 }
1582 return; 1587 return;
1583 case 0x0F20: 1588 case 0x0F20:
  1589 + idx = 9;
1584 switch (PPC_EXCP(env)) { 1590 switch (PPC_EXCP(env)) {
1585 case PPC_FLAGS_EXCP_40x: 1591 case PPC_FLAGS_EXCP_40x:
1586 /* APU unavailable on 405 */ 1592 /* APU unavailable on 405 */
@@ -1600,11 +1606,13 @@ void do_interrupt (CPUState *env) @@ -1600,11 +1606,13 @@ void do_interrupt (CPUState *env)
1600 } 1606 }
1601 return; 1607 return;
1602 case 0x1000: 1608 case 0x1000:
  1609 + idx = 10;
1603 switch (PPC_EXCP(env)) { 1610 switch (PPC_EXCP(env)) {
1604 case PPC_FLAGS_EXCP_40x: 1611 case PPC_FLAGS_EXCP_40x:
1605 /* PIT on 4xx */ 1612 /* PIT on 4xx */
1606 - /* XXX: TODO */  
1607 - cpu_abort(env, "40x PIT exception is not implemented yet !\n"); 1613 + msr &= ~0xFFFF0000;
  1614 + if (loglevel != 0)
  1615 + fprintf(logfile, "PIT exception\n");
1608 goto store_next; 1616 goto store_next;
1609 case PPC_FLAGS_EXCP_602: 1617 case PPC_FLAGS_EXCP_602:
1610 case PPC_FLAGS_EXCP_603: 1618 case PPC_FLAGS_EXCP_603:
@@ -1619,11 +1627,13 @@ void do_interrupt (CPUState *env) @@ -1619,11 +1627,13 @@ void do_interrupt (CPUState *env)
1619 } 1627 }
1620 return; 1628 return;
1621 case 0x1010: 1629 case 0x1010:
  1630 + idx = 11;
1622 switch (PPC_EXCP(env)) { 1631 switch (PPC_EXCP(env)) {
1623 case PPC_FLAGS_EXCP_40x: 1632 case PPC_FLAGS_EXCP_40x:
1624 /* FIT on 4xx */ 1633 /* FIT on 4xx */
1625 - /* XXX: TODO */  
1626 - cpu_abort(env, "40x FIT exception is not implemented yet !\n"); 1634 + msr &= ~0xFFFF0000;
  1635 + if (loglevel != 0)
  1636 + fprintf(logfile, "FIT exception\n");
1627 goto store_next; 1637 goto store_next;
1628 default: 1638 default:
1629 cpu_abort(env, "Invalid exception 0x1010 !\n"); 1639 cpu_abort(env, "Invalid exception 0x1010 !\n");
@@ -1631,19 +1641,25 @@ void do_interrupt (CPUState *env) @@ -1631,19 +1641,25 @@ void do_interrupt (CPUState *env)
1631 } 1641 }
1632 return; 1642 return;
1633 case 0x1020: 1643 case 0x1020:
  1644 + idx = 12;
1634 switch (PPC_EXCP(env)) { 1645 switch (PPC_EXCP(env)) {
1635 case PPC_FLAGS_EXCP_40x: 1646 case PPC_FLAGS_EXCP_40x:
1636 /* Watchdog on 4xx */ 1647 /* Watchdog on 4xx */
1637 - /* XXX: TODO */  
1638 - cpu_abort(env,  
1639 - "40x watchdog exception is not implemented yet !\n"); 1648 + msr &= ~0xFFFF0000;
  1649 + if (loglevel != 0)
  1650 + fprintf(logfile, "WDT exception\n");
1640 goto store_next; 1651 goto store_next;
  1652 + case PPC_FLAGS_EXCP_BOOKE:
  1653 + srr_0 = &env->spr[SPR_BOOKE_CSRR0];
  1654 + srr_1 = &env->spr[SPR_BOOKE_CSRR1];
  1655 + break;
1641 default: 1656 default:
1642 cpu_abort(env, "Invalid exception 0x1020 !\n"); 1657 cpu_abort(env, "Invalid exception 0x1020 !\n");
1643 break; 1658 break;
1644 } 1659 }
1645 return; 1660 return;
1646 case 0x1100: 1661 case 0x1100:
  1662 + idx = 13;
1647 switch (PPC_EXCP(env)) { 1663 switch (PPC_EXCP(env)) {
1648 case PPC_FLAGS_EXCP_40x: 1664 case PPC_FLAGS_EXCP_40x:
1649 /* DTLBMISS on 4xx */ 1665 /* DTLBMISS on 4xx */
@@ -1662,6 +1678,7 @@ void do_interrupt (CPUState *env) @@ -1662,6 +1678,7 @@ void do_interrupt (CPUState *env)
1662 } 1678 }
1663 return; 1679 return;
1664 case 0x1200: 1680 case 0x1200:
  1681 + idx = 14;
1665 switch (PPC_EXCP(env)) { 1682 switch (PPC_EXCP(env)) {
1666 case PPC_FLAGS_EXCP_40x: 1683 case PPC_FLAGS_EXCP_40x:
1667 /* ITLBMISS on 4xx */ 1684 /* ITLBMISS on 4xx */
@@ -1838,6 +1855,10 @@ void do_interrupt (CPUState *env) @@ -1838,6 +1855,10 @@ void do_interrupt (CPUState *env)
1838 cpu_abort(env, 1855 cpu_abort(env,
1839 "601 run mode exception is not implemented yet !\n"); 1856 "601 run mode exception is not implemented yet !\n");
1840 goto store_next; 1857 goto store_next;
  1858 + case PPC_FLAGS_EXCP_BOOKE:
  1859 + srr_0 = &env->spr[SPR_BOOKE_CSRR0];
  1860 + srr_1 = &env->spr[SPR_BOOKE_CSRR1];
  1861 + break;
1841 default: 1862 default:
1842 cpu_abort(env, "Invalid exception 0x1800 !\n"); 1863 cpu_abort(env, "Invalid exception 0x1800 !\n");
1843 break; 1864 break;
@@ -1852,15 +1873,19 @@ void do_interrupt (CPUState *env) @@ -1852,15 +1873,19 @@ void do_interrupt (CPUState *env)
1852 return; 1873 return;
1853 store_current: 1874 store_current:
1854 /* save current instruction location */ 1875 /* save current instruction location */
1855 - *srr_0 = (env->nip - 4) & 0xFFFFFFFFULL; 1876 + *srr_0 = env->nip - 4;
1856 break; 1877 break;
1857 store_next: 1878 store_next:
1858 /* save next instruction location */ 1879 /* save next instruction location */
1859 - *srr_0 = env->nip & 0xFFFFFFFFULL; 1880 + *srr_0 = env->nip;
1860 break; 1881 break;
1861 } 1882 }
1862 /* Save msr */ 1883 /* Save msr */
1863 *srr_1 = msr; 1884 *srr_1 = msr;
  1885 + if (asrr_0 != NULL)
  1886 + *asrr_0 = *srr_0;
  1887 + if (asrr_1 != NULL)
  1888 + *asrr_1 = *srr_1;
1864 /* If we disactivated any translation, flush TLBs */ 1889 /* If we disactivated any translation, flush TLBs */
1865 if (msr_ir || msr_dr) { 1890 if (msr_ir || msr_dr) {
1866 tlb_flush(env, 1); 1891 tlb_flush(env, 1);
@@ -1877,10 +1902,28 @@ void do_interrupt (CPUState *env) @@ -1877,10 +1902,28 @@ void do_interrupt (CPUState *env)
1877 msr_dr = 0; 1902 msr_dr = 0;
1878 msr_ri = 0; 1903 msr_ri = 0;
1879 msr_le = msr_ile; 1904 msr_le = msr_ile;
1880 - msr_sf = msr_isf; 1905 + if (PPC_EXCP(env) == PPC_FLAGS_EXCP_BOOKE) {
  1906 + msr_cm = msr_icm;
  1907 + if (idx == -1 || (idx >= 16 && idx < 32)) {
  1908 + cpu_abort(env, "Invalid exception index for excp %d %08x idx %d\n",
  1909 + excp, excp, idx);
  1910 + }
  1911 +#if defined(TARGET_PPC64)
  1912 + if (msr_cm)
  1913 + env->nip = (uint64_t)env->spr[SPR_BOOKE_IVPR];
  1914 + else
  1915 +#endif
  1916 + env->nip = (uint32_t)env->spr[SPR_BOOKE_IVPR];
  1917 + if (idx < 16)
  1918 + env->nip |= env->spr[SPR_BOOKE_IVOR0 + idx];
  1919 + else if (idx < 38)
  1920 + env->nip |= env->spr[SPR_BOOKE_IVOR32 + idx - 32];
  1921 + } else {
  1922 + msr_sf = msr_isf;
  1923 + env->nip = excp;
  1924 + }
1881 do_compute_hflags(env); 1925 do_compute_hflags(env);
1882 /* Jump to handler */ 1926 /* Jump to handler */
1883 - env->nip = excp;  
1884 env->exception_index = EXCP_NONE; 1927 env->exception_index = EXCP_NONE;
1885 } 1928 }
1886 1929