Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/vmm/io/ppt.c
| Show First 20 Lines • Show All 145 Lines • ▼ Show 20 Lines | else | ||||
| */ | */ | ||||
| return (BUS_PROBE_NOWILDCARD); | return (BUS_PROBE_NOWILDCARD); | ||||
| } | } | ||||
| static int | static int | ||||
| ppt_attach(device_t dev) | ppt_attach(device_t dev) | ||||
| { | { | ||||
| struct pptdev *ppt; | struct pptdev *ppt; | ||||
| uint16_t cmd; | |||||
| ppt = device_get_softc(dev); | ppt = device_get_softc(dev); | ||||
| cmd = pci_read_config(dev, PCIR_COMMAND, 2); | |||||
| cmd &= ~(PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); | |||||
| pci_write_config(dev, PCIR_COMMAND, cmd, 2); | |||||
| iommu_remove_device(iommu_host_domain(), pci_get_rid(dev)); | iommu_remove_device(iommu_host_domain(), pci_get_rid(dev)); | ||||
| num_pptdevs++; | num_pptdevs++; | ||||
| TAILQ_INSERT_TAIL(&pptdev_list, ppt, next); | TAILQ_INSERT_TAIL(&pptdev_list, ppt, next); | ||||
| ppt->dev = dev; | ppt->dev = dev; | ||||
| if (bootverbose) | if (bootverbose) | ||||
| device_printf(dev, "attached\n"); | device_printf(dev, "attached\n"); | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| static int | static int | ||||
| ppt_detach(device_t dev) | ppt_detach(device_t dev) | ||||
| { | { | ||||
| struct pptdev *ppt; | struct pptdev *ppt; | ||||
| ppt = device_get_softc(dev); | ppt = device_get_softc(dev); | ||||
| if (ppt->vm != NULL) | if (ppt->vm != NULL) | ||||
| return (EBUSY); | return (EBUSY); | ||||
| num_pptdevs--; | num_pptdevs--; | ||||
| TAILQ_REMOVE(&pptdev_list, ppt, next); | TAILQ_REMOVE(&pptdev_list, ppt, next); | ||||
| pci_disable_busmaster(dev); | |||||
jhb: Note that we disable busmastering during detach. I wonder if we want to disable it during… | |||||
| if (iommu_host_domain() != NULL) | if (iommu_host_domain() != NULL) | ||||
| iommu_add_device(iommu_host_domain(), pci_get_rid(dev)); | iommu_add_device(iommu_host_domain(), pci_get_rid(dev)); | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| static device_method_t ppt_methods[] = { | static device_method_t ppt_methods[] = { | ||||
| /* Device interface */ | /* Device interface */ | ||||
| ▲ Show 20 Lines • Show All 182 Lines • ▼ Show 20 Lines | ppt_pci_reset(device_t dev) | ||||
| if (pcie_flr(dev, | if (pcie_flr(dev, | ||||
| max(pcie_get_max_completion_timeout(dev) / 1000, 10), true)) | max(pcie_get_max_completion_timeout(dev) / 1000, 10), true)) | ||||
| return; | return; | ||||
| pci_power_reset(dev); | pci_power_reset(dev); | ||||
| } | } | ||||
| static uint16_t | |||||
| ppt_bar_enables(struct pptdev *ppt) | |||||
| { | |||||
| struct pci_map *pm; | |||||
| uint16_t cmd; | |||||
| cmd = 0; | |||||
| for (pm = pci_first_bar(ppt->dev); pm != NULL; pm = pci_next_bar(pm)) { | |||||
| if (PCI_BAR_IO(pm->pm_value)) | |||||
| cmd |= PCIM_CMD_PORTEN; | |||||
| if (PCI_BAR_MEM(pm->pm_value)) | |||||
| cmd |= PCIM_CMD_MEMEN; | |||||
| } | |||||
| return (cmd); | |||||
| } | |||||
| 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; | ||||
| int error; | int error; | ||||
| uint16_t cmd; | |||||
| /* Passing NULL requires the device to be unowned. */ | /* Passing NULL requires the device to be unowned. */ | ||||
| error = ppt_find(NULL, bus, slot, func, &ppt); | error = ppt_find(NULL, bus, slot, func, &ppt); | ||||
| if (error) | if (error) | ||||
| return (error); | return (error); | ||||
| pci_save_state(ppt->dev); | pci_save_state(ppt->dev); | ||||
| ppt_pci_reset(ppt->dev); | ppt_pci_reset(ppt->dev); | ||||
| 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)); | ||||
| cmd = pci_read_config(ppt->dev, PCIR_COMMAND, 2); | |||||
| cmd |= PCIM_CMD_BUSMASTEREN | ppt_bar_enables(ppt); | |||||
| pci_write_config(ppt->dev, PCIR_COMMAND, cmd, 2); | |||||
| return (0); | return (0); | ||||
Not Done Inline ActionsIt's a bit confusing that we don't do that for IO BARs too. Would be a good idea to add a command explaining why we don't need to enable IO encoding here. corvink: It's a bit confusing that we don't do that for IO BARs too. Would be a good idea to add a… | |||||
Done Inline ActionsHmm, I could just enable I/O decoding so long as there is an I/O BAR. It won't hurt and might be more intuitive. jhb: Hmm, I could just enable I/O decoding so long as there is an I/O BAR. It won't hurt and might… | |||||
| } | } | ||||
| 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; | ||||
| int error; | int error; | ||||
| uint16_t cmd; | |||||
| error = ppt_find(vm, bus, slot, func, &ppt); | error = ppt_find(vm, bus, slot, func, &ppt); | ||||
| if (error) | if (error) | ||||
| return (error); | return (error); | ||||
| cmd = pci_read_config(ppt->dev, PCIR_COMMAND, 2); | |||||
Not Done Inline ActionsShould we save the initial busmaster state and restore it here? Anyways, I'm unsure whether we need this here at all. We perform an FLR/power reset on ppt_pci_reset two lines below. Don't know if it resets busmastering too. corvink: Should we save the initial busmaster state and restore it here? Anyways, I'm unsure whether we… | |||||
Done Inline ActionsBut the pci_save_state/pci_restore_state around the FLR means we turn bus mastering back on since it would be in the saved command register value. jhb: But the pci_save_state/pci_restore_state around the FLR means we turn bus mastering back on… | |||||
Done Inline ActionsPossibly this should also disable I/O port decoding during unassign? jhb: Possibly this should also disable I/O port decoding during unassign? | |||||
| cmd &= ~(PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); | |||||
| pci_write_config(ppt->dev, PCIR_COMMAND, cmd, 2); | |||||
| pci_save_state(ppt->dev); | pci_save_state(ppt->dev); | ||||
| ppt_pci_reset(ppt->dev); | ppt_pci_reset(ppt->dev); | ||||
| pci_restore_state(ppt->dev); | pci_restore_state(ppt->dev); | ||||
| ppt_unmap_all_mmio(vm, ppt); | ppt_unmap_all_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; | ||||
| ▲ Show 20 Lines • Show All 344 Lines • Show Last 20 Lines | |||||
Note that we disable busmastering during detach. I wonder if we want to disable it during attach instead so that it stays disabled after attach until it is assigned to a VM?