From f711d3a6395cc509cd0af9eeb679ed8479b99fc8 Mon Sep 17 00:00:00 2001 From: "Li, Fei1" Date: Tue, 22 Oct 2019 17:47:05 +0800 Subject: [PATCH] hv: vpci: define PCI CONFIG_ADDRESS Register as its physical layout Refine PCI CONFIG_ADDRESS Register definition as its physical layout. In this case, we could read/write PCI CONFIG_ADDRESS Register atomically. Tracked-On: #3475 Signed-off-by: Li, Fei1 --- hypervisor/dm/vpci/vpci.c | 51 ++++++++++++++---------------------- hypervisor/include/dm/vpci.h | 14 ++++++---- 2 files changed, 28 insertions(+), 37 deletions(-) diff --git a/hypervisor/dm/vpci/vpci.c b/hypervisor/dm/vpci/vpci.c index 07f44829b..7f8fb4753 100644 --- a/hypervisor/dm/vpci/vpci.c +++ b/hypervisor/dm/vpci/vpci.c @@ -40,16 +40,6 @@ static void deinit_postlaunched_vm_vpci(const struct acrn_vm *vm); static void read_cfg(const struct acrn_vpci *vpci, union pci_bdf bdf, uint32_t offset, uint32_t bytes, uint32_t *val); static void write_cfg(const struct acrn_vpci *vpci, union pci_bdf bdf, uint32_t offset, uint32_t bytes, uint32_t val); -/** - * @pre pi != NULL - */ -static void pci_cfg_clear_cache(struct pci_addr_info *pi) -{ - pi->cached_bdf.value = 0xFFFFU; - pi->cached_reg = 0U; - pi->cached_enable = false; -} - /** * @pre vcpu != NULL * @pre vcpu->vm != NULL @@ -58,16 +48,11 @@ static bool pci_cfgaddr_io_read(struct acrn_vcpu *vcpu, uint16_t addr, size_t by { uint32_t val = ~0U; struct acrn_vpci *vpci = &vcpu->vm->vpci; - struct pci_addr_info *pi = &vpci->addr_info; + union pci_cfg_addr_reg *cfg_addr = &vpci->addr; struct pio_request *pio_req = &vcpu->req.reqs.pio; 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; - } + val = cfg_addr->value; } pio_req->value = val; @@ -82,12 +67,11 @@ static bool pci_cfgaddr_io_read(struct acrn_vcpu *vcpu, uint16_t addr, size_t by static bool pci_cfgaddr_io_write(struct acrn_vcpu *vcpu, uint16_t addr, size_t bytes, uint32_t val) { struct acrn_vpci *vpci = &vcpu->vm->vpci; - struct pci_addr_info *pi = &vpci->addr_info; + union pci_cfg_addr_reg *cfg_addr = &vpci->addr; if ((addr == (uint16_t)PCI_CONFIG_ADDR) && (bytes == 4U)) { - pi->cached_bdf.value = (uint16_t)(val >> 8U); - pi->cached_reg = val & PCI_REGMASK; - pi->cached_enable = ((val & PCI_CFG_ENABLE) == PCI_CFG_ENABLE); + /* unmask reserved fields: BITs 24-30 and BITs 0-1 */ + cfg_addr->value = val & (~0x7f000003U); } return true; @@ -119,20 +103,23 @@ static bool pci_cfgdata_io_read(struct acrn_vcpu *vcpu, uint16_t addr, size_t by { struct acrn_vm *vm = vcpu->vm; struct acrn_vpci *vpci = &vm->vpci; - struct pci_addr_info *pi = &vpci->addr_info; + union pci_cfg_addr_reg cfg_addr; + union pci_bdf bdf; uint16_t offset = addr - PCI_CONFIG_DATA; uint32_t val = ~0U; struct acrn_vm_config *vm_config; struct pio_request *pio_req = &vcpu->req.reqs.pio; - if (pi->cached_enable) { - if (vpci_is_valid_access(pi->cached_reg + offset, bytes)) { + cfg_addr.value = atomic_readandclear32(&vpci->addr.value); + if (cfg_addr.bits.enable != 0U) { + if (vpci_is_valid_access(cfg_addr.bits.reg_num + offset, bytes)) { vm_config = get_vm_config(vm->vm_id); switch (vm_config->load_order) { case PRE_LAUNCHED_VM: case SOS_VM: - read_cfg(vpci, pi->cached_bdf, pi->cached_reg + offset, bytes, &val); + bdf.value = cfg_addr.bits.bdf; + read_cfg(vpci, bdf, cfg_addr.bits.reg_num + offset, bytes, &val); break; default: @@ -140,7 +127,6 @@ static bool pci_cfgdata_io_read(struct acrn_vcpu *vcpu, uint16_t addr, size_t by break; } } - pci_cfg_clear_cache(pi); } pio_req->value = val; @@ -159,19 +145,21 @@ static bool pci_cfgdata_io_write(struct acrn_vcpu *vcpu, uint16_t addr, size_t b { struct acrn_vm *vm = vcpu->vm; struct acrn_vpci *vpci = &vm->vpci; - struct pci_addr_info *pi = &vpci->addr_info; + union pci_cfg_addr_reg cfg_addr; + union pci_bdf bdf; uint16_t offset = addr - PCI_CONFIG_DATA; struct acrn_vm_config *vm_config; - - if (pi->cached_enable) { - if (vpci_is_valid_access(pi->cached_reg + offset, bytes)) { + cfg_addr.value = atomic_readandclear32(&vpci->addr.value); + if (cfg_addr.bits.enable != 0U) { + if (vpci_is_valid_access(cfg_addr.bits.reg_num + offset, bytes)) { vm_config = get_vm_config(vm->vm_id); switch (vm_config->load_order) { case PRE_LAUNCHED_VM: case SOS_VM: - write_cfg(vpci, pi->cached_bdf, pi->cached_reg + offset, bytes, val); + bdf.value = cfg_addr.bits.bdf; + write_cfg(vpci, bdf, cfg_addr.bits.reg_num + offset, bytes, val); break; default: @@ -179,7 +167,6 @@ static bool pci_cfgdata_io_write(struct acrn_vcpu *vcpu, uint16_t addr, size_t b break; } } - pci_cfg_clear_cache(pi); } return true; diff --git a/hypervisor/include/dm/vpci.h b/hypervisor/include/dm/vpci.h index 2574e4f82..a6bb3ce8e 100644 --- a/hypervisor/include/dm/vpci.h +++ b/hypervisor/include/dm/vpci.h @@ -101,15 +101,19 @@ struct pci_vdev { struct pci_vdev *new_owner; }; -struct pci_addr_info { - union pci_bdf cached_bdf; - uint32_t cached_reg; - bool cached_enable; +union pci_cfg_addr_reg { + uint32_t value; + struct { + uint32_t reg_num : 8; /* BITs 0-7, Register Number (BITs 0-1, always reserve to 0) */ + uint32_t bdf : 16; /* BITs 8-23, BDF Number */ + uint32_t resv : 7; /* BITs 24-30, Reserved */ + uint32_t enable : 1; /* BITs 31, Enable bit */ + } bits; }; struct acrn_vpci { struct acrn_vm *vm; - struct pci_addr_info addr_info; + union pci_cfg_addr_reg addr; uint32_t pci_vdev_cnt; struct pci_vdev pci_vdevs[CONFIG_MAX_PCI_DEV_NUM]; };