cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

gpio-mockup.sh (8685B)


      1#!/bin/bash -efu
      2# SPDX-License-Identifier: GPL-2.0
      3
      4#exit status
      5#0: success
      6#1: fail
      7#4: skip test - including run as non-root user
      8
      9BASE=${0%/*}
     10DEBUGFS=
     11GPIO_DEBUGFS=
     12dev_type="cdev"
     13module="gpio-mockup"
     14verbose=
     15full_test=
     16random=
     17uapi_opt=
     18active_opt=
     19bias_opt=
     20line_set_pid=
     21
     22# Kselftest return codes
     23ksft_fail=1
     24ksft_skip=4
     25
     26usage()
     27{
     28	echo "Usage:"
     29	echo "$0 [-frv] [-t type]"
     30	echo "-f:  full test (minimal set run by default)"
     31	echo "-r:  test random lines as well as fence posts"
     32	echo "-t:  interface type:"
     33	echo "      cdev (character device ABI) - default"
     34	echo "      cdev_v1 (deprecated character device ABI)"
     35	echo "      sysfs (deprecated SYSFS ABI)"
     36	echo "-v:  verbose progress reporting"
     37	exit $ksft_fail
     38}
     39
     40skip()
     41{
     42	echo "$*" >&2
     43	echo "GPIO $module test SKIP"
     44	exit $ksft_skip
     45}
     46
     47prerequisite()
     48{
     49	[ $(id -u) -eq 0 ] || skip "must be run as root"
     50
     51	DEBUGFS=$(grep -w debugfs /proc/mounts | cut -f2 -d' ')
     52	[ -d "$DEBUGFS" ] || skip "debugfs is not mounted"
     53
     54	GPIO_DEBUGFS=$DEBUGFS/$module
     55}
     56
     57remove_module()
     58{
     59	modprobe -r -q $module
     60}
     61
     62cleanup()
     63{
     64	set +e
     65	release_line
     66	remove_module
     67	jobs -p | xargs -r kill > /dev/null 2>&1
     68}
     69
     70fail()
     71{
     72	echo "test failed: $*" >&2
     73	echo "GPIO $module test FAIL"
     74	exit $ksft_fail
     75}
     76
     77try_insert_module()
     78{
     79	modprobe -q $module "$1" || fail "insert $module failed with error $?"
     80}
     81
     82log()
     83{
     84	[ -z "$verbose" ] || echo "$*"
     85}
     86
     87# The following line helpers, release_Line, get_line and set_line, all
     88# make use of the global $chip and $offset variables.
     89#
     90# This implementation drives the GPIO character device (cdev) uAPI.
     91# Other implementations may override these to test different uAPIs.
     92
     93# Release any resources related to the line
     94release_line()
     95{
     96	[ "$line_set_pid" ] && kill $line_set_pid && wait $line_set_pid || true
     97	line_set_pid=
     98}
     99
    100# Read the current value of the line
    101get_line()
    102{
    103	release_line
    104
    105	local cdev_opts=${uapi_opt}${active_opt}
    106	$BASE/gpio-mockup-cdev $cdev_opts /dev/$chip $offset
    107	echo $?
    108}
    109
    110# Set the state of the line
    111#
    112# Changes to line configuration are provided as parameters.
    113# The line is assumed to be an output if the line value 0 or 1 is
    114# specified, else an input.
    115set_line()
    116{
    117	local val=
    118
    119	release_line
    120
    121	# parse config options...
    122	for option in $*; do
    123		case $option in
    124		active-low)
    125			active_opt="-l "
    126			;;
    127		active-high)
    128			active_opt=
    129			;;
    130		bias-none)
    131			bias_opt=
    132			;;
    133		pull-down)
    134			bias_opt="-bpull-down "
    135			;;
    136		pull-up)
    137			bias_opt="-bpull-up "
    138			;;
    139		0)
    140			val=0
    141			;;
    142		1)
    143			val=1
    144			;;
    145		esac
    146	done
    147
    148	local cdev_opts=${uapi_opt}${active_opt}
    149	if [ "$val" ]; then
    150		$BASE/gpio-mockup-cdev $cdev_opts -s$val /dev/$chip $offset &
    151		# failure to set is detected by reading mockup and toggling values
    152		line_set_pid=$!
    153		# allow for gpio-mockup-cdev to launch and request line
    154		# (there is limited value in checking if line has been requested)
    155		sleep 0.01
    156	elif [ "$bias_opt" ]; then
    157		cdev_opts=${cdev_opts}${bias_opt}
    158		$BASE/gpio-mockup-cdev $cdev_opts /dev/$chip $offset || true
    159	fi
    160}
    161
    162assert_line()
    163{
    164	local val
    165	# don't need any retry here as set_mock allows for propagation
    166	val=$(get_line)
    167	[ "$val" = "$1" ] || fail "line value is ${val:-empty} when $1 was expected"
    168}
    169
    170# The following mockup helpers all make use of the $mock_line
    171assert_mock()
    172{
    173	local backoff_wait=10
    174	local retry=0
    175	local val
    176	# retry allows for set propagation from uAPI to mockup
    177	while true; do
    178		val=$(< $mock_line)
    179		[ "$val" = "$1" ] && break
    180		retry=$((retry + 1))
    181		[ $retry -lt 5 ] || fail "mockup $mock_line value ${val:-empty} when $1 expected"
    182		sleep $(printf "%0.2f" $((backoff_wait))e-3)
    183		backoff_wait=$((backoff_wait * 2))
    184	done
    185}
    186
    187set_mock()
    188{
    189	echo "$1" > $mock_line
    190	# allow for set propagation - so we won't be in a race with set_line
    191	assert_mock "$1"
    192}
    193
    194# test the functionality of a line
    195#
    196# The line is set from the mockup side and is read from the userspace side
    197# (input), and is set from the userspace side and is read from the mockup side
    198# (output).
    199#
    200# Setting the mockup pull using the userspace interface bias settings is
    201# tested where supported by the userspace interface (cdev).
    202test_line()
    203{
    204	chip=$1
    205	offset=$2
    206	log "test_line $chip $offset"
    207	mock_line=$GPIO_DEBUGFS/$chip/$offset
    208	[ -e "$mock_line" ] || fail "missing line $chip:$offset"
    209
    210	# test input active-high
    211	set_mock 1
    212	set_line input active-high
    213	assert_line 1
    214	set_mock 0
    215	assert_line 0
    216	set_mock 1
    217	assert_line 1
    218
    219	if [ "$full_test" ]; then
    220		if [ "$dev_type" != "sysfs" ]; then
    221			# test pulls
    222			set_mock 0
    223			set_line input pull-up
    224			assert_line 1
    225			set_mock 0
    226			assert_line 0
    227
    228			set_mock 1
    229			set_line input pull-down
    230			assert_line 0
    231			set_mock 1
    232			assert_line 1
    233
    234			set_line bias-none
    235		fi
    236
    237		# test input active-low
    238		set_mock 0
    239		set_line active-low
    240		assert_line 1
    241		set_mock 1
    242		assert_line 0
    243		set_mock 0
    244		assert_line 1
    245
    246		# test output active-high
    247		set_mock 1
    248		set_line active-high 0
    249		assert_mock 0
    250		set_line 1
    251		assert_mock 1
    252		set_line 0
    253		assert_mock 0
    254	fi
    255
    256	# test output active-low
    257	set_mock 0
    258	set_line active-low 0
    259	assert_mock 1
    260	set_line 1
    261	assert_mock 0
    262	set_line 0
    263	assert_mock 1
    264
    265	release_line
    266}
    267
    268test_no_line()
    269{
    270	log test_no_line "$*"
    271	[ ! -e "$GPIO_DEBUGFS/$1/$2" ] || fail "unexpected line $1:$2"
    272}
    273
    274# Load the module and check that the expected number of gpiochips, with the
    275# expected number of lines, are created and are functional.
    276#
    277# $1 is the gpio_mockup_ranges parameter for the module
    278# The remaining parameters are the number of lines, n, expected for each of
    279# the gpiochips expected to be created.
    280#
    281# For each gpiochip the fence post lines, 0 and n-1, are tested, and the
    282# line on the far side of the fence post, n, is tested to not exist.
    283#
    284# If the $random flag is set then a random line in the middle of the
    285# gpiochip is tested as well.
    286insmod_test()
    287{
    288	local ranges=
    289	local gc=
    290	local width=
    291
    292	[ "${1:-}" ] || fail "missing ranges"
    293	ranges=$1 ; shift
    294	try_insert_module "gpio_mockup_ranges=$ranges"
    295	log "GPIO $module test with ranges: <$ranges>:"
    296	# e.g. /sys/kernel/debug/gpio-mockup/gpiochip1
    297	gpiochip=$(find "$DEBUGFS/$module/" -name gpiochip* -type d | sort)
    298	for chip in $gpiochip; do
    299		gc=${chip##*/}
    300		[ "${1:-}" ] || fail "unexpected chip - $gc"
    301		width=$1 ; shift
    302		test_line $gc 0
    303		if [ "$random" -a $width -gt 2 ]; then
    304			test_line $gc $((RANDOM % ($width - 2) + 1))
    305		fi
    306		test_line $gc $(($width - 1))
    307		test_no_line $gc $width
    308	done
    309	[ "${1:-}" ] && fail "missing expected chip of width $1"
    310	remove_module || fail "failed to remove module with error $?"
    311}
    312
    313while getopts ":frvt:" opt; do
    314	case $opt in
    315	f)
    316		full_test=true
    317		;;
    318	r)
    319		random=true
    320		;;
    321	t)
    322		dev_type=$OPTARG
    323		;;
    324	v)
    325		verbose=true
    326		;;
    327	*)
    328		usage
    329		;;
    330	esac
    331done
    332shift $((OPTIND - 1))
    333
    334[ "${1:-}" ] && fail "unknown argument '$1'"
    335
    336prerequisite
    337
    338trap 'exit $ksft_fail' SIGTERM SIGINT
    339trap cleanup EXIT
    340
    341case "$dev_type" in
    342sysfs)
    343	source $BASE/gpio-mockup-sysfs.sh
    344	echo "WARNING: gpio sysfs ABI is deprecated."
    345	;;
    346cdev_v1)
    347	echo "WARNING: gpio cdev ABI v1 is deprecated."
    348	uapi_opt="-u1 "
    349	;;
    350cdev)
    351	;;
    352*)
    353	fail "unknown interface type: $dev_type"
    354	;;
    355esac
    356
    357remove_module || fail "can't remove existing $module module"
    358
    359# manual gpio allocation tests fail if a physical chip already exists
    360[ "$full_test" -a -e "/dev/gpiochip0" ] && skip "full tests conflict with gpiochip0"
    361
    362echo "1.  Module load tests"
    363echo "1.1.  dynamic allocation of gpio"
    364insmod_test "-1,32" 32
    365insmod_test "-1,23,-1,32" 23 32
    366insmod_test "-1,23,-1,26,-1,32" 23 26 32
    367if [ "$full_test" ]; then
    368	echo "1.2.  manual allocation of gpio"
    369	insmod_test "0,32" 32
    370	insmod_test "0,32,32,60" 32 28
    371	insmod_test "0,32,40,64,64,96" 32 24 32
    372	echo "1.3.  dynamic and manual allocation of gpio"
    373	insmod_test "-1,32,32,62" 32 30
    374	insmod_test "-1,22,-1,23,0,24,32,64" 22 23 24 32
    375	insmod_test "-1,32,32,60,-1,29" 32 28 29
    376	insmod_test "-1,32,40,64,-1,5" 32 24 5
    377	insmod_test "0,32,32,44,-1,22,-1,31" 32 12 22 31
    378fi
    379echo "2.  Module load error tests"
    380echo "2.1 gpio overflow"
    381# Currently: The max number of gpio(1024) is defined in arm architecture.
    382insmod_test "-1,1024"
    383if [ "$full_test" ]; then
    384	echo "2.2 no lines defined"
    385	insmod_test "0,0"
    386	echo "2.3 ignore range overlap"
    387	insmod_test "0,32,0,1" 32
    388	insmod_test "0,32,1,5" 32
    389	insmod_test "0,32,30,35" 32
    390	insmod_test "0,32,31,32" 32
    391	insmod_test "10,32,30,35" 22
    392	insmod_test "10,32,9,14" 22
    393	insmod_test "0,32,20,21,40,56" 32 16
    394	insmod_test "0,32,32,64,32,40" 32 32
    395	insmod_test "0,32,32,64,36,37" 32 32
    396	insmod_test "0,32,35,64,34,36" 32 29
    397	insmod_test "0,30,35,64,35,45" 30 29
    398	insmod_test "0,32,40,56,30,33" 32 16
    399	insmod_test "0,32,40,56,30,41" 32 16
    400	insmod_test "0,32,40,56,39,45" 32 16
    401fi
    402
    403echo "GPIO $module test PASS"