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.
This commit is contained in:
joevt 2022-08-22 02:29:09 -07:00
parent fca6cb11b6
commit 6af8b52376
3 changed files with 124 additions and 48 deletions

View File

@ -31,6 +31,15 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <cinttypes>
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);

View File

@ -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
);
}
}

View File

@ -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
);
}
}
}