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 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;

View File

@ -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];
};