diff options
author | Joerg Roedel <jroedel@suse.de> | 2016-09-05 06:43:16 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2016-09-05 06:43:16 -0400 |
commit | 368d06cd536ecace3a904ae2e6e42771636d52aa (patch) | |
tree | b09c2b36487bb9af8a9b0587c63d8d012f7788ec | |
parent | 395adae45095e55ee90e688e9021d79dd6ffaefe (diff) | |
parent | d98de49a53e48f51332e97568127e722415e1232 (diff) |
Merge branch 'x86/amd-avic' into x86/amd
-rw-r--r-- | Documentation/kernel-parameters.txt | 9 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu.c | 484 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu_init.c | 181 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu_proto.h | 1 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu_types.h | 149 | ||||
-rw-r--r-- | include/linux/amd-iommu.h | 43 |
6 files changed, 801 insertions, 66 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 46c030a49186..748ef7bdd64d 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -460,6 +460,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
460 | driver will print ACPI tables for AMD IOMMU during | 460 | driver will print ACPI tables for AMD IOMMU during |
461 | IOMMU initialization. | 461 | IOMMU initialization. |
462 | 462 | ||
463 | amd_iommu_intr= [HW,X86-64] | ||
464 | Specifies one of the following AMD IOMMU interrupt | ||
465 | remapping modes: | ||
466 | legacy - Use legacy interrupt remapping mode. | ||
467 | vapic - Use virtual APIC mode, which allows IOMMU | ||
468 | to inject interrupts directly into guest. | ||
469 | This mode requires kvm-amd.avic=1. | ||
470 | (Default when IOMMU HW support is present.) | ||
471 | |||
463 | amijoy.map= [HW,JOY] Amiga joystick support | 472 | amijoy.map= [HW,JOY] Amiga joystick support |
464 | Map of devices attached to JOY0DAT and JOY1DAT | 473 | Map of devices attached to JOY0DAT and JOY1DAT |
465 | Format: <a>,<b> | 474 | Format: <a>,<b> |
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 2bcaca53aba5..bebe728019af 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
@@ -137,6 +137,7 @@ struct iommu_dev_data { | |||
137 | bool pri_tlp; /* PASID TLB required for | 137 | bool pri_tlp; /* PASID TLB required for |
138 | PPR completions */ | 138 | PPR completions */ |
139 | u32 errata; /* Bitmap for errata to apply */ | 139 | u32 errata; /* Bitmap for errata to apply */ |
140 | bool use_vapic; /* Enable device to use vapic mode */ | ||
140 | }; | 141 | }; |
141 | 142 | ||
142 | /* | 143 | /* |
@@ -707,14 +708,74 @@ static void iommu_poll_ppr_log(struct amd_iommu *iommu) | |||
707 | } | 708 | } |
708 | } | 709 | } |
709 | 710 | ||
711 | #ifdef CONFIG_IRQ_REMAP | ||
712 | static int (*iommu_ga_log_notifier)(u32); | ||
713 | |||
714 | int amd_iommu_register_ga_log_notifier(int (*notifier)(u32)) | ||
715 | { | ||
716 | iommu_ga_log_notifier = notifier; | ||
717 | |||
718 | return 0; | ||
719 | } | ||
720 | EXPORT_SYMBOL(amd_iommu_register_ga_log_notifier); | ||
721 | |||
722 | static void iommu_poll_ga_log(struct amd_iommu *iommu) | ||
723 | { | ||
724 | u32 head, tail, cnt = 0; | ||
725 | |||
726 | if (iommu->ga_log == NULL) | ||
727 | return; | ||
728 | |||
729 | head = readl(iommu->mmio_base + MMIO_GA_HEAD_OFFSET); | ||
730 | tail = readl(iommu->mmio_base + MMIO_GA_TAIL_OFFSET); | ||
731 | |||
732 | while (head != tail) { | ||
733 | volatile u64 *raw; | ||
734 | u64 log_entry; | ||
735 | |||
736 | raw = (u64 *)(iommu->ga_log + head); | ||
737 | cnt++; | ||
738 | |||
739 | /* Avoid memcpy function-call overhead */ | ||
740 | log_entry = *raw; | ||
741 | |||
742 | /* Update head pointer of hardware ring-buffer */ | ||
743 | head = (head + GA_ENTRY_SIZE) % GA_LOG_SIZE; | ||
744 | writel(head, iommu->mmio_base + MMIO_GA_HEAD_OFFSET); | ||
745 | |||
746 | /* Handle GA entry */ | ||
747 | switch (GA_REQ_TYPE(log_entry)) { | ||
748 | case GA_GUEST_NR: | ||
749 | if (!iommu_ga_log_notifier) | ||
750 | break; | ||
751 | |||
752 | pr_debug("AMD-Vi: %s: devid=%#x, ga_tag=%#x\n", | ||
753 | __func__, GA_DEVID(log_entry), | ||
754 | GA_TAG(log_entry)); | ||
755 | |||
756 | if (iommu_ga_log_notifier(GA_TAG(log_entry)) != 0) | ||
757 | pr_err("AMD-Vi: GA log notifier failed.\n"); | ||
758 | break; | ||
759 | default: | ||
760 | break; | ||
761 | } | ||
762 | } | ||
763 | } | ||
764 | #endif /* CONFIG_IRQ_REMAP */ | ||
765 | |||
766 | #define AMD_IOMMU_INT_MASK \ | ||
767 | (MMIO_STATUS_EVT_INT_MASK | \ | ||
768 | MMIO_STATUS_PPR_INT_MASK | \ | ||
769 | MMIO_STATUS_GALOG_INT_MASK) | ||
770 | |||
710 | irqreturn_t amd_iommu_int_thread(int irq, void *data) | 771 | irqreturn_t amd_iommu_int_thread(int irq, void *data) |
711 | { | 772 | { |
712 | struct amd_iommu *iommu = (struct amd_iommu *) data; | 773 | struct amd_iommu *iommu = (struct amd_iommu *) data; |
713 | u32 status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); | 774 | u32 status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); |
714 | 775 | ||
715 | while (status & (MMIO_STATUS_EVT_INT_MASK | MMIO_STATUS_PPR_INT_MASK)) { | 776 | while (status & AMD_IOMMU_INT_MASK) { |
716 | /* Enable EVT and PPR interrupts again */ | 777 | /* Enable EVT and PPR and GA interrupts again */ |
717 | writel((MMIO_STATUS_EVT_INT_MASK | MMIO_STATUS_PPR_INT_MASK), | 778 | writel(AMD_IOMMU_INT_MASK, |
718 | iommu->mmio_base + MMIO_STATUS_OFFSET); | 779 | iommu->mmio_base + MMIO_STATUS_OFFSET); |
719 | 780 | ||
720 | if (status & MMIO_STATUS_EVT_INT_MASK) { | 781 | if (status & MMIO_STATUS_EVT_INT_MASK) { |
@@ -727,6 +788,13 @@ irqreturn_t amd_iommu_int_thread(int irq, void *data) | |||
727 | iommu_poll_ppr_log(iommu); | 788 | iommu_poll_ppr_log(iommu); |
728 | } | 789 | } |
729 | 790 | ||
791 | #ifdef CONFIG_IRQ_REMAP | ||
792 | if (status & MMIO_STATUS_GALOG_INT_MASK) { | ||
793 | pr_devel("AMD-Vi: Processing IOMMU GA Log\n"); | ||
794 | iommu_poll_ga_log(iommu); | ||
795 | } | ||
796 | #endif | ||
797 | |||
730 | /* | 798 | /* |
731 | * Hardware bug: ERBT1312 | 799 | * Hardware bug: ERBT1312 |
732 | * When re-enabling interrupt (by writing 1 | 800 | * When re-enabling interrupt (by writing 1 |
@@ -2948,6 +3016,12 @@ static void amd_iommu_detach_device(struct iommu_domain *dom, | |||
2948 | if (!iommu) | 3016 | if (!iommu) |
2949 | return; | 3017 | return; |
2950 | 3018 | ||
3019 | #ifdef CONFIG_IRQ_REMAP | ||
3020 | if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) && | ||
3021 | (dom->type == IOMMU_DOMAIN_UNMANAGED)) | ||
3022 | dev_data->use_vapic = 0; | ||
3023 | #endif | ||
3024 | |||
2951 | iommu_completion_wait(iommu); | 3025 | iommu_completion_wait(iommu); |
2952 | } | 3026 | } |
2953 | 3027 | ||
@@ -2973,6 +3047,15 @@ static int amd_iommu_attach_device(struct iommu_domain *dom, | |||
2973 | 3047 | ||
2974 | ret = attach_device(dev, domain); | 3048 | ret = attach_device(dev, domain); |
2975 | 3049 | ||
3050 | #ifdef CONFIG_IRQ_REMAP | ||
3051 | if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir)) { | ||
3052 | if (dom->type == IOMMU_DOMAIN_UNMANAGED) | ||
3053 | dev_data->use_vapic = 1; | ||
3054 | else | ||
3055 | dev_data->use_vapic = 0; | ||
3056 | } | ||
3057 | #endif | ||
3058 | |||
2976 | iommu_completion_wait(iommu); | 3059 | iommu_completion_wait(iommu); |
2977 | 3060 | ||
2978 | return ret; | 3061 | return ret; |
@@ -3511,34 +3594,6 @@ EXPORT_SYMBOL(amd_iommu_device_info); | |||
3511 | * | 3594 | * |
3512 | *****************************************************************************/ | 3595 | *****************************************************************************/ |
3513 | 3596 | ||
3514 | union irte { | ||
3515 | u32 val; | ||
3516 | struct { | ||
3517 | u32 valid : 1, | ||
3518 | no_fault : 1, | ||
3519 | int_type : 3, | ||
3520 | rq_eoi : 1, | ||
3521 | dm : 1, | ||
3522 | rsvd_1 : 1, | ||
3523 | destination : 8, | ||
3524 | vector : 8, | ||
3525 | rsvd_2 : 8; | ||
3526 | } fields; | ||
3527 | }; | ||
3528 | |||
3529 | struct irq_2_irte { | ||
3530 | u16 devid; /* Device ID for IRTE table */ | ||
3531 | u16 index; /* Index into IRTE table*/ | ||
3532 | }; | ||
3533 | |||
3534 | struct amd_ir_data { | ||
3535 | struct irq_2_irte irq_2_irte; | ||
3536 | union irte irte_entry; | ||
3537 | union { | ||
3538 | struct msi_msg msi_entry; | ||
3539 | }; | ||
3540 | }; | ||
3541 | |||
3542 | static struct irq_chip amd_ir_chip; | 3597 | static struct irq_chip amd_ir_chip; |
3543 | 3598 | ||
3544 | #define DTE_IRQ_PHYS_ADDR_MASK (((1ULL << 45)-1) << 6) | 3599 | #define DTE_IRQ_PHYS_ADDR_MASK (((1ULL << 45)-1) << 6) |
@@ -3560,8 +3615,6 @@ static void set_dte_irq_entry(u16 devid, struct irq_remap_table *table) | |||
3560 | amd_iommu_dev_table[devid].data[2] = dte; | 3615 | amd_iommu_dev_table[devid].data[2] = dte; |
3561 | } | 3616 | } |
3562 | 3617 | ||
3563 | #define IRTE_ALLOCATED (~1U) | ||
3564 | |||
3565 | static struct irq_remap_table *get_irq_table(u16 devid, bool ioapic) | 3618 | static struct irq_remap_table *get_irq_table(u16 devid, bool ioapic) |
3566 | { | 3619 | { |
3567 | struct irq_remap_table *table = NULL; | 3620 | struct irq_remap_table *table = NULL; |
@@ -3607,13 +3660,18 @@ static struct irq_remap_table *get_irq_table(u16 devid, bool ioapic) | |||
3607 | goto out; | 3660 | goto out; |
3608 | } | 3661 | } |
3609 | 3662 | ||
3610 | memset(table->table, 0, MAX_IRQS_PER_TABLE * sizeof(u32)); | 3663 | if (!AMD_IOMMU_GUEST_IR_GA(amd_iommu_guest_ir)) |
3664 | memset(table->table, 0, | ||
3665 | MAX_IRQS_PER_TABLE * sizeof(u32)); | ||
3666 | else | ||
3667 | memset(table->table, 0, | ||
3668 | (MAX_IRQS_PER_TABLE * (sizeof(u64) * 2))); | ||
3611 | 3669 | ||
3612 | if (ioapic) { | 3670 | if (ioapic) { |
3613 | int i; | 3671 | int i; |
3614 | 3672 | ||
3615 | for (i = 0; i < 32; ++i) | 3673 | for (i = 0; i < 32; ++i) |
3616 | table->table[i] = IRTE_ALLOCATED; | 3674 | iommu->irte_ops->set_allocated(table, i); |
3617 | } | 3675 | } |
3618 | 3676 | ||
3619 | irq_lookup_table[devid] = table; | 3677 | irq_lookup_table[devid] = table; |
@@ -3639,6 +3697,10 @@ static int alloc_irq_index(u16 devid, int count) | |||
3639 | struct irq_remap_table *table; | 3697 | struct irq_remap_table *table; |
3640 | unsigned long flags; | 3698 | unsigned long flags; |
3641 | int index, c; | 3699 | int index, c; |
3700 | struct amd_iommu *iommu = amd_iommu_rlookup_table[devid]; | ||
3701 | |||
3702 | if (!iommu) | ||
3703 | return -ENODEV; | ||
3642 | 3704 | ||
3643 | table = get_irq_table(devid, false); | 3705 | table = get_irq_table(devid, false); |
3644 | if (!table) | 3706 | if (!table) |
@@ -3650,14 +3712,14 @@ static int alloc_irq_index(u16 devid, int count) | |||
3650 | for (c = 0, index = table->min_index; | 3712 | for (c = 0, index = table->min_index; |
3651 | index < MAX_IRQS_PER_TABLE; | 3713 | index < MAX_IRQS_PER_TABLE; |
3652 | ++index) { | 3714 | ++index) { |
3653 | if (table->table[index] == 0) | 3715 | if (!iommu->irte_ops->is_allocated(table, index)) |
3654 | c += 1; | 3716 | c += 1; |
3655 | else | 3717 | else |
3656 | c = 0; | 3718 | c = 0; |
3657 | 3719 | ||
3658 | if (c == count) { | 3720 | if (c == count) { |
3659 | for (; c != 0; --c) | 3721 | for (; c != 0; --c) |
3660 | table->table[index - c + 1] = IRTE_ALLOCATED; | 3722 | iommu->irte_ops->set_allocated(table, index - c + 1); |
3661 | 3723 | ||
3662 | index -= count - 1; | 3724 | index -= count - 1; |
3663 | goto out; | 3725 | goto out; |
@@ -3672,7 +3734,42 @@ out: | |||
3672 | return index; | 3734 | return index; |
3673 | } | 3735 | } |
3674 | 3736 | ||
3675 | static int modify_irte(u16 devid, int index, union irte irte) | 3737 | static int modify_irte_ga(u16 devid, int index, struct irte_ga *irte, |
3738 | struct amd_ir_data *data) | ||
3739 | { | ||
3740 | struct irq_remap_table *table; | ||
3741 | struct amd_iommu *iommu; | ||
3742 | unsigned long flags; | ||
3743 | struct irte_ga *entry; | ||
3744 | |||
3745 | iommu = amd_iommu_rlookup_table[devid]; | ||
3746 | if (iommu == NULL) | ||
3747 | return -EINVAL; | ||
3748 | |||
3749 | table = get_irq_table(devid, false); | ||
3750 | if (!table) | ||
3751 | return -ENOMEM; | ||
3752 | |||
3753 | spin_lock_irqsave(&table->lock, flags); | ||
3754 | |||
3755 | entry = (struct irte_ga *)table->table; | ||
3756 | entry = &entry[index]; | ||
3757 | entry->lo.fields_remap.valid = 0; | ||
3758 | entry->hi.val = irte->hi.val; | ||
3759 | entry->lo.val = irte->lo.val; | ||
3760 | entry->lo.fields_remap.valid = 1; | ||
3761 | if (data) | ||
3762 | data->ref = entry; | ||
3763 | |||
3764 | spin_unlock_irqrestore(&table->lock, flags); | ||
3765 | |||
3766 | iommu_flush_irt(iommu, devid); | ||
3767 | iommu_completion_wait(iommu); | ||
3768 | |||
3769 | return 0; | ||
3770 | } | ||
3771 | |||
3772 | static int modify_irte(u16 devid, int index, union irte *irte) | ||
3676 | { | 3773 | { |
3677 | struct irq_remap_table *table; | 3774 | struct irq_remap_table *table; |
3678 | struct amd_iommu *iommu; | 3775 | struct amd_iommu *iommu; |
@@ -3687,7 +3784,7 @@ static int modify_irte(u16 devid, int index, union irte irte) | |||
3687 | return -ENOMEM; | 3784 | return -ENOMEM; |
3688 | 3785 | ||
3689 | spin_lock_irqsave(&table->lock, flags); | 3786 | spin_lock_irqsave(&table->lock, flags); |
3690 | table->table[index] = irte.val; | 3787 | table->table[index] = irte->val; |
3691 | spin_unlock_irqrestore(&table->lock, flags); | 3788 | spin_unlock_irqrestore(&table->lock, flags); |
3692 | 3789 | ||
3693 | iommu_flush_irt(iommu, devid); | 3790 | iommu_flush_irt(iommu, devid); |
@@ -3711,13 +3808,146 @@ static void free_irte(u16 devid, int index) | |||
3711 | return; | 3808 | return; |
3712 | 3809 | ||
3713 | spin_lock_irqsave(&table->lock, flags); | 3810 | spin_lock_irqsave(&table->lock, flags); |
3714 | table->table[index] = 0; | 3811 | iommu->irte_ops->clear_allocated(table, index); |
3715 | spin_unlock_irqrestore(&table->lock, flags); | 3812 | spin_unlock_irqrestore(&table->lock, flags); |
3716 | 3813 | ||
3717 | iommu_flush_irt(iommu, devid); | 3814 | iommu_flush_irt(iommu, devid); |
3718 | iommu_completion_wait(iommu); | 3815 | iommu_completion_wait(iommu); |
3719 | } | 3816 | } |
3720 | 3817 | ||
3818 | static void irte_prepare(void *entry, | ||
3819 | u32 delivery_mode, u32 dest_mode, | ||
3820 | u8 vector, u32 dest_apicid, int devid) | ||
3821 | { | ||
3822 | union irte *irte = (union irte *) entry; | ||
3823 | |||
3824 | irte->val = 0; | ||
3825 | irte->fields.vector = vector; | ||
3826 | irte->fields.int_type = delivery_mode; | ||
3827 | irte->fields.destination = dest_apicid; | ||
3828 | irte->fields.dm = dest_mode; | ||
3829 | irte->fields.valid = 1; | ||
3830 | } | ||
3831 | |||
3832 | static void irte_ga_prepare(void *entry, | ||
3833 | u32 delivery_mode, u32 dest_mode, | ||
3834 | u8 vector, u32 dest_apicid, int devid) | ||
3835 | { | ||
3836 | struct irte_ga *irte = (struct irte_ga *) entry; | ||
3837 | struct iommu_dev_data *dev_data = search_dev_data(devid); | ||
3838 | |||
3839 | irte->lo.val = 0; | ||
3840 | irte->hi.val = 0; | ||
3841 | irte->lo.fields_remap.guest_mode = dev_data ? dev_data->use_vapic : 0; | ||
3842 | irte->lo.fields_remap.int_type = delivery_mode; | ||
3843 | irte->lo.fields_remap.dm = dest_mode; | ||
3844 | irte->hi.fields.vector = vector; | ||
3845 | irte->lo.fields_remap.destination = dest_apicid; | ||
3846 | irte->lo.fields_remap.valid = 1; | ||
3847 | } | ||
3848 | |||
3849 | static void irte_activate(void *entry, u16 devid, u16 index) | ||
3850 | { | ||
3851 | union irte *irte = (union irte *) entry; | ||
3852 | |||
3853 | irte->fields.valid = 1; | ||
3854 | modify_irte(devid, index, irte); | ||
3855 | } | ||
3856 | |||
3857 | static void irte_ga_activate(void *entry, u16 devid, u16 index) | ||
3858 | { | ||
3859 | struct irte_ga *irte = (struct irte_ga *) entry; | ||
3860 | |||
3861 | irte->lo.fields_remap.valid = 1; | ||
3862 | modify_irte_ga(devid, index, irte, NULL); | ||
3863 | } | ||
3864 | |||
3865 | static void irte_deactivate(void *entry, u16 devid, u16 index) | ||
3866 | { | ||
3867 | union irte *irte = (union irte *) entry; | ||
3868 | |||
3869 | irte->fields.valid = 0; | ||
3870 | modify_irte(devid, index, irte); | ||
3871 | } | ||
3872 | |||
3873 | static void irte_ga_deactivate(void *entry, u16 devid, u16 index) | ||
3874 | { | ||
3875 | struct irte_ga *irte = (struct irte_ga *) entry; | ||
3876 | |||
3877 | irte->lo.fields_remap.valid = 0; | ||
3878 | modify_irte_ga(devid, index, irte, NULL); | ||
3879 | } | ||
3880 | |||
3881 | static void irte_set_affinity(void *entry, u16 devid, u16 index, | ||
3882 | u8 vector, u32 dest_apicid) | ||
3883 | { | ||
3884 | union irte *irte = (union irte *) entry; | ||
3885 | |||
3886 | irte->fields.vector = vector; | ||
3887 | irte->fields.destination = dest_apicid; | ||
3888 | modify_irte(devid, index, irte); | ||
3889 | } | ||
3890 | |||
3891 | static void irte_ga_set_affinity(void *entry, u16 devid, u16 index, | ||
3892 | u8 vector, u32 dest_apicid) | ||
3893 | { | ||
3894 | struct irte_ga *irte = (struct irte_ga *) entry; | ||
3895 | struct iommu_dev_data *dev_data = search_dev_data(devid); | ||
3896 | |||
3897 | if (!dev_data || !dev_data->use_vapic) { | ||
3898 | irte->hi.fields.vector = vector; | ||
3899 | irte->lo.fields_remap.destination = dest_apicid; | ||
3900 | irte->lo.fields_remap.guest_mode = 0; | ||
3901 | modify_irte_ga(devid, index, irte, NULL); | ||
3902 | } | ||
3903 | } | ||
3904 | |||
3905 | #define IRTE_ALLOCATED (~1U) | ||
3906 | static void irte_set_allocated(struct irq_remap_table *table, int index) | ||
3907 | { | ||
3908 | table->table[index] = IRTE_ALLOCATED; | ||
3909 | } | ||
3910 | |||
3911 | static void irte_ga_set_allocated(struct irq_remap_table *table, int index) | ||
3912 | { | ||
3913 | struct irte_ga *ptr = (struct irte_ga *)table->table; | ||
3914 | struct irte_ga *irte = &ptr[index]; | ||
3915 | |||
3916 | memset(&irte->lo.val, 0, sizeof(u64)); | ||
3917 | memset(&irte->hi.val, 0, sizeof(u64)); | ||
3918 | irte->hi.fields.vector = 0xff; | ||
3919 | } | ||
3920 | |||
3921 | static bool irte_is_allocated(struct irq_remap_table *table, int index) | ||
3922 | { | ||
3923 | union irte *ptr = (union irte *)table->table; | ||
3924 | union irte *irte = &ptr[index]; | ||
3925 | |||
3926 | return irte->val != 0; | ||
3927 | } | ||
3928 | |||
3929 | static bool irte_ga_is_allocated(struct irq_remap_table *table, int index) | ||
3930 | { | ||
3931 | struct irte_ga *ptr = (struct irte_ga *)table->table; | ||
3932 | struct irte_ga *irte = &ptr[index]; | ||
3933 | |||
3934 | return irte->hi.fields.vector != 0; | ||
3935 | } | ||
3936 | |||
3937 | static void irte_clear_allocated(struct irq_remap_table *table, int index) | ||
3938 | { | ||
3939 | table->table[index] = 0; | ||
3940 | } | ||
3941 | |||
3942 | static void irte_ga_clear_allocated(struct irq_remap_table *table, int index) | ||
3943 | { | ||
3944 | struct irte_ga *ptr = (struct irte_ga *)table->table; | ||
3945 | struct irte_ga *irte = &ptr[index]; | ||
3946 | |||
3947 | memset(&irte->lo.val, 0, sizeof(u64)); | ||
3948 | memset(&irte->hi.val, 0, sizeof(u64)); | ||
3949 | } | ||
3950 | |||
3721 | static int get_devid(struct irq_alloc_info *info) | 3951 | static int get_devid(struct irq_alloc_info *info) |
3722 | { | 3952 | { |
3723 | int devid = -1; | 3953 | int devid = -1; |
@@ -3802,19 +4032,17 @@ static void irq_remapping_prepare_irte(struct amd_ir_data *data, | |||
3802 | { | 4032 | { |
3803 | struct irq_2_irte *irte_info = &data->irq_2_irte; | 4033 | struct irq_2_irte *irte_info = &data->irq_2_irte; |
3804 | struct msi_msg *msg = &data->msi_entry; | 4034 | struct msi_msg *msg = &data->msi_entry; |
3805 | union irte *irte = &data->irte_entry; | ||
3806 | struct IO_APIC_route_entry *entry; | 4035 | struct IO_APIC_route_entry *entry; |
4036 | struct amd_iommu *iommu = amd_iommu_rlookup_table[devid]; | ||
4037 | |||
4038 | if (!iommu) | ||
4039 | return; | ||
3807 | 4040 | ||
3808 | data->irq_2_irte.devid = devid; | 4041 | data->irq_2_irte.devid = devid; |
3809 | data->irq_2_irte.index = index + sub_handle; | 4042 | data->irq_2_irte.index = index + sub_handle; |
3810 | 4043 | iommu->irte_ops->prepare(data->entry, apic->irq_delivery_mode, | |
3811 | /* Setup IRTE for IOMMU */ | 4044 | apic->irq_dest_mode, irq_cfg->vector, |
3812 | irte->val = 0; | 4045 | irq_cfg->dest_apicid, devid); |
3813 | irte->fields.vector = irq_cfg->vector; | ||
3814 | irte->fields.int_type = apic->irq_delivery_mode; | ||
3815 | irte->fields.destination = irq_cfg->dest_apicid; | ||
3816 | irte->fields.dm = apic->irq_dest_mode; | ||
3817 | irte->fields.valid = 1; | ||
3818 | 4046 | ||
3819 | switch (info->type) { | 4047 | switch (info->type) { |
3820 | case X86_IRQ_ALLOC_TYPE_IOAPIC: | 4048 | case X86_IRQ_ALLOC_TYPE_IOAPIC: |
@@ -3845,12 +4073,32 @@ static void irq_remapping_prepare_irte(struct amd_ir_data *data, | |||
3845 | } | 4073 | } |
3846 | } | 4074 | } |
3847 | 4075 | ||
4076 | struct amd_irte_ops irte_32_ops = { | ||
4077 | .prepare = irte_prepare, | ||
4078 | .activate = irte_activate, | ||
4079 | .deactivate = irte_deactivate, | ||
4080 | .set_affinity = irte_set_affinity, | ||
4081 | .set_allocated = irte_set_allocated, | ||
4082 | .is_allocated = irte_is_allocated, | ||
4083 | .clear_allocated = irte_clear_allocated, | ||
4084 | }; | ||
4085 | |||
4086 | struct amd_irte_ops irte_128_ops = { | ||
4087 | .prepare = irte_ga_prepare, | ||
4088 | .activate = irte_ga_activate, | ||
4089 | .deactivate = irte_ga_deactivate, | ||
4090 | .set_affinity = irte_ga_set_affinity, | ||
4091 | .set_allocated = irte_ga_set_allocated, | ||
4092 | .is_allocated = irte_ga_is_allocated, | ||
4093 | .clear_allocated = irte_ga_clear_allocated, | ||
4094 | }; | ||
4095 | |||
3848 | static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq, | 4096 | static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq, |
3849 | unsigned int nr_irqs, void *arg) | 4097 | unsigned int nr_irqs, void *arg) |
3850 | { | 4098 | { |
3851 | struct irq_alloc_info *info = arg; | 4099 | struct irq_alloc_info *info = arg; |
3852 | struct irq_data *irq_data; | 4100 | struct irq_data *irq_data; |
3853 | struct amd_ir_data *data; | 4101 | struct amd_ir_data *data = NULL; |
3854 | struct irq_cfg *cfg; | 4102 | struct irq_cfg *cfg; |
3855 | int i, ret, devid; | 4103 | int i, ret, devid; |
3856 | int index = -1; | 4104 | int index = -1; |
@@ -3903,6 +4151,16 @@ static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq, | |||
3903 | if (!data) | 4151 | if (!data) |
3904 | goto out_free_data; | 4152 | goto out_free_data; |
3905 | 4153 | ||
4154 | if (!AMD_IOMMU_GUEST_IR_GA(amd_iommu_guest_ir)) | ||
4155 | data->entry = kzalloc(sizeof(union irte), GFP_KERNEL); | ||
4156 | else | ||
4157 | data->entry = kzalloc(sizeof(struct irte_ga), | ||
4158 | GFP_KERNEL); | ||
4159 | if (!data->entry) { | ||
4160 | kfree(data); | ||
4161 | goto out_free_data; | ||
4162 | } | ||
4163 | |||
3906 | irq_data->hwirq = (devid << 16) + i; | 4164 | irq_data->hwirq = (devid << 16) + i; |
3907 | irq_data->chip_data = data; | 4165 | irq_data->chip_data = data; |
3908 | irq_data->chip = &amd_ir_chip; | 4166 | irq_data->chip = &amd_ir_chip; |
@@ -3939,6 +4197,7 @@ static void irq_remapping_free(struct irq_domain *domain, unsigned int virq, | |||
3939 | data = irq_data->chip_data; | 4197 | data = irq_data->chip_data; |
3940 | irte_info = &data->irq_2_irte; | 4198 | irte_info = &data->irq_2_irte; |
3941 | free_irte(irte_info->devid, irte_info->index); | 4199 | free_irte(irte_info->devid, irte_info->index); |
4200 | kfree(data->entry); | ||
3942 | kfree(data); | 4201 | kfree(data); |
3943 | } | 4202 | } |
3944 | } | 4203 | } |
@@ -3950,8 +4209,11 @@ static void irq_remapping_activate(struct irq_domain *domain, | |||
3950 | { | 4209 | { |
3951 | struct amd_ir_data *data = irq_data->chip_data; | 4210 | struct amd_ir_data *data = irq_data->chip_data; |
3952 | struct irq_2_irte *irte_info = &data->irq_2_irte; | 4211 | struct irq_2_irte *irte_info = &data->irq_2_irte; |
4212 | struct amd_iommu *iommu = amd_iommu_rlookup_table[irte_info->devid]; | ||
3953 | 4213 | ||
3954 | modify_irte(irte_info->devid, irte_info->index, data->irte_entry); | 4214 | if (iommu) |
4215 | iommu->irte_ops->activate(data->entry, irte_info->devid, | ||
4216 | irte_info->index); | ||
3955 | } | 4217 | } |
3956 | 4218 | ||
3957 | static void irq_remapping_deactivate(struct irq_domain *domain, | 4219 | static void irq_remapping_deactivate(struct irq_domain *domain, |
@@ -3959,10 +4221,11 @@ static void irq_remapping_deactivate(struct irq_domain *domain, | |||
3959 | { | 4221 | { |
3960 | struct amd_ir_data *data = irq_data->chip_data; | 4222 | struct amd_ir_data *data = irq_data->chip_data; |
3961 | struct irq_2_irte *irte_info = &data->irq_2_irte; | 4223 | struct irq_2_irte *irte_info = &data->irq_2_irte; |
3962 | union irte entry; | 4224 | struct amd_iommu *iommu = amd_iommu_rlookup_table[irte_info->devid]; |
3963 | 4225 | ||
3964 | entry.val = 0; | 4226 | if (iommu) |
3965 | modify_irte(irte_info->devid, irte_info->index, data->irte_entry); | 4227 | iommu->irte_ops->deactivate(data->entry, irte_info->devid, |
4228 | irte_info->index); | ||
3966 | } | 4229 | } |
3967 | 4230 | ||
3968 | static struct irq_domain_ops amd_ir_domain_ops = { | 4231 | static struct irq_domain_ops amd_ir_domain_ops = { |
@@ -3972,6 +4235,70 @@ static struct irq_domain_ops amd_ir_domain_ops = { | |||
3972 | .deactivate = irq_remapping_deactivate, | 4235 | .deactivate = irq_remapping_deactivate, |
3973 | }; | 4236 | }; |
3974 | 4237 | ||
4238 | static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *vcpu_info) | ||
4239 | { | ||
4240 | struct amd_iommu *iommu; | ||
4241 | struct amd_iommu_pi_data *pi_data = vcpu_info; | ||
4242 | struct vcpu_data *vcpu_pi_info = pi_data->vcpu_data; | ||
4243 | struct amd_ir_data *ir_data = data->chip_data; | ||
4244 | struct irte_ga *irte = (struct irte_ga *) ir_data->entry; | ||
4245 | struct irq_2_irte *irte_info = &ir_data->irq_2_irte; | ||
4246 | struct iommu_dev_data *dev_data = search_dev_data(irte_info->devid); | ||
4247 | |||
4248 | /* Note: | ||
4249 | * This device has never been set up for guest mode. | ||
4250 | * we should not modify the IRTE | ||
4251 | */ | ||
4252 | if (!dev_data || !dev_data->use_vapic) | ||
4253 | return 0; | ||
4254 | |||
4255 | pi_data->ir_data = ir_data; | ||
4256 | |||
4257 | /* Note: | ||
4258 | * SVM tries to set up for VAPIC mode, but we are in | ||
4259 | * legacy mode. So, we force legacy mode instead. | ||
4260 | */ | ||
4261 | if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir)) { | ||
4262 | pr_debug("AMD-Vi: %s: Fall back to using intr legacy remap\n", | ||
4263 | __func__); | ||
4264 | pi_data->is_guest_mode = false; | ||
4265 | } | ||
4266 | |||
4267 | iommu = amd_iommu_rlookup_table[irte_info->devid]; | ||
4268 | if (iommu == NULL) | ||
4269 | return -EINVAL; | ||
4270 | |||
4271 | pi_data->prev_ga_tag = ir_data->cached_ga_tag; | ||
4272 | if (pi_data->is_guest_mode) { | ||
4273 | /* Setting */ | ||
4274 | irte->hi.fields.ga_root_ptr = (pi_data->base >> 12); | ||
4275 | irte->hi.fields.vector = vcpu_pi_info->vector; | ||
4276 | irte->lo.fields_vapic.guest_mode = 1; | ||
4277 | irte->lo.fields_vapic.ga_tag = pi_data->ga_tag; | ||
4278 | |||
4279 | ir_data->cached_ga_tag = pi_data->ga_tag; | ||
4280 | } else { | ||
4281 | /* Un-Setting */ | ||
4282 | struct irq_cfg *cfg = irqd_cfg(data); | ||
4283 | |||
4284 | irte->hi.val = 0; | ||
4285 | irte->lo.val = 0; | ||
4286 | irte->hi.fields.vector = cfg->vector; | ||
4287 | irte->lo.fields_remap.guest_mode = 0; | ||
4288 | irte->lo.fields_remap.destination = cfg->dest_apicid; | ||
4289 | irte->lo.fields_remap.int_type = apic->irq_delivery_mode; | ||
4290 | irte->lo.fields_remap.dm = apic->irq_dest_mode; | ||
4291 | |||
4292 | /* | ||
4293 | * This communicates the ga_tag back to the caller | ||
4294 | * so that it can do all the necessary clean up. | ||
4295 | */ | ||
4296 | ir_data->cached_ga_tag = 0; | ||
4297 | } | ||
4298 | |||
4299 | return modify_irte_ga(irte_info->devid, irte_info->index, irte, ir_data); | ||
4300 | } | ||
4301 | |||
3975 | static int amd_ir_set_affinity(struct irq_data *data, | 4302 | static int amd_ir_set_affinity(struct irq_data *data, |
3976 | const struct cpumask *mask, bool force) | 4303 | const struct cpumask *mask, bool force) |
3977 | { | 4304 | { |
@@ -3979,8 +4306,12 @@ static int amd_ir_set_affinity(struct irq_data *data, | |||
3979 | struct irq_2_irte *irte_info = &ir_data->irq_2_irte; | 4306 | struct irq_2_irte *irte_info = &ir_data->irq_2_irte; |
3980 | struct irq_cfg *cfg = irqd_cfg(data); | 4307 | struct irq_cfg *cfg = irqd_cfg(data); |
3981 | struct irq_data *parent = data->parent_data; | 4308 | struct irq_data *parent = data->parent_data; |
4309 | struct amd_iommu *iommu = amd_iommu_rlookup_table[irte_info->devid]; | ||
3982 | int ret; | 4310 | int ret; |
3983 | 4311 | ||
4312 | if (!iommu) | ||
4313 | return -ENODEV; | ||
4314 | |||
3984 | ret = parent->chip->irq_set_affinity(parent, mask, force); | 4315 | ret = parent->chip->irq_set_affinity(parent, mask, force); |
3985 | if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE) | 4316 | if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE) |
3986 | return ret; | 4317 | return ret; |
@@ -3989,9 +4320,8 @@ static int amd_ir_set_affinity(struct irq_data *data, | |||
3989 | * Atomically updates the IRTE with the new destination, vector | 4320 | * Atomically updates the IRTE with the new destination, vector |
3990 | * and flushes the interrupt entry cache. | 4321 | * and flushes the interrupt entry cache. |
3991 | */ | 4322 | */ |
3992 | ir_data->irte_entry.fields.vector = cfg->vector; | 4323 | iommu->irte_ops->set_affinity(ir_data->entry, irte_info->devid, |
3993 | ir_data->irte_entry.fields.destination = cfg->dest_apicid; | 4324 | irte_info->index, cfg->vector, cfg->dest_apicid); |
3994 | modify_irte(irte_info->devid, irte_info->index, ir_data->irte_entry); | ||
3995 | 4325 | ||
3996 | /* | 4326 | /* |
3997 | * After this point, all the interrupts will start arriving | 4327 | * After this point, all the interrupts will start arriving |
@@ -4013,6 +4343,7 @@ static void ir_compose_msi_msg(struct irq_data *irq_data, struct msi_msg *msg) | |||
4013 | static struct irq_chip amd_ir_chip = { | 4343 | static struct irq_chip amd_ir_chip = { |
4014 | .irq_ack = ir_ack_apic_edge, | 4344 | .irq_ack = ir_ack_apic_edge, |
4015 | .irq_set_affinity = amd_ir_set_affinity, | 4345 | .irq_set_affinity = amd_ir_set_affinity, |
4346 | .irq_set_vcpu_affinity = amd_ir_set_vcpu_affinity, | ||
4016 | .irq_compose_msi_msg = ir_compose_msi_msg, | 4347 | .irq_compose_msi_msg = ir_compose_msi_msg, |
4017 | }; | 4348 | }; |
4018 | 4349 | ||
@@ -4027,4 +4358,43 @@ int amd_iommu_create_irq_domain(struct amd_iommu *iommu) | |||
4027 | 4358 | ||
4028 | return 0; | 4359 | return 0; |
4029 | } | 4360 | } |
4361 | |||
4362 | int amd_iommu_update_ga(int cpu, bool is_run, void *data) | ||
4363 | { | ||
4364 | unsigned long flags; | ||
4365 | struct amd_iommu *iommu; | ||
4366 | struct irq_remap_table *irt; | ||
4367 | struct amd_ir_data *ir_data = (struct amd_ir_data *)data; | ||
4368 | int devid = ir_data->irq_2_irte.devid; | ||
4369 | struct irte_ga *entry = (struct irte_ga *) ir_data->entry; | ||
4370 | struct irte_ga *ref = (struct irte_ga *) ir_data->ref; | ||
4371 | |||
4372 | if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) || | ||
4373 | !ref || !entry || !entry->lo.fields_vapic.guest_mode) | ||
4374 | return 0; | ||
4375 | |||
4376 | iommu = amd_iommu_rlookup_table[devid]; | ||
4377 | if (!iommu) | ||
4378 | return -ENODEV; | ||
4379 | |||
4380 | irt = get_irq_table(devid, false); | ||
4381 | if (!irt) | ||
4382 | return -ENODEV; | ||
4383 | |||
4384 | spin_lock_irqsave(&irt->lock, flags); | ||
4385 | |||
4386 | if (ref->lo.fields_vapic.guest_mode) { | ||
4387 | if (cpu >= 0) | ||
4388 | ref->lo.fields_vapic.destination = cpu; | ||
4389 | ref->lo.fields_vapic.is_run = is_run; | ||
4390 | barrier(); | ||
4391 | } | ||
4392 | |||
4393 | spin_unlock_irqrestore(&irt->lock, flags); | ||
4394 | |||
4395 | iommu_flush_irt(iommu, devid); | ||
4396 | iommu_completion_wait(iommu); | ||
4397 | return 0; | ||
4398 | } | ||
4399 | EXPORT_SYMBOL(amd_iommu_update_ga); | ||
4030 | #endif | 4400 | #endif |
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 59741ead7e15..cd1713631a4a 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c | |||
@@ -84,6 +84,7 @@ | |||
84 | #define ACPI_DEVFLAG_LINT1 0x80 | 84 | #define ACPI_DEVFLAG_LINT1 0x80 |
85 | #define ACPI_DEVFLAG_ATSDIS 0x10000000 | 85 | #define ACPI_DEVFLAG_ATSDIS 0x10000000 |
86 | 86 | ||
87 | #define LOOP_TIMEOUT 100000 | ||
87 | /* | 88 | /* |
88 | * ACPI table definitions | 89 | * ACPI table definitions |
89 | * | 90 | * |
@@ -145,6 +146,8 @@ struct ivmd_header { | |||
145 | bool amd_iommu_dump; | 146 | bool amd_iommu_dump; |
146 | bool amd_iommu_irq_remap __read_mostly; | 147 | bool amd_iommu_irq_remap __read_mostly; |
147 | 148 | ||
149 | int amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC; | ||
150 | |||
148 | static bool amd_iommu_detected; | 151 | static bool amd_iommu_detected; |
149 | static bool __initdata amd_iommu_disabled; | 152 | static bool __initdata amd_iommu_disabled; |
150 | static int amd_iommu_target_ivhd_type; | 153 | static int amd_iommu_target_ivhd_type; |
@@ -386,6 +389,10 @@ static void iommu_disable(struct amd_iommu *iommu) | |||
386 | iommu_feature_disable(iommu, CONTROL_EVT_INT_EN); | 389 | iommu_feature_disable(iommu, CONTROL_EVT_INT_EN); |
387 | iommu_feature_disable(iommu, CONTROL_EVT_LOG_EN); | 390 | iommu_feature_disable(iommu, CONTROL_EVT_LOG_EN); |
388 | 391 | ||
392 | /* Disable IOMMU GA_LOG */ | ||
393 | iommu_feature_disable(iommu, CONTROL_GALOG_EN); | ||
394 | iommu_feature_disable(iommu, CONTROL_GAINT_EN); | ||
395 | |||
389 | /* Disable IOMMU hardware itself */ | 396 | /* Disable IOMMU hardware itself */ |
390 | iommu_feature_disable(iommu, CONTROL_IOMMU_EN); | 397 | iommu_feature_disable(iommu, CONTROL_IOMMU_EN); |
391 | } | 398 | } |
@@ -671,6 +678,99 @@ static void __init free_ppr_log(struct amd_iommu *iommu) | |||
671 | free_pages((unsigned long)iommu->ppr_log, get_order(PPR_LOG_SIZE)); | 678 | free_pages((unsigned long)iommu->ppr_log, get_order(PPR_LOG_SIZE)); |
672 | } | 679 | } |
673 | 680 | ||
681 | static void free_ga_log(struct amd_iommu *iommu) | ||
682 | { | ||
683 | #ifdef CONFIG_IRQ_REMAP | ||
684 | if (iommu->ga_log) | ||
685 | free_pages((unsigned long)iommu->ga_log, | ||
686 | get_order(GA_LOG_SIZE)); | ||
687 | if (iommu->ga_log_tail) | ||
688 | free_pages((unsigned long)iommu->ga_log_tail, | ||
689 | get_order(8)); | ||
690 | #endif | ||
691 | } | ||
692 | |||
693 | static int iommu_ga_log_enable(struct amd_iommu *iommu) | ||
694 | { | ||
695 | #ifdef CONFIG_IRQ_REMAP | ||
696 | u32 status, i; | ||
697 | |||
698 | if (!iommu->ga_log) | ||
699 | return -EINVAL; | ||
700 | |||
701 | status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); | ||
702 | |||
703 | /* Check if already running */ | ||
704 | if (status & (MMIO_STATUS_GALOG_RUN_MASK)) | ||
705 | return 0; | ||
706 | |||
707 | iommu_feature_enable(iommu, CONTROL_GAINT_EN); | ||
708 | iommu_feature_enable(iommu, CONTROL_GALOG_EN); | ||
709 | |||
710 | for (i = 0; i < LOOP_TIMEOUT; ++i) { | ||
711 | status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); | ||
712 | if (status & (MMIO_STATUS_GALOG_RUN_MASK)) | ||
713 | break; | ||
714 | } | ||
715 | |||
716 | if (i >= LOOP_TIMEOUT) | ||
717 | return -EINVAL; | ||
718 | #endif /* CONFIG_IRQ_REMAP */ | ||
719 | return 0; | ||
720 | } | ||
721 | |||
722 | #ifdef CONFIG_IRQ_REMAP | ||
723 | static int iommu_init_ga_log(struct amd_iommu *iommu) | ||
724 | { | ||
725 | u64 entry; | ||
726 | |||
727 | if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir)) | ||
728 | return 0; | ||
729 | |||
730 | iommu->ga_log = (u8 *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, | ||
731 | get_order(GA_LOG_SIZE)); | ||
732 | if (!iommu->ga_log) | ||
733 | goto err_out; | ||
734 | |||
735 | iommu->ga_log_tail = (u8 *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, | ||
736 | get_order(8)); | ||
737 | if (!iommu->ga_log_tail) | ||
738 | goto err_out; | ||
739 | |||
740 | entry = (u64)virt_to_phys(iommu->ga_log) | GA_LOG_SIZE_512; | ||
741 | memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_BASE_OFFSET, | ||
742 | &entry, sizeof(entry)); | ||
743 | entry = ((u64)virt_to_phys(iommu->ga_log) & 0xFFFFFFFFFFFFFULL) & ~7ULL; | ||
744 | memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_TAIL_OFFSET, | ||
745 | &entry, sizeof(entry)); | ||
746 | writel(0x00, iommu->mmio_base + MMIO_GA_HEAD_OFFSET); | ||
747 | writel(0x00, iommu->mmio_base + MMIO_GA_TAIL_OFFSET); | ||
748 | |||
749 | return 0; | ||
750 | err_out: | ||
751 | free_ga_log(iommu); | ||
752 | return -EINVAL; | ||
753 | } | ||
754 | #endif /* CONFIG_IRQ_REMAP */ | ||
755 | |||
756 | static int iommu_init_ga(struct amd_iommu *iommu) | ||
757 | { | ||
758 | int ret = 0; | ||
759 | |||
760 | #ifdef CONFIG_IRQ_REMAP | ||
761 | /* Note: We have already checked GASup from IVRS table. | ||
762 | * Now, we need to make sure that GAMSup is set. | ||
763 | */ | ||
764 | if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) && | ||
765 | !iommu_feature(iommu, FEATURE_GAM_VAPIC)) | ||
766 | amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY_GA; | ||
767 | |||
768 | ret = iommu_init_ga_log(iommu); | ||
769 | #endif /* CONFIG_IRQ_REMAP */ | ||
770 | |||
771 | return ret; | ||
772 | } | ||
773 | |||
674 | static void iommu_enable_gt(struct amd_iommu *iommu) | 774 | static void iommu_enable_gt(struct amd_iommu *iommu) |
675 | { | 775 | { |
676 | if (!iommu_feature(iommu, FEATURE_GT)) | 776 | if (!iommu_feature(iommu, FEATURE_GT)) |
@@ -1144,6 +1244,7 @@ static void __init free_iommu_one(struct amd_iommu *iommu) | |||
1144 | free_command_buffer(iommu); | 1244 | free_command_buffer(iommu); |
1145 | free_event_buffer(iommu); | 1245 | free_event_buffer(iommu); |
1146 | free_ppr_log(iommu); | 1246 | free_ppr_log(iommu); |
1247 | free_ga_log(iommu); | ||
1147 | iommu_unmap_mmio_space(iommu); | 1248 | iommu_unmap_mmio_space(iommu); |
1148 | } | 1249 | } |
1149 | 1250 | ||
@@ -1258,6 +1359,8 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) | |||
1258 | iommu->mmio_phys_end = MMIO_REG_END_OFFSET; | 1359 | iommu->mmio_phys_end = MMIO_REG_END_OFFSET; |
1259 | else | 1360 | else |
1260 | iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET; | 1361 | iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET; |
1362 | if (((h->efr_attr & (0x1 << IOMMU_FEAT_GASUP_SHIFT)) == 0)) | ||
1363 | amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY; | ||
1261 | break; | 1364 | break; |
1262 | case 0x11: | 1365 | case 0x11: |
1263 | case 0x40: | 1366 | case 0x40: |
@@ -1265,6 +1368,8 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) | |||
1265 | iommu->mmio_phys_end = MMIO_REG_END_OFFSET; | 1368 | iommu->mmio_phys_end = MMIO_REG_END_OFFSET; |
1266 | else | 1369 | else |
1267 | iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET; | 1370 | iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET; |
1371 | if (((h->efr_reg & (0x1 << IOMMU_EFR_GASUP_SHIFT)) == 0)) | ||
1372 | amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY; | ||
1268 | break; | 1373 | break; |
1269 | default: | 1374 | default: |
1270 | return -EINVAL; | 1375 | return -EINVAL; |
@@ -1432,6 +1537,7 @@ static int iommu_init_pci(struct amd_iommu *iommu) | |||
1432 | { | 1537 | { |
1433 | int cap_ptr = iommu->cap_ptr; | 1538 | int cap_ptr = iommu->cap_ptr; |
1434 | u32 range, misc, low, high; | 1539 | u32 range, misc, low, high; |
1540 | int ret; | ||
1435 | 1541 | ||
1436 | iommu->dev = pci_get_bus_and_slot(PCI_BUS_NUM(iommu->devid), | 1542 | iommu->dev = pci_get_bus_and_slot(PCI_BUS_NUM(iommu->devid), |
1437 | iommu->devid & 0xff); | 1543 | iommu->devid & 0xff); |
@@ -1488,6 +1594,10 @@ static int iommu_init_pci(struct amd_iommu *iommu) | |||
1488 | if (iommu_feature(iommu, FEATURE_PPR) && alloc_ppr_log(iommu)) | 1594 | if (iommu_feature(iommu, FEATURE_PPR) && alloc_ppr_log(iommu)) |
1489 | return -ENOMEM; | 1595 | return -ENOMEM; |
1490 | 1596 | ||
1597 | ret = iommu_init_ga(iommu); | ||
1598 | if (ret) | ||
1599 | return ret; | ||
1600 | |||
1491 | if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE)) | 1601 | if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE)) |
1492 | amd_iommu_np_cache = true; | 1602 | amd_iommu_np_cache = true; |
1493 | 1603 | ||
@@ -1545,16 +1655,24 @@ static void print_iommu_info(void) | |||
1545 | dev_name(&iommu->dev->dev), iommu->cap_ptr); | 1655 | dev_name(&iommu->dev->dev), iommu->cap_ptr); |
1546 | 1656 | ||
1547 | if (iommu->cap & (1 << IOMMU_CAP_EFR)) { | 1657 | if (iommu->cap & (1 << IOMMU_CAP_EFR)) { |
1548 | pr_info("AMD-Vi: Extended features: "); | 1658 | pr_info("AMD-Vi: Extended features (%#llx):\n", |
1659 | iommu->features); | ||
1549 | for (i = 0; i < ARRAY_SIZE(feat_str); ++i) { | 1660 | for (i = 0; i < ARRAY_SIZE(feat_str); ++i) { |
1550 | if (iommu_feature(iommu, (1ULL << i))) | 1661 | if (iommu_feature(iommu, (1ULL << i))) |
1551 | pr_cont(" %s", feat_str[i]); | 1662 | pr_cont(" %s", feat_str[i]); |
1552 | } | 1663 | } |
1664 | |||
1665 | if (iommu->features & FEATURE_GAM_VAPIC) | ||
1666 | pr_cont(" GA_vAPIC"); | ||
1667 | |||
1553 | pr_cont("\n"); | 1668 | pr_cont("\n"); |
1554 | } | 1669 | } |
1555 | } | 1670 | } |
1556 | if (irq_remapping_enabled) | 1671 | if (irq_remapping_enabled) { |
1557 | pr_info("AMD-Vi: Interrupt remapping enabled\n"); | 1672 | pr_info("AMD-Vi: Interrupt remapping enabled\n"); |
1673 | if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir)) | ||
1674 | pr_info("AMD-Vi: virtual APIC enabled\n"); | ||
1675 | } | ||
1558 | } | 1676 | } |
1559 | 1677 | ||
1560 | static int __init amd_iommu_init_pci(void) | 1678 | static int __init amd_iommu_init_pci(void) |
@@ -1645,6 +1763,8 @@ enable_faults: | |||
1645 | if (iommu->ppr_log != NULL) | 1763 | if (iommu->ppr_log != NULL) |
1646 | iommu_feature_enable(iommu, CONTROL_PPFINT_EN); | 1764 | iommu_feature_enable(iommu, CONTROL_PPFINT_EN); |
1647 | 1765 | ||
1766 | iommu_ga_log_enable(iommu); | ||
1767 | |||
1648 | return 0; | 1768 | return 0; |
1649 | } | 1769 | } |
1650 | 1770 | ||
@@ -1862,6 +1982,24 @@ static void iommu_apply_resume_quirks(struct amd_iommu *iommu) | |||
1862 | iommu->stored_addr_lo | 1); | 1982 | iommu->stored_addr_lo | 1); |
1863 | } | 1983 | } |
1864 | 1984 | ||
1985 | static void iommu_enable_ga(struct amd_iommu *iommu) | ||
1986 | { | ||
1987 | #ifdef CONFIG_IRQ_REMAP | ||
1988 | switch (amd_iommu_guest_ir) { | ||
1989 | case AMD_IOMMU_GUEST_IR_VAPIC: | ||
1990 | iommu_feature_enable(iommu, CONTROL_GAM_EN); | ||
1991 | /* Fall through */ | ||
1992 | case AMD_IOMMU_GUEST_IR_LEGACY_GA: | ||
1993 | iommu_feature_enable(iommu, CONTROL_GA_EN); | ||
1994 | iommu->irte_ops = &irte_128_ops; | ||
1995 | break; | ||
1996 | default: | ||
1997 | iommu->irte_ops = &irte_32_ops; | ||
1998 | break; | ||
1999 | } | ||
2000 | #endif | ||
2001 | } | ||
2002 | |||
1865 | /* | 2003 | /* |
1866 | * This function finally enables all IOMMUs found in the system after | 2004 | * This function finally enables all IOMMUs found in the system after |
1867 | * they have been initialized | 2005 | * they have been initialized |
@@ -1877,9 +2015,15 @@ static void early_enable_iommus(void) | |||
1877 | iommu_enable_command_buffer(iommu); | 2015 | iommu_enable_command_buffer(iommu); |
1878 | iommu_enable_event_buffer(iommu); | 2016 | iommu_enable_event_buffer(iommu); |
1879 | iommu_set_exclusion_range(iommu); | 2017 | iommu_set_exclusion_range(iommu); |
2018 | iommu_enable_ga(iommu); | ||
1880 | iommu_enable(iommu); | 2019 | iommu_enable(iommu); |
1881 | iommu_flush_all_caches(iommu); | 2020 | iommu_flush_all_caches(iommu); |
1882 | } | 2021 | } |
2022 | |||
2023 | #ifdef CONFIG_IRQ_REMAP | ||
2024 | if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir)) | ||
2025 | amd_iommu_irq_ops.capability |= (1 << IRQ_POSTING_CAP); | ||
2026 | #endif | ||
1883 | } | 2027 | } |
1884 | 2028 | ||
1885 | static void enable_iommus_v2(void) | 2029 | static void enable_iommus_v2(void) |
@@ -1905,6 +2049,11 @@ static void disable_iommus(void) | |||
1905 | 2049 | ||
1906 | for_each_iommu(iommu) | 2050 | for_each_iommu(iommu) |
1907 | iommu_disable(iommu); | 2051 | iommu_disable(iommu); |
2052 | |||
2053 | #ifdef CONFIG_IRQ_REMAP | ||
2054 | if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir)) | ||
2055 | amd_iommu_irq_ops.capability &= ~(1 << IRQ_POSTING_CAP); | ||
2056 | #endif | ||
1908 | } | 2057 | } |
1909 | 2058 | ||
1910 | /* | 2059 | /* |
@@ -2059,7 +2208,7 @@ static int __init early_amd_iommu_init(void) | |||
2059 | struct acpi_table_header *ivrs_base; | 2208 | struct acpi_table_header *ivrs_base; |
2060 | acpi_size ivrs_size; | 2209 | acpi_size ivrs_size; |
2061 | acpi_status status; | 2210 | acpi_status status; |
2062 | int i, ret = 0; | 2211 | int i, remap_cache_sz, ret = 0; |
2063 | 2212 | ||
2064 | if (!amd_iommu_detected) | 2213 | if (!amd_iommu_detected) |
2065 | return -ENODEV; | 2214 | return -ENODEV; |
@@ -2157,10 +2306,14 @@ static int __init early_amd_iommu_init(void) | |||
2157 | * remapping tables. | 2306 | * remapping tables. |
2158 | */ | 2307 | */ |
2159 | ret = -ENOMEM; | 2308 | ret = -ENOMEM; |
2309 | if (!AMD_IOMMU_GUEST_IR_GA(amd_iommu_guest_ir)) | ||
2310 | remap_cache_sz = MAX_IRQS_PER_TABLE * sizeof(u32); | ||
2311 | else | ||
2312 | remap_cache_sz = MAX_IRQS_PER_TABLE * (sizeof(u64) * 2); | ||
2160 | amd_iommu_irq_cache = kmem_cache_create("irq_remap_cache", | 2313 | amd_iommu_irq_cache = kmem_cache_create("irq_remap_cache", |
2161 | MAX_IRQS_PER_TABLE * sizeof(u32), | 2314 | remap_cache_sz, |
2162 | IRQ_TABLE_ALIGNMENT, | 2315 | IRQ_TABLE_ALIGNMENT, |
2163 | 0, NULL); | 2316 | 0, NULL); |
2164 | if (!amd_iommu_irq_cache) | 2317 | if (!amd_iommu_irq_cache) |
2165 | goto out; | 2318 | goto out; |
2166 | 2319 | ||
@@ -2413,6 +2566,21 @@ static int __init parse_amd_iommu_dump(char *str) | |||
2413 | return 1; | 2566 | return 1; |
2414 | } | 2567 | } |
2415 | 2568 | ||
2569 | static int __init parse_amd_iommu_intr(char *str) | ||
2570 | { | ||
2571 | for (; *str; ++str) { | ||
2572 | if (strncmp(str, "legacy", 6) == 0) { | ||
2573 | amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY; | ||
2574 | break; | ||
2575 | } | ||
2576 | if (strncmp(str, "vapic", 5) == 0) { | ||
2577 | amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC; | ||
2578 | break; | ||
2579 | } | ||
2580 | } | ||
2581 | return 1; | ||
2582 | } | ||
2583 | |||
2416 | static int __init parse_amd_iommu_options(char *str) | 2584 | static int __init parse_amd_iommu_options(char *str) |
2417 | { | 2585 | { |
2418 | for (; *str; ++str) { | 2586 | for (; *str; ++str) { |
@@ -2521,6 +2689,7 @@ static int __init parse_ivrs_acpihid(char *str) | |||
2521 | 2689 | ||
2522 | __setup("amd_iommu_dump", parse_amd_iommu_dump); | 2690 | __setup("amd_iommu_dump", parse_amd_iommu_dump); |
2523 | __setup("amd_iommu=", parse_amd_iommu_options); | 2691 | __setup("amd_iommu=", parse_amd_iommu_options); |
2692 | __setup("amd_iommu_intr=", parse_amd_iommu_intr); | ||
2524 | __setup("ivrs_ioapic", parse_ivrs_ioapic); | 2693 | __setup("ivrs_ioapic", parse_ivrs_ioapic); |
2525 | __setup("ivrs_hpet", parse_ivrs_hpet); | 2694 | __setup("ivrs_hpet", parse_ivrs_hpet); |
2526 | __setup("ivrs_acpihid", parse_ivrs_acpihid); | 2695 | __setup("ivrs_acpihid", parse_ivrs_acpihid); |
diff --git a/drivers/iommu/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h index a1f3346736e5..7eb60c15c582 100644 --- a/drivers/iommu/amd_iommu_proto.h +++ b/drivers/iommu/amd_iommu_proto.h | |||
@@ -38,6 +38,7 @@ extern int amd_iommu_enable(void); | |||
38 | extern void amd_iommu_disable(void); | 38 | extern void amd_iommu_disable(void); |
39 | extern int amd_iommu_reenable(int); | 39 | extern int amd_iommu_reenable(int); |
40 | extern int amd_iommu_enable_faulting(void); | 40 | extern int amd_iommu_enable_faulting(void); |
41 | extern int amd_iommu_guest_ir; | ||
41 | 42 | ||
42 | /* IOMMUv2 specific functions */ | 43 | /* IOMMUv2 specific functions */ |
43 | struct iommu_domain; | 44 | struct iommu_domain; |
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index caf5e3822715..fa766eefd590 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <linux/mutex.h> | 24 | #include <linux/mutex.h> |
25 | #include <linux/msi.h> | ||
25 | #include <linux/list.h> | 26 | #include <linux/list.h> |
26 | #include <linux/spinlock.h> | 27 | #include <linux/spinlock.h> |
27 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
@@ -69,6 +70,8 @@ | |||
69 | #define MMIO_EXCL_LIMIT_OFFSET 0x0028 | 70 | #define MMIO_EXCL_LIMIT_OFFSET 0x0028 |
70 | #define MMIO_EXT_FEATURES 0x0030 | 71 | #define MMIO_EXT_FEATURES 0x0030 |
71 | #define MMIO_PPR_LOG_OFFSET 0x0038 | 72 | #define MMIO_PPR_LOG_OFFSET 0x0038 |
73 | #define MMIO_GA_LOG_BASE_OFFSET 0x00e0 | ||
74 | #define MMIO_GA_LOG_TAIL_OFFSET 0x00e8 | ||
72 | #define MMIO_CMD_HEAD_OFFSET 0x2000 | 75 | #define MMIO_CMD_HEAD_OFFSET 0x2000 |
73 | #define MMIO_CMD_TAIL_OFFSET 0x2008 | 76 | #define MMIO_CMD_TAIL_OFFSET 0x2008 |
74 | #define MMIO_EVT_HEAD_OFFSET 0x2010 | 77 | #define MMIO_EVT_HEAD_OFFSET 0x2010 |
@@ -76,6 +79,8 @@ | |||
76 | #define MMIO_STATUS_OFFSET 0x2020 | 79 | #define MMIO_STATUS_OFFSET 0x2020 |
77 | #define MMIO_PPR_HEAD_OFFSET 0x2030 | 80 | #define MMIO_PPR_HEAD_OFFSET 0x2030 |
78 | #define MMIO_PPR_TAIL_OFFSET 0x2038 | 81 | #define MMIO_PPR_TAIL_OFFSET 0x2038 |
82 | #define MMIO_GA_HEAD_OFFSET 0x2040 | ||
83 | #define MMIO_GA_TAIL_OFFSET 0x2048 | ||
79 | #define MMIO_CNTR_CONF_OFFSET 0x4000 | 84 | #define MMIO_CNTR_CONF_OFFSET 0x4000 |
80 | #define MMIO_CNTR_REG_OFFSET 0x40000 | 85 | #define MMIO_CNTR_REG_OFFSET 0x40000 |
81 | #define MMIO_REG_END_OFFSET 0x80000 | 86 | #define MMIO_REG_END_OFFSET 0x80000 |
@@ -92,6 +97,7 @@ | |||
92 | #define FEATURE_GA (1ULL<<7) | 97 | #define FEATURE_GA (1ULL<<7) |
93 | #define FEATURE_HE (1ULL<<8) | 98 | #define FEATURE_HE (1ULL<<8) |
94 | #define FEATURE_PC (1ULL<<9) | 99 | #define FEATURE_PC (1ULL<<9) |
100 | #define FEATURE_GAM_VAPIC (1ULL<<21) | ||
95 | 101 | ||
96 | #define FEATURE_PASID_SHIFT 32 | 102 | #define FEATURE_PASID_SHIFT 32 |
97 | #define FEATURE_PASID_MASK (0x1fULL << FEATURE_PASID_SHIFT) | 103 | #define FEATURE_PASID_MASK (0x1fULL << FEATURE_PASID_SHIFT) |
@@ -110,6 +116,9 @@ | |||
110 | #define MMIO_STATUS_EVT_INT_MASK (1 << 1) | 116 | #define MMIO_STATUS_EVT_INT_MASK (1 << 1) |
111 | #define MMIO_STATUS_COM_WAIT_INT_MASK (1 << 2) | 117 | #define MMIO_STATUS_COM_WAIT_INT_MASK (1 << 2) |
112 | #define MMIO_STATUS_PPR_INT_MASK (1 << 6) | 118 | #define MMIO_STATUS_PPR_INT_MASK (1 << 6) |
119 | #define MMIO_STATUS_GALOG_RUN_MASK (1 << 8) | ||
120 | #define MMIO_STATUS_GALOG_OVERFLOW_MASK (1 << 9) | ||
121 | #define MMIO_STATUS_GALOG_INT_MASK (1 << 10) | ||
113 | 122 | ||
114 | /* event logging constants */ | 123 | /* event logging constants */ |
115 | #define EVENT_ENTRY_SIZE 0x10 | 124 | #define EVENT_ENTRY_SIZE 0x10 |
@@ -146,6 +155,10 @@ | |||
146 | #define CONTROL_PPFINT_EN 0x0eULL | 155 | #define CONTROL_PPFINT_EN 0x0eULL |
147 | #define CONTROL_PPR_EN 0x0fULL | 156 | #define CONTROL_PPR_EN 0x0fULL |
148 | #define CONTROL_GT_EN 0x10ULL | 157 | #define CONTROL_GT_EN 0x10ULL |
158 | #define CONTROL_GA_EN 0x11ULL | ||
159 | #define CONTROL_GAM_EN 0x19ULL | ||
160 | #define CONTROL_GALOG_EN 0x1CULL | ||
161 | #define CONTROL_GAINT_EN 0x1DULL | ||
149 | 162 | ||
150 | #define CTRL_INV_TO_MASK (7 << CONTROL_INV_TIMEOUT) | 163 | #define CTRL_INV_TO_MASK (7 << CONTROL_INV_TIMEOUT) |
151 | #define CTRL_INV_TO_NONE 0 | 164 | #define CTRL_INV_TO_NONE 0 |
@@ -224,6 +237,19 @@ | |||
224 | 237 | ||
225 | #define PPR_REQ_FAULT 0x01 | 238 | #define PPR_REQ_FAULT 0x01 |
226 | 239 | ||
240 | /* Constants for GA Log handling */ | ||
241 | #define GA_LOG_ENTRIES 512 | ||
242 | #define GA_LOG_SIZE_SHIFT 56 | ||
243 | #define GA_LOG_SIZE_512 (0x8ULL << GA_LOG_SIZE_SHIFT) | ||
244 | #define GA_ENTRY_SIZE 8 | ||
245 | #define GA_LOG_SIZE (GA_ENTRY_SIZE * GA_LOG_ENTRIES) | ||
246 | |||
247 | #define GA_TAG(x) (u32)(x & 0xffffffffULL) | ||
248 | #define GA_DEVID(x) (u16)(((x) >> 32) & 0xffffULL) | ||
249 | #define GA_REQ_TYPE(x) (((x) >> 60) & 0xfULL) | ||
250 | |||
251 | #define GA_GUEST_NR 0x1 | ||
252 | |||
227 | #define PAGE_MODE_NONE 0x00 | 253 | #define PAGE_MODE_NONE 0x00 |
228 | #define PAGE_MODE_1_LEVEL 0x01 | 254 | #define PAGE_MODE_1_LEVEL 0x01 |
229 | #define PAGE_MODE_2_LEVEL 0x02 | 255 | #define PAGE_MODE_2_LEVEL 0x02 |
@@ -329,6 +355,12 @@ | |||
329 | #define IOMMU_CAP_NPCACHE 26 | 355 | #define IOMMU_CAP_NPCACHE 26 |
330 | #define IOMMU_CAP_EFR 27 | 356 | #define IOMMU_CAP_EFR 27 |
331 | 357 | ||
358 | /* IOMMU Feature Reporting Field (for IVHD type 10h */ | ||
359 | #define IOMMU_FEAT_GASUP_SHIFT 6 | ||
360 | |||
361 | /* IOMMU Extended Feature Register (EFR) */ | ||
362 | #define IOMMU_EFR_GASUP_SHIFT 7 | ||
363 | |||
332 | #define MAX_DOMAIN_ID 65536 | 364 | #define MAX_DOMAIN_ID 65536 |
333 | 365 | ||
334 | /* Protection domain flags */ | 366 | /* Protection domain flags */ |
@@ -400,6 +432,7 @@ struct amd_iommu_fault { | |||
400 | 432 | ||
401 | struct iommu_domain; | 433 | struct iommu_domain; |
402 | struct irq_domain; | 434 | struct irq_domain; |
435 | struct amd_irte_ops; | ||
403 | 436 | ||
404 | /* | 437 | /* |
405 | * This structure contains generic data for IOMMU protection domains | 438 | * This structure contains generic data for IOMMU protection domains |
@@ -490,6 +523,12 @@ struct amd_iommu { | |||
490 | /* Base of the PPR log, if present */ | 523 | /* Base of the PPR log, if present */ |
491 | u8 *ppr_log; | 524 | u8 *ppr_log; |
492 | 525 | ||
526 | /* Base of the GA log, if present */ | ||
527 | u8 *ga_log; | ||
528 | |||
529 | /* Tail of the GA log, if present */ | ||
530 | u8 *ga_log_tail; | ||
531 | |||
493 | /* true if interrupts for this IOMMU are already enabled */ | 532 | /* true if interrupts for this IOMMU are already enabled */ |
494 | bool int_enabled; | 533 | bool int_enabled; |
495 | 534 | ||
@@ -523,6 +562,8 @@ struct amd_iommu { | |||
523 | #ifdef CONFIG_IRQ_REMAP | 562 | #ifdef CONFIG_IRQ_REMAP |
524 | struct irq_domain *ir_domain; | 563 | struct irq_domain *ir_domain; |
525 | struct irq_domain *msi_domain; | 564 | struct irq_domain *msi_domain; |
565 | |||
566 | struct amd_irte_ops *irte_ops; | ||
526 | #endif | 567 | #endif |
527 | }; | 568 | }; |
528 | 569 | ||
@@ -681,4 +722,112 @@ static inline int get_hpet_devid(int id) | |||
681 | return -EINVAL; | 722 | return -EINVAL; |
682 | } | 723 | } |
683 | 724 | ||
725 | enum amd_iommu_intr_mode_type { | ||
726 | AMD_IOMMU_GUEST_IR_LEGACY, | ||
727 | |||
728 | /* This mode is not visible to users. It is used when | ||
729 | * we cannot fully enable vAPIC and fallback to only support | ||
730 | * legacy interrupt remapping via 128-bit IRTE. | ||
731 | */ | ||
732 | AMD_IOMMU_GUEST_IR_LEGACY_GA, | ||
733 | AMD_IOMMU_GUEST_IR_VAPIC, | ||
734 | }; | ||
735 | |||
736 | #define AMD_IOMMU_GUEST_IR_GA(x) (x == AMD_IOMMU_GUEST_IR_VAPIC || \ | ||
737 | x == AMD_IOMMU_GUEST_IR_LEGACY_GA) | ||
738 | |||
739 | #define AMD_IOMMU_GUEST_IR_VAPIC(x) (x == AMD_IOMMU_GUEST_IR_VAPIC) | ||
740 | |||
741 | union irte { | ||
742 | u32 val; | ||
743 | struct { | ||
744 | u32 valid : 1, | ||
745 | no_fault : 1, | ||
746 | int_type : 3, | ||
747 | rq_eoi : 1, | ||
748 | dm : 1, | ||
749 | rsvd_1 : 1, | ||
750 | destination : 8, | ||
751 | vector : 8, | ||
752 | rsvd_2 : 8; | ||
753 | } fields; | ||
754 | }; | ||
755 | |||
756 | union irte_ga_lo { | ||
757 | u64 val; | ||
758 | |||
759 | /* For int remapping */ | ||
760 | struct { | ||
761 | u64 valid : 1, | ||
762 | no_fault : 1, | ||
763 | /* ------ */ | ||
764 | int_type : 3, | ||
765 | rq_eoi : 1, | ||
766 | dm : 1, | ||
767 | /* ------ */ | ||
768 | guest_mode : 1, | ||
769 | destination : 8, | ||
770 | rsvd : 48; | ||
771 | } fields_remap; | ||
772 | |||
773 | /* For guest vAPIC */ | ||
774 | struct { | ||
775 | u64 valid : 1, | ||
776 | no_fault : 1, | ||
777 | /* ------ */ | ||
778 | ga_log_intr : 1, | ||
779 | rsvd1 : 3, | ||
780 | is_run : 1, | ||
781 | /* ------ */ | ||
782 | guest_mode : 1, | ||
783 | destination : 8, | ||
784 | rsvd2 : 16, | ||
785 | ga_tag : 32; | ||
786 | } fields_vapic; | ||
787 | }; | ||
788 | |||
789 | union irte_ga_hi { | ||
790 | u64 val; | ||
791 | struct { | ||
792 | u64 vector : 8, | ||
793 | rsvd_1 : 4, | ||
794 | ga_root_ptr : 40, | ||
795 | rsvd_2 : 12; | ||
796 | } fields; | ||
797 | }; | ||
798 | |||
799 | struct irte_ga { | ||
800 | union irte_ga_lo lo; | ||
801 | union irte_ga_hi hi; | ||
802 | }; | ||
803 | |||
804 | struct irq_2_irte { | ||
805 | u16 devid; /* Device ID for IRTE table */ | ||
806 | u16 index; /* Index into IRTE table*/ | ||
807 | }; | ||
808 | |||
809 | struct amd_ir_data { | ||
810 | u32 cached_ga_tag; | ||
811 | struct irq_2_irte irq_2_irte; | ||
812 | struct msi_msg msi_entry; | ||
813 | void *entry; /* Pointer to union irte or struct irte_ga */ | ||
814 | void *ref; /* Pointer to the actual irte */ | ||
815 | }; | ||
816 | |||
817 | struct amd_irte_ops { | ||
818 | void (*prepare)(void *, u32, u32, u8, u32, int); | ||
819 | void (*activate)(void *, u16, u16); | ||
820 | void (*deactivate)(void *, u16, u16); | ||
821 | void (*set_affinity)(void *, u16, u16, u8, u32); | ||
822 | void *(*get)(struct irq_remap_table *, int); | ||
823 | void (*set_allocated)(struct irq_remap_table *, int); | ||
824 | bool (*is_allocated)(struct irq_remap_table *, int); | ||
825 | void (*clear_allocated)(struct irq_remap_table *, int); | ||
826 | }; | ||
827 | |||
828 | #ifdef CONFIG_IRQ_REMAP | ||
829 | extern struct amd_irte_ops irte_32_ops; | ||
830 | extern struct amd_irte_ops irte_128_ops; | ||
831 | #endif | ||
832 | |||
684 | #endif /* _ASM_X86_AMD_IOMMU_TYPES_H */ | 833 | #endif /* _ASM_X86_AMD_IOMMU_TYPES_H */ |
diff --git a/include/linux/amd-iommu.h b/include/linux/amd-iommu.h index 2b08e79f5100..09751d349963 100644 --- a/include/linux/amd-iommu.h +++ b/include/linux/amd-iommu.h | |||
@@ -22,6 +22,20 @@ | |||
22 | 22 | ||
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | 24 | ||
25 | /* | ||
26 | * This is mainly used to communicate information back-and-forth | ||
27 | * between SVM and IOMMU for setting up and tearing down posted | ||
28 | * interrupt | ||
29 | */ | ||
30 | struct amd_iommu_pi_data { | ||
31 | u32 ga_tag; | ||
32 | u32 prev_ga_tag; | ||
33 | u64 base; | ||
34 | bool is_guest_mode; | ||
35 | struct vcpu_data *vcpu_data; | ||
36 | void *ir_data; | ||
37 | }; | ||
38 | |||
25 | #ifdef CONFIG_AMD_IOMMU | 39 | #ifdef CONFIG_AMD_IOMMU |
26 | 40 | ||
27 | struct task_struct; | 41 | struct task_struct; |
@@ -168,11 +182,34 @@ typedef void (*amd_iommu_invalidate_ctx)(struct pci_dev *pdev, int pasid); | |||
168 | 182 | ||
169 | extern int amd_iommu_set_invalidate_ctx_cb(struct pci_dev *pdev, | 183 | extern int amd_iommu_set_invalidate_ctx_cb(struct pci_dev *pdev, |
170 | amd_iommu_invalidate_ctx cb); | 184 | amd_iommu_invalidate_ctx cb); |
171 | 185 | #else /* CONFIG_AMD_IOMMU */ | |
172 | #else | ||
173 | 186 | ||
174 | static inline int amd_iommu_detect(void) { return -ENODEV; } | 187 | static inline int amd_iommu_detect(void) { return -ENODEV; } |
175 | 188 | ||
176 | #endif | 189 | #endif /* CONFIG_AMD_IOMMU */ |
190 | |||
191 | #if defined(CONFIG_AMD_IOMMU) && defined(CONFIG_IRQ_REMAP) | ||
192 | |||
193 | /* IOMMU AVIC Function */ | ||
194 | extern int amd_iommu_register_ga_log_notifier(int (*notifier)(u32)); | ||
195 | |||
196 | extern int | ||
197 | amd_iommu_update_ga(int cpu, bool is_run, void *data); | ||
198 | |||
199 | #else /* defined(CONFIG_AMD_IOMMU) && defined(CONFIG_IRQ_REMAP) */ | ||
200 | |||
201 | static inline int | ||
202 | amd_iommu_register_ga_log_notifier(int (*notifier)(u32)) | ||
203 | { | ||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | static inline int | ||
208 | amd_iommu_update_ga(int cpu, bool is_run, void *data) | ||
209 | { | ||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | #endif /* defined(CONFIG_AMD_IOMMU) && defined(CONFIG_IRQ_REMAP) */ | ||
177 | 214 | ||
178 | #endif /* _ASM_X86_AMD_IOMMU_H */ | 215 | #endif /* _ASM_X86_AMD_IOMMU_H */ |