fault.tcl 8.04 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. 
#


random seed


##
## returns a random kseg0 address. if an optional node number is supplied
## restricts the address to be on that node
##

proc RandomKSeg0Addr {{node -1}} {
    global PARAM numCells K0BASE

    set highMem [expr $PARAM(MEMSYS.MemSize) << 20]

    if {$node != -1} {
        set memPerNode [expr $highMem / $numCells]
        set addr [expr [random $memPerNode] + ($memPerNode * $node) + $K0BASE]
    } else {
        set addr [expr [random $highMem] + $K0BASE]
    }

    hex [expr $addr & 0xfffffffc]
}


###
### these anns needed for the hivePostPmake script
###

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"
}


##
## 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"
}

##
## pid tracking
##

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

##
## graceful exit
##

annotation set pc kernel::Simos_idlenap {
    console "going into idlenap... exiting\n"
    exit
}

##
## firewall stats - % data pages unprotected
##

annotation set simos periodic {
    for {set cell 0} {$cell < $numCells} {incr cell} {
        log "FREEMEM cycle=$CYCLES cell=$cell [symbol read kernel$cell::freemem]\n"
    }
}


###
### fault support
###
### globals used:
###    faultCPU
###    faultType
###    faulrArg
###    faultWith
###    faultTime
###    faultEnd
###

set currentDieSet 0

annotation set pc kernel::SimosGetDieSet:END {
    set v0 $currentDieSet
}

proc haltFault {start end {cpu -1}} {
    global faultCPU

    if {$cpu == -1} {
        set faultCPU [expr [random 3] + 1]
    } else {
        set faultCPU $cpu
    }
    
    if {$end} {        
        set time [expr [random [expr $end - $start]] + $start]
    } else {
        set time $start
    }

    console "fault set cycles $time cell $faultCPU halt\n"

    annotation set cycle $time {
        log "FAULT: halting cell $faultCPU cycles $CYCLES\n"
        fault cpu $faultCPU halt
        set currentDieSet [expr $currentDieSet | (1 << $faultCPU)]
    }

    annotation set cycle 2000000000 {
        console "ERROR: I hit 2 billion cycles. bye bye...\n"
        exit
    }
}


##
## with: number, "plus4", or "addr"
## type: "preg", "pmap", "pfdHash", "runq", "upage"
##

proc setSmash {type arg cell with start {end 0}} {
    global faultCPU faultType faultArg faultWith

    if {$end} {        
        set time [expr [random [expr $end - $start]] + $start]
    } else {
        set time $start
    }
    
    console "fault set faultype $type cycles $time cell $cell smash $type arg $arg with $with\n"
    
    set faultCPU $cell
    set faultType $type
    set faultArg $arg
    set faultWith $with
    
    annotation set cycle $time {
        set addr [GET$faultType $faultArg kernel$faultCPU]

        if {!$addr} {
            console "ERROR: couldn't get smash addr\n"
            return
        }
        
        if {$faultWith == "plus4"} {
            set MEMORY($addr) [expr $MEMORY($addr) + 4]
        } elseif {$faultWith == "addr"} {
            set MEMORY($addr) $addr
        } else {
            set MEMORY($addr) $faultWith
        }

        set av [hex $addr]
        set hv [hex $MEMORY($addr)]
        log "FAULT: smashing cell $faultCPU cycles $CYCLES type $faultWith ($av := $hv)\n"

        if {0} {
            # skip this -- OS should now correctly reboot failed cell
            set currentDieSet [expr $currentDieSet | (1 << $faultCPU)]
        }
    }

    annotation set cycle 2000000000 {
        console "ERROR: I hit 2 billion cycles. bye bye...\n"
        exit
    }
}

##
## return the address of the processes (given by pid) pregion pointer
##

