The branch main has been updated by jhb:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=776cd02b891ccd984963c9ec26f9748d213f0b9b

commit 776cd02b891ccd984963c9ec26f9748d213f0b9b
Author:     John Baldwin <j...@freebsd.org>
AuthorDate: 2024-08-22 18:40:48 +0000
Commit:     John Baldwin <j...@freebsd.org>
CommitDate: 2024-08-22 18:40:48 +0000

    vmm ppt: Enable busmastering and BAR decoding while a device is assigned
    
    Reviewed by:    corvink, markj
    Fixes:          f44ff2aba2d6 bhyve: Treat the COMMAND register for PCI 
passthru devices as emulated
    Sponsored by:   Chelsio Communications
    Differential Revision:  https://reviews.freebsd.org/D46245
---
 sys/amd64/vmm/io/ppt.c | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/sys/amd64/vmm/io/ppt.c b/sys/amd64/vmm/io/ppt.c
index 3451e91d9de1..9fcfdc7cb441 100644
--- a/sys/amd64/vmm/io/ppt.c
+++ b/sys/amd64/vmm/io/ppt.c
@@ -151,9 +151,13 @@ static int
 ppt_attach(device_t dev)
 {
        struct pptdev *ppt;
+       uint16_t cmd;
 
        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));
        num_pptdevs++;
        TAILQ_INSERT_TAIL(&pptdev_list, ppt, next);
@@ -176,7 +180,6 @@ ppt_detach(device_t dev)
                return (EBUSY);
        num_pptdevs--;
        TAILQ_REMOVE(&pptdev_list, ppt, next);
-       pci_disable_busmaster(dev);
 
        if (iommu_host_domain() != NULL)
                iommu_add_device(iommu_host_domain(), pci_get_rid(dev));
@@ -376,11 +379,28 @@ ppt_pci_reset(device_t 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
 ppt_assign_device(struct vm *vm, int bus, int slot, int func)
 {
        struct pptdev *ppt;
        int error;
+       uint16_t cmd;
 
        /* Passing NULL requires the device to be unowned. */
        error = ppt_find(NULL, bus, slot, func, &ppt);
@@ -392,6 +412,9 @@ ppt_assign_device(struct vm *vm, int bus, int slot, int 
func)
        pci_restore_state(ppt->dev);
        ppt->vm = vm;
        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);
 }
 
@@ -400,11 +423,15 @@ ppt_unassign_device(struct vm *vm, int bus, int slot, int 
func)
 {
        struct pptdev *ppt;
        int error;
+       uint16_t cmd;
 
        error = ppt_find(vm, bus, slot, func, &ppt);
        if (error)
                return (error);
 
+       cmd = pci_read_config(ppt->dev, PCIR_COMMAND, 2);
+       cmd &= ~(PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
+       pci_write_config(ppt->dev, PCIR_COMMAND, cmd, 2);
        pci_save_state(ppt->dev);
        ppt_pci_reset(ppt->dev);
        pci_restore_state(ppt->dev);

Reply via email to