table_walker.cc (10109:b58c5c5854de) table_walker.cc (10324:f40134eb3f85)
1/*
1/*
2 * Copyright (c) 2010, 2012-2013 ARM Limited
2 * Copyright (c) 2010, 2012-2014 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated

--- 204 unchanged lines hidden (view full) ---

215 else
216 currState->vaddr = currState->vaddr_tainted;
217
218 if (currState->aarch64) {
219 switch (currState->el) {
220 case EL0:
221 case EL1:
222 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL1);
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated

--- 204 unchanged lines hidden (view full) ---

215 else
216 currState->vaddr = currState->vaddr_tainted;
217
218 if (currState->aarch64) {
219 switch (currState->el) {
220 case EL0:
221 case EL1:
222 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL1);
223 currState->ttbcr = currState->tc->readMiscReg(MISCREG_TCR_EL1);
223 currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL1);
224 break;
225 // @todo: uncomment this to enable Virtualization
226 // case EL2:
227 // assert(haveVirtualization);
228 // currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL2);
224 break;
225 // @todo: uncomment this to enable Virtualization
226 // case EL2:
227 // assert(haveVirtualization);
228 // currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL2);
229 // currState->ttbcr = currState->tc->readMiscReg(MISCREG_TCR_EL2);
229 // currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL2);
230 // break;
231 case EL3:
232 assert(haveSecurity);
233 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL3);
230 // break;
231 case EL3:
232 assert(haveSecurity);
233 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL3);
234 currState->ttbcr = currState->tc->readMiscReg(MISCREG_TCR_EL3);
234 currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL3);
235 break;
236 default:
237 panic("Invalid exception level");
238 break;
239 }
240 } else {
241 currState->sctlr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
242 MISCREG_SCTLR, currState->tc, !currState->isSecure));

--- 377 unchanged lines hidden (view full) ---

620 flag = Request::UNCACHEABLE;
621 }
622
623 if (currState->isSecure)
624 flag.set(Request::SECURE);
625
626 currState->longDesc.lookupLevel = start_lookup_level;
627 currState->longDesc.aarch64 = false;
235 break;
236 default:
237 panic("Invalid exception level");
238 break;
239 }
240 } else {
241 currState->sctlr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
242 MISCREG_SCTLR, currState->tc, !currState->isSecure));

--- 377 unchanged lines hidden (view full) ---

620 flag = Request::UNCACHEABLE;
621 }
622
623 if (currState->isSecure)
624 flag.set(Request::SECURE);
625
626 currState->longDesc.lookupLevel = start_lookup_level;
627 currState->longDesc.aarch64 = false;
628 currState->longDesc.largeGrain = false;
629 currState->longDesc.grainSize = 12;
628 currState->longDesc.grainSize = Grain4KB;
630
631 Event *event = start_lookup_level == L1 ? (Event *) &doL1LongDescEvent
632 : (Event *) &doL2LongDescEvent;
633
634 bool delayed = fetchDescriptor(desc_addr, (uint8_t*)&currState->longDesc.data,
635 sizeof(uint64_t), flag, start_lookup_level,
636 event, &TableWalker::doLongDescriptor);
637 if (!delayed) {

--- 20 unchanged lines hidden (view full) ---

658 bits(addr, MaxPhysAddrRange - 1, currPhysAddrRange));
659}
660
661Fault
662TableWalker::processWalkAArch64()
663{
664 assert(currState->aarch64);
665
629
630 Event *event = start_lookup_level == L1 ? (Event *) &doL1LongDescEvent
631 : (Event *) &doL2LongDescEvent;
632
633 bool delayed = fetchDescriptor(desc_addr, (uint8_t*)&currState->longDesc.data,
634 sizeof(uint64_t), flag, start_lookup_level,
635 event, &TableWalker::doLongDescriptor);
636 if (!delayed) {

--- 20 unchanged lines hidden (view full) ---

657 bits(addr, MaxPhysAddrRange - 1, currPhysAddrRange));
658}
659
660Fault
661TableWalker::processWalkAArch64()
662{
663 assert(currState->aarch64);
664
666 DPRINTF(TLB, "Beginning table walk for address %#llx, TTBCR: %#llx\n",
667 currState->vaddr_tainted, currState->ttbcr);
665 DPRINTF(TLB, "Beginning table walk for address %#llx, TCR: %#llx\n",
666 currState->vaddr_tainted, currState->tcr);
668
667
668 static const GrainSize GrainMapDefault[] =
669 { Grain4KB, Grain64KB, Grain16KB, ReservedGrain };
670 static const GrainSize GrainMap_EL1_tg1[] =
671 { ReservedGrain, Grain16KB, Grain4KB, Grain64KB };
672
669 // Determine TTBR, table size, granule size and phys. address range
670 Addr ttbr = 0;
671 int tsz = 0, ps = 0;
673 // Determine TTBR, table size, granule size and phys. address range
674 Addr ttbr = 0;
675 int tsz = 0, ps = 0;
672 bool large_grain = false;
676 GrainSize tg = Grain4KB; // grain size computed from tg* field
673 bool fault = false;
674 switch (currState->el) {
675 case EL0:
676 case EL1:
677 switch (bits(currState->vaddr, 63,48)) {
678 case 0:
679 DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n");
680 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL1);
677 bool fault = false;
678 switch (currState->el) {
679 case EL0:
680 case EL1:
681 switch (bits(currState->vaddr, 63,48)) {
682 case 0:
683 DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n");
684 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL1);
681 tsz = adjustTableSizeAArch64(64 - currState->ttbcr.t0sz);
682 large_grain = currState->ttbcr.tg0;
685 tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz);
686 tg = GrainMapDefault[currState->tcr.tg0];
683 if (bits(currState->vaddr, 63, tsz) != 0x0 ||
687 if (bits(currState->vaddr, 63, tsz) != 0x0 ||
684 currState->ttbcr.epd0)
688 currState->tcr.epd0)
685 fault = true;
686 break;
687 case 0xffff:
688 DPRINTF(TLB, " - Selecting TTBR1 (AArch64)\n");
689 ttbr = currState->tc->readMiscReg(MISCREG_TTBR1_EL1);
689 fault = true;
690 break;
691 case 0xffff:
692 DPRINTF(TLB, " - Selecting TTBR1 (AArch64)\n");
693 ttbr = currState->tc->readMiscReg(MISCREG_TTBR1_EL1);
690 tsz = adjustTableSizeAArch64(64 - currState->ttbcr.t1sz);
691 large_grain = currState->ttbcr.tg1;
694 tsz = adjustTableSizeAArch64(64 - currState->tcr.t1sz);
695 tg = GrainMap_EL1_tg1[currState->tcr.tg1];
692 if (bits(currState->vaddr, 63, tsz) != mask(64-tsz) ||
696 if (bits(currState->vaddr, 63, tsz) != mask(64-tsz) ||
693 currState->ttbcr.epd1)
697 currState->tcr.epd1)
694 fault = true;
695 break;
696 default:
697 // top two bytes must be all 0s or all 1s, else invalid addr
698 fault = true;
699 }
698 fault = true;
699 break;
700 default:
701 // top two bytes must be all 0s or all 1s, else invalid addr
702 fault = true;
703 }
700 ps = currState->ttbcr.ips;
704 ps = currState->tcr.ips;
701 break;
702 case EL2:
703 case EL3:
704 switch(bits(currState->vaddr, 63,48)) {
705 case 0:
705 break;
706 case EL2:
707 case EL3:
708 switch(bits(currState->vaddr, 63,48)) {
709 case 0:
706 DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n");
707 if (currState->el == EL2)
708 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL2);
709 else
710 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL3);
711 tsz = adjustTableSizeAArch64(64 - currState->ttbcr.t0sz);
712 large_grain = currState->ttbcr.tg0;
710 DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n");
711 if (currState->el == EL2)
712 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL2);
713 else
714 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL3);
715 tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz);
716 tg = GrainMapDefault[currState->tcr.tg0];
713 break;
714 default:
715 // invalid addr if top two bytes are not all 0s
717 break;
718 default:
719 // invalid addr if top two bytes are not all 0s
716 fault = true;
720 fault = true;
717 }
721 }
718 ps = currState->ttbcr.ps;
722 ps = currState->tcr.ips;
719 break;
720 }
721
722 if (fault) {
723 Fault f;
724 if (currState->isFetch)
725 f = new PrefetchAbort(currState->vaddr_tainted,
726 ArmFault::TranslationLL + L0, isStage2,

--- 12 unchanged lines hidden (view full) ---

739 } else {
740 currState->tc = NULL;
741 currState->req = NULL;
742 }
743 return f;
744
745 }
746
723 break;
724 }
725
726 if (fault) {
727 Fault f;
728 if (currState->isFetch)
729 f = new PrefetchAbort(currState->vaddr_tainted,
730 ArmFault::TranslationLL + L0, isStage2,

--- 12 unchanged lines hidden (view full) ---

743 } else {
744 currState->tc = NULL;
745 currState->req = NULL;
746 }
747 return f;
748
749 }
750
751 if (tg == ReservedGrain) {
752 warn_once("Reserved granule size requested; gem5's IMPLEMENTATION "
753 "DEFINED behavior takes this to mean 4KB granules\n");
754 tg = Grain4KB;
755 }
756
757 int stride = tg - 3;
758 LookupLevel start_lookup_level = MAX_LOOKUP_LEVELS;
759
747 // Determine starting lookup level
760 // Determine starting lookup level
748 LookupLevel start_lookup_level;
749 int grain_size, stride;
750 if (large_grain) { // 64 KB granule
751 grain_size = 16;
752 stride = grain_size - 3;
753 if (tsz > grain_size + 2 * stride)
754 start_lookup_level = L1;
755 else if (tsz > grain_size + stride)
756 start_lookup_level = L2;
757 else
758 start_lookup_level = L3;
759 } else { // 4 KB granule
760 grain_size = 12;
761 stride = grain_size - 3;
762 if (tsz > grain_size + 3 * stride)
763 start_lookup_level = L0;
764 else if (tsz > grain_size + 2 * stride)
765 start_lookup_level = L1;
766 else
767 start_lookup_level = L2;
761 // See aarch64/translation/walk in Appendix G: ARMv8 Pseudocode Library
762 // in ARM DDI 0487A. These table values correspond to the cascading tests
763 // to compute the lookup level and are of the form
764 // (grain_size + N*stride), for N = {1, 2, 3}.
765 // A value of 64 will never succeed and a value of 0 will always succeed.
766 {
767 struct GrainMap {
768 GrainSize grain_size;
769 unsigned lookup_level_cutoff[MAX_LOOKUP_LEVELS];
770 };
771 static const GrainMap GM[] = {
772 { Grain4KB, { 39, 30, 0, 0 } },
773 { Grain16KB, { 47, 36, 25, 0 } },
774 { Grain64KB, { 64, 42, 29, 0 } }
775 };
776
777 const unsigned *lookup = NULL; // points to a lookup_level_cutoff
778
779 for (unsigned i = 0; i < 3; ++i) { // choose entry of GM[]
780 if (tg == GM[i].grain_size) {
781 lookup = GM[i].lookup_level_cutoff;
782 break;
783 }
784 }
785 assert(lookup);
786
787 for (int L = L0; L != MAX_LOOKUP_LEVELS; ++L) {
788 if (tsz > lookup[L]) {
789 start_lookup_level = (LookupLevel) L;
790 break;
791 }
792 }
793 panic_if(start_lookup_level == MAX_LOOKUP_LEVELS,
794 "Table walker couldn't find lookup level\n");
768 }
769
770 // Determine table base address
795 }
796
797 // Determine table base address
771 int base_addr_lo = 3 + tsz - stride * (3 - start_lookup_level) -
772 grain_size;
798 int base_addr_lo = 3 + tsz - stride * (3 - start_lookup_level) - tg;
773 Addr base_addr = mbits(ttbr, 47, base_addr_lo);
774
775 // Determine physical address size and raise an Address Size Fault if
776 // necessary
777 int pa_range = decodePhysAddrRange64(ps);
778 // Clamp to lower limit
779 if (pa_range > physAddrRange)
780 currState->physAddrRange = physAddrRange;

--- 26 unchanged lines hidden (view full) ---

807 }
808 return f;
809
810 }
811
812 // Determine descriptor address
813 Addr desc_addr = base_addr |
814 (bits(currState->vaddr, tsz - 1,
799 Addr base_addr = mbits(ttbr, 47, base_addr_lo);
800
801 // Determine physical address size and raise an Address Size Fault if
802 // necessary
803 int pa_range = decodePhysAddrRange64(ps);
804 // Clamp to lower limit
805 if (pa_range > physAddrRange)
806 currState->physAddrRange = physAddrRange;

--- 26 unchanged lines hidden (view full) ---

833 }
834 return f;
835
836 }
837
838 // Determine descriptor address
839 Addr desc_addr = base_addr |
840 (bits(currState->vaddr, tsz - 1,
815 stride * (3 - start_lookup_level) + grain_size) << 3);
841 stride * (3 - start_lookup_level) + tg) << 3);
816
817 // Trickbox address check
818 Fault f = tlb->walkTrickBoxCheck(desc_addr, currState->isSecure,
819 currState->vaddr, sizeof(uint64_t), currState->isFetch,
820 currState->isWrite, TlbEntry::DomainType::NoAccess,
821 start_lookup_level);
822 if (f) {
823 DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted);

--- 10 unchanged lines hidden (view full) ---

834
835 Request::Flags flag = 0;
836 if (currState->sctlr.c == 0) {
837 flag = Request::UNCACHEABLE;
838 }
839
840 currState->longDesc.lookupLevel = start_lookup_level;
841 currState->longDesc.aarch64 = true;
842
843 // Trickbox address check
844 Fault f = tlb->walkTrickBoxCheck(desc_addr, currState->isSecure,
845 currState->vaddr, sizeof(uint64_t), currState->isFetch,
846 currState->isWrite, TlbEntry::DomainType::NoAccess,
847 start_lookup_level);
848 if (f) {
849 DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted);

--- 10 unchanged lines hidden (view full) ---

860
861 Request::Flags flag = 0;
862 if (currState->sctlr.c == 0) {
863 flag = Request::UNCACHEABLE;
864 }
865
866 currState->longDesc.lookupLevel = start_lookup_level;
867 currState->longDesc.aarch64 = true;
842 currState->longDesc.largeGrain = large_grain;
843 currState->longDesc.grainSize = grain_size;
868 currState->longDesc.grainSize = tg;
844
845 if (currState->timing) {
846 Event *event;
847 switch (start_lookup_level) {
848 case L0:
849 event = (Event *) &doL0LongDescEvent;
850 break;
851 case L1:

--- 1112 unchanged lines hidden ---
869
870 if (currState->timing) {
871 Event *event;
872 switch (start_lookup_level) {
873 case L0:
874 event = (Event *) &doL0LongDescEvent;
875 break;
876 case L1:

--- 1112 unchanged lines hidden ---