Spdk/scripts/get-pmr
Michal Berger 843606d7c6 scripts/get-pmr: Adjust BAR2 lookup
Under latest QEMU, BAR2 is exclusively dedicated to CMB, so
reflect that.

Also, add paranoid check for the header type to make sure we
use proper offsets along the way.

Signed-off-by: Michal Berger <michal.berger@intel.com>
Change-Id: I75ecfa5bf03861aedfc7bd064cbad60522b8bf0e
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16774
Reviewed-by: Konrad Sztyber <konrad.sztyber@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
2023-02-24 12:52:04 +00:00

94 lines
2.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (C) 2021 Intel Corporation
# All rights reserved.
# We simply check if BAR2, BAR4 are present as that's where PMR or CMB is
# meant to be located under qemu. If found, print some stats then exit.
shopt -s nullglob
[[ $(uname -s) == Linux ]] || exit 0
# Use MSR instead?
[[ $(< /sys/class/dmi/id/chassis_vendor) == QEMU ]] || exit 0
get_bar() {
echo "0x$(setpci -s "$1" "$2.${3:-L}")"
}
get_size() {
local addr=$1
local start end type
while IFS="- " read -r start end type; do
start=0x$start end=0x$end
if ((start == addr)) && [[ $type == *"$pci"* ]]; then
printf '0x%08x:0x%08x:0x%08x\n' \
"$start" "$end" $((end - start + 1))
return 0
fi
done < /proc/iomem
echo "unknown/unassigned"
}
info() {
local dev=$1
local pref
local head
local base_addr2
local base_addr4
local bar2 bar3 bar4 bar5
pref[0]=non-prefetchable
pref[1]=prefetchable
print_info() {
local bar=$1 base_addr=$2 bar_type=$3
printf '%s:%s:%s:%s:%s:%s\n' \
"${nvme##*/}" \
"$dev" \
"64-bit" \
"${pref[bar & 1 << 3 ? 1 : 0]}" \
"$(get_size "$base_addr")" \
"$bar_type"
}
head=$(get_bar "$dev" 0x0e B)
bar2=$(get_bar "$dev" 0x18)
bar3=$(get_bar "$dev" 0x1c)
bar4=$(get_bar "$dev" 0x20)
bar5=$(get_bar "$dev" 0x24)
if ((head != 0)); then
echo "Wrong haeder type under $dev" >&2
return 1
fi
# QEMU uses 64-bit BARs. If there is no CMB or PMR present, report
# that to the user and signal failure.
if ((!(bar2 & 1 << 2) && !(bar4 & 1 << 2))); then
echo "No CMB|PMR present under $dev" >&2
return 1
fi
if ((bar2 & 1 << 2)); then
base_addr2=$(((bar2 & ~0xf) + (bar3 << 32)))
print_info "$bar2" "$base_addr2" cmb
fi
if ((bar4 & 1 << 2)); then
base_addr4=$(((bar4 & ~0xf) + (bar5 << 32)))
print_info "$bar4" "$base_addr4" pmr
fi
}
missing_buf=0
for nvme in /sys/class/nvme/nvme*; do
pci=$(readlink -f "$nvme/device") pci=${pci##*/}
info "$pci" || ((++missing_buf))
done
((missing_buf == 0))