(&mut self, reg_idx: usize)
| 1351 | } |
| 1352 | |
| 1353 | pub(crate) fn read_config_register(&mut self, reg_idx: usize) -> u32 { |
| 1354 | // When reading the BARs, we trap it and return what comes |
| 1355 | // from our local configuration space. We want the guest to |
| 1356 | // use that and not the VFIO device BARs as it does not map |
| 1357 | // with the guest address space. |
| 1358 | if (PCI_CONFIG_BAR0_INDEX..PCI_CONFIG_BAR0_INDEX + BAR_NUMS).contains(®_idx) |
| 1359 | || reg_idx == PCI_ROM_EXP_BAR_INDEX |
| 1360 | { |
| 1361 | return self.configuration.read_reg(reg_idx); |
| 1362 | } |
| 1363 | |
| 1364 | if let Some(id) = self.get_msix_cap_idx() { |
| 1365 | let msix = self.interrupt.msix.as_mut().unwrap(); |
| 1366 | if reg_idx * 4 == id + 4 { |
| 1367 | return msix.cap.table; |
| 1368 | } else if reg_idx * 4 == id + 8 { |
| 1369 | return msix.cap.pba; |
| 1370 | } |
| 1371 | } |
| 1372 | |
| 1373 | // Since we don't support passing multi-functions devices, we should |
| 1374 | // mask the multi-function bit, bit 7 of the Header Type byte on the |
| 1375 | // register 3. |
| 1376 | let mask = if reg_idx == PCI_HEADER_TYPE_REG_INDEX { |
| 1377 | 0xff7f_ffff |
| 1378 | } else { |
| 1379 | 0xffff_ffff |
| 1380 | }; |
| 1381 | |
| 1382 | // The config register read comes from the VFIO device itself. |
| 1383 | let mut value = self.vfio_wrapper.read_config_dword((reg_idx * 4) as u32) & mask; |
| 1384 | |
| 1385 | if let Some(config_patch) = self.patches.get(®_idx) { |
| 1386 | value = (value & !config_patch.mask) | config_patch.patch; |
| 1387 | } |
| 1388 | |
| 1389 | value |
| 1390 | } |
| 1391 | |
| 1392 | fn state(&self) -> VfioCommonState { |
| 1393 | let intx_state = self.interrupt.intx.as_ref().map(|intx| IntxState { |
no test coverage detected