RID-PASID Support(RPS) is not set in vIOMMU ECAP register, the supporting
code is there but never takes effect.
Meanwhile, according to VTD spec section 3.4.3:
"Implementations not supporting RID_PASID capability (ECAP_REG.RPS is 0b),
use a PASID value of 0 to perform address translation for requests without
PASID."
We should delete the supporting code which fetches RID_PASID field from
scalable context entry and use 0 as RID_PASID directly, because RID_PASID
field is ignored if no RPS support according to spec.
This simplifies the code and doesn't bring any penalty.
Suggested-by: Yi Liu <yi.l.liu@intel.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
---
hw/i386/intel_iommu_internal.h | 2 +-
hw/i386/intel_iommu.c | 89 +++++++++++-----------------------
2 files changed, 28 insertions(+), 63 deletions(-)
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index 75bafdf0cd..36d04427dd 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -609,7 +609,7 @@ typedef struct VTDRootEntry VTDRootEntry;
#define VTD_CTX_ENTRY_LEGACY_SIZE 16
#define VTD_CTX_ENTRY_SCALABLE_SIZE 32
-#define VTD_SM_CONTEXT_ENTRY_RID2PASID_MASK 0xfffff
+#define PASID_0 0
#define VTD_SM_CONTEXT_ENTRY_RSVD_VAL0(aw) (0x1e0ULL | ~VTD_HAW_MASK(aw))
#define VTD_SM_CONTEXT_ENTRY_RSVD_VAL1 0xffffffffffe00000ULL
#define VTD_SM_CONTEXT_ENTRY_PRE 0x10ULL
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 7b6eeb4d7d..46d2c88493 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -42,8 +42,6 @@
#include "trace.h"
/* context entry operations */
-#define VTD_CE_GET_RID2PASID(ce) \
- ((ce)->val[1] & VTD_SM_CONTEXT_ENTRY_RID2PASID_MASK)
#define VTD_CE_GET_PASID_DIR_TABLE(ce) \
((ce)->val[0] & VTD_PASID_DIR_BASE_ADDR_MASK)
#define VTD_CE_GET_PRE(ce) \
@@ -959,15 +957,12 @@ static int vtd_ce_get_pasid_entry(IntelIOMMUState *s, VTDContextEntry *ce,
VTDPASIDEntry *pe, uint32_t pasid)
{
dma_addr_t pasid_dir_base;
- int ret = 0;
if (pasid == PCI_NO_PASID) {
- pasid = VTD_CE_GET_RID2PASID(ce);
+ pasid = PASID_0;
}
pasid_dir_base = VTD_CE_GET_PASID_DIR_TABLE(ce);
- ret = vtd_get_pe_from_pasid_table(s, pasid_dir_base, pasid, pe);
-
- return ret;
+ return vtd_get_pe_from_pasid_table(s, pasid_dir_base, pasid, pe);
}
static int vtd_ce_get_pasid_fpd(IntelIOMMUState *s,
@@ -981,7 +976,7 @@ static int vtd_ce_get_pasid_fpd(IntelIOMMUState *s,
VTDPASIDEntry pe;
if (pasid == PCI_NO_PASID) {
- pasid = VTD_CE_GET_RID2PASID(ce);
+ pasid = PASID_0;
}
pasid_dir_base = VTD_CE_GET_PASID_DIR_TABLE(ce);
@@ -1521,17 +1516,15 @@ static inline int vtd_context_entry_rsvd_bits_check(IntelIOMMUState *s,
return 0;
}
-static int vtd_ce_rid2pasid_check(IntelIOMMUState *s,
- VTDContextEntry *ce)
+static int vtd_ce_pasid_0_check(IntelIOMMUState *s, VTDContextEntry *ce)
{
VTDPASIDEntry pe;
/*
* Make sure in Scalable Mode, a present context entry
- * has valid rid2pasid setting, which includes valid
- * rid2pasid field and corresponding pasid entry setting
+ * has valid pasid entry setting at PASID_0.
*/
- return vtd_ce_get_pasid_entry(s, ce, &pe, PCI_NO_PASID);
+ return vtd_ce_get_pasid_entry(s, ce, &pe, PASID_0);
}
/* Map a device to its corresponding domain (context-entry) */
@@ -1592,15 +1585,11 @@ static int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num,
}
} else {
/*
- * Check if the programming of context-entry.rid2pasid
- * and corresponding pasid setting is valid, and thus
- * avoids to check pasid entry fetching result in future
- * helper function calling.
+ * Check if the programming of pasid setting of PASID_0
+ * is valid, and thus avoids to check pasid entry fetching
+ * result in future helper function calling.
*/
- ret_fr = vtd_ce_rid2pasid_check(s, ce);
- if (ret_fr) {
- return ret_fr;
- }
+ return vtd_ce_pasid_0_check(s, ce);
}
return 0;
@@ -2109,7 +2098,6 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,
bool reads = true;
bool writes = true;
uint8_t access_flags, pgtt;
- bool rid2pasid = (pasid == PCI_NO_PASID) && s->root_scalable;
VTDIOTLBEntry *iotlb_entry;
uint64_t xlat, size;
@@ -2121,21 +2109,23 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,
vtd_iommu_lock(s);
- cc_entry = &vtd_as->context_cache_entry;
+ if (pasid == PCI_NO_PASID && s->root_scalable) {
+ pasid = PASID_0;
+ }
- /* Try to fetch pte from IOTLB, we don't need RID2PASID logic */
- if (!rid2pasid) {
- iotlb_entry = vtd_lookup_iotlb(s, source_id, pasid, addr);
- if (iotlb_entry) {
- trace_vtd_iotlb_page_hit(source_id, addr, iotlb_entry->pte,
- iotlb_entry->domain_id);
- pte = iotlb_entry->pte;
- access_flags = iotlb_entry->access_flags;
- page_mask = iotlb_entry->mask;
- goto out;
- }
+ /* Try to fetch pte from IOTLB */
+ iotlb_entry = vtd_lookup_iotlb(s, source_id, pasid, addr);
+ if (iotlb_entry) {
+ trace_vtd_iotlb_page_hit(source_id, addr, iotlb_entry->pte,
+ iotlb_entry->domain_id);
+ pte = iotlb_entry->pte;
+ access_flags = iotlb_entry->access_flags;
+ page_mask = iotlb_entry->mask;
+ goto out;
}
+ cc_entry = &vtd_as->context_cache_entry;
+
/* Try to fetch context-entry from cache first */
if (cc_entry->context_cache_gen == s->context_cache_gen) {
trace_vtd_iotlb_cc_hit(bus_num, devfn, cc_entry->context_entry.hi,
@@ -2172,10 +2162,6 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,
cc_entry->context_cache_gen = s->context_cache_gen;
}
- if (rid2pasid) {
- pasid = VTD_CE_GET_RID2PASID(&ce);
- }
-
/*
* We don't need to translate for pass-through context entries.
* Also, let's ignore IOTLB caching as well for PT devices.
@@ -2201,19 +2187,6 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,
return true;
}
- /* Try to fetch pte from IOTLB for RID2PASID slow path */
- if (rid2pasid) {
- iotlb_entry = vtd_lookup_iotlb(s, source_id, pasid, addr);
- if (iotlb_entry) {
- trace_vtd_iotlb_page_hit(source_id, addr, iotlb_entry->pte,
- iotlb_entry->domain_id);
- pte = iotlb_entry->pte;
- access_flags = iotlb_entry->access_flags;
- page_mask = iotlb_entry->mask;
- goto out;
- }
- }
-
if (s->flts && s->root_scalable) {
ret_fr = vtd_iova_to_flpte(s, &ce, addr, is_write, &pte, &level,
&reads, &writes, s->aw_bits, pasid);
@@ -2476,20 +2449,14 @@ static void vtd_iotlb_page_invalidate_notify(IntelIOMMUState *s,
ret = vtd_dev_to_context_entry(s, pci_bus_num(vtd_as->bus),
vtd_as->devfn, &ce);
if (!ret && domain_id == vtd_get_domain_id(s, &ce, vtd_as->pasid)) {
- uint32_t rid2pasid = PCI_NO_PASID;
-
- if (s->root_scalable) {
- rid2pasid = VTD_CE_GET_RID2PASID(&ce);
- }
-
/*
* In legacy mode, vtd_as->pasid == pasid is always true.
* In scalable mode, for vtd address space backing a PCI
* device without pasid, needs to compare pasid with
- * rid2pasid of this device.
+ * PASID_0 of this device.
*/
if (!(vtd_as->pasid == pasid ||
- (vtd_as->pasid == PCI_NO_PASID && pasid == rid2pasid))) {
+ (vtd_as->pasid == PCI_NO_PASID && pasid == PASID_0))) {
continue;
}
@@ -2994,9 +2961,7 @@ static void vtd_piotlb_pasid_invalidate(IntelIOMMUState *s,
if (!vtd_dev_to_context_entry(s, pci_bus_num(vtd_as->bus),
vtd_as->devfn, &ce) &&
domain_id == vtd_get_domain_id(s, &ce, vtd_as->pasid)) {
- uint32_t rid2pasid = VTD_CE_GET_RID2PASID(&ce);
-
- if ((vtd_as->pasid != PCI_NO_PASID || pasid != rid2pasid) &&
+ if ((vtd_as->pasid != PCI_NO_PASID || pasid != PASID_0) &&
vtd_as->pasid != pasid) {
continue;
}
--
2.47.1
On Mon, Nov 17, 2025 at 5:38 PM Zhenzhong Duan <zhenzhong.duan@intel.com> wrote: > > RID-PASID Support(RPS) is not set in vIOMMU ECAP register, the supporting > code is there but never takes effect. > > Meanwhile, according to VTD spec section 3.4.3: > "Implementations not supporting RID_PASID capability (ECAP_REG.RPS is 0b), > use a PASID value of 0 to perform address translation for requests without > PASID." > > We should delete the supporting code which fetches RID_PASID field from > scalable context entry and use 0 as RID_PASID directly, because RID_PASID > field is ignored if no RPS support according to spec. > > This simplifies the code and doesn't bring any penalty. > > Suggested-by: Yi Liu <yi.l.liu@intel.com> > Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> > --- Is the feature deprecated in the spec? If not, it should be still better to enable it. Thanks
On 2025/12/11 16:22, Jason Wang wrote:
> On Mon, Nov 17, 2025 at 5:38 PM Zhenzhong Duan <zhenzhong.duan@intel.com> wrote:
>>
>> RID-PASID Support(RPS) is not set in vIOMMU ECAP register, the supporting
>> code is there but never takes effect.
>>
>> Meanwhile, according to VTD spec section 3.4.3:
>> "Implementations not supporting RID_PASID capability (ECAP_REG.RPS is 0b),
>> use a PASID value of 0 to perform address translation for requests without
>> PASID."
>>
>> We should delete the supporting code which fetches RID_PASID field from
>> scalable context entry and use 0 as RID_PASID directly, because RID_PASID
>> field is ignored if no RPS support according to spec.
>>
>> This simplifies the code and doesn't bring any penalty.
>>
>> Suggested-by: Yi Liu <yi.l.liu@intel.com>
>> Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
>> ---
>
> Is the feature deprecated in the spec? If not, it should be still
> better to enable it.
Hi Jason,
The feature is still in the spec. However, using PASID#0 for the
requests without pasid is aligned across vendors. So the linux iommu
subsystem uses PASID#0 to differentiate the pasid path and non-pasid
path like below:
commit bc06f7f66de404ae6323963361fe4e2f5f71a1e5
Author: Yi Liu <yi.l.liu@intel.com>
Date: Fri Mar 21 10:19:26 2025 -0700
iommufd/device: Only add reserved_iova in non-pasid path
As the pasid is passed through the attach/replace/detach helpers, it is
necessary to ensure only the non-pasid path adds reserved_iova.
Link:
https://patch.msgid.link/r/20250321171940.7213-5-yi.l.liu@intel.com
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
Tested-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c
index 7051feda2fab..4625f084f7d0 100644
--- a/drivers/iommu/iommufd/device.c
+++ b/drivers/iommu/iommufd/device.c
@@ -483,6 +483,7 @@ int iommufd_hw_pagetable_attach(struct
iommufd_hw_pagetable *hwpt,
struct iommufd_device *idev, ioasid_t
pasid)
{
struct iommufd_hwpt_paging *hwpt_paging = find_hwpt_paging(hwpt);
+ bool attach_resv = hwpt_paging && pasid == IOMMU_NO_PASID;
int rc;
So even though intel hardware report RPS=1, the linux intel iommu
driver uses PASID#0 as rid_pasid and ignores the RPS value. So
I don't think we will ever report RPS=1 to VM. Also, as Zhenzhong's
commit message states, current vIOMMU does not report RPS, the logic to
retrieve rid_pasid from context entry is not necessary as well. Based on
the fact, I think it is nice to drop the support. Please let us know if
you have other ideas.
Regards,
Yi Liu
On Thu, Dec 11, 2025 at 6:57 PM Yi Liu <yi.l.liu@intel.com> wrote:
>
> On 2025/12/11 16:22, Jason Wang wrote:
> > On Mon, Nov 17, 2025 at 5:38 PM Zhenzhong Duan <zhenzhong.duan@intel.com> wrote:
> >>
> >> RID-PASID Support(RPS) is not set in vIOMMU ECAP register, the supporting
> >> code is there but never takes effect.
> >>
> >> Meanwhile, according to VTD spec section 3.4.3:
> >> "Implementations not supporting RID_PASID capability (ECAP_REG.RPS is 0b),
> >> use a PASID value of 0 to perform address translation for requests without
> >> PASID."
> >>
> >> We should delete the supporting code which fetches RID_PASID field from
> >> scalable context entry and use 0 as RID_PASID directly, because RID_PASID
> >> field is ignored if no RPS support according to spec.
> >>
> >> This simplifies the code and doesn't bring any penalty.
> >>
> >> Suggested-by: Yi Liu <yi.l.liu@intel.com>
> >> Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
> >> ---
> >
> > Is the feature deprecated in the spec? If not, it should be still
> > better to enable it.
>
> Hi Jason,
>
> The feature is still in the spec. However, using PASID#0 for the
> requests without pasid is aligned across vendors. So the linux iommu
> subsystem uses PASID#0 to differentiate the pasid path and non-pasid
> path like below:
>
> commit bc06f7f66de404ae6323963361fe4e2f5f71a1e5
> Author: Yi Liu <yi.l.liu@intel.com>
> Date: Fri Mar 21 10:19:26 2025 -0700
>
> iommufd/device: Only add reserved_iova in non-pasid path
>
> As the pasid is passed through the attach/replace/detach helpers, it is
> necessary to ensure only the non-pasid path adds reserved_iova.
>
> Link:
> https://patch.msgid.link/r/20250321171940.7213-5-yi.l.liu@intel.com
> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
> Reviewed-by: Kevin Tian <kevin.tian@intel.com>
> Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
> Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
> Signed-off-by: Yi Liu <yi.l.liu@intel.com>
> Tested-by: Nicolin Chen <nicolinc@nvidia.com>
> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
>
> diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c
> index 7051feda2fab..4625f084f7d0 100644
> --- a/drivers/iommu/iommufd/device.c
> +++ b/drivers/iommu/iommufd/device.c
> @@ -483,6 +483,7 @@ int iommufd_hw_pagetable_attach(struct
> iommufd_hw_pagetable *hwpt,
> struct iommufd_device *idev, ioasid_t
> pasid)
> {
> struct iommufd_hwpt_paging *hwpt_paging = find_hwpt_paging(hwpt);
> + bool attach_resv = hwpt_paging && pasid == IOMMU_NO_PASID;
> int rc;
>
>
> So even though intel hardware report RPS=1, the linux intel iommu
> driver uses PASID#0 as rid_pasid and ignores the RPS value.
Probably, but we need to support OSes other than Linux.
> So
> I don't think we will ever report RPS=1 to VM. Also, as Zhenzhong's
> commit message states, current vIOMMU does not report RPS, the logic to
> retrieve rid_pasid from context entry is not necessary as well. Based on
> the fact, I think it is nice to drop the support. Please let us know if
> you have other ideas.
I'm fine to drop that, just want to double check if it's worth keeping
with an option to enable it.
Thanks
>
> Regards,
> Yi Liu
>
>-----Original Message-----
>From: Jason Wang <jasowang@redhat.com>
>Subject: Re: [PATCH v8 02/23] intel_iommu: Delete RPS capability related
>supporting code
>
>On Thu, Dec 11, 2025 at 6:57 PM Yi Liu <yi.l.liu@intel.com> wrote:
>>
>> On 2025/12/11 16:22, Jason Wang wrote:
>> > On Mon, Nov 17, 2025 at 5:38 PM Zhenzhong Duan
><zhenzhong.duan@intel.com> wrote:
>> >>
>> >> RID-PASID Support(RPS) is not set in vIOMMU ECAP register, the
>supporting
>> >> code is there but never takes effect.
>> >>
>> >> Meanwhile, according to VTD spec section 3.4.3:
>> >> "Implementations not supporting RID_PASID capability (ECAP_REG.RPS is
>0b),
>> >> use a PASID value of 0 to perform address translation for requests
>without
>> >> PASID."
>> >>
>> >> We should delete the supporting code which fetches RID_PASID field
>from
>> >> scalable context entry and use 0 as RID_PASID directly, because
>RID_PASID
>> >> field is ignored if no RPS support according to spec.
>> >>
>> >> This simplifies the code and doesn't bring any penalty.
>> >>
>> >> Suggested-by: Yi Liu <yi.l.liu@intel.com>
>> >> Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
>> >> ---
>> >
>> > Is the feature deprecated in the spec? If not, it should be still
>> > better to enable it.
>>
>> Hi Jason,
>>
>> The feature is still in the spec. However, using PASID#0 for the
>> requests without pasid is aligned across vendors. So the linux iommu
>> subsystem uses PASID#0 to differentiate the pasid path and non-pasid
>> path like below:
>>
>> commit bc06f7f66de404ae6323963361fe4e2f5f71a1e5
>> Author: Yi Liu <yi.l.liu@intel.com>
>> Date: Fri Mar 21 10:19:26 2025 -0700
>>
>> iommufd/device: Only add reserved_iova in non-pasid path
>>
>> As the pasid is passed through the attach/replace/detach helpers, it is
>> necessary to ensure only the non-pasid path adds reserved_iova.
>>
>> Link:
>> https://patch.msgid.link/r/20250321171940.7213-5-yi.l.liu@intel.com
>> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
>> Reviewed-by: Kevin Tian <kevin.tian@intel.com>
>> Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
>> Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
>> Signed-off-by: Yi Liu <yi.l.liu@intel.com>
>> Tested-by: Nicolin Chen <nicolinc@nvidia.com>
>> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
>>
>> diff --git a/drivers/iommu/iommufd/device.c
>b/drivers/iommu/iommufd/device.c
>> index 7051feda2fab..4625f084f7d0 100644
>> --- a/drivers/iommu/iommufd/device.c
>> +++ b/drivers/iommu/iommufd/device.c
>> @@ -483,6 +483,7 @@ int iommufd_hw_pagetable_attach(struct
>> iommufd_hw_pagetable *hwpt,
>> struct iommufd_device *idev,
>ioasid_t
>> pasid)
>> {
>> struct iommufd_hwpt_paging *hwpt_paging =
>find_hwpt_paging(hwpt);
>> + bool attach_resv = hwpt_paging && pasid == IOMMU_NO_PASID;
>> int rc;
>>
>>
>> So even though intel hardware report RPS=1, the linux intel iommu
>> driver uses PASID#0 as rid_pasid and ignores the RPS value.
>
>Probably, but we need to support OSes other than Linux.
IIUC, existing qemu doesn't expose RPS cap, a working OS with existing qemu should also work after this patch, because it should always choose PAISD_0 for rid_pasid.
>
>> So
>> I don't think we will ever report RPS=1 to VM. Also, as Zhenzhong's
>> commit message states, current vIOMMU does not report RPS, the logic to
>> retrieve rid_pasid from context entry is not necessary as well. Based on
>> the fact, I think it is nice to drop the support. Please let us know if
>> you have other ideas.
>
>I'm fine to drop that, just want to double check if it's worth keeping
>with an option to enable it.
I think no need, enabling it doesn't make qemu compatible with more OSes.
An OS supporting RPS cap should already follow VTD spec and support without RPS cap.
Thanks
Zhenzhong
Hi Zhenzhong,
On 11/17/25 10:37 AM, Zhenzhong Duan wrote:
> RID-PASID Support(RPS) is not set in vIOMMU ECAP register, the supporting
> code is there but never takes effect.
>
> Meanwhile, according to VTD spec section 3.4.3:
> "Implementations not supporting RID_PASID capability (ECAP_REG.RPS is 0b),
> use a PASID value of 0 to perform address translation for requests without
> PASID."
>
> We should delete the supporting code which fetches RID_PASID field from
> scalable context entry and use 0 as RID_PASID directly, because RID_PASID
> field is ignored if no RPS support according to spec.
>
> This simplifies the code and doesn't bring any penalty.
>
> Suggested-by: Yi Liu <yi.l.liu@intel.com>
> Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
> ---
> hw/i386/intel_iommu_internal.h | 2 +-
> hw/i386/intel_iommu.c | 89 +++++++++++-----------------------
> 2 files changed, 28 insertions(+), 63 deletions(-)
>
> diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
> index 75bafdf0cd..36d04427dd 100644
> --- a/hw/i386/intel_iommu_internal.h
> +++ b/hw/i386/intel_iommu_internal.h
> @@ -609,7 +609,7 @@ typedef struct VTDRootEntry VTDRootEntry;
> #define VTD_CTX_ENTRY_LEGACY_SIZE 16
> #define VTD_CTX_ENTRY_SCALABLE_SIZE 32
>
> -#define VTD_SM_CONTEXT_ENTRY_RID2PASID_MASK 0xfffff
> +#define PASID_0 0
> #define VTD_SM_CONTEXT_ENTRY_RSVD_VAL0(aw) (0x1e0ULL | ~VTD_HAW_MASK(aw))
> #define VTD_SM_CONTEXT_ENTRY_RSVD_VAL1 0xffffffffffe00000ULL
> #define VTD_SM_CONTEXT_ENTRY_PRE 0x10ULL
> diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
> index 7b6eeb4d7d..46d2c88493 100644
> --- a/hw/i386/intel_iommu.c
> +++ b/hw/i386/intel_iommu.c
> @@ -42,8 +42,6 @@
> #include "trace.h"
>
> /* context entry operations */
> -#define VTD_CE_GET_RID2PASID(ce) \
> - ((ce)->val[1] & VTD_SM_CONTEXT_ENTRY_RID2PASID_MASK)
> #define VTD_CE_GET_PASID_DIR_TABLE(ce) \
> ((ce)->val[0] & VTD_PASID_DIR_BASE_ADDR_MASK)
> #define VTD_CE_GET_PRE(ce) \
> @@ -959,15 +957,12 @@ static int vtd_ce_get_pasid_entry(IntelIOMMUState *s, VTDContextEntry *ce,
> VTDPASIDEntry *pe, uint32_t pasid)
> {
> dma_addr_t pasid_dir_base;
> - int ret = 0;
>
> if (pasid == PCI_NO_PASID) {
> - pasid = VTD_CE_GET_RID2PASID(ce);
> + pasid = PASID_0;
> }
> pasid_dir_base = VTD_CE_GET_PASID_DIR_TABLE(ce);
> - ret = vtd_get_pe_from_pasid_table(s, pasid_dir_base, pasid, pe);
> -
> - return ret;
> + return vtd_get_pe_from_pasid_table(s, pasid_dir_base, pasid, pe);
> }
>
> static int vtd_ce_get_pasid_fpd(IntelIOMMUState *s,
> @@ -981,7 +976,7 @@ static int vtd_ce_get_pasid_fpd(IntelIOMMUState *s,
> VTDPASIDEntry pe;
>
> if (pasid == PCI_NO_PASID) {
> - pasid = VTD_CE_GET_RID2PASID(ce);
> + pasid = PASID_0;
> }
> pasid_dir_base = VTD_CE_GET_PASID_DIR_TABLE(ce);
>
> @@ -1521,17 +1516,15 @@ static inline int vtd_context_entry_rsvd_bits_check(IntelIOMMUState *s,
> return 0;
> }
>
> -static int vtd_ce_rid2pasid_check(IntelIOMMUState *s,
> - VTDContextEntry *ce)
> +static int vtd_ce_pasid_0_check(IntelIOMMUState *s, VTDContextEntry *ce)
> {
> VTDPASIDEntry pe;
>
> /*
> * Make sure in Scalable Mode, a present context entry
> - * has valid rid2pasid setting, which includes valid
> - * rid2pasid field and corresponding pasid entry setting
> + * has valid pasid entry setting at PASID_0.
> */
> - return vtd_ce_get_pasid_entry(s, ce, &pe, PCI_NO_PASID);
> + return vtd_ce_get_pasid_entry(s, ce, &pe, PASID_0);
> }
>
> /* Map a device to its corresponding domain (context-entry) */
> @@ -1592,15 +1585,11 @@ static int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num,
> }
> } else {
> /*
> - * Check if the programming of context-entry.rid2pasid
> - * and corresponding pasid setting is valid, and thus
> - * avoids to check pasid entry fetching result in future
> - * helper function calling.
> + * Check if the programming of pasid setting of PASID_0
> + * is valid, and thus avoids to check pasid entry fetching
> + * result in future helper function calling.
> */
> - ret_fr = vtd_ce_rid2pasid_check(s, ce);
> - if (ret_fr) {
> - return ret_fr;
> - }
> + return vtd_ce_pasid_0_check(s, ce);
> }
>
> return 0;
> @@ -2109,7 +2098,6 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,
> bool reads = true;
> bool writes = true;
> uint8_t access_flags, pgtt;
> - bool rid2pasid = (pasid == PCI_NO_PASID) && s->root_scalable;
> VTDIOTLBEntry *iotlb_entry;
> uint64_t xlat, size;
>
> @@ -2121,21 +2109,23 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,
>
> vtd_iommu_lock(s);
>
> - cc_entry = &vtd_as->context_cache_entry;
> + if (pasid == PCI_NO_PASID && s->root_scalable) {
> + pasid = PASID_0;
> + }
>
> - /* Try to fetch pte from IOTLB, we don't need RID2PASID logic */
> - if (!rid2pasid) {
> - iotlb_entry = vtd_lookup_iotlb(s, source_id, pasid, addr);
> - if (iotlb_entry) {
> - trace_vtd_iotlb_page_hit(source_id, addr, iotlb_entry->pte,
> - iotlb_entry->domain_id);
> - pte = iotlb_entry->pte;
> - access_flags = iotlb_entry->access_flags;
> - page_mask = iotlb_entry->mask;
> - goto out;
> - }
> + /* Try to fetch pte from IOTLB */
> + iotlb_entry = vtd_lookup_iotlb(s, source_id, pasid, addr);
> + if (iotlb_entry) {
> + trace_vtd_iotlb_page_hit(source_id, addr, iotlb_entry->pte,
> + iotlb_entry->domain_id);
> + pte = iotlb_entry->pte;
> + access_flags = iotlb_entry->access_flags;
> + page_mask = iotlb_entry->mask;
> + goto out;
> }
>
> + cc_entry = &vtd_as->context_cache_entry;
> +
> /* Try to fetch context-entry from cache first */
> if (cc_entry->context_cache_gen == s->context_cache_gen) {
> trace_vtd_iotlb_cc_hit(bus_num, devfn, cc_entry->context_entry.hi,
> @@ -2172,10 +2162,6 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,
> cc_entry->context_cache_gen = s->context_cache_gen;
> }
>
> - if (rid2pasid) {
> - pasid = VTD_CE_GET_RID2PASID(&ce);
> - }
> -
> /*
> * We don't need to translate for pass-through context entries.
> * Also, let's ignore IOTLB caching as well for PT devices.
> @@ -2201,19 +2187,6 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,
> return true;
> }
>
> - /* Try to fetch pte from IOTLB for RID2PASID slow path */
> - if (rid2pasid) {
> - iotlb_entry = vtd_lookup_iotlb(s, source_id, pasid, addr);
> - if (iotlb_entry) {
> - trace_vtd_iotlb_page_hit(source_id, addr, iotlb_entry->pte,
> - iotlb_entry->domain_id);
> - pte = iotlb_entry->pte;
> - access_flags = iotlb_entry->access_flags;
> - page_mask = iotlb_entry->mask;
> - goto out;
> - }
> - }
> -
> if (s->flts && s->root_scalable) {
> ret_fr = vtd_iova_to_flpte(s, &ce, addr, is_write, &pte, &level,
> &reads, &writes, s->aw_bits, pasid);
> @@ -2476,20 +2449,14 @@ static void vtd_iotlb_page_invalidate_notify(IntelIOMMUState *s,
> ret = vtd_dev_to_context_entry(s, pci_bus_num(vtd_as->bus),
> vtd_as->devfn, &ce);
> if (!ret && domain_id == vtd_get_domain_id(s, &ce, vtd_as->pasid)) {
> - uint32_t rid2pasid = PCI_NO_PASID;
> -
> - if (s->root_scalable) {
> - rid2pasid = VTD_CE_GET_RID2PASID(&ce);
> - }
> -
> /*
> * In legacy mode, vtd_as->pasid == pasid is always true.
> * In scalable mode, for vtd address space backing a PCI
> * device without pasid, needs to compare pasid with
> - * rid2pasid of this device.
> + * PASID_0 of this device.
> */
> if (!(vtd_as->pasid == pasid ||
> - (vtd_as->pasid == PCI_NO_PASID && pasid == rid2pasid))) {
> + (vtd_as->pasid == PCI_NO_PASID && pasid == PASID_0))) {
> continue;
> }
>
> @@ -2994,9 +2961,7 @@ static void vtd_piotlb_pasid_invalidate(IntelIOMMUState *s,
> if (!vtd_dev_to_context_entry(s, pci_bus_num(vtd_as->bus),
> vtd_as->devfn, &ce) &&
> domain_id == vtd_get_domain_id(s, &ce, vtd_as->pasid)) {
> - uint32_t rid2pasid = VTD_CE_GET_RID2PASID(&ce);
> -
> - if ((vtd_as->pasid != PCI_NO_PASID || pasid != rid2pasid) &&
> + if ((vtd_as->pasid != PCI_NO_PASID || pasid != PASID_0) &&
> vtd_as->pasid != pasid) {
> continue;
> }
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Eric
© 2016 - 2026 Red Hat, Inc.