os.tcl 10.3 KB
#
# Copyright (C) 1998 by the Board of Trustees
#    of Leland Stanford Junior University.
# Copyright (C) 1998 Digital Equipment Corporation
#
# This file is part of the SimOS distribution.
# See LICENSE file for terms of the license.
#

#
# 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. 
#

###
### This file is responsible for raising OS level annotations and tracking
### the current process.
###
###

####
#### init this module
####

FileSourced osf/os.tcl

source syscalls.tcl
source osfpal.tcl



annotation type osEvent enum {
    startUser   endUser
    startKernel endKernel
    startPal    endPal
    startIdle   endIdle
    startSync   endSync
    switchIn    switchOut
    procstart   procexit   procexec  procwait
}

# must agree with cpus-alpha/alpha-shared/ev5.c
annotation type exc enum {
    reset mchk arith interrupt ndtb_miss pdtb_miss unalign dtb_fault itb_miss itb_acv opdec fen pal
}

proc inUserMode {} {
    global IPR
    set IPR_PS 0x10f
    set PS $IPR(0x10f)
    return [expr ($PS & 24) != 0]
}

####
#### the annotations 
####

##
## process and idle tracking
##

annotation set simos enter {
    set palCodeCount($CPU) 0
    set PCBB($CPU) $IPR(0x157)
    if {$PCBB($CPU)==0} {
	### only if booting
	### hack to make it unique across processors
	###
	set PCBB($CPU) [expr -1 * $CPU]
    }
    console "OS.TCl: entering for cpu $CPU. pc=$pc \n"
    set PID($CPU) $PCBB($CPU)
    if [catch {currentProcess}] {
        # booting
        set PROCESS($CPU) "boot"
        set OSPID($CPU) boot$CPU
        
    } elseif {(([hex $pc] >= [symbol read vmunix::idle_thread:START])
               && ([hex $pc] <= ([symbol read vmunix::idle_thread:END] + 4)))
              || ((![catch {symbol read vmunix::checkRunq:START}]) && 
                  ([hex $pc] >= [symbol read vmunix::checkRunq:START])
                  && ([hex $pc] <= ([symbol read vmunix::checkRunq:END] + 4)))} {
        # idle
        set PROCESS($CPU) "idle"
        set OSPID($CPU) idle$CPU
        
    } else {
        set PROCESS($CPU) "someprocess"
        set OSPID($CPU) "someprocess$CPU"
    }

    console "OS.TCL entering for cpu=$CPU with pid=$OSPID($CPU) pcbb=$PCBB($CPU) process=$PROCESS($CPU) \n"
}


proc newproc { pid process comment } {
    global CPU PROCESS PID PCBB OSPID
    if {($PCBB($CPU) != $PID($CPU))} { 
        annotation exec osEvent switchOut
        set PROCESS($CPU) $process
        set OSPID($CPU) $pid
        set PID($CPU) $PCBB($CPU)
        #console "XXX newproc $comment $pid $process \n"
        annotation exec osEvent switchIn
	if {$PROCESS($CPU) == "kernel idle"} {
	    annotation exec osEvent startIdle
	}
    } else {
        console "newproc. Switching to the same (pid,process)=($OSPID($CPU),$PROCESS($CPU)) and same PCBB comment=$comment \n"
       
        
    }
}


proc currentProcess {} {
    global sp
    global MEMORY PROCESS PID  UU_COMM  UTASK_OFFSET UPROC_OFFSET a0 CPU CYCLES
    set stack_layout [hex [expr $sp & ~0x3fff]]
    set task  [symbol read "vmunix::((struct stack_layout *)$stack_layout)->uthread.utask"]
    set newPROCESS [symbol read "vmunix::((struct utask *)$task)->uu_comm"]
    return $newPROCESS
}

proc currentPID {} {
    global sp
    global MEMORY PROCESS PID  UU_COMM  UTASK_OFFSET UPROC_OFFSET a0 CPU CYCLES

    set stack_layout [hex [expr $sp & ~0x3fff]]
    set pproc [symbol read "vmunix::((struct stack_layout *)$stack_layout)->uthread.proc"] 
    set newPID [symbol read "vmunix::((struct proc *)$pproc)->p_pid"] 
    return $newPID
}

