mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-23 22:18:17 +00:00
hv: vpci: add PCI BAR re-program address check
In theory, guest could re-program PCI BAR address to any address. However, ACRN hypervisor only support [0, top_address_space) EPT memory mapping. So we need to check whether the PCI BAR re-program address is within this scope. Tracked-On: #3475 Signed-off-by: Li, Fei1 <fei1.li@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
dab14856c2
commit
dc1e2adaec
@ -18,6 +18,18 @@
|
||||
|
||||
#define ACRN_DBG_EPT 6U
|
||||
|
||||
bool ept_is_mr_valid(const struct acrn_vm *vm, uint64_t base, uint64_t size)
|
||||
{
|
||||
bool valid = true;
|
||||
uint64_t end = base + size;
|
||||
uint64_t top_address_space = vm->arch_vm.ept_mem_ops.info->ept.top_address_space;
|
||||
if ((end <= base) || (end > top_address_space)) {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
void destroy_ept(struct acrn_vm *vm)
|
||||
{
|
||||
/* Destroy secure world */
|
||||
|
@ -626,7 +626,6 @@ static int32_t add_vm_memory_region(struct acrn_vm *vm, struct acrn_vm *target_v
|
||||
static int32_t set_vm_memory_region(struct acrn_vm *vm,
|
||||
struct acrn_vm *target_vm, const struct vm_memory_region *region)
|
||||
{
|
||||
uint64_t gpa_end;
|
||||
uint64_t *pml4_page;
|
||||
int32_t ret;
|
||||
|
||||
@ -635,8 +634,7 @@ static int32_t set_vm_memory_region(struct acrn_vm *vm,
|
||||
__func__, target_vm->vm_id, region->size);
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
gpa_end = region->gpa + region->size;
|
||||
if (gpa_end > target_vm->arch_vm.ept_mem_ops.info->ept.top_address_space) {
|
||||
if (!ept_is_mr_valid(target_vm, region->gpa, region->size)) {
|
||||
pr_err("%s, invalid gpa: 0x%llx, size: 0x%llx, top_address_space: 0x%llx", __func__,
|
||||
region->gpa, region->size,
|
||||
target_vm->arch_vm.ept_mem_ops.info->ept.top_address_space);
|
||||
|
@ -248,15 +248,20 @@ static void vdev_pt_remap_generic_mem_vbar(struct pci_vdev *vdev, uint32_t idx)
|
||||
vbar->size);
|
||||
}
|
||||
|
||||
/* Map the physical BAR in the guest MMIO space */
|
||||
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);
|
||||
if (ept_is_mr_valid(vm, vbar_base, vbar->size)) {
|
||||
/* Map the physical BAR in the guest MMIO space */
|
||||
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 */
|
||||
vdev->bar_base_mapped[idx] = vbar_base;
|
||||
/* Remember the previously mapped MMIO vbar */
|
||||
vdev->bar_base_mapped[idx] = vbar_base;
|
||||
} else {
|
||||
pr_fatal("%s, %x:%x.%x set invalid bar[%d] address: 0x%llx\n", __func__,
|
||||
vdev->bdf.bits.b, vdev->bdf.bits.d, vdev->bdf.bits.f, idx, vbar_base);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,17 @@ typedef void (*pge_handler)(uint64_t *pgentry, uint64_t size);
|
||||
#define INVALID_HPA (0x1UL << 52U)
|
||||
#define INVALID_GPA (0x1UL << 52U)
|
||||
/* External Interfaces */
|
||||
/**
|
||||
* @brief Check guest-physical memory region mapping valid
|
||||
*
|
||||
* @param[in] vm the pointer that points to VM data structure
|
||||
* @param[in] base The specified start guest physical address of guest
|
||||
* physical memory region
|
||||
* @param[in] size The size of guest physical memory region
|
||||
*
|
||||
* @retval true if the guest-physical memory region mapping valid, false otherwise.
|
||||
*/
|
||||
bool ept_is_mr_valid(const struct acrn_vm *vm, uint64_t base, uint64_t size);
|
||||
/**
|
||||
* @brief EPT page tables destroy
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user