Message ID | 20240911052255.1294071-13-zhenzhong.duan@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | intel_iommu: Enable stage-1 translation for emulated device | expand |
On Wed, Sep 11, 2024 at 1:27 PM Zhenzhong Duan <zhenzhong.duan@intel.com> wrote: > > From: Clément Mathieu--Drif <clement.mathieu--drif@eviden.com> > > Signed-off-by: Clément Mathieu--Drif <clement.mathieu--drif@eviden.com> > Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> > --- > hw/i386/intel_iommu_internal.h | 11 ++++++++ > hw/i386/intel_iommu.c | 50 ++++++++++++++++++++++++++++++++++ > 2 files changed, 61 insertions(+) > > diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h > index 4f2c3a9350..52bdbf3bc5 100644 > --- a/hw/i386/intel_iommu_internal.h > +++ b/hw/i386/intel_iommu_internal.h > @@ -375,6 +375,7 @@ typedef union VTDInvDesc VTDInvDesc; > #define VTD_INV_DESC_WAIT 0x5 /* Invalidation Wait Descriptor */ > #define VTD_INV_DESC_PIOTLB 0x6 /* PASID-IOTLB Invalidate Desc */ > #define VTD_INV_DESC_PC 0x7 /* PASID-cache Invalidate Desc */ > +#define VTD_INV_DESC_DEV_PIOTLB 0x8 /* PASID-based-DIOTLB inv_desc*/ > #define VTD_INV_DESC_NONE 0 /* Not an Invalidate Descriptor */ > > /* Masks for Invalidation Wait Descriptor*/ > @@ -413,6 +414,16 @@ typedef union VTDInvDesc VTDInvDesc; > #define VTD_INV_DESC_DEVICE_IOTLB_RSVD_HI 0xffeULL > #define VTD_INV_DESC_DEVICE_IOTLB_RSVD_LO 0xffff0000ffe0fff8 > > +/* Mask for PASID Device IOTLB Invalidate Descriptor */ > +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_ADDR(val) ((val) & \ > + 0xfffffffffffff000ULL) > +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_SIZE(val) ((val >> 11) & 0x1) > +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_GLOBAL(val) ((val) & 0x1) > +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_SID(val) (((val) >> 16) & 0xffffULL) > +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_PASID(val) ((val >> 32) & 0xfffffULL) > +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_HI 0x7feULL > +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_LO 0xfff000000000f000ULL > + > /* Rsvd field masks for spte */ > #define VTD_SPTE_SNP 0x800ULL > > diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c > index d28c862598..4cf56924e1 100644 > --- a/hw/i386/intel_iommu.c > +++ b/hw/i386/intel_iommu.c > @@ -3017,6 +3017,49 @@ static void do_invalidate_device_tlb(VTDAddressSpace *vtd_dev_as, > memory_region_notify_iommu(&vtd_dev_as->iommu, 0, event); > } > > +static bool vtd_process_device_piotlb_desc(IntelIOMMUState *s, > + VTDInvDesc *inv_desc) > +{ > + uint16_t sid; > + VTDAddressSpace *vtd_dev_as; > + bool size; > + bool global; > + hwaddr addr; > + uint32_t pasid; > + > + if ((inv_desc->hi & VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_HI) || > + (inv_desc->lo & VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_LO)) { > + error_report_once("%s: invalid pasid-based dev iotlb inv desc:" > + "hi=%"PRIx64 "(reserved nonzero)", > + __func__, inv_desc->hi); > + return false; > + } > + > + global = VTD_INV_DESC_PASID_DEVICE_IOTLB_GLOBAL(inv_desc->hi); > + size = VTD_INV_DESC_PASID_DEVICE_IOTLB_SIZE(inv_desc->hi); > + addr = VTD_INV_DESC_PASID_DEVICE_IOTLB_ADDR(inv_desc->hi); > + sid = VTD_INV_DESC_PASID_DEVICE_IOTLB_SID(inv_desc->lo); > + if (global) { > + QLIST_FOREACH(vtd_dev_as, &s->vtd_as_with_notifiers, next) { > + if ((vtd_dev_as->pasid != PCI_NO_PASID) && > + (PCI_BUILD_BDF(pci_bus_num(vtd_dev_as->bus), > + vtd_dev_as->devfn) == sid)) { > + do_invalidate_device_tlb(vtd_dev_as, size, addr); > + } > + } > + } else { > + pasid = VTD_INV_DESC_PASID_DEVICE_IOTLB_PASID(inv_desc->lo); > + vtd_dev_as = vtd_get_as_by_sid_and_pasid(s, sid, pasid); > + if (!vtd_dev_as) { > + return true; > + } > + > + do_invalidate_device_tlb(vtd_dev_as, size, addr); Question: I wonder if current vhost (which has a device IOTLB abstraction via virtio-pci) can work with this (PASID based IOTLB invalidation) THanks > + } > + > + return true; > +} > + > static bool vtd_process_device_iotlb_desc(IntelIOMMUState *s, > VTDInvDesc *inv_desc) > { > @@ -3111,6 +3154,13 @@ static bool vtd_process_inv_desc(IntelIOMMUState *s) > } > break; > > + case VTD_INV_DESC_DEV_PIOTLB: > + trace_vtd_inv_desc("device-piotlb", inv_desc.hi, inv_desc.lo); > + if (!vtd_process_device_piotlb_desc(s, &inv_desc)) { > + return false; > + } > + break; > + > case VTD_INV_DESC_DEVICE: > trace_vtd_inv_desc("device", inv_desc.hi, inv_desc.lo); > if (!vtd_process_device_iotlb_desc(s, &inv_desc)) { > -- > 2.34.1 >
>-----Original Message----- >From: Jason Wang <jasowang@redhat.com> >Subject: Re: [PATCH v3 12/17] intel_iommu: Add support for PASID-based >device IOTLB invalidation > >On Wed, Sep 11, 2024 at 1:27 PM Zhenzhong Duan ><zhenzhong.duan@intel.com> wrote: >> >> From: Clément Mathieu--Drif <clement.mathieu--drif@eviden.com> >> >> Signed-off-by: Clément Mathieu--Drif <clement.mathieu--drif@eviden.com> >> Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> >> --- >> hw/i386/intel_iommu_internal.h | 11 ++++++++ >> hw/i386/intel_iommu.c | 50 >++++++++++++++++++++++++++++++++++ >> 2 files changed, 61 insertions(+) >> >> diff --git a/hw/i386/intel_iommu_internal.h >b/hw/i386/intel_iommu_internal.h >> index 4f2c3a9350..52bdbf3bc5 100644 >> --- a/hw/i386/intel_iommu_internal.h >> +++ b/hw/i386/intel_iommu_internal.h >> @@ -375,6 +375,7 @@ typedef union VTDInvDesc VTDInvDesc; >> #define VTD_INV_DESC_WAIT 0x5 /* Invalidation Wait Descriptor >*/ >> #define VTD_INV_DESC_PIOTLB 0x6 /* PASID-IOTLB Invalidate Desc >*/ >> #define VTD_INV_DESC_PC 0x7 /* PASID-cache Invalidate Desc */ >> +#define VTD_INV_DESC_DEV_PIOTLB 0x8 /* PASID-based-DIOTLB >inv_desc*/ >> #define VTD_INV_DESC_NONE 0 /* Not an Invalidate Descriptor >*/ >> >> /* Masks for Invalidation Wait Descriptor*/ >> @@ -413,6 +414,16 @@ typedef union VTDInvDesc VTDInvDesc; >> #define VTD_INV_DESC_DEVICE_IOTLB_RSVD_HI 0xffeULL >> #define VTD_INV_DESC_DEVICE_IOTLB_RSVD_LO 0xffff0000ffe0fff8 >> >> +/* Mask for PASID Device IOTLB Invalidate Descriptor */ >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_ADDR(val) ((val) & \ >> + 0xfffffffffffff000ULL) >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_SIZE(val) ((val >> 11) & 0x1) >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_GLOBAL(val) ((val) & 0x1) >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_SID(val) (((val) >> 16) & >0xffffULL) >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_PASID(val) ((val >> 32) & >0xfffffULL) >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_HI 0x7feULL >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_LO >0xfff000000000f000ULL >> + >> /* Rsvd field masks for spte */ >> #define VTD_SPTE_SNP 0x800ULL >> >> diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c >> index d28c862598..4cf56924e1 100644 >> --- a/hw/i386/intel_iommu.c >> +++ b/hw/i386/intel_iommu.c >> @@ -3017,6 +3017,49 @@ static void >do_invalidate_device_tlb(VTDAddressSpace *vtd_dev_as, >> memory_region_notify_iommu(&vtd_dev_as->iommu, 0, event); >> } >> >> +static bool vtd_process_device_piotlb_desc(IntelIOMMUState *s, >> + VTDInvDesc *inv_desc) >> +{ >> + uint16_t sid; >> + VTDAddressSpace *vtd_dev_as; >> + bool size; >> + bool global; >> + hwaddr addr; >> + uint32_t pasid; >> + >> + if ((inv_desc->hi & VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_HI) || >> + (inv_desc->lo & VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_LO)) { >> + error_report_once("%s: invalid pasid-based dev iotlb inv desc:" >> + "hi=%"PRIx64 "(reserved nonzero)", >> + __func__, inv_desc->hi); >> + return false; >> + } >> + >> + global = VTD_INV_DESC_PASID_DEVICE_IOTLB_GLOBAL(inv_desc->hi); >> + size = VTD_INV_DESC_PASID_DEVICE_IOTLB_SIZE(inv_desc->hi); >> + addr = VTD_INV_DESC_PASID_DEVICE_IOTLB_ADDR(inv_desc->hi); >> + sid = VTD_INV_DESC_PASID_DEVICE_IOTLB_SID(inv_desc->lo); >> + if (global) { >> + QLIST_FOREACH(vtd_dev_as, &s->vtd_as_with_notifiers, next) { >> + if ((vtd_dev_as->pasid != PCI_NO_PASID) && >> + (PCI_BUILD_BDF(pci_bus_num(vtd_dev_as->bus), >> + vtd_dev_as->devfn) == sid)) { >> + do_invalidate_device_tlb(vtd_dev_as, size, addr); >> + } >> + } >> + } else { >> + pasid = VTD_INV_DESC_PASID_DEVICE_IOTLB_PASID(inv_desc->lo); >> + vtd_dev_as = vtd_get_as_by_sid_and_pasid(s, sid, pasid); >> + if (!vtd_dev_as) { >> + return true; >> + } >> + >> + do_invalidate_device_tlb(vtd_dev_as, size, addr); > >Question: > >I wonder if current vhost (which has a device IOTLB abstraction via >virtio-pci) can work with this (PASID based IOTLB invalidation) Currently, it depends on if caching-mode is on. If it's off, vhost works. E.g.: -device intel-iommu,caching-mode=off,dma-drain=on,device-iotlb=on,x-scalable-mode=on -netdev tap,id=tap0,vhost=on,script=/etc/qemu-ifup -device virtio-net-pci,netdev=tap0,bus=root0,iommu_platform=on,ats=on It doesn't work currently when caching-mode is on. Reason is linux kernel has an optimization to send only piotlb invalidation, no device-piotlb invalidation is sent. But I heard from Yi the optimization will be dropped, then it will work too when caching-mode is on. Thanks Zhenzhong
>-----Original Message----- >From: Duan, Zhenzhong >Subject: RE: [PATCH v3 12/17] intel_iommu: Add support for PASID-based >device IOTLB invalidation > > > >>-----Original Message----- >>From: Jason Wang <jasowang@redhat.com> >>Subject: Re: [PATCH v3 12/17] intel_iommu: Add support for PASID-based >>device IOTLB invalidation >> >>On Wed, Sep 11, 2024 at 1:27 PM Zhenzhong Duan >><zhenzhong.duan@intel.com> wrote: >>> >>> From: Clément Mathieu--Drif <clement.mathieu--drif@eviden.com> >>> >>> Signed-off-by: Clément Mathieu--Drif <clement.mathieu-- >drif@eviden.com> >>> Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> >>> --- >>> hw/i386/intel_iommu_internal.h | 11 ++++++++ >>> hw/i386/intel_iommu.c | 50 >>++++++++++++++++++++++++++++++++++ >>> 2 files changed, 61 insertions(+) >>> >>> diff --git a/hw/i386/intel_iommu_internal.h >>b/hw/i386/intel_iommu_internal.h >>> index 4f2c3a9350..52bdbf3bc5 100644 >>> --- a/hw/i386/intel_iommu_internal.h >>> +++ b/hw/i386/intel_iommu_internal.h >>> @@ -375,6 +375,7 @@ typedef union VTDInvDesc VTDInvDesc; >>> #define VTD_INV_DESC_WAIT 0x5 /* Invalidation Wait >Descriptor >>*/ >>> #define VTD_INV_DESC_PIOTLB 0x6 /* PASID-IOTLB Invalidate >Desc >>*/ >>> #define VTD_INV_DESC_PC 0x7 /* PASID-cache Invalidate Desc >*/ >>> +#define VTD_INV_DESC_DEV_PIOTLB 0x8 /* PASID-based-DIOTLB >>inv_desc*/ >>> #define VTD_INV_DESC_NONE 0 /* Not an Invalidate Descriptor >>*/ >>> >>> /* Masks for Invalidation Wait Descriptor*/ >>> @@ -413,6 +414,16 @@ typedef union VTDInvDesc VTDInvDesc; >>> #define VTD_INV_DESC_DEVICE_IOTLB_RSVD_HI 0xffeULL >>> #define VTD_INV_DESC_DEVICE_IOTLB_RSVD_LO 0xffff0000ffe0fff8 >>> >>> +/* Mask for PASID Device IOTLB Invalidate Descriptor */ >>> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_ADDR(val) ((val) & \ >>> + 0xfffffffffffff000ULL) >>> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_SIZE(val) ((val >> 11) & >0x1) >>> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_GLOBAL(val) ((val) & 0x1) >>> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_SID(val) (((val) >> 16) & >>0xffffULL) >>> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_PASID(val) ((val >> 32) & >>0xfffffULL) >>> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_HI 0x7feULL >>> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_LO >>0xfff000000000f000ULL >>> + >>> /* Rsvd field masks for spte */ >>> #define VTD_SPTE_SNP 0x800ULL >>> >>> diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c >>> index d28c862598..4cf56924e1 100644 >>> --- a/hw/i386/intel_iommu.c >>> +++ b/hw/i386/intel_iommu.c >>> @@ -3017,6 +3017,49 @@ static void >>do_invalidate_device_tlb(VTDAddressSpace *vtd_dev_as, >>> memory_region_notify_iommu(&vtd_dev_as->iommu, 0, event); >>> } >>> >>> +static bool vtd_process_device_piotlb_desc(IntelIOMMUState *s, >>> + VTDInvDesc *inv_desc) >>> +{ >>> + uint16_t sid; >>> + VTDAddressSpace *vtd_dev_as; >>> + bool size; >>> + bool global; >>> + hwaddr addr; >>> + uint32_t pasid; >>> + >>> + if ((inv_desc->hi & VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_HI) || >>> + (inv_desc->lo & VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_LO)) { >>> + error_report_once("%s: invalid pasid-based dev iotlb inv desc:" >>> + "hi=%"PRIx64 "(reserved nonzero)", >>> + __func__, inv_desc->hi); >>> + return false; >>> + } >>> + >>> + global = VTD_INV_DESC_PASID_DEVICE_IOTLB_GLOBAL(inv_desc->hi); >>> + size = VTD_INV_DESC_PASID_DEVICE_IOTLB_SIZE(inv_desc->hi); >>> + addr = VTD_INV_DESC_PASID_DEVICE_IOTLB_ADDR(inv_desc->hi); >>> + sid = VTD_INV_DESC_PASID_DEVICE_IOTLB_SID(inv_desc->lo); >>> + if (global) { >>> + QLIST_FOREACH(vtd_dev_as, &s->vtd_as_with_notifiers, next) { >>> + if ((vtd_dev_as->pasid != PCI_NO_PASID) && >>> + (PCI_BUILD_BDF(pci_bus_num(vtd_dev_as->bus), >>> + vtd_dev_as->devfn) == sid)) { >>> + do_invalidate_device_tlb(vtd_dev_as, size, addr); >>> + } >>> + } >>> + } else { >>> + pasid = VTD_INV_DESC_PASID_DEVICE_IOTLB_PASID(inv_desc->lo); >>> + vtd_dev_as = vtd_get_as_by_sid_and_pasid(s, sid, pasid); >>> + if (!vtd_dev_as) { >>> + return true; >>> + } >>> + >>> + do_invalidate_device_tlb(vtd_dev_as, size, addr); >> >>Question: >> >>I wonder if current vhost (which has a device IOTLB abstraction via >>virtio-pci) can work with this (PASID based IOTLB invalidation) > >Currently, it depends on if caching-mode is on. If it's off, vhost works. E.g.: > >-device intel-iommu,caching-mode=off,dma-drain=on,device-iotlb=on,x- >scalable-mode=on >-netdev tap,id=tap0,vhost=on,script=/etc/qemu-ifup >-device virtio-net-pci,netdev=tap0,bus=root0,iommu_platform=on,ats=on Sorry, typo error on scalable mode parameter, should be: -device intel-iommu,caching-mode=off,dma-drain=on,device-iotlb=on,x-scalable-mode=modern -netdev tap,id=tap0,vhost=on,script=/etc/qemu-ifup -device virtio-net-pci,netdev=tap0,bus=root0,iommu_platform=on,ats=on Thanks Zhenzhong > >It doesn't work currently when caching-mode is on. >Reason is linux kernel has an optimization to send only piotlb invalidation, >no device-piotlb invalidation is sent. But I heard from Yi the optimization >will be dropped, then it will work too when caching-mode is on. > >Thanks >Zhenzhong
On Fri, Sep 27, 2024 at 3:18 PM Duan, Zhenzhong <zhenzhong.duan@intel.com> wrote: > > > > >-----Original Message----- > >From: Jason Wang <jasowang@redhat.com> > >Subject: Re: [PATCH v3 12/17] intel_iommu: Add support for PASID-based > >device IOTLB invalidation > > > >On Wed, Sep 11, 2024 at 1:27 PM Zhenzhong Duan > ><zhenzhong.duan@intel.com> wrote: > >> > >> From: Clément Mathieu--Drif <clement.mathieu--drif@eviden.com> > >> > >> Signed-off-by: Clément Mathieu--Drif <clement.mathieu--drif@eviden.com> > >> Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> > >> --- > >> hw/i386/intel_iommu_internal.h | 11 ++++++++ > >> hw/i386/intel_iommu.c | 50 > >++++++++++++++++++++++++++++++++++ > >> 2 files changed, 61 insertions(+) > >> > >> diff --git a/hw/i386/intel_iommu_internal.h > >b/hw/i386/intel_iommu_internal.h > >> index 4f2c3a9350..52bdbf3bc5 100644 > >> --- a/hw/i386/intel_iommu_internal.h > >> +++ b/hw/i386/intel_iommu_internal.h > >> @@ -375,6 +375,7 @@ typedef union VTDInvDesc VTDInvDesc; > >> #define VTD_INV_DESC_WAIT 0x5 /* Invalidation Wait Descriptor > >*/ > >> #define VTD_INV_DESC_PIOTLB 0x6 /* PASID-IOTLB Invalidate Desc > >*/ > >> #define VTD_INV_DESC_PC 0x7 /* PASID-cache Invalidate Desc */ > >> +#define VTD_INV_DESC_DEV_PIOTLB 0x8 /* PASID-based-DIOTLB > >inv_desc*/ > >> #define VTD_INV_DESC_NONE 0 /* Not an Invalidate Descriptor > >*/ > >> > >> /* Masks for Invalidation Wait Descriptor*/ > >> @@ -413,6 +414,16 @@ typedef union VTDInvDesc VTDInvDesc; > >> #define VTD_INV_DESC_DEVICE_IOTLB_RSVD_HI 0xffeULL > >> #define VTD_INV_DESC_DEVICE_IOTLB_RSVD_LO 0xffff0000ffe0fff8 > >> > >> +/* Mask for PASID Device IOTLB Invalidate Descriptor */ > >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_ADDR(val) ((val) & \ > >> + 0xfffffffffffff000ULL) > >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_SIZE(val) ((val >> 11) & 0x1) > >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_GLOBAL(val) ((val) & 0x1) > >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_SID(val) (((val) >> 16) & > >0xffffULL) > >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_PASID(val) ((val >> 32) & > >0xfffffULL) > >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_HI 0x7feULL > >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_LO > >0xfff000000000f000ULL > >> + > >> /* Rsvd field masks for spte */ > >> #define VTD_SPTE_SNP 0x800ULL > >> > >> diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c > >> index d28c862598..4cf56924e1 100644 > >> --- a/hw/i386/intel_iommu.c > >> +++ b/hw/i386/intel_iommu.c > >> @@ -3017,6 +3017,49 @@ static void > >do_invalidate_device_tlb(VTDAddressSpace *vtd_dev_as, > >> memory_region_notify_iommu(&vtd_dev_as->iommu, 0, event); > >> } > >> > >> +static bool vtd_process_device_piotlb_desc(IntelIOMMUState *s, > >> + VTDInvDesc *inv_desc) > >> +{ > >> + uint16_t sid; > >> + VTDAddressSpace *vtd_dev_as; > >> + bool size; > >> + bool global; > >> + hwaddr addr; > >> + uint32_t pasid; > >> + > >> + if ((inv_desc->hi & VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_HI) || > >> + (inv_desc->lo & VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_LO)) { > >> + error_report_once("%s: invalid pasid-based dev iotlb inv desc:" > >> + "hi=%"PRIx64 "(reserved nonzero)", > >> + __func__, inv_desc->hi); > >> + return false; > >> + } > >> + > >> + global = VTD_INV_DESC_PASID_DEVICE_IOTLB_GLOBAL(inv_desc->hi); > >> + size = VTD_INV_DESC_PASID_DEVICE_IOTLB_SIZE(inv_desc->hi); > >> + addr = VTD_INV_DESC_PASID_DEVICE_IOTLB_ADDR(inv_desc->hi); > >> + sid = VTD_INV_DESC_PASID_DEVICE_IOTLB_SID(inv_desc->lo); > >> + if (global) { > >> + QLIST_FOREACH(vtd_dev_as, &s->vtd_as_with_notifiers, next) { > >> + if ((vtd_dev_as->pasid != PCI_NO_PASID) && > >> + (PCI_BUILD_BDF(pci_bus_num(vtd_dev_as->bus), > >> + vtd_dev_as->devfn) == sid)) { > >> + do_invalidate_device_tlb(vtd_dev_as, size, addr); > >> + } > >> + } > >> + } else { > >> + pasid = VTD_INV_DESC_PASID_DEVICE_IOTLB_PASID(inv_desc->lo); > >> + vtd_dev_as = vtd_get_as_by_sid_and_pasid(s, sid, pasid); > >> + if (!vtd_dev_as) { > >> + return true; > >> + } > >> + > >> + do_invalidate_device_tlb(vtd_dev_as, size, addr); > > > >Question: > > > >I wonder if current vhost (which has a device IOTLB abstraction via > >virtio-pci) can work with this (PASID based IOTLB invalidation) > > Currently, it depends on if caching-mode is on. If it's off, vhost works. E.g.: > > -device intel-iommu,caching-mode=off,dma-drain=on,device-iotlb=on,x-scalable-mode=on > -netdev tap,id=tap0,vhost=on,script=/etc/qemu-ifup > -device virtio-net-pci,netdev=tap0,bus=root0,iommu_platform=on,ats=on > > It doesn't work currently when caching-mode is on. > Reason is linux kernel has an optimization to send only piotlb invalidation, > no device-piotlb invalidation is sent. But I heard from Yi the optimization > will be dropped, then it will work too when caching-mode is on. Great, if possible please copy me when sending those fixes. Thanks > > Thanks > Zhenzhong
>-----Original Message----- >From: Jason Wang <jasowang@redhat.com> >Subject: Re: [PATCH v3 12/17] intel_iommu: Add support for PASID-based >device IOTLB invalidation > >On Fri, Sep 27, 2024 at 3:18 PM Duan, Zhenzhong ><zhenzhong.duan@intel.com> wrote: >> >> >> >> >-----Original Message----- >> >From: Jason Wang <jasowang@redhat.com> >> >Subject: Re: [PATCH v3 12/17] intel_iommu: Add support for PASID- >based >> >device IOTLB invalidation >> > >> >On Wed, Sep 11, 2024 at 1:27 PM Zhenzhong Duan >> ><zhenzhong.duan@intel.com> wrote: >> >> >> >> From: Clément Mathieu--Drif <clement.mathieu--drif@eviden.com> >> >> >> >> Signed-off-by: Clément Mathieu--Drif <clement.mathieu-- >drif@eviden.com> >> >> Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> >> >> --- >> >> hw/i386/intel_iommu_internal.h | 11 ++++++++ >> >> hw/i386/intel_iommu.c | 50 >> >++++++++++++++++++++++++++++++++++ >> >> 2 files changed, 61 insertions(+) >> >> >> >> diff --git a/hw/i386/intel_iommu_internal.h >> >b/hw/i386/intel_iommu_internal.h >> >> index 4f2c3a9350..52bdbf3bc5 100644 >> >> --- a/hw/i386/intel_iommu_internal.h >> >> +++ b/hw/i386/intel_iommu_internal.h >> >> @@ -375,6 +375,7 @@ typedef union VTDInvDesc VTDInvDesc; >> >> #define VTD_INV_DESC_WAIT 0x5 /* Invalidation Wait >Descriptor >> >*/ >> >> #define VTD_INV_DESC_PIOTLB 0x6 /* PASID-IOTLB Invalidate >Desc >> >*/ >> >> #define VTD_INV_DESC_PC 0x7 /* PASID-cache Invalidate >Desc */ >> >> +#define VTD_INV_DESC_DEV_PIOTLB 0x8 /* PASID-based-DIOTLB >> >inv_desc*/ >> >> #define VTD_INV_DESC_NONE 0 /* Not an Invalidate >Descriptor >> >*/ >> >> >> >> /* Masks for Invalidation Wait Descriptor*/ >> >> @@ -413,6 +414,16 @@ typedef union VTDInvDesc VTDInvDesc; >> >> #define VTD_INV_DESC_DEVICE_IOTLB_RSVD_HI 0xffeULL >> >> #define VTD_INV_DESC_DEVICE_IOTLB_RSVD_LO 0xffff0000ffe0fff8 >> >> >> >> +/* Mask for PASID Device IOTLB Invalidate Descriptor */ >> >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_ADDR(val) ((val) & \ >> >> + 0xfffffffffffff000ULL) >> >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_SIZE(val) ((val >> 11) & >0x1) >> >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_GLOBAL(val) ((val) & >0x1) >> >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_SID(val) (((val) >> 16) & >> >0xffffULL) >> >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_PASID(val) ((val >> 32) >& >> >0xfffffULL) >> >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_HI 0x7feULL >> >> +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_LO >> >0xfff000000000f000ULL >> >> + >> >> /* Rsvd field masks for spte */ >> >> #define VTD_SPTE_SNP 0x800ULL >> >> >> >> diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c >> >> index d28c862598..4cf56924e1 100644 >> >> --- a/hw/i386/intel_iommu.c >> >> +++ b/hw/i386/intel_iommu.c >> >> @@ -3017,6 +3017,49 @@ static void >> >do_invalidate_device_tlb(VTDAddressSpace *vtd_dev_as, >> >> memory_region_notify_iommu(&vtd_dev_as->iommu, 0, event); >> >> } >> >> >> >> +static bool vtd_process_device_piotlb_desc(IntelIOMMUState *s, >> >> + VTDInvDesc *inv_desc) >> >> +{ >> >> + uint16_t sid; >> >> + VTDAddressSpace *vtd_dev_as; >> >> + bool size; >> >> + bool global; >> >> + hwaddr addr; >> >> + uint32_t pasid; >> >> + >> >> + if ((inv_desc->hi & VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_HI) >|| >> >> + (inv_desc->lo & VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_LO)) >{ >> >> + error_report_once("%s: invalid pasid-based dev iotlb inv desc:" >> >> + "hi=%"PRIx64 "(reserved nonzero)", >> >> + __func__, inv_desc->hi); >> >> + return false; >> >> + } >> >> + >> >> + global = VTD_INV_DESC_PASID_DEVICE_IOTLB_GLOBAL(inv_desc- >>hi); >> >> + size = VTD_INV_DESC_PASID_DEVICE_IOTLB_SIZE(inv_desc->hi); >> >> + addr = VTD_INV_DESC_PASID_DEVICE_IOTLB_ADDR(inv_desc->hi); >> >> + sid = VTD_INV_DESC_PASID_DEVICE_IOTLB_SID(inv_desc->lo); >> >> + if (global) { >> >> + QLIST_FOREACH(vtd_dev_as, &s->vtd_as_with_notifiers, next) { >> >> + if ((vtd_dev_as->pasid != PCI_NO_PASID) && >> >> + (PCI_BUILD_BDF(pci_bus_num(vtd_dev_as->bus), >> >> + vtd_dev_as->devfn) == sid)) { >> >> + do_invalidate_device_tlb(vtd_dev_as, size, addr); >> >> + } >> >> + } >> >> + } else { >> >> + pasid = VTD_INV_DESC_PASID_DEVICE_IOTLB_PASID(inv_desc- >>lo); >> >> + vtd_dev_as = vtd_get_as_by_sid_and_pasid(s, sid, pasid); >> >> + if (!vtd_dev_as) { >> >> + return true; >> >> + } >> >> + >> >> + do_invalidate_device_tlb(vtd_dev_as, size, addr); >> > >> >Question: >> > >> >I wonder if current vhost (which has a device IOTLB abstraction via >> >virtio-pci) can work with this (PASID based IOTLB invalidation) >> >> Currently, it depends on if caching-mode is on. If it's off, vhost works. E.g.: >> >> -device intel-iommu,caching-mode=off,dma-drain=on,device-iotlb=on,x- >scalable-mode=on >> -netdev tap,id=tap0,vhost=on,script=/etc/qemu-ifup >> -device virtio-net-pci,netdev=tap0,bus=root0,iommu_platform=on,ats=on >> >> It doesn't work currently when caching-mode is on. >> Reason is linux kernel has an optimization to send only piotlb invalidation, >> no device-piotlb invalidation is sent. But I heard from Yi the optimization >> will be dropped, then it will work too when caching-mode is on. > >Great, if possible please copy me when sending those fixes. Sure, +Yi, Baolu for their attention. Thanks Zhenzhong
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h index 4f2c3a9350..52bdbf3bc5 100644 --- a/hw/i386/intel_iommu_internal.h +++ b/hw/i386/intel_iommu_internal.h @@ -375,6 +375,7 @@ typedef union VTDInvDesc VTDInvDesc; #define VTD_INV_DESC_WAIT 0x5 /* Invalidation Wait Descriptor */ #define VTD_INV_DESC_PIOTLB 0x6 /* PASID-IOTLB Invalidate Desc */ #define VTD_INV_DESC_PC 0x7 /* PASID-cache Invalidate Desc */ +#define VTD_INV_DESC_DEV_PIOTLB 0x8 /* PASID-based-DIOTLB inv_desc*/ #define VTD_INV_DESC_NONE 0 /* Not an Invalidate Descriptor */ /* Masks for Invalidation Wait Descriptor*/ @@ -413,6 +414,16 @@ typedef union VTDInvDesc VTDInvDesc; #define VTD_INV_DESC_DEVICE_IOTLB_RSVD_HI 0xffeULL #define VTD_INV_DESC_DEVICE_IOTLB_RSVD_LO 0xffff0000ffe0fff8 +/* Mask for PASID Device IOTLB Invalidate Descriptor */ +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_ADDR(val) ((val) & \ + 0xfffffffffffff000ULL) +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_SIZE(val) ((val >> 11) & 0x1) +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_GLOBAL(val) ((val) & 0x1) +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_SID(val) (((val) >> 16) & 0xffffULL) +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_PASID(val) ((val >> 32) & 0xfffffULL) +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_HI 0x7feULL +#define VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_LO 0xfff000000000f000ULL + /* Rsvd field masks for spte */ #define VTD_SPTE_SNP 0x800ULL diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index d28c862598..4cf56924e1 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -3017,6 +3017,49 @@ static void do_invalidate_device_tlb(VTDAddressSpace *vtd_dev_as, memory_region_notify_iommu(&vtd_dev_as->iommu, 0, event); } +static bool vtd_process_device_piotlb_desc(IntelIOMMUState *s, + VTDInvDesc *inv_desc) +{ + uint16_t sid; + VTDAddressSpace *vtd_dev_as; + bool size; + bool global; + hwaddr addr; + uint32_t pasid; + + if ((inv_desc->hi & VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_HI) || + (inv_desc->lo & VTD_INV_DESC_PASID_DEVICE_IOTLB_RSVD_LO)) { + error_report_once("%s: invalid pasid-based dev iotlb inv desc:" + "hi=%"PRIx64 "(reserved nonzero)", + __func__, inv_desc->hi); + return false; + } + + global = VTD_INV_DESC_PASID_DEVICE_IOTLB_GLOBAL(inv_desc->hi); + size = VTD_INV_DESC_PASID_DEVICE_IOTLB_SIZE(inv_desc->hi); + addr = VTD_INV_DESC_PASID_DEVICE_IOTLB_ADDR(inv_desc->hi); + sid = VTD_INV_DESC_PASID_DEVICE_IOTLB_SID(inv_desc->lo); + if (global) { + QLIST_FOREACH(vtd_dev_as, &s->vtd_as_with_notifiers, next) { + if ((vtd_dev_as->pasid != PCI_NO_PASID) && + (PCI_BUILD_BDF(pci_bus_num(vtd_dev_as->bus), + vtd_dev_as->devfn) == sid)) { + do_invalidate_device_tlb(vtd_dev_as, size, addr); + } + } + } else { + pasid = VTD_INV_DESC_PASID_DEVICE_IOTLB_PASID(inv_desc->lo); + vtd_dev_as = vtd_get_as_by_sid_and_pasid(s, sid, pasid); + if (!vtd_dev_as) { + return true; + } + + do_invalidate_device_tlb(vtd_dev_as, size, addr); + } + + return true; +} + static bool vtd_process_device_iotlb_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc) { @@ -3111,6 +3154,13 @@ static bool vtd_process_inv_desc(IntelIOMMUState *s) } break; + case VTD_INV_DESC_DEV_PIOTLB: + trace_vtd_inv_desc("device-piotlb", inv_desc.hi, inv_desc.lo); + if (!vtd_process_device_piotlb_desc(s, &inv_desc)) { + return false; + } + break; + case VTD_INV_DESC_DEVICE: trace_vtd_inv_desc("device", inv_desc.hi, inv_desc.lo); if (!vtd_process_device_iotlb_desc(s, &inv_desc)) {