Pali Rohár [Thu, 16 Jun 2022 14:14:56 +0000 (16:14 +0200)]
setpci: Check if standard register on device exist
Some standard registers are available only on device with header type 0,
some only on header type 1, some other only on header type 2 and some on
header type 0 and 1. Add definitions which registers are available on which
header type and add check to access only available registers.
libpci: i386-io-windows.h: Do not define __readeflags() for GCC 4.9+
GCC header file <x86intrin.h> defines static inline function __readeflags()
which calls correct __builtin_ia32_readeflags_XX() builtin.
Header file <x86intrin.h> is included by MinGW-w64's <intrin.h> header file
in new versions of MinGW-w64 and <intrin.h> may be included transitionally
by some other header files automatically.
Defining __readeflags() as both macro and static inline function cause
compile errors.
Fix this compile error by not defining __readeflags() macro and instead
include GCC header file <x86intrin.h>.
Pali Rohár [Sun, 2 Jan 2022 19:51:02 +0000 (20:51 +0100)]
libpci: Add new windows NT sysdbg implementation
NT SysDbg interface allow access to the PCI config space. Only devices on
the first domain are available and only first 256 bytes of the PCI config
space can be accessed. Compared to intel-conf1 access, this API is race
free as NT kernel serialize access to PCI I/O ports. This NT SysDbg API is
used by the !pci command of 32-bit WinDbg kernel debugger for displaying
PCI config space. Debug privilege is required to use this NT interface.
Pali Rohár [Thu, 10 Mar 2022 20:38:18 +0000 (21:38 +0100)]
lspci: Fix detection of memory space bar
intel-conf1 backend never show AtomicOpsCap: capabilities despite the fact
that is successfuly detects memory bars on device. But other backends show
this capability.
Error is in device_has_memory_space_bar() function, it expects that ->size
member is always filled. But size of the BAR is not available in PCI config
space and therefore raw backends cannot retrieve it.
Probably intention of the non-zero check was to verify that base address
was filled with non-zero size. So either base address is non-zero or length
is non-zero. Adjust check.
Pali Rohár [Sat, 5 Mar 2022 23:22:03 +0000 (00:22 +0100)]
lspci: Fix detection of virtual regions
There are many issues with detection of virtual regions.
1. Variable for detecting virtual region is global and if one BAR is marked
as virtual then all remaining BARs are treated as virtual too as this
variable is not reset at next loop iteration.
2. Lower address is read from flg variable which on backends without config
space is initialized from PCI flags, not from base address.
3. Code mixes at many places PCI flags, resource flags, PCI addresses and
resource addresses. Some backends reports PCI flags in PCI addresses,
some not.
Cleanup mess of ->base_addr, ->flags and PCI_BASE_ADDRESS. If backend
provides ->flags value (test via PCI_FILL_IO_FLAGS) then use it instead of
reading flags from pci config space.
Fix reading of PCI hw_lower and hw_upper addresses. If PCI_BASE_ADDRESS
reports different type than what is stored in base_addr then completely
ignore hw_lower and hw_upper values. It means that backend either provide
fiction information or provide resources in different order as they are
stored in hardware. In any case values from HW cannot be used as they do
not match values reported by backend.
And in the last case, make virtual variable local to the current BAR
processing and do not increment loop variable i when 64-bit MEM type is
detected via data from config space. It could miss some virtual resource
reported by the backend.
This change fixes displaying resources of PCI devices which have some
unset/unused BARs in the middle and OS reports virtual regions and
remaining regions without holes. E.g. HW BARs 0, 2, 5 are used and OS
reports base_addr 0, 1, 2, 3.
Pali Rohár [Sun, 27 Feb 2022 00:57:38 +0000 (01:57 +0100)]
libpci: Always call pci_set_name_list_path() in pci_init_name_list_path()
If pci_init_name_list_path() does not call pci_set_name_list_path() then
a->id_file_name variable is NULL and pci_load_name_list() would crash as it
tries to do fopen(NULL, ...).
If libpci was configured at compile time to use current executable path for
locating pci.ids file and it is not possible to determinate current
executable path then call pci_set_name_list_path() with just filename
without path (this would fallback to the current working directory).
Pali Rohár [Tue, 28 Dec 2021 19:29:21 +0000 (20:29 +0100)]
lspci: Do not access config space when it is emulated
Emulated config space contains only few information so it could look like
some valid config space. libpci compose emulated config space either from
struct pci_dev or put some fake information (when struct pci_dev does not
have them).
To prevent showing to user fake/bogus information about PCI devices, show
only information which are directly stored in struct pci_dev when emulated
config space is used.
Do it via setting lspci's header type to invalid value (byte)-1, so lspci
code will handle device as unknown without trying to interpret values
config space. This header type is set only in lspci, not in libpci, so
other libpci applications would see valid config space.
lspci users are probably not interested in fake information provided by
libpci just for purpose to export syntactically valid config space.
Information stored in struct pci_dev are the correct one (or rather what OS
things that is correct).
Pali Rohár [Fri, 31 Dec 2021 16:49:00 +0000 (17:49 +0100)]
libpci: Add windows cfgmgr32 implementation
Access via cfgmgr32.dll library allows to list PCI devices and retrieve
their basic properties and system resource configuration. Access is
available to all users and should not require special privileges, access
tokens, rights or permissions.
This cfgmgr32.dll library does not provide access to PCI config space.
Pali Rohár [Sun, 2 Jan 2022 12:33:12 +0000 (13:33 +0100)]
libpci: Implement virtual config space for provides without access to config space
Add a new pci_dev member no_config_access which signals that there is no
access to config space for particular device. Reading operation in this
case should return data from emulated virtual config space. For provides
there is a new helper function pci_generic_read() which emulates config
spaces based on struct pci_dev members.
Pali Rohár [Sun, 27 Feb 2022 15:06:59 +0000 (16:06 +0100)]
lspci: Show information also for devices with unknown header type
lspci sees header type with 0x7f value in case config space is not
accessible. It may be because of permission issues or missing backend
(e.g. on Windows) or because device itself does not respond to config
cycles and config space is inaccessible.
Inaccessible config space is common scenario for switchable PCIe GPU
cards. Some Nvidia and also some AMD cards when sleep then lspci sees
all-ones in their config space. But kernel has registered those cards and
some of their properties are cached ans available via sysfs or procfs (from
time when card was awake).
Currently lspci shows error message "Unknown header type 7f" and does not
parse any value neither from config space nor from sysfs backend.
So try to show at least information which kernel provided into libpci
struct pci_dev.
Set unknown values to zeros (instead of all-ones which are returned from
config space) and add a new function show_htype_unknown() for showing
additional information in case header type is unknown.
This change will also help new windows backend which has only emulated
config space and therefore valid data only in struct pci_dev.
Jonathan Cameron [Thu, 10 Feb 2022 16:19:45 +0000 (16:19 +0000)]
pciutils: Add decode support for Data Object Exchange Extended Capability
PCI Data Object Exchange [1] provides a mailbox interface used as the
transport for various protocols defined by PCI-SIG and others. Make the
limited information in config space available. Note the Read/Write
Mailbox registers themselves are not currently parsed as the usefulness
of accessing one dword of a protocol is probably limited.
In future, operating systems may provide means to safely query the
supported protocols, but those have not yet been defined.
Example output:
Capabilities: [100 v1] Data Object Exchange
DOECap: IntSup+
Interrupt Message Number 001
DOECtl: IntEn+
DOESta: Busy- IntSta- Error- ObjectReady+
[1] PCIe r6.0, sections 6.30 and 7.9.24
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Pali Rohár [Fri, 25 Feb 2022 18:12:09 +0000 (19:12 +0100)]
lspci: Decode PCIe 6.0 Slot Power Limit values
When the Slot Power Limit Scale field equals 00b (1.0x) and Slot
Power Limit Value exceeds EFh, the following alternative encodings
are used:
F0h > 239 W and ≤ 250 W Slot Power Limit
F1h > 250 W and ≤ 275 W Slot Power Limit
F2h > 275 W and ≤ 300 W Slot Power Limit
F3h > 300 W and ≤ 325 W Slot Power Limit
F4h > 325 W and ≤ 350 W Slot Power Limit
F5h > 350 W and ≤ 375 W Slot Power Limit
F6h > 375 W and ≤ 400 W Slot Power Limit
F7h > 400 W and ≤ 425 W Slot Power Limit
F8h > 425 W and ≤ 450 W Slot Power Limit
F9h > 450 W and ≤ 475 W Slot Power Limit
FAh > 475 W and ≤ 500 W Slot Power Limit
FBh > 500 W and ≤ 525 W Slot Power Limit
FCh > 525 W and ≤ 550 W Slot Power Limit
FDh > 550 W and ≤ 575 W Slot Power Limit
FEh > 575 W and ≤ 600 W Slot Power Limit
FFh Reserved for Slot Power Limit Values above 600 W
Previously only values F0h, F1h and F2h were covered.
Pali Rohár [Mon, 27 Dec 2021 13:04:59 +0000 (14:04 +0100)]
libpci: Define new string property PCI_FILL_DRIVER
This change extends libpci library and allows providers to fill
PCI_FILL_DRIVER via native system APIs. As it is string property there is
no need to increase ABI version.
Pali Rohár [Fri, 31 Dec 2021 13:39:51 +0000 (14:39 +0100)]
lspci: Do not show -[00]- bus in tree output
Secondary or subordinate bus cannot be zero. Zero value could indicate
either invalid secondary bus value or the fact that secondary bus value was
not filled or indicates non-compliant PCI-to-PCI bridge. This change makes
tree output better readable when bus numbers are not known or not provided.
Pali Rohár [Tue, 28 Dec 2021 19:14:47 +0000 (20:14 +0100)]
lspci: Build tree based on PCI_FILL_PARENT information
Topology reported by system (libpci provider) may be different from
topology built based on primary/secondary/subordinate numbers from PCI
bridges by lspci.
This happens for example when some non-compliant PCI-to-PCI bridge
with Type 0 header (e.g. Marvell one) is available in the system.
So add additional edges reported by libpci when building tree in lspci.
Pali Rohár [Mon, 20 Dec 2021 21:39:42 +0000 (22:39 +0100)]
lspci: Retrieve prog if, subsystem ids and revision id via libpci
Use pci_fill_info with CLASS_EXT and SUBSYS to fill this information.
lspci in some places reads class from what libpci provider fills in
dev->device_class and in some other places it reads directly from config
space. In dev->device_class is stored class possible different class as in
config space (e.g. if kernel is fixing class because device has bogus
information stored in config space).
With this change is class always read from dev->device_class which reflects
and respects lspci -b option (Bus-centric view). Same applies for subsystem
ids and revision id (note that prog if is part of class).
Pali Rohár [Mon, 20 Dec 2021 21:07:28 +0000 (22:07 +0100)]
libpci: Add new options for pci_fill_info: CLASS_EXT and SUBSYS
This change extends libpci library and allows providers to fill these
informations (Programming interface, Revision id and Subsystem ids) via
native system APIs, which sometimes may differs from what is stored in PCI
config space.
Programming interface is part of 24-bit Device Class number but apparently
libpci exports only high 16-bit of this number via device_class member.
Pali Rohár [Sat, 20 Nov 2021 14:13:20 +0000 (15:13 +0100)]
lspci: Use PCI_FILL_BRIDGE_BASES to detect if range behind bridge is disabled or unsupported
Show resources behind bridge as reported by PCI_FILL_BRIDGE_BASES.
I/O or Prefetchable memory behind bridge is unsupported by bridge if both
base and limit bridge registers are read-only and returns zero. So if base
and limit registers returns zero (which is valid enabled range) and kernel
reports that particular resource is disabled it means that resource is
unsupported. Both I/O or Prefetchable memory resources are only optional.
Pali Rohár [Thu, 10 Feb 2022 12:33:46 +0000 (13:33 +0100)]
libpci: i386-io-windows.h: Fix comment about CRTDLL
There is no 64-bit version of CRTDLL library. MinGW-w64 provided bogus
64-bit import library for non-existent runtime DLL library, which was
recently deleted.
Pali Rohár [Sun, 26 Dec 2021 21:12:00 +0000 (22:12 +0100)]
lspci: Define PCI_U64_FMT_U format for printing u64
Windows CRTDLL and MSVCRT runtime system libraries do not support %llu
format string in printf. They support only %I64u format string. Fix this
problem by providing PCI_U64_FMT_U macro in the same way as existing
PCI_U64_FMT_X macro (for %llx).
For C99 systems this PCI_U64_FMT_U macro is defined to C99 PRIu64 constant.
This change fixes printing unsigned decimal 64-bit numbers by lspci on
Window systems independently of used compiler (MinGW or MSVC).
Pali Rohár [Sun, 26 Dec 2021 21:11:51 +0000 (22:11 +0100)]
lspci: Replace unsigned long long type by u64 and %llx format by PCI_U64_FMT_X
pciutils already provides and uses u64 type together with PCI_U64_FMT_X
format macro for printing hex value of this type. So use u64 and
PCI_U64_FMT_X also on other few remaining places.
This change fixes printing hexadecimal 64-bit numbers by lspci on Window
systems independently of used compiler (MinGW or MSVC).
Pali Rohár [Sun, 26 Dec 2021 21:11:30 +0000 (22:11 +0100)]
libpci: For PCI_OS_WINDOWS include windows.h instead of windef.h
According to Win32 API guidelines applications should include <windows.h>
instead of <windef.h>. This change fixes compilation under MSVC as MSVC
<windef.h> header file expects that some other Win32 header files from
<window.h> are already included.
Pali Rohár [Sun, 26 Dec 2021 21:11:22 +0000 (22:11 +0100)]
libpci: For PCI_OS_WINDOWS define strncasecmp as alias for _strnicmp
CRTDLL, MSVCRT and UCRT runtimes provides strncasecmp()-like functionality
in _strnicmp() function. As opposite of strcasecmp() for which there are
_stricmp() and _strcmpi() variants, for strncasecmp() there is only
_strnicmp() function.
Without this change linking final setpci.exe executable undef MSVC fails.
Pali Rohár [Sun, 26 Dec 2021 23:47:53 +0000 (00:47 +0100)]
libpci: For MSVC < 19.00 define snprintf outside of endian section
snprintf() macro is not endian specific and therefore should be declared
outside of the endian section.
This also fixes snprintf() function for new MinGW-w64 toolchains where
snprintf() is defined as wrapper around _snprintf() which do not return
negative value on overflow. libpci would call MinGW-w64 patched snprintf()
function and not broken system function _snprintf().
Martin Mares [Fri, 21 Jan 2022 13:09:16 +0000 (14:09 +0100)]
pci.h: The error callback is now declared with PCI_NONRET
Users of the repeatedly complain that the library crashes, which is
usually caused by providing an error hook which returns to the library.
Let's try warning them more explicitly.
i386-ports.c: In function ‘conf12_setup_io’:
i386-io-windows.h:1021: warning: ‘old_token’ may be used uninitialized in this function
i386-io-windows.h:1021: note: ‘old_token’ was declared here
It is always properly initialized when accessed, just gcc compiler does not see it.
Pali Rohár [Sun, 26 Dec 2021 17:18:59 +0000 (18:18 +0100)]
lib: Fix definition of strcasecmp() for PCI_OS_WINDOWS
UCRT, MSVCRT and CRTDLL runtime libraries provides only _strcmpi()
function and not strcmpi().
MinGW32 has static libraries libcoldname.a and libmoldname.a which provides
strcmpi() function (as link-time redirect to _strcmpi()). libcoldname.a is
automatically linked when compiling for CRTDLL runtime and libmoldname.a
for MSVCRT runtime.
MinGW-w64 has only libmoldname.a library with strcmpi() function and it is
linked to final executable only when compiling for MSVCRT runtime.
when linking with MSVCRT.
To prevent dependency on particular linking configuration and MinGW
toolchain, use set strcasecmp() as alias to _strcmpi() function which is
provided by any runtime library.