1 #!/usr/bin/ksh
2 #
3 #
4 # This file and its contents are supplied under the terms of the
5 # Common Development and Distribution License ("CDDL"), version 1.0.
6 # You may only use this file in accordance with the terms of version
7 # 1.0 of the CDDL.
8 #
9 # A full copy of the text of the CDDL should have accompanied this
10 # source. A copy of the CDDL is also available via the Internet at
11 # http://www.illumos.org/license/CDDL.
12 #
13
14 #
15 # Copyright 2023 Oxide Computer Company
16 #
17
18 #
19 # This shell script is a runner that tries to verify that if we write to
20 # a target program's xregs via /proc, that it actualy sees the same
21 # register contents that we put in. There are four different pieces to
22 # this:
23 #
24 # o The 'proc_xregs_set' binaries which sets the registers of the target.
25 # Right now we expect the bitness to match whatever it is running against.
26 # o The 'xregs_dump' binaries which dump the FPU state that they have in a
27 # bespoke format.
28 # o The output data files that we use to try to match what is generated.
29 # o The 'xsu_hwtype' binaries which tell us what data format we should expect.
30 #
31 # We have to discover what kind of hardware our target is running on and then
32 # that allows us to ensure that we can match up the right input and output
33 # files. We always run both the 32-bit and 64-bit versions of this; however,
34 # because 32-bit programs have access to fewer registers, they have a different
35 # data file to match against.
36 #
37 # We also reprat the process of 'proc_xregs_set' using the fpregs binary
38 # instead. That allows us to also verify some of the same behavior, but also
39 # pieces of fpregs functionality.
40 #
41
42 unalias -a
43 set -o pipefail
44 export LANG=C.UTF-8
45
46 pw_exit=0;
47 pw_arg0="$(basename $0)"
48 pw_dir="$(dirname $0)"
49 pw_datadir="$pw_dir/data"
50
51 #
52 # The starting value is used to determine the way that the regiser contents are
53 # set in the target's FPU. If you change this value, the check files must be
54 # updated.
55 #
56 typeset -A pw_start
57 pw_start["xregs32"]="0xc120ff06"
58 pw_start["xregs64"]="0xfaceecaf"
59 pw_start["fpregs32"]="0x20190909"
60 pw_start["fpregs64"]="0x28186002"
61
62 typeset -A pw_hwtypes
63 typeset -A pw_dump
64 typeset -A pw_prog
65 pw_hwtypes["32"]="$pw_dir/xsu_hwtype.32"
66 pw_hwtypes["64"]="$pw_dir/xsu_hwtype.64"
67 pw_dump["32"]="$pw_dir/xregs_dump.32"
68 pw_dump["64"]="$pw_dir/xregs_dump.64"
69 pw_prog["xregs32"]="$pw_dir/proc_xregs_set.32"
70 pw_prog["xregs64"]="$pw_dir/proc_xregs_set.64"
71 pw_prog["fpregs32"]="$pw_dir/fpregs.32"
72 pw_prog["fpregs64"]="$pw_dir/fpregs.64"
73
74 #
75 # All our victim programs are usually the same here and have a single breakpoint
76 # we want. This should become an associative array if this changes in the
77 # future.
78 #
79 pw_bkpt="xsu_getfpu"
80
81 warn()
82 {
83 typeset msg="$*"
84 echo "TEST FAILED: $msg" >&2
85 pw_exit=1
86 }
87
88 run_single()
89 {
90 typeset prog="$1"
91 typeset arch="$2"
92 typeset comb="$prog$arch"
93 typeset fpu_type=
94 typeset start=${pw_start[$comb]}
95 typeset hwtype=${pw_hwtypes[$arch]}
96 typeset dump=${pw_dump[$arch]}
97 typeset exe=${pw_prog[$comb]}
98 typeset output=
99 typeset check=
100
101 if ! fpu_type=$($hwtype 2>/dev/null); then
102 warn "failed to determine $arch-bit FPU type"
103 return
104 fi
105
106 printf "Discovered FPU: %s %s-bit\n" $fpu_type $arch
107 output="/tmp/$prog.$fpu_type.$arch.$$"
108 check="$pw_datadir/proc_writes.$prog.$fpu_type.$arch"
109
110 if ! [[ -r $check ]]; then
111 warn "missing expected output file $check"
112 return;
113 fi
114
115 printf "Running %s %s %s %s\n" $exe $dump $output $start
116 if ! $exe $dump $output $start $pw_bkpt; then
117 warn "$exe did not execute successfully"
118 rm -f $output
119 fi
120
121 if ! diff -q $check $output; then
122 diff -u $check $output
123 warn "$fpu_type $arch-bit FPU regs did not match expected " \
124 "output"
125 else
126 printf "TEST PASSED: %s %s-bit FPU regs matched /proc write\n" \
127 $fpu_type $arch
128 fi
129
130 rm -f $output
131 }
132
133 run_single xregs 32
134 run_single xregs 64
135 run_single fpregs 32
136 run_single fpregs 64
137
138 if (( pw_exit == 0 )); then
139 printf "All tests passed successfully\n"
140 fi
141
142 exit $pw_exit