aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2008-06-26 15:27:49 -0400
committerIngo Molnar <mingo@elte.hu>2008-06-27 04:12:12 -0400
commitbe2a022c0dd0f630b06f83de284df53cb60a308f (patch)
tree4e4fb7f371fc968f7bd106229ca5b4107581d4d5
parente47d402d2df89bb1aa77b7573597a9dd2241aafe (diff)
x86, AMD IOMMU: add functions to parse IOMMU memory mapping requirements for devices
This patch adds the functions to parse the information about IOMMU exclusion ranges and required unity mappings for the devices handled by the IOMMU. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> Cc: iommu@lists.linux-foundation.org Cc: bhavna.sarathy@amd.com Cc: Sebastian.Biemueller@amd.com Cc: robert.richter@amd.com Cc: joro@8bytes.org Signed-off-by: Ingo Molnar <mingo@elte.hu>
-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