110037SARM gem5 Developers/*
213375Sanouk.vanlaer@arm.com * Copyright (c) 2010-2013, 2016, 2018 ARM Limited
310037SARM gem5 Developers * All rights reserved
410037SARM gem5 Developers *
510037SARM gem5 Developers * The license below extends only to copyright in the software and shall
610037SARM gem5 Developers * not be construed as granting a license to any other intellectual
710037SARM gem5 Developers * property including but not limited to intellectual property relating
810037SARM gem5 Developers * to a hardware implementation of the functionality of the software
910037SARM gem5 Developers * licensed hereunder.  You may use the software subject to the license
1010037SARM gem5 Developers * terms below provided that you ensure that this notice is replicated
1110037SARM gem5 Developers * unmodified and in its entirety in all distributions of the software,
1210037SARM gem5 Developers * modified or unmodified, in source code or in binary form.
1310037SARM gem5 Developers *
1410037SARM gem5 Developers * Redistribution and use in source and binary forms, with or without
1510037SARM gem5 Developers * modification, are permitted provided that the following conditions are
1610037SARM gem5 Developers * met: redistributions of source code must retain the above copyright
1710037SARM gem5 Developers * notice, this list of conditions and the following disclaimer;
1810037SARM gem5 Developers * redistributions in binary form must reproduce the above copyright
1910037SARM gem5 Developers * notice, this list of conditions and the following disclaimer in the
2010037SARM gem5 Developers * documentation and/or other materials provided with the distribution;
2110037SARM gem5 Developers * neither the name of the copyright holders nor the names of its
2210037SARM gem5 Developers * contributors may be used to endorse or promote products derived from
2310037SARM gem5 Developers * this software without specific prior written permission.
2410037SARM gem5 Developers *
2510037SARM gem5 Developers * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2610037SARM gem5 Developers * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2710037SARM gem5 Developers * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2810037SARM gem5 Developers * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2910037SARM gem5 Developers * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3010037SARM gem5 Developers * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3110037SARM gem5 Developers * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3210037SARM gem5 Developers * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3310037SARM gem5 Developers * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3410037SARM gem5 Developers * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3510037SARM gem5 Developers * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3610037SARM gem5 Developers *
3710037SARM gem5 Developers * Authors: Ali Saidi
3810037SARM gem5 Developers *          Giacomo Gabrielli
3910037SARM gem5 Developers */
4010037SARM gem5 Developers
4111793Sbrandon.potter@amd.com#include "arch/arm/stage2_lookup.hh"
4211793Sbrandon.potter@amd.com
4310037SARM gem5 Developers#include "arch/arm/faults.hh"
4410037SARM gem5 Developers#include "arch/arm/system.hh"
4510037SARM gem5 Developers#include "arch/arm/table_walker.hh"
4610037SARM gem5 Developers#include "arch/arm/tlb.hh"
4710037SARM gem5 Developers#include "cpu/base.hh"
4810037SARM gem5 Developers#include "cpu/thread_context.hh"
4910037SARM gem5 Developers#include "debug/Checkpoint.hh"
5010037SARM gem5 Developers#include "debug/TLB.hh"
5110037SARM gem5 Developers#include "debug/TLBVerbose.hh"
5210037SARM gem5 Developers#include "sim/system.hh"
5310037SARM gem5 Developers
5410037SARM gem5 Developersusing namespace ArmISA;
5510037SARM gem5 Developers
5610037SARM gem5 DevelopersFault
5710037SARM gem5 DevelopersStage2LookUp::getTe(ThreadContext *tc, TlbEntry *destTe)
5810037SARM gem5 Developers
5910037SARM gem5 Developers{
6012749Sgiacomo.travaglini@arm.com    fault = stage2Tlb->getTE(&stage2Te, req, tc, mode, this, timing,
6110037SARM gem5 Developers                                   functional, false, tranType);
6210037SARM gem5 Developers    // Call finish if we're done already
6310037SARM gem5 Developers    if ((fault != NoFault) || (stage2Te != NULL)) {
6411586SDylan.Johnson@ARM.com        // Since we directly requested the table entry (which we need later on
6511586SDylan.Johnson@ARM.com        // to merge the attributes) then we've skipped some stage2 permissions
6611586SDylan.Johnson@ARM.com        // checking. So call translate on stage 2 to do the checking. As the
6711586SDylan.Johnson@ARM.com        // entry is now in the TLB this should always hit the cache.
6811586SDylan.Johnson@ARM.com        if (fault == NoFault) {
6912736Sandreas.sandberg@arm.com            if (ELIs64(tc, EL2))
7012749Sgiacomo.travaglini@arm.com                fault = stage2Tlb->checkPermissions64(stage2Te, req, mode, tc);
7111586SDylan.Johnson@ARM.com            else
7212749Sgiacomo.travaglini@arm.com                fault = stage2Tlb->checkPermissions(stage2Te, req, mode);
7311586SDylan.Johnson@ARM.com        }
7411586SDylan.Johnson@ARM.com
7512749Sgiacomo.travaglini@arm.com        mergeTe(req, mode);
7610037SARM gem5 Developers        *destTe = stage1Te;
7710037SARM gem5 Developers    }
7810037SARM gem5 Developers    return fault;
7910037SARM gem5 Developers}
8010037SARM gem5 Developers
8110037SARM gem5 Developersvoid
8212749Sgiacomo.travaglini@arm.comStage2LookUp::mergeTe(const RequestPtr &req, BaseTLB::Mode mode)
8310037SARM gem5 Developers{
8410037SARM gem5 Developers    // Check again that we haven't got a fault
8510037SARM gem5 Developers    if (fault == NoFault) {
8610037SARM gem5 Developers        assert(stage2Te != NULL);
8710037SARM gem5 Developers
8810037SARM gem5 Developers        // Now we have the table entries for both stages of translation
8910037SARM gem5 Developers        // merge them and insert the result into the stage 1 TLB. See
9010037SARM gem5 Developers        // CombineS1S2Desc() in pseudocode
9110037SARM gem5 Developers        stage1Te.nonCacheable |= stage2Te->nonCacheable;
9210037SARM gem5 Developers        stage1Te.xn           |= stage2Te->xn;
9310037SARM gem5 Developers
9410037SARM gem5 Developers        if (stage1Te.size > stage2Te->size) {
9510037SARM gem5 Developers            // Size mismatch also implies vpn mismatch (this is shifted by
9610037SARM gem5 Developers            // sizebits!).
9712734Sandreas.sandberg@arm.com            stage1Te.vpn  = s1Req->getVaddr() >> stage2Te->N;
9810037SARM gem5 Developers            stage1Te.pfn  = stage2Te->pfn;
9910037SARM gem5 Developers            stage1Te.size = stage2Te->size;
10012734Sandreas.sandberg@arm.com            stage1Te.N    = stage2Te->N;
10110037SARM gem5 Developers        } else if (stage1Te.size < stage2Te->size) {
10210037SARM gem5 Developers            // Guest 4K could well be section-backed by host hugepage!  In this
10310037SARM gem5 Developers            // case a 4K entry is added but pfn needs to be adjusted.  New PFN =
10410037SARM gem5 Developers            // offset into section PFN given by stage2 IPA treated as a stage1
10510037SARM gem5 Developers            // page size.
10612734Sandreas.sandberg@arm.com            const Addr pa = (stage2Te->pfn << stage2Te->N);
10712734Sandreas.sandberg@arm.com            const Addr ipa = (stage1Te.pfn << stage1Te.N);
10812734Sandreas.sandberg@arm.com            stage1Te.pfn = (pa | (ipa & mask(stage2Te->N))) >> stage1Te.N;
10910037SARM gem5 Developers            // Size remains smaller of the two.
11010037SARM gem5 Developers        } else {
11110037SARM gem5 Developers            // Matching sizes
11210037SARM gem5 Developers            stage1Te.pfn = stage2Te->pfn;
11310037SARM gem5 Developers        }
11410037SARM gem5 Developers
11510037SARM gem5 Developers        if (stage2Te->mtype == TlbEntry::MemoryType::StronglyOrdered ||
11610037SARM gem5 Developers            stage1Te.mtype  == TlbEntry::MemoryType::StronglyOrdered) {
11710037SARM gem5 Developers            stage1Te.mtype  =  TlbEntry::MemoryType::StronglyOrdered;
11810037SARM gem5 Developers        } else if (stage2Te->mtype == TlbEntry::MemoryType::Device ||
11910037SARM gem5 Developers                   stage1Te.mtype  == TlbEntry::MemoryType::Device) {
12010037SARM gem5 Developers            stage1Te.mtype = TlbEntry::MemoryType::Device;
12110037SARM gem5 Developers        } else {
12210037SARM gem5 Developers            stage1Te.mtype = TlbEntry::MemoryType::Normal;
12310037SARM gem5 Developers        }
12410037SARM gem5 Developers
12510037SARM gem5 Developers        if (stage1Te.mtype == TlbEntry::MemoryType::Normal) {
12610037SARM gem5 Developers
12710037SARM gem5 Developers            if (stage2Te->innerAttrs == 0 ||
12810037SARM gem5 Developers                stage1Te.innerAttrs  == 0) {
12910037SARM gem5 Developers                // either encoding Non-cacheable
13010037SARM gem5 Developers                stage1Te.innerAttrs = 0;
13110037SARM gem5 Developers            } else if (stage2Te->innerAttrs == 2 ||
13210037SARM gem5 Developers                       stage1Te.innerAttrs  == 2) {
13310037SARM gem5 Developers                // either encoding Write-Through cacheable
13410037SARM gem5 Developers                stage1Te.innerAttrs = 2;
13510037SARM gem5 Developers            } else {
13610037SARM gem5 Developers                // both encodings Write-Back
13710037SARM gem5 Developers                stage1Te.innerAttrs = 3;
13810037SARM gem5 Developers            }
13910037SARM gem5 Developers
14010037SARM gem5 Developers            if (stage2Te->outerAttrs == 0 ||
14110037SARM gem5 Developers                stage1Te.outerAttrs  == 0) {
14210037SARM gem5 Developers                // either encoding Non-cacheable
14310037SARM gem5 Developers                stage1Te.outerAttrs = 0;
14410037SARM gem5 Developers            } else if (stage2Te->outerAttrs == 2 ||
14510037SARM gem5 Developers                       stage1Te.outerAttrs  == 2) {
14610037SARM gem5 Developers                // either encoding Write-Through cacheable
14710037SARM gem5 Developers                stage1Te.outerAttrs = 2;
14810037SARM gem5 Developers            } else {
14910037SARM gem5 Developers                // both encodings Write-Back
15010037SARM gem5 Developers                stage1Te.outerAttrs = 3;
15110037SARM gem5 Developers            }
15210037SARM gem5 Developers
15310037SARM gem5 Developers            stage1Te.shareable       |= stage2Te->shareable;
15410037SARM gem5 Developers            stage1Te.outerShareable |= stage2Te->outerShareable;
15510037SARM gem5 Developers            if (stage1Te.innerAttrs == 0 &&
15610037SARM gem5 Developers                stage1Te.outerAttrs == 0) {
15710037SARM gem5 Developers                // something Non-cacheable at each level is outer shareable
15810037SARM gem5 Developers                stage1Te.shareable       = true;
15910037SARM gem5 Developers                stage1Te.outerShareable = true;
16010037SARM gem5 Developers            }
16110037SARM gem5 Developers        } else {
16210037SARM gem5 Developers            stage1Te.shareable       = true;
16310037SARM gem5 Developers            stage1Te.outerShareable = true;
16410037SARM gem5 Developers        }
16510037SARM gem5 Developers        stage1Te.updateAttributes();
16610037SARM gem5 Developers    }
16710037SARM gem5 Developers
16810037SARM gem5 Developers    // if there's a fault annotate it,
16910037SARM gem5 Developers    if (fault != NoFault) {
17010037SARM gem5 Developers        // If the second stage of translation generated a fault add the
17110037SARM gem5 Developers        // details of the original stage 1 virtual address
17210037SARM gem5 Developers        reinterpret_cast<ArmFault *>(fault.get())->annotate(ArmFault::OVA,
17310037SARM gem5 Developers            s1Req->getVaddr());
17410037SARM gem5 Developers    }
17510037SARM gem5 Developers    complete = true;
17610037SARM gem5 Developers}
17710037SARM gem5 Developers
17810037SARM gem5 Developersvoid
17912749Sgiacomo.travaglini@arm.comStage2LookUp::finish(const Fault &_fault, const RequestPtr &req,
18010037SARM gem5 Developers    ThreadContext *tc, BaseTLB::Mode mode)
18110037SARM gem5 Developers{
18210037SARM gem5 Developers    fault = _fault;
18310037SARM gem5 Developers    // if we haven't got the table entry get it now
18410037SARM gem5 Developers    if ((fault == NoFault) && (stage2Te == NULL)) {
18510037SARM gem5 Developers        fault = stage2Tlb->getTE(&stage2Te, req, tc, mode, this,
18610037SARM gem5 Developers            timing, functional, false, tranType);
18710037SARM gem5 Developers    }
18810037SARM gem5 Developers
18910037SARM gem5 Developers    // Now we have the stage 2 table entry we need to merge it with the stage
19010037SARM gem5 Developers    // 1 entry we were given at the start
19110037SARM gem5 Developers    mergeTe(req, mode);
19210037SARM gem5 Developers
19310037SARM gem5 Developers    if (fault != NoFault) {
19413375Sanouk.vanlaer@arm.com        // Returning with a fault requires the original request
19513375Sanouk.vanlaer@arm.com        transState->finish(fault, s1Req, tc, mode);
19610037SARM gem5 Developers    } else if (timing) {
19710037SARM gem5 Developers        // Now notify the original stage 1 translation that we finally have
19810037SARM gem5 Developers        // a result
19910037SARM gem5 Developers        stage1Tlb->translateComplete(s1Req, tc, transState, mode, tranType, true);
20010037SARM gem5 Developers    }
20110037SARM gem5 Developers    // if we have been asked to delete ourselfs do it now
20210037SARM gem5 Developers    if (selfDelete) {
20310037SARM gem5 Developers        delete this;
20410037SARM gem5 Developers    }
20510037SARM gem5 Developers}
20610037SARM gem5 Developers
207