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