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 | 92 | /* Xen will never allocate port zero for any purpose. */ |
| 93 | 93 | #define VALID_EVTCHN(chn) ((chn) != 0) |
| 94 | 94 | |
| 95 | +static struct irq_info *legacy_info_ptrs[NR_IRQS_LEGACY]; | |
| 96 | + | |
| 95 | 97 | static struct irq_chip xen_dynamic_chip; |
| 96 | 98 | static struct irq_chip xen_percpu_chip; |
| 97 | 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 | 158 | /* Get info for IRQ */ |
| 157 | 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 | 175 | /* Constructors for packed IRQ information. */ |
| @@ -377,7 +390,7 @@ static void xen_irq_init(unsigned irq) · 214 unmodified lines | ||
| 377 | 390 | info->type = IRQT_UNBOUND; |
| 378 | 391 | info->refcnt = -1; |
| 379 | 392 | |
| 380 | − irq_set_chip_data(irq, info); | |
| 393 | + set_info_for_irq(irq, info); | |
| 381 | 394 | |
| 382 | 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 | 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 | 444 | if (WARN_ON(!info)) |
| 432 | 445 | return; |
| 433 | 446 | |
| 434 | 447 | list_del(&info->list); |
| 435 | 448 | |
| 436 | − irq_set_chip_data(irq, NULL); | |
| 449 | + set_info_for_irq(irq, NULL); | |
| 437 | 450 | |
| 438 | 451 | WARN_ON(info->refcnt > 0); |
| 439 | 452 | |
| @@ -603,7 +616,7 @@ EXPORT_SYMBOL_GPL(xen_irq_from_gsi); · 163 unmodified lines | ||
| 603 | 616 | static void __unbind_from_irq(unsigned int irq) |
| 604 | 617 | { |
| 605 | 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 | 621 | if (info->refcnt > 0) { |
| 609 | 622 | info->refcnt--; |
| @@ -1108,7 +1121,7 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi, · 498 unmodified lines | ||
| 1108 | 1121 | |
| 1109 | 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 | 1126 | if (WARN_ON(!info)) |
| 1114 | 1127 | return; |
| @@ -1142,7 +1155,7 @@ int evtchn_make_refcounted(evtchn_port_t evtchn) · 27 unmodified lines | ||
| 1142 | 1155 | if (irq == -1) |
| 1143 | 1156 | return -ENOENT; |
| 1144 | 1157 | |
| 1145 | − info = irq_get_chip_data(irq); | |
| 1158 | + info = info_for_irq(irq); | |
| 1146 | 1159 | |
| 1147 | 1160 | if (!info) |
| 1148 | 1161 | return -ENOENT; |
| @@ -1170,7 +1183,7 @@ int evtchn_get(evtchn_port_t evtchn) · 21 unmodified lines | ||
| 1170 | 1183 | if (irq == -1) |
| 1171 | 1184 | goto done; |
| 1172 | 1185 | |
| 1173 | − info = irq_get_chip_data(irq); | |
| 1186 | + info = info_for_irq(irq); | |
| 1174 | 1187 | |
| 1175 | 1188 | if (!info) |
| 1176 | 1189 | goto done; |