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 --- |