smashinsts.tcl 3.73 KB
#
# Copyright (C) 1996-1998 by the Board of Trustees
#    of Leland Stanford Junior University.
# 
# This file is part of the SimOS distribution. 
# See LICENSE file for terms of the license. 
#
#
# set:
#
#  smashlist:   filename with list of 'addr funcname' pairs
#  smashcycle:  cycle in which to change instruction
#  startindex:  index into smash list to start search for a smashable inst
#  switchdelay: number of periodic's to wait after smashed inst executed
#               before switching to Embra
#
#  smashtest :  1 -> this run is to filter smashlist by which instrs can be
#               smashed.  If so need to set
#


set smash_f [open $smashlist r]
for {set skipline 0} {$skipline < $startindex} {incr skipline} {
    if {[gets $smash_f ignoreline] < 0} {
        console "Premature end-of-file in smash list\n"
        exit
    }
}

if {$switchdelay < 1} {
    console "smashinsts.tcl: ERROR. must set switchdelay to 1 or higher\n"
    incr FORCETCLERROR
}

if {$smashtest == 0} {
    if {[gets $smash_f smashline] < 0} {
        console "Premature end-of-file in smash list\n"
        exit
    }


    set switchtoembra 0

    set smashfields     [split $smashline]
    set smashaddr       [lindex $smashfields 2]
    set smashcontrol    [lindex $smashfields 3]
    set smashfunc       [lindex $smashfields 4]

    log "SMASH will be cyc $smashcycle: [lrange $smashfields 2 end]\n"

    annotation set cycle $smashcycle {
        set okp [fault inst smash $smashaddr $smashcontrol $smashfunc]
        if {$okp != "OK"} {
            console "$smashcycle SMASH failed to smash instruction\n"
        }
    }

    annotation set pc $smashaddr {
        if {$CYCLES > $smashcycle} {
            if {$SIMOS(EmbraPresent) && ($switchtoembra == 0)} {
                log "SMASH $CYCLES executed smashed instruction\n"
                incr switchtoembra
            }
        }
    }

    annotation set simos periodic {
        if {$switchtoembra > 0} {
            if {$switchtoembra <= $switchdelay} {
                incr switchtoembra
                if {$switchtoembra > $switchdelay} {
                    cpuEnter EMBRA_PAGE
                }
            }
        }
    }

} else {

    annotation set simos enter {
        if {$CPU == 0} {
            while {! [eof $smash_f]} {
                set againp RETRY
                set rval [random 0xfff]
                while {$againp == "RETRY"} {
                    if {[gets $smash_f smashline] < 0} {
                        break
                    }
                    set smashpair [split $smashline]
                    set againp [fault inst test [lindex $smashpair 0] $rval [lindex $smashpair 1]]
                }
            }
            exit
        }
    }
}

##
## recovery timing
##

annotation set pc kernel::hive_LSET:lset_started {
    log "RECOVERY lsetStart cycle=$CYCLES cpu=$CPU\n"
}

annotation set pc kernel::hive_LSET:lset_finished {
    log "RECOVERY lsetFinish cycle=$CYCLES cpu=$CPU\n"
}

annotation set pc kernel::hive_RECV:recovery_started {
    log "RECOVERY recoveryStart cycle=$CYCLES cpu=$CPU\n"
}

annotation set pc kernel::hive_RECV:recovery_finished {
    log "RECOVERY recoveryFinish cycle=$CYCLES cpu=$CPU\n"
}

##
## remote fork 
##

annotation set pc kernel:fork.c:procfork_remote:START {
    log "REMFORK start cycle=$CYCLES cpu=$CPU to=$a0\n"
}

annotation set pc kernel:fork.c:procfork_remote:END {
    log "REMFORK finish cycle=$CYCLES cpu=$CPU\n"
}

proc NewProc {} {
    global CPU CYCLES CELL K0BASE u
    set procp "(*(struct proc*)[symbol read kernel:user.h:$u.u_procp])"
    log "PROCESS cell=$CELL "
    log "pid=[symbol read kernel:timer.c:$procp.p_pid] "
    log "name=[symbol read kernel:user.h:$u.u_comm] "
    log "cycle=$CYCLES \n"
}

annotation set pc kernel::exece:END {
    NewProc
}