Revision faadf50e target-ppc/helper.c
b/target-ppc/helper.c | ||
---|---|---|
448 | 448 |
} |
449 | 449 |
|
450 | 450 |
/* Perform BAT hit & translation */ |
451 |
static always_inline void bat_size_prot (CPUState *env, target_ulong *blp, |
|
452 |
int *validp, int *protp, |
|
453 |
target_ulong *BATu, target_ulong *BATl) |
|
454 |
{ |
|
455 |
target_ulong bl; |
|
456 |
int pp, valid, prot; |
|
457 |
|
|
458 |
bl = (*BATu & 0x00001FFC) << 15; |
|
459 |
valid = 0; |
|
460 |
prot = 0; |
|
461 |
if (((msr_pr == 0) && (*BATu & 0x00000002)) || |
|
462 |
((msr_pr != 0) && (*BATu & 0x00000001))) { |
|
463 |
valid = 1; |
|
464 |
pp = *BATl & 0x00000003; |
|
465 |
if (pp != 0) { |
|
466 |
prot = PAGE_READ | PAGE_EXEC; |
|
467 |
if (pp == 0x2) |
|
468 |
prot |= PAGE_WRITE; |
|
469 |
} |
|
470 |
} |
|
471 |
*blp = bl; |
|
472 |
*validp = valid; |
|
473 |
*protp = prot; |
|
474 |
} |
|
475 |
|
|
476 |
static always_inline void bat_601_size_prot (CPUState *env,target_ulong *blp, |
|
477 |
int *validp, int *protp, |
|
478 |
target_ulong *BATu, |
|
479 |
target_ulong *BATl) |
|
480 |
{ |
|
481 |
target_ulong bl; |
|
482 |
int key, pp, valid, prot; |
|
483 |
|
|
484 |
bl = (*BATl & 0x0000003F) << 17; |
|
485 |
if (loglevel != 0) { |
|
486 |
fprintf(logfile, "b %02x ==> bl %08x msk %08x\n", |
|
487 |
*BATl & 0x0000003F, bl, ~bl); |
|
488 |
} |
|
489 |
prot = 0; |
|
490 |
valid = (*BATl >> 6) & 1; |
|
491 |
if (valid) { |
|
492 |
pp = *BATu & 0x00000003; |
|
493 |
if (msr_pr == 0) |
|
494 |
key = (*BATu >> 3) & 1; |
|
495 |
else |
|
496 |
key = (*BATu >> 2) & 1; |
|
497 |
prot = pp_check(key, pp, 0); |
|
498 |
} |
|
499 |
*blp = bl; |
|
500 |
*validp = valid; |
|
501 |
*protp = prot; |
|
502 |
} |
|
503 |
|
|
451 | 504 |
static always_inline int get_bat (CPUState *env, mmu_ctx_t *ctx, |
452 | 505 |
target_ulong virtual, int rw, int type) |
453 | 506 |
{ |
454 | 507 |
target_ulong *BATlt, *BATut, *BATu, *BATl; |
455 | 508 |
target_ulong base, BEPIl, BEPIu, bl; |
456 |
int i, pp, pr;
|
|
509 |
int i, valid, prot;
|
|
457 | 510 |
int ret = -1; |
458 | 511 |
|
459 | 512 |
#if defined (DEBUG_BATS) |
... | ... | |
462 | 515 |
type == ACCESS_CODE ? 'I' : 'D', virtual); |
463 | 516 |
} |
464 | 517 |
#endif |
465 |
pr = msr_pr; |
|
466 | 518 |
switch (type) { |
467 | 519 |
case ACCESS_CODE: |
468 | 520 |
BATlt = env->IBAT[1]; |
... | ... | |
480 | 532 |
} |
481 | 533 |
#endif |
482 | 534 |
base = virtual & 0xFFFC0000; |
483 |
for (i = 0; i < 4; i++) {
|
|
535 |
for (i = 0; i < env->nb_BATs; i++) {
|
|
484 | 536 |
BATu = &BATut[i]; |
485 | 537 |
BATl = &BATlt[i]; |
486 | 538 |
BEPIu = *BATu & 0xF0000000; |
487 | 539 |
BEPIl = *BATu & 0x0FFE0000; |
488 |
bl = (*BATu & 0x00001FFC) << 15; |
|
540 |
if (unlikely(env->mmu_model == POWERPC_MMU_601)) { |
|
541 |
bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl); |
|
542 |
} else { |
|
543 |
bat_size_prot(env, &bl, &valid, &prot, BATu, BATl); |
|
544 |
} |
|
489 | 545 |
#if defined (DEBUG_BATS) |
490 | 546 |
if (loglevel != 0) { |
491 | 547 |
fprintf(logfile, "%s: %cBAT%d v 0x" ADDRX " BATu 0x" ADDRX |
... | ... | |
497 | 553 |
if ((virtual & 0xF0000000) == BEPIu && |
498 | 554 |
((virtual & 0x0FFE0000) & ~bl) == BEPIl) { |
499 | 555 |
/* BAT matches */ |
500 |
if (((pr == 0) && (*BATu & 0x00000002)) || |
|
501 |
((pr != 0) && (*BATu & 0x00000001))) { |
|
556 |
if (valid != 0) { |
|
502 | 557 |
/* Get physical address */ |
503 | 558 |
ctx->raddr = (*BATl & 0xF0000000) | |
504 | 559 |
((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) | |
505 | 560 |
(virtual & 0x0001F000); |
506 | 561 |
/* Compute access rights */ |
507 |
pp = *BATl & 0x00000003; |
|
508 |
ctx->prot = 0; |
|
509 |
if (pp != 0) { |
|
510 |
ctx->prot = PAGE_READ | PAGE_EXEC; |
|
511 |
if (pp == 0x2) |
|
512 |
ctx->prot |= PAGE_WRITE; |
|
513 |
} |
|
562 |
ctx->prot = prot; |
|
514 | 563 |
ret = check_prot(ctx->prot, rw, type); |
515 | 564 |
#if defined (DEBUG_BATS) |
516 | 565 |
if (ret == 0 && loglevel != 0) { |
... | ... | |
1302 | 1351 |
ret = 0; |
1303 | 1352 |
switch (env->mmu_model) { |
1304 | 1353 |
case POWERPC_MMU_32B: |
1354 |
case POWERPC_MMU_601: |
|
1305 | 1355 |
case POWERPC_MMU_SOFT_6xx: |
1306 | 1356 |
case POWERPC_MMU_SOFT_74xx: |
1307 | 1357 |
case POWERPC_MMU_SOFT_4xx: |
... | ... | |
1353 | 1403 |
} |
1354 | 1404 |
|
1355 | 1405 |
int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr, |
1356 |
int rw, int access_type, int check_BATs)
|
|
1406 |
int rw, int access_type) |
|
1357 | 1407 |
{ |
1358 | 1408 |
int ret; |
1359 | 1409 |
|
... | ... | |
1370 | 1420 |
ret = -1; |
1371 | 1421 |
switch (env->mmu_model) { |
1372 | 1422 |
case POWERPC_MMU_32B: |
1423 |
case POWERPC_MMU_601: |
|
1373 | 1424 |
case POWERPC_MMU_SOFT_6xx: |
1374 | 1425 |
case POWERPC_MMU_SOFT_74xx: |
1375 |
/* Try to find a BAT */ |
|
1376 |
if (check_BATs) |
|
1377 |
ret = get_bat(env, ctx, eaddr, rw, access_type); |
|
1378 |
/* No break here */ |
|
1379 | 1426 |
#if defined(TARGET_PPC64) |
1380 | 1427 |
case POWERPC_MMU_64B: |
1381 | 1428 |
#endif |
1429 |
/* Try to find a BAT */ |
|
1430 |
if (env->nb_BATs != 0) |
|
1431 |
ret = get_bat(env, ctx, eaddr, rw, access_type); |
|
1382 | 1432 |
if (ret < 0) { |
1383 | 1433 |
/* We didn't match any BAT entry or don't have BATs */ |
1384 | 1434 |
ret = get_segment(env, ctx, eaddr, rw, access_type); |
... | ... | |
1419 | 1469 |
{ |
1420 | 1470 |
mmu_ctx_t ctx; |
1421 | 1471 |
|
1422 |
if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT, 1) != 0))
|
|
1472 |
if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0)) |
|
1423 | 1473 |
return -1; |
1424 | 1474 |
|
1425 | 1475 |
return ctx.raddr & TARGET_PAGE_MASK; |
... | ... | |
1444 | 1494 |
access_type = ACCESS_INT; |
1445 | 1495 |
// access_type = env->access_type; |
1446 | 1496 |
} |
1447 |
ret = get_physical_address(env, &ctx, address, rw, access_type, 1);
|
|
1497 |
ret = get_physical_address(env, &ctx, address, rw, access_type); |
|
1448 | 1498 |
if (ret == 0) { |
1449 | 1499 |
ret = tlb_set_page_exec(env, address & TARGET_PAGE_MASK, |
1450 | 1500 |
ctx.raddr & TARGET_PAGE_MASK, ctx.prot, |
... | ... | |
1476 | 1526 |
env->spr[SPR_40x_ESR] = 0x00000000; |
1477 | 1527 |
break; |
1478 | 1528 |
case POWERPC_MMU_32B: |
1529 |
case POWERPC_MMU_601: |
|
1479 | 1530 |
#if defined(TARGET_PPC64) |
1480 | 1531 |
case POWERPC_MMU_64B: |
1481 | 1532 |
#endif |
... | ... | |
1567 | 1618 |
env->spr[SPR_40x_ESR] = 0x00000000; |
1568 | 1619 |
break; |
1569 | 1620 |
case POWERPC_MMU_32B: |
1621 |
case POWERPC_MMU_601: |
|
1570 | 1622 |
#if defined(TARGET_PPC64) |
1571 | 1623 |
case POWERPC_MMU_64B: |
1572 | 1624 |
#endif |
... | ... | |
1809 | 1861 |
cpu_abort(env, "MMU model not implemented\n"); |
1810 | 1862 |
break; |
1811 | 1863 |
case POWERPC_MMU_32B: |
1864 |
case POWERPC_MMU_601: |
|
1812 | 1865 |
#if defined(TARGET_PPC64) |
1813 | 1866 |
case POWERPC_MMU_64B: |
1814 | 1867 |
#endif /* defined(TARGET_PPC64) */ |
... | ... | |
1848 | 1901 |
cpu_abort(env, "MMU model not implemented\n"); |
1849 | 1902 |
break; |
1850 | 1903 |
case POWERPC_MMU_32B: |
1904 |
case POWERPC_MMU_601: |
|
1851 | 1905 |
/* tlbie invalidate TLBs for all segments */ |
1852 | 1906 |
addr &= ~((target_ulong)-1 << 28); |
1853 | 1907 |
/* XXX: this case should be optimized, |
Also available in: Unified diff