diff options
author | Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> | 2016-08-23 14:52:40 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2016-09-05 06:41:46 -0400 |
commit | d98de49a53e48f51332e97568127e722415e1232 (patch) | |
tree | 8f668204ee34ba5e28f884cd52ca505eff31e62a | |
parent | b9fc6b56f478b487dc8fc400da73d89ac9137201 (diff) |
iommu/amd: Enable vAPIC interrupt remapping mode by default
Introduce struct iommu_dev_data.use_vapic flag, which IOMMU driver
uses to determine if it should enable vAPIC support, by setting
the ga_mode bit in the device's interrupt remapping table entry.
Currently, it is enabled for all pass-through device if vAPIC mode
is enabled.
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r-- | drivers/iommu/amd_iommu.c | 44 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu_init.c | 12 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu_types.h | 2 |
3 files changed, 48 insertions, 10 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 69fc57e0b975..a7aa0e76eebd 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 | /* |
@@ -3015,6 +3016,12 @@ static void amd_iommu_detach_device(struct iommu_domain *dom, | |||
3015 | if (!iommu) | 3016 | if (!iommu) |
3016 | return; | 3017 | return; |
3017 | 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 | |||
3018 | iommu_completion_wait(iommu); | 3025 | iommu_completion_wait(iommu); |
3019 | } | 3026 | } |
3020 | 3027 | ||
@@ -3040,6 +3047,15 @@ static int amd_iommu_attach_device(struct iommu_domain *dom, | |||
3040 | 3047 | ||
3041 | ret = attach_device(dev, domain); | 3048 | ret = attach_device(dev, domain); |
3042 | 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 | |||
3043 | iommu_completion_wait(iommu); | 3059 | iommu_completion_wait(iommu); |
3044 | 3060 | ||
3045 | return ret; | 3061 | return ret; |
@@ -3801,7 +3817,7 @@ static void free_irte(u16 devid, int index) | |||
3801 | 3817 | ||
3802 | static void irte_prepare(void *entry, | 3818 | static void irte_prepare(void *entry, |
3803 | u32 delivery_mode, u32 dest_mode, | 3819 | u32 delivery_mode, u32 dest_mode, |
3804 | u8 vector, u32 dest_apicid) | 3820 | u8 vector, u32 dest_apicid, int devid) |
3805 | { | 3821 | { |
3806 | union irte *irte = (union irte *) entry; | 3822 | union irte *irte = (union irte *) entry; |
3807 | 3823 | ||
@@ -3815,13 +3831,14 @@ static void irte_prepare(void *entry, | |||
3815 | 3831 | ||
3816 | static void irte_ga_prepare(void *entry, | 3832 | static void irte_ga_prepare(void *entry, |
3817 | u32 delivery_mode, u32 dest_mode, | 3833 | u32 delivery_mode, u32 dest_mode, |
3818 | u8 vector, u32 dest_apicid) | 3834 | u8 vector, u32 dest_apicid, int devid) |
3819 | { | 3835 | { |
3820 | struct irte_ga *irte = (struct irte_ga *) entry; | 3836 | struct irte_ga *irte = (struct irte_ga *) entry; |
3837 | struct iommu_dev_data *dev_data = search_dev_data(devid); | ||
3821 | 3838 | ||
3822 | irte->lo.val = 0; | 3839 | irte->lo.val = 0; |
3823 | irte->hi.val = 0; | 3840 | irte->hi.val = 0; |
3824 | irte->lo.fields_remap.guest_mode = 0; | 3841 | irte->lo.fields_remap.guest_mode = dev_data ? dev_data->use_vapic : 0; |
3825 | irte->lo.fields_remap.int_type = delivery_mode; | 3842 | irte->lo.fields_remap.int_type = delivery_mode; |
3826 | irte->lo.fields_remap.dm = dest_mode; | 3843 | irte->lo.fields_remap.dm = dest_mode; |
3827 | irte->hi.fields.vector = vector; | 3844 | irte->hi.fields.vector = vector; |
@@ -3875,11 +3892,14 @@ static void irte_ga_set_affinity(void *entry, u16 devid, u16 index, | |||
3875 | u8 vector, u32 dest_apicid) | 3892 | u8 vector, u32 dest_apicid) |
3876 | { | 3893 | { |
3877 | struct irte_ga *irte = (struct irte_ga *) entry; | 3894 | struct irte_ga *irte = (struct irte_ga *) entry; |
3895 | struct iommu_dev_data *dev_data = search_dev_data(devid); | ||
3878 | 3896 | ||
3879 | irte->hi.fields.vector = vector; | 3897 | if (!dev_data || !dev_data->use_vapic) { |
3880 | irte->lo.fields_remap.destination = dest_apicid; | 3898 | irte->hi.fields.vector = vector; |
3881 | irte->lo.fields_remap.guest_mode = 0; | 3899 | irte->lo.fields_remap.destination = dest_apicid; |
3882 | modify_irte_ga(devid, index, irte, NULL); | 3900 | irte->lo.fields_remap.guest_mode = 0; |
3901 | modify_irte_ga(devid, index, irte, NULL); | ||
3902 | } | ||
3883 | } | 3903 | } |
3884 | 3904 | ||
3885 | #define IRTE_ALLOCATED (~1U) | 3905 | #define IRTE_ALLOCATED (~1U) |
@@ -4022,7 +4042,7 @@ static void irq_remapping_prepare_irte(struct amd_ir_data *data, | |||
4022 | data->irq_2_irte.index = index + sub_handle; | 4042 | data->irq_2_irte.index = index + sub_handle; |
4023 | iommu->irte_ops->prepare(data->entry, apic->irq_delivery_mode, | 4043 | iommu->irte_ops->prepare(data->entry, apic->irq_delivery_mode, |
4024 | apic->irq_dest_mode, irq_cfg->vector, | 4044 | apic->irq_dest_mode, irq_cfg->vector, |
4025 | irq_cfg->dest_apicid); | 4045 | irq_cfg->dest_apicid, devid); |
4026 | 4046 | ||
4027 | switch (info->type) { | 4047 | switch (info->type) { |
4028 | case X86_IRQ_ALLOC_TYPE_IOAPIC: | 4048 | case X86_IRQ_ALLOC_TYPE_IOAPIC: |
@@ -4222,6 +4242,14 @@ static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *vcpu_info) | |||
4222 | struct amd_ir_data *ir_data = data->chip_data; | 4242 | struct amd_ir_data *ir_data = data->chip_data; |
4223 | struct irte_ga *irte = (struct irte_ga *) ir_data->entry; | 4243 | struct irte_ga *irte = (struct irte_ga *) ir_data->entry; |
4224 | struct irq_2_irte *irte_info = &ir_data->irq_2_irte; | 4244 | struct irq_2_irte *irte_info = &ir_data->irq_2_irte; |
4245 | struct iommu_dev_data *dev_data = search_dev_data(irte_info->devid); | ||
4246 | |||
4247 | /* Note: | ||
4248 | * This device has never been set up for guest mode. | ||
4249 | * we should not modify the IRTE | ||
4250 | */ | ||
4251 | if (!dev_data || !dev_data->use_vapic) | ||
4252 | return 0; | ||
4225 | 4253 | ||
4226 | pi_data->ir_data = ir_data; | 4254 | pi_data->ir_data = ir_data; |
4227 | 4255 | ||
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 156ab4b0f4bd..cd1713631a4a 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c | |||
@@ -146,7 +146,7 @@ struct ivmd_header { | |||
146 | bool amd_iommu_dump; | 146 | bool amd_iommu_dump; |
147 | bool amd_iommu_irq_remap __read_mostly; | 147 | bool amd_iommu_irq_remap __read_mostly; |
148 | 148 | ||
149 | int amd_iommu_guest_ir; | 149 | int amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC; |
150 | 150 | ||
151 | static bool amd_iommu_detected; | 151 | static bool amd_iommu_detected; |
152 | static bool __initdata amd_iommu_disabled; | 152 | static bool __initdata amd_iommu_disabled; |
@@ -2019,6 +2019,11 @@ static void early_enable_iommus(void) | |||
2019 | iommu_enable(iommu); | 2019 | iommu_enable(iommu); |
2020 | iommu_flush_all_caches(iommu); | 2020 | iommu_flush_all_caches(iommu); |
2021 | } | 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 | ||
2022 | } | 2027 | } |
2023 | 2028 | ||
2024 | static void enable_iommus_v2(void) | 2029 | static void enable_iommus_v2(void) |
@@ -2044,6 +2049,11 @@ static void disable_iommus(void) | |||
2044 | 2049 | ||
2045 | for_each_iommu(iommu) | 2050 | for_each_iommu(iommu) |
2046 | 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 | ||
2047 | } | 2057 | } |
2048 | 2058 | ||
2049 | /* | 2059 | /* |
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index 79e91e68ee76..fa766eefd590 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h | |||
@@ -815,7 +815,7 @@ struct amd_ir_data { | |||
815 | }; | 815 | }; |
816 | 816 | ||
817 | struct amd_irte_ops { | 817 | struct amd_irte_ops { |
818 | void (*prepare)(void *, u32, u32, u8, u32); | 818 | void (*prepare)(void *, u32, u32, u8, u32, int); |
819 | void (*activate)(void *, u16, u16); | 819 | void (*activate)(void *, u16, u16); |
820 | void (*deactivate)(void *, u16, u16); | 820 | void (*deactivate)(void *, u16, u16); |
821 | void (*set_affinity)(void *, u16, u16, u8, u32); | 821 | void (*set_affinity)(void *, u16, u16, u8, u32); |