hv: refine the VMCS io bitmap handling when pass-thru PIO bar

In current design, when pass-thru dev,
for the PIO bar, need to ensure the guest PIO start address
equals to host PIO start address.
Then set the VMCS io bitmap to pass-thru the corresponding
port io to guest for performance.

But malicious guest may reprogram the PIO bar,
then hv will pass-thru the reprogramed PIO address to guest.
This isn't safe behavior.

Here only pass-thru the host physical device PIO to guest.
If guest regrogram the PIO bar, just update the virtual bar only.
Currently, we don't support PIO bar reprogramming,
if guest reprogram the PIO bar, guest should take responsibility itself

When init the pass-thru dev PIO bars, set the VMCS io bitmap.
setup_io_bitmap is called before init pass-thru dev to
initiailize the io bitmap, so don't need to
call deny_guest_pio_access when deinit pass-thru dev.

v1 -> v2:
	* set the VMCS io bitmap when init pass-thru devices
	to migrate redoing allow_guest_pio_access()/deny_guest_pio_access().

Tracked-On: #6508

Signed-off-by: Liu,Junming <junming.liu@intel.com>
This commit is contained in:
Liu,Junming 2021-08-28 13:14:09 +00:00 committed by wenlingz
parent cf345269d9
commit 041a7dec98
2 changed files with 10 additions and 26 deletions

View File

@ -260,31 +260,12 @@ 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(vm)) { if (!is_sos_vm(vm)) {
struct pci_vbar *vbar = &vdev->vbars[idx]; struct pci_vbar *vbar = &vdev->vbars[idx];
if (vbar->base_gpa != 0UL) { if (vbar->base_hpa != 0UL) {
allow_guest_pio_access(vm, (uint16_t)vbar->base_gpa, (uint32_t)(vbar->size)); allow_guest_pio_access(vm, (uint16_t)vbar->base_hpa, (uint32_t)(vbar->size));
} }
} }
} }
/**
* @brief Deny IO bar access
* @pre vdev != NULL
* @pre vdev->vpci != NULL
*/
static void vdev_pt_deny_io_vbar(struct pci_vdev *vdev, uint32_t idx)
{
struct acrn_vm *vm = vpci2vm(vdev->vpci);
/* For SOS, all port IO access is allowed by default, so skip SOS here */
if (!is_sos_vm(vm)) {
struct pci_vbar *vbar = &vdev->vbars[idx];
if (vbar->base_gpa != 0UL) {
deny_guest_pio_access(vm, (uint16_t)(vbar->base_gpa), (uint32_t)(vbar->size));
}
}
}
/** /**
* @pre vdev != NULL * @pre vdev != NULL
*/ */
@ -293,7 +274,7 @@ 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)) { 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, NULL, NULL);
} else if (is_pci_mem_bar(vbar)) { } else if (is_pci_mem_bar(vbar)) {
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);
} }
@ -426,6 +407,10 @@ static void init_bars(struct pci_vdev *vdev, bool is_sriov_bar)
if (!is_sriov_bar) { if (!is_sriov_bar) {
pci_vdev_write_vbar(vdev, idx, lo); pci_vdev_write_vbar(vdev, idx, lo);
} }
if (is_pci_io_bar(vbar)) {
vdev_pt_allow_io_vbar(vdev, idx);
}
} }
} }
} }

View File

@ -784,9 +784,6 @@ int32_t vpci_deassign_pcidev(struct acrn_vm *tgt_vm, struct acrn_pcidev *pcidev)
return ret; return ret;
} }
/*
* @pre unmap_cb != NULL
*/
void vpci_update_one_vbar(struct pci_vdev *vdev, uint32_t bar_idx, uint32_t val, void vpci_update_one_vbar(struct pci_vdev *vdev, uint32_t bar_idx, uint32_t val,
map_pcibar map_cb, unmap_pcibar unmap_cb) map_pcibar map_cb, unmap_pcibar unmap_cb)
{ {
@ -796,7 +793,9 @@ void vpci_update_one_vbar(struct pci_vdev *vdev, uint32_t bar_idx, uint32_t val,
if (vbar->is_mem64hi) { if (vbar->is_mem64hi) {
update_idx -= 1U; update_idx -= 1U;
} }
unmap_cb(vdev, update_idx); if (unmap_cb != NULL) {
unmap_cb(vdev, update_idx);
}
pci_vdev_write_vbar(vdev, bar_idx, val); pci_vdev_write_vbar(vdev, bar_idx, val);
if ((map_cb != NULL) && (vdev->vbars[update_idx].base_gpa != 0UL)) { if ((map_cb != NULL) && (vdev->vbars[update_idx].base_gpa != 0UL)) {
map_cb(vdev, update_idx); map_cb(vdev, update_idx);