run: extend pci test to show more information

Add some more vendors and classcode decoding. Additionally, walk PCI cap
space of each device and decode some of the types.

Issue #3928
This commit is contained in:
Alexander Boettcher 2020-09-20 16:47:40 +02:00 committed by Christian Helmuth
parent 194305a8bb
commit 95c2e5beb3

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2008-2017 Genode Labs GmbH
* Copyright (C) 2008-2020 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
@ -19,8 +19,83 @@
using namespace Genode;
enum { INTEL_VENDOR_ID = 0x8086 };
enum { AMD_VENDOR_ID = 0x1022, INTEL_VENDOR_ID = 0x8086 };
enum {
CLASS_CODE_SATA = 0x106,
CLASS_CODE_ETHERNET = 0x200,
CLASS_CODE_VGA = 0x300,
CLASS_CODE_HOST_BRIDGE = 0x600,
CLASS_CODE_HOST_ISA = 0x601,
CLASS_CODE_PCI_PCI_BRIDGE = 0x604,
CLASS_CODE_IOMMU = 0x806,
CLASS_CODE_USB = 0xc03,
CLASS_CODE_SMBUS = 0xc05,
};
enum {
USB_UHCI = 0x00,
USB_OHCI = 0x10,
USB_EHCI = 0x20,
USB_XHCI = 0x30
};
enum {
DEVICE_AMD_HUDSON2_SMBUS = 0x780b,
};
enum {
CAP_MSI = 0x05,
CAP_HT = 0x08,
CAP_SECDEV = 0x0f,
CAP_PCI_E = 0x10,
CAP_MSIX = 0x11
};
enum {
EXT_CAP_ERRREP = 0x01, /* advanced error reporting */
EXT_CAP_DEVSNR = 0x03, /* device serial number */
EXT_CAP_VENDOR = 0x0b, /* vendor specific */
EXT_CAP_ACSERV = 0x0d, /* access control service */
};
typedef Platform::Device::Access_size Size;
static void dump_extended_pci_caps(Platform::Device_client &device)
{
unsigned cap = 0x100;
unsigned max_caps = (0x1000 - cap) / 8;
String<128> cap_string { };
while (max_caps) {
unsigned const val = device.config_read(cap, Size::ACCESS_32BIT);
switch (val & 0xffff) {
case 0:
break;
case EXT_CAP_ERRREP:
cap_string = String<128>(cap_string, " ERR_REP");
break;
case EXT_CAP_DEVSNR:
cap_string = String<128>(cap_string, " DEV_SNR");
break;
case EXT_CAP_VENDOR:
cap_string = String<128>(cap_string, " VENDOR");
break;
case EXT_CAP_ACSERV:
cap_string = String<128>(cap_string, " ACS");
break;
default:
cap_string = String<128>(cap_string, " ", Hex(val & 0xffff));
};
max_caps --;
cap = (val >> 20) & 0xffc;
if (cap <= 0x100 || cap >= 0x1000 - 4 /* size of 32Bit */)
break;
}
if (cap_string.valid())
log(" ECAP:", cap_string);
}
/**
* Print device information
@ -36,17 +111,48 @@ static void print_device_info(Platform::Device_capability device_cap)
unsigned char bus = 0, dev = 0, fun = 0;
device.bus_address(&bus, &dev, &fun);
unsigned short vendor_id = device.vendor_id();
unsigned short device_id = device.device_id();
unsigned class_code = device.class_code() >> 8;
unsigned short const vendor_id = device.vendor_id();
unsigned short const device_id = device.device_id();
unsigned const class_code = device.class_code() >> 8;
unsigned char const revision = device.config_read(0x8, Size::ACCESS_8BIT);
unsigned char const prog_if = device.config_read(0x9, Size::ACCESS_8BIT);
unsigned const pci_cmd = device.config_read(0x4, Size::ACCESS_16BIT);
log(Hex(bus, Hex::OMIT_PREFIX), ":",
Hex(dev, Hex::OMIT_PREFIX), ".",
Hex(fun, Hex::OMIT_PREFIX), " "
"class=", Hex(class_code), " "
"vendor=", Hex(vendor_id), " ",
(vendor_id == INTEL_VENDOR_ID ? "(Intel)" : "(unknown)"),
" device=", Hex(device_id));
"class=", Hex(class_code), " ",
(class_code == CLASS_CODE_VGA) ? "(VGA)" :
(class_code == CLASS_CODE_HOST_BRIDGE) ? "(bridge host)" :
(class_code == CLASS_CODE_HOST_ISA) ? "(bridge ISA)" :
(class_code == CLASS_CODE_PCI_PCI_BRIDGE) ? "(bridge PCI)" :
(class_code == CLASS_CODE_IOMMU) ? "(IOMMU)" :
(class_code == CLASS_CODE_USB) ? "(USB)" :
(class_code == CLASS_CODE_SMBUS) ? "(SMBUS)" :
(class_code == CLASS_CODE_SATA) ? "(SATA)" : "",
(class_code == CLASS_CODE_ETHERNET) ? "(Ethernet)" : "",
" vendor=", Hex(vendor_id), " ",
((vendor_id == INTEL_VENDOR_ID) ? "(Intel)" :
(vendor_id == AMD_VENDOR_ID) ? "(AMD)" : "(unknown)"),
" device=", Hex(device_id),
" prog_if=", Genode::Hex(prog_if),
(class_code != CLASS_CODE_USB) ? "" :
(prog_if == USB_UHCI) ? "(UHCI)" :
(prog_if == USB_OHCI) ? "(OHCI)" :
(prog_if == USB_EHCI) ? "(EHCI)" :
(prog_if == USB_XHCI) ? "(XHCI)" : "",
" revision=", Genode::Hex(revision),
" pci_cmd=", Genode::Hex(pci_cmd));
if (vendor_id == AMD_VENDOR_ID && device_id == DEVICE_AMD_HUDSON2_SMBUS) {
if (revision >= 0x11 && revision <= 0x14)
log("chipset: AMD HUDSON2");
else if (revision >= 0x15 && revision <= 0x18)
log("chipset: AMD BOLTON");
else if (revision >= 0x39 && revision <= 0x3a)
log("chipset: AMD ANGTZE");
}
for (int resource_id = 0; resource_id < 6; resource_id++) {
@ -54,13 +160,49 @@ static void print_device_info(Platform::Device_capability device_cap)
Resource const resource = device.resource(resource_id);
if (resource.type() != Resource::INVALID)
if (resource.type() != Resource::INVALID) {
log(" Resource ", resource_id, " "
"(", (resource.type() == Resource::IO ? "I/O" : "MEM"), "): "
"base=", Genode::Hex(resource.base()), " "
"size=", Genode::Hex(resource.size()), " ",
(resource.prefetchable() ? "prefetchable" : ""));
"base=", Genode::Hex(resource.base()), " "
"size=", Genode::Hex(resource.size()), " ",
(resource.prefetchable() ? "prefetchable" : "")
);
}
}
unsigned cap = device.config_read(0x34, Size::ACCESS_8BIT);
if (cap) {
String<128> cap_string { };
for (Genode::uint32_t val = 0; cap; cap = (val >> 8) & 0xff) {
val = device.config_read(cap, Size::ACCESS_32BIT);
unsigned const type = val & 0xff;
switch (type) {
case CAP_MSI: {
uint16_t msi_val = device.config_read(cap + 2, Size::ACCESS_16BIT);
if (msi_val & 0x80)
cap_string = String<128>(cap_string, " MSI-64");
else
cap_string = String<128>(cap_string, " MSI");
break;
}
case CAP_HT: cap_string = String<128>(cap_string, " HYPERTRANSPORT"); break;
case CAP_MSIX: cap_string = String<128>(cap_string, " MSI-X"); break;
case CAP_PCI_E: cap_string = String<128>(cap_string, " PCI-E"); break;
case CAP_SECDEV: cap_string = String<128>(cap_string, " SECURE-DEVICE"); break;
default:
cap_string = String<128>(cap_string, " ", Hex(type));
}
if (type == CAP_PCI_E) {
uint16_t flags = device.config_read(cap + 2, Size::ACCESS_16BIT);
uint8_t type = (flags >> 4) & 0xf;
cap_string = String<128>(cap_string, "(T", Hex(type, Hex::OMIT_PREFIX), ")");
}
}
log(" CAP:", cap_string);
}
dump_extended_pci_caps(device);
}