#!/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 curdir=$(readlink -f "$(dirname "$0")") source "$curdir/common.sh" 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\n' \ "$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 cache_pci_bus for pci in ${pci_bus_cache[0x010802]}; do info "$pci" || ((++missing_buf)) done ((missing_buf == 0))