Skip to content

Commit cf484d0

Browse files
committed
iommu/vt-d: Mark copied context entries
Mark the context entries we copied over from the old kernel, so that we don't detect them as present in other code paths. This makes sure we safely overwrite old context entries when a new domain is assigned. Tested-by: ZhenHua Li <zhen-hual@hp.com> Tested-by: Baoquan He <bhe@redhat.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent dbcd861 commit cf484d0

File tree

1 file changed

+51
-2
lines changed

1 file changed

+51
-2
lines changed

drivers/iommu/intel-iommu.c

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,10 +233,38 @@ struct context_entry {
233233
u64 hi;
234234
};
235235

236-
static inline bool context_present(struct context_entry *context)
236+
static inline void context_clear_pasid_enable(struct context_entry *context)
237+
{
238+
context->lo &= ~(1ULL << 11);
239+
}
240+
241+
static inline bool context_pasid_enabled(struct context_entry *context)
242+
{
243+
return !!(context->lo & (1ULL << 11));
244+
}
245+
246+
static inline void context_set_copied(struct context_entry *context)
247+
{
248+
context->hi |= (1ull << 3);
249+
}
250+
251+
static inline bool context_copied(struct context_entry *context)
252+
{
253+
return !!(context->hi & (1ULL << 3));
254+
}
255+
256+
static inline bool __context_present(struct context_entry *context)
237257
{
238258
return (context->lo & 1);
239259
}
260+
261+
static inline bool context_present(struct context_entry *context)
262+
{
263+
return context_pasid_enabled(context) ?
264+
__context_present(context) :
265+
__context_present(context) && !context_copied(context);
266+
}
267+
240268
static inline void context_set_present(struct context_entry *context)
241269
{
242270
context->lo |= 1;
@@ -1861,6 +1889,8 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
18611889
return 0;
18621890
}
18631891

1892+
context_clear_entry(context);
1893+
18641894
id = domain->id;
18651895
pgd = domain->pgd;
18661896

@@ -2859,13 +2889,32 @@ static int copy_context_table(struct intel_iommu *iommu,
28592889
/* Now copy the context entry */
28602890
ce = old_ce[idx];
28612891

2862-
if (!context_present(&ce))
2892+
if (!__context_present(&ce))
28632893
continue;
28642894

28652895
did = context_domain_id(&ce);
28662896
if (did >= 0 && did < cap_ndoms(iommu->cap))
28672897
set_bit(did, iommu->domain_ids);
28682898

2899+
/*
2900+
* We need a marker for copied context entries. This
2901+
* marker needs to work for the old format as well as
2902+
* for extended context entries.
2903+
*
2904+
* Bit 67 of the context entry is used. In the old
2905+
* format this bit is available to software, in the
2906+
* extended format it is the PGE bit, but PGE is ignored
2907+
* by HW if PASIDs are disabled (and thus still
2908+
* available).
2909+
*
2910+
* So disable PASIDs first and then mark the entry
2911+
* copied. This means that we don't copy PASID
2912+
* translations from the old kernel, but this is fine as
2913+
* faults there are not fatal.
2914+
*/
2915+
context_clear_pasid_enable(&ce);
2916+
context_set_copied(&ce);
2917+
28692918
new_ce[idx] = ce;
28702919
}
28712920

0 commit comments

Comments
 (0)