##// END OF EJS Templates
Added b2bst scan script....
jeandet -
r372:c3bc6f763f5f R3++ draft
parent child
Show More
This diff has been collapsed as it changes many lines, (681 lines changed) Show them Hide them
@@ -0,0 +1,681
1 #! /usr/bin/tclsh
2 #
3 # TCL script to scan disassembled programs against the "LEON3FT Stale Cache
4 # Entry After Store with Data Tag Parity Error" errata, GRLIB-TN-0009.
5 #
6 # The following Cobham components are affected by GRLIB-TN-0009:
7 # - GR712RC
8 # - LEON3FT-RTAX (all versions)
9 # - UT699
10 # - UT699E
11 # - UT700
12 #
13 # For information on how custom LEON3 systems may be affected, see
14 # GRLIB-TN-0009.
15 #
16 # Copyright (C) 2016, Cobham Gaisler
17 #
18 # Usage: sparc-elf-objdump -d program | leon3ft-b2bst-scan.tcl
19 #
20 # Command line parameters:
21 # -nonote: Do not print NOTE messages.
22 # -noinfo: Do not print INFO messages.
23 # -silent: Do not print NOTE or INFO messages.
24 #
25 # Return values:
26 # 0: No potential error locations found.
27 # 1: At least one potential error location found.
28 #
29 # Rev. history:
30 # rev 1, MH, Initial revision, based on ut699scan.tcl. Add scanning for
31 # store-store errata, reorganize comments
32 # rev 2, MA, Restruction and clean-up, fixed Sequence B.
33 # rev 3, MA, Added decoding of casa instruction, exit status and verbosity
34 # parameters.
35 # rev 4, MA, Reduced false warnings due to Store into Alternate space
36 # instructions which can not trig the errata. Script renamed to
37 # leon3ft-b2bst-scan.tcl.
38 #
39 # Note 1: Two modes are available with respect to call/ret (dslot_mode):
40 # 1) ret, and call are assumed not to have stores in their delay slots.
41 # The tool will warn if any such operations are found in the delay
42 # slot of ret,call during the scan
43 # 0) ret and call may have stores in their delay slots
44 # The tool will not warn if any such operations are found in the
45 # delay slot during the scan. Instead it will assume this
46 # possibility exists when evaluating insns following a function call
47 #
48
49 ### CONFIGURATION
50 set b2bst_seqa_scan 1; # enable/disable scanning for Sequence A
51 set b2bst_seqb_scan 1; # enable/disable scanning for Sequence B
52 # set dslot_mode 0; # assume store can be in delay slot of call,jmpl
53 set dslot_mode 1; # do not allow store in delay slot of call,jmpl
54 ###
55
56 # Mask values for types of output messages
57 set MSG_INFO 1; # Information on things to check manually.
58 set MSG_NOTE 2; # Notices on branch following
59 set msglevel [expr {$MSG_INFO | $MSG_NOTE}]
60
61 set errata_desc "LEON3FT Stale Cache Entry After Store with Data Tag Parity Error"
62 set util_rev 4
63 set util_date "20170215"
64
65 set b2bst_seqa_desc "Sequence A"
66 set b2bst_seqb_desc "Sequence B"
67
68 set op_count 0
69 set lineskip_count 0
70 set line_count 0
71 set err_count 0
72 set fn_count 0
73 set fninst_count 0
74
75 proc puts_info {str} {
76 global msglevel MSG_INFO
77 if {$msglevel & $MSG_INFO} { puts "INFO: $str" }
78 }
79
80 proc puts_note {str} {
81 global msglevel MSG_NOTE
82 if {$msglevel & $MSG_NOTE} { puts "NOTE: $str" }
83 }
84
85 # ----------------------------------------------------------------------------
86 # Routine that decodes specified opcode and returns list of
87 # 0 :optype Class of opcode
88 # one of call,jmpl,branch,sethi,ld,st,atomic,alu,fpop,save,restore
89 # 1 :target-reg Register modified by op
90 # 2 :source-reg1 First source register (rs1)
91 # 3 :source-reg2 Second source register (rs2)
92 # 4 :store-reg Source register for store data
93 # regs are numbered 0-31 integer regs, 32-63 FP regs
94 # 5 :double-flag
95 # ORed mask: 8) target-reg is DP, 4) sreg1 is DP, 2) sreg2 is DP, 1) store-reg is DP
96 # 6 :immed Immediate operand
97 # 7 :nnpc1 Next instructions nPC if branch not taken (normal case), normally nPC+4
98 # 8 :nnpc2 Next instruction's nPC if branch is taken, if not branch then nnpc2=nnpc1
99 # 9 :annul
100 # ORed mask: next inst annulled if 2) branch not taken 1) branch taken
101 # 10:bubbles Number of extra cycles spent in decode stage (bubbles inserted)
102 proc decode_inst { opcode {pc "0x00000000"} {npc "0x00000004"}} {
103 # Some "sta" instructions do not trig the errata. The related ASI:s are
104 # defined here.
105 set safeasi [list 0x02 0x03 0x04 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x13 0x14 0x15 0x18 0x19 0x1c 0x1d 0x1e]
106 #Default values if no cond matches
107 set opname "unknown"
108 set destreg 0
109 set sreg1 0
110 set sreg2 0
111 set streg 0
112 set dblflag 0
113 set immed 0
114
115 if { [string is integer $npc] } {
116 set nnpc1 [format "0x%08x" [ expr {$npc+4} ] ]
117 } else {
118 set nnpc1 "$npc+4"
119 }
120 set nnpc2 $nnpc1
121 set annul 0
122 set bubbles 0
123 #Decode
124 set op1 [ expr {$opcode >> 30} ]
125 if { $op1 == 1 } {
126 set opname "call"
127 set disp [ expr { ($opcode & 0x3fffffff)<<2 } ]
128 set nnpc1 [ format "0x%08x" [ expr { $pc + $disp } ] ]
129 set nnpc2 $nnpc1
130 } elseif { $op1 == 0 } {
131 set op2 [ expr {($opcode >> 22) & 7} ]
132 # NOTE: 2=Bicc, 6=FBcc, 7=CBcc
133 if { $op2 == 2 || $op2 == 6 } {
134 set opname "branch"
135 set disp [expr { ($opcode & 0x3fffff) << 2 } ]
136 if { $disp > 0x800000 } { set disp [expr {$disp - 0x1000000}] }
137 # Todo check cond,annul, handle always or never
138 set nnpc2 [ format "0x%08x" [ expr { $pc + $disp } ] ]
139 set cond [ expr { ($opcode >> 25) & 15 } ]
140 set annulbit [ expr { $opcode & 0x20000000 } ]
141 if { $cond == 0 } { # Branch never
142 set nnpc2 $nnpc1
143 if { $annulbit } { set annul 3 }
144 } elseif { $cond == 8 } { # Branch always
145 set nnpc1 $nnpc2
146 if { $annulbit } { set annul 3 }
147 } else { # True cond branch
148 if { $annulbit } { set annul 2 }
149 }
150 } elseif { $op2 == 4 } {
151 set opname "sethi"
152 set destreg [ expr { ($opcode >> 25) & 31 } ]
153 set immed [ expr { ($opcode & 0x3fffff) << 10 } ]
154 }
155 } elseif { $op1 == 3 } {
156 # SPARC V8 Table F-4
157 # set opname "mem" - changed to use ld/st/atomic instead
158 set op3 [ expr { ($opcode >> 19) & 63 } ]
159 set rs1 [ expr { (($opcode >> 14) & 31) } ]
160 set rs2 [ expr { (($opcode ) & 31) } ]
161 set rd [ expr { (($opcode >> 25) & 31) } ]
162 set sreg1 $rs1
163 if { $opcode & 0x2000 } {
164 set immed [ expr { $opcode & 0x1fff } ]
165 if { $immed > 0xfff } { set immed [ expr { $immed-(0x2000) } ] }
166 } else {
167 set sreg2 $rs2
168 }
169 if { (($op3 & 13) == 13) || ($op3 == 0x3c) } {
170 # Atomic ldst/swap/casa
171 set opname "atomic"
172 set destreg $rd
173 set streg $rd
174 } else {
175 # Adjust reg no if FP ld/st (op3[5]=1)
176 if { ($op3 & 0x20) != 0 } { set rd [expr {32 + $rd} ] }
177 # Check if read or write op3[2]
178 if { ($op3 & 4) != 0 } {
179 set opname "st"
180 set streg $rd
181 set allow_safe_sta true
182 if { $allow_safe_sta && (($op3 & 0x3c) == 0x14) } {
183 # op3 is 0x14, 0x15, 0x16 or 0x17 (sta, stba, stha or stda)
184 # (if i = 0)
185 set asi [expr { (($opcode >> 5) & 0xff) }]
186 set safematch [lsearch -exact -integer $safeasi $asi]
187 if {0 <= $safematch} {
188 set opname "sta_safe"
189 }
190 }
191 } else {
192 set opname "ld"
193 set destreg $rd
194 }
195 # Check size op3[1:0]
196 if { ($op3 & 3) == 3 } {
197 if { $opname eq "st" } { set dblflag 1 } else { set dblflag 8 }
198 }
199 }
200 } else {
201 set op3 [ expr { ($opcode >> 19) & 63 } ]
202 if { $op3 == 0x34 || $op3 == 0x35 } {
203 set opname "fpop"
204 set opf [ expr { ($opcode >> 5) & 0x1ff } ]
205 set rs1 [ expr { 32 + (($opcode >> 14) & 31) } ]
206 set rs2 [ expr { 32 + (($opcode ) & 31) } ]
207 set rd [ expr { 32 + (($opcode >> 25) & 31) } ]
208 # opf[1:0] corresponds to operand size of rs2
209 # opf[7:6]=11 is conv op, opf[3:2] gives opsize of rd, rs1 unused
210 # opf[7:6]=00 is single-operand op, rd same size as rs2, rs1 unused
211 # opf[7:4]=0100 regular op, rs1,rd same size as rs2
212 # opf[7:4]=0101 comp op, rd unused, rs1 same size as rs2
213 # opf[7:4]=0110 conv+mul, opf[3:2] gives opsize of rd, rs1 same size as rs2
214 set sreg2 $rs2
215 if { ($opf & 3) > 1 } { set dblflag 2 }
216 if { ($opf & 0xc0) == 0x40 } {
217 set sreg1 $rs1
218 if { $dblflag & 2 } { set dblflag [ expr { $dblflag | 4 } ] }
219 }
220 if { ($opf & 0xc0) == 0xc0 || ($opf & 0xf0) == 0x60 } {
221 set destreg $rd
222 if { ($opf & 0xc) > 4 } { set dblflag [ expr { $dblflag | 8 } ] }
223 } elseif { ($opf & 0xf0) != 0x50 } {
224 set destreg $rd
225 if { $dblflag & 2 } { set dblflag [ expr { $dblflag | 8 } ] }
226 }
227 } else {
228 set opname "alu"
229 set destreg [ expr { (($opcode >> 25) & 31) } ]
230 set sreg1 [ expr { (($opcode >> 14) & 31) } ]
231 if { $opcode & 0x2000 } {
232 set immed [ expr { $opcode & 0x1fff } ]
233 if { $immed > 0xfff } { set immed [ expr { $immed-(0x2000) } ] }
234 } else {
235 set sreg2 [ expr { (($opcode ) & 31) } ]
236 }
237 if { $op3 == 0x38 } {
238 set opname "jmpl"
239 set nnpc1 "jmpaddr"
240 set nnpc2 "jmpaddr"
241 set bubbles 2
242 } elseif { $op3 == 0x3c } {
243 set opname "save"
244 } elseif { $op3 == 0x3d } {
245 set opname "restore"
246 }
247 }
248 }
249 #Return values
250 return [list $opname $destreg $sreg1 $sreg2 $streg $dblflag $immed $nnpc1 $nnpc2 $annul $bubbles]
251 }
252
253 proc is_store { opcode } {
254 set op1 [ expr { ($opcode >> 30) } ]
255 set op3 [ expr { ($opcode >> 19) & 63 } ]
256 return [expr {($op1 == 3) && (($op3 & 0xc) == 0x4)}]
257 }
258
259 # -------------------------------------------------------------------------------------
260
261 proc unpack { l args } {
262 for { set i 0 } { $i < [llength $args] } { incr i } {
263 uplevel 1 "set [lindex $args $i] [lindex $l $i]"
264 }
265 }
266
267 # --------- Postprocessing on whole function
268
269 # Number of instructions printed is starti + 2
270 proc print_trace { fnpc state fnarr seqstart {starti 4}} {
271 upvar $fnarr fnops
272
273 puts " # PC Opcode"
274 set cnt [expr {$seqstart-$starti}]
275 for { set x $starti } { $x > -2 } { set x [expr {$x-1}] } {
276 incr cnt
277 if { $cnt > 0 } { set cntv $cnt } else { set cntv " " }
278 if { $x >= 0 } { set pc [lindex $state $x] } else { set pc $fnpc }
279 if { $pc eq "?" || $pc eq "call" || $pc eq "ret" || $pc eq "dslot" } {
280 puts " $cntv (other fn) $pc"
281 } else {
282 if { [string index $pc 0] eq "A" } {
283 set pc [string range $pc 1 end]
284 set annul " (annulled)"
285 } else {
286 set annul ""
287 }
288 if { [info exists fnops($pc)] } {
289 set op $fnops($pc)
290 } else {
291 set op [list "0x???????? (outside func)"]
292 }
293 puts " $cntv $pc [join $op] $annul"
294 }
295 }
296 puts ""
297 }
298
299 # Routine called by scan_wholefunc_main to check
300 # instruction sequences described in GRLIB-TN-009, Issue 1.0
301 #
302 # "Sequence A"
303 # 1. store of word size or less (st / stb / sth / stf)
304 # 2. any single instruction that is not a load or store
305 # 3. any store instruction (st / stb / sth / stf / std / stdf)
306 #
307 # "Sequence B"
308 # 1. store of double word size (std / stdf)
309 # 2. any store instruction (st / stb / sth / stf / std / stdf)
310 proc scan_b2bst { fnname fnpc fnop opdec fnarr state } {
311 global b2bst_seqa_scan
312 global b2bst_seqb_scan
313 upvar $fnarr fnops
314 global dslot_mode
315
316 # Check latest 3 insn if they can be st/std/regular
317 set pca [list $fnpc [lindex $state 0] [lindex $state 1]]
318 set can_be_arr [list]
319 for { set i 0 } { $i < 3 } { incr i } {
320 set can_be [list 0 0 0] ; # st std regular
321 set pcv [lindex $pca $i]
322 if { $pcv eq "?" } {
323 set can_be [list 1 1 1]
324 } elseif { $pcv eq "dslot" } {
325 set can_be [list [expr {1-$dslot_mode}] [expr {1-$dslot_mode}] 1]
326 } elseif { [string index $pcv 0] eq "A" || $pcv eq "call" || $pcv eq "ret" } {
327 set can_be [list 0 0 1]
328 } else {
329 set op $fnops($pcv)
330 set ophex [lindex $op 0]
331 set opdec [decode_inst $ophex]
332 set optype [lindex $opdec 0]
333 set opstorereg [lindex $opdec 4]
334 set opdblflag [lindex $opdec 5]
335 if { $optype eq "st" && ($opdblflag & 1) } {
336 set can_be [list 0 1 0]
337 } elseif { $optype eq "st" } {
338 set can_be [list 1 0 0]
339 } elseif { $optype ne "ld" && $optype ne "atomic" } {
340 # Any single instruction that is not a load or store
341 set can_be [list 0 0 1]
342 }
343 }
344 lappend can_be_arr $can_be
345 }
346 # can_be_arr has at index
347 # - at index 2: previous previous instruction
348 # - at index 1: previous instruction
349 # - at index 0: current instruction
350 set pp_insn [lindex $can_be_arr 2]
351 set p_insn [lindex $can_be_arr 1]
352 set c_insn [lindex $can_be_arr 0]
353 # Sequence A
354 # 1. store of word size or less
355 # 2. any single instruction that is not a load or store
356 # 3. any store instruction
357 if {
358 (
359 $b2bst_seqa_scan &&
360 [lindex $pp_insn 0] &&
361 [lindex $p_insn 2] &&
362 ([lindex $c_insn 0] || [lindex $c_insn 1])
363 ) } {
364 puts "WARNING: Possible sequence matching LEON3FT b2bst errata (sequence A) in function $fnname"
365 print_trace $fnpc $state fnops 1
366 puts ""
367 return 1
368 }
369
370 # Sequence B
371 # 1. any store instruction
372 # 2. store of double word size
373 if {
374 (
375 $b2bst_seqb_scan &&
376 [lindex $p_insn 1] &&
377 ([lindex $c_insn 0] || [lindex $c_insn 1])
378 ) } {
379 puts "WARNING: Possible sequence matching LEON3FT b2bst errata (sequence B) in function $fnname"
380 print_trace $fnpc $state fnops 0
381 puts ""
382 return 1
383 }
384 return 0
385 }
386
387
388 # Main recursive function doing scan
389 # fnname - funcion name
390 # fnpc, fnnpc, PC/nPC of current insn (8-digit hex, 0x prefix) prefix also with A if annulled,
391 # fnarr - array/hash-table, see descr for scan_wholefunc
392 # dpdist - number of SP FPOPs done minimum since last DP FPOP
393 # state - List of 5 last instruction addresses (hex w 0x prefix), special values "?"=unknown "call"=call from calling proc
394 # smap - Hash table used to track where we have been already
395 proc scan_wholefunc_main { fnname fnpc fnnpc fnarr savelevel dpdist state smap lastoptype } {
396 global dslot_mode
397 upvar $fnarr fnops
398 upvar $smap statemap
399
400 set r 0
401
402 # puts "entering scan_wholefunc_main: PC:$fnpc nPC:$fnnpc dpdist:$dpdist savelevel:$savelevel state:$state"
403 # puts "fnops exists [info exists fnops] [array exists fnops] [array names fnops]"
404 while {1} {
405 # puts "scan_wholefunc_main: PC:$fnpc nPC:$fnnpc dpdist:$dpdist savelevel:$savelevel state:$state"
406 set statedesc [list $fnpc $fnnpc $savelevel $dpdist $state]
407 if { [info exists statemap($statedesc)] } {
408 # Already been here
409 return $r
410 }
411 set statemap($statedesc) 1
412
413 set fnpca $fnpc
414 set pcannul 0
415 if { [string index $fnpc 0] eq "A" } {
416 set pcannul 1
417 set fnpc [string range $fnpc 1 end]
418 set ophex "0x01000000"
419 } else {
420 if {![info exists fnops($fnpc)]} {
421 puts_note "$fnname: Execution leaves function without return";
422 return $r
423 }
424
425 set op $fnops($fnpc)
426 set ophex [lindex $op 0]
427 set opname [lindex $op 1]
428 }
429
430 set opdec [ decode_inst $ophex $fnpc $fnnpc ]
431 unpack $opdec optype treg sreg1 sreg2 streg dblflag immed nnpc1 nnpc2 annul bubbles
432
433 set prev_savelevel $savelevel
434 if { $optype eq "fpop" } {
435 # update dpdist
436 if { ($dblflag & 6) == 0 } {
437 if { $dpdist < 2 } { incr dpdist }
438 } else {
439 set dpdist 0
440 }
441 } elseif { $optype eq "save" } {
442 if { $savelevel > 9 } {
443 puts_note "$fnname: More than 10 deep saves (possibly regfile clear loop)"
444 } else {
445 incr savelevel
446 }
447 # puts "save at $fnpc, new savelevel: $savelevel"
448 } elseif { $optype eq "restore" } {
449 if { $savelevel < -9 } {
450 puts_note "$fnname: More than 10 deep restores (possibly regfile clear loop)"
451 } else {
452 if { $savelevel == 0 } {
453 puts_note "$fnname: More restore than save instructions"
454 }
455 set savelevel [ expr { $savelevel-1} ]
456 }
457 # puts "restore at $fnpc, new savelevel: $savelevel"
458 }
459 if { true && ($optype eq "st") } {
460 if { [scan_b2bst $fnname $fnpc $op $opdec fnops $state] } { incr r }
461 }
462
463 # Handle jmpl and call
464 # If in delay slot of jmpl:
465 # If ret or retl, stop recursing further
466 # If other jmpl, check savelevel if it will return or not
467 # If in delay slot of call, set dpdist to 0 (called proc may have done DP operation)
468 set is_call 0
469 if {
470 (
471 $dslot_mode != 0 &&
472 ($lastoptype eq "branch" || $lastoptype eq "jmpl" || $lastoptype eq "call")
473 ) } {
474 if { $optype eq "st" } {
475 puts "WARNING: $fnname: $opname in delay slot of branch/call/ret at $fnpc may cause errata"
476 print_trace $fnpc $state fnops -1 1
477 puts ""
478 incr r
479 }
480 }
481 if { $lastoptype eq "jmpl" } {
482 set linst [lindex $state 0]
483 set q $fnops($linst)
484 set qh [lindex $q 0]
485 set qdec [ decode_inst $qh $linst $fnpc ]
486 unpack $qdec qdtype qdtreg qdsreg1 qdsreg2 qdstreg qddblflag qdimmed qdnnpc1 qdnnpc2 qdannul
487 if { $qdtreg==15 && $prev_savelevel==1 && $savelevel==1 } {
488 # Function call via pointer
489 incr is_call
490 } elseif { $qdtreg==0 && $savelevel==0 } {
491 # Return or tail recursion
492 return $r
493 } else {
494 # Computed goto or some other non-standard construct
495 puts_info "$fnname: Unable to trace jmpl at $linst - check manually"
496 return $r
497 }
498 } elseif { $lastoptype eq "call" } {
499 if { $savelevel==0 && $prev_savelevel==1 } {
500 # call,restore tail recursion into other fn
501 return $r
502 } elseif { $savelevel==0 && $prev_savelevel==0 && $treg == 15 } {
503 puts_note "$fnname: Leaf tail recursion construct at $fnpc"
504 return $r
505 } else {
506 incr is_call
507 }
508 }
509 # Update history
510 for { set z 0 } { $z <= $bubbles } { incr z } {
511 set state [concat $fnpca [lrange $state 0 4] ]
512 }
513 if { $is_call } {
514 if { $optype eq "branch" || $optype eq "call" || $optype eq "jmpl" } {
515 puts_info "$fnname: jump in delay slot of call - check manually"
516 }
517 # Setup state after call has returned
518 set dpdist 0
519 set state [list "dslot" "ret" "ret" "ret" "?" ]
520 set optype "?"; # for lastoptype
521 set fnnpc [ format "0x%08x" [expr {$fnpc+4}]]
522 set nnpc1 [ format "0x%08x" [expr {$fnpc+8}]]
523 set nnpc2 $nnpc1
524 set annul 0
525 }
526 # Handle annullment
527 if { ($annul & 2) != 0 } { set npc1 "A$fnnpc" } else { set npc1 $fnnpc }
528 if { ($annul & 1) != 0 } { set npc2 "A$fnnpc" } else { set npc2 $fnnpc }
529 # Recurse if multiple nPC:s, tail recurse for last element
530 if { $nnpc1 != $nnpc2 || $npc1 != $npc2 } {
531 # puts "Recursion nnpc:$nnpc2!"
532 set q [scan_wholefunc_main $fnname $npc1 $nnpc2 fnops $savelevel $dpdist $state statemap $optype]
533 set r [expr {$r+$q}]
534 }
535 set fnpc $npc1
536 set fnnpc $nnpc1
537 set lastoptype $optype
538 }
539 }
540
541 # Whole function scan for "LEON3FT Stale Cache After Store with Data Tag Parity Error" errata
542 # fnname - function name, fnaddr - function addres
543 # fnarr - name of array/hash-table containing operations
544 # key to the array is the address as 8-digit hex number prefixed with 0x
545 # value is a list containing 0:opcode, 1:mnemonic, 2:args
546 proc scan_wholefunc { fnname fnaddr fnarr } {
547 global fn_count fninst_count;
548 upvar $fnarr fnops
549
550 if { $fnname eq ".text" } {
551 puts "WARNING: The disassembled binary appears to be stripped, the script can not scan stripped binaries"
552 }
553
554 # Does the fn not contain any store at all, then we can skip it
555 set sid [array startsearch fnops]
556 set found_st 0
557 while { !$found_st } {
558 set op [array nextelement fnops $sid]
559 if { $op eq "" } { array donesearch fnops $sid; break }
560 set ophex [lindex $fnops($op) 0]
561 # puts "$ophex"
562 if { [is_store $ophex] } { incr found_st }
563 }
564 if { !$found_st } {
565 # puts "No store in $fnname!"
566 return 0
567 }
568
569 # -- Function contains store, proceed with scanning
570 # puts "Checking $fnname"
571 set pc "0x$fnaddr"
572 # puts "pc: $pc"
573 set npc [format "0x%08x" [expr {$pc+4}]]
574 array unset statemap
575 array set statemap ""
576 set ec [scan_wholefunc_main $fnname $pc $npc fnops 0 0 [list "dslot" "call" "?" "?" "?" "?"] statemap "?"]
577 # Update fn_count/fninst_count
578 incr fn_count
579 array unset itagchk
580 array set itagchk ""
581 set sid [array startsearch statemap]
582 while { [array anymore statemap $sid] } {
583 set x [array nextelement statemap $sid]
584 set iaddr [lindex $x 0]
585 # puts "iaddr: $iaddr"
586 if { [info exists fnops($iaddr)] && ![info exists itagchk($iaddr)]} {
587 incr fninst_count
588 set itagchk($iaddr) 1
589 }
590 }
591 array donesearch statemap $sid
592 return $ec
593 }
594
595
596 # --------- Main routine
597
598 if { ! [info exists sourcing] } {
599
600 # Parse command line
601 for {set i 0} {$i < $argc} {incr i} {
602 set arg [lindex $argv $i]
603 puts "arg=$arg"
604 if {"-noinfo" eq $arg} {
605 set msglevel [expr {$msglevel & ~($MSG_INFO)}]
606 }
607 if {"-nonote" eq $arg} {
608 set msglevel [expr {$msglevel & ~($MSG_NOTE)}]
609 }
610 if {"-silent" eq $arg} {
611 set msglevel 0
612 }
613 }
614
615 puts "\n$errata_desc errata scanning utility, rev $util_rev ($util_date)"
616
617 puts "Searching objdump -d output on standard input for:"
618 if {$b2bst_seqa_scan} {
619 puts " - $b2bst_seqa_desc"
620 }
621 if {$b2bst_seqb_scan} {
622 puts " - $b2bst_seqb_desc"
623 }
624 puts ""
625
626 set fn_valid 0
627 while {! [eof stdin]} {
628 set l [gets stdin]
629 incr line_count
630 # puts "line $l"
631 # Remove comment after '!'
632 set x [string first "!" "$l"]
633 if { $x >= 0 } then { set l [string range "$l" 0 $x] }
634 # check if entry point / function start
635 set m [regexp {^ *([0-9A-Fa-f]+) <([^ ]+)>:} "$l" t1 addr symname]
636 if { $m > 0 } then {
637 # puts "Function name=$symname addr=$addr"
638 if { $fn_valid } {
639 # puts $curfn_ops(0x40000000)
640 set q [scan_wholefunc $curfn $curfn_addr curfn_ops]
641 # puts "q=$q err_count=$err_count"
642 set err_count [ expr { $err_count + $q } ]
643 }
644 set curfn "$symname"
645 set curfn_addr "$addr"
646 array unset curfn_ops
647 array set curfn_ops ""
648 set fn_valid 0
649 } else {
650 # Check if opcode
651 set m [regexp {^ *([0-9A-Fa-f]+): *\t(.. .. .. ..) *\t([^ ]+)(.*)$} "$l" t1 addr hexcode opname opargs]
652 if { $m > 0 } then {
653 # puts "Opcode name=$opname args=$opargs addr=$addr"
654 incr op_count
655 set addr [format "%08x" 0x$addr]
656 set hexcode [string map {" " ""} $hexcode]
657 # puts "setting curfn_ops 0x$addr"
658 set curfn_ops(0x$addr) [list "0x$hexcode" $opname $opargs "" ""]
659 incr fn_valid
660 } else {
661 incr lineskip_count
662 }
663 }
664 }
665 if { $fn_valid } {
666 set q [scan_wholefunc $curfn $curfn_addr curfn_ops]
667 set err_count [ expr { $err_count + $q } ]
668 }
669
670 puts "\nObjdump lines processed: $line_count, lines skipped: $lineskip_count"
671 puts "Functions scanned: ${fn_count}, reachable instruction count: ${fninst_count}"
672 puts "Potential error locations found: $err_count\n"
673
674 if {$err_count == 0} {
675 exit 0
676 } else {
677 exit 1
678 }
679
680 }
681
@@ -1,10 +1,24
1 set(rtems_dir /opt/rtems-4.10/)
2
1 set(CMAKE_SYSTEM_NAME rtems)
3 set(CMAKE_SYSTEM_NAME rtems)
4 set(CMAKE_C_COMPILER ${rtems_dir}/bin/sparc-rtems-gcc)
5 set(CMAKE_CXX_COMPILER ${rtems_dir}/bin/sparc-rtems-g++)
6 set(CMAKE_LINKER ${rtems_dir}/bin/sparc-rtems-g++)
7 SET(CMAKE_EXE_LINKER_FLAGS "-static")
8 option(fix-b2bst "Activate -mfix-b2bst switch to mitigate \"LEON3FT Stale Cache Entry After Store with Data Tag Parity Error\" errata, GRLIB-TN-0009" ON)
9 if(fix-b2bst)
10 set(CMAKE_C_FLAGS_RELEASE "-O3 -mfix-b2bst")
2
11
3 set(CMAKE_C_COMPILER /opt/rtems-4.10/bin/sparc-rtems-gcc)
12 else()
4 set(CMAKE_CXX_COMPILER /opt/rtems-4.10/bin/sparc-rtems-g++)
13 set(CMAKE_C_FLAGS_RELEASE "-O3")
5 set(CMAKE_LINKER /opt/rtems-4.10/bin/sparc-rtems-g++)
14 endif()
6 SET(CMAKE_EXE_LINKER_FLAGS "-static")
7 set(CMAKE_C_FLAGS_RELEASE "-O3 -mfix-b2bst")
8 #set(CMAKE_C_FLAGS_RELEASE "-O3")
9 set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_LINKER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
15 set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_LINKER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
10 include_directories("/opt/rtems-4.10/sparc-rtems/leon3/lib/include")
16 include_directories("${rtems_dir}/sparc-rtems/leon3/lib/include")
17
18
19 function (check_b2bst target bin)
20 add_custom_command(TARGET ${target}
21 POST_BUILD
22 COMMAND ${rtems_dir}/bin/sparc-rtems-objdump -d ${bin}/${target} | ${CMAKE_SOURCE_DIR}/sparc/leon3ft-b2bst-scan.tcl
23 )
24 endfunction()
@@ -103,5 +103,10 add_definitions(-DSW_VERSION_N3=${SW_VER
103 add_definitions(-DSW_VERSION_N4=${SW_VERSION_N4})
103 add_definitions(-DSW_VERSION_N4=${SW_VERSION_N4})
104
104
105 add_executable(fsw ${SOURCES})
105 add_executable(fsw ${SOURCES})
106
107 if(fix-b2bst)
108 check_b2bst(fsw ${CMAKE_CURRENT_BINARY_DIR})
109 endif()
110
106 add_test_cppcheck(fsw STYLE UNUSED_FUNCTIONS POSSIBLE_ERROR MISSING_INCLUDE)
111 add_test_cppcheck(fsw STYLE UNUSED_FUNCTIONS POSSIBLE_ERROR MISSING_INCLUDE)
107
112
General Comments 0
You need to be logged in to leave comments. Login now