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

Baolu Lu
2026-03-11T08:43:30Z

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