Since commit c330fb1ddc0a ("XEN uses irqdesc::irq_data_common::handler_data to store a per interrupt XEN data pointer which contains XEN specific information.") Xen is using the chip_data pointer for storing IRQ specific data. When running as a HVM domain this can result in problems for legacy IRQs, as those might use chip_data for their own purposes. Use a local array for this purpose in case of legacy IRQs, avoiding the double use.
Unified · Split
| @@ -92,6 +92,8 @@ static bool (*pirq_needs_eoi)(unsigned irq); · 91 unmodified lines | |||
| 92 | /* Xen will never allocate port zero for any purpose. */ | 92 | /* Xen will never allocate port zero for any purpose. */ |
| 93 | #define VALID_EVTCHN(chn) ((chn) != 0) | 93 | #define VALID_EVTCHN(chn) ((chn) != 0) |
| 94 | 94 | ||
| 95 | static struct irq_info *legacy_info_ptrs[NR_IRQS_LEGACY]; | ||
| 96 | |||
| 95 | static struct irq_chip xen_dynamic_chip; | 97 | static struct irq_chip xen_dynamic_chip; |
| 96 | static struct irq_chip xen_percpu_chip; | 98 | static struct irq_chip xen_percpu_chip; |
| 97 | static struct irq_chip xen_pirq_chip; | 99 | static struct irq_chip xen_pirq_chip; |
| @@ -156,7 +158,18 @@ int get_evtchn_to_irq(evtchn_port_t evtchn) · 58 unmodified lines | |||
| 156 | /* Get info for IRQ */ | 158 | /* Get info for IRQ */ |
| 157 | struct irq_info *info_for_irq(unsigned irq) | 159 | struct irq_info *info_for_irq(unsigned irq) |
| 158 | { | 160 | { |
| 159 | return irq_get_chip_data(irq); | 161 | if (irq < nr_legacy_irqs()) |
| 162 | return legacy_info_ptrs[irq]; | ||
| 163 | else | ||
| 164 | return irq_get_chip_data(irq); | ||
| 165 | } | ||
| 166 | |||
| 167 | static void set_info_for_irq(unsigned int irq, struct irq_info *info) | ||
| 168 | { | ||
| 169 | if (irq < nr_legacy_irqs()) | ||
| 170 | legacy_info_ptrs[irq] = info; | ||
| 171 | else | ||
| 172 | irq_set_chip_data(irq, info); | ||
| 160 | } | 173 | } |
| 161 | 174 | ||
| 162 | /* Constructors for packed IRQ information. */ | 175 | /* Constructors for packed IRQ information. */ |
| @@ -377,7 +390,7 @@ static void xen_irq_init(unsigned irq) · 214 unmodified lines | |||
| 377 | info->type = IRQT_UNBOUND; | 390 | info->type = IRQT_UNBOUND; |
| 378 | info->refcnt = -1; | 391 | info->refcnt = -1; |
| 379 | 392 | ||
| 380 | irq_set_chip_data(irq, info); | 393 | set_info_for_irq(irq, info); |
| 381 | 394 | ||
| 382 | list_add_tail(&info->list, &xen_irq_list_head); | 395 | list_add_tail(&info->list, &xen_irq_list_head); |
| 383 | } | 396 | } |
| @@ -426,14 +439,14 @@ static int __must_check xen_allocate_irq_gsi(unsigned gsi) · 42 unmodified lines | |||
| 426 | 439 | ||
| 427 | static void xen_free_irq(unsigned irq) | 440 | static void xen_free_irq(unsigned irq) |
| 428 | { | 441 | { |
| 429 | struct irq_info *info = irq_get_chip_data(irq); | 442 | struct irq_info *info = info_for_irq(irq); |
| 430 | 443 | ||
| 431 | if (WARN_ON(!info)) | 444 | if (WARN_ON(!info)) |
| 432 | return; | 445 | return; |
| 433 | 446 | ||
| 434 | list_del(&info->list); | 447 | list_del(&info->list); |
| 435 | 448 | ||
| 436 | irq_set_chip_data(irq, NULL); | 449 | set_info_for_irq(irq, NULL); |
| 437 | 450 | ||
| 438 | WARN_ON(info->refcnt > 0); | 451 | WARN_ON(info->refcnt > 0); |
| 439 | 452 | ||
| @@ -603,7 +616,7 @@ EXPORT_SYMBOL_GPL(xen_irq_from_gsi); · 163 unmodified lines | |||
| 603 | static void __unbind_from_irq(unsigned int irq) | 616 | static void __unbind_from_irq(unsigned int irq) |
| 604 | { | 617 | { |
| 605 | evtchn_port_t evtchn = evtchn_from_irq(irq); | 618 | evtchn_port_t evtchn = evtchn_from_irq(irq); |
| 606 | struct irq_info *info = irq_get_chip_data(irq); | 619 | struct irq_info *info = info_for_irq(irq); |
| 607 | 620 | ||
| 608 | if (info->refcnt > 0) { | 621 | if (info->refcnt > 0) { |
| 609 | info->refcnt--; | 622 | info->refcnt--; |
| @@ -1108,7 +1121,7 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi, · 498 unmodified lines | |||
| 1108 | 1121 | ||
| 1109 | void unbind_from_irqhandler(unsigned int irq, void *dev_id) | 1122 | void unbind_from_irqhandler(unsigned int irq, void *dev_id) |
| 1110 | { | 1123 | { |
| 1111 | struct irq_info *info = irq_get_chip_data(irq); | 1124 | struct irq_info *info = info_for_irq(irq); |
| 1112 | 1125 | ||
| 1113 | if (WARN_ON(!info)) | 1126 | if (WARN_ON(!info)) |
| 1114 | return; | 1127 | return; |
| @@ -1142,7 +1155,7 @@ int evtchn_make_refcounted(evtchn_port_t evtchn) · 27 unmodified lines | |||
| 1142 | if (irq == -1) | 1155 | if (irq == -1) |
| 1143 | return -ENOENT; | 1156 | return -ENOENT; |
| 1144 | 1157 | ||
| 1145 | info = irq_get_chip_data(irq); | 1158 | info = info_for_irq(irq); |
| 1146 | 1159 | ||
| 1147 | if (!info) | 1160 | if (!info) |
| 1148 | return -ENOENT; | 1161 | return -ENOENT; |
| @@ -1170,7 +1183,7 @@ int evtchn_get(evtchn_port_t evtchn) · 21 unmodified lines | |||
| 1170 | if (irq == -1) | 1183 | if (irq == -1) |
| 1171 | goto done; | 1184 | goto done; |
| 1172 | 1185 | ||
| 1173 | info = irq_get_chip_data(irq); | 1186 | info = info_for_irq(irq); |
| 1174 | 1187 | ||
| 1175 | if (!info) | 1188 | if (!info) |
| 1176 | goto done; | 1189 | goto done; |