Re: [PATCH 2/8] iommu/vt-d: Add entry_sync support for PASID entry updates

From: Baolu Lu

Date: Wed Mar 11 2026 - 04:43:44 EST


On 3/9/26 21:41, Jason Gunthorpe wrote:
On Mon, Mar 09, 2026 at 02:06:42PM +0800, Lu Baolu wrote:
+static void intel_pasid_get_used(const u128 *entry, u128 *used)
+{
+ struct pasid_entry *pe = (struct pasid_entry *)entry;
+ struct pasid_entry *ue = (struct pasid_entry *)used;
+ u16 pgtt;
+
+ /* Initialize used bits to 0. */
+ memset(ue, 0, sizeof(*ue));
+
+ /* Present bit always matters. */
+ ue->val[0] |= PASID_PTE_PRESENT;
+
+ /* Nothing more for non-present entries. */
+ if (!(pe->val[0] & PASID_PTE_PRESENT))
+ return;
+
+ pgtt = pasid_pte_get_pgtt(pe);
+ switch (pgtt) {
+ case PASID_ENTRY_PGTT_FL_ONLY:
+ /* AW, PGTT */
+ ue->val[0] |= GENMASK_ULL(4, 2) | GENMASK_ULL(8, 6);
+ /* DID, PWSNP, PGSNP */
+ ue->val[1] |= GENMASK_ULL(24, 23) | GENMASK_ULL(15, 0);
+ /* FSPTPTR, FSPM */
+ ue->val[2] |= GENMASK_ULL(63, 12) | GENMASK_ULL(3, 2);
This would be an excellent time to properly add these constants 🙁

/* 9.6 Scalable-Mode PASID Table Entry */
#define SM_PASID0_P BIT_U64(0)
#define SM_PASID0_FPD BIT_U64(1)
#define SM_PASID0_AW GENMASK_U64(4, 2)
#define SM_PASID0_SSEE BIT_U64(5)
#define SM_PASID0_PGTT GENMASK_U64(8, 6)
#define SM_PASID0_SSADE BIT_U64(9)
#define SM_PASID0_SSPTPTR GENMASK_U64(63, 12)

#define SM_PASID1_DID GENMASK_U64(15, 0)
#define SM_PASID1_PWSNP BIT_U64(23)
#define SM_PASID1_PGSNP BIT_U64(24)
#define SM_PASID1_CD BIT_U64(25)
#define SM_PASID1_EMTE BIT_U64(26)
#define SM_PASID1_PAT GENMASK_U64(63, 32)

#define SM_PASID2_SRE BIT_U64(0)
#define SM_PASID2_ERE BIT_U64(1)
#define SM_PASID2_FSPM GENMASK_U64(3, 2)
#define SM_PASID2_WPE BIT_U64(4)
#define SM_PASID2_NXE BIT_U64(5)
#define SM_PASID2_SMEP BIT_U64(6)
#define SM_PASID2_EAFE BIT_U64(7)
#define SM_PASID2_FSPTPTR GENMASK_U64(63, 12)

Yeah, code updated like this,

drivers/iommu/intel/pasid.h:

/* 9.6 Scalable-Mode PASID Table Entry */
#define SM_PASID0_P BIT_U64(0)
#define SM_PASID0_FPD BIT_U64(1)
#define SM_PASID0_AW GENMASK_U64(4, 2)
#define SM_PASID0_PGTT GENMASK_U64(8, 6)
#define SM_PASID0_SSADE BIT_U64(9)
#define SM_PASID0_SSPTPTR GENMASK_U64(63, 12)

#define SM_PASID1_DID GENMASK_U64(15, 0)
#define SM_PASID1_PWSNP BIT_U64(23)
#define SM_PASID1_PGSNP BIT_U64(24)
#define SM_PASID1_CD BIT_U64(25)
#define SM_PASID1_EMTE BIT_U64(26)
#define SM_PASID1_PAT GENMASK_U64(63, 32)

#define SM_PASID2_SRE BIT_U64(0)
#define SM_PASID2_FSPM GENMASK_U64(3, 2)
#define SM_PASID2_WPE BIT_U64(4)
#define SM_PASID2_EAFE BIT_U64(7)
#define SM_PASID2_FSPTPTR GENMASK_U64(63, 12)

drivers/iommu/intel/pasid.c:

static void intel_pasid_get_used(const u128 *entry, u128 *used)
{
struct pasid_entry *pe = (struct pasid_entry *)entry;
struct pasid_entry *ue = (struct pasid_entry *)used;
u16 pgtt;

/* Initialize used bits to 0. */
memset(ue, 0, sizeof(*ue));

/* Present bit always matters. */
ue->val[0] |= SM_PASID0_P;

/* Nothing more for non-present entries. */
if (!(pe->val[0] & SM_PASID0_P)) {
trace_entry_get_used(entry, used);
return;
}

pgtt = pasid_pte_get_pgtt(pe);
switch (pgtt) {
case PASID_ENTRY_PGTT_FL_ONLY:
/* AW, PGTT */
ue->val[0] |= SM_PASID0_AW | SM_PASID0_PGTT;
/* DID, PWSNP, PGSNP */
ue->val[1] |= SM_PASID1_DID | SM_PASID1_PWSNP | SM_PASID1_PGSNP;
/* FSPTPTR, FSPM */
ue->val[2] |= SM_PASID2_FSPTPTR | SM_PASID2_FSPM;
break;
case PASID_ENTRY_PGTT_NESTED:
/* FPD, AW, PGTT, SSADE, SSPTPTR*/
ue->val[0] |= SM_PASID0_FPD | SM_PASID0_AW | SM_PASID0_PGTT |
SM_PASID0_SSADE | SM_PASID0_SSPTPTR;
/* PGSNP, DID, PWSNP */
ue->val[1] |= SM_PASID1_DID | SM_PASID1_PWSNP | SM_PASID1_PGSNP;
/* FSPTPTR, FSPM, EAFE, WPE, SRE */
ue->val[2] |= SM_PASID2_SRE | SM_PASID2_WPE | SM_PASID2_EAFE |
SM_PASID2_FSPM | SM_PASID2_FSPTPTR;
break;
case PASID_ENTRY_PGTT_SL_ONLY:
/* FPD, AW, PGTT, SSADE, SSPTPTR */
ue->val[0] |= SM_PASID0_FPD | SM_PASID0_AW | SM_PASID0_PGTT |
SM_PASID0_SSADE | SM_PASID0_SSPTPTR;
/* PGSNP, DID, PWSNP */
ue->val[1] |= SM_PASID1_DID | SM_PASID1_PWSNP | SM_PASID1_PGSNP;
break;
case PASID_ENTRY_PGTT_PT:
/* FPD, AW, PGTT */
ue->val[0] |= SM_PASID0_FPD | SM_PASID0_AW | SM_PASID0_PGTT;
/* PGSNP, DID, PWSNP */
ue->val[1] |= SM_PASID1_DID | SM_PASID1_PWSNP | SM_PASID1_PGSNP;
break;
default:
WARN_ON(true);
}

trace_entry_get_used(entry, used);
}

Thanks,
baolu