Skip to content

Commit

Permalink
core: pci: Migrate MMCONFIG access handling to the new MMIO dispatcher
Browse files Browse the repository at this point in the history
Register the MMCONFIG memory region, if available, with the generic MMIO
dispatcher and drop the related handler invocation from
pci_mmio_access_handler.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
  • Loading branch information
jan-kiszka committed Aug 14, 2015
1 parent 3f3aecc commit e17d525
Showing 1 changed file with 44 additions and 33 deletions.
77 changes: 44 additions & 33 deletions hypervisor/pci.c
Expand Up @@ -62,7 +62,7 @@ static const struct pci_cfg_control bridge_write[PCI_CONFIG_HEADER_SIZE] = {
};

static void *pci_space;
static u64 mmcfg_start, mmcfg_end;
static u64 mmcfg_start, mmcfg_size;
static u8 end_bus;

unsigned int pci_mmio_count_regions(struct cell *cell)
Expand All @@ -71,6 +71,9 @@ unsigned int pci_mmio_count_regions(struct cell *cell)
jailhouse_cell_pci_devices(cell->config);
unsigned int n, regions = 0;

if (system_config->platform_info.x86.mmconfig_base)
regions++;

for (n = 0; n < cell->config->num_pci_devices; n++)
if (dev_infos[n].type == JAILHOUSE_PCI_TYPE_IVSHMEM)
regions += PCI_IVSHMEM_NUM_MMIO_REGIONS;
Expand Down Expand Up @@ -353,7 +356,6 @@ enum pci_access pci_cfg_write_moderate(struct pci_device *device, u16 address,
*/
int pci_init(void)
{
unsigned int mmcfg_size;
int err;

err = pci_cell_init(&root_cell);
Expand All @@ -366,7 +368,6 @@ int pci_init(void)

end_bus = system_config->platform_info.x86.mmconfig_end_bus;
mmcfg_size = (end_bus + 1) * 256 * 4096;
mmcfg_end = mmcfg_start + mmcfg_size - 4;

pci_space = page_alloc(&remap_pool, mmcfg_size / PAGE_SIZE);
if (!pci_space)
Expand Down Expand Up @@ -434,52 +435,58 @@ static int pci_msix_access_handler(const struct cell *cell, bool is_write,
return -1;
}

/**
* Handler for MMIO-accesses to PCI config space.
* @param cell Request issuing cell.
* @param is_write True if write access.
* @param addr Address accessed.
* @param value Pointer to value for reading/writing.
*
* @return 1 if handled successfully, 0 if unhandled, -1 on access error.
*/
int pci_mmio_access_handler(const struct cell *cell, bool is_write,
u64 addr, u32 *value)
static enum mmio_result pci_mmconfig_access_handler(void *arg,
struct mmio_access *mmio)
{
u32 mmcfg_offset, reg_addr;
u32 reg_addr = mmio->address & 0xfff;
struct pci_device *device;
enum pci_access access;
enum pci_access result;
u32 val;

if (!pci_space || addr < mmcfg_start || addr > mmcfg_end)
return pci_msix_access_handler(cell, is_write, addr, value);

mmcfg_offset = addr - mmcfg_start;
reg_addr = mmcfg_offset & 0xfff;
/* access must be DWORD-aligned */
if (reg_addr & 0x3)
goto invalid_access;

device = pci_get_assigned_device(cell, mmcfg_offset >> 12);
device = pci_get_assigned_device(this_cell(), mmio->address >> 12);

if (is_write) {
access = pci_cfg_write_moderate(device, reg_addr, 4, *value);
if (access == PCI_ACCESS_REJECT)
if (mmio->is_write) {
result = pci_cfg_write_moderate(device, reg_addr, 4,
mmio->value);
if (result == PCI_ACCESS_REJECT)
goto invalid_access;
if (access == PCI_ACCESS_PERFORM)
mmio_write32(pci_space + mmcfg_offset, *value);
if (result == PCI_ACCESS_PERFORM)
mmio_write32(pci_space + mmio->address, mmio->value);
} else {
access = pci_cfg_read_moderate(device, reg_addr, 4, value);
if (access == PCI_ACCESS_PERFORM)
*value = mmio_read32(pci_space + mmcfg_offset);
result = pci_cfg_read_moderate(device, reg_addr, 4, &val);
if (result == PCI_ACCESS_PERFORM)
mmio->value = mmio_read32(pci_space + mmio->address);
else
mmio->value = val;
}

return 1;
return MMIO_HANDLED;

invalid_access:
panic_printk("FATAL: Invalid PCI MMCONFIG write, device %02x:%02x.%x, "
"reg: %\n", PCI_BDF_PARAMS(mmcfg_offset >> 12), reg_addr);
return -1;
"reg: %\n", PCI_BDF_PARAMS(mmio->address >> 12),
reg_addr);
return MMIO_ERROR;

}

/**
* Handler for MMIO-accesses to PCI config space.
* @param cell Request issuing cell.
* @param is_write True if write access.
* @param addr Address accessed.
* @param value Pointer to value for reading/writing.
*
* @return 1 if handled successfully, 0 if unhandled, -1 on access error.
*/
int pci_mmio_access_handler(const struct cell *cell, bool is_write,
u64 addr, u32 *value)
{
return pci_msix_access_handler(cell, is_write, addr, value);
}

/**
Expand Down Expand Up @@ -683,6 +690,10 @@ int pci_cell_init(struct cell *cell)
unsigned int ndev, ncap;
int err;

if (pci_space)
mmio_region_register(cell, mmcfg_start, mmcfg_size,
pci_mmconfig_access_handler, NULL);

cell->pci_devices = page_alloc(&mem_pool, devlist_pages);
if (!cell->pci_devices)
return -ENOMEM;
Expand Down

0 comments on commit e17d525

Please sign in to comment.