From b7b37c359c0c6edee6903313b2488ac9af28441a Mon Sep 17 00:00:00 2001 From: Jan M Michalski Date: Thu, 19 Nov 2020 12:05:53 -0500 Subject: [PATCH] common: tools: ddio.sh --- tools/ddio.sh | 364 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 364 insertions(+) create mode 100755 tools/ddio.sh diff --git a/tools/ddio.sh b/tools/ddio.sh new file mode 100755 index 0000000000..84e8733bbf --- /dev/null +++ b/tools/ddio.sh @@ -0,0 +1,364 @@ +#!/usr/bin/env bash +# +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2020, Intel Corporation +# + +# +# ddio -- query and toggle DDIO state per PCIe root port (EXPERIMENTAL) +# + +# +# usage -- print usage message and exit +# +usage() +{ + [ "$1" ] && echo Error: $1 + cat >&2 <]:]]:][][.[]] + For details please see setpci(8). + +-s DDIO-state desired DDIO state, either enable or disable + Note: 'enable' is an equivalent of restoring default registers values + For details please use -e. + +-q query DDIO state + exit code 1 means DDIO is enabled (on) + exit code 0 means DDIO is disabled ('off') + +-v be verbose + +-h print this help message + +-e print an excerpt from the documentation + describing a principle of operation of this tool + +EOF + exit 1 +} + + +# +# excerpt -- print a principle of operation and exit +# +excerpt() +{ + cat <> $DDIO_LOG +} + + +# +# _register_get -- read a register value +# +function _register_get() +{ + register="$1" + + valhex=$(setpci -s "$device" "$register") + valdec=$((16#$valhex)) + + _log "setpci -s $device $register" + _log "=$valhex" + + echo $valdec +} + + +# +# _register_set -- write a register value +# +function _register_set() +{ + register="$1" + valdec="$2" + + valhex=`printf "%x\n" $valdec` + out=$(setpci -s $device $register=$valhex 2>&1) + + _log "setpci -s $device $register=$valhex" + _log "=$?" + _log "$out" +} + + +# +# _bit_git -- get bit from a value +# +function _bit_get() { + valdec="$1" + bit="$2" + + valdec=$(($valdec & $bit)) + echo "$valdec" +} + + +# +# _bit_enable -- enable bit in a value +# +function _bit_enable() { + valdec="$1" + bit="$2" + + valdec=$(($valdec | $bit)) + echo "$valdec" +} + + +# +# _bit_disable -- disable bit in a value +# +function _bit_disable() { + valdec="$1" + bit="$2" + + valdec=$(($valdec & ~($bit))) + echo "$valdec" +} + + +# +# _require_device -- verify the provided device is valid +# +function _require_device() +{ + [ -z "$device" ] && usage "device required: $device" + setpci -s "$device" "$perfctrlsts_0_reg" 2>&1 > /dev/null + [ "$?" -ne "0" ] && usage "invalid device: $device" +} + + +# +# _require_root -- verify the script is run with root privileges +# +function _require_root() +{ + [ "$EUID" -ne "0" ] && usage "root privileges required" +} + +# +# ddio_query -- read DDIO state +# +function ddio_query() +{ + _require_device + _require_root + + # read registers value + pcs0=$(_register_get "$perfctrlsts_0_reg") + pcs1=$(_register_get "$perfctrlsts_1_reg") + + # read meaningful bits from the registers + use_alloacting_flow_wr=$(_bit_get "$pcs0" "$use_alloacting_flow_wr_bit") + nosnoopopwren=$(_bit_get "$pcs0" "$nosnoopopwren_bit") + tphdis=$(_bit_get "$pcs1" "$tphdis_bit") + + ddio_on="DDIO is enabled" + ddio_off="DDIO is disabled" + [ "$use_alloacting_flow_wr" -ne "0" ] && { + [ "$verbose" -eq "1" ] && echo "$ddio_on: use_allocating_flow_wr != 0" 1>&2 + return 1 + } + [ "$nosnoopopwren" -ne "0" ] && { + [ "$verbose" -eq "1" ] && echo "$ddio_on: nosnoopopwren != 0" 1>&2 + return 1 + } + [ "$tphdis" -eq "0" ] && { + [ "$verbose" -eq "1" ] && echo "$ddio_on: TPHDIS == 0" 1>&2 + return 1 + } + + [ "$verbose" -eq "1" ] && echo "$ddio_off" 1>&2 + return 0 +} + + +# +# _ddio_set_disable -- turn off DDIO +# +function _ddio_set_disable() +{ + [ "$use_alloacting_flow_wr" -ne "0" ] && { + [ "$verbose" -eq "1" ] && echo "set use_allocating_flow_wr = 0" 1>&2 + pcs0=$(_bit_disable "$pcs0" "$use_alloacting_flow_wr_bit") + pcs0_mod=1 + } + [ "$nosnoopopwren" -ne "0" ] && { + [ "$verbose" -eq "1" ] && echo "set nosnoopopwren = 0" 1>&2 + pcs0=$(_bit_disable "$pcs0" "$nosnoopopwren_bit") + pcs0_mod=1 + } + [ "$tphdis" -eq "0" ] && { + [ "$verbose" -eq "1" ] && echo "set TPHDIS = 1" 1>&2 + pcs1=$(_bit_enable "$pcs1" "$tphdis_bit") + pcs1_mod=1 + } +} + + +# +# _ddio_set_enable -- turn on DDIO (restore defaults) +# +function _ddio_set_enable() +{ + def="(default)" + [ "$use_alloacting_flow_wr" -eq "0" ] && { + [ "$verbose" -eq "1" ] && echo "set use_allocating_flow_wr = 1 $def" 1>&2 + pcs0=$(_bit_enable "$pcs0" "$use_alloacting_flow_wr_bit") + pcs0_mod=1 + } + [ "$nosnoopopwren" -ne "0" ] && { + [ "$verbose" -eq "1" ] && echo "set nosnoopopwren = 0 $def" 1>&2 + pcs0=$(_bit_disable "$pcs0" "$nosnoopopwren_bit") + pcs0_mod=1 + } + [ "$tphdis" -ne "0" ] && { + [ "$verbose" -eq "1" ] && echo "set TPHDIS = 0" 1>&2 + pcs1=$(_bit_disable "$pcs1" "$tphdis_bit") + pcs1_mod=1 + } +} + + +# +# ddio_set -- write DDIO state +# +function ddio_set() +{ + _require_device + _require_root + + # read current registers value + pcs0=$(_register_get "$perfctrlsts_0_reg") + pcs1=$(_register_get "$perfctrlsts_1_reg") + + # read meaningful bits from the registers + use_alloacting_flow_wr=$(_bit_get "$pcs0" "$use_alloacting_flow_wr_bit") + nosnoopopwren=$(_bit_get "$pcs0" "$nosnoopopwren_bit") + tphdis=$(_bit_get "$pcs1" "$tphdis_bit") + + # setup the registers modification indicators + pcs0_mod=0 + pcs1_mod=0 + + _ddio_set_$ddio + + # write the new registers value + [ "$pcs0_mod" -eq "1" ] && _register_set "$perfctrlsts_0_reg" "$pcs0" + [ "$pcs1_mod" -eq "1" ] && _register_set "$perfctrlsts_1_reg" "$pcs1" +} + + +# +# defaults +# +device= +op=usage +ddio= +verbose=0 + + +# +# command-line argument processing... +# +args=`getopt d:s:qvhe $*` +[ $? != 0 ] && usage +set -- $args +for arg +do + case "$arg" + in + -d) + device="$2" + shift 2 + ;; + -s) + op="ddio_set" + case "$2" + in + enable|disable) + ;; + *) + usage "invalid DDIO-state value '$2'" + ;; + esac + ddio="$2" + shift 2 + ;; + -q) + op="ddio_query" + shift + ;; + -v) + verbose=1 + shift + ;; + -h) + usage + ;; + -e) + excerpt + ;; + esac +done + + +# +# run a required operation +# +$op +