proc GETpreg {pid kernel} {
    set procp [symbol read $kernel::proc]
    set nump [symbol read $kernel::v.v_proc]

    for {set i 0} {$i < $nump} {incr i} {
        if {[symbol read $kernel:proc.h:((proc_t*)$procp)<$i>.p_pid] == $pid} {
            return [symbol read $kernel:proc.h:&((proc_t*)$procp)<$i>.p_region]
        }       
    }

    return 0
}

##
## return the address of the processes (given by pid) heap segment pointer
##

proc GETpmap {pid kernel} {
    set procp [symbol read $kernel::proc]
    set nump [symbol read $kernel::v.v_proc]

    for {set i 0} {$i < $nump} {incr i} {
        if {[symbol read $kernel:proc.h:((proc_t*)$procp)<$i>.p_pid] == $pid} {
            set pmap [symbol read $kernel:proc.h:((proc_t*)$procp)<$i>.p_pmap]
            return [symbol read $kernel:pmap.c:&((pseg_t*)$pmap)->pseg_segptr<64>]
        }       
    }

    return 0
}

##
## return the address of the head of the page hash table
##

proc GETpfdHash {arg kernel} {
    return [symbol read $kernel::&phash]
}

##
## return the address of the head of the global affinity runq
##

proc GETrunq {arg kernel} {
    set qdp [symbol read $kernel:runq.c:Runq._qlist]
    while {[symbol read $kernel:runq_private.h:((QueueDesc*)$qdp)->_type] != 2} {
        set qdp [symbol read $kernel:runq_private.h:((QueueDesc*)$qdp)->_link]
    }

    # I must smash some stuf to make sure it looks down this queue
    symbol set $kernel:runq_private.h:((QueueDesc*)$qdp)->_globalq._nq 100
    symbol set $kernel:runq_private.h:((QueueDesc*)$qdp)->_globalq._highest_pri 0

    return [symbol read $kernel:runq_private.h:&((QueueDesc*)$qdp)->_globalq._arunq]
}

##
## return the address of the processes (given by pid) fileid 3's vnode ptr
##

proc GETupage {pid kernel} {
    global MEMORY

    set procp [symbol read $kernel::proc]
    set nump [symbol read $kernel::v.v_proc]

    for {set i 0} {$i < $nump} {incr i} {
        if {[symbol read $kernel:proc.h:((proc_t*)$procp)<$i>.p_pid] == $pid} {
            return [symbol read $kernel:proc.h:&((proc_t*)$procp)<$i>.p_upgs<0>]
        }       
    }

    return 0
}


##
## Must do something different for kernel malloc smash
##
## smash v0 on the first kmem_zone_alloc after random time 
##
## with: "minus8" or val
##

proc setKmemAllocSmash {cell with start {end 0}} {
    global faultCPU faultWith faultTime faultEnd
    
    if {$end} {        
        set time [expr [random [expr $end - $start]] + $start]
    } else {
        set time $start
    }

    console "fault set cycles $time cell $cell smash kernFree with $with\n"
    
    set faultCPU $cell
    set faultWith $with
    set faultTime $time
    set faultEnd $end

    annotation set pc kernel$cell::kmem_zone_alloc:END -tag smashit {
        if {$CYCLES > $faultTime} {
            if {$faultEnd && ($CYCLES > $faultEnd)} {
                console "SMASH ERROR: missed smash time $faultEnd now $CYCLES\n"
                exit
            }

            if {$faultWith == "minus8"} {
                set REGISTER(v0) [expr $REGISTER(v0) - 8]
            } else {
                set REGISTER(v0) $faultWith
            }

            set hv [hex $REGISTER(v0)]
            console "FAULT: smashing cell $faultCPU cycles $CYCLES kmem_register ($hv)\n"
            annotation disable smashit

            if {0} {
                set currentDieSet [expr $currentDieSet | (1 << $faultCPU)]
            }
        }
    }

    annotation set cycle 2000000000 {
        console "ERROR: I hit 2 billion cycles. bye bye...\n"
        simosExit
    }
}