2 * Copyright (c) 2010-2013, 2016, 2018 ARM Limited
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
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 #include "arch/arm/stage2_lookup.hh"
43 #include "arch/arm/faults.hh"
44 #include "arch/arm/system.hh"
45 #include "arch/arm/table_walker.hh"
46 #include "arch/arm/tlb.hh"
47 #include "cpu/base.hh"
48 #include "cpu/thread_context.hh"
49 #include "debug/Checkpoint.hh"
50 #include "debug/TLB.hh"
51 #include "debug/TLBVerbose.hh"
52 #include "sim/system.hh"
54 using namespace ArmISA
;
57 Stage2LookUp::getTe(ThreadContext
*tc
, TlbEntry
*destTe
)
60 fault
= stage2Tlb
->getTE(&stage2Te
, req
, tc
, mode
, this, timing
,
61 functional
, false, tranType
);
62 // Call finish if we're done already
63 if ((fault
!= NoFault
) || (stage2Te
!= NULL
)) {
64 // Since we directly requested the table entry (which we need later on
65 // to merge the attributes) then we've skipped some stage2 permissions
66 // checking. So call translate on stage 2 to do the checking. As the
67 // entry is now in the TLB this should always hit the cache.
68 if (fault
== NoFault
) {
70 fault
= stage2Tlb
->checkPermissions64(stage2Te
, req
, mode
, tc
);
72 fault
= stage2Tlb
->checkPermissions(stage2Te
, req
, mode
);
82 Stage2LookUp::mergeTe(const RequestPtr
&req
, BaseTLB::Mode mode
)
84 // Check again that we haven't got a fault
85 if (fault
== NoFault
) {
86 assert(stage2Te
!= NULL
);
88 // Now we have the table entries for both stages of translation
89 // merge them and insert the result into the stage 1 TLB. See
90 // CombineS1S2Desc() in pseudocode
91 stage1Te
.nonCacheable
|= stage2Te
->nonCacheable
;
92 stage1Te
.xn
|= stage2Te
->xn
;
94 if (stage1Te
.size
> stage2Te
->size
) {
95 // Size mismatch also implies vpn mismatch (this is shifted by
97 stage1Te
.vpn
= s1Req
->getVaddr() >> stage2Te
->N
;
98 stage1Te
.pfn
= stage2Te
->pfn
;
99 stage1Te
.size
= stage2Te
->size
;
100 stage1Te
.N
= stage2Te
->N
;
101 } else if (stage1Te
.size
< stage2Te
->size
) {
102 // Guest 4K could well be section-backed by host hugepage! In this
103 // case a 4K entry is added but pfn needs to be adjusted. New PFN =
104 // offset into section PFN given by stage2 IPA treated as a stage1
106 const Addr pa
= (stage2Te
->pfn
<< stage2Te
->N
);
107 const Addr ipa
= (stage1Te
.pfn
<< stage1Te
.N
);
108 stage1Te
.pfn
= (pa
| (ipa
& mask(stage2Te
->N
))) >> stage1Te
.N
;
109 // Size remains smaller of the two.
112 stage1Te
.pfn
= stage2Te
->pfn
;
115 if (stage2Te
->mtype
== TlbEntry::MemoryType::StronglyOrdered
||
116 stage1Te
.mtype
== TlbEntry::MemoryType::StronglyOrdered
) {
117 stage1Te
.mtype
= TlbEntry::MemoryType::StronglyOrdered
;
118 } else if (stage2Te
->mtype
== TlbEntry::MemoryType::Device
||
119 stage1Te
.mtype
== TlbEntry::MemoryType::Device
) {
120 stage1Te
.mtype
= TlbEntry::MemoryType::Device
;
122 stage1Te
.mtype
= TlbEntry::MemoryType::Normal
;
125 if (stage1Te
.mtype
== TlbEntry::MemoryType::Normal
) {
127 if (stage2Te
->innerAttrs
== 0 ||
128 stage1Te
.innerAttrs
== 0) {
129 // either encoding Non-cacheable
130 stage1Te
.innerAttrs
= 0;
131 } else if (stage2Te
->innerAttrs
== 2 ||
132 stage1Te
.innerAttrs
== 2) {
133 // either encoding Write-Through cacheable
134 stage1Te
.innerAttrs
= 2;
136 // both encodings Write-Back
137 stage1Te
.innerAttrs
= 3;
140 if (stage2Te
->outerAttrs
== 0 ||
141 stage1Te
.outerAttrs
== 0) {
142 // either encoding Non-cacheable
143 stage1Te
.outerAttrs
= 0;
144 } else if (stage2Te
->outerAttrs
== 2 ||
145 stage1Te
.outerAttrs
== 2) {
146 // either encoding Write-Through cacheable
147 stage1Te
.outerAttrs
= 2;
149 // both encodings Write-Back
150 stage1Te
.outerAttrs
= 3;
153 stage1Te
.shareable
|= stage2Te
->shareable
;
154 stage1Te
.outerShareable
|= stage2Te
->outerShareable
;
155 if (stage1Te
.innerAttrs
== 0 &&
156 stage1Te
.outerAttrs
== 0) {
157 // something Non-cacheable at each level is outer shareable
158 stage1Te
.shareable
= true;
159 stage1Te
.outerShareable
= true;
162 stage1Te
.shareable
= true;
163 stage1Te
.outerShareable
= true;
165 stage1Te
.updateAttributes();
168 // if there's a fault annotate it,
169 if (fault
!= NoFault
) {
170 // If the second stage of translation generated a fault add the
171 // details of the original stage 1 virtual address
172 reinterpret_cast<ArmFault
*>(fault
.get())->annotate(ArmFault::OVA
,
179 Stage2LookUp::finish(const Fault
&_fault
, const RequestPtr
&req
,
180 ThreadContext
*tc
, BaseTLB::Mode mode
)
183 // if we haven't got the table entry get it now
184 if ((fault
== NoFault
) && (stage2Te
== NULL
)) {
185 fault
= stage2Tlb
->getTE(&stage2Te
, req
, tc
, mode
, this,
186 timing
, functional
, false, tranType
);
189 // Now we have the stage 2 table entry we need to merge it with the stage
190 // 1 entry we were given at the start
193 if (fault
!= NoFault
) {
194 // Returning with a fault requires the original request
195 transState
->finish(fault
, s1Req
, tc
, mode
);
197 // Now notify the original stage 1 translation that we finally have
199 stage1Tlb
->translateComplete(s1Req
, tc
, transState
, mode
, tranType
, true);
201 // if we have been asked to delete ourselfs do it now