proc currentPPID {} {
    global sp
    global MEMORY PROCESS PID  UU_COMM  UTASK_OFFSET UPROC_OFFSET a0 CPU CYCLES

    set stack_layout [hex [expr $sp & ~0x3fff]]
    set pproc [symbol read "vmunix::((struct stack_layout *)$stack_layout)->uthread.proc"] 
    set ppid [symbol read "vmunix::((struct proc *)$pproc)->p_ppid"] 
    return $ppid
}

proc ContextSwitch { ptr} { 
   
    global MEMORY PROCESS PID  UU_COMM  UTASK_OFFSET UPROC_OFFSET a0 CPU CYCLES
   
    set stack_layout [hex $ptr]
 
    ##
    ## find base of get_sp()->uthread
    ## 

    set task  [symbol read "vmunix::((struct stack_layout *)$stack_layout)->uthread.utask"]
    set pproc [symbol read "vmunix::((struct stack_layout *)$stack_layout)->uthread.proc"] 
    
    set newPROCESS [symbol read "vmunix::((struct utask *)$task)->uu_comm"]
    set newPID [symbol read "vmunix::((struct proc *)$pproc)->p_pid"] 

    if {($newPROCESS != $PROCESS($CPU)) || ($newPID != $OSPID($CPU))} { 
	newproc  $newPID $newPROCESS ContextSwitch
    }
}


######################################################
####  Annotations 
######################################################

### PALENTRY(0x6c01) == callpal_swpctx

annotation set pc 0x6c01 {
    #console "CALL_PAL swpctxt $a0 \n"
    set PCBB($CPU) $a0
}

    
annotation set pc vmunix::idle_thread:START {
    #newproc  idle$CPU "idle" idle_thread_START
    set OSPID($CPU) idle$CPU
    set PROCESS($CPU) idle
    annotation exec osEvent startIdle
}

annotation set pc vmunix::idle_thread:END {
    if {$PROCESS($CPU) != "idle"} {
        # this can happen when we take an interrupt on idle end
        console "OS.TCL: ignoring end idle when process != idle $CYCLES\n"
    } else {
        annotation exec osEvent endIdle
        newproc  runq$CPU "runq" idle_threadEND
    }
}

annotation set pc vmunix::swtch:START {
    newproc  runq$CPU "runq" swtchSTART
}

annotation set pc vmunix::swtch:END {
    newproc  [currentPID] [currentProcess] swtchEND
}

annotation set pc vmunix::swtch_pri:START {
    newproc  runq$CPU "runq" swtch_pri_START
}

annotation set pc vmunix::swtch_pri:END {
    newproc  [currentPID] [currentProcess] swtch_pri_END
}

####
#### This is the key annotation. Ocurs just after the callpal swpctx
####
annotation  set pc vmunix::thread_continue {
    newproc [currentPID] [currentProcess] thread_continue
}

#annotation set pc vmunix::thread_ex_end { 
   # console "Reached thread_ex_end \n"
   # newproc [currentPID] [currentProcess] thread_ex_end
#}





console "@@@ adding annotation to vmunix::newproc:END\n"

annotation set pc vmunix::newproc:END {
    global a1 sp v0
    global MEMORY PROCESS PID  UU_COMM  UTASK_OFFSET UPROC_OFFSET a0 CPU CYCLES CHILD_PID

    if {$v0 != 0} {
	set th $v0
	set ptask [symbol read "vmunix::((struct thread *)$th)->task"]
	set newPID [symbol read "vmunix::((struct super_task *)$ptask)->proc.p_pid"]
	# child process of the fork
	log "newproc in os.tcl: current PID is $OSPID($CPU), new pid is $newPID\n"
	set CHILD_OSPID($CPU) $newPID
	annotation exec osEvent procstart
	# does not cause a process switch
    }
}

annotation set pc vmunix::waitf:END {
    ## process join
    global CHILD_PID CPU a3 v0
    set CHILD_OSPID($CPU) 0
    if {$v0 == 0} {
	catch {set CHILD_OSPID($CPU) [Double $a3]} err
    }
    annotation exec osEvent procwait
}

annotation set pc vmunix::common_exec:END {
    annotation exec osEvent switchOut
    set PROCESS($CPU) [currentProcess]
    annotation exec osEvent procexec
    annotation exec osEvent switchIn
}

