1 /*
2  * Copyright 2014, General Dynamics C4 Systems
3  *
4  * SPDX-License-Identifier: GPL-2.0-only
5  */
6 
7 #include <config.h>
8 #include <util.h>
9 #include <assert.h>
10 #include <machine/io.h>
11 #include <linker.h>
12 #include <plat/machine.h>
13 #include <plat/machine/acpi.h>
14 #include <plat/machine/devices.h>
15 
16 enum acpi_type {
17     ACPI_RSDP,
18     ACPI_RSDT
19 };
20 
21 /* DMA Remapping Reporting Table */
22 typedef struct acpi_dmar {
23     acpi_header_t header;
24     uint8_t       host_addr_width;
25     uint8_t       flags;
26     uint8_t       reserved[10];
27 } acpi_dmar_t;
28 compile_assert(acpi_dmar_packed,
29                sizeof(acpi_dmar_t) == sizeof(acpi_header_t) + 12)
30 
31 /* DMA Remapping Structure Header */
32 typedef struct acpi_dmar_header {
33     uint16_t type;
34     uint16_t length;
35 } acpi_dmar_header_t;
36 compile_assert(acpi_dmar_header_packed, sizeof(acpi_dmar_header_t) == 4)
37 
38 /* DMA Remapping Structure Types */
39 enum acpi_table_dmar_struct_type {
40     DMAR_DRHD = 0,
41     DMAR_RMRR = 1,
42     DMAR_ATSR = 2,
43 };
44 
45 /* DMA Remapping Hardware unit Definition */
46 typedef struct acpi_dmar_drhd {
47     acpi_dmar_header_t header;
48     uint8_t            flags;
49     uint8_t            reserved;
50     uint16_t           segment;
51     uint32_t           reg_base[2];
52 } acpi_dmar_drhd_t;
53 compile_assert(acpi_dmar_drhd_packed,
54                sizeof(acpi_dmar_drhd_t) == sizeof(acpi_dmar_header_t) + 12)
55 
56 /* Reserved Memory Region Reporting structure Definition */
57 typedef struct acpi_dmar_devscope {
58     uint8_t  type;
59     uint8_t  length;
60     uint16_t reserved;
61     uint8_t  enum_id;
62     uint8_t  start_bus;
63     struct {
64         uint8_t dev;
65         uint8_t fun;
66     } path_0;
67 } acpi_dmar_devscope_t;
68 compile_assert(acpi_dmar_devscope_packed, sizeof(acpi_dmar_devscope_t) == 8)
69 
70 /* Reserved Memory Region Reporting structure Definition */
71 typedef struct acpi_dmar_rmrr {
72     acpi_dmar_header_t   header;
73     uint16_t             reserved;
74     uint16_t             segment;
75     uint32_t             reg_base[2];
76     uint32_t             reg_limit[2];
77     acpi_dmar_devscope_t devscope_0;
78 } acpi_dmar_rmrr_t;
79 compile_assert(acpi_dmar_rmrr_packed, sizeof(acpi_dmar_rmrr_t) ==
80                sizeof(acpi_dmar_header_t) + 20 + sizeof(acpi_dmar_devscope_t))
81 
82 /* Fixed ACPI Description Table (FADT), partial as we only need flags */
83 typedef struct acpi_fadt {
84     acpi_header_t  header;
85     uint8_t        reserved[76];
86     uint32_t       flags;
87 } acpi_fadt_t;
88 compile_assert(acpi_fadt_packed,
89                sizeof(acpi_fadt_t) == sizeof(acpi_header_t) + 80)
90 
91 /* Multiple APIC Description Table (MADT) */
92 typedef struct acpi_madt {
93     acpi_header_t header;
94     uint32_t      apic_addr;
95     uint32_t      flags;
96 } acpi_madt_t;
97 compile_assert(acpi_madt_packed,
98                sizeof(acpi_madt_t) == sizeof(acpi_header_t) + 8)
99 
100 typedef struct acpi_madt_header {
101     uint8_t type;
102     uint8_t length;
103 } acpi_madt_header_t;
104 compile_assert(acpi_madt_header_packed, sizeof(acpi_madt_header_t) == 2)
105 
106 enum acpi_table_madt_struct_type {
107     MADT_APIC   = 0,
108     MADT_IOAPIC = 1,
109     MADT_ISO    = 2,
110     MADT_x2APIC = 9
111 };
112 
113 typedef struct acpi_madt_apic {
114     acpi_madt_header_t header;
115     uint8_t            cpu_id;
116     uint8_t            apic_id;
117     uint32_t           flags;
118 } acpi_madt_apic_t;
119 compile_assert(acpi_madt_apic_packed,
120                sizeof(acpi_madt_apic_t) == sizeof(acpi_madt_header_t) + 6)
121 
122 typedef struct acpi_madt_x2apic {
123     acpi_madt_header_t  header;
124     uint16_t            reserved;
125     uint32_t            x2apic_id;
126     uint32_t            flags;
127     uint32_t            acpi_processor_uid;
128 } acpi_madt_x2apic_t;
129 compile_assert(acpi_madt_x2apic_packed,
130                sizeof(acpi_madt_x2apic_t) == sizeof(acpi_madt_header_t) + 14)
131 
132 typedef struct acpi_madt_ioapic {
133     acpi_madt_header_t header;
134     uint8_t            ioapic_id;
135     uint8_t            reserved[1];
136     uint32_t           ioapic_addr;
137     uint32_t           gsib;
138 } acpi_madt_ioapic_t;
139 compile_assert(acpi_madt_ioapic_packed,
140                sizeof(acpi_madt_ioapic_t) == sizeof(acpi_madt_header_t) + 10)
141 
142 typedef struct acpi_madt_iso {
143     acpi_madt_header_t header;
144     uint8_t            bus; /* always 0 (ISA) */
145     uint8_t            source;
146     uint32_t           gsi;
147     uint16_t           flags;
148 } acpi_madt_iso_t;
149 /* We can't assert on the sizeof acpi_madt_iso because it contains trailing
150  * padding.
151  */
152 unverified_compile_assert(acpi_madt_iso_packed,
153                           OFFSETOF(acpi_madt_iso_t, flags) == sizeof(acpi_madt_header_t) + 6)
154 
155 /* workaround because string literals are not supported by C parser */
156 const char acpi_str_rsd[]  = {'R', 'S', 'D', ' ', 'P', 'T', 'R', ' ', 0};
157 const char acpi_str_fadt[] = {'F', 'A', 'C', 'P', 0};
158 const char acpi_str_apic[] = {'A', 'P', 'I', 'C', 0};
159 const char acpi_str_dmar[] = {'D', 'M', 'A', 'R', 0};
160 
acpi_calc_checksum(char * start,uint32_t length)161 BOOT_CODE static uint8_t acpi_calc_checksum(char *start, uint32_t length)
162 {
163     uint8_t checksum = 0;
164 
165     while (length > 0) {
166         checksum += *start;
167         start++;
168         length--;
169     }
170     return checksum;
171 }
172 
acpi_get_rsdp(void)173 BOOT_CODE static acpi_rsdp_t *acpi_get_rsdp(void)
174 {
175     char *addr;
176 
177     for (addr = (char *)BIOS_PADDR_START; addr < (char *)BIOS_PADDR_END; addr += 16) {
178         if (strncmp(addr, acpi_str_rsd, 8) == 0) {
179             if (acpi_calc_checksum(addr, ACPI_V1_SIZE) == 0) {
180                 return (acpi_rsdp_t *)addr;
181             }
182         }
183     }
184     return NULL;
185 }
186 
acpi_table_init(void * entry,enum acpi_type table_type)187 BOOT_CODE static void *acpi_table_init(void *entry, enum acpi_type table_type)
188 {
189     void *acpi_table;
190     unsigned int pages_for_table;
191     unsigned int pages_for_header = 1;
192 
193     /* if we need to map another page to read header */
194     unsigned long offset_in_page = (unsigned long)entry & MASK(LARGE_PAGE_BITS);
195     if (MASK(LARGE_PAGE_BITS) - offset_in_page < sizeof(acpi_rsdp_t)) {
196         pages_for_header++;
197     }
198 
199     /* map in table's header */
200     acpi_table = map_temp_boot_page(entry, pages_for_header);
201 
202     switch (table_type) {
203     case ACPI_RSDP: {
204         acpi_rsdp_t *rsdp_entry = (acpi_rsdp_t *)entry;
205         pages_for_table = (rsdp_entry->length + offset_in_page) / MASK(LARGE_PAGE_BITS) + 1;
206         break;
207     }
208     case ACPI_RSDT: { // RSDT, MADT, DMAR etc.
209         acpi_rsdt_t *rsdt_entry = (acpi_rsdt_t *)entry;
210         pages_for_table = (rsdt_entry->header.length + offset_in_page) / MASK(LARGE_PAGE_BITS) + 1;
211         break;
212     }
213     default:
214         printf("Error: Mapping unknown ACPI table type\n");
215         assert(false);
216         return NULL;
217     }
218 
219     /* map in full table */
220     acpi_table = map_temp_boot_page(entry, pages_for_table);
221 
222     return acpi_table;
223 }
224 
acpi_init(acpi_rsdp_t * rsdp_data)225 BOOT_CODE bool_t acpi_init(acpi_rsdp_t *rsdp_data)
226 {
227     acpi_rsdp_t *acpi_rsdp = acpi_get_rsdp();
228 
229     if (acpi_rsdp == NULL) {
230         printf("BIOS: No ACPI support detected\n");
231         return false;
232     }
233     printf("ACPI: RSDP paddr=%p\n", acpi_rsdp);
234     acpi_rsdp = acpi_table_init(acpi_rsdp, ACPI_RSDP);
235     printf("ACPI: RSDP vaddr=%p\n", acpi_rsdp);
236 
237     /* create a copy of the rsdp data */
238     *rsdp_data = *acpi_rsdp;
239 
240     /* perform final validation */
241     return acpi_validate_rsdp(rsdp_data);
242 }
243 
acpi_validate_rsdp(acpi_rsdp_t * acpi_rsdp)244 BOOT_CODE bool_t acpi_validate_rsdp(acpi_rsdp_t *acpi_rsdp)
245 {
246     acpi_rsdt_t *acpi_rsdt;
247     acpi_rsdt_t *acpi_rsdt_mapped;
248 
249     if (acpi_calc_checksum((char *)acpi_rsdp, ACPI_V1_SIZE) != 0) {
250         printf("BIOS: ACPIv1 information corrupt\n");
251         return false;
252     }
253 
254     if (acpi_rsdp->revision > 0 && acpi_calc_checksum((char *)acpi_rsdp, sizeof(*acpi_rsdp)) != 0) {
255         printf("BIOS: ACPIv2 information corrupt\n");
256         return false;
257     }
258 
259     /* verify the rsdt, even though we do not actually make use of the mapping right now */
260     acpi_rsdt = (acpi_rsdt_t *)(word_t)acpi_rsdp->rsdt_address;
261     printf("ACPI: RSDT paddr=%p\n", acpi_rsdt);
262     acpi_rsdt_mapped = (acpi_rsdt_t *)acpi_table_init(acpi_rsdt, ACPI_RSDT);
263     printf("ACPI: RSDT vaddr=%p\n", acpi_rsdt_mapped);
264 
265     assert(acpi_rsdt_mapped->header.length > 0);
266     if (acpi_calc_checksum((char *)acpi_rsdt_mapped, acpi_rsdt_mapped->header.length) != 0) {
267         printf("ACPI: RSDT checksum failure\n");
268         return false;
269     }
270 
271     return true;
272 }
273 
acpi_madt_scan(acpi_rsdp_t * acpi_rsdp,cpu_id_t * cpu_list,uint32_t * num_ioapic,paddr_t * ioapic_paddrs)274 BOOT_CODE uint32_t acpi_madt_scan(
275     acpi_rsdp_t *acpi_rsdp,
276     cpu_id_t    *cpu_list,
277     uint32_t    *num_ioapic,
278     paddr_t     *ioapic_paddrs
279 )
280 {
281     unsigned int entries;
282     uint32_t            num_cpu;
283     uint32_t            count;
284     acpi_madt_t        *acpi_madt;
285     acpi_madt_header_t *acpi_madt_header;
286 
287     acpi_rsdt_t *acpi_rsdt_mapped;
288     acpi_madt_t *acpi_madt_mapped;
289     acpi_rsdt_mapped = (acpi_rsdt_t *)acpi_table_init((acpi_rsdt_t *)(word_t)acpi_rsdp->rsdt_address, ACPI_RSDT);
290 
291     num_cpu = 0;
292     *num_ioapic = 0;
293 
294     assert(acpi_rsdt_mapped->header.length >= sizeof(acpi_header_t));
295     /* Divide by uint32_t explicitly as this is the size as mandated by the ACPI standard */
296     entries = (acpi_rsdt_mapped->header.length - sizeof(acpi_header_t)) / sizeof(uint32_t);
297     for (count = 0; count < entries; count++) {
298         acpi_madt = (acpi_madt_t *)(word_t)acpi_rsdt_mapped->entry[count];
299         acpi_madt_mapped = (acpi_madt_t *)acpi_table_init(acpi_madt, ACPI_RSDT);
300 
301         if (strncmp(acpi_str_apic, acpi_madt_mapped->header.signature, 4) == 0) {
302             printf("ACPI: MADT paddr=%p\n", acpi_madt);
303             printf("ACPI: MADT vaddr=%p\n", acpi_madt_mapped);
304             printf("ACPI: MADT apic_addr=0x%x\n", acpi_madt_mapped->apic_addr);
305             printf("ACPI: MADT flags=0x%x\n", acpi_madt_mapped->flags);
306 
307             acpi_madt_header = (acpi_madt_header_t *)(acpi_madt_mapped + 1);
308 
309             while ((char *)acpi_madt_header < (char *)acpi_madt_mapped + acpi_madt_mapped->header.length) {
310                 switch (acpi_madt_header->type) {
311                 /* ACPI specifies the following rules when listing APIC IDs:
312                  *  - Boot processor is listed first
313                  *  - For multi-threaded processors, BIOS should list the first logical
314                  *    processor of each of the individual multi-threaded processors in MADT
315                  *    before listing any of the second logical processors.
316                  *  - APIC IDs < 0xFF should be listed in APIC subtable, APIC IDs >= 0xFF
317                  *    should be listed in X2APIC subtable */
318                 case MADT_APIC: {
319                     /* what Intel calls apic_id is what is called cpu_id in seL4! */
320                     uint8_t  cpu_id = ((acpi_madt_apic_t *)acpi_madt_header)->apic_id;
321                     uint32_t flags  = ((acpi_madt_apic_t *)acpi_madt_header)->flags;
322                     if (flags == 1) {
323                         printf("ACPI: MADT_APIC apic_id=0x%x\n", cpu_id);
324                         if (num_cpu == CONFIG_MAX_NUM_NODES) {
325                             printf("ACPI: Not recording this APIC, only support %d\n", CONFIG_MAX_NUM_NODES);
326                         } else {
327                             cpu_list[num_cpu] = cpu_id;
328                             num_cpu++;
329                         }
330                     }
331                     break;
332                 }
333                 case MADT_x2APIC: {
334                     uint32_t cpu_id = ((acpi_madt_x2apic_t *)acpi_madt_header)->x2apic_id;
335                     uint32_t flags  = ((acpi_madt_x2apic_t *)acpi_madt_header)->flags;
336                     if (flags == 1) {
337                         printf("ACPI: MADT_x2APIC apic_id=0x%x\n", cpu_id);
338                         if (num_cpu == CONFIG_MAX_NUM_NODES) {
339                             printf("ACPI: Not recording this APIC, only support %d\n", CONFIG_MAX_NUM_NODES);
340                         } else {
341                             cpu_list[num_cpu] = cpu_id;
342                             num_cpu++;
343                         }
344                     }
345                     break;
346                 }
347                 case MADT_IOAPIC:
348                     printf(
349                         "ACPI: MADT_IOAPIC ioapic_id=%d ioapic_addr=0x%x gsib=%d\n",
350                         ((acpi_madt_ioapic_t *)acpi_madt_header)->ioapic_id,
351                         ((acpi_madt_ioapic_t *)acpi_madt_header)->ioapic_addr,
352                         ((acpi_madt_ioapic_t *)acpi_madt_header)->gsib
353                     );
354                     if (*num_ioapic == CONFIG_MAX_NUM_IOAPIC) {
355                         printf("ACPI: Not recording this IOAPIC, only support %d\n", CONFIG_MAX_NUM_IOAPIC);
356                     } else {
357                         ioapic_paddrs[*num_ioapic] = ((acpi_madt_ioapic_t *)acpi_madt_header)->ioapic_addr;
358                         (*num_ioapic)++;
359                     }
360                     break;
361                 case MADT_ISO:
362                     printf("ACPI: MADT_ISO bus=%d source=%d gsi=%d flags=0x%x\n",
363                            ((acpi_madt_iso_t *)acpi_madt_header)->bus,
364                            ((acpi_madt_iso_t *)acpi_madt_header)->source,
365                            ((acpi_madt_iso_t *)acpi_madt_header)->gsi,
366                            ((acpi_madt_iso_t *)acpi_madt_header)->flags);
367                     break;
368                 default:
369                     break;
370                 }
371                 acpi_madt_header = (acpi_madt_header_t *)((char *)acpi_madt_header + acpi_madt_header->length);
372             }
373         }
374     }
375 
376     printf("ACPI: %d CPU(s) detected\n", num_cpu);
377 
378     return num_cpu;
379 }
380 
acpi_fadt_scan(acpi_rsdp_t * acpi_rsdp)381 BOOT_CODE bool_t acpi_fadt_scan(
382     acpi_rsdp_t *acpi_rsdp
383 )
384 {
385     unsigned int entries;
386     uint32_t            count;
387     acpi_fadt_t        *acpi_fadt;
388 
389     acpi_rsdt_t *acpi_rsdt_mapped;
390     acpi_fadt_t *acpi_fadt_mapped;
391     acpi_rsdt_mapped = (acpi_rsdt_t *)acpi_table_init((acpi_rsdt_t *)(word_t)acpi_rsdp->rsdt_address, ACPI_RSDT);
392 
393     assert(acpi_rsdt_mapped->header.length >= sizeof(acpi_header_t));
394     /* Divide by uint32_t explicitly as this is the size as mandated by the ACPI standard */
395     entries = (acpi_rsdt_mapped->header.length - sizeof(acpi_header_t)) / sizeof(uint32_t);
396     for (count = 0; count < entries; count++) {
397         acpi_fadt = (acpi_fadt_t *)(word_t)acpi_rsdt_mapped->entry[count];
398         acpi_fadt_mapped = (acpi_fadt_t *)acpi_table_init(acpi_fadt, ACPI_RSDT);
399 
400         if (strncmp(acpi_str_fadt, acpi_fadt_mapped->header.signature, 4) == 0) {
401             printf("ACPI: FADT paddr=%p\n", acpi_fadt);
402             printf("ACPI: FADT vaddr=%p\n", acpi_fadt_mapped);
403             printf("ACPI: FADT flags=0x%x\n", acpi_fadt_mapped->flags);
404 
405             if (config_set(CONFIG_USE_LOGICAL_IDS) &&
406                 acpi_fadt_mapped->flags & BIT(19)) {
407                 printf("system requires apic physical mode\n");
408                 return false;
409             }
410         }
411     }
412 
413     return true;
414 }
415 
acpi_dmar_scan(acpi_rsdp_t * acpi_rsdp,paddr_t * drhu_list,uint32_t * num_drhu,uint32_t max_drhu_list_len,acpi_rmrr_list_t * rmrr_list)416 BOOT_CODE void acpi_dmar_scan(
417     acpi_rsdp_t *acpi_rsdp,
418     paddr_t     *drhu_list,
419     uint32_t    *num_drhu,
420     uint32_t     max_drhu_list_len,
421     acpi_rmrr_list_t *rmrr_list
422 )
423 {
424     word_t i;
425     unsigned int entries;
426     uint32_t count;
427     uint32_t reg_basel, reg_baseh;
428     int rmrr_count;
429     dev_id_t dev_id;
430 
431     acpi_dmar_t          *acpi_dmar;
432     acpi_dmar_header_t   *acpi_dmar_header;
433     acpi_dmar_rmrr_t     *acpi_dmar_rmrr;
434     acpi_dmar_devscope_t *acpi_dmar_devscope;
435 
436     acpi_rsdt_t *acpi_rsdt_mapped;
437     acpi_dmar_t *acpi_dmar_mapped;
438 
439     acpi_rsdt_mapped = (acpi_rsdt_t *)acpi_table_init((acpi_rsdt_t *)(word_t)acpi_rsdp->rsdt_address, ACPI_RSDT);
440 
441     *num_drhu = 0;
442     rmrr_count = 0;
443 
444     assert(acpi_rsdt_mapped->header.length >= sizeof(acpi_header_t));
445     entries = (acpi_rsdt_mapped->header.length - sizeof(acpi_header_t)) / sizeof(uint32_t);
446     for (count = 0; count < entries; count++) {
447         acpi_dmar = (acpi_dmar_t *)(word_t)acpi_rsdt_mapped->entry[count];
448         acpi_dmar_mapped = (acpi_dmar_t *)acpi_table_init(acpi_dmar, ACPI_RSDT);
449 
450         if (strncmp(acpi_str_dmar, acpi_dmar_mapped->header.signature, 4) == 0) {
451             printf("ACPI: DMAR paddr=%p\n", acpi_dmar);
452             printf("ACPI: DMAR vaddr=%p\n", acpi_dmar_mapped);
453             printf("ACPI: IOMMU host address width: %d\n", acpi_dmar_mapped->host_addr_width + 1);
454             acpi_dmar_header = (acpi_dmar_header_t *)(acpi_dmar_mapped + 1);
455 
456             while ((char *)acpi_dmar_header < (char *)acpi_dmar_mapped + acpi_dmar_mapped->header.length) {
457                 switch (acpi_dmar_header->type) {
458 
459                 case DMAR_DRHD:
460                     if (*num_drhu == max_drhu_list_len) {
461                         printf("ACPI: too many IOMMUs, disabling IOMMU support\n");
462                         /* try to increase MAX_NUM_DRHU in config.h */
463                         *num_drhu = 0; /* report zero IOMMUs */
464                         return;
465                     }
466                     reg_basel = ((acpi_dmar_drhd_t *)acpi_dmar_header)->reg_base[0];
467                     reg_baseh = ((acpi_dmar_drhd_t *)acpi_dmar_header)->reg_base[1];
468                     /* check if value fits into uint32_t */
469                     if (reg_baseh != 0) {
470                         printf("ACPI: DMAR_DRHD reg_base exceeds 32 bit, disabling IOMMU support\n");
471                         /* try to make BIOS map it below 4G */
472                         *num_drhu = 0; /* report zero IOMMUs */
473                         return;
474                     }
475                     drhu_list[*num_drhu] = (paddr_t)reg_basel;
476                     (*num_drhu)++;
477                     break;
478 
479                 case DMAR_RMRR:
480                     /* loop through all device scopes of this RMRR */
481                     acpi_dmar_rmrr = (acpi_dmar_rmrr_t *)acpi_dmar_header;
482                     if (acpi_dmar_rmrr->reg_base[1] != 0 ||
483                         acpi_dmar_rmrr->reg_limit[1] != 0) {
484                         printf("ACPI: RMRR device above 4GiB, disabling IOMMU support\n");
485                         *num_drhu = 0;
486                         return ;
487                     }
488 
489                     for (i = 0; i <= (acpi_dmar_header->length - sizeof(acpi_dmar_rmrr_t)) / sizeof(acpi_dmar_devscope_t); i++) {
490                         acpi_dmar_devscope = &acpi_dmar_rmrr->devscope_0 + i;
491 
492                         if (acpi_dmar_devscope->type != 1) {
493                             /* FIXME - bugzilla bug 170 */
494                             printf("ACPI: RMRR device scope: non-PCI-Endpoint-Devices not supported yet, disabling IOMMU support\n");
495                             *num_drhu = 0; /* report zero IOMMUs */
496                             return;
497                         }
498 
499                         if (acpi_dmar_devscope->length > sizeof(acpi_dmar_devscope_t)) {
500                             /* FIXME - bugzilla bug 170 */
501                             printf("ACPI: RMRR device scope: devices behind bridges not supported yet, disabling IOMMU support\n");
502                             *num_drhu = 0; /* report zero IOMMUs */
503                             return;
504                         }
505 
506                         dev_id =
507                             get_dev_id(
508                                 acpi_dmar_devscope->start_bus,
509                                 acpi_dmar_devscope->path_0.dev,
510                                 acpi_dmar_devscope->path_0.fun
511                             );
512 
513                         if (rmrr_count == CONFIG_MAX_RMRR_ENTRIES) {
514                             printf("ACPI: Too many RMRR entries, disabling IOMMU support\n");
515                             *num_drhu = 0;
516                             return;
517                         }
518                         printf("\tACPI: registering RMRR entry for region for device: bus=0x%x dev=0x%x fun=0x%x\n",
519                                acpi_dmar_devscope->start_bus,
520                                acpi_dmar_devscope->path_0.dev,
521                                acpi_dmar_devscope->path_0.fun
522                               );
523 
524                         rmrr_list->entries[rmrr_count].device = dev_id;
525                         rmrr_list->entries[rmrr_count].base = acpi_dmar_rmrr->reg_base[0];
526                         rmrr_list->entries[rmrr_count].limit = acpi_dmar_rmrr->reg_limit[0];
527                         rmrr_count++;
528                     }
529                     break;
530 
531                 case DMAR_ATSR:
532                     /* not implemented yet */
533                     break;
534 
535                 default:
536                     printf("ACPI: Unknown DMA remapping structure type: %x\n", acpi_dmar_header->type);
537                 }
538                 acpi_dmar_header = (acpi_dmar_header_t *)((char *)acpi_dmar_header + acpi_dmar_header->length);
539             }
540         }
541     }
542     rmrr_list->num = rmrr_count;
543     printf("ACPI: %d IOMMUs detected\n", *num_drhu);
544 }
545