xref: /spdk/scripts/get-pmr (revision 34edd9f1bf5fda4c987f4500ddc3c9f50be32e7d)
1#!/usr/bin/env bash
2#  SPDX-License-Identifier: BSD-3-Clause
3#  Copyright (C) 2021 Intel Corporation
4#  All rights reserved.
5
6# We simply check if BAR2, BAR4 are present as that's where PMR or CMB is
7# meant to be located under qemu. If found, print some stats then exit.
8shopt -s nullglob
9
10[[ $(uname -s) == Linux ]] || exit 0
11# Use MSR instead?
12[[ $(< /sys/class/dmi/id/chassis_vendor) == QEMU ]] || exit 0
13
14curdir=$(readlink -f "$(dirname "$0")")
15source "$curdir/common.sh"
16
17get_bar() {
18	echo "0x$(setpci -s "$1" "$2.${3:-L}")"
19}
20
21get_size() {
22	local addr=$1
23	local start end type
24
25	while IFS="- " read -r start end type; do
26		start=0x$start end=0x$end
27		if ((start == addr)) && [[ $type == *"$pci"* ]]; then
28			printf '0x%08x:0x%08x:0x%08x\n' \
29				"$start" "$end" $((end - start + 1))
30			return 0
31		fi
32	done < /proc/iomem
33	echo "unknown/unassigned"
34}
35
36info() {
37	local dev=$1
38
39	local pref
40	local head
41
42	local base_addr2
43	local base_addr4
44
45	local bar2 bar3 bar4 bar5
46
47	pref[0]=non-prefetchable
48	pref[1]=prefetchable
49
50	print_info() {
51		local bar=$1 base_addr=$2 bar_type=$3
52
53		printf '%s:%s:%s:%s:%s\n' \
54			"$dev" \
55			"64-bit" \
56			"${pref[bar & 1 << 3 ? 1 : 0]}" \
57			"$(get_size "$base_addr")" \
58			"$bar_type"
59	}
60
61	head=$(get_bar "$dev" 0x0e B)
62	bar2=$(get_bar "$dev" 0x18)
63	bar3=$(get_bar "$dev" 0x1c)
64	bar4=$(get_bar "$dev" 0x20)
65	bar5=$(get_bar "$dev" 0x24)
66
67	if ((head != 0)); then
68		echo "Wrong header type under $dev" >&2
69		return 1
70	fi
71
72	# QEMU uses 64-bit BARs. If there is no CMB or PMR present, report
73	# that to the user and signal failure.
74	if ((!(bar2 & 1 << 2) && !(bar4 & 1 << 2))); then
75		echo "No CMB|PMR present under $dev" >&2
76		return 1
77	fi
78
79	if ((bar2 & 1 << 2)); then
80		base_addr2=$(((bar2 & ~0xf) + (bar3 << 32)))
81		print_info "$bar2" "$base_addr2" cmb
82	fi
83
84	if ((bar4 & 1 << 2)); then
85		base_addr4=$(((bar4 & ~0xf) + (bar5 << 32)))
86		print_info "$bar4" "$base_addr4" pmr
87	fi
88}
89
90missing_buf=0
91cache_pci_bus
92
93for pci in ${pci_bus_cache[0x010802]}; do
94	info "$pci" || ((++missing_buf))
95done
96((missing_buf == 0))
97