hv: vpci: move vBAR base setting into pci_vdev_write_bar

Updating vBAR base when setting vBAR configuration sapce.

Tracked-On: #3475
Signed-off-by: Li Fei1 <fei1.li@intel.com>
This commit is contained in:
Li Fei1 2019-11-14 17:58:13 +08:00 committed by wenlingz
parent 5fdb6cc0ac
commit 5aa92b85ea
3 changed files with 44 additions and 44 deletions

View File

@ -49,7 +49,6 @@ static void vdev_pt_unmap_mem_vbar(struct pci_vdev *vdev, uint32_t idx)
ept_del_mr(vm, (uint64_t *)(vm->arch_vm.nworld_eptp), ept_del_mr(vm, (uint64_t *)(vm->arch_vm.nworld_eptp),
vbar->base, /* GPA (old vbar) */ vbar->base, /* GPA (old vbar) */
vbar->size); vbar->size);
vbar->base = 0UL;
} }
is_msix_table_bar = (has_msix_cap(vdev) && (idx == vdev->msix.table_bar)); is_msix_table_bar = (has_msix_cap(vdev) && (idx == vdev->msix.table_bar));
@ -89,30 +88,16 @@ static void vdev_pt_map_mem_vbar(struct pci_vdev *vdev, uint32_t idx)
{ {
bool is_msix_table_bar; bool is_msix_table_bar;
struct pci_bar *vbar; struct pci_bar *vbar;
uint64_t vbar_base;
struct acrn_vm *vm = vdev->vpci->vm; struct acrn_vm *vm = vdev->vpci->vm;
vbar = &vdev->bar[idx]; vbar = &vdev->bar[idx];
vbar_base = pci_vdev_get_bar_base(vdev, idx); if (vbar->base != 0UL) {
if (vbar_base != 0UL) { ept_add_mr(vm, (uint64_t *)(vm->arch_vm.nworld_eptp),
if (ept_is_mr_valid(vm, vbar_base, vbar->size)) { vbar->base_hpa, /* HPA (pbar) */
uint64_t hpa = gpa2hpa(vdev->vpci->vm, vbar_base); vbar->base, /* GPA (new vbar) */
uint64_t pbar_base = vbar->base_hpa; /* pbar (hpa) */ vbar->size,
EPT_WR | EPT_RD | EPT_UNCACHED);
if (hpa != pbar_base) {
ept_add_mr(vm, (uint64_t *)(vm->arch_vm.nworld_eptp),
pbar_base, /* HPA (pbar) */
vbar_base, /* GPA (new vbar) */
vbar->size,
EPT_WR | EPT_RD | EPT_UNCACHED);
}
/* Remember the previously mapped MMIO vbar */
vbar->base = vbar_base;
} else {
pr_fatal("%s, %x:%x.%x set invalid bar[%d] address: 0x%lx\n", __func__,
vdev->bdf.bits.b, vdev->bdf.bits.d, vdev->bdf.bits.f, idx, vbar_base);
}
} }
is_msix_table_bar = (has_msix_cap(vdev) && (idx == vdev->msix.table_bar)); is_msix_table_bar = (has_msix_cap(vdev) && (idx == vdev->msix.table_bar));
@ -145,11 +130,8 @@ static void vdev_pt_allow_io_vbar(struct pci_vdev *vdev, uint32_t idx)
/* For SOS, all port IO access is allowed by default, so skip SOS here */ /* For SOS, all port IO access is allowed by default, so skip SOS here */
if (!is_sos_vm(vdev->vpci->vm)) { if (!is_sos_vm(vdev->vpci->vm)) {
struct pci_bar *vbar = &vdev->bar[idx]; struct pci_bar *vbar = &vdev->bar[idx];
uint64_t vbar_base = pci_vdev_get_bar_base(vdev, idx); /* vbar (gpa) */ if (vbar->base != 0UL) {
if (vbar_base != 0UL) { allow_guest_pio_access(vdev->vpci->vm, (uint16_t)vbar->base, (uint32_t)(vbar->size));
allow_guest_pio_access(vdev->vpci->vm, (uint16_t)vbar_base, (uint32_t)(vbar->size));
/* Remember the previously allowed IO vbar base */
vbar->base = vbar_base;
} }
} }
} }
@ -167,7 +149,6 @@ static void vdev_pt_deny_io_vbar(struct pci_vdev *vdev, uint32_t idx)
struct pci_bar *vbar = &vdev->bar[idx]; struct pci_bar *vbar = &vdev->bar[idx];
if (vbar->base != 0UL) { if (vbar->base != 0UL) {
deny_guest_pio_access(vdev->vpci->vm, (uint16_t)(vbar->base), (uint32_t)(vbar->size)); deny_guest_pio_access(vdev->vpci->vm, (uint16_t)(vbar->base), (uint32_t)(vbar->size));
vbar->base = 0UL;
} }
} }
@ -190,6 +171,7 @@ void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t idx, uint32_t val)
vdev_pt_allow_io_vbar(vdev, update_idx); vdev_pt_allow_io_vbar(vdev, update_idx);
} else { } else {
pci_vdev_write_cfg_u32(vdev, offset, val); pci_vdev_write_cfg_u32(vdev, offset, val);
vdev->bar[update_idx].base = 0UL;
} }
break; break;
@ -199,7 +181,7 @@ void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t idx, uint32_t val)
default: default:
if (vbar->type == PCIBAR_MEM64HI) { if (vbar->type == PCIBAR_MEM64HI) {
update_idx = idx - 1U; update_idx -= 1U;
} }
vdev_pt_unmap_mem_vbar(vdev, update_idx); vdev_pt_unmap_mem_vbar(vdev, update_idx);
if (val != ~0U) { if (val != ~0U) {
@ -207,6 +189,7 @@ void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t idx, uint32_t val)
vdev_pt_map_mem_vbar(vdev, update_idx); vdev_pt_map_mem_vbar(vdev, update_idx);
} else { } else {
pci_vdev_write_cfg_u32(vdev, offset, val); pci_vdev_write_cfg_u32(vdev, offset, val);
vdev->bar[update_idx].base = 0UL;
} }
break; break;
} }
@ -280,7 +263,6 @@ void init_vdev_pt(struct pci_vdev *vdev)
if (is_prelaunched_vm(vdev->vpci->vm)) { if (is_prelaunched_vm(vdev->vpci->vm)) {
lo = (uint32_t)vdev->pci_dev_config->vbar_base[idx]; lo = (uint32_t)vdev->pci_dev_config->vbar_base[idx];
} }
pci_vdev_write_bar(vdev, idx, lo);
if (type == PCIBAR_MEM64) { if (type == PCIBAR_MEM64) {
idx++; idx++;
@ -300,12 +282,14 @@ void init_vdev_pt(struct pci_vdev *vdev)
if (is_prelaunched_vm(vdev->vpci->vm)) { if (is_prelaunched_vm(vdev->vpci->vm)) {
hi = (uint32_t)(vdev->pci_dev_config->vbar_base[idx - 1U] >> 32U); hi = (uint32_t)(vdev->pci_dev_config->vbar_base[idx - 1U] >> 32U);
} }
pci_vdev_write_bar(vdev, idx - 1U, lo);
pci_vdev_write_bar(vdev, idx, hi); pci_vdev_write_bar(vdev, idx, hi);
} else { } else {
vbar->size = vbar->size & ~(vbar->size - 1UL); vbar->size = vbar->size & ~(vbar->size - 1UL);
if (type == PCIBAR_MEM32) { if (type == PCIBAR_MEM32) {
vbar->size = round_page_up(vbar->size); vbar->size = round_page_up(vbar->size);
} }
pci_vdev_write_bar(vdev, idx, lo);
} }
} }
} }

