xref: /spdk/scripts/get-pmr (revision d491e7ea33f0f52fd9abbfc4fbfff6a7f3cf2ec2)
1#!/usr/bin/env bash
2# We simply check if BAR2 is present as that's where PMR or CMB is
3# meant to be located under qemu. If found, print some stats then exit.
4shopt -s nullglob
5
6[[ $(uname -s) == Linux ]] || exit 0
7# Use MSR instead?
8[[ $(< /sys/class/dmi/id/chassis_vendor) == QEMU ]] || exit 0
9
10get_bar() {
11	echo "0x$(setpci -s "$1" "$2.L")"
12}
13
14get_size() {
15	local addr=$1
16	local start end type
17
18	while IFS="- " read -r start end type; do
19		start=0x$start end=0x$end
20		if ((start == addr)) && [[ $type == *"$pci"* ]]; then
21			printf '0x%08x:0x%08x:0x%08x\n' \
22				"$start" "$end" $((end - start + 1))
23			return 0
24		fi
25	done < /proc/iomem
26	echo "unknown/unassigned"
27}
28
29info() {
30	local dev=$1
31
32	local pref loc
33
34	local base_addr2
35	local base_addr4
36
37	local bar local bar2 bar3 bar4 bar5
38	local bar_type2
39
40	pref[0]=non-prefetchable
41	pref[1]=prefetchable
42
43	print_info() {
44		local bar=$1 base_addr=$2 bar_type=$3
45
46		printf '%s:%s:%s:%s:%s:%s\n' \
47			"${nvme##*/}" \
48			"$dev" \
49			"64-bit" \
50			"${pref[bar & 1 << 3 ? 1 : 0]}" \
51			"$(get_size "$base_addr")" \
52			"$bar_type"
53	}
54
55	bar2=$(get_bar "$dev" 0x18)
56	bar3=$(get_bar "$dev" 0x1c)
57	bar4=$(get_bar "$dev" 0x20)
58	bar5=$(get_bar "$dev" 0x24)
59
60	# QEMU uses 64-bit BARs
61	if ((bar2 & 1 << 2)); then
62		bar_type2=pmr
63		if [[ -e $nvme/cmb ]]; then
64			bar_type2=cmb
65		fi
66		base_addr2=$(((bar2 & ~0xf) + (bar3 << 32)))
67		print_info "$bar2" "$base_addr2" "$bar_type2"
68	fi
69	# QEMU uses 64-bit BARs
70	if ((bar4 & 1 << 2)); then
71		base_addr4=$(((bar4 & ~0xf) + (bar5 << 32)))
72		print_info "$bar4" "$base_addr4" pmr
73	fi
74}
75
76for nvme in /sys/class/nvme/nvme*; do
77	pci=$(readlink -f "$nvme/device") pci=${pci##*/}
78	info "$pci"
79done
80