Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * OpenSPARC T2 Processor File: SS_Tte.h | |
5 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. | |
7 | * | |
8 | * The above named program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public | |
10 | * License version 2 as published by the Free Software Foundation. | |
11 | * | |
12 | * The above named program is distributed in the hope that it will be | |
13 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public | |
18 | * License along with this work; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |
20 | * | |
21 | * ========== Copyright Header End ============================================ | |
22 | */ | |
23 | #ifndef __SS_Tte_h__ | |
24 | #define __SS_Tte_h__ | |
25 | ||
26 | #include "SS_Types.h" | |
27 | #include "SS_State.h" | |
28 | ||
29 | class SS_Tte; | |
30 | ||
31 | class SS_Tte | |
32 | { | |
33 | public: | |
34 | SS_Tte() : tte_is_real(0), tte_is_virt(0), usage_count(0), tte_flags(0) {} | |
35 | ||
36 | // The first part of the SS_Tte object, the virt/phys_page/mask is for caching the TTE | |
37 | // and applying fast matching (match()) and translation (trans()). All the TTE specifics | |
38 | // should have been tested by the inst_mmu or data_mmu functions respectively in the strand. | |
39 | // The adapt() function is used when the tag or taddr ( translated address) is updated. | |
40 | ||
41 | SS_Vaddr virt_page; | |
42 | SS_Vaddr virt_mask; | |
43 | SS_Paddr phys_page; | |
44 | SS_Paddr phys_mask; | |
45 | ||
46 | bool match( SS_Vaddr a ) const { return (a & virt_mask) == virt_page; } | |
47 | SS_Paddr trans( SS_Vaddr a ) const { return (a &~ phys_mask) | phys_page; } | |
48 | ||
49 | void adapt() | |
50 | { | |
51 | virt_mask = ~SS_Vaddr(0) << (tte_page_size * 3 + 13); | |
52 | virt_page = tte_tag & virt_mask; | |
53 | phys_page = tte_taddr & virt_mask; | |
54 | phys_mask = virt_mask; | |
55 | } | |
56 | ||
57 | SS_Tte* next; // Next pointer in the free tte list in the tlb class | |
58 | uint_t index; // The index in the TLB where this tte is located. | |
59 | ||
60 | // The usage_count is 1 when the TTE is valid. Just before a TTE is demapped | |
61 | // we set the usage_count to the number of strands that might use the TTE. | |
62 | // When we are in tracing mode the usage_count is bumped to 2 and back to 1, | |
63 | // this to prevent accidental cases where the TTE is being demapped and we | |
64 | // we need it to produce trace output. | |
65 | ||
66 | int_t usage_count; // A count used to hold on to the TTE | |
67 | ||
68 | // The third part of the TTE is the actual TTE information as per architecture. | |
69 | // E.g all the associated bits. | |
70 | ||
71 | enum Flags | |
72 | { | |
73 | INVALID = 0x0000, | |
74 | PRIVILEGED = 0x0001, // p | |
75 | EXECUTABLE = 0x0002, // x (ep) | |
76 | WRITEABLE = 0x0004, // w | |
77 | NONFAULT = 0x0008, // nfo | |
78 | INV_ENDIAN = 0x0010, // ie | |
79 | CP = 0x0020, // cp | |
80 | CV = 0x0040, // cv | |
81 | SIDE_EFFECT = 0x0080, // e | |
82 | TAG_PARITY = 0x0100, // tag parity | |
83 | DATA_PARITY = 0x0200, // data parity | |
84 | VALID_BIT = 0x0400, // v | |
85 | REAL_BIT = 0x0800, // r | |
86 | LOCK_BIT = 0x1000, // l | |
87 | MULTI_HIT = 0x2000, // a condition that is set when TTE is looked up | |
88 | VALID_ERROR = 0x4000 // duplicated valid bit mismatch | |
89 | }; | |
90 | ||
91 | int valid() { return tte_is_real || tte_is_virt; } | |
92 | int is_real() { return tte_is_real; } | |
93 | int is_virt() { return tte_is_virt; } | |
94 | uint8_t pid() { return tte_pid; } | |
95 | uint16_t context() { return tte_context; } | |
96 | uint8_t page_size() { return tte_page_size; } | |
97 | SS_Vaddr tag() { return tte_tag; } | |
98 | SS_Paddr taddr() { return tte_taddr; } | |
99 | ||
100 | private: | |
101 | void assign_flag( Flags bit, int val ) { if (val) tte_flags |= bit; else tte_flags &= ~bit; } | |
102 | int test_flag( Flags bit ) { return 0 != (tte_flags & bit); } | |
103 | ||
104 | public: | |
105 | int p() { return test_flag(PRIVILEGED); } | |
106 | int x() { return test_flag(EXECUTABLE); } | |
107 | int w() { return test_flag(WRITEABLE); } | |
108 | int nfo() { return test_flag(NONFAULT); } | |
109 | int ie() { return test_flag(INV_ENDIAN); } | |
110 | int cp() { return test_flag(CP); } | |
111 | int cv() { return test_flag(CV); } | |
112 | int e() { return test_flag(SIDE_EFFECT); } | |
113 | int lock() { return test_flag(LOCK_BIT); } | |
114 | int valid_bit() { return test_flag(VALID_BIT); } | |
115 | int real_bit() { return test_flag(REAL_BIT); } | |
116 | int multi_hit() { return test_flag(MULTI_HIT); } | |
117 | int tag_parity_error() { return test_flag(TAG_PARITY); } | |
118 | int data_parity_error() { return test_flag(DATA_PARITY); } | |
119 | int valid_bit_error() { return test_flag(VALID_ERROR); } | |
120 | ||
121 | void p( int f ) { assign_flag(PRIVILEGED,f); } | |
122 | void x( int f ) { assign_flag(EXECUTABLE,f); } | |
123 | void w( int f ) { assign_flag(WRITEABLE,f); } | |
124 | void nfo( int f ) { assign_flag(NONFAULT,f); } | |
125 | void ie( int f ) { assign_flag(INV_ENDIAN,f); } | |
126 | void cp( int f ) { assign_flag(CP,f); } | |
127 | void cv( int f ) { assign_flag(CV,f); } | |
128 | void e( int f ) { assign_flag(SIDE_EFFECT,f); } | |
129 | void lock( int f ) { assign_flag(LOCK_BIT,f); } | |
130 | void valid_bit( int f ) { assign_flag(VALID_BIT,f); virt_real_update(); } | |
131 | void real_bit( int f ) { assign_flag(REAL_BIT,f); virt_real_update(); } | |
132 | void multi_hit( int f ) { assign_flag(MULTI_HIT,f); } | |
133 | void tag_parity_error( int f ) { assign_flag(TAG_PARITY,f); } | |
134 | void data_parity_error( int f ) { assign_flag(DATA_PARITY,f); } | |
135 | void valid_bit_error( int f ) { assign_flag(VALID_ERROR,f); } | |
136 | ||
137 | void virt_real_update() | |
138 | { | |
139 | // We keep two one hot bits for faster checking for | |
140 | // valid real or valid virt TTEs. However for interface reasons | |
141 | // we need to keep the valid and real bit as is. Just internally | |
142 | // we use the one bit test is_real, is_virt flags. | |
143 | ||
144 | if (valid_bit()) | |
145 | { | |
146 | if (real_bit()) | |
147 | { | |
148 | tte_is_real = true; | |
149 | tte_is_virt = false; | |
150 | } | |
151 | else | |
152 | { | |
153 | tte_is_real = false; | |
154 | tte_is_virt = true; | |
155 | } | |
156 | } | |
157 | else | |
158 | { | |
159 | tte_is_real = false; | |
160 | tte_is_virt = false; | |
161 | } | |
162 | } | |
163 | ||
164 | void virt( int v ) { tte_is_virt = v; } | |
165 | void real( int r ) { tte_is_real = r; } | |
166 | void pid( uint8_t p ) { tte_pid = p; } | |
167 | void context( uint16_t c ) { tte_context = c; } | |
168 | void page_size( uint8_t p ) { tte_page_size = p; adapt(); } | |
169 | void tag( SS_Vaddr t ) { tte_tag = t; adapt(); } | |
170 | void taddr( SS_Paddr t ) { tte_taddr = t; adapt(); } | |
171 | ||
172 | void set_real( uint16_t pid, uint8_t ps, SS_Vaddr tag, SS_Paddr dst ) | |
173 | { | |
174 | valid_bit(true); | |
175 | real_bit(true); | |
176 | tte_pid = pid; | |
177 | tte_page_size = ps; | |
178 | tte_tag = tag; | |
179 | tte_taddr = dst; | |
180 | adapt(); | |
181 | } | |
182 | ||
183 | void set_virt( uint16_t pid, uint16_t context, uint8_t ps, SS_Vaddr tag, SS_Paddr dst ) | |
184 | { | |
185 | valid_bit(true); | |
186 | real_bit(false); | |
187 | tte_pid = pid; | |
188 | tte_page_size = ps; | |
189 | tte_tag = tag; | |
190 | tte_context = context; | |
191 | tte_taddr = dst; | |
192 | adapt(); | |
193 | } | |
194 | ||
195 | bool match_real( SS_Vaddr ra, uint_t pid ) const | |
196 | { | |
197 | return tte_is_real && match(ra) && (tte_pid == pid); | |
198 | } | |
199 | ||
200 | bool match_virt( SS_Vaddr va, uint64_t ctxt, uint_t pid ) const | |
201 | { | |
202 | return tte_is_virt && (tte_context == ctxt) && match(va) && (tte_pid == pid); | |
203 | } | |
204 | ||
205 | bool match_virt( SS_Vaddr va, uint64_t ctxt0, uint64_t ctxt1, uint_t pid ) const | |
206 | { | |
207 | return tte_is_virt && ((tte_context == ctxt0) || (tte_context == ctxt1)) && match(va) && (tte_pid == pid); | |
208 | } | |
209 | ||
210 | // This routine checks if there is a multi hit error or a tag parity error or data parity error | |
211 | bool has_errors() | |
212 | { | |
213 | return multi_hit() | tag_parity_error() | data_parity_error() | valid_bit_error(); | |
214 | } | |
215 | ||
216 | // insert_tsb_tte() inserts a sun4v TTE into this TTE. The vpn of the TTE is extended | |
217 | // with bits 21:13 of the va, as the vpn in the TSB only has bit 63:22. | |
218 | void insert_tsb_tte( uint16_t pid, uint64_t tag, uint64_t data, SS_Vaddr addr ) | |
219 | { | |
220 | SS_TsbTteTag tsb_tag; | |
221 | SS_TsbTteData tsb_data; | |
222 | ||
223 | tte_flags = 0; | |
224 | ||
225 | tsb_tag = tag; | |
226 | tsb_data = data; | |
227 | ||
228 | real_bit(0); | |
229 | valid_bit(tsb_data.v()); | |
230 | ||
231 | tte_pid = pid; | |
232 | tte_context = tsb_tag.context(); | |
233 | tte_page_size = tsb_data.size(); | |
234 | ||
235 | p( tsb_data.p()); | |
236 | x( tsb_data.x()); | |
237 | w( tsb_data.w()); | |
238 | nfo(tsb_data.nfo()); | |
239 | ie( tsb_data.ie()); | |
240 | cp( tsb_data.cp()); | |
241 | cv( tsb_data.cv()); | |
242 | e( tsb_data.e()); | |
243 | ||
244 | tte_tag = ((tsb_tag.va() << 9) | ((addr >> 13) & 0x1ff)) << 13; | |
245 | tte_taddr = tsb_data.pa() << 13; | |
246 | ||
247 | adapt(); | |
248 | } | |
249 | ||
250 | // insert_sun4u_tsb_tte() inserts a sun4u TTE into the TTE. The vpn of the TTE is extended | |
251 | // with bits 21:13 of the va, as the vpn in the TSB only has bit 63:22. | |
252 | void insert_sun4u_tsb_tte( uint16_t pid, uint64_t tag, uint64_t data, SS_Vaddr addr ) | |
253 | { | |
254 | // TODO for Ch and N1, see above | |
255 | } | |
256 | ||
257 | void snapshot( SS_SnapShot& ss, const char* prefix ); | |
258 | void dump(FILE *fp=stdout); | |
259 | ||
260 | protected: | |
261 | uint8_t tte_is_real; // Nonzero for valid real TTE | |
262 | uint8_t tte_is_virt; // Nonzero for valid virt TTE | |
263 | uint8_t tte_pid; // The partition for which this TTE is valid | |
264 | uint8_t tte_page_size; // 0=8Kb, 1=64Kb, ... | |
265 | uint16_t tte_context; // The context for virt TTE | |
266 | uint16_t tte_flags; // The flags p,w,x,ie,nfo ... | |
267 | SS_Vaddr tte_tag; // The TTE tag (va or ra) | |
268 | SS_Paddr tte_taddr; // The TTE target address (pa or ra) | |
269 | }; | |
270 | ||
271 | #endif | |
272 |