From 6af8b523767bf314aed7d1c7d8d5139ec6057c71 Mon Sep 17 00:00:00 2001 From: joevt Date: Mon, 22 Aug 2022 02:29:09 -0700 Subject: [PATCH] changes to pci logging For invalid or unsupported PCI accesses, do the following: - log a device's full pci address using pciutils setpci command format bb:dd.f @rr.s (bus:device:function @register+offset.size). - report as read or write access. - log value for writes. - bus, device, function, and register values cannot be determined from Invalid IDSEL values so they will output as ??. - for invalid IDSEL values, report the entire value of the config_addr. - for valid IDSEL values, the bus number cannot be determined since IDSEL only specifies device number. It's probably bus 00 but we'll show ?? to indicate an IDSEL type access. Add missing config type read access logging for chaos. --- devices/common/pci/bandit.cpp | 143 +++++++++++++++++++++++-------- devices/common/pci/pcidevice.cpp | 14 ++- devices/memctrl/mpc106.cpp | 15 ++-- 3 files changed, 124 insertions(+), 48 deletions(-) diff --git a/devices/common/pci/bandit.cpp b/devices/common/pci/bandit.cpp index 9516046..1255dd4 100644 --- a/devices/common/pci/bandit.cpp +++ b/devices/common/pci/bandit.cpp @@ -31,6 +31,15 @@ along with this program. If not, see . #include +const int MultiplyDeBruijnBitPosition2[] = +{ + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 +}; + +/** finds the position of the bit that is set */ +#define WHAT_BIT_SET(val) (MultiplyDeBruijnBitPosition2[(uint32_t)(val * 0x077CB531U) >> 27]) + Bandit::Bandit(int bridge_num, std::string name) : PCIHost(), PCIDevice(name) { supports_types(HWCompType::PCI_HOST | HWCompType::PCI_DEV); @@ -104,24 +113,36 @@ void Bandit::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) uint32_t Bandit::read(uint32_t reg_start, uint32_t offset, int size) { - int fun_num; + int bus_num, dev_num, fun_num; uint8_t reg_offs; uint32_t result, idsel; if (offset & BANDIT_CONFIG_SPACE) { if (offset & 0x00400000) { + fun_num = (this->config_addr >> 8) & 7; + reg_offs = this->config_addr & 0xFCU; + // access to the CONFIG_DATA pseudo-register causes a Config Cycle if (this->config_addr & BANDIT_CAR_TYPE) { - LOG_F(WARNING, "%s: config cycle type 1 not supported yet", this->name.c_str()); + bus_num = (this->config_addr >> 16) & 255; + dev_num = (this->config_addr >> 11) & 31; + LOG_F( + WARNING, "%s: read config cycle type 1 not supported yet %02x:%02x.%x @%02x.%c", + this->name.c_str(), bus_num, dev_num, fun_num, reg_offs + (offset & 3), + size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size + ); return 0; } - idsel = (this->config_addr >> 11) & 0x1FFFFFU; - fun_num = (this->config_addr >> 8) & 7; - reg_offs = this->config_addr & 0xFCU; + idsel = (this->config_addr >> 11) & 0x1FFFFFU; if (!SINGLE_BIT_SET(idsel)) { - LOG_F(ERROR, "%s: invalid IDSEL=0x%X passed", this->name.c_str(), idsel); + LOG_F( + ERROR, "%s: read invalid IDSEL=0x%X config:0x%X ??:??.%x? @%02x?.%c", + this->name.c_str(), idsel, this->config_addr, + fun_num, reg_offs + (offset & 3), + size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size + ); return 0; } @@ -131,11 +152,12 @@ uint32_t Bandit::read(uint32_t reg_start, uint32_t offset, int size) if (this->dev_map.count(idsel)) { result = this->dev_map[idsel]->pci_cfg_read(reg_offs, size); } else { + dev_num = WHAT_BIT_SET(idsel) + 11; LOG_F( - ERROR, - "%s err: read attempt from non-existing PCI device %d", - this->name.c_str(), - idsel); + ERROR, "%s err: read attempt from non-existing PCI device ??:%02x.%x @%02x.%c", + this->name.c_str(), dev_num, fun_num, reg_offs + (offset & 3), + size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size + ); return 0xFFFFFFFFUL; // PCI spec §6.1 } } @@ -158,24 +180,36 @@ uint32_t Bandit::read(uint32_t reg_start, uint32_t offset, int size) void Bandit::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size) { - int fun_num; + int bus_num, dev_num, fun_num; uint8_t reg_offs; uint32_t idsel; if (offset & BANDIT_CONFIG_SPACE) { if (offset & 0x00400000) { + fun_num = (this->config_addr >> 8) & 7; + reg_offs = this->config_addr & 0xFCU; + // access to the CONFIG_DATA pseudo-register causes a Config Cycle if (this->config_addr & BANDIT_CAR_TYPE) { - LOG_F(WARNING, "%s: config cycle type 1 not supported yet", this->name.c_str()); + bus_num = (this->config_addr >> 16) & 255; + dev_num = (this->config_addr >> 11) & 31; + LOG_F( + WARNING, "%s: write config cycle type 1 not supported yet %02x:%02x.%x @%02x.%c = %0*x", + this->name.c_str(), bus_num, dev_num, fun_num, reg_offs + (offset & 3), + size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, value + ); return; } - idsel = (this->config_addr >> 11) & 0x1FFFFFU; - fun_num = (this->config_addr >> 8) & 7; - reg_offs = this->config_addr & 0xFCU; + idsel = (this->config_addr >> 11) & 0x1FFFFFU; if (!SINGLE_BIT_SET(idsel)) { - LOG_F(ERROR, "%s: invalid IDSEL=0x%X passed", this->name.c_str(), idsel); + LOG_F( + ERROR, "%s: write invalid IDSEL=0x%X config:0x%X ??:??.%x? @%02x?.%c = %0*x", + this->name.c_str(), idsel, this->config_addr, + fun_num, reg_offs + (offset & 3), + size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, value + ); return; } @@ -187,11 +221,12 @@ void Bandit::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size if (this->dev_map.count(idsel)) { this->dev_map[idsel]->pci_cfg_write(reg_offs, value, size); } else { + dev_num = WHAT_BIT_SET(idsel) + 11; LOG_F( - ERROR, - "%s err: write attempt to non-existing PCI device %d", - this->name.c_str(), - idsel); + ERROR, "%s err: write attempt to non-existing PCI device ??:%02x.%x @%02x.%c = %0*x", + this->name.c_str(), dev_num, fun_num, reg_offs + (offset & 3), + size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, value + ); } } else { this->config_addr = BYTESWAP_32(value); @@ -251,29 +286,48 @@ Chaos::Chaos(std::string name) : PCIHost() uint32_t Chaos::read(uint32_t reg_start, uint32_t offset, int size) { - int fun_num; + int bus_num, dev_num, fun_num; uint8_t reg_offs; uint32_t result, idsel; if (offset & BANDIT_CONFIG_SPACE) { if (offset & 0x00400000) { - idsel = (this->config_addr >> 11) & 0x1FFFFFU; - fun_num = (this->config_addr >> 8) & 7; + fun_num = (this->config_addr >> 8) & 7; reg_offs = this->config_addr & 0xFCU; + // access to the CONFIG_DATA pseudo-register causes a Config Cycle + if (this->config_addr & BANDIT_CAR_TYPE) { + bus_num = (this->config_addr >> 16) & 255; + dev_num = (this->config_addr >> 11) & 31; + LOG_F( + WARNING, "%s: read config cycle type 1 not supported yet %02x:%02x.%x @%02x.%c", + this->name.c_str(), bus_num, dev_num, fun_num, reg_offs + (offset & 3), + size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size + ); + return 0; + } + + idsel = (this->config_addr >> 11) & 0x1FFFFFU; + if (!SINGLE_BIT_SET(idsel)) { - LOG_F(ERROR, "%s: invalid IDSEL=0x%X passed", this->name.c_str(), idsel); + LOG_F( + ERROR, "%s: read invalid IDSEL=0x%X config:0x%X ??:??.%x? @%02x?.%c", + this->name.c_str(), idsel, this->config_addr, + fun_num, reg_offs + (offset & 3), + size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size + ); return 0; } if (this->dev_map.count(idsel)) { result = this->dev_map[idsel]->pci_cfg_read(reg_offs, size); } else { + dev_num = WHAT_BIT_SET(idsel) + 11; LOG_F( - ERROR, - "%s err: read attempt from non-existing VCI device %d", - this->name.c_str(), - idsel); + ERROR, "%s err: read attempt from non-existing VCI device ??:%02x.%x @%02x.%c", + this->name.c_str(), dev_num, fun_num, reg_offs + (offset & 3), + size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size + ); return 0xFFFFFFFFUL; // PCI spec §6.1 } } else { @@ -288,35 +342,48 @@ uint32_t Chaos::read(uint32_t reg_start, uint32_t offset, int size) void Chaos::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size) { - int fun_num; + int bus_num, dev_num, fun_num; uint8_t reg_offs; uint32_t idsel; if (offset & BANDIT_CONFIG_SPACE) { if (offset & 0x00400000) { + fun_num = (this->config_addr >> 8) & 7; + reg_offs = this->config_addr & 0xFCU; + // access to the CONFIG_DATA pseudo-register causes a Config Cycle if (this->config_addr & BANDIT_CAR_TYPE) { - LOG_F(WARNING, "%s: config cycle type 1 not supported yet", this->name.c_str()); + bus_num = (this->config_addr >> 16) & 255; + dev_num = (this->config_addr >> 11) & 31; + LOG_F( + WARNING, "%s: write config cycle type 1 not supported yet %02x:%02x.%x @%02x.%c = %0*x", + this->name.c_str(), bus_num, dev_num, fun_num, reg_offs + (offset & 3), + size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, value + ); return; } - idsel = (this->config_addr >> 11) & 0x1FFFFFU; - fun_num = (this->config_addr >> 8) & 7; - reg_offs = this->config_addr & 0xFCU; + idsel = (this->config_addr >> 11) & 0x1FFFFFU; if (!SINGLE_BIT_SET(idsel)) { - LOG_F(ERROR, "%s: invalid IDSEL=0x%X passed", this->name.c_str(), idsel); + LOG_F( + ERROR, "%s: write invalid IDSEL=0x%X config:0x%X ??:??.%x? @%02x?.%c = %0*x", + this->name.c_str(), idsel, this->config_addr, + fun_num, reg_offs + (offset & 3), + size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, value + ); return; } if (this->dev_map.count(idsel)) { this->dev_map[idsel]->pci_cfg_write(reg_offs, value, size); } else { + dev_num = WHAT_BIT_SET(idsel) + 11; LOG_F( - ERROR, - "%s err: write attempt to non-existing VCI device %d", - this->name.c_str(), - idsel); + ERROR, "%s err: write attempt to non-existing VCI device ??:%02x.%x @%02x.%c = %0*x", + this->name.c_str(), dev_num, fun_num, reg_offs + (offset & 3), + size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, value + ); } } else { this->config_addr = BYTESWAP_32(value); diff --git a/devices/common/pci/pcidevice.cpp b/devices/common/pci/pcidevice.cpp index 71523d1..4d0db09 100644 --- a/devices/common/pci/pcidevice.cpp +++ b/devices/common/pci/pcidevice.cpp @@ -84,8 +84,11 @@ uint32_t PCIDevice::pci_cfg_read(uint32_t reg_offs, uint32_t size) result = (max_lat << 24) | (min_gnt << 16) | (irq_pin << 8) | irq_line; break; default: - LOG_F(WARNING, "%s: attempt to read from reserved/unimplemented register %d", - this->pci_name.c_str(), reg_offs); + LOG_F( + WARNING, "%s: attempt to read from reserved/unimplemented register @%02x.%c", + this->pci_name.c_str(), reg_offs, + size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size + ); return 0; } @@ -147,8 +150,11 @@ void PCIDevice::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) this->irq_line = data >> 24; break; default: - LOG_F(WARNING, "%s: attempt to write to reserved/unimplemented register %d", - this->pci_name.c_str(), reg_offs); + LOG_F( + WARNING, "%s: attempt to write to reserved/unimplemented register @%02x.%c = %0*x", + this->pci_name.c_str(), reg_offs, + size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, size * 2, value + ); } } diff --git a/devices/memctrl/mpc106.cpp b/devices/memctrl/mpc106.cpp index 05e7f0d..407af00 100644 --- a/devices/memctrl/mpc106.cpp +++ b/devices/memctrl/mpc106.cpp @@ -143,9 +143,10 @@ uint32_t MPC106::pci_read(uint32_t size) { } else { LOG_F( ERROR, - "%s err: read attempt from non-existing PCI device %d", - this->name.c_str(), - dev_num); + "%s err: read attempt from non-existing PCI device %02x:%02x.%x @%02x.%c", + this->name.c_str(), bus_num, dev_num, fun_num, reg_offs, + size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size + ); return 0; } } @@ -178,9 +179,11 @@ void MPC106::pci_write(uint32_t value, uint32_t size) { } else { LOG_F( ERROR, - "%s err: write attempt to non-existing PCI device %d", - this->name.c_str(), - dev_num); + "%s err: write attempt to non-existing PCI device %02x:%02x.%x @%02x.%c = %0*x", + this->name.c_str(), bus_num, dev_num, fun_num, reg_offs, + size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size, + size * 2, value + ); } } }