diff --git a/sys/amd64/vmm/io/ppt.c b/sys/amd64/vmm/io/ppt.c --- a/sys/amd64/vmm/io/ppt.c +++ b/sys/amd64/vmm/io/ppt.c @@ -439,6 +439,23 @@ return (0); } +static bool +ppt_valid_bar_mapping(struct pptdev *ppt, vm_paddr_t hpa, size_t len) +{ + struct pci_map *pm; + pci_addr_t base, size; + + for (pm = pci_first_bar(ppt->dev); pm != NULL; pm = pci_next_bar(pm)) { + if (!PCI_BAR_MEM(pm->pm_value)) + continue; + base = pm->pm_value & PCIM_BAR_MEM_BASE; + size = (pci_addr_t)1 << pm->pm_size; + if (hpa >= base && hpa + len <= base + size) + return (true); + } + return (false); +} + int ppt_map_mmio(struct vm *vm, int bus, int slot, int func, vm_paddr_t gpa, size_t len, vm_paddr_t hpa) @@ -447,10 +464,17 @@ struct pptseg *seg; struct pptdev *ppt; + if (len % PAGE_SIZE != 0 || len == 0 || gpa % PAGE_SIZE != 0 || + hpa % PAGE_SIZE != 0 || gpa + len < gpa || hpa + len < hpa) + return (EINVAL); + error = ppt_find(vm, bus, slot, func, &ppt); if (error) return (error); + if (!ppt_valid_bar_mapping(ppt, hpa, len)) + return (EINVAL); + for (i = 0; i < MAX_MMIOSEGS; i++) { seg = &ppt->mmio[i]; if (seg->len == 0) {