#!/usr/bin/env bash # We simply check if BAR2 is present as that's where PMR or CMB is # meant to be located under qemu. If found, print some stats then exit. [[ $(uname -s) == Linux ]] || exit 0 # Use MSR instead? [[ $(< /sys/class/dmi/id/chassis_vendor) == QEMU ]] || exit 0 get_bar2() { echo "0x$(setpci -s "$1" 0x18.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" } info() { local bar=$1 local pref loc pref[0]=non-prefetchable pref[1]=prefetchable loc[0]=32-bit loc[1]="<1MiB" loc[2]=64-bit echo "${loc[(bar >> 1) & 0x3]}:${pref[bar & 1 << 3 ? 1 : 0]}:$(get_size $((bar & ~0xf)))" } for nvme in /sys/class/nvme/nvme*; do pci=$(readlink -f "$nvme/device") pci=${pci##*/} bar2=$(get_bar2 "$pci") || continue ((bar2 != 0x0)) || continue bar=pmr [[ -e $nvme/cmb ]] && bar=cmb echo "${nvme##*/}:$pci:$(info "$bar2"):$bar" done