From fe9a340ea92f340c2f6d5881fb932dbf1db7a6ba Mon Sep 17 00:00:00 2001 From: Zide Chen Date: Fri, 9 Nov 2018 20:46:41 -0800 Subject: [PATCH] hv: separate the PCI CONFIG_ADDR and CONFIG_DATA I/O port handlers Register separate I/O emulation handlers for I/O port CF8 and CFC. This makes the code simpler, and offers some flexibilities to be able to handle CF8 and CFC ports differently. Tracked-On: #1815 Signed-off-by: Zide Chen Reviewed-by: Li, Fei1 Acked-by: Anthony Xu --- hypervisor/dm/vpci/vpci.c | 118 +++++++++++++++---------------- hypervisor/include/arch/x86/io.h | 5 +- 2 files changed, 60 insertions(+), 63 deletions(-) diff --git a/hypervisor/dm/vpci/vpci.c b/hypervisor/dm/vpci/vpci.c index b943e01bf..33fe4b2f4 100644 --- a/hypervisor/dm/vpci/vpci.c +++ b/hypervisor/dm/vpci/vpci.c @@ -30,17 +30,6 @@ #include #include "pci_priv.h" - -static bool is_cfg_addr(uint16_t addr) -{ - return (addr >= PCI_CONFIG_ADDR) && (addr < (PCI_CONFIG_ADDR + 4U)); -} - -static bool is_cfg_data(uint16_t addr) -{ - return (addr >= PCI_CONFIG_DATA) && (addr < (PCI_CONFIG_DATA + 4U)); -} - static void pci_cfg_clear_cache(struct pci_addr_info *pi) { pi->cached_bdf.value = 0xFFFFU; @@ -48,79 +37,81 @@ static void pci_cfg_clear_cache(struct pci_addr_info *pi) pi->cached_enable = false; } -static uint32_t pci_cfg_io_read(struct acrn_vm *vm, uint16_t addr, size_t bytes) +static uint32_t pci_cfgaddr_io_read(struct acrn_vm *vm, uint16_t addr, size_t bytes) { - uint32_t val = 0xFFFFFFFFU; + uint32_t val = ~0U; struct vpci *vpci = &vm->vpci; struct pci_addr_info *pi = &vpci->addr_info; - if (is_cfg_addr(addr)) { - /* TODO: handling the non 4 bytes access */ - if (bytes == 4U) { - val = (uint32_t)pi->cached_bdf.value; - val <<= 8U; - val |= pi->cached_reg; - if (pi->cached_enable) { - val |= PCI_CFG_ENABLE; - } - } - } else { - if (is_cfg_data(addr)) { - if (pi->cached_enable) { - uint16_t offset = addr - PCI_CONFIG_DATA; - - if ((vpci->ops != NULL) && (vpci->ops->cfgread != NULL)) { - vpci->ops->cfgread(vpci, pi->cached_bdf, - pi->cached_reg + offset, bytes, &val); - } - - pci_cfg_clear_cache(pi); - } - } else { - val = 0xFFFFFFFFU; + if ((addr == (uint16_t)PCI_CONFIG_ADDR) && (bytes == 4U)) { + val = (uint32_t)pi->cached_bdf.value; + val <<= 8U; + val |= pi->cached_reg; + if (pi->cached_enable) { + val |= PCI_CFG_ENABLE; } } return val; } -static void pci_cfg_io_write(struct acrn_vm *vm, uint16_t addr, size_t bytes, - uint32_t val) +static void pci_cfgaddr_io_write(struct acrn_vm *vm, uint16_t addr, size_t bytes, uint32_t val) { struct vpci *vpci = &vm->vpci; struct pci_addr_info *pi = &vpci->addr_info; - if (is_cfg_addr(addr)) { - /* TODO: handling the non 4 bytes access */ - if (bytes == 4U) { - pi->cached_bdf.value = (uint16_t)(val >> 8U); - pi->cached_reg = val & PCI_REGMAX; - pi->cached_enable = ((val & PCI_CFG_ENABLE) == PCI_CFG_ENABLE); - } - } else { - if (is_cfg_data(addr)) { - if (pi->cached_enable) { - uint16_t offset = addr - PCI_CONFIG_DATA; + if ((addr == (uint16_t)PCI_CONFIG_ADDR) && (bytes == 4U)) { + pi->cached_bdf.value = (uint16_t)(val >> 8U); + pi->cached_reg = val & PCI_REGMAX; + pi->cached_enable = ((val & PCI_CFG_ENABLE) == PCI_CFG_ENABLE); + } +} - if ((vpci->ops != NULL) && (vpci->ops->cfgwrite != NULL)) { - vpci->ops->cfgwrite(vpci, pi->cached_bdf, - pi->cached_reg + offset, bytes, val); - } - pci_cfg_clear_cache(pi); - } - } else { - pr_err("Not PCI cfg data/addr port access!"); +static uint32_t pci_cfgdata_io_read(struct acrn_vm *vm, uint16_t addr, size_t bytes) +{ + struct vpci *vpci = &vm->vpci; + struct pci_addr_info *pi = &vpci->addr_info; + uint16_t offset = addr - PCI_CONFIG_DATA; + uint32_t val = ~0U; + + if (pi->cached_enable) { + if ((vpci->ops != NULL) && (vpci->ops->cfgread != NULL)) { + vpci->ops->cfgread(vpci, pi->cached_bdf, pi->cached_reg + offset, bytes, &val); } + pci_cfg_clear_cache(pi); + } + + return val; +} + +static void pci_cfgdata_io_write(struct acrn_vm *vm, uint16_t addr, size_t bytes, uint32_t val) +{ + struct vpci *vpci = &vm->vpci; + struct pci_addr_info *pi = &vpci->addr_info; + uint16_t offset = addr - PCI_CONFIG_DATA; + + if (pi->cached_enable) { + if ((vpci->ops != NULL) && (vpci->ops->cfgwrite != NULL)) { + vpci->ops->cfgwrite(vpci, pi->cached_bdf, pi->cached_reg + offset, bytes, val); + } + pci_cfg_clear_cache(pi); } } void vpci_init(struct acrn_vm *vm) { struct vpci *vpci = &vm->vpci; - struct vm_io_range pci_cfg_range = { + + struct vm_io_range pci_cfgaddr_range = { .flags = IO_ATTR_RW, .base = PCI_CONFIG_ADDR, - .len = 8U + .len = 4U + }; + + struct vm_io_range pci_cfgdata_range = { + .flags = IO_ATTR_RW, + .base = PCI_CONFIG_DATA, + .len = 4U }; vpci->vm = vm; @@ -132,7 +123,12 @@ void vpci_init(struct acrn_vm *vm) #endif if ((vpci->ops->init != NULL) && (vpci->ops->init(vm) == 0)) { - register_io_emulation_handler(vm, PCI_PIO_IDX, &pci_cfg_range, pci_cfg_io_read, pci_cfg_io_write); + register_io_emulation_handler(vm, PCI_CFGADDR_PIO_IDX, &pci_cfgaddr_range, + pci_cfgaddr_io_read, pci_cfgaddr_io_write); + + register_io_emulation_handler(vm, PCI_CFGDATA_PIO_IDX, &pci_cfgdata_range, + pci_cfgdata_io_read, pci_cfgdata_io_write); + /* This is a tmp solution to avoid sos reboot failure, it need pass-thru IO port CF9 for Reset Control * register. */ diff --git a/hypervisor/include/arch/x86/io.h b/hypervisor/include/arch/x86/io.h index 1eaf3756e..ffaca3b0a 100644 --- a/hypervisor/include/arch/x86/io.h +++ b/hypervisor/include/arch/x86/io.h @@ -13,8 +13,9 @@ #define PIC_MASTER_PIO_IDX 0U #define PIC_SLAVE_PIO_IDX (PIC_MASTER_PIO_IDX + 1U) #define PIC_ELC_PIO_IDX (PIC_SLAVE_PIO_IDX + 1U) -#define PCI_PIO_IDX (PIC_ELC_PIO_IDX + 1U) -#define UART_PIO_IDX (PCI_PIO_IDX + 1U) +#define PCI_CFGADDR_PIO_IDX (PIC_ELC_PIO_IDX + 1U) +#define PCI_CFGDATA_PIO_IDX (PCI_CFGADDR_PIO_IDX + 1U) +#define UART_PIO_IDX (PCI_CFGDATA_PIO_IDX + 1U) #define PM1A_EVT_PIO_IDX (UART_PIO_IDX + 1U) #define PM1A_CNT_PIO_IDX (PM1A_EVT_PIO_IDX + 1U) #define PM1B_EVT_PIO_IDX (PM1A_CNT_PIO_IDX + 1U)