Message ID | 1487515629-13815-3-git-send-email-tianyu.lan@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Loop Jacob and Ashok. > -----Original Message----- > From: Lan, Tianyu > Sent: Sunday, February 19, 2017 10:47 PM > To: kvm@vger.kernel.org > Cc: Lan, Tianyu <tianyu.lan@intel.com>; Tian, Kevin <kevin.tian@intel.com>; > mst@redhat.com; jan.kiszka@siemens.com; jasowang@redhat.com; > peterx@redhat.com; david@gibson.dropbear.id.au; > alex.williamson@redhat.com; Liu, Yi L <yi.l.liu@intel.com> > Subject: [RFC PATCH 2/3] VFIO: Add IOMMU fault notifier callback > > This patch is to add callback to handle fault event reported by IOMMU driver. > Callback stores fault into an array and notify userspace via eventfd to read fault > info. > > Signed-off-by: Lan Tianyu <tianyu.lan@intel.com> > --- > drivers/vfio/vfio_iommu_type1.c | 30 ++++++++++++++++++++++++++++++ > include/linux/iommu.h | 7 +++++++ > include/uapi/linux/vfio.h | 7 +++++++ > 3 files changed, 44 insertions(+) > > diff --git a/drivers/vfio/vfio_iommu_type1.c > b/drivers/vfio/vfio_iommu_type1.c index 46674ea..dc434a3 100644 > --- a/drivers/vfio/vfio_iommu_type1.c > +++ b/drivers/vfio/vfio_iommu_type1.c > @@ -56,6 +56,8 @@ > MODULE_PARM_DESC(disable_hugepages, > "Disable VFIO IOMMU support for IOMMU hugepages."); > > +#define NR_IOMMU_FAULT_INFO 10 > + > struct vfio_iommu { > struct list_head domain_list; > struct vfio_domain *external_domain; /* domain for external user > */ > @@ -64,6 +66,9 @@ struct vfio_iommu { > struct blocking_notifier_head notifier; > struct eventfd_ctx *iommu_fault_fd; > struct mutex fault_lock; > + struct vfio_iommu_fault_info fault_info[NR_IOMMU_FAULT_INFO]; > + struct blocking_notifier_head iommu_fault_notifier; > + u8 fault_count; > bool v2; > bool nesting; > }; > @@ -1456,6 +1461,7 @@ static void *vfio_iommu_type1_open(unsigned long > arg) > iommu->dma_list = RB_ROOT; > mutex_init(&iommu->lock); > mutex_init(&iommu->fault_lock); > + iommu->fault_count = 0; > BLOCKING_INIT_NOTIFIER_HEAD(&iommu->notifier); > > return iommu; > @@ -1516,6 +1522,30 @@ static int vfio_domains_have_iommu_cache(struct > vfio_iommu *iommu) > return ret; > } > > +static int vfio_iommu_fault_event_notifier(struct notifier_block *nb, > + struct iommu_fault_info *fault_info, > + void *data) > +{ > + struct vfio_iommu *iommu = data; > + struct vfio_iommu_fault_info *info; > + > + mutex_lock(&iommu->fault_lock); > + > + info = &iommu->fault_info[iommu->fault_count]; > + info->addr = fault_info->addr; > + info->sid = fault_info->sid; > + info->fault_reason = fault_info->fault_reason; > + info->is_write = fault_info->is_write; > + > + iommu->fault_count++; > + > + if (iommu->iommu_fault_fd) > + eventfd_signal(iommu->iommu_fault_fd, 1); > + > + mutex_unlock(&iommu->fault_lock); > + return 0; > +} > + > static long vfio_iommu_type1_ioctl(void *iommu_data, > unsigned int cmd, unsigned long arg) { diff --git > a/include/linux/iommu.h b/include/linux/iommu.h index 0ff5111..b6a7bdb > 100644 > --- a/include/linux/iommu.h > +++ b/include/linux/iommu.h > @@ -86,6 +86,13 @@ struct iommu_domain { > void *iova_cookie; > }; > > +struct iommu_fault_info { > + __u64 addr; > + __u16 sid; > + __u8 fault_reason; > + __u8 is_write:1; > +}; > + > enum iommu_cap { > IOMMU_CAP_CACHE_COHERENCY, /* IOMMU can enforce cache > coherent DMA > transactions */ > diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h index > 8616334..da359dd 100644 > --- a/include/uapi/linux/vfio.h > +++ b/include/uapi/linux/vfio.h > @@ -562,6 +562,13 @@ struct vfio_iommu_type1_set_fault_eventfd { > > #define VFIO_IOMMU_SET_FAULT_EVENTFD _IO(VFIO_TYPE, VFIO_BASE + 17) > > +struct vfio_iommu_fault_info { > + __u64 addr; > + __u16 sid; > + __u8 fault_reason; > + __u8 is_write:1; > +}; > + > /* -------- Additional API for SPAPR TCE (Server POWERPC) IOMMU -------- */ > > /* > -- > 1.8.3.1
On Sun, 19 Feb 2017 22:47:08 +0800 Lan Tianyu <tianyu.lan@intel.com> wrote: > This patch is to add callback to handle fault event reported by > IOMMU driver. Callback stores fault into an array and notify userspace > via eventfd to read fault info. > > Signed-off-by: Lan Tianyu <tianyu.lan@intel.com> > --- > drivers/vfio/vfio_iommu_type1.c | 30 ++++++++++++++++++++++++++++++ > include/linux/iommu.h | 7 +++++++ > include/uapi/linux/vfio.h | 7 +++++++ > 3 files changed, 44 insertions(+) > > diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c > index 46674ea..dc434a3 100644 > --- a/drivers/vfio/vfio_iommu_type1.c > +++ b/drivers/vfio/vfio_iommu_type1.c > @@ -56,6 +56,8 @@ > MODULE_PARM_DESC(disable_hugepages, > "Disable VFIO IOMMU support for IOMMU hugepages."); > > +#define NR_IOMMU_FAULT_INFO 10 How is this value determined? > + > struct vfio_iommu { > struct list_head domain_list; > struct vfio_domain *external_domain; /* domain for external user */ > @@ -64,6 +66,9 @@ struct vfio_iommu { > struct blocking_notifier_head notifier; > struct eventfd_ctx *iommu_fault_fd; > struct mutex fault_lock; > + struct vfio_iommu_fault_info fault_info[NR_IOMMU_FAULT_INFO]; > + struct blocking_notifier_head iommu_fault_notifier; > + u8 fault_count; > bool v2; > bool nesting; > }; > @@ -1456,6 +1461,7 @@ static void *vfio_iommu_type1_open(unsigned long arg) > iommu->dma_list = RB_ROOT; > mutex_init(&iommu->lock); > mutex_init(&iommu->fault_lock); > + iommu->fault_count = 0; > BLOCKING_INIT_NOTIFIER_HEAD(&iommu->notifier); > > return iommu; > @@ -1516,6 +1522,30 @@ static int vfio_domains_have_iommu_cache(struct vfio_iommu *iommu) > return ret; > } > > +static int vfio_iommu_fault_event_notifier(struct notifier_block *nb, > + struct iommu_fault_info *fault_info, > + void *data) > +{ > + struct vfio_iommu *iommu = data; > + struct vfio_iommu_fault_info *info; > + > + mutex_lock(&iommu->fault_lock); > + > + info = &iommu->fault_info[iommu->fault_count]; > + info->addr = fault_info->addr; > + info->sid = fault_info->sid; > + info->fault_reason = fault_info->fault_reason; > + info->is_write = fault_info->is_write; > + > + iommu->fault_count++; > + > + if (iommu->iommu_fault_fd) > + eventfd_signal(iommu->iommu_fault_fd, 1); > + > + mutex_unlock(&iommu->fault_lock); > + return 0; > +} This notifier is never registered as any sort of IOMMU fault reporting infrastructure is currently imaginary, and the iommu development list isn't cc'd. > + > static long vfio_iommu_type1_ioctl(void *iommu_data, > unsigned int cmd, unsigned long arg) > { > diff --git a/include/linux/iommu.h b/include/linux/iommu.h > index 0ff5111..b6a7bdb 100644 > --- a/include/linux/iommu.h > +++ b/include/linux/iommu.h > @@ -86,6 +86,13 @@ struct iommu_domain { > void *iova_cookie; > }; > > +struct iommu_fault_info { > + __u64 addr; > + __u16 sid; > + __u8 fault_reason; > + __u8 is_write:1; > +}; A common fault reporting structure would need to be agreed upon by all parties, ie. everyone that current supporting the IOMMU API. As used in QEMU, the fault_reason here appears to be very VT-d specific. > + > enum iommu_cap { > IOMMU_CAP_CACHE_COHERENCY, /* IOMMU can enforce cache coherent DMA > transactions */ > diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h > index 8616334..da359dd 100644 > --- a/include/uapi/linux/vfio.h > +++ b/include/uapi/linux/vfio.h > @@ -562,6 +562,13 @@ struct vfio_iommu_type1_set_fault_eventfd { > > #define VFIO_IOMMU_SET_FAULT_EVENTFD _IO(VFIO_TYPE, VFIO_BASE + 17) > > +struct vfio_iommu_fault_info { > + __u64 addr; > + __u16 sid; > + __u8 fault_reason; > + __u8 is_write:1; > +}; > + > /* -------- Additional API for SPAPR TCE (Server POWERPC) IOMMU -------- */ > > /*
On Sun, Feb 19, 2017 at 10:47:08PM +0800, Lan Tianyu wrote: > This patch is to add callback to handle fault event reported by > IOMMU driver. Callback stores fault into an array and notify userspace > via eventfd to read fault info. > > Signed-off-by: Lan Tianyu <tianyu.lan@intel.com> > --- > drivers/vfio/vfio_iommu_type1.c | 30 ++++++++++++++++++++++++++++++ > include/linux/iommu.h | 7 +++++++ > include/uapi/linux/vfio.h | 7 +++++++ > 3 files changed, 44 insertions(+) > > diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c > index 46674ea..dc434a3 100644 > --- a/drivers/vfio/vfio_iommu_type1.c > +++ b/drivers/vfio/vfio_iommu_type1.c > @@ -56,6 +56,8 @@ > MODULE_PARM_DESC(disable_hugepages, > "Disable VFIO IOMMU support for IOMMU hugepages."); > > +#define NR_IOMMU_FAULT_INFO 10 > + > struct vfio_iommu { > struct list_head domain_list; > struct vfio_domain *external_domain; /* domain for external user */ > @@ -64,6 +66,9 @@ struct vfio_iommu { > struct blocking_notifier_head notifier; > struct eventfd_ctx *iommu_fault_fd; > struct mutex fault_lock; > + struct vfio_iommu_fault_info fault_info[NR_IOMMU_FAULT_INFO]; What if you run out of this space? Userspace will not see any more faults. What will cause progress to happen? > + struct blocking_notifier_head iommu_fault_notifier; > + u8 fault_count; > bool v2; > bool nesting; > }; > @@ -1456,6 +1461,7 @@ static void *vfio_iommu_type1_open(unsigned long arg) > iommu->dma_list = RB_ROOT; > mutex_init(&iommu->lock); > mutex_init(&iommu->fault_lock); > + iommu->fault_count = 0; > BLOCKING_INIT_NOTIFIER_HEAD(&iommu->notifier); > > return iommu; > @@ -1516,6 +1522,30 @@ static int vfio_domains_have_iommu_cache(struct vfio_iommu *iommu) > return ret; > } > > +static int vfio_iommu_fault_event_notifier(struct notifier_block *nb, > + struct iommu_fault_info *fault_info, > + void *data) > +{ > + struct vfio_iommu *iommu = data; > + struct vfio_iommu_fault_info *info; > + > + mutex_lock(&iommu->fault_lock); > + > + info = &iommu->fault_info[iommu->fault_count]; > + info->addr = fault_info->addr; > + info->sid = fault_info->sid; > + info->fault_reason = fault_info->fault_reason; > + info->is_write = fault_info->is_write; > + > + iommu->fault_count++; Will corrupt memory once array overflows NR_IOMMU_FAULT_INFO. > + > + if (iommu->iommu_fault_fd) > + eventfd_signal(iommu->iommu_fault_fd, 1); > + > + mutex_unlock(&iommu->fault_lock); > + return 0; > +} > + > static long vfio_iommu_type1_ioctl(void *iommu_data, > unsigned int cmd, unsigned long arg) > { > diff --git a/include/linux/iommu.h b/include/linux/iommu.h > index 0ff5111..b6a7bdb 100644 > --- a/include/linux/iommu.h > +++ b/include/linux/iommu.h > @@ -86,6 +86,13 @@ struct iommu_domain { > void *iova_cookie; > }; > > +struct iommu_fault_info { > + __u64 addr; > + __u16 sid; > + __u8 fault_reason; > + __u8 is_write:1; > +}; > + > enum iommu_cap { > IOMMU_CAP_CACHE_COHERENCY, /* IOMMU can enforce cache coherent DMA > transactions */ > diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h > index 8616334..da359dd 100644 > --- a/include/uapi/linux/vfio.h > +++ b/include/uapi/linux/vfio.h > @@ -562,6 +562,13 @@ struct vfio_iommu_type1_set_fault_eventfd { > > #define VFIO_IOMMU_SET_FAULT_EVENTFD _IO(VFIO_TYPE, VFIO_BASE + 17) > > +struct vfio_iommu_fault_info { > + __u64 addr; > + __u16 sid; It's not clear it's userspace's business to know the sid. It normally does not care once management has bound vfio to a device. You should use a device identifier that makes sense. > + __u8 fault_reason; > + __u8 is_write:1; > +}; > + > /* -------- Additional API for SPAPR TCE (Server POWERPC) IOMMU -------- */ > > /* > -- > 1.8.3.1
On 2017年02月21日 04:53, Alex Williamson wrote: > On Sun, 19 Feb 2017 22:47:08 +0800 > Lan Tianyu <tianyu.lan@intel.com> wrote: > >> This patch is to add callback to handle fault event reported by >> IOMMU driver. Callback stores fault into an array and notify userspace >> via eventfd to read fault info. >> >> Signed-off-by: Lan Tianyu <tianyu.lan@intel.com> >> --- >> drivers/vfio/vfio_iommu_type1.c | 30 ++++++++++++++++++++++++++++++ >> include/linux/iommu.h | 7 +++++++ >> include/uapi/linux/vfio.h | 7 +++++++ >> 3 files changed, 44 insertions(+) >> >> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c >> index 46674ea..dc434a3 100644 >> --- a/drivers/vfio/vfio_iommu_type1.c >> +++ b/drivers/vfio/vfio_iommu_type1.c >> @@ -56,6 +56,8 @@ >> MODULE_PARM_DESC(disable_hugepages, >> "Disable VFIO IOMMU support for IOMMU hugepages."); >> >> +#define NR_IOMMU_FAULT_INFO 10 > > How is this value determined? The length of fault info array is defined by manually. It's hard to estimate how many fault info entry will be queued in the array. > >> + >> struct vfio_iommu { >> struct list_head domain_list; >> struct vfio_domain *external_domain; /* domain for external user */ >> @@ -64,6 +66,9 @@ struct vfio_iommu { >> struct blocking_notifier_head notifier; >> struct eventfd_ctx *iommu_fault_fd; >> struct mutex fault_lock; >> + struct vfio_iommu_fault_info fault_info[NR_IOMMU_FAULT_INFO]; >> + struct blocking_notifier_head iommu_fault_notifier; >> + u8 fault_count; >> bool v2; >> bool nesting; >> }; >> @@ -1456,6 +1461,7 @@ static void *vfio_iommu_type1_open(unsigned long arg) >> iommu->dma_list = RB_ROOT; >> mutex_init(&iommu->lock); >> mutex_init(&iommu->fault_lock); >> + iommu->fault_count = 0; >> BLOCKING_INIT_NOTIFIER_HEAD(&iommu->notifier); >> >> return iommu; >> @@ -1516,6 +1522,30 @@ static int vfio_domains_have_iommu_cache(struct vfio_iommu *iommu) >> return ret; >> } >> >> +static int vfio_iommu_fault_event_notifier(struct notifier_block *nb, >> + struct iommu_fault_info *fault_info, >> + void *data) >> +{ >> + struct vfio_iommu *iommu = data; >> + struct vfio_iommu_fault_info *info; >> + >> + mutex_lock(&iommu->fault_lock); >> + >> + info = &iommu->fault_info[iommu->fault_count]; >> + info->addr = fault_info->addr; >> + info->sid = fault_info->sid; >> + info->fault_reason = fault_info->fault_reason; >> + info->is_write = fault_info->is_write; >> + >> + iommu->fault_count++; >> + >> + if (iommu->iommu_fault_fd) >> + eventfd_signal(iommu->iommu_fault_fd, 1); >> + >> + mutex_unlock(&iommu->fault_lock); >> + return 0; >> +} > > > This notifier is never registered as any sort of IOMMU fault reporting > infrastructure is currently imaginary, and the iommu development list > isn't cc'd. Yes, I should cc IOMM maillist. I thought this patchset was to determine new VFIO API and so... > >> + >> static long vfio_iommu_type1_ioctl(void *iommu_data, >> unsigned int cmd, unsigned long arg) >> { >> diff --git a/include/linux/iommu.h b/include/linux/iommu.h >> index 0ff5111..b6a7bdb 100644 >> --- a/include/linux/iommu.h >> +++ b/include/linux/iommu.h >> @@ -86,6 +86,13 @@ struct iommu_domain { >> void *iova_cookie; >> }; >> >> +struct iommu_fault_info { >> + __u64 addr; >> + __u16 sid; >> + __u8 fault_reason; >> + __u8 is_write:1; >> +}; > > > A common fault reporting structure would need to be agreed upon by all > parties, ie. everyone that current supporting the IOMMU API. As used > in QEMU, the fault_reason here appears to be very VT-d specific. Fault reason number will be platform specific and it'd hard to use a common definition to show fault reason number of all platforms. I wonder whether we can define a vendor field in the fault info and consumer can use the vendor field to deal with platform specific info.
On 2017年02月21日 13:55, Michael S. Tsirkin wrote: > On Sun, Feb 19, 2017 at 10:47:08PM +0800, Lan Tianyu wrote: >> This patch is to add callback to handle fault event reported by >> IOMMU driver. Callback stores fault into an array and notify userspace >> via eventfd to read fault info. >> >> Signed-off-by: Lan Tianyu <tianyu.lan@intel.com> >> --- >> drivers/vfio/vfio_iommu_type1.c | 30 ++++++++++++++++++++++++++++++ >> include/linux/iommu.h | 7 +++++++ >> include/uapi/linux/vfio.h | 7 +++++++ >> 3 files changed, 44 insertions(+) >> >> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c >> index 46674ea..dc434a3 100644 >> --- a/drivers/vfio/vfio_iommu_type1.c >> +++ b/drivers/vfio/vfio_iommu_type1.c >> @@ -56,6 +56,8 @@ >> MODULE_PARM_DESC(disable_hugepages, >> "Disable VFIO IOMMU support for IOMMU hugepages."); >> >> +#define NR_IOMMU_FAULT_INFO 10 >> + >> struct vfio_iommu { >> struct list_head domain_list; >> struct vfio_domain *external_domain; /* domain for external user */ >> @@ -64,6 +66,9 @@ struct vfio_iommu { >> struct blocking_notifier_head notifier; >> struct eventfd_ctx *iommu_fault_fd; >> struct mutex fault_lock; >> + struct vfio_iommu_fault_info fault_info[NR_IOMMU_FAULT_INFO]; > > What if you run out of this space? Userspace will not > see any more faults. What will cause progress to happen? When userspace gets fault info via new VFIO cmd, the fault_info in arry will be clear. If userspace doesn't get fault info after triggering fault event fd, the surplus fault info will be ignored. > > >> + struct blocking_notifier_head iommu_fault_notifier; >> + u8 fault_count; >> bool v2; >> bool nesting; >> }; >> @@ -1456,6 +1461,7 @@ static void *vfio_iommu_type1_open(unsigned long arg) >> iommu->dma_list = RB_ROOT; >> mutex_init(&iommu->lock); >> mutex_init(&iommu->fault_lock); >> + iommu->fault_count = 0; >> BLOCKING_INIT_NOTIFIER_HEAD(&iommu->notifier); >> >> return iommu; >> @@ -1516,6 +1522,30 @@ static int vfio_domains_have_iommu_cache(struct vfio_iommu *iommu) >> return ret; >> } >> >> +static int vfio_iommu_fault_event_notifier(struct notifier_block *nb, >> + struct iommu_fault_info *fault_info, >> + void *data) >> +{ >> + struct vfio_iommu *iommu = data; >> + struct vfio_iommu_fault_info *info; >> + >> + mutex_lock(&iommu->fault_lock); >> + >> + info = &iommu->fault_info[iommu->fault_count]; >> + info->addr = fault_info->addr; >> + info->sid = fault_info->sid; >> + info->fault_reason = fault_info->fault_reason; >> + info->is_write = fault_info->is_write; >> + >> + iommu->fault_count++; > > Will corrupt memory once array overflows NR_IOMMU_FAULT_INFO. Yes, I miss check of NR_IOMMU_FAULT_INFO Here. Thanks. > > >> + >> + if (iommu->iommu_fault_fd) >> + eventfd_signal(iommu->iommu_fault_fd, 1); >> + >> + mutex_unlock(&iommu->fault_lock); >> + return 0; >> +} >> + >> static long vfio_iommu_type1_ioctl(void *iommu_data, >> unsigned int cmd, unsigned long arg) >> { >> diff --git a/include/linux/iommu.h b/include/linux/iommu.h >> index 0ff5111..b6a7bdb 100644 >> --- a/include/linux/iommu.h >> +++ b/include/linux/iommu.h >> @@ -86,6 +86,13 @@ struct iommu_domain { >> void *iova_cookie; >> }; >> >> +struct iommu_fault_info { >> + __u64 addr; >> + __u16 sid; >> + __u8 fault_reason; >> + __u8 is_write:1; >> +}; >> + >> enum iommu_cap { >> IOMMU_CAP_CACHE_COHERENCY, /* IOMMU can enforce cache coherent DMA >> transactions */ >> diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h >> index 8616334..da359dd 100644 >> --- a/include/uapi/linux/vfio.h >> +++ b/include/uapi/linux/vfio.h >> @@ -562,6 +562,13 @@ struct vfio_iommu_type1_set_fault_eventfd { >> >> #define VFIO_IOMMU_SET_FAULT_EVENTFD _IO(VFIO_TYPE, VFIO_BASE + 17) >> >> +struct vfio_iommu_fault_info { >> + __u64 addr; >> + __u16 sid; > > It's not clear it's userspace's business to know the sid. It normally > does not care once management has bound vfio to a device. You should use > a device identifier that makes sense. Yes, How about "bdf"? > > >> + __u8 fault_reason; >> + __u8 is_write:1; >> +}; >> + >> /* -------- Additional API for SPAPR TCE (Server POWERPC) IOMMU -------- */ >> >> /* >> -- >> 1.8.3.1
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 46674ea..dc434a3 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -56,6 +56,8 @@ MODULE_PARM_DESC(disable_hugepages, "Disable VFIO IOMMU support for IOMMU hugepages."); +#define NR_IOMMU_FAULT_INFO 10 + struct vfio_iommu { struct list_head domain_list; struct vfio_domain *external_domain; /* domain for external user */ @@ -64,6 +66,9 @@ struct vfio_iommu { struct blocking_notifier_head notifier; struct eventfd_ctx *iommu_fault_fd; struct mutex fault_lock; + struct vfio_iommu_fault_info fault_info[NR_IOMMU_FAULT_INFO]; + struct blocking_notifier_head iommu_fault_notifier; + u8 fault_count; bool v2; bool nesting; }; @@ -1456,6 +1461,7 @@ static void *vfio_iommu_type1_open(unsigned long arg) iommu->dma_list = RB_ROOT; mutex_init(&iommu->lock); mutex_init(&iommu->fault_lock); + iommu->fault_count = 0; BLOCKING_INIT_NOTIFIER_HEAD(&iommu->notifier); return iommu; @@ -1516,6 +1522,30 @@ static int vfio_domains_have_iommu_cache(struct vfio_iommu *iommu) return ret; } +static int vfio_iommu_fault_event_notifier(struct notifier_block *nb, + struct iommu_fault_info *fault_info, + void *data) +{ + struct vfio_iommu *iommu = data; + struct vfio_iommu_fault_info *info; + + mutex_lock(&iommu->fault_lock); + + info = &iommu->fault_info[iommu->fault_count]; + info->addr = fault_info->addr; + info->sid = fault_info->sid; + info->fault_reason = fault_info->fault_reason; + info->is_write = fault_info->is_write; + + iommu->fault_count++; + + if (iommu->iommu_fault_fd) + eventfd_signal(iommu->iommu_fault_fd, 1); + + mutex_unlock(&iommu->fault_lock); + return 0; +} + static long vfio_iommu_type1_ioctl(void *iommu_data, unsigned int cmd, unsigned long arg) { diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 0ff5111..b6a7bdb 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -86,6 +86,13 @@ struct iommu_domain { void *iova_cookie; }; +struct iommu_fault_info { + __u64 addr; + __u16 sid; + __u8 fault_reason; + __u8 is_write:1; +}; + enum iommu_cap { IOMMU_CAP_CACHE_COHERENCY, /* IOMMU can enforce cache coherent DMA transactions */ diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h index 8616334..da359dd 100644 --- a/include/uapi/linux/vfio.h +++ b/include/uapi/linux/vfio.h @@ -562,6 +562,13 @@ struct vfio_iommu_type1_set_fault_eventfd { #define VFIO_IOMMU_SET_FAULT_EVENTFD _IO(VFIO_TYPE, VFIO_BASE + 17) +struct vfio_iommu_fault_info { + __u64 addr; + __u16 sid; + __u8 fault_reason; + __u8 is_write:1; +}; + /* -------- Additional API for SPAPR TCE (Server POWERPC) IOMMU -------- */ /*
This patch is to add callback to handle fault event reported by IOMMU driver. Callback stores fault into an array and notify userspace via eventfd to read fault info. Signed-off-by: Lan Tianyu <tianyu.lan@intel.com> --- drivers/vfio/vfio_iommu_type1.c | 30 ++++++++++++++++++++++++++++++ include/linux/iommu.h | 7 +++++++ include/uapi/linux/vfio.h | 7 +++++++ 3 files changed, 44 insertions(+)