annotation set pc vmunix::exit:START {
    global a0 a1 sp v0 ra
    global MEMORY PROCESS PID  UU_COMM  UTASK_OFFSET UPROC_OFFSET a0 CPU CYCLES

    set pproc $a0
    set pid [symbol read "vmunix::((struct proc *)$pproc)->p_pid"]
#    console "exit:START: current PID is $OSPID($CPU), exiting pid is $pid (ra=$ra)\n"
    set sym [symbol find vmunix $ra]
#    console "\t ra is in $sym\n"
#    annotation exec osEvent procexit
}

if {$detailLevel >= 2} {

    ##
    ## kernel - user transitions
    ##

    set MAX_CPUS 256

    for {set i 0} {$i < $MAX_CPUS} {incr i} {
        set utlb($i) 0
    }
    
    annotation set utlb {
        set utlb($CPU) 1
	    # should be looking at $IPR(EXC_ADDR)?
	console "UTLB: os.tcl\n"
        exit
# 	if {![inUserMode]} {
#             annotation exec osEvent endUser
#         }
#         annotation exec osEvent startKernel

    }
    
    ###
    ### 0x70c1 callsys   0x4101 interrupt  0x4381 DTB_FAULT  0x4481 ITB_ACV
    ### 0x6f41 retsys    0x6fc1 rti
    ### 0x6241 cserve a2==9 --> jToPal

    annotation set exc {
        set currentPalEntry($CPU) $PALENTRY($pc)
        incr palCodeCount($CPU)
        #log "PALCODE $CYCLES $CPU $palCodeCount($CPU) entry excAddr=$IPR(0x10b) entry $PALENTRY($pc)\n"
        if {($pc==0x70c1) || ($pc==0x4101) || ($pc==0x4381) ||($pc==0x4081)} { 
            annotation exec osEvent startKernel
        }
        if {($pc==0x6f41) || ($pc==0x6fc1)} { 
            #console "OS.TCL $CYCLES RTI/RETSYS pc=$pc exc=$IPR(0x10b) \n"
            annotation exec osEvent endKernel
        }
        if {($pc==0x6241) && $a2==0x9} {
            console "OS.TCL:: cServe jToPal. Pusing extra startPal state\n"
            annotation exec osEvent startPal
        }
       
	annotation exec osEvent startPal
        
    }
    if {0} { 
        global IPR
        
	set exc_addr $IPR(0x10b)

        console "OS.TCL:: EXC  $exc_addr $pc $PALENTRY($pc) \n"
	if {$exc_addr & 1 } {
            incr palCodeCount($CPU) -1
            #log "PALCODE $CYCLES $CPU $palCodeCount($CPU) exit\n"
	    annotation exec osEvent endPal
	} elseif [inUserMode] {
	    annotation exec osEvent endUser
        } else {
	    annotation exec osEvent endKernel
	}
	annotation exec osEvent startPal
        set utlb($CPU) 0
    }
        
    annotation set inst rfe {
        incr palCodeCount($CPU) -1
        #log "PALCODE $CYCLES$CPU $palCodeCount($CPU) exit\n"
        annotation exec osEvent endPal
    }
        

    ##
    ## synchronization stuff
    ##

    if {0} {

	# MP kernel
	console "INFO: DigitalUnix multiprocessor\n"
	
	annotation set pc vmunix::fiolock:START {
	    annotation exec osEvent startSync
	}
	annotation set pc vmunix::fiolock:END {
	    annotation exec osEvent endSync
	}

	annotation set pc vmunix::fiounlock:START {
	    annotation exec osEvent startSync
	}
	annotation set pc vmunix::fiounlock:END {
	    annotation exec osEvent endSync
	}

	if {0} {
	    annotation set pc vmunix::simple_lock:START {
		annotation exec osEvent startSync
	    }
	    annotation set pc vmunix::simple_lock:END {
		annotation exec osEvent endSync
	    }

	    annotation set pc vmunix::simple_unlock:START {
		annotation exec osEvent startSync
	    }
	    annotation set pc vmunix::simple_unlock:END {
		annotation exec osEvent endSync
	    }
	}
	
    }
}