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