Commit 1ddd0027 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'vfio-v5.4-rc1' of git://github.com/awilliam/linux-vfio

Pull VFIO updates from Alex Williamson:

 - Fix spapr iommu error case case (Alexey Kardashevskiy)

 - Consolidate region type definitions (Cornelia Huck)

 - Restore saved original PCI state on release (hexin)

 - Simplify mtty sample driver interrupt path (Parav Pandit)

 - Support for reporting valid IOVA regions to user (Shameer Kolothum)

* tag 'vfio-v5.4-rc1' of git://github.com/awilliam/linux-vfio:
  vfio_pci: Restore original state on release
  vfio/type1: remove duplicate retrieval of reserved regions
  vfio/type1: Add IOVA range capability support
  vfio/type1: check dma map request is within a valid iova range
  vfio/spapr_tce: Fix incorrect tce_iommu_group memory free
  vfio-mdev/mtty: Simplify interrupt generation
  vfio: re-arrange vfio region definitions
  vfio/type1: Update iova list on detach
  vfio/type1: Check reserved region conflict and update iova list
  vfio/type1: Introduce iova list and add iommu aperture validity check
parents 45824fc0 e6c5d727
...@@ -438,11 +438,20 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev) ...@@ -438,11 +438,20 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev)
pci_write_config_word(pdev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE); pci_write_config_word(pdev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE);
/* /*
* Try to reset the device. The success of this is dependent on * Try to get the locks ourselves to prevent a deadlock. The
* being able to lock the device, which is not always possible. * success of this is dependent on being able to lock the device,
* which is not always possible.
* We can not use the "try" reset interface here, which will
* overwrite the previously restored configuration information.
*/ */
if (vdev->reset_works && !pci_try_reset_function(pdev)) if (vdev->reset_works && pci_cfg_access_trylock(pdev)) {
vdev->needs_reset = false; if (device_trylock(&pdev->dev)) {
if (!__pci_reset_function_locked(pdev))
vdev->needs_reset = false;
device_unlock(&pdev->dev);
}
pci_cfg_access_unlock(pdev);
}
pci_restore_state(pdev); pci_restore_state(pdev);
out: out:
......
...@@ -1240,7 +1240,7 @@ static long tce_iommu_take_ownership_ddw(struct tce_container *container, ...@@ -1240,7 +1240,7 @@ static long tce_iommu_take_ownership_ddw(struct tce_container *container,
static int tce_iommu_attach_group(void *iommu_data, static int tce_iommu_attach_group(void *iommu_data,
struct iommu_group *iommu_group) struct iommu_group *iommu_group)
{ {
int ret; int ret = 0;
struct tce_container *container = iommu_data; struct tce_container *container = iommu_data;
struct iommu_table_group *table_group; struct iommu_table_group *table_group;
struct tce_iommu_group *tcegrp = NULL; struct tce_iommu_group *tcegrp = NULL;
...@@ -1293,13 +1293,13 @@ static int tce_iommu_attach_group(void *iommu_data, ...@@ -1293,13 +1293,13 @@ static int tce_iommu_attach_group(void *iommu_data,
!table_group->ops->release_ownership) { !table_group->ops->release_ownership) {
if (container->v2) { if (container->v2) {
ret = -EPERM; ret = -EPERM;
goto unlock_exit; goto free_exit;
} }
ret = tce_iommu_take_ownership(container, table_group); ret = tce_iommu_take_ownership(container, table_group);
} else { } else {
if (!container->v2) { if (!container->v2) {
ret = -EPERM; ret = -EPERM;
goto unlock_exit; goto free_exit;
} }
ret = tce_iommu_take_ownership_ddw(container, table_group); ret = tce_iommu_take_ownership_ddw(container, table_group);
if (!tce_groups_attached(container) && !container->tables[0]) if (!tce_groups_attached(container) && !container->tables[0])
...@@ -1311,10 +1311,11 @@ static int tce_iommu_attach_group(void *iommu_data, ...@@ -1311,10 +1311,11 @@ static int tce_iommu_attach_group(void *iommu_data,
list_add(&tcegrp->next, &container->group_list); list_add(&tcegrp->next, &container->group_list);
} }
unlock_exit: free_exit:
if (ret && tcegrp) if (ret && tcegrp)
kfree(tcegrp); kfree(tcegrp);
unlock_exit:
mutex_unlock(&container->lock); mutex_unlock(&container->lock);
return ret; return ret;
......
This diff is collapsed.
...@@ -295,15 +295,38 @@ struct vfio_region_info_cap_type { ...@@ -295,15 +295,38 @@ struct vfio_region_info_cap_type {
__u32 subtype; /* type specific */ __u32 subtype; /* type specific */
}; };
/*
* List of region types, global per bus driver.
* If you introduce a new type, please add it here.
*/
/* PCI region type containing a PCI vendor part */
#define VFIO_REGION_TYPE_PCI_VENDOR_TYPE (1 << 31) #define VFIO_REGION_TYPE_PCI_VENDOR_TYPE (1 << 31)
#define VFIO_REGION_TYPE_PCI_VENDOR_MASK (0xffff) #define VFIO_REGION_TYPE_PCI_VENDOR_MASK (0xffff)
#define VFIO_REGION_TYPE_GFX (1)
#define VFIO_REGION_TYPE_CCW (2)
/* sub-types for VFIO_REGION_TYPE_PCI_* */
/* 8086 Vendor sub-types */ /* 8086 vendor PCI sub-types */
#define VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION (1) #define VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION (1)
#define VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG (2) #define VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG (2)
#define VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG (3) #define VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG (3)
#define VFIO_REGION_TYPE_GFX (1) /* 10de vendor PCI sub-types */
/*
* NVIDIA GPU NVlink2 RAM is coherent RAM mapped onto the host address space.
*/
#define VFIO_REGION_SUBTYPE_NVIDIA_NVLINK2_RAM (1)
/* 1014 vendor PCI sub-types */
/*
* IBM NPU NVlink2 ATSD (Address Translation Shootdown) register of NPU
* to do TLB invalidation on a GPU.
*/
#define VFIO_REGION_SUBTYPE_IBM_NVLINK2_ATSD (1)
/* sub-types for VFIO_REGION_TYPE_GFX */
#define VFIO_REGION_SUBTYPE_GFX_EDID (1) #define VFIO_REGION_SUBTYPE_GFX_EDID (1)
/** /**
...@@ -353,25 +376,9 @@ struct vfio_region_gfx_edid { ...@@ -353,25 +376,9 @@ struct vfio_region_gfx_edid {
#define VFIO_DEVICE_GFX_LINK_STATE_DOWN 2 #define VFIO_DEVICE_GFX_LINK_STATE_DOWN 2
}; };
#define VFIO_REGION_TYPE_CCW (2) /* sub-types for VFIO_REGION_TYPE_CCW */
/* ccw sub-types */
#define VFIO_REGION_SUBTYPE_CCW_ASYNC_CMD (1) #define VFIO_REGION_SUBTYPE_CCW_ASYNC_CMD (1)
/*
* 10de vendor sub-type
*
* NVIDIA GPU NVlink2 RAM is coherent RAM mapped onto the host address space.
*/
#define VFIO_REGION_SUBTYPE_NVIDIA_NVLINK2_RAM (1)
/*
* 1014 vendor sub-type
*
* IBM NPU NVlink2 ATSD (Address Translation Shootdown) register of NPU
* to do TLB invalidation on a GPU.
*/
#define VFIO_REGION_SUBTYPE_IBM_NVLINK2_ATSD (1)
/* /*
* The MSIX mappable capability informs that MSIX data of a BAR can be mmapped * The MSIX mappable capability informs that MSIX data of a BAR can be mmapped
* which allows direct access to non-MSIX registers which happened to be within * which allows direct access to non-MSIX registers which happened to be within
...@@ -714,7 +721,31 @@ struct vfio_iommu_type1_info { ...@@ -714,7 +721,31 @@ struct vfio_iommu_type1_info {
__u32 argsz; __u32 argsz;
__u32 flags; __u32 flags;
#define VFIO_IOMMU_INFO_PGSIZES (1 << 0) /* supported page sizes info */ #define VFIO_IOMMU_INFO_PGSIZES (1 << 0) /* supported page sizes info */
__u64 iova_pgsizes; /* Bitmap of supported page sizes */ #define VFIO_IOMMU_INFO_CAPS (1 << 1) /* Info supports caps */
__u64 iova_pgsizes; /* Bitmap of supported page sizes */
__u32 cap_offset; /* Offset within info struct of first cap */
};
/*
* The IOVA capability allows to report the valid IOVA range(s)
* excluding any non-relaxable reserved regions exposed by
* devices attached to the container. Any DMA map attempt
* outside the valid iova range will return error.
*
* The structures below define version 1 of this capability.
*/
#define VFIO_IOMMU_TYPE1_INFO_CAP_IOVA_RANGE 1
struct vfio_iova_range {
__u64 start;
__u64 end;
};
struct vfio_iommu_type1_info_cap_iova_range {
struct vfio_info_cap_header header;
__u32 nr_iovas;
__u32 reserved;
struct vfio_iova_range iova_ranges[];
}; };
#define VFIO_IOMMU_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12) #define VFIO_IOMMU_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12)
......
...@@ -152,20 +152,9 @@ static const struct file_operations vd_fops = { ...@@ -152,20 +152,9 @@ static const struct file_operations vd_fops = {
/* function prototypes */ /* function prototypes */
static int mtty_trigger_interrupt(const guid_t *uuid); static int mtty_trigger_interrupt(struct mdev_state *mdev_state);
/* Helper functions */ /* Helper functions */
static struct mdev_state *find_mdev_state_by_uuid(const guid_t *uuid)
{
struct mdev_state *mds;
list_for_each_entry(mds, &mdev_devices_list, next) {
if (guid_equal(mdev_uuid(mds->mdev), uuid))
return mds;
}
return NULL;
}
static void dump_buffer(u8 *buf, uint32_t count) static void dump_buffer(u8 *buf, uint32_t count)
{ {
...@@ -337,8 +326,7 @@ static void handle_bar_write(unsigned int index, struct mdev_state *mdev_state, ...@@ -337,8 +326,7 @@ static void handle_bar_write(unsigned int index, struct mdev_state *mdev_state,
pr_err("Serial port %d: Fifo level trigger\n", pr_err("Serial port %d: Fifo level trigger\n",
index); index);
#endif #endif
mtty_trigger_interrupt( mtty_trigger_interrupt(mdev_state);
mdev_uuid(mdev_state->mdev));
} }
} else { } else {
#if defined(DEBUG_INTR) #if defined(DEBUG_INTR)
...@@ -352,8 +340,7 @@ static void handle_bar_write(unsigned int index, struct mdev_state *mdev_state, ...@@ -352,8 +340,7 @@ static void handle_bar_write(unsigned int index, struct mdev_state *mdev_state,
*/ */
if (mdev_state->s[index].uart_reg[UART_IER] & if (mdev_state->s[index].uart_reg[UART_IER] &
UART_IER_RLSI) UART_IER_RLSI)
mtty_trigger_interrupt( mtty_trigger_interrupt(mdev_state);
mdev_uuid(mdev_state->mdev));
} }
mutex_unlock(&mdev_state->rxtx_lock); mutex_unlock(&mdev_state->rxtx_lock);
break; break;
...@@ -372,8 +359,7 @@ static void handle_bar_write(unsigned int index, struct mdev_state *mdev_state, ...@@ -372,8 +359,7 @@ static void handle_bar_write(unsigned int index, struct mdev_state *mdev_state,
pr_err("Serial port %d: IER_THRI write\n", pr_err("Serial port %d: IER_THRI write\n",
index); index);
#endif #endif
mtty_trigger_interrupt( mtty_trigger_interrupt(mdev_state);
mdev_uuid(mdev_state->mdev));
} }
mutex_unlock(&mdev_state->rxtx_lock); mutex_unlock(&mdev_state->rxtx_lock);
...@@ -444,7 +430,7 @@ static void handle_bar_write(unsigned int index, struct mdev_state *mdev_state, ...@@ -444,7 +430,7 @@ static void handle_bar_write(unsigned int index, struct mdev_state *mdev_state,
#if defined(DEBUG_INTR) #if defined(DEBUG_INTR)
pr_err("Serial port %d: MCR_OUT2 write\n", index); pr_err("Serial port %d: MCR_OUT2 write\n", index);
#endif #endif
mtty_trigger_interrupt(mdev_uuid(mdev_state->mdev)); mtty_trigger_interrupt(mdev_state);
} }
if ((mdev_state->s[index].uart_reg[UART_IER] & UART_IER_MSI) && if ((mdev_state->s[index].uart_reg[UART_IER] & UART_IER_MSI) &&
...@@ -452,7 +438,7 @@ static void handle_bar_write(unsigned int index, struct mdev_state *mdev_state, ...@@ -452,7 +438,7 @@ static void handle_bar_write(unsigned int index, struct mdev_state *mdev_state,
#if defined(DEBUG_INTR) #if defined(DEBUG_INTR)
pr_err("Serial port %d: MCR RTS/DTR write\n", index); pr_err("Serial port %d: MCR RTS/DTR write\n", index);
#endif #endif
mtty_trigger_interrupt(mdev_uuid(mdev_state->mdev)); mtty_trigger_interrupt(mdev_state);
} }
break; break;
...@@ -503,8 +489,7 @@ static void handle_bar_read(unsigned int index, struct mdev_state *mdev_state, ...@@ -503,8 +489,7 @@ static void handle_bar_read(unsigned int index, struct mdev_state *mdev_state,
#endif #endif
if (mdev_state->s[index].uart_reg[UART_IER] & if (mdev_state->s[index].uart_reg[UART_IER] &
UART_IER_THRI) UART_IER_THRI)
mtty_trigger_interrupt( mtty_trigger_interrupt(mdev_state);
mdev_uuid(mdev_state->mdev));
} }
mutex_unlock(&mdev_state->rxtx_lock); mutex_unlock(&mdev_state->rxtx_lock);
...@@ -1028,17 +1013,9 @@ static int mtty_set_irqs(struct mdev_device *mdev, uint32_t flags, ...@@ -1028,17 +1013,9 @@ static int mtty_set_irqs(struct mdev_device *mdev, uint32_t flags,
return ret; return ret;
} }
static int mtty_trigger_interrupt(const guid_t *uuid) static int mtty_trigger_interrupt(struct mdev_state *mdev_state)
{ {
int ret = -1; int ret = -1;
struct mdev_state *mdev_state;
mdev_state = find_mdev_state_by_uuid(uuid);
if (!mdev_state) {
pr_info("%s: mdev not found\n", __func__);
return -EINVAL;
}
if ((mdev_state->irq_index == VFIO_PCI_MSI_IRQ_INDEX) && if ((mdev_state->irq_index == VFIO_PCI_MSI_IRQ_INDEX) &&
(!mdev_state->msi_evtfd)) (!mdev_state->msi_evtfd))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment