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 42unalias -a 43set -o pipefail 44export LANG=C.UTF-8 45 46pw_exit=0; 47pw_arg0="$(basename $0)" 48pw_dir="$(dirname $0)" 49pw_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# 56typeset -A pw_start 57pw_start["xregs32"]="0xc120ff06" 58pw_start["xregs64"]="0xfaceecaf" 59pw_start["fpregs32"]="0x20190909" 60pw_start["fpregs64"]="0x28186002" 61 62typeset -A pw_hwtypes 63typeset -A pw_dump 64typeset -A pw_prog 65pw_hwtypes["32"]="$pw_dir/xsu_hwtype.32" 66pw_hwtypes["64"]="$pw_dir/xsu_hwtype.64" 67pw_dump["32"]="$pw_dir/xregs_dump.32" 68pw_dump["64"]="$pw_dir/xregs_dump.64" 69pw_prog["xregs32"]="$pw_dir/proc_xregs_set.32" 70pw_prog["xregs64"]="$pw_dir/proc_xregs_set.64" 71pw_prog["fpregs32"]="$pw_dir/fpregs.32" 72pw_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# 79pw_bkpt="xsu_getfpu" 80 81warn() 82{ 83 typeset msg="$*" 84 echo "TEST FAILED: $msg" >&2 85 pw_exit=1 86} 87 88run_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 133run_single xregs 32 134run_single xregs 64 135run_single fpregs 32 136run_single fpregs 64 137 138if (( pw_exit == 0 )); then 139 printf "All tests passed successfully\n" 140fi 141 142exit $pw_exit 143