mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-12-23 06:29:38 +00:00
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:
parent
fca6cb11b6
commit
6af8b52376
@ -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);
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user