View File

@ -29,6 +29,8 @@
#include <vm.h> #include <vm.h>
#include "vpci_priv.h" #include "vpci_priv.h"
#include <ept.h>
#include <logmsg.h>
/** /**
* @pre vdev != NULL * @pre vdev != NULL
@ -105,24 +107,13 @@ uint32_t pci_vdev_read_bar(const struct pci_vdev *vdev, uint32_t idx)
return bar; return bar;
} }
void pci_vdev_write_bar(struct pci_vdev *vdev, uint32_t idx, uint32_t val) static void pci_vdev_update_bar_base(struct pci_vdev *vdev, uint32_t idx)
{ {
struct pci_bar *vbar; struct pci_bar *vbar;
uint32_t bar, offset;
vbar = &vdev->bar[idx];
bar = val & vbar->mask;
bar |= vbar->fixed;
offset = pci_bar_offset(idx);
pci_vdev_write_cfg_u32(vdev, offset, bar);
}
uint64_t pci_vdev_get_bar_base(const struct pci_vdev *vdev, uint32_t idx)
{
const struct pci_bar *vbar;
enum pci_bar_type type; enum pci_bar_type type;
uint64_t base = 0UL; uint64_t base = 0UL;
uint32_t lo, hi, offset; uint32_t lo, hi, offset;
struct acrn_vm *vm = vdev->vpci->vm;
vbar = &vdev->bar[idx]; vbar = &vdev->bar[idx];
offset = pci_bar_offset(idx); offset = pci_bar_offset(idx);
@ -146,5 +137,31 @@ uint64_t pci_vdev_get_bar_base(const struct pci_vdev *vdev, uint32_t idx)
} }
} }
return base; if ((base != 0UL) && !ept_is_mr_valid(vm, base, vdev->bar[idx].size)) {
pr_fatal("%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->bar[idx].size);
/* If guest set a invalid GPA, ignore it temporarily */
base = 0UL;
}
vdev->bar[idx].base = base;
}
void pci_vdev_write_bar(struct pci_vdev *vdev, uint32_t idx, uint32_t val)
{
struct pci_bar *vbar;
uint32_t bar, offset;
uint32_t update_idx = idx;
vbar = &vdev->bar[idx];
bar = val & vbar->mask;
bar |= vbar->fixed;
offset = pci_bar_offset(idx);
pci_vdev_write_cfg_u32(vdev, offset, bar);
if (vbar->type == PCIBAR_MEM64HI) {
update_idx -= 1U;
}
pci_vdev_update_bar_base(vdev, update_idx);
} }

View File

@ -146,5 +146,4 @@ struct pci_vdev *pci_find_vdev(struct acrn_vpci *vpci, union pci_bdf vbdf);
uint32_t pci_vdev_read_bar(const struct pci_vdev *vdev, uint32_t idx); uint32_t pci_vdev_read_bar(const struct pci_vdev *vdev, uint32_t idx);
void pci_vdev_write_bar(struct pci_vdev *vdev, uint32_t idx, uint32_t val); void pci_vdev_write_bar(struct pci_vdev *vdev, uint32_t idx, uint32_t val);
uint64_t pci_vdev_get_bar_base(const struct pci_vdev *vdev, uint32_t idx);
#endif /* VPCI_PRIV_H_ */ #endif /* VPCI_PRIV_H_ */