1290001Sglebius#!/bin/ksh 2290001Sglebius 3290001Sglebius# 4290001Sglebius# File: patchfreq 5290001Sglebius# Author: Bryan Cantrill (bmc@eng.sun.com), Solaris Performance 6290001Sglebius# Modified: Sat Apr 26 04:00:59 PDT 1997 7290001Sglebius# 8290001Sglebius# This is a little script to patch a 5.5 or 5.5.1 kernel to get around 9290001Sglebius# the cpu_tick_freq inaccuracy. Before running this script, one must 10290001Sglebius# know the true frequency of one's CPU; this can be derived by NTP, 11290001Sglebius# or by observing the clock relative to the time-of-day chip over a 12290001Sglebius# long period of time (the TOD will pull system time when it drifts 13290001Sglebius# by more than two seconds). 14290001Sglebius# 15290001Sglebius# Patching a kernel can render a machine unbootable; do not run this 16290001Sglebius# script unless you are prepared to accept that possibility. It 17290001Sglebius# is advisable to have a backout path (e.g. net booting, an alternate 18290001Sglebius# boot disk, an installation CD) should your machine fail to boot. 19290001Sglebius# 20290001Sglebius# This is not a product of Sun Microsystems, and is provided "as is", 21290001Sglebius# without warranty of any kind expressed or implied including, but not 22290001Sglebius# limited to, the suitability of this script for any purpose. 23290001Sglebius# 24290001Sglebius 25290001Sglebiusif [ $# -eq 0 ]; then 26290001Sglebius echo "Usage: $0 cpu_tick_freq [ alternate_kernel ]" 27290001Sglebius exit 1 28290001Sglebiusfi 29290001Sglebius 30290001Sglebiuscpu_tick_freq=$1 31290001Sglebiuskernel=/platform/sun4u/kernel/unix 32290001Sglebius 33290001Sglebiusif [ $# -eq 2 ]; then 34290001Sglebius kernel=$2 35290001Sglebiusfi 36290001Sglebius 37290001Sglebiusif [ ! -w $kernel ]; then 38290001Sglebius echo "$0: Cannot open $kernel for writing." 39290001Sglebius exit 1 40290001Sglebiusfi 41290001Sglebius 42290001Sglebiusarch=`echo utsname+404?s | adb $kernel | cut -d: -f2` 43290001Sglebius 44290001Sglebiusif [ ! $arch = "sun4u" ]; then 45290001Sglebius echo "Patch only applies to sun4u" 46290001Sglebius exit 1 47290001Sglebiusfi 48290001Sglebius 49290001Sglebiusrel=`echo utsname+202?s | adb $kernel | cut -d: -f2` 50290001Sglebius 51290001Sglebiusif [ ! $rel = "5.5" ] && [ ! $rel = "5.5.1" ]; then 52290001Sglebius echo "Patch only applies to 5.5 or 5.5.1..." 53290001Sglebius exit 1 54290001Sglebiusfi 55290001Sglebius 56290001Sglebiusnop="1000000" # nop 57290001Sglebiusstore_mask="ffffe000" # mask out low 13 bits 58290001Sglebiusstore="da256000" # st %o5, [%l5 + offset] 59290001Sglebius 60290001Sglebiusinstr=`echo setcpudelay+34?X | adb $kernel | cut -d: -f 2 | nawk '{ print $1 }'` 61290001Sglebius 62290001Sglebiusif [ $instr = $nop ]; then 63290001Sglebius echo "Instruction already patched..." 64290001Sglebiuselse 65290001Sglebius let masked="(16#$store_mask & 16#$instr) - 16#$store" 66290001Sglebius if [ $masked -ne 0 ]; then 67290001Sglebius echo "Couldn't find instruction to patch; aborting." 68290001Sglebius exit 1 69290001Sglebius fi 70290001Sglebius 71290001Sglebius if ! echo setcpudelay+34?W $nop | adb -w $kernel 1> /dev/null 72290001Sglebius then 73290001Sglebius echo "adb returned an unexpected error; aborting." 74290001Sglebius fi 75290001Sglebiusfi 76290001Sglebius 77290001Sglebiusecho "Patching cpu_tick_freq to $cpu_tick_freq..." 78290001Sglebius 79290001Sglebiusif ! echo cpu_tick_freq?W 0t$cpu_tick_freq | adb -w $kernel 1> /dev/null; then 80290001Sglebius echo "adb returned an unexpected error; aborting." 81290001Sglebius exit 1 82290001Sglebiusfi 83290001Sglebius 84290001Sglebiusecho "$kernel successfully patched." 85290001Sglebiusexit 0 86