Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | # ========== Copyright Header Begin ========================================== |
2 | # | |
3 | # OpenSPARC T2 Processor File: TTEFormat.pm | |
4 | # Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved | |
5 | # 4150 Network Circle, Santa Clara, California 95054, U.S.A. | |
6 | # | |
7 | # * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
8 | # | |
9 | # This program is free software; you can redistribute it and/or modify | |
10 | # it under the terms of the GNU General Public License as published by | |
11 | # the Free Software Foundation; version 2 of the License. | |
12 | # | |
13 | # This program is distributed in the hope that it will be useful, | |
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | # GNU General Public License for more details. | |
17 | # | |
18 | # You should have received a copy of the GNU General Public License | |
19 | # along with this program; if not, write to the Free Software | |
20 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 | # | |
22 | # For the avoidance of doubt, and except that if any non-GPL license | |
23 | # choice is available it will apply instead, Sun elects to use only | |
24 | # the General Public License version 2 (GPLv2) at this time for any | |
25 | # software where a choice of GPL license versions is made | |
26 | # available with the language indicating that GPLv2 or any later version | |
27 | # may be used, or where a choice of which version of the GPL is applied is | |
28 | # otherwise unspecified. | |
29 | # | |
30 | # Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
31 | # CA 95054 USA or visit www.sun.com if you need additional information or | |
32 | # have any questions. | |
33 | # | |
34 | # ========== Copyright Header End ============================================ | |
35 | # -*- perl -*- | |
36 | ||
37 | package Midas::MMU::TTEFormat; | |
38 | use strict; | |
39 | ||
40 | use TRELoad 'BitFieldTie'; | |
41 | use Tie::IxHash; | |
42 | ||
43 | require Exporter; | |
44 | ||
45 | our @ISA = qw(Exporter); | |
46 | our @EXPORT = qw( | |
47 | get_tte_field_hash | |
48 | get_union_tte_field_hash | |
49 | tte_hash_to_tsb_data | |
50 | tte_hash_to_tsb_tag | |
51 | parse_tsb_data | |
52 | is_good_format_for_mmu | |
53 | ||
54 | %TSB_TAG_FORMAT | |
55 | %TSB_DATA_FORMAT | |
56 | ); | |
57 | ||
58 | our %TSB_TAG_FORMAT; | |
59 | our %TSB_DATA_FORMAT; | |
60 | ||
61 | # BEGIN block, because these need to be defined when other modules | |
62 | # call get_union_tte_field hash inside a 'use fields' clause. | |
63 | BEGIN { | |
64 | ||
65 | our %TSB_TAG_FORMAT = | |
66 | ( | |
67 | ultra2 => | |
68 | { | |
69 | tagtarget => | |
70 | { | |
71 | G => { hi=>63, lo=>63 }, | |
72 | CONTEXT => { hi=>60, lo=>48 }, | |
73 | VA => { hi=>41, lo=> 0, src=>'63:22' }, | |
74 | }, | |
75 | tagaccess => | |
76 | { | |
77 | VA => { hi=>63, lo=>13, src=>'63:13' }, | |
78 | CONTEXT => { hi=>12, lo=> 0 }, | |
79 | }, | |
80 | }, | |
81 | ||
82 | niagara => | |
83 | { | |
84 | tagtarget => | |
85 | { | |
86 | CONTEXT => { hi=>60, lo=>48 }, | |
87 | VA => { hi=>41, lo=> 0, src=>'63:22' }, | |
88 | }, | |
89 | tagaccess => | |
90 | { | |
91 | VA => { hi=>63, lo=>13, src=>'63:13' }, | |
92 | CONTEXT => { hi=>12, lo=> 0 }, | |
93 | }, | |
94 | }, | |
95 | ||
96 | niagara2 => | |
97 | { | |
98 | tagtarget => | |
99 | { | |
100 | CONTEXT => { hi=>60, lo=>48 }, | |
101 | VA => { hi=>41, lo=> 0, src=>'63:22' }, | |
102 | }, | |
103 | tagaccess => | |
104 | { | |
105 | VA => { hi=>63, lo=>13, src=>'63:13' }, | |
106 | CONTEXT => { hi=>12, lo=> 0 }, | |
107 | }, | |
108 | }, | |
109 | X => | |
110 | { | |
111 | tagtarget => | |
112 | { | |
113 | CONTEXT => { hi=>60, lo=>48 }, | |
114 | VA => { hi=>41, lo=> 0, src=>'63:22' }, | |
115 | }, | |
116 | tagaccess => | |
117 | { | |
118 | VA => { hi=>63, lo=>13, src=>'63:13' }, | |
119 | CONTEXT => { hi=>12, lo=> 0 }, | |
120 | }, | |
121 | }, | |
122 | ||
123 | ||
124 | ); | |
125 | ||
126 | tie my %tsb_data_ultra2_sun4u, 'Tie::IxHash'; | |
127 | tie my %tsb_data_niagara_sun4u, 'Tie::IxHash'; | |
128 | tie my %tsb_data_niagara_sun4v, 'Tie::IxHash'; | |
129 | tie my %tsb_data_niagara2_sun4u, 'Tie::IxHash'; | |
130 | tie my %tsb_data_niagara2_sun4v, 'Tie::IxHash'; | |
131 | tie my %tsb_data_X_sun4v, 'Tie::IxHash'; | |
132 | ||
133 | %tsb_data_ultra2_sun4u = | |
134 | ( | |
135 | V => { hi=>63, lo=>63, default => 1, descr => "Valid bit, default=1" }, | |
136 | SIZE => { hi=>62, lo=>61, descr => "Encoded page size"}, | |
137 | NFO => { hi=>60, lo=>60, descr => "Non-Faulting Only" }, | |
138 | IE => { hi=>59, lo=>59, descr => "Invert Endianness" }, | |
139 | SOFT2=> { hi=>58, lo=>50, descr => "Software usable"}, | |
140 | DIAG => { hi=>49, lo=>41, descr => "Diagnostic"}, | |
141 | PA => { hi=>40, lo=>13, src=>'40:13', descr => "Physical Address"}, | |
142 | SOFT => { hi=>12, lo=> 7, descr => "Software usable" }, | |
143 | L => { hi=> 6, lo=> 6, descr => "Lock"}, | |
144 | CP => { hi=> 5, lo=> 5, | |
145 | descr => "Cacheable in phys. indexed cache"}, | |
146 | CV => { hi=> 4, lo=> 4, | |
147 | descr => "Cacheable in virt. indexed cache"}, | |
148 | E => { hi=> 3, lo=> 3, descr => "Side-effect"}, | |
149 | P => { hi=> 2, lo=> 2, descr => "Priviliged"}, | |
150 | W => { hi=> 1, lo=> 1, descr => "Writeable"}, | |
151 | G => { hi=> 0, lo=> 0, descr => "Global" }, | |
152 | ); | |
153 | ||
154 | %tsb_data_niagara_sun4u = | |
155 | ( | |
156 | V => { hi=>63, lo=>63, default => 1, descr => "Valid bit, default=1"}, | |
157 | SZL => { hi=>62, lo=>61, name=>'SIZE', src=>'1:0', | |
158 | descr => "Low bits of encoded page size" }, | |
159 | NFO => { hi=>60, lo=>60, descr => "Non-Faulting Only"}, | |
160 | IE => { hi=>59, lo=>59, descr => "Invert Endianness"}, | |
161 | SOFT2=> { hi=>58, lo=>49, descr => "Software usable"}, | |
162 | SZH => { hi=>48, lo=>48, name=>'SIZE', src=>'2', | |
163 | descr => "High bit of encoded page size" }, | |
164 | DIAG => { hi=>47, lo=>40, descr => "Diagnostic"}, | |
165 | PA => { hi=>39, lo=>13, src=>'39:13', descr => "Physical Address"}, | |
166 | SOFT => { hi=>12, lo=> 8, descr => "Software usable"}, | |
167 | RSVD0=> { hi=> 7, lo=> 7, descr => "Reserved"}, | |
168 | L => { hi=> 6, lo=> 6, descr => "Lock" }, | |
169 | CP => { hi=> 5, lo=> 5, | |
170 | descr => "Cacheable in phys. indexed cache"}, | |
171 | CV => { hi=> 4, lo=> 4, | |
172 | descr => "Cacheable in virt. indexed cache"}, | |
173 | E => { hi=> 3, lo=> 3, descr => "Side-effect"}, | |
174 | P => { hi=> 2, lo=> 2, descr => "Priviliged" }, | |
175 | W => { hi=> 1, lo=> 1, descr => "Writeable" }, | |
176 | RSVD1=> { hi=> 0, lo=> 0, aliases=>['G'], descr => "Reserved" }, | |
177 | ); | |
178 | ||
179 | %tsb_data_niagara_sun4v = | |
180 | ( | |
181 | V => { hi=>63, lo=>63, default => 1, descr => "Valid bit, default=1"}, | |
182 | NFO => { hi=>62, lo=>62, descr => "Non-Faulting Only" }, | |
183 | L => { hi=>61, lo=>61, descr => "Lock" }, | |
184 | SOFT => { hi=>60, lo=>40, descr => "Software usable"}, | |
185 | PA => { hi=>39, lo=>13, src=>'39:13', descr => "Physical Address"}, | |
186 | IE => { hi=>12, lo=>12, descr => "Invert Endianness"}, | |
187 | E => { hi=>11, lo=>11, descr => "Side-effect"}, | |
188 | CP => { hi=>10, lo=>10, | |
189 | descr => "Cacheable in phys. indexed cache"}, | |
190 | CV => { hi=> 9, lo=> 9, | |
191 | descr => "Cacheable in virt. indexed cache"}, | |
192 | P => { hi=> 8, lo=> 8, descr => "Priviliged" }, | |
193 | RSVD0=> { hi=> 7, lo=> 7, descr => "Reserved" }, | |
194 | W => { hi=> 6, lo=> 6, descr => "Writeable" }, | |
195 | SW1 => { hi=> 5, lo=> 5, descr => "Software usable" }, | |
196 | SW0 => { hi=> 4, lo=> 4, descr => "Software usable" }, | |
197 | RSVD1=> { hi=> 3, lo=> 3, descr => "Reserved" }, | |
198 | SIZE => { hi=> 2, lo=> 0, descr => "Encoded page size" }, | |
199 | ); | |
200 | ||
201 | %tsb_data_niagara2_sun4u = | |
202 | ( | |
203 | V => { hi=>63, lo=>63, default => 1, descr => "Valid bit, default=1"}, | |
204 | SZL => { hi=>62, lo=>61, name=>'SIZE', src=>'1:0', | |
205 | descr => "Low bits of encoded page size" }, | |
206 | NFO => { hi=>60, lo=>60, descr => "Non-Faulting Only"}, | |
207 | IE => { hi=>59, lo=>59, descr => "Invert Endianness"}, | |
208 | SOFT2=> { hi=>58, lo=>49, descr => "Software usable"}, | |
209 | SZH => { hi=>48, lo=>48, name=>'SIZE', src=>'2', | |
210 | descr => "High bit of encoded page size" }, | |
211 | DIAG => { hi=>47, lo=>40, descr => "Diagnostic" }, | |
212 | PA => { hi=>39, lo=>13, src=>'39:13', descr => "Physical Address"}, | |
213 | SOFT => { hi=>12, lo=> 8, descr => "Software usable"}, | |
214 | EP => { hi=> 7, lo=> 7, aliases=>['X'], | |
215 | descr => "Executable (also TTE_X)"}, | |
216 | L => { hi=> 6, lo=> 6, descr => "Lock" }, | |
217 | CP => { hi=> 5, lo=> 5, | |
218 | descr => "Cacheable in phys. indexed cache"}, | |
219 | CV => { hi=> 4, lo=> 4, | |
220 | descr => "Cacheable in virt. indexed cache"}, | |
221 | E => { hi=> 3, lo=> 3, descr => "Side-effect"}, | |
222 | P => { hi=> 2, lo=> 2, descr => "Priviliged" }, | |
223 | W => { hi=> 1, lo=> 1, descr => "Writeable" }, | |
224 | RSVD1=> { hi=> 0, lo=> 0, aliases=>['G'], descr => "Reserved" }, | |
225 | ); | |
226 | ||
227 | %tsb_data_niagara2_sun4v = | |
228 | ( | |
229 | V => { hi=>63, lo=>63, default => 1, descr => "Valid bit, default=1"}, | |
230 | NFO => { hi=>62, lo=>62, descr => "Non-Faulting Only" }, | |
231 | L => { hi=>61, lo=>61, descr => "Lock"}, | |
232 | SOFT => { hi=>60, lo=>40, descr => "Software usable"}, | |
233 | PA => { hi=>39, lo=>13, src=>'39:13', descr => "Physical Address"}, | |
234 | IE => { hi=>12, lo=>12, descr => "Invert Endianness"}, | |
235 | E => { hi=>11, lo=>11, descr => "Side-effect"}, | |
236 | CP => { hi=>10, lo=>10, | |
237 | descr => "Cacheable in phys. indexed cache"}, | |
238 | CV => { hi=> 9, lo=> 9, | |
239 | descr => "Cacheable in virt. indexed cache"}, | |
240 | P => { hi=> 8, lo=> 8, descr => "Priviliged"}, | |
241 | EP => { hi=> 7, lo=> 7, aliases=>['X'], | |
242 | descr => "Executable (also TTE_X)"}, | |
243 | W => { hi=> 6, lo=> 6, descr => "Writeable" }, | |
244 | SW1 => { hi=> 5, lo=> 5, descr => "Software usable"}, | |
245 | SW0 => { hi=> 4, lo=> 4, descr => "Software usable"}, | |
246 | RSVD1=> { hi=> 3, lo=> 3, descr => "Reserved" }, | |
247 | SIZE => { hi=> 2, lo=> 0, descr => "Encoded page size"}, | |
248 | ); | |
249 | ||
250 | %tsb_data_X_sun4v = | |
251 | ( | |
252 | V => { hi=>63, lo=>63, default => 1, descr => "Valid bit, default=1"}, | |
253 | NFO => { hi=>62, lo=>62, descr => "Non-Faulting Only" }, | |
254 | SW1 => { hi=>61, lo=>47, descr => "Software usable"}, | |
255 | PA => { hi=>46, lo=>13, src=>'46:13', descr => "Physical Address"}, | |
256 | IE => { hi=>12, lo=>12, descr => "Invert Endianness" }, | |
257 | E => { hi=>11, lo=>11, descr => "Side-effect"}, | |
258 | CP => { hi=>10, lo=>10, | |
259 | descr => "Cacheable in phys. indexed cache"}, | |
260 | CV => { hi=> 9, lo=> 9, | |
261 | descr => "Cacheable in virt. indexed cache"}, | |
262 | P => { hi=> 8, lo=> 8, descr => "Priviliged" }, | |
263 | X => { hi=> 7, lo=> 7, aliases=>['EP'], | |
264 | descr => "Executable (also TTE_EP)" }, | |
265 | W => { hi=> 6, lo=> 6, descr => "Writeable" }, | |
266 | R => { hi=> 5, lo=> 5, descr => "Readable" }, | |
267 | SW0 => { hi=> 4, lo=> 4, descr => "Software usable"}, | |
268 | RSVD0=> { hi=> 3, lo=> 3, descr => "Reserved"}, | |
269 | SIZE => { hi=> 2, lo=> 0, descr => "Encoded page size" }, | |
270 | ); | |
271 | ||
272 | our %TSB_DATA_FORMAT = | |
273 | ( | |
274 | ||
275 | ultra2 => { | |
276 | sun4u => \%tsb_data_ultra2_sun4u, | |
277 | }, | |
278 | niagara => { | |
279 | sun4u => \%tsb_data_niagara_sun4u, | |
280 | sun4v => \%tsb_data_niagara_sun4v, | |
281 | }, | |
282 | ||
283 | niagara2 => { | |
284 | sun4u => \%tsb_data_niagara2_sun4u, | |
285 | sun4v => \%tsb_data_niagara2_sun4v, | |
286 | }, | |
287 | ||
288 | ||
289 | X => { | |
290 | sun4v => \%tsb_data_X_sun4v, | |
291 | }, | |
292 | ||
293 | ); | |
294 | } | |
295 | ||
296 | ############################################################################## | |
297 | ||
298 | sub get_tte_field_hash { | |
299 | my $mmu_type = shift; | |
300 | my $ttefmt = shift; | |
301 | my $tsbtagfmt = shift; | |
302 | ||
303 | my %fields; | |
304 | foreach my $field (keys %{$TSB_DATA_FORMAT{$mmu_type}{$ttefmt}}) { | |
305 | my $descr = $TSB_DATA_FORMAT{$mmu_type}{$ttefmt}{$field}; | |
306 | my $size = $descr->{hi} - $descr->{lo} + 1; | |
307 | my $name = (exists $descr->{name}) ? $descr->{name} : $field; | |
308 | ||
309 | my @names = ($name); | |
310 | push @names, @{ $descr->{aliases} } if exists $descr->{aliases}; | |
311 | ||
312 | foreach my $n (@names) { | |
313 | my $tte_n = lc('tte_' . $n); | |
314 | ||
315 | $fields{$tte_n} = 0 unless exists $fields{$tte_n}; | |
316 | $fields{$tte_n} += $size; | |
317 | } | |
318 | } | |
319 | ||
320 | foreach my $field (keys %{$TSB_TAG_FORMAT{$mmu_type}{$tsbtagfmt}}) { | |
321 | my $descr = $TSB_TAG_FORMAT{$mmu_type}{$tsbtagfmt}{$field}; | |
322 | my $size = $descr->{hi} - $descr->{lo} + 1; | |
323 | my $name = (exists $descr->{name}) ? $descr->{name} : $field; | |
324 | ||
325 | my @names = ($name); | |
326 | push @names, @{ $descr->{aliases} } if exists $descr->{aliases}; | |
327 | ||
328 | foreach my $n (@names) { | |
329 | my $tte_n = lc('tte_' . $n); | |
330 | ||
331 | $fields{$tte_n} = 0 unless exists $fields{$tte_n}; | |
332 | if($tte_n eq 'tte_g') { | |
333 | $fields{$tte_n} = $size; | |
334 | } else { | |
335 | $fields{$tte_n} += $size; | |
336 | } | |
337 | } | |
338 | } | |
339 | ||
340 | delete $fields{tte_va} if exists $fields{tte_va}; | |
341 | delete $fields{tte_ra} if exists $fields{tte_ra}; | |
342 | delete $fields{tte_pa} if exists $fields{tte_pa}; | |
343 | ||
344 | ||
345 | return \%fields; | |
346 | } | |
347 | ||
348 | ############################################################################## | |
349 | ||
350 | sub get_union_tte_field_hash { | |
351 | my $mmu_type = shift; | |
352 | ||
353 | my %fields; | |
354 | foreach my $ttefmt (keys %{ $TSB_DATA_FORMAT{$mmu_type} }) { | |
355 | foreach my $tsbtagfmt (keys %{ $TSB_TAG_FORMAT{$mmu_type} } ) { | |
356 | my $fieldHash = get_tte_field_hash($mmu_type, $ttefmt, $tsbtagfmt); | |
357 | foreach my $field (keys %$fieldHash) { | |
358 | $fields{$field} = 0 unless defined $fields{$field}; | |
359 | $fields{$field} = ($fields{$field} > $fieldHash->{$field}) ? | |
360 | $fields{$field} : $fieldHash->{$field}; | |
361 | } | |
362 | } | |
363 | } | |
364 | ||
365 | return \%fields; | |
366 | } | |
367 | ||
368 | ############################################################################## | |
369 | ||
370 | sub tte_hash_to_tsb_data { | |
371 | my $mmutype = shift; | |
372 | my $ttefmt = shift; | |
373 | my $ttehash = shift; | |
374 | my $addr = shift; | |
375 | ||
376 | $addr = '0' unless defined $addr; | |
377 | ||
378 | my $pa = BitFieldTie->new(64, $addr); | |
379 | my $data = BitFieldTie->new(64, 0); | |
380 | my $size = (exists $ttehash->{tte_size}) ? | |
381 | BitFieldTie->new(64, $ttehash->{tte_size}) : undef; | |
382 | ||
383 | tie my %data, 'BitFieldTie', $data; | |
384 | tie my %pa, 'BitFieldTie', $pa; | |
385 | tie my %size, 'BitFieldTie', $size; | |
386 | ||
387 | foreach my $field (keys %{ $TSB_DATA_FORMAT{$mmutype}{$ttefmt} }) { | |
388 | my $descr = $TSB_DATA_FORMAT{$mmutype}{$ttefmt}{$field}; | |
389 | my $name = (exists $descr->{name}) ? $descr->{name} : $field; | |
390 | ||
391 | my @names = ($name); | |
392 | push @names, @{ $descr->{aliases} } if exists $descr->{aliases}; | |
393 | ||
394 | my $def_value = (defined $descr->{default}) ? $descr->{default} : 0; | |
395 | my $value; | |
396 | my $set_already = 0; | |
397 | if($name eq 'PA' or $name eq 'SIZE') { | |
398 | my $bits = (exists $descr->{src}) ? $descr->{src} : '31:0'; | |
399 | if($name eq 'PA') { | |
400 | if($bits =~ /^(\d+):(\d+)$/) { | |
401 | my ($hi, $lo) = ($1, $2); | |
402 | my $dist = $hi - $lo + 1; | |
403 | if($dist > 32) { | |
404 | my $mid_hi = $hi-31; | |
405 | my $mid_lo = $mid_hi-1; | |
406 | ||
407 | my $descr_mid_hi = $descr->{hi} - 31; | |
408 | my $descr_mid_lo = $descr_mid_hi - 1; | |
409 | ||
410 | $data{"$descr->{hi}:$descr_mid_hi"} = | |
411 | $pa{"${hi}:$mid_hi"}; | |
412 | ||
413 | $data{"${descr_mid_lo}:$descr->{lo}"} = | |
414 | $pa{"${mid_lo}:$lo"}; | |
415 | ||
416 | $set_already = 1; | |
417 | } else { | |
418 | $value = $pa{$bits}; | |
419 | } | |
420 | } else { | |
421 | $value = $pa{$bits}; | |
422 | } | |
423 | } elsif($name eq 'SIZE') { | |
424 | $value = $size{$bits}; | |
425 | } | |
426 | } else { | |
427 | my $found = 0; | |
428 | foreach my $n (@names) { | |
429 | my $tte_n = lc('tte_' . $n); | |
430 | if(exists $ttehash->{$tte_n}) { | |
431 | $value ||= $ttehash->{$tte_n}; | |
432 | $found = 1; | |
433 | } | |
434 | } | |
435 | $value = $def_value unless $found; | |
436 | } | |
437 | ||
438 | $data{"$descr->{hi}" . ':' . "$descr->{lo}"} = $value | |
439 | unless $set_already; | |
440 | ||
441 | } | |
442 | return $data->stringify(); | |
443 | } | |
444 | ||
445 | ############################################################################## | |
446 | ||
447 | sub tte_hash_to_tsb_tag { | |
448 | my $mmutype = shift; | |
449 | my $tsbtagfmt = shift; | |
450 | my $ttehash = shift; | |
451 | my $addr = shift; | |
452 | my $force_ctx_zero = shift; | |
453 | ||
454 | $addr = '0' unless defined $addr; | |
455 | $force_ctx_zero = 0 unless defined $force_ctx_zero; | |
456 | ||
457 | my $va = BitFieldTie->new(64, $addr); | |
458 | my $tag = BitFieldTie->new(64, 0); | |
459 | ||
460 | tie my %tag, 'BitFieldTie', $tag; | |
461 | tie my %va, 'BitFieldTie', $va; | |
462 | ||
463 | foreach my $field (keys %{ $TSB_TAG_FORMAT{$mmutype}{$tsbtagfmt} }) { | |
464 | my $descr = $TSB_TAG_FORMAT{$mmutype}{$tsbtagfmt}{$field}; | |
465 | my $name = (exists $descr->{name}) ? $descr->{name} : $field; | |
466 | ||
467 | my @names = ($name); | |
468 | push @names, @{ $descr->{aliases} } if exists $descr->{aliases}; | |
469 | ||
470 | my $value = (defined $descr->{default}) ? $descr->{default} : 0; | |
471 | if( $name eq 'VA') { | |
472 | my $bits = (exists $descr->{src}) ? $descr->{src} : '31:0'; | |
473 | ||
474 | my $hi = $descr->{hi}; | |
475 | my $lo = $descr->{lo}; | |
476 | my $dist = ($hi-$lo+1); | |
477 | if($dist >= 32) { | |
478 | my $cut = $hi-31; | |
479 | if($bits =~ /(\d+)\:(\d+)/) { | |
480 | my ($bitsHi, $bitsLo) = ($1, $2); | |
481 | my $bitsCut = $bitsHi-31; | |
482 | $tag{"${hi}:${cut}"} = $va{"${bitsHi}:${bitsCut}"}; | |
483 | $cut--; $bitsCut--; | |
484 | $tag{"${cut}:${lo}"} = $va{"${bitsCut}:${bitsLo}"}; | |
485 | } | |
486 | } else { | |
487 | $tag{"${hi}:${lo}"} = $va{$bits}; | |
488 | } | |
489 | ||
490 | ||
491 | } else { | |
492 | foreach my $n (@names) { | |
493 | my $tte_n = lc('tte_' . $n); | |
494 | if(exists $ttehash->{$tte_n}) { | |
495 | $value ||= $ttehash->{$tte_n}; | |
496 | } | |
497 | if($tte_n eq 'tte_context' and $force_ctx_zero) { | |
498 | $value = 0; | |
499 | } | |
500 | } | |
501 | ||
502 | $tag{"$descr->{hi}" . ':' . "$descr->{lo}"} = $value; | |
503 | } | |
504 | ||
505 | ||
506 | } | |
507 | return $tag->stringify(); | |
508 | } | |
509 | ||
510 | ############################################################################## | |
511 | ||
512 | sub parse_tsb_data { | |
513 | my $mmutype = shift; | |
514 | my $ttefmt = shift; | |
515 | my $tte_data = shift; | |
516 | ||
517 | tie my %parsed, 'Tie::IxHash'; | |
518 | ||
519 | my $data = BitFieldTie->new(64, $tte_data); | |
520 | tie my %data, 'BitFieldTie', $data; | |
521 | ||
522 | my $types = $TSB_DATA_FORMAT{$mmutype}{$ttefmt}; | |
523 | foreach my $field (sort { $types->{$b}{hi} <=> $types->{$a}{hi}} | |
524 | keys %$types) | |
525 | { | |
526 | my $descr = $types->{$field}; | |
527 | my $value = $data{"$descr->{hi}" . ':' . "$descr->{lo}"}; | |
528 | my $name = (exists $descr->{name}) ? $descr->{name} : $field; | |
529 | ||
530 | $parsed{$name} = 0 unless defined $parsed{$name}; | |
531 | if(exists $descr->{src}) { | |
532 | my $v = BitFieldTie->new(64, 0); | |
533 | tie my %v, 'BitFieldTie', $v; | |
534 | $v{$descr->{src}} = $value; | |
535 | $value = $v->extract(31,0); | |
536 | } | |
537 | $parsed{$name} |= $value; | |
538 | ||
539 | } | |
540 | ||
541 | return \%parsed; | |
542 | } | |
543 | ||
544 | ############################################################################## | |
545 | ||
546 | sub is_good_format_for_mmu { | |
547 | my $mmutype = shift; | |
548 | my $ttefmt = shift; | |
549 | return 1 if exists $TSB_DATA_FORMAT{$mmutype}{$ttefmt}; | |
550 | return; | |
551 | } | |
552 | ||
553 | ############################################################################## | |
554 | 1; |