xen/events: don't use chip_data for legacy IRQs

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.

Cc: stable@vger.kernel.org
Fixes: c330fb1ddc0a ("XEN uses irqdesc::irq_data_common::handler_data to store a per interrupt XEN data pointer which contains XEN specific information.")
Signed-off-by: Juergen Gross <jgross@suse.com>
Tested-by: Stefan Bader <stefan.bader@canonical.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Link: https://lore.kernel.org/r/20200930091614.13660-1-jgross@suse.com
Signed-off-by: Juergen Gross <jgross@suse.com>

Changed files
+21 -8
drivers
xen
events
+21 -8
drivers/xen/events/events_base.c
··· 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; ··· 158 156 /* Get info for IRQ */ 159 157 struct irq_info *info_for_irq(unsigned irq) 160 158 { 161 - return irq_get_chip_data(irq); 159 + if (irq < nr_legacy_irqs()) 160 + return legacy_info_ptrs[irq]; 161 + else 162 + return irq_get_chip_data(irq); 163 + } 164 + 165 + static void set_info_for_irq(unsigned int irq, struct irq_info *info) 166 + { 167 + if (irq < nr_legacy_irqs()) 168 + legacy_info_ptrs[irq] = info; 169 + else 170 + irq_set_chip_data(irq, info); 162 171 } 163 172 164 173 /* Constructors for packed IRQ information. */ ··· 390 377 info->type = IRQT_UNBOUND; 391 378 info->refcnt = -1; 392 379 393 - irq_set_chip_data(irq, info); 380 + set_info_for_irq(irq, info); 394 381 395 382 list_add_tail(&info->list, &xen_irq_list_head); 396 383 } ··· 439 426 440 427 static void xen_free_irq(unsigned irq) 441 428 { 442 - struct irq_info *info = irq_get_chip_data(irq); 429 + struct irq_info *info = info_for_irq(irq); 443 430 444 431 if (WARN_ON(!info)) 445 432 return; 446 433 447 434 list_del(&info->list); 448 435 449 - irq_set_chip_data(irq, NULL); 436 + set_info_for_irq(irq, NULL); 450 437 451 438 WARN_ON(info->refcnt > 0); 452 439 ··· 616 603 static void __unbind_from_irq(unsigned int irq) 617 604 { 618 605 evtchn_port_t evtchn = evtchn_from_irq(irq); 619 - struct irq_info *info = irq_get_chip_data(irq); 606 + struct irq_info *info = info_for_irq(irq); 620 607 621 608 if (info->refcnt > 0) { 622 609 info->refcnt--; ··· 1121 1108 1122 1109 void unbind_from_irqhandler(unsigned int irq, void *dev_id) 1123 1110 { 1124 - struct irq_info *info = irq_get_chip_data(irq); 1111 + struct irq_info *info = info_for_irq(irq); 1125 1112 1126 1113 if (WARN_ON(!info)) 1127 1114 return; ··· 1155 1142 if (irq == -1) 1156 1143 return -ENOENT; 1157 1144 1158 - info = irq_get_chip_data(irq); 1145 + info = info_for_irq(irq); 1159 1146 1160 1147 if (!info) 1161 1148 return -ENOENT; ··· 1183 1170 if (irq == -1) 1184 1171 goto done; 1185 1172 1186 - info = irq_get_chip_data(irq); 1173 + info = info_for_irq(irq); 1187 1174 1188 1175 if (!info) 1189 1176 goto done;