table_walker.cc (11574:868c31fcca24) | table_walker.cc (11575:0005b28685f0) |
---|---|
1/* 2 * Copyright (c) 2010, 2012-2016 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 --- 235 unchanged lines hidden (view full) --- 244 currState->vaddr_tainted = currState->req->getVaddr(); 245 if (currState->aarch64) 246 currState->vaddr = purifyTaggedAddr(currState->vaddr_tainted, 247 currState->tc, currState->el); 248 else 249 currState->vaddr = currState->vaddr_tainted; 250 251 if (currState->aarch64) { | 1/* 2 * Copyright (c) 2010, 2012-2016 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 --- 235 unchanged lines hidden (view full) --- 244 currState->vaddr_tainted = currState->req->getVaddr(); 245 if (currState->aarch64) 246 currState->vaddr = purifyTaggedAddr(currState->vaddr_tainted, 247 currState->tc, currState->el); 248 else 249 currState->vaddr = currState->vaddr_tainted; 250 251 if (currState->aarch64) { |
252 switch (currState->el) { | 252 if (isStage2) { 253 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL1); 254 currState->vtcr = currState->tc->readMiscReg(MISCREG_VTCR_EL2); 255 } else switch (currState->el) { |
253 case EL0: 254 case EL1: 255 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL1); 256 currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL1); 257 break; 258 case EL2: 259 assert(_haveVirtualization); 260 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL2); 261 currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL2); 262 break; 263 case EL3: 264 assert(haveSecurity); 265 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL3); 266 currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL3); 267 break; 268 default: 269 panic("Invalid exception level"); 270 break; 271 } | 256 case EL0: 257 case EL1: 258 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL1); 259 currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL1); 260 break; 261 case EL2: 262 assert(_haveVirtualization); 263 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL2); 264 currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL2); 265 break; 266 case EL3: 267 assert(haveSecurity); 268 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL3); 269 currState->tcr = currState->tc->readMiscReg(MISCREG_TCR_EL3); 270 break; 271 default: 272 panic("Invalid exception level"); 273 break; 274 } |
275 currState->hcr = currState->tc->readMiscReg(MISCREG_HCR_EL2); |
|
272 } else { 273 currState->sctlr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 274 MISCREG_SCTLR, currState->tc, !currState->isSecure)); 275 currState->ttbcr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 276 MISCREG_TTBCR, currState->tc, !currState->isSecure)); 277 currState->htcr = currState->tc->readMiscReg(MISCREG_HTCR); 278 currState->hcr = currState->tc->readMiscReg(MISCREG_HCR); 279 currState->vtcr = currState->tc->readMiscReg(MISCREG_VTCR); --- 4 unchanged lines hidden (view full) --- 284 currState->isWrite = (currState->mode == TLB::Write); 285 286 statRequestOrigin[REQUESTED][currState->isFetch]++; 287 288 // We only do a second stage of translation if we're not secure, or in 289 // hyp mode, the second stage MMU is enabled, and this table walker 290 // instance is the first stage. 291 currState->doingStage2 = false; | 276 } else { 277 currState->sctlr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 278 MISCREG_SCTLR, currState->tc, !currState->isSecure)); 279 currState->ttbcr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 280 MISCREG_TTBCR, currState->tc, !currState->isSecure)); 281 currState->htcr = currState->tc->readMiscReg(MISCREG_HTCR); 282 currState->hcr = currState->tc->readMiscReg(MISCREG_HCR); 283 currState->vtcr = currState->tc->readMiscReg(MISCREG_VTCR); --- 4 unchanged lines hidden (view full) --- 288 currState->isWrite = (currState->mode == TLB::Write); 289 290 statRequestOrigin[REQUESTED][currState->isFetch]++; 291 292 // We only do a second stage of translation if we're not secure, or in 293 // hyp mode, the second stage MMU is enabled, and this table walker 294 // instance is the first stage. 295 currState->doingStage2 = false; |
292 // @todo: for now disable this in AArch64 (HCR is not set) 293 currState->stage2Req = !currState->aarch64 && currState->hcr.vm && 294 !isStage2 && !currState->isSecure && !currState->isHyp; | 296 currState->stage2Req = currState->hcr.vm && !isStage2 && 297 !currState->isSecure && !currState->isHyp; |
295 296 bool long_desc_format = currState->aarch64 || _isHyp || isStage2 || 297 longDescFormatInUse(currState->tc); 298 299 if (long_desc_format) { 300 // Helper variables used for hierarchical permissions 301 currState->secureLookup = currState->isSecure; 302 currState->rwTable = true; --- 435 unchanged lines hidden (view full) --- 738 739 statWalkWaitTime.sample(curTick() - currState->startTime); 740 741 // Determine TTBR, table size, granule size and phys. address range 742 Addr ttbr = 0; 743 int tsz = 0, ps = 0; 744 GrainSize tg = Grain4KB; // grain size computed from tg* field 745 bool fault = false; | 298 299 bool long_desc_format = currState->aarch64 || _isHyp || isStage2 || 300 longDescFormatInUse(currState->tc); 301 302 if (long_desc_format) { 303 // Helper variables used for hierarchical permissions 304 currState->secureLookup = currState->isSecure; 305 currState->rwTable = true; --- 435 unchanged lines hidden (view full) --- 741 742 statWalkWaitTime.sample(curTick() - currState->startTime); 743 744 // Determine TTBR, table size, granule size and phys. address range 745 Addr ttbr = 0; 746 int tsz = 0, ps = 0; 747 GrainSize tg = Grain4KB; // grain size computed from tg* field 748 bool fault = false; |
749 750 LookupLevel start_lookup_level = MAX_LOOKUP_LEVELS; 751 |
|
746 switch (currState->el) { 747 case EL0: 748 case EL1: | 752 switch (currState->el) { 753 case EL0: 754 case EL1: |
749 switch (bits(currState->vaddr, 63,48)) { | 755 if (isStage2) { 756 DPRINTF(TLB, " - Selecting VTTBR0 (AArch64 stage 2)\n"); 757 ttbr = currState->tc->readMiscReg(MISCREG_VTTBR_EL2); 758 tsz = 64 - currState->vtcr.t0sz64; 759 tg = GrainMapDefault[currState->vtcr.tg0]; 760 // ARM DDI 0487A.f D7-2148 761 // The starting level of stage 2 translation depends on 762 // VTCR_EL2.SL0 and VTCR_EL2.TG0 763 LookupLevel __ = MAX_LOOKUP_LEVELS; // invalid level 764 uint8_t sl_tg = (currState->vtcr.sl0 << 2) | currState->vtcr.tg0; 765 static const LookupLevel SLL[] = { 766 L2, L3, L3, __, // sl0 == 0 767 L1, L2, L2, __, // sl0 == 1, etc. 768 L0, L1, L1, __, 769 __, __, __, __ 770 }; 771 start_lookup_level = SLL[sl_tg]; 772 panic_if(start_lookup_level == MAX_LOOKUP_LEVELS, 773 "Cannot discern lookup level from vtcr.{sl0,tg0}"); 774 } else switch (bits(currState->vaddr, 63,48)) { |
750 case 0: 751 DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n"); 752 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL1); 753 tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz); 754 tg = GrainMapDefault[currState->tcr.tg0]; 755 if (bits(currState->vaddr, 63, tsz) != 0x0 || 756 currState->tcr.epd0) 757 fault = true; --- 61 unchanged lines hidden (view full) --- 819 } 820 821 if (tg == ReservedGrain) { 822 warn_once("Reserved granule size requested; gem5's IMPLEMENTATION " 823 "DEFINED behavior takes this to mean 4KB granules\n"); 824 tg = Grain4KB; 825 } 826 | 775 case 0: 776 DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n"); 777 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL1); 778 tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz); 779 tg = GrainMapDefault[currState->tcr.tg0]; 780 if (bits(currState->vaddr, 63, tsz) != 0x0 || 781 currState->tcr.epd0) 782 fault = true; --- 61 unchanged lines hidden (view full) --- 844 } 845 846 if (tg == ReservedGrain) { 847 warn_once("Reserved granule size requested; gem5's IMPLEMENTATION " 848 "DEFINED behavior takes this to mean 4KB granules\n"); 849 tg = Grain4KB; 850 } 851 |
827 int stride = tg - 3; 828 LookupLevel start_lookup_level = MAX_LOOKUP_LEVELS; 829 | |
830 // Determine starting lookup level 831 // See aarch64/translation/walk in Appendix G: ARMv8 Pseudocode Library 832 // in ARM DDI 0487A. These table values correspond to the cascading tests 833 // to compute the lookup level and are of the form 834 // (grain_size + N*stride), for N = {1, 2, 3}. 835 // A value of 64 will never succeed and a value of 0 will always succeed. | 852 // Determine starting lookup level 853 // See aarch64/translation/walk in Appendix G: ARMv8 Pseudocode Library 854 // in ARM DDI 0487A. These table values correspond to the cascading tests 855 // to compute the lookup level and are of the form 856 // (grain_size + N*stride), for N = {1, 2, 3}. 857 // A value of 64 will never succeed and a value of 0 will always succeed. |
836 { | 858 if (start_lookup_level == MAX_LOOKUP_LEVELS) { |
837 struct GrainMap { 838 GrainSize grain_size; 839 unsigned lookup_level_cutoff[MAX_LOOKUP_LEVELS]; 840 }; 841 static const GrainMap GM[] = { 842 { Grain4KB, { 39, 30, 0, 0 } }, 843 { Grain16KB, { 47, 36, 25, 0 } }, 844 { Grain64KB, { 64, 42, 29, 0 } } --- 14 unchanged lines hidden (view full) --- 859 start_lookup_level = (LookupLevel) L; 860 break; 861 } 862 } 863 panic_if(start_lookup_level == MAX_LOOKUP_LEVELS, 864 "Table walker couldn't find lookup level\n"); 865 } 866 | 859 struct GrainMap { 860 GrainSize grain_size; 861 unsigned lookup_level_cutoff[MAX_LOOKUP_LEVELS]; 862 }; 863 static const GrainMap GM[] = { 864 { Grain4KB, { 39, 30, 0, 0 } }, 865 { Grain16KB, { 47, 36, 25, 0 } }, 866 { Grain64KB, { 64, 42, 29, 0 } } --- 14 unchanged lines hidden (view full) --- 881 start_lookup_level = (LookupLevel) L; 882 break; 883 } 884 } 885 panic_if(start_lookup_level == MAX_LOOKUP_LEVELS, 886 "Table walker couldn't find lookup level\n"); 887 } 888 |
889 int stride = tg - 3; 890 |
|
867 // Determine table base address 868 int base_addr_lo = 3 + tsz - stride * (3 - start_lookup_level) - tg; 869 Addr base_addr = mbits(ttbr, 47, base_addr_lo); 870 871 // Determine physical address size and raise an Address Size Fault if 872 // necessary 873 int pa_range = decodePhysAddrRange64(ps); 874 // Clamp to lower limit --- 89 unchanged lines hidden (view full) --- 964 event, (uint8_t*) &currState->longDesc.data, 965 currState->tc->getCpuPtr()->clockPeriod(), flag); 966 DPRINTF(TLBVerbose, 967 "Adding to walker fifo: queue size before adding: %d\n", 968 stateQueues[start_lookup_level].size()); 969 stateQueues[start_lookup_level].push_back(currState); 970 currState = NULL; 971 } else if (!currState->functional) { | 891 // Determine table base address 892 int base_addr_lo = 3 + tsz - stride * (3 - start_lookup_level) - tg; 893 Addr base_addr = mbits(ttbr, 47, base_addr_lo); 894 895 // Determine physical address size and raise an Address Size Fault if 896 // necessary 897 int pa_range = decodePhysAddrRange64(ps); 898 // Clamp to lower limit --- 89 unchanged lines hidden (view full) --- 988 event, (uint8_t*) &currState->longDesc.data, 989 currState->tc->getCpuPtr()->clockPeriod(), flag); 990 DPRINTF(TLBVerbose, 991 "Adding to walker fifo: queue size before adding: %d\n", 992 stateQueues[start_lookup_level].size()); 993 stateQueues[start_lookup_level].push_back(currState); 994 currState = NULL; 995 } else if (!currState->functional) { |
972 port->dmaAction(MemCmd::ReadReq, desc_addr, sizeof(uint64_t), 973 NULL, (uint8_t*) &currState->longDesc.data, 974 currState->tc->getCpuPtr()->clockPeriod(), flag); 975 doLongDescriptor(); | 996 fetchDescriptor(desc_addr, (uint8_t*)&currState->longDesc.data, 997 sizeof(uint64_t), flag, -1, NULL, 998 &TableWalker::doLongDescriptor); |
976 f = currState->fault; 977 } else { 978 RequestPtr req = new Request(desc_addr, sizeof(uint64_t), flag, 979 masterId); 980 PacketPtr pkt = new Packet(req, MemCmd::ReadReq); 981 pkt->dataStatic((uint8_t*) &currState->longDesc.data); 982 port->sendFunctional(pkt); 983 doLongDescriptor(); --- 924 unchanged lines hidden (view full) --- 1908 1909bool 1910TableWalker::fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes, 1911 Request::Flags flags, int queueIndex, Event *event, 1912 void (TableWalker::*doDescriptor)()) 1913{ 1914 bool isTiming = currState->timing; 1915 | 999 f = currState->fault; 1000 } else { 1001 RequestPtr req = new Request(desc_addr, sizeof(uint64_t), flag, 1002 masterId); 1003 PacketPtr pkt = new Packet(req, MemCmd::ReadReq); 1004 pkt->dataStatic((uint8_t*) &currState->longDesc.data); 1005 port->sendFunctional(pkt); 1006 doLongDescriptor(); --- 924 unchanged lines hidden (view full) --- 1931 1932bool 1933TableWalker::fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes, 1934 Request::Flags flags, int queueIndex, Event *event, 1935 void (TableWalker::*doDescriptor)()) 1936{ 1937 bool isTiming = currState->timing; 1938 |
1916 // do the requests for the page table descriptors have to go through the 1917 // second stage MMU | 1939 DPRINTF(TLBVerbose, "Fetching descriptor at address: 0x%x stage2Req: %d\n", 1940 descAddr, currState->stage2Req); 1941 1942 // If this translation has a stage 2 then we know descAddr is an IPA and 1943 // needs to be translated before we can access the page table. Do that 1944 // check here. |
1918 if (currState->stage2Req) { 1919 Fault fault; 1920 flags = flags | TLB::MustBeOne; 1921 1922 if (isTiming) { 1923 Stage2MMU::Stage2Translation *tran = new 1924 Stage2MMU::Stage2Translation(*stage2Mmu, data, event, 1925 currState->vaddr); --- 299 unchanged lines hidden --- | 1945 if (currState->stage2Req) { 1946 Fault fault; 1947 flags = flags | TLB::MustBeOne; 1948 1949 if (isTiming) { 1950 Stage2MMU::Stage2Translation *tran = new 1951 Stage2MMU::Stage2Translation(*stage2Mmu, data, event, 1952 currState->vaddr); --- 299 unchanged lines hidden --- |