mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-28 16:27:01 +00:00
Fix: HV: keep reshuffling on VBARs
The commit 'Fix: HV: VM OS failed to assign new address to pci-vuart BARs' need more reshuffle. Tracked-On: #5491 Signed-off-by: Tao Yuhong <yuhong.tao@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
5c5d272358
commit
6c6fa5f340
@ -295,8 +295,11 @@ static void init_ivshmem_bar(struct pci_vdev *vdev, uint32_t bar_idx)
|
|||||||
struct acrn_vm_pci_dev_config *dev_config = vdev->pci_dev_config;
|
struct acrn_vm_pci_dev_config *dev_config = vdev->pci_dev_config;
|
||||||
|
|
||||||
addr = dev_config->vbar_base[bar_idx];
|
addr = dev_config->vbar_base[bar_idx];
|
||||||
mask = (is_pci_io_bar((uint32_t)addr)) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK;
|
|
||||||
vbar = &vdev->vbars[bar_idx];
|
vbar = &vdev->vbars[bar_idx];
|
||||||
|
vbar->bar_type.bits = addr;
|
||||||
|
mask = is_pci_io_bar(vbar) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK;
|
||||||
|
vbar->bar_type.bits &= (~mask);
|
||||||
|
|
||||||
if (bar_idx == IVSHMEM_SHM_BAR) {
|
if (bar_idx == IVSHMEM_SHM_BAR) {
|
||||||
struct ivshmem_shm_region *region = find_shm_region(dev_config->shm_region_name);
|
struct ivshmem_shm_region *region = find_shm_region(dev_config->shm_region_name);
|
||||||
if (region != NULL) {
|
if (region != NULL) {
|
||||||
@ -314,9 +317,8 @@ static void init_ivshmem_bar(struct pci_vdev *vdev, uint32_t bar_idx)
|
|||||||
if (size != 0UL) {
|
if (size != 0UL) {
|
||||||
vbar->size = size;
|
vbar->size = size;
|
||||||
vbar->mask = (uint32_t) (~(size - 1UL));
|
vbar->mask = (uint32_t) (~(size - 1UL));
|
||||||
vbar->bar_type.bits = (uint32_t) (addr & (~mask));
|
pci_vdev_write_vbar(vdev, bar_idx, (uint32_t)addr);
|
||||||
pci_vdev_write_vbar(vdev, bar_idx, (uint32_t) addr);
|
if (is_pci_mem64lo_bar(vbar)) {
|
||||||
if (is_pci_mem64_bar((uint32_t)addr)) {
|
|
||||||
vbar = &vdev->vbars[bar_idx + 1U];
|
vbar = &vdev->vbars[bar_idx + 1U];
|
||||||
vbar->is_mem64hi = true;
|
vbar->is_mem64hi = true;
|
||||||
vbar->mask = (uint32_t) ((~(size - 1UL)) >> 32U);
|
vbar->mask = (uint32_t) ((~(size - 1UL)) >> 32U);
|
||||||
|
@ -292,11 +292,9 @@ void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t idx, uint32_t val)
|
|||||||
{
|
{
|
||||||
struct pci_vbar *vbar = &vdev->vbars[idx];
|
struct pci_vbar *vbar = &vdev->vbars[idx];
|
||||||
|
|
||||||
if (is_pci_io_bar(vbar->bar_type.bits)) {
|
if (is_pci_io_bar(vbar)) {
|
||||||
vpci_update_one_vbar(vdev, idx, val, vdev_pt_allow_io_vbar, vdev_pt_deny_io_vbar);
|
vpci_update_one_vbar(vdev, idx, val, vdev_pt_allow_io_vbar, vdev_pt_deny_io_vbar);
|
||||||
}
|
} else if (is_pci_mem_bar(vbar)) {
|
||||||
|
|
||||||
if (is_pci_mem32_bar(vbar->bar_type.bits) || is_pci_mem64_bar(vbar->bar_type.bits) || vbar->is_mem64hi) {
|
|
||||||
vpci_update_one_vbar(vdev, idx, val, vdev_pt_map_mem_vbar, vdev_pt_unmap_mem_vbar);
|
vpci_update_one_vbar(vdev, idx, val, vdev_pt_map_mem_vbar, vdev_pt_unmap_mem_vbar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -360,14 +358,15 @@ static void init_bars(struct pci_vdev *vdev, bool is_sriov_bar)
|
|||||||
offset = pci_bar_offset(idx);
|
offset = pci_bar_offset(idx);
|
||||||
}
|
}
|
||||||
lo = pci_pdev_read_cfg(pbdf, offset, 4U);
|
lo = pci_pdev_read_cfg(pbdf, offset, 4U);
|
||||||
|
vbar->bar_type.bits = lo;
|
||||||
|
|
||||||
if (!(is_pci_io_bar(lo) || is_pci_mem32_bar(lo) || is_pci_mem64_bar(lo))) {
|
if (is_pci_reserved_bar(vbar)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
mask = (is_pci_io_bar(lo)) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK;
|
mask = (is_pci_io_bar(vbar)) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK;
|
||||||
vbar->base_hpa = (uint64_t)lo & mask;
|
vbar->base_hpa = (uint64_t)lo & mask;
|
||||||
|
|
||||||
if (is_pci_mem64_bar(lo)) {
|
if (is_pci_mem64lo_bar(vbar)) {
|
||||||
hi = pci_pdev_read_cfg(pbdf, offset + 4U, 4U);
|
hi = pci_pdev_read_cfg(pbdf, offset + 4U, 4U);
|
||||||
vbar->base_hpa |= ((uint64_t)hi << 32U);
|
vbar->base_hpa |= ((uint64_t)hi << 32U);
|
||||||
}
|
}
|
||||||
@ -378,14 +377,14 @@ static void init_bars(struct pci_vdev *vdev, bool is_sriov_bar)
|
|||||||
pci_pdev_write_cfg(pbdf, offset, 4U, lo);
|
pci_pdev_write_cfg(pbdf, offset, 4U, lo);
|
||||||
|
|
||||||
vbar->mask = size32 & mask;
|
vbar->mask = size32 & mask;
|
||||||
vbar->bar_type.bits = lo & (~mask);
|
vbar->bar_type.bits &= (~mask);
|
||||||
vbar->size = (uint64_t)size32 & mask;
|
vbar->size = (uint64_t)size32 & mask;
|
||||||
|
|
||||||
if (is_prelaunched_vm(vpci2vm(vdev->vpci))) {
|
if (is_prelaunched_vm(vpci2vm(vdev->vpci))) {
|
||||||
lo = (uint32_t)vdev->pci_dev_config->vbar_base[idx];
|
lo = (uint32_t)vdev->pci_dev_config->vbar_base[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_pci_mem64_bar(lo)) {
|
if (is_pci_mem64lo_bar(vbar)) {
|
||||||
idx++;
|
idx++;
|
||||||
if (is_sriov_bar) {
|
if (is_sriov_bar) {
|
||||||
offset = sriov_bar_offset(vdev, idx);
|
offset = sriov_bar_offset(vdev, idx);
|
||||||
@ -419,7 +418,7 @@ static void init_bars(struct pci_vdev *vdev, bool is_sriov_bar)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vbar->size = vbar->size & ~(vbar->size - 1UL);
|
vbar->size = vbar->size & ~(vbar->size - 1UL);
|
||||||
if (is_pci_mem32_bar(lo)) {
|
if (is_pci_mem32_bar(vbar)) {
|
||||||
vbar->size = round_page_up(vbar->size);
|
vbar->size = round_page_up(vbar->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,10 +115,10 @@ static void pci_vdev_update_vbar_base(struct pci_vdev *vdev, uint32_t idx)
|
|||||||
vbar = &vdev->vbars[idx];
|
vbar = &vdev->vbars[idx];
|
||||||
offset = pci_bar_offset(idx);
|
offset = pci_bar_offset(idx);
|
||||||
lo = pci_vdev_read_vcfg(vdev, offset, 4U);
|
lo = pci_vdev_read_vcfg(vdev, offset, 4U);
|
||||||
if (((is_pci_io_bar(vbar->bar_type.bits) || is_pci_mem32_bar(vbar->bar_type.bits) || is_pci_mem64_bar(vbar->bar_type.bits) || vbar->is_mem64hi)) && (lo != ~0U)) {
|
if ((!is_pci_reserved_bar(vbar)) && (lo != ~0U)) {
|
||||||
base = lo & vbar->mask;
|
base = lo & vbar->mask;
|
||||||
|
|
||||||
if (is_pci_mem64_bar(vbar->bar_type.bits)) {
|
if (is_pci_mem64lo_bar(vbar)) {
|
||||||
vbar = &vdev->vbars[idx + 1U];
|
vbar = &vdev->vbars[idx + 1U];
|
||||||
hi = pci_vdev_read_vcfg(vdev, (offset + 4U), 4U);
|
hi = pci_vdev_read_vcfg(vdev, (offset + 4U), 4U);
|
||||||
if (hi != ~0U) {
|
if (hi != ~0U) {
|
||||||
@ -128,12 +128,14 @@ static void pci_vdev_update_vbar_base(struct pci_vdev *vdev, uint32_t idx)
|
|||||||
base = 0UL;
|
base = 0UL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is_pci_io_bar(vbar->bar_type.bits)) {
|
} else if (is_pci_io_bar(vbar)) {
|
||||||
base &= 0xffffUL;
|
/* Because guest driver may write to upper 16-bits of PIO BAR and expect that should have no effect,
|
||||||
}
|
* SO PIO BAR base may bigger than 0xffff after calculation, should mask the upper 16-bits.
|
||||||
|
*/
|
||||||
|
base &= 0xffffUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((base != 0UL) && !ept_is_mr_valid(vpci2vm(vdev->vpci), base, vdev->vbars[idx].size)) {
|
if (is_pci_mem_bar(vbar) && (base != 0UL) && !ept_is_mr_valid(vpci2vm(vdev->vpci), base, vdev->vbars[idx].size)) {
|
||||||
pr_warn("%s, %x:%x.%x set invalid bar[%d] base: 0x%lx, size: 0x%lx\n", __func__,
|
pr_warn("%s, %x:%x.%x set invalid bar[%d] base: 0x%lx, size: 0x%lx\n", __func__,
|
||||||
vdev->bdf.bits.b, vdev->bdf.bits.d, vdev->bdf.bits.f, idx, base, vdev->vbars[idx].size);
|
vdev->bdf.bits.b, vdev->bdf.bits.d, vdev->bdf.bits.f, idx, base, vdev->vbars[idx].size);
|
||||||
base = 0UL; /* 0UL means invalid GPA, so that EPT won't map */
|
base = 0UL; /* 0UL means invalid GPA, so that EPT won't map */
|
||||||
@ -150,13 +152,17 @@ void pci_vdev_write_vbar(struct pci_vdev *vdev, uint32_t idx, uint32_t val)
|
|||||||
|
|
||||||
vbar = &vdev->vbars[idx];
|
vbar = &vdev->vbars[idx];
|
||||||
bar = val & vbar->mask;
|
bar = val & vbar->mask;
|
||||||
bar |= vbar->bar_type.bits;
|
if (vbar->is_mem64hi) {
|
||||||
|
update_idx -= 1U;
|
||||||
|
} else {
|
||||||
|
if (is_pci_io_bar(vbar)) {
|
||||||
|
bar |= (vbar->bar_type.bits & (~PCI_BASE_ADDRESS_IO_MASK));
|
||||||
|
} else {
|
||||||
|
bar |= (vbar->bar_type.bits & (~PCI_BASE_ADDRESS_MEM_MASK));
|
||||||
|
}
|
||||||
|
}
|
||||||
offset = pci_bar_offset(idx);
|
offset = pci_bar_offset(idx);
|
||||||
pci_vdev_write_vcfg(vdev, offset, 4U, bar);
|
pci_vdev_write_vcfg(vdev, offset, 4U, bar);
|
||||||
|
|
||||||
if (vbar->is_mem64hi) {
|
|
||||||
update_idx -= 1U;
|
|
||||||
}
|
|
||||||
|
|
||||||
pci_vdev_update_vbar_base(vdev, update_idx);
|
pci_vdev_update_vbar_base(vdev, update_idx);
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ void init_vmsix_on_msi(struct pci_vdev *vdev)
|
|||||||
if (vdev->vbars[i].base_hpa == 0UL){
|
if (vdev->vbars[i].base_hpa == 0UL){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (is_pci_mem64_bar(vdev->vbars[i].bar_type.bits)) {
|
if (is_pci_mem64lo_bar(&vdev->vbars[i])) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,11 +38,11 @@
|
|||||||
#define VDEV_LIST_HASHSIZE (1U << VDEV_LIST_HASHBITS)
|
#define VDEV_LIST_HASHSIZE (1U << VDEV_LIST_HASHBITS)
|
||||||
|
|
||||||
struct pci_vbar {
|
struct pci_vbar {
|
||||||
bool is_mem64hi;;
|
bool is_mem64hi; /* this is to indicate the high part of 64 bits MMIO bar */
|
||||||
uint64_t size; /* BAR size */
|
uint64_t size; /* BAR size */
|
||||||
uint64_t base_gpa; /* BAR guest physical address */
|
uint64_t base_gpa; /* BAR guest physical address */
|
||||||
uint64_t base_hpa; /* BAR host physical address */
|
uint64_t base_hpa; /* BAR host physical address */
|
||||||
union pci_bar_type bar_type;
|
union pci_bar_type bar_type; /* the low 2(PIO)/4(MMIO) bits of BAR */
|
||||||
uint32_t mask; /* BAR size mask */
|
uint32_t mask; /* BAR size mask */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -184,4 +184,30 @@ int32_t vpci_assign_pcidev(struct acrn_vm *tgt_vm, struct acrn_assign_pcidev *pc
|
|||||||
int32_t vpci_deassign_pcidev(struct acrn_vm *tgt_vm, struct acrn_assign_pcidev *pcidev);
|
int32_t vpci_deassign_pcidev(struct acrn_vm *tgt_vm, struct acrn_assign_pcidev *pcidev);
|
||||||
struct pci_vdev *vpci_init_vdev(struct acrn_vpci *vpci, struct acrn_vm_pci_dev_config *dev_config, struct pci_vdev *parent_pf_vdev);
|
struct pci_vdev *vpci_init_vdev(struct acrn_vpci *vpci, struct acrn_vm_pci_dev_config *dev_config, struct pci_vdev *parent_pf_vdev);
|
||||||
|
|
||||||
|
static inline bool is_pci_io_bar(struct pci_vbar *vbar)
|
||||||
|
{
|
||||||
|
return ((vbar->bar_type.io_space.indicator == 1U) && (!vbar->is_mem64hi));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool is_pci_mem_bar(struct pci_vbar *vbar)
|
||||||
|
{
|
||||||
|
return ((vbar->is_mem64hi) || ((vbar->bar_type.mem_space.indicator == 0U)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reserved PCI BAR type: 1.Memory bar with reserved memory type; 2.IO bar reserved bit is set */
|
||||||
|
static inline bool is_pci_reserved_bar(struct pci_vbar *vbar)
|
||||||
|
{
|
||||||
|
return (((vbar->bar_type.mem_space.indicator == 0U) && ((vbar->bar_type.mem_space.mem_type & 0x1U) == 0x1U) && (!vbar->is_mem64hi)) ||
|
||||||
|
((vbar->bar_type.io_space.indicator == 1U) && (vbar->bar_type.io_space.reserved == 1U)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool is_pci_mem32_bar(struct pci_vbar *vbar)
|
||||||
|
{
|
||||||
|
return ((vbar->bar_type.mem_space.indicator == 0U) && (vbar->bar_type.mem_space.mem_type == 0U) && (!vbar->is_mem64hi));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool is_pci_mem64lo_bar(struct pci_vbar *vbar)
|
||||||
|
{
|
||||||
|
return ((vbar->bar_type.mem_space.indicator == 0U) && (vbar->bar_type.mem_space.mem_type == 2U) && (!vbar->is_mem64hi));
|
||||||
|
}
|
||||||
#endif /* VPCI_H_ */
|
#endif /* VPCI_H_ */
|
||||||
|
@ -203,16 +203,22 @@ union pci_bdf {
|
|||||||
} fields;
|
} fields;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The next data structure is to reflect the format of PCI BAR base on the PCI sepc.
|
||||||
|
*/
|
||||||
|
|
||||||
union pci_bar_type {
|
union pci_bar_type {
|
||||||
uint32_t bits;
|
uint32_t bits;
|
||||||
struct {
|
struct {
|
||||||
uint8_t indicator :1; /* BITs[0], mapped to I/O space if read as 1 */
|
uint32_t indicator :1; /* BITs[0], mapped to I/O space if read as 1 */
|
||||||
uint8_t reserved :1; /* BITs[1], reserved */
|
uint32_t reserved :1; /* BITs[1], reserved and must be "0" per spec. */
|
||||||
|
uint32_t reserved2 : 30;
|
||||||
} io_space;
|
} io_space;
|
||||||
struct {
|
struct {
|
||||||
uint8_t indicator :1; /* BITs[0], mapped to memory space if read as 0 */
|
uint32_t indicator :1; /* BITs[0], mapped to memory space if read as 0 */
|
||||||
uint8_t mem_type :2; /* BITs[1:2], 32-bit address if read as 00b, 64-bit address as 01b */
|
uint32_t mem_type :2; /* BITs[1:2], 32-bit address if read as 00b, 64-bit address as 01b */
|
||||||
uint8_t prefetchable :1; /* BITs[3], set to 1b if the data is prefetchable and set to 0b otherwise */
|
uint32_t prefetchable :1; /* BITs[3], set to 1b if the data is prefetchable and set to 0b otherwise */
|
||||||
|
uint32_t reserved2 : 28;
|
||||||
} mem_space;
|
} mem_space;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -309,34 +315,6 @@ static inline bool is_bar_offset(uint32_t nr_bars, uint32_t offset)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool is_pci_io_bar(uint32_t val)
|
|
||||||
{
|
|
||||||
union pci_bar_type bar_type = {.bits = val};
|
|
||||||
|
|
||||||
return (bar_type.io_space.indicator == 1U);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool is_pci_mem_bar(uint32_t val)
|
|
||||||
{
|
|
||||||
union pci_bar_type bar_type = {.bits = val};
|
|
||||||
|
|
||||||
return ((bar_type.mem_space.indicator == 0U));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool is_pci_mem32_bar(uint32_t val)
|
|
||||||
{
|
|
||||||
union pci_bar_type bar_type = {.bits = val};
|
|
||||||
|
|
||||||
return (is_pci_mem_bar(val) && (bar_type.mem_space.mem_type == 0U));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool is_pci_mem64_bar(uint32_t val)
|
|
||||||
{
|
|
||||||
union pci_bar_type bar_type = {.bits = val};
|
|
||||||
|
|
||||||
return (is_pci_mem_bar(val) && (bar_type.mem_space.mem_type == 2U));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool bdf_is_equal(union pci_bdf a, union pci_bdf b)
|
static inline bool bdf_is_equal(union pci_bdf a, union pci_bdf b)
|
||||||
{
|
{
|
||||||
return (a.value == b.value);
|
return (a.value == b.value);
|
||||||
|
Loading…
Reference in New Issue
Block a user