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