This patch tries to make sure the virtio interrupt handler for MMIO won't be called after a reset and before virtio_device_ready(). We can't use IRQF_NO_AUTOEN since we're using shared interrupt (IRQF_SHARED). So this patch tracks the interrupt enabling status in a new intr_soft_enabled variable and toggle it during in vm_disable/enable_interrupts(). The MMIO interrupt handler will check intr_soft_enabled before processing the actual interrupt. Signed-off-by: Jason Wang <jasowang at redhat.com> --- drivers/virtio/virtio_mmio.c | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index 56128b9c46eb..796f0c789b09 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -90,6 +90,7 @@ struct virtio_mmio_device { /* a list of queues so we can dispatch IRQs */ spinlock_t lock; struct list_head virtqueues; + bool intr_soft_enabled; }; struct virtio_mmio_vq_info { @@ -100,7 +101,37 @@ struct virtio_mmio_vq_info { struct list_head node; }; +/* disable irq handlers */ +void vm_disable_cbs(struct virtio_device *vdev) +{ + struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); + int irq = platform_get_irq(vm_dev->pdev, 0); + /* + * The below synchronize() guarantees that any + * interrupt for this line arriving after + * synchronize_irq() has completed is guaranteed to see + * intx_soft_enabled == false. + */ + WRITE_ONCE(vm_dev->intr_soft_enabled, false); + synchronize_irq(irq); +} + +/* enable irq handlers */ +void vm_enable_cbs(struct virtio_device *vdev) +{ + struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); + int irq = platform_get_irq(vm_dev->pdev, 0); + + disable_irq(irq); + /* + * The above disable_irq() provides TSO ordering and + * as such promotes the below store to store-release. + */ + WRITE_ONCE(vm_dev->intr_soft_enabled, true); + enable_irq(irq); + return; +} /* Configuration interface */ @@ -262,6 +293,8 @@ static void vm_reset(struct virtio_device *vdev) /* 0 status means a reset. */ writel(0, vm_dev->base + VIRTIO_MMIO_STATUS); + /* Disable VQ/configuration callbacks. */ + vm_disable_cbs(vdev); } @@ -288,6 +321,9 @@ static irqreturn_t vm_interrupt(int irq, void *opaque) unsigned long flags; irqreturn_t ret = IRQ_NONE; + if (!READ_ONCE(vm_dev->intr_soft_enabled)) + return IRQ_NONE; + /* Read and acknowledge interrupts */ status = readl(vm_dev->base + VIRTIO_MMIO_INTERRUPT_STATUS); writel(status, vm_dev->base + VIRTIO_MMIO_INTERRUPT_ACK); @@ -529,6 +565,7 @@ static bool vm_get_shm_region(struct virtio_device *vdev, } static const struct virtio_config_ops virtio_mmio_config_ops = { + .enable_cbs = vm_enable_cbs, .get = vm_get, .set = vm_set, .generation = vm_generation, -- 2.25.1
Hi Jason, I love your patch! Perhaps something to improve: [auto build test WARNING on linus/master] [also build test WARNING on v5.16-rc2 next-20211125] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Jason-Wang/virtio-mmio-harden-interrupt/20211125-143334 base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 5f53fa508db098c9d372423a6dac31c8a5679cdf config: m68k-allyesconfig (https://download.01.org/0day-ci/archive/20211125/202111251934.ybhaqyh7-lkp at intel.com/config) compiler: m68k-linux-gcc (GCC) 11.2.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/e19a8a1a95bd891090863b2d6828b8dc55d3633f git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Jason-Wang/virtio-mmio-harden-interrupt/20211125-143334 git checkout e19a8a1a95bd891090863b2d6828b8dc55d3633f # save the config file to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=m68k If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp at intel.com> All warnings (new ones prefixed by >>):>> drivers/virtio/virtio_mmio.c:105:6: warning: no previous prototype for 'vm_disable_cbs' [-Wmissing-prototypes]105 | void vm_disable_cbs(struct virtio_device *vdev) | ^~~~~~~~~~~~~~>> drivers/virtio/virtio_mmio.c:121:6: warning: no previous prototype for 'vm_enable_cbs' [-Wmissing-prototypes]121 | void vm_enable_cbs(struct virtio_device *vdev) | ^~~~~~~~~~~~~ vim +/vm_disable_cbs +105 drivers/virtio/virtio_mmio.c 103 104 /* disable irq handlers */ > 105 void vm_disable_cbs(struct virtio_device *vdev) 106 { 107 struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); 108 int irq = platform_get_irq(vm_dev->pdev, 0); 109 110 /* 111 * The below synchronize() guarantees that any 112 * interrupt for this line arriving after 113 * synchronize_irq() has completed is guaranteed to see 114 * intx_soft_enabled == false. 115 */ 116 WRITE_ONCE(vm_dev->intr_soft_enabled, false); 117 synchronize_irq(irq); 118 } 119 120 /* enable irq handlers */ > 121 void vm_enable_cbs(struct virtio_device *vdev) 122 { 123 struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); 124 int irq = platform_get_irq(vm_dev->pdev, 0); 125 126 disable_irq(irq); 127 /* 128 * The above disable_irq() provides TSO ordering and 129 * as such promotes the below store to store-release. 130 */ 131 WRITE_ONCE(vm_dev->intr_soft_enabled, true); 132 enable_irq(irq); 133 return; 134 } 135 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all at lists.01.org
Hi Jason, I love your patch! Perhaps something to improve: [auto build test WARNING on linus/master] [also build test WARNING on v5.16-rc2 next-20211125] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Jason-Wang/virtio-mmio-harden-interrupt/20211125-143334 base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 5f53fa508db098c9d372423a6dac31c8a5679cdf config: mips-buildonly-randconfig-r003-20211125 (https://download.01.org/0day-ci/archive/20211125/202111252001.Z5tli1Np-lkp at intel.com/config) compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 67a1c45def8a75061203461ab0060c75c864df1c) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install mips cross compiling tool for clang build # apt-get install binutils-mips-linux-gnu # https://github.com/0day-ci/linux/commit/e19a8a1a95bd891090863b2d6828b8dc55d3633f git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Jason-Wang/virtio-mmio-harden-interrupt/20211125-143334 git checkout e19a8a1a95bd891090863b2d6828b8dc55d3633f # save the config file to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=mips If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp at intel.com> All warnings (new ones prefixed by >>):>> drivers/virtio/virtio_mmio.c:105:6: warning: no previous prototype for function 'vm_disable_cbs' [-Wmissing-prototypes]void vm_disable_cbs(struct virtio_device *vdev) ^ drivers/virtio/virtio_mmio.c:105:1: note: declare 'static' if the function is not intended to be used outside of this translation unit void vm_disable_cbs(struct virtio_device *vdev) ^ static>> drivers/virtio/virtio_mmio.c:121:6: warning: no previous prototype for function 'vm_enable_cbs' [-Wmissing-prototypes]void vm_enable_cbs(struct virtio_device *vdev) ^ drivers/virtio/virtio_mmio.c:121:1: note: declare 'static' if the function is not intended to be used outside of this translation unit void vm_enable_cbs(struct virtio_device *vdev) ^ static 2 warnings generated. vim +/vm_disable_cbs +105 drivers/virtio/virtio_mmio.c 103 104 /* disable irq handlers */ > 105 void vm_disable_cbs(struct virtio_device *vdev) 106 { 107 struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); 108 int irq = platform_get_irq(vm_dev->pdev, 0); 109 110 /* 111 * The below synchronize() guarantees that any 112 * interrupt for this line arriving after 113 * synchronize_irq() has completed is guaranteed to see 114 * intx_soft_enabled == false. 115 */ 116 WRITE_ONCE(vm_dev->intr_soft_enabled, false); 117 synchronize_irq(irq); 118 } 119 120 /* enable irq handlers */ > 121 void vm_enable_cbs(struct virtio_device *vdev) 122 { 123 struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); 124 int irq = platform_get_irq(vm_dev->pdev, 0); 125 126 disable_irq(irq); 127 /* 128 * The above disable_irq() provides TSO ordering and 129 * as such promotes the below store to store-release. 130 */ 131 WRITE_ONCE(vm_dev->intr_soft_enabled, true); 132 enable_irq(irq); 133 return; 134 } 135 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all at lists.01.org