On Tue, 18 Aug 2020, Roman Shaposhnik wrote: > Hi! > first things first -- booting on those devices have always > required efi=no-rs -- but it seems that Xen 4.14 is now  > busted at a more fundamental level. I'm attaching two > boot sequences (one with kernel 4.19.5 and one with 5.4.51) > in the hopes that this may provide some clues right away. > > Any help would be greatly appreciated! > > Oh, and finally it appears that this is NOT a regression from > Xen 4.13 -- it fails the same way. I haven't tried Xen's earlier > than that. FYI Roman and I tracked down the issue and it is due to the gpio controller driver (drivers/pinctrl/intel/pinctrl-baytrail.c) overwriting the interrupt handler data used by Xen to store the irq_data structure. I have a very small tentative workaround, see below. It allows the kernel to boot successfully as dom0 and gpio writes work. I am still thinking on how to fix the issue properly in an upstreamable way, but I wanted to send this out to the list right away in case somebody else is stuck on this problem. diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index f38d596efa05..acd28a9e6a8a 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -1604,8 +1604,8 @@ static struct irq_chip byt_irqchip = { static void byt_gpio_irq_handler(struct irq_desc *desc) { struct irq_data *data = irq_desc_get_irq_data(desc); - struct byt_gpio *vg = gpiochip_get_data( - irq_desc_get_handler_data(desc)); + struct gpio_chip *gc = irq_desc_get_chip_data(desc); + struct byt_gpio *vg = (struct byt_gpio *)gc; struct irq_chip *chip = irq_data_get_irq_chip(data); u32 base, pin; void __iomem *reg; diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index a2b3d9de999c..b9551fb41ed1 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -1003,7 +1003,8 @@ irq_set_chained_handler_and_data(unsigned int irq, irq_flow_handler_t handle, if (!desc) return; - desc->irq_common_data.handler_data = data; + if (!desc->irq_common_data.handler_data) + desc->irq_common_data.handler_data = data; __irq_do_set_handler(desc, handle, 1, NULL); irq_put_desc_busunlock(desc, flags);