diff options
-rw-r--r-- | drivers/pci/intel-iommu.c | 85 |
1 files changed, 55 insertions, 30 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index c1c59a619650..3be931b3bf98 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -105,28 +105,53 @@ struct context_entry { | |||
105 | u64 lo; | 105 | u64 lo; |
106 | u64 hi; | 106 | u64 hi; |
107 | }; | 107 | }; |
108 | #define context_present(c) ((c).lo & 1) | 108 | |
109 | #define context_fault_disable(c) (((c).lo >> 1) & 1) | 109 | static inline bool context_present(struct context_entry *context) |
110 | #define context_translation_type(c) (((c).lo >> 2) & 3) | 110 | { |
111 | #define context_address_root(c) ((c).lo & VTD_PAGE_MASK) | 111 | return (context->lo & 1); |
112 | #define context_address_width(c) ((c).hi & 7) | 112 | } |
113 | #define context_domain_id(c) (((c).hi >> 8) & ((1 << 16) - 1)) | 113 | static inline void context_set_present(struct context_entry *context) |
114 | 114 | { | |
115 | #define context_set_present(c) do {(c).lo |= 1;} while (0) | 115 | context->lo |= 1; |
116 | #define context_set_fault_enable(c) \ | 116 | } |
117 | do {(c).lo &= (((u64)-1) << 2) | 1;} while (0) | 117 | |
118 | #define context_set_translation_type(c, val) \ | 118 | static inline void context_set_fault_enable(struct context_entry *context) |
119 | do { \ | 119 | { |
120 | (c).lo &= (((u64)-1) << 4) | 3; \ | 120 | context->lo &= (((u64)-1) << 2) | 1; |
121 | (c).lo |= ((val) & 3) << 2; \ | 121 | } |
122 | } while (0) | 122 | |
123 | #define CONTEXT_TT_MULTI_LEVEL 0 | 123 | #define CONTEXT_TT_MULTI_LEVEL 0 |
124 | #define context_set_address_root(c, val) \ | 124 | |
125 | do {(c).lo |= (val) & VTD_PAGE_MASK; } while (0) | 125 | static inline void context_set_translation_type(struct context_entry *context, |
126 | #define context_set_address_width(c, val) do {(c).hi |= (val) & 7;} while (0) | 126 | unsigned long value) |
127 | #define context_set_domain_id(c, val) \ | 127 | { |
128 | do {(c).hi |= ((val) & ((1 << 16) - 1)) << 8;} while (0) | 128 | context->lo &= (((u64)-1) << 4) | 3; |
129 | #define context_clear_entry(c) do {(c).lo = 0; (c).hi = 0;} while (0) | 129 | context->lo |= (value & 3) << 2; |
130 | } | ||
131 | |||
132 | static inline void context_set_address_root(struct context_entry *context, | ||
133 | unsigned long value) | ||
134 | { | ||
135 | context->lo |= value & VTD_PAGE_MASK; | ||
136 | } | ||
137 | |||
138 | static inline void context_set_address_width(struct context_entry *context, | ||
139 | unsigned long value) | ||
140 | { | ||
141 | context->hi |= value & 7; | ||
142 | } | ||
143 | |||
144 | static inline void context_set_domain_id(struct context_entry *context, | ||
145 | unsigned long value) | ||
146 | { | ||
147 | context->hi |= (value & ((1 << 16) - 1)) << 8; | ||
148 | } | ||
149 | |||
150 | static inline void context_clear_entry(struct context_entry *context) | ||
151 | { | ||
152 | context->lo = 0; | ||
153 | context->hi = 0; | ||
154 | } | ||
130 | 155 | ||
131 | /* | 156 | /* |
132 | * 0: readable | 157 | * 0: readable |
@@ -349,7 +374,7 @@ static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn) | |||
349 | ret = 0; | 374 | ret = 0; |
350 | goto out; | 375 | goto out; |
351 | } | 376 | } |
352 | ret = context_present(context[devfn]); | 377 | ret = context_present(&context[devfn]); |
353 | out: | 378 | out: |
354 | spin_unlock_irqrestore(&iommu->lock, flags); | 379 | spin_unlock_irqrestore(&iommu->lock, flags); |
355 | return ret; | 380 | return ret; |
@@ -365,7 +390,7 @@ static void clear_context_table(struct intel_iommu *iommu, u8 bus, u8 devfn) | |||
365 | root = &iommu->root_entry[bus]; | 390 | root = &iommu->root_entry[bus]; |
366 | context = get_context_addr_from_root(root); | 391 | context = get_context_addr_from_root(root); |
367 | if (context) { | 392 | if (context) { |
368 | context_clear_entry(context[devfn]); | 393 | context_clear_entry(&context[devfn]); |
369 | __iommu_flush_cache(iommu, &context[devfn], \ | 394 | __iommu_flush_cache(iommu, &context[devfn], \ |
370 | sizeof(*context)); | 395 | sizeof(*context)); |
371 | } | 396 | } |
@@ -1284,17 +1309,17 @@ static int domain_context_mapping_one(struct dmar_domain *domain, | |||
1284 | if (!context) | 1309 | if (!context) |
1285 | return -ENOMEM; | 1310 | return -ENOMEM; |
1286 | spin_lock_irqsave(&iommu->lock, flags); | 1311 | spin_lock_irqsave(&iommu->lock, flags); |
1287 | if (context_present(*context)) { | 1312 | if (context_present(context)) { |
1288 | spin_unlock_irqrestore(&iommu->lock, flags); | 1313 | spin_unlock_irqrestore(&iommu->lock, flags); |
1289 | return 0; | 1314 | return 0; |
1290 | } | 1315 | } |
1291 | 1316 | ||
1292 | context_set_domain_id(*context, domain->id); | 1317 | context_set_domain_id(context, domain->id); |
1293 | context_set_address_width(*context, domain->agaw); | 1318 | context_set_address_width(context, domain->agaw); |
1294 | context_set_address_root(*context, virt_to_phys(domain->pgd)); | 1319 | context_set_address_root(context, virt_to_phys(domain->pgd)); |
1295 | context_set_translation_type(*context, CONTEXT_TT_MULTI_LEVEL); | 1320 | context_set_translation_type(context, CONTEXT_TT_MULTI_LEVEL); |
1296 | context_set_fault_enable(*context); | 1321 | context_set_fault_enable(context); |
1297 | context_set_present(*context); | 1322 | context_set_present(context); |
1298 | __iommu_flush_cache(iommu, context, sizeof(*context)); | 1323 | __iommu_flush_cache(iommu, context, sizeof(*context)); |
1299 | 1324 | ||
1300 | /* it's a non-present to present mapping */ | 1325 | /* it's a non-present to present mapping */ |