Revision a8dea12f target-ppc/helper.c
b/target-ppc/helper.c | ||
---|---|---|
549 | 549 |
if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) { |
550 | 550 |
/* Software TLB search */ |
551 | 551 |
ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type); |
552 |
} else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) { |
|
553 |
/* XXX: TODO */ |
|
554 | 552 |
} else { |
555 | 553 |
#if defined (DEBUG_MMU) |
556 | 554 |
if (loglevel > 0) { |
... | ... | |
632 | 630 |
return ret; |
633 | 631 |
} |
634 | 632 |
|
633 |
int mmu4xx_get_physical_address (CPUState *env, mmu_ctx_t *ctx, |
|
634 |
uint32_t address, int rw, int access_type) |
|
635 |
{ |
|
636 |
ppcemb_tlb_t *tlb; |
|
637 |
target_phys_addr_t raddr; |
|
638 |
target_ulong mask; |
|
639 |
int i, ret, zsel, zpr; |
|
640 |
|
|
641 |
ret = -6; |
|
642 |
for (i = 0; i < env->nb_tlb; i++) { |
|
643 |
tlb = &env->tlb[i].tlbe; |
|
644 |
/* Check valid flag */ |
|
645 |
if (!(tlb->prot & PAGE_VALID)) { |
|
646 |
if (loglevel) |
|
647 |
fprintf(logfile, "%s: TLB %d not valid\n", __func__, i); |
|
648 |
continue; |
|
649 |
} |
|
650 |
mask = ~(tlb->size - 1); |
|
651 |
if (loglevel) { |
|
652 |
fprintf(logfile, "%s: TLB %d address %08x PID %04x <=> " |
|
653 |
"%08x %08x %04x\n", |
|
654 |
__func__, i, address, env->spr[SPR_40x_PID], |
|
655 |
tlb->EPN, mask, tlb->PID); |
|
656 |
} |
|
657 |
/* Check PID */ |
|
658 |
if (tlb->PID != 0 && tlb->PID != env->spr[SPR_40x_PID]) |
|
659 |
continue; |
|
660 |
/* Check effective address */ |
|
661 |
if ((address & mask) != tlb->EPN) |
|
662 |
continue; |
|
663 |
raddr = (tlb->RPN & mask) | (address & ~mask); |
|
664 |
zsel = (tlb->attr >> 4) & 0xF; |
|
665 |
zpr = (env->spr[SPR_40x_ZPR] >> (28 - (2 * zsel))) & 0x3; |
|
666 |
if (loglevel) { |
|
667 |
fprintf(logfile, "%s: TLB %d zsel %d zpr %d rw %d attr %08x\n", |
|
668 |
__func__, i, zsel, zpr, rw, tlb->attr); |
|
669 |
} |
|
670 |
if (access_type == ACCESS_CODE) { |
|
671 |
/* Check execute enable bit */ |
|
672 |
switch (zpr) { |
|
673 |
case 0x0: |
|
674 |
if (msr_pr) { |
|
675 |
ret = -3; |
|
676 |
ctx->prot = 0; |
|
677 |
break; |
|
678 |
} |
|
679 |
/* No break here */ |
|
680 |
case 0x1: |
|
681 |
case 0x2: |
|
682 |
/* Check from TLB entry */ |
|
683 |
if (!(tlb->prot & PAGE_EXEC)) { |
|
684 |
ret = -3; |
|
685 |
} else { |
|
686 |
if (tlb->prot & PAGE_WRITE) |
|
687 |
ctx->prot = PAGE_READ | PAGE_WRITE; |
|
688 |
else |
|
689 |
ctx->prot = PAGE_READ; |
|
690 |
ret = 0; |
|
691 |
} |
|
692 |
break; |
|
693 |
case 0x3: |
|
694 |
/* All accesses granted */ |
|
695 |
ret = 0; |
|
696 |
ctx->prot = PAGE_READ | PAGE_WRITE; |
|
697 |
break; |
|
698 |
} |
|
699 |
} else { |
|
700 |
switch (zpr) { |
|
701 |
case 0x0: |
|
702 |
if (msr_pr) { |
|
703 |
ret = -2; |
|
704 |
ctx->prot = 0; |
|
705 |
break; |
|
706 |
} |
|
707 |
/* No break here */ |
|
708 |
case 0x1: |
|
709 |
case 0x2: |
|
710 |
/* Check from TLB entry */ |
|
711 |
/* Check write protection bit */ |
|
712 |
if (rw && !(tlb->prot & PAGE_WRITE)) { |
|
713 |
ret = -2; |
|
714 |
} else { |
|
715 |
ret = 2; |
|
716 |
if (tlb->prot & PAGE_WRITE) |
|
717 |
ctx->prot = PAGE_READ | PAGE_WRITE; |
|
718 |
else |
|
719 |
ctx->prot = PAGE_READ; |
|
720 |
} |
|
721 |
break; |
|
722 |
case 0x3: |
|
723 |
/* All accesses granted */ |
|
724 |
ret = 2; |
|
725 |
ctx->prot = PAGE_READ | PAGE_WRITE; |
|
726 |
break; |
|
727 |
} |
|
728 |
} |
|
729 |
if (ret >= 0) { |
|
730 |
ctx->raddr = raddr; |
|
731 |
if (loglevel) { |
|
732 |
fprintf(logfile, "%s: access granted " ADDRX " => " REGX |
|
733 |
" %d\n", __func__, address, ctx->raddr, ctx->prot); |
|
734 |
} |
|
735 |
return i; |
|
736 |
} |
|
737 |
} |
|
738 |
|
|
739 |
return ret; |
|
740 |
} |
|
741 |
|
|
635 | 742 |
static int check_physical (CPUState *env, mmu_ctx_t *ctx, |
636 | 743 |
target_ulong eaddr, int rw) |
637 | 744 |
{ |
... | ... | |
682 | 789 |
/* No address translation */ |
683 | 790 |
ret = check_physical(env, ctx, eaddr, rw); |
684 | 791 |
} else { |
685 |
/* Try to find a BAT */ |
|
686 |
ret = -1; |
|
687 |
if (check_BATs) |
|
688 |
ret = get_bat(env, ctx, eaddr, rw, access_type); |
|
689 |
if (ret < 0) { |
|
690 |
/* We didn't match any BAT entry */ |
|
691 |
ret = get_segment(env, ctx, eaddr, rw, access_type); |
|
792 |
switch (PPC_MMU(env)) { |
|
793 |
case PPC_FLAGS_MMU_32B: |
|
794 |
case PPC_FLAGS_MMU_SOFT_6xx: |
|
795 |
/* Try to find a BAT */ |
|
796 |
ret = -1; |
|
797 |
if (check_BATs) |
|
798 |
ret = get_bat(env, ctx, eaddr, rw, access_type); |
|
799 |
if (ret < 0) { |
|
800 |
/* We didn't match any BAT entry */ |
|
801 |
ret = get_segment(env, ctx, eaddr, rw, access_type); |
|
802 |
} |
|
803 |
break; |
|
804 |
case PPC_FLAGS_MMU_SOFT_4xx: |
|
805 |
ret = mmu4xx_get_physical_address(env, ctx, eaddr, |
|
806 |
rw, access_type); |
|
807 |
break; |
|
808 |
default: |
|
809 |
/* XXX: TODO */ |
|
810 |
cpu_abort(env, "MMU model not implemented\n"); |
|
811 |
return -1; |
|
692 | 812 |
} |
693 | 813 |
} |
694 | 814 |
#if 0 |
... | ... | |
753 | 873 |
error_code = 1 << 18; |
754 | 874 |
goto tlb_miss; |
755 | 875 |
} else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) { |
756 |
/* XXX: TODO */ |
|
876 |
exception = EXCP_40x_ITLBMISS; |
|
877 |
error_code = 0; |
|
878 |
env->spr[SPR_40x_DEAR] = address; |
|
879 |
env->spr[SPR_40x_ESR] = 0x00000000; |
|
757 | 880 |
} else { |
758 | 881 |
error_code = 0x40000000; |
759 | 882 |
} |
... | ... | |
799 | 922 |
/* Do not alter DAR nor DSISR */ |
800 | 923 |
goto out; |
801 | 924 |
} else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) { |
802 |
/* XXX: TODO */ |
|
925 |
exception = EXCP_40x_DTLBMISS; |
|
926 |
error_code = 0; |
|
927 |
env->spr[SPR_40x_DEAR] = address; |
|
928 |
if (rw) |
|
929 |
env->spr[SPR_40x_ESR] = 0x00800000; |
|
930 |
else |
|
931 |
env->spr[SPR_40x_ESR] = 0x00000000; |
|
803 | 932 |
} else { |
804 | 933 |
error_code = 0x40000000; |
805 | 934 |
} |
... | ... | |
1518 | 1647 |
switch (PPC_EXCP(env)) { |
1519 | 1648 |
case PPC_FLAGS_EXCP_40x: |
1520 | 1649 |
/* DTLBMISS on 4xx */ |
1521 |
/* XXX: TODO */ |
|
1522 |
cpu_abort(env, |
|
1523 |
"40x DTLBMISS exception is not implemented yet !\n"); |
|
1650 |
msr &= ~0xFFFF0000; |
|
1524 | 1651 |
goto store_next; |
1525 | 1652 |
case PPC_FLAGS_EXCP_602: |
1526 | 1653 |
case PPC_FLAGS_EXCP_603: |
... | ... | |
1538 | 1665 |
switch (PPC_EXCP(env)) { |
1539 | 1666 |
case PPC_FLAGS_EXCP_40x: |
1540 | 1667 |
/* ITLBMISS on 4xx */ |
1541 |
/* XXX: TODO */ |
|
1542 |
cpu_abort(env, |
|
1543 |
"40x ITLBMISS exception is not implemented yet !\n"); |
|
1668 |
msr &= ~0xFFFF0000; |
|
1544 | 1669 |
goto store_next; |
1545 | 1670 |
case PPC_FLAGS_EXCP_602: |
1546 | 1671 |
case PPC_FLAGS_EXCP_603: |
Also available in: Unified diff