aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/amd_iommu_init.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index 3f4f7b890441..555fcc9830c8 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -556,3 +556,90 @@ static int __init init_iommu_all(struct acpi_table_header *table)
556 return 0; 556 return 0;
557} 557}
558 558
559static void __init free_unity_maps(void)
560{
561 struct unity_map_entry *entry, *next;
562
563 list_for_each_entry_safe(entry, next, &amd_iommu_unity_map, list) {
564 list_del(&entry->list);
565 kfree(entry);
566 }
567}
568
569static int __init init_exclusion_range(struct ivmd_header *m)
570{
571 int i;
572
573 switch (m->type) {
574 case ACPI_IVMD_TYPE:
575 set_device_exclusion_range(m->devid, m);
576 break;
577 case ACPI_IVMD_TYPE_ALL:
578 for (i = 0; i < amd_iommu_last_bdf; ++i)
579 set_device_exclusion_range(i, m);
580 break;
581 case ACPI_IVMD_TYPE_RANGE:
582 for (i = m->devid; i <= m->aux; ++i)
583 set_device_exclusion_range(i, m);
584 break;
585 default:
586 break;
587 }
588
589 return 0;
590}
591
592static int __init init_unity_map_range(struct ivmd_header *m)
593{
594 struct unity_map_entry *e = 0;
595
596 e = kzalloc(sizeof(*e), GFP_KERNEL);
597 if (e == NULL)
598 return -ENOMEM;
599
600 switch (m->type) {
601 default:
602 case ACPI_IVMD_TYPE:
603 e->devid_start = e->devid_end = m->devid;
604 break;
605 case ACPI_IVMD_TYPE_ALL:
606 e->devid_start = 0;
607 e->devid_end = amd_iommu_last_bdf;
608 break;
609 case ACPI_IVMD_TYPE_RANGE:
610 e->devid_start = m->devid;
611 e->devid_end = m->aux;
612 break;
613 }
614 e->address_start = PAGE_ALIGN(m->range_start);
615 e->address_end = e->address_start + PAGE_ALIGN(m->range_length);
616 e->prot = m->flags >> 1;
617
618 list_add_tail(&e->list, &amd_iommu_unity_map);
619
620 return 0;
621}
622
623static int __init init_memory_definitions(struct acpi_table_header *table)
624{
625 u8 *p = (u8 *)table, *end = (u8 *)table;
626 struct ivmd_header *m;
627
628 INIT_LIST_HEAD(&amd_iommu_unity_map);
629
630 end += table->length;
631 p += IVRS_HEADER_LENGTH;
632
633 while (p < end) {
634 m = (struct ivmd_header *)p;
635 if (m->flags & IVMD_FLAG_EXCL_RANGE)
636 init_exclusion_range(m);
637 else if (m->flags & IVMD_FLAG_UNITY_MAP)
638 init_unity_map_range(m);
639
640 p += m->length;
641 }
642
643 return 0;
644}
645