1 /*
2  * Copyright (C) 2018-2022 Intel Corporation.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef VTD_H
8 #define VTD_H
9 #include <types.h>
10 #include <pci.h>
11 #include <platform_acpi_info.h>
12 
13 #define INVALID_DRHD_INDEX 0xFFFFFFFFU
14 #define INVALID_IRTE_ID 0xFFFFU
15 
16 /*
17  * Intel IOMMU register specification per version 1.0 public spec.
18  */
19 
20 #define DMAR_VER_REG    0x0U /* Arch version supported by this IOMMU */
21 #define DMAR_CAP_REG    0x8U /* Hardware supported capabilities */
22 #define DMAR_ECAP_REG   0x10U    /* Extended capabilities supported */
23 #define DMAR_GCMD_REG   0x18U    /* Global command register */
24 #define DMAR_GSTS_REG   0x1cU    /* Global status register */
25 #define DMAR_RTADDR_REG 0x20U    /* Root entry table */
26 #define DMAR_CCMD_REG   0x28U    /* Context command reg */
27 #define DMAR_FSTS_REG   0x34U    /* Fault Status register */
28 #define DMAR_FECTL_REG  0x38U    /* Fault control register */
29 #define DMAR_FEDATA_REG 0x3cU    /* Fault event interrupt data register */
30 #define DMAR_FEADDR_REG 0x40U    /* Fault event interrupt addr register */
31 #define DMAR_FEUADDR_REG 0x44U   /* Upper address register */
32 #define DMAR_AFLOG_REG  0x58U    /* Advanced Fault control */
33 #define DMAR_PMEN_REG   0x64U    /* Enable Protected Memory Region */
34 #define DMAR_PLMBASE_REG 0x68U   /* PMRR Low addr */
35 #define DMAR_PLMLIMIT_REG 0x6cU  /* PMRR low limit */
36 #define DMAR_PHMBASE_REG 0x70U   /* PMRR high base addr */
37 #define DMAR_PHMLIMIT_REG 0x78U  /* PMRR high limit */
38 #define DMAR_IQH_REG    0x80U    /* Invalidation queue head register */
39 #define DMAR_IQT_REG    0x88U    /* Invalidation queue tail register */
40 #define DMAR_IQ_SHIFT   4   /* Invalidation queue head/tail shift */
41 #define DMAR_IQA_REG    0x90U    /* Invalidation queue addr register */
42 #define DMAR_ICS_REG    0x9cU    /* Invalidation complete status register */
43 #define DMAR_IRTA_REG   0xb8U    /* Interrupt remapping table addr register */
44 
45 /* Values for entry_type in ACPI_DMAR_DEVICE_SCOPE - device types */
46 enum acpi_dmar_scope_type {
47 	ACPI_DMAR_SCOPE_TYPE_NOT_USED       = 0,
48 	ACPI_DMAR_SCOPE_TYPE_ENDPOINT       = 1,
49 	ACPI_DMAR_SCOPE_TYPE_BRIDGE         = 2,
50 	ACPI_DMAR_SCOPE_TYPE_IOAPIC         = 3,
51 	ACPI_DMAR_SCOPE_TYPE_HPET           = 4,
52 	ACPI_DMAR_SCOPE_TYPE_NAMESPACE      = 5,
53 	ACPI_DMAR_SCOPE_TYPE_RESERVED       = 6 /* 6 and greater are reserved */
54 };
55 
56 struct iommu_domain {
57 	uint16_t vm_id;
58 	uint32_t addr_width;   /* address width of the domain */
59 	uint64_t trans_table_ptr;
60 };
61 
62 union source {
63 	uint16_t ioapic_id;
64 	union pci_bdf msi;
65 };
66 
67 struct intr_source {
68 	bool is_msi;
69 	union source src;
70 	/*
71 	 * pid_paddr = 0: invalid address, indicate that remapped mode shall be used
72 	 *
73 	 * pid_paddr != 0: physical address of posted interrupt descriptor, indicate
74 	 * that posted mode shall be used
75 	 */
76 	uint64_t pid_paddr;
77 };
78 
dmar_ver_major(uint64_t version)79 static inline uint8_t dmar_ver_major(uint64_t version)
80 {
81 	return (((uint8_t)version & 0xf0U) >> 4U);
82 }
83 
dmar_ver_minor(uint64_t version)84 static inline uint8_t dmar_ver_minor(uint64_t version)
85 {
86 	return ((uint8_t)version & 0x0fU);
87 }
88 
89 /*
90  * Decoding Capability Register
91  */
iommu_cap_pi(uint64_t cap)92 static inline uint8_t iommu_cap_pi(uint64_t cap)
93 {
94 	return ((uint8_t)(cap >> 59U) & 1U);
95 }
96 
iommu_cap_read_drain(uint64_t cap)97 static inline uint8_t iommu_cap_read_drain(uint64_t cap)
98 {
99 	return ((uint8_t)(cap >> 55U) & 1U);
100 }
101 
iommu_cap_write_drain(uint64_t cap)102 static inline uint8_t iommu_cap_write_drain(uint64_t cap)
103 {
104 	return ((uint8_t)(cap >> 54U) & 1U);
105 }
106 
iommu_cap_max_amask_val(uint64_t cap)107 static inline uint8_t iommu_cap_max_amask_val(uint64_t cap)
108 {
109 	return ((uint8_t)(cap >> 48U) & 0x3fU);
110 }
111 
iommu_cap_num_fault_regs(uint64_t cap)112 static inline uint16_t iommu_cap_num_fault_regs(uint64_t cap)
113 {
114 	return (((uint16_t)(cap >> 40U) & 0xffU) + 1U);
115 }
116 
iommu_cap_pgsel_inv(uint64_t cap)117 static inline uint8_t iommu_cap_pgsel_inv(uint64_t cap)
118 {
119 	return ((uint8_t)(cap >> 39U) & 1U);
120 }
121 
iommu_cap_super_page_val(uint64_t cap)122 static inline uint8_t iommu_cap_super_page_val(uint64_t cap)
123 {
124 	return ((uint8_t)(cap >> 34U) & 0xfU);
125 }
126 
iommu_cap_fault_reg_offset(uint64_t cap)127 static inline uint16_t iommu_cap_fault_reg_offset(uint64_t cap)
128 {
129 	return (((uint16_t)(cap >> 24U) & 0x3ffU) * 16U);
130 }
131 
iommu_cap_max_fault_reg_offset(uint64_t cap)132 static inline uint16_t iommu_cap_max_fault_reg_offset(uint64_t cap)
133 {
134 	return (iommu_cap_fault_reg_offset(cap) +
135 		(iommu_cap_num_fault_regs(cap) * 16U));
136 }
137 
iommu_cap_zlr(uint64_t cap)138 static inline uint8_t iommu_cap_zlr(uint64_t cap)
139 {
140 	return ((uint8_t)(cap >> 22U) & 1U);
141 }
142 
iommu_cap_isoch(uint64_t cap)143 static inline uint8_t iommu_cap_isoch(uint64_t cap)
144 {
145 	return ((uint8_t)(cap >> 23U) & 1U);
146 }
147 
iommu_cap_mgaw(uint64_t cap)148 static inline uint8_t iommu_cap_mgaw(uint64_t cap)
149 {
150 	return (((uint8_t)(cap >> 16U) & 0x3fU) + 1U);
151 }
152 
iommu_cap_sagaw(uint64_t cap)153 static inline uint8_t iommu_cap_sagaw(uint64_t cap)
154 {
155 	return ((uint8_t)(cap >> 8U) & 0x1fU);
156 }
157 
iommu_cap_caching_mode(uint64_t cap)158 static inline uint8_t iommu_cap_caching_mode(uint64_t cap)
159 {
160 	return ((uint8_t)(cap >> 7U) & 1U);
161 }
162 
iommu_cap_phmr(uint64_t cap)163 static inline uint8_t iommu_cap_phmr(uint64_t cap)
164 {
165 	return ((uint8_t)(cap >> 6U) & 1U);
166 }
167 
iommu_cap_plmr(uint64_t cap)168 static inline uint8_t iommu_cap_plmr(uint64_t cap)
169 {
170 	return ((uint8_t)(cap >> 5U) & 1U);
171 }
172 
iommu_cap_afl(uint64_t cap)173 static inline uint8_t iommu_cap_afl(uint64_t cap)
174 {
175 	return ((uint8_t)(cap >> 3U) & 1U);
176 }
177 
iommu_cap_ndoms(uint64_t cap)178 static inline uint32_t iommu_cap_ndoms(uint64_t cap)
179 {
180 	return ((1U) << (4U + (2U * ((uint8_t)cap & 0x7U))));
181 }
182 
183 /*
184  * Decoding Extended Capability Register
185  */
iommu_ecap_c(uint64_t ecap)186 static inline uint8_t iommu_ecap_c(uint64_t ecap)
187 {
188 	return ((uint8_t)(ecap >> 0U) & 1U);
189 }
190 
iommu_ecap_qi(uint64_t ecap)191 static inline uint8_t iommu_ecap_qi(uint64_t ecap)
192 {
193 	return ((uint8_t)(ecap >> 1U) & 1U);
194 }
195 
iommu_ecap_dt(uint64_t ecap)196 static inline uint8_t iommu_ecap_dt(uint64_t ecap)
197 {
198 	return ((uint8_t)(ecap >> 2U) & 1U);
199 }
200 
iommu_ecap_ir(uint64_t ecap)201 static inline uint8_t iommu_ecap_ir(uint64_t ecap)
202 {
203 	return ((uint8_t)(ecap >> 3U) & 1U);
204 }
205 
iommu_ecap_eim(uint64_t ecap)206 static inline uint8_t iommu_ecap_eim(uint64_t ecap)
207 {
208 	return ((uint8_t)(ecap >> 4U) & 1U);
209 }
210 
iommu_ecap_pt(uint64_t ecap)211 static inline uint8_t iommu_ecap_pt(uint64_t ecap)
212 {
213 	return ((uint8_t)(ecap >> 6U) & 1U);
214 }
215 
iommu_ecap_iro(uint64_t ecap)216 static inline uint16_t iommu_ecap_iro(uint64_t ecap)
217 {
218 	return ((uint16_t)(ecap >> 8U) & 0x3ffU);
219 }
220 
iommu_ecap_mhmv(uint64_t ecap)221 static inline uint8_t iommu_ecap_mhmv(uint64_t ecap)
222 {
223 	return ((uint8_t)(ecap >> 20U) & 0xfU);
224 }
225 
iommu_ecap_ecs(uint64_t ecap)226 static inline uint8_t iommu_ecap_ecs(uint64_t ecap)
227 {
228 	return ((uint8_t)(ecap >> 24U) & 1U);
229 }
230 
iommu_ecap_mts(uint64_t ecap)231 static inline uint8_t iommu_ecap_mts(uint64_t ecap)
232 {
233 	return ((uint8_t)(ecap >> 25U) & 1U);
234 }
235 
iommu_ecap_nest(uint64_t ecap)236 static inline uint8_t iommu_ecap_nest(uint64_t ecap)
237 {
238 	return ((uint8_t)(ecap >> 26U) & 1U);
239 }
240 
iommu_ecap_dis(uint64_t ecap)241 static inline uint8_t iommu_ecap_dis(uint64_t ecap)
242 {
243 	return ((uint8_t)(ecap >> 27U) & 1U);
244 }
245 
iommu_ecap_prs(uint64_t ecap)246 static inline uint8_t iommu_ecap_prs(uint64_t ecap)
247 {
248 	return ((uint8_t)(ecap >> 29U) & 1U);
249 }
250 
iommu_ecap_ers(uint64_t ecap)251 static inline uint8_t iommu_ecap_ers(uint64_t ecap)
252 {
253 	return ((uint8_t)(ecap >> 30U) & 1U);
254 }
255 
iommu_ecap_srs(uint64_t ecap)256 static inline uint8_t iommu_ecap_srs(uint64_t ecap)
257 {
258 	return ((uint8_t)(ecap >> 31U) & 1U);
259 }
260 
iommu_ecap_nwfs(uint64_t ecap)261 static inline uint8_t iommu_ecap_nwfs(uint64_t ecap)
262 {
263 	return ((uint8_t)(ecap >> 33U) & 1U);
264 }
265 
iommu_ecap_eafs(uint64_t ecap)266 static inline uint8_t iommu_ecap_eafs(uint64_t ecap)
267 {
268 	return ((uint8_t)(ecap >> 34U) & 1U);
269 }
270 
iommu_ecap_pss(uint64_t ecap)271 static inline uint8_t iommu_ecap_pss(uint64_t ecap)
272 {
273 	return ((uint8_t)(ecap >> 35U) & 0x1fU);
274 }
275 
iommu_ecap_pasid(uint64_t ecap)276 static inline uint8_t iommu_ecap_pasid(uint64_t ecap)
277 {
278 	return ((uint8_t)(ecap >> 40U) & 1U);
279 }
280 
iommu_ecap_dit(uint64_t ecap)281 static inline uint8_t iommu_ecap_dit(uint64_t ecap)
282 {
283 	return ((uint8_t)(ecap >> 41U) & 1U);
284 }
285 
iommu_ecap_pds(uint64_t ecap)286 static inline uint8_t iommu_ecap_pds(uint64_t ecap)
287 {
288 	return ((uint8_t)(ecap >> 42U) & 1U);
289 }
290 
291 /* PMEN_REG */
292 #define DMA_PMEN_EPM (1U << 31U)
293 #define DMA_PMEN_PRS (1U << 0U)
294 
295 /* GCMD_REG */
296 #define DMA_GCMD_TE (1U << 31U)
297 #define DMA_GCMD_SRTP (1U << 30U)
298 #define DMA_GCMD_SFL (1U << 29U)
299 #define DMA_GCMD_EAFL (1U << 28U)
300 #define DMA_GCMD_WBF (1U << 27U)
301 #define DMA_GCMD_QIE (1U << 26U)
302 #define DMA_GCMD_SIRTP (1U << 24U)
303 #define DMA_GCMD_IRE (1U << 25U)
304 #define DMA_GCMD_CFI (1U << 23U)
305 
306 /* GSTS_REG */
307 #define DMA_GSTS_TES (1U << 31U)
308 #define DMA_GSTS_RTPS (1U << 30U)
309 #define DMA_GSTS_FLS (1U << 29U)
310 #define DMA_GSTS_AFLS (1U << 28U)
311 #define DMA_GSTS_WBFS (1U << 27U)
312 #define DMA_GSTS_QIES (1U << 26U)
313 #define DMA_GSTS_IRTPS (1U << 24U)
314 #define DMA_GSTS_IRES (1U << 25U)
315 #define DMA_GSTS_CFIS (1U << 23U)
316 
317 /* CCMD_REG */
318 #define DMA_CONTEXT_GLOBAL_INVL (1UL << 4U)
319 #define DMA_CONTEXT_DOMAIN_INVL (2UL << 4U)
320 #define DMA_CONTEXT_DEVICE_INVL (3UL << 4U)
dma_ccmd_fm(uint8_t fm)321 static inline uint64_t dma_ccmd_fm(uint8_t fm)
322 {
323 	return (((uint64_t)fm & 0x3UL) << 48UL);
324 }
325 
326 #define DMA_CCMD_MASK_NOBIT 0UL
327 #define DMA_CCMD_MASK_1BIT 1UL
328 #define DMA_CCMD_MASK_2BIT 2UL
329 #define DMA_CCMD_MASK_3BIT 3UL
dma_ccmd_sid(uint16_t sid)330 static inline uint64_t dma_ccmd_sid(uint16_t sid)
331 {
332 	return (((uint64_t)sid & 0xffffUL) << 32UL);
333 }
334 
dma_ccmd_did(uint16_t did)335 static inline uint64_t dma_ccmd_did(uint16_t did)
336 {
337 	return (((uint64_t)did & 0xffffUL) << 16UL);
338 }
339 
dma_ccmd_get_caig_32(uint32_t gaig)340 static inline uint8_t dma_ccmd_get_caig_32(uint32_t gaig)
341 {
342 	return ((uint8_t)(gaig >> 27U) & 0x3U);
343 }
344 
345 
346 /* IOTLB_REG */
347 #define DMA_IOTLB_IVT				(((uint64_t)1UL) << 63U)
348 #define DMA_IOTLB_IVT_32			(((uint32_t)1U)  << 31U)
349 #define DMA_IOTLB_GLOBAL_INVL			(((uint64_t)1UL) << 4U)
350 #define DMA_IOTLB_DOMAIN_INVL			(((uint64_t)2UL) << 4U)
351 #define DMA_IOTLB_PAGE_INVL			(((uint64_t)3UL) << 4U)
352 #define DMA_IOTLB_DR				(((uint64_t)1UL) << 7U)
353 #define DMA_IOTLB_DW				(((uint64_t)1UL) << 6U)
dma_iotlb_did(uint16_t did)354 static inline uint64_t dma_iotlb_did(uint16_t did)
355 {
356 	return (((uint64_t)did & 0xffffUL) << 16UL);
357 }
358 
dma_iotlb_get_iaig_32(uint32_t iai)359 static inline uint8_t dma_iotlb_get_iaig_32(uint32_t iai)
360 {
361 	return ((uint8_t)(iai >> 25U) & 0x3U);
362 }
363 
364 /* INVALIDATE_ADDRESS_REG */
dma_iotlb_invl_addr_am(uint8_t am)365 static inline uint8_t dma_iotlb_invl_addr_am(uint8_t am)
366 {
367 	return (am & 0x3fU);
368 }
369 
370 /* IEC_REG */
371 #define DMAR_IECI_INDEXED		(((uint64_t)1UL) << 4U)
372 #define DMAR_IEC_GLOBAL_INVL		(((uint64_t)0UL) << 4U)
dma_iec_index(uint16_t index,uint8_t index_mask)373 static inline uint64_t dma_iec_index(uint16_t index, uint8_t index_mask)
374 {
375 	return ((((uint64_t)index & 0xFFFFU) << 32U) | (((uint64_t)index_mask & 0x1FU) << 27U));
376 }
377 
378 #define DMA_IOTLB_INVL_ADDR_IH_UNMODIFIED	(((uint64_t)1UL) << 6U)
379 
380 /* FECTL_REG */
381 #define DMA_FECTL_IM				(((uint32_t)1U) << 31U)
382 
383 /* FSTS_REG */
dma_fsts_pfo(uint32_t pfo)384 static inline bool dma_fsts_pfo(uint32_t pfo)
385 {
386 	return (((pfo >> 0U) & 1U) == 1U);
387 }
388 
dma_fsts_ppf(uint32_t ppf)389 static inline bool dma_fsts_ppf(uint32_t ppf)
390 {
391 	return (((ppf >> 1U) & 1U) == 1U);
392 }
393 
dma_fsts_afo(uint32_t afo)394 static inline bool dma_fsts_afo(uint32_t afo)
395 {
396 	return (((afo >> 2U) & 1U) == 1U);
397 }
398 
dma_fsts_apf(uint32_t apf)399 static inline bool dma_fsts_apf(uint32_t apf)
400 {
401 	return (((apf >> 3U) & 1U) == 1U);
402 }
403 
dma_fsts_iqe(uint32_t iqe)404 static inline bool dma_fsts_iqe(uint32_t iqe)
405 {
406 	return (((iqe >> 4U) & 1U) == 1U);
407 }
408 
dma_fsts_ice(uint32_t ice)409 static inline bool dma_fsts_ice(uint32_t ice)
410 {
411 	return (((ice >> 5U) & 1U) == 1U);
412 }
413 
dma_fsts_ite(uint32_t ite)414 static inline bool dma_fsts_ite(uint32_t ite)
415 {
416 	return (((ite >> 6U) & 1U) == 1U);
417 }
418 
dma_fsts_pro(uint32_t pro)419 static inline bool dma_fsts_pro(uint32_t pro)
420 {
421 	return (((pro >> 7U) & 1U) == 1U);
422 }
423 
dma_fsts_fri(uint32_t fri)424 static inline uint8_t dma_fsts_fri(uint32_t fri)
425 {
426 	return ((uint8_t)(fri >> 8U) & 0xFFU);
427 }
428 
429 /* FRCD_REGs: upper 64 bits*/
dma_frcd_up_f(uint64_t up_f)430 static inline bool dma_frcd_up_f(uint64_t up_f)
431 {
432 	return (((up_f >> 63U) & 1UL) == 1UL);
433 }
434 
dma_frcd_up_t(uint64_t up_t)435 static inline uint8_t dma_frcd_up_t(uint64_t up_t)
436 {
437 	return ((uint8_t)(up_t >> 62U) & 1U);
438 }
439 
dma_frcd_up_at(uint64_t up_at)440 static inline uint8_t dma_frcd_up_at(uint64_t up_at)
441 {
442 	return ((uint8_t)(up_at >> 60U) & 3U);
443 }
444 
dma_frcd_up_pasid(uint64_t up_pasid)445 static inline uint32_t dma_frcd_up_pasid(uint64_t up_pasid)
446 {
447 	return ((uint32_t)(up_pasid >> 40U) & 0xfffffU);
448 }
449 
dma_frcd_up_fr(uint64_t up_fr)450 static inline uint8_t dma_frcd_up_fr(uint64_t up_fr)
451 {
452 	return ((uint8_t)(up_fr >> 32U) & 0xffU);
453 }
454 
dma_frcd_up_pp(uint64_t up_pp)455 static inline bool dma_frcd_up_pp(uint64_t up_pp)
456 {
457 	return (((up_pp >> 31U) & 1UL) == 1UL);
458 }
459 
dma_frcd_up_exe(uint64_t up_exe)460 static inline bool dma_frcd_up_exe(uint64_t up_exe)
461 {
462 	return (((up_exe >> 30U) & 1UL) == 1UL);
463 }
464 
dma_frcd_up_priv(uint64_t up_priv)465 static inline bool dma_frcd_up_priv(uint64_t up_priv)
466 {
467 	return (((up_priv >> 29U) & 1UL) == 1UL);
468 }
469 
dma_frcd_up_sid(uint64_t up_sid)470 static inline uint16_t dma_frcd_up_sid(uint64_t up_sid)
471 {
472 	return ((uint16_t)up_sid & 0xffffU);
473 }
474 
475 #define MAX_DRHDS		DRHD_COUNT
476 #define MAX_DRHD_DEVSCOPES	DRHD_MAX_DEVSCOPE_COUNT
477 
478 #define DMAR_CONTEXT_TRANSLATION_TYPE_TRANSLATED 0x00U
479 #define DMAR_CONTEXT_TRANSLATION_TYPE_RESERVED 0x01U
480 #define DMAR_CONTEXT_TRANSLATION_TYPE_PASSED_THROUGH 0x02U
481 
482 #define DRHD_FLAG_INCLUDE_PCI_ALL_MASK      (1U)
483 
484 #define DEVFUN(dev, fun)            ((((dev) & 0x1FU) << 3U) | (((fun) & 0x7U)))
485 
486 struct dmar_dev_scope {
487 	enum acpi_dmar_scope_type type;
488 	uint8_t id;
489 	uint8_t bus;
490 	uint8_t devfun;
491 };
492 
493 struct dmar_drhd {
494 	uint32_t dev_cnt;
495 	uint16_t segment;
496 	uint8_t flags;
497 	bool ignore;
498 	uint64_t reg_base_addr;
499 	/* assume no pci device hotplug support */
500 	struct dmar_dev_scope *devices;
501 };
502 
503 struct dmar_info {
504 	uint32_t drhd_count;
505 	struct dmar_drhd *drhd_units;
506 };
507 
508 struct dmar_entry {
509 	uint64_t lo_64;
510 	uint64_t hi_64;
511 };
512 
513 union dmar_ir_entry {
514 	struct dmar_entry value;
515 
516 	union {
517 		/* Remapped mode */
518 		struct {
519 			uint64_t present:1;
520 			uint64_t fpd:1;
521 			uint64_t dest_mode:1;
522 			uint64_t rh:1;
523 			uint64_t trigger_mode:1;
524 			uint64_t delivery_mode:3;
525 			uint64_t avail:4;
526 			uint64_t rsvd_1:3;
527 			uint64_t mode:1;
528 			uint64_t vector:8;
529 			uint64_t rsvd_2:8;
530 			uint64_t dest:32;
531 
532 			uint64_t sid:16;
533 			uint64_t sq:2;
534 			uint64_t svt:2;
535 			uint64_t rsvd_3:44;
536 		} remap;
537 
538 		/* Posted mode */
539 		struct {
540 			uint64_t present:1;
541 			uint64_t fpd:1;
542 			uint64_t rsvd_1:6;
543 			uint64_t avail:4;
544 			uint64_t rsvd_2:2;
545 			uint64_t urgent:1;
546 			uint64_t mode:1;
547 			uint64_t vector:8;
548 			uint64_t rsvd_3:14;
549 			uint64_t pda_l:26;
550 
551 			uint64_t sid:16;
552 			uint64_t sq:2;
553 			uint64_t svt:2;
554 			uint64_t rsvd_4:12;
555 			uint64_t pda_h:32;
556 		} post;
557 	} bits __packed;
558 };
559 
560 #ifdef CONFIG_ACPI_PARSE_ENABLED
561 int32_t parse_dmar_table(struct dmar_info *plat_dmar_info);
562 #endif
563 
564 /**
565  * @file vtd.h
566  *
567  * @brief public APIs for VT-d
568  */
569 
570 /**
571  * @brief VT-d
572  *
573  * @defgroup acrn_vtd ACRN VT-d
574  * @{
575  */
576 
577 
578 /**
579  * @brief iommu domain.
580  *
581  * This struct declaration for iommu domain.
582  *
583  */
584 struct iommu_domain;
585 
586 /**
587  * @brief Assign a device specified by bus & devfun to a iommu domain.
588  *
589  * Remove the device from the from_domain (if non-NULL), and add it to the to_domain (if non-NULL).
590  * API silently fails to add/remove devices to/from domains that are under "Ignored" DMAR units.
591  *
592  * @param[in]    from_domain iommu domain from which the device is removed from
593  * @param[in]    to_domain iommu domain to which the device is assgined to
594  * @param[in]    bus the 8-bit bus number of the device
595  * @param[in]    devfun the 8-bit device(5-bit):function(3-bit) of the device
596  *
597  * @retval 0 on success.
598  * @retval 1 fail to unassign the device
599  *
600  * @pre domain != NULL
601  *
602  */
603 int32_t move_pt_device(const struct iommu_domain *from_domain, const struct iommu_domain *to_domain, uint8_t bus, uint8_t devfun);
604 
605 /**
606  * @brief Create a iommu domain for a VM specified by vm_id.
607  *
608  * Create a iommu domain for a VM specified by vm_id, along with address translation table and address width.
609  *
610  * @param[in] vm_id vm_id of the VM the domain created for
611  * @param[in] translation_table the physcial address of EPT table of the VM specified by the vm_id
612  * @param[in] addr_width address width of the VM
613  *
614  * @return Pointer to the created iommu_domain
615  *
616  * @retval NULL when \p translation_table is 0
617  * @retval !NULL when \p translation_table is not 0
618  *
619  * @pre vm_id is valid
620  * @pre translation_table != 0
621  *
622  */
623 struct iommu_domain *create_iommu_domain(uint16_t vm_id, uint64_t translation_table, uint32_t addr_width);
624 
625 /**
626  * @brief Destroy the specific iommu domain.
627  *
628  * Destroy the specific iommu domain when a VM no longer needs it.
629  *
630  * @param[in] domain iommu domain to destroy
631  *
632  * @pre domain != NULL
633  *
634  */
635 void destroy_iommu_domain(struct iommu_domain *domain);
636 
637 /**
638  * @brief Enable translation of IOMMUs.
639  *
640  * Enable address translation of all IOMMUs, which are not ignored on the platform.
641  *
642  */
643 void enable_iommu(void);
644 
645 /**
646  * @brief Suspend IOMMUs.
647  *
648  * Suspend all IOMMUs, which are not ignored on the platform.
649  *
650  */
651 void suspend_iommu(void);
652 
653 /**
654  * @brief Resume IOMMUs.
655  *
656  * Resume all IOMMUs, which are not ignored on the platform.
657  *
658  */
659 void resume_iommu(void);
660 
661 /**
662  * @brief Init IOMMUs.
663  *
664  * Register DMAR units on the platform according to the pre-parsed information
665  * or DMAR table. IOMMU is a must have feature, if init_iommu failed, the system
666  * should not continue booting.
667  *
668  * @retval 0 on success
669  * @retval <0 on failure
670  *
671  */
672 int32_t init_iommu(void);
673 
674 /**
675  * @brief Reserve num continuous IRTEs.
676  *
677  * @param[in] intr_src filled with type of interrupt source and the source
678  * @param[in] num number of IRTEs to reserve
679  * @param[out] start_id start index of reserved IRTEs, caller should check the value is INVALID_IRTE_ID or not.
680  *
681  * @retval 0 on success, caller should check whether the returned start index is valid or not.
682  * @retval -EINVAL if corresponding DMAR is not preset.
683  *
684  * @pre num can only be 2, 4, 8, 16 or 32
685  *
686  */
687 int32_t dmar_reserve_irte(const struct intr_source *intr_src, uint16_t num, uint16_t *start_id);
688 
689 /**
690  * @brief Assign RTE for Interrupt Remapping Table.
691  *
692  * @param[in] intr_src filled with type of interrupt source and the source
693  * @param[in] irte filled with information about interrupt delivery mode, destination core(s) and destination mode
694  * @param[in] idx_in if this value is INVALID_IRTE_ID, a new IRTE will be allocated, otherwise, use the IRTE directly.
695  * @param[out] idx_out return the actual IRTE index used, need to check whether the returned value is valid or not.
696  *
697  * @retval -EINVAL if corresponding DMAR is not present
698  * @retval 0 on success, caller should check whether the returned start index is valid or not.
699  *
700  */
701 int32_t dmar_assign_irte(const struct intr_source *intr_src, union dmar_ir_entry *irte,
702 	uint16_t idx_in, uint16_t *idx_out);
703 
704 /**
705  * @brief Free IRTE for Interrupt Remapping Table.
706  *
707  * @param[in] intr_src filled with type of interrupt source and the source
708  * @param[in] index into Interrupt Remapping Table
709  *
710  */
711 void dmar_free_irte(const struct intr_source *intr_src, uint16_t index);
712 
713 /**
714  * @brief Flash cacheline(s) for a specific address with specific size.
715  *
716  * Flash cacheline(s) for a specific address with specific size,
717  * if all IOMMUs active support page-walk coherency, cacheline(s) are not fluashed.
718  *
719  * @param[in] p the address of the buffer, whose cache need to be invalidated
720  * @param[in] size the size of the buffer
721  *
722  */
723 void iommu_flush_cache(const void *p, uint32_t size);
724 /**
725   * @}
726   */
727 
728 #endif
729