@@ -233,10 +233,38 @@ struct context_entry {
233
233
u64 hi ;
234
234
};
235
235
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 )
237
257
{
238
258
return (context -> lo & 1 );
239
259
}
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
+
240
268
static inline void context_set_present (struct context_entry * context )
241
269
{
242
270
context -> lo |= 1 ;
@@ -1861,6 +1889,8 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
1861
1889
return 0 ;
1862
1890
}
1863
1891
1892
+ context_clear_entry (context );
1893
+
1864
1894
id = domain -> id ;
1865
1895
pgd = domain -> pgd ;
1866
1896
@@ -2859,13 +2889,32 @@ static int copy_context_table(struct intel_iommu *iommu,
2859
2889
/* Now copy the context entry */
2860
2890
ce = old_ce [idx ];
2861
2891
2862
- if (!context_present (& ce ))
2892
+ if (!__context_present (& ce ))
2863
2893
continue ;
2864
2894
2865
2895
did = context_domain_id (& ce );
2866
2896
if (did >= 0 && did < cap_ndoms (iommu -> cap ))
2867
2897
set_bit (did , iommu -> domain_ids );
2868
2898
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
+
2869
2918
new_ce [idx ] = ce ;
2870
2919
}
2871
2920
0 commit comments