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 <fei1.li@intel.com>
This commit is contained in:
Li, Fei1 2019-10-22 17:47:05 +08:00 committed by wenlingz
parent c8fa8e15f8
commit f711d3a639
2 changed files with 28 additions and 37 deletions

View File

@ -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 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); 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 != NULL
* @pre vcpu->vm != 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; uint32_t val = ~0U;
struct acrn_vpci *vpci = &vcpu->vm->vpci; 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; struct pio_request *pio_req = &vcpu->req.reqs.pio;
if ((addr == (uint16_t)PCI_CONFIG_ADDR) && (bytes == 4U)) { if ((addr == (uint16_t)PCI_CONFIG_ADDR) && (bytes == 4U)) {
val = (uint32_t)pi->cached_bdf.value; val = cfg_addr->value;
val <<= 8U;
val |= pi->cached_reg;
if (pi->cached_enable) {
val |= PCI_CFG_ENABLE;
}
} }
pio_req->value = val; 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) 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 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)) { if ((addr == (uint16_t)PCI_CONFIG_ADDR) && (bytes == 4U)) {
pi->cached_bdf.value = (uint16_t)(val >> 8U); /* unmask reserved fields: BITs 24-30 and BITs 0-1 */
pi->cached_reg = val & PCI_REGMASK; cfg_addr->value = val & (~0x7f000003U);
pi->cached_enable = ((val & PCI_CFG_ENABLE) == PCI_CFG_ENABLE);
} }
return true; 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_vm *vm = vcpu->vm;
struct acrn_vpci *vpci = &vm->vpci; 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; uint16_t offset = addr - PCI_CONFIG_DATA;
uint32_t val = ~0U; uint32_t val = ~0U;
struct acrn_vm_config *vm_config; struct acrn_vm_config *vm_config;
struct pio_request *pio_req = &vcpu->req.reqs.pio; struct pio_request *pio_req = &vcpu->req.reqs.pio;
if (pi->cached_enable) { cfg_addr.value = atomic_readandclear32(&vpci->addr.value);
if (vpci_is_valid_access(pi->cached_reg + offset, bytes)) { 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); vm_config = get_vm_config(vm->vm_id);
switch (vm_config->load_order) { switch (vm_config->load_order) {
case PRE_LAUNCHED_VM: case PRE_LAUNCHED_VM:
case SOS_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; break;
default: default:
@ -140,7 +127,6 @@ static bool pci_cfgdata_io_read(struct acrn_vcpu *vcpu, uint16_t addr, size_t by
break; break;
} }
} }
pci_cfg_clear_cache(pi);
} }
pio_req->value = val; 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_vm *vm = vcpu->vm;
struct acrn_vpci *vpci = &vm->vpci; 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; uint16_t offset = addr - PCI_CONFIG_DATA;
struct acrn_vm_config *vm_config; struct acrn_vm_config *vm_config;
cfg_addr.value = atomic_readandclear32(&vpci->addr.value);
if (pi->cached_enable) { if (cfg_addr.bits.enable != 0U) {
if (vpci_is_valid_access(pi->cached_reg + offset, bytes)) { if (vpci_is_valid_access(cfg_addr.bits.reg_num + offset, bytes)) {
vm_config = get_vm_config(vm->vm_id); vm_config = get_vm_config(vm->vm_id);
switch (vm_config->load_order) { switch (vm_config->load_order) {
case PRE_LAUNCHED_VM: case PRE_LAUNCHED_VM:
case SOS_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; break;
default: default:
@ -179,7 +167,6 @@ static bool pci_cfgdata_io_write(struct acrn_vcpu *vcpu, uint16_t addr, size_t b
break; break;
} }
} }
pci_cfg_clear_cache(pi);
} }
return true; return true;

View File

@ -101,15 +101,19 @@ struct pci_vdev {
struct pci_vdev *new_owner; struct pci_vdev *new_owner;
}; };
struct pci_addr_info { union pci_cfg_addr_reg {
union pci_bdf cached_bdf; uint32_t value;
uint32_t cached_reg; struct {
bool cached_enable; 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_vpci {
struct acrn_vm *vm; struct acrn_vm *vm;
struct pci_addr_info addr_info; union pci_cfg_addr_reg addr;
uint32_t pci_vdev_cnt; uint32_t pci_vdev_cnt;
struct pci_vdev pci_vdevs[CONFIG_MAX_PCI_DEV_NUM]; struct pci_vdev pci_vdevs[CONFIG_MAX_PCI_DEV_NUM];
}; };