Changeset View
Changeset View
Standalone View
Standalone View
head/sys/amd64/vmm/io/ppt.c
Show First 20 Lines • Show All 347 Lines • ▼ Show 20 Lines | for (i = 0; i < MAX_MMIOSEGS; i++) { | ||||
if (gpa >= seg->gpa && gpa < seg->gpa + seg->len) | if (gpa >= seg->gpa && gpa < seg->gpa + seg->len) | ||||
return (TRUE); | return (TRUE); | ||||
} | } | ||||
} | } | ||||
return (FALSE); | return (FALSE); | ||||
} | } | ||||
static void | |||||
ppt_pci_reset(device_t dev) | |||||
{ | |||||
int ps; | |||||
if (pcie_flr(dev, | |||||
max(pcie_get_max_completion_timeout(dev) / 1000, 10), | |||||
true)) | |||||
return; | |||||
/* | |||||
* If FLR fails, attempt a power-management reset by cycling | |||||
* the device in/out of D3 state. | |||||
* PCI spec says we can only go into D3 state from D0 state. | |||||
* Transition from D[12] into D0 before going to D3 state. | |||||
*/ | |||||
ps = pci_get_powerstate(dev); | |||||
if (ps != PCI_POWERSTATE_D0 && ps != PCI_POWERSTATE_D3) | |||||
pci_set_powerstate(dev, PCI_POWERSTATE_D0); | |||||
if (pci_get_powerstate(dev) != PCI_POWERSTATE_D3) | |||||
pci_set_powerstate(dev, PCI_POWERSTATE_D3); | |||||
pci_set_powerstate(dev, ps); | |||||
} | |||||
int | int | ||||
ppt_assign_device(struct vm *vm, int bus, int slot, int func) | ppt_assign_device(struct vm *vm, int bus, int slot, int func) | ||||
{ | { | ||||
struct pptdev *ppt; | struct pptdev *ppt; | ||||
ppt = ppt_find(bus, slot, func); | ppt = ppt_find(bus, slot, func); | ||||
if (ppt != NULL) { | if (ppt != NULL) { | ||||
/* | /* | ||||
* If this device is owned by a different VM then we | * If this device is owned by a different VM then we | ||||
* cannot change its owner. | * cannot change its owner. | ||||
*/ | */ | ||||
if (ppt->vm != NULL && ppt->vm != vm) | if (ppt->vm != NULL && ppt->vm != vm) | ||||
return (EBUSY); | return (EBUSY); | ||||
pci_save_state(ppt->dev); | pci_save_state(ppt->dev); | ||||
pcie_flr(ppt->dev, | ppt_pci_reset(ppt->dev); | ||||
max(pcie_get_max_completion_timeout(ppt->dev) / 1000, 10), | |||||
true); | |||||
pci_restore_state(ppt->dev); | pci_restore_state(ppt->dev); | ||||
ppt->vm = vm; | ppt->vm = vm; | ||||
iommu_add_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev)); | iommu_add_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev)); | ||||
return (0); | return (0); | ||||
} | } | ||||
return (ENOENT); | return (ENOENT); | ||||
} | } | ||||
int | int | ||||
ppt_unassign_device(struct vm *vm, int bus, int slot, int func) | ppt_unassign_device(struct vm *vm, int bus, int slot, int func) | ||||
{ | { | ||||
struct pptdev *ppt; | struct pptdev *ppt; | ||||
ppt = ppt_find(bus, slot, func); | ppt = ppt_find(bus, slot, func); | ||||
if (ppt != NULL) { | if (ppt != NULL) { | ||||
/* | /* | ||||
* If this device is not owned by this 'vm' then bail out. | * If this device is not owned by this 'vm' then bail out. | ||||
*/ | */ | ||||
if (ppt->vm != vm) | if (ppt->vm != vm) | ||||
return (EBUSY); | return (EBUSY); | ||||
pci_save_state(ppt->dev); | pci_save_state(ppt->dev); | ||||
pcie_flr(ppt->dev, | ppt_pci_reset(ppt->dev); | ||||
max(pcie_get_max_completion_timeout(ppt->dev) / 1000, 10), | |||||
true); | |||||
pci_restore_state(ppt->dev); | pci_restore_state(ppt->dev); | ||||
ppt_unmap_mmio(vm, ppt); | ppt_unmap_mmio(vm, ppt); | ||||
ppt_teardown_msi(ppt); | ppt_teardown_msi(ppt); | ||||
ppt_teardown_msix(ppt); | ppt_teardown_msix(ppt); | ||||
iommu_remove_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev)); | iommu_remove_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev)); | ||||
ppt->vm = NULL; | ppt->vm = NULL; | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 267 Lines • Show Last 20 Lines |