Message ID | 20240214084419.6194-3-brgl@bgdev.pl |
---|---|
State | New |
Headers | show |
Series | gpio: fix SRCU bugs | expand |
On 14.02.2024 09:44, Bartosz Golaszewski wrote: > From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> > > We never dereference the chip pointer in character device code so we can > use the lighter rcu_access_pointer() helper. This also makes lockep > happier as it no longer complains about suspicious rcu_dereference() > usage. > > Fixes: d83cee3d2bb1 ("gpio: protect the pointer to gpio_chip in gpio_device with SRCU") > Reported-by: kernel test robot <oliver.sang@intel.com> > Closes: https://lore.kernel.org/oe-lkp/202402122234.d85cca9b-lkp@intel.com > Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> > Reviewed-by: Linus Walleij <linus.walleij@linaro.org> > --- > drivers/gpio/gpiolib-cdev.c | 25 ++++++++++++------------- > 1 file changed, 12 insertions(+), 13 deletions(-) > > diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c > index 9323b357df43..85037fa4925e 100644 > --- a/drivers/gpio/gpiolib-cdev.c > +++ b/drivers/gpio/gpiolib-cdev.c > @@ -206,7 +206,7 @@ static long linehandle_ioctl(struct file *file, unsigned int cmd, > > guard(srcu)(&lh->gdev->srcu); > > - if (!rcu_dereference(lh->gdev->chip)) > + if (!rcu_access_pointer(lh->gdev->chip)) > return -ENODEV; > > switch (cmd) { > @@ -1521,7 +1521,7 @@ static long linereq_ioctl(struct file *file, unsigned int cmd, > > guard(srcu)(&lr->gdev->srcu); > > - if (!rcu_dereference(lr->gdev->chip)) > + if (!rcu_access_pointer(lr->gdev->chip)) > return -ENODEV; > > switch (cmd) { > @@ -1552,7 +1552,7 @@ static __poll_t linereq_poll(struct file *file, > > guard(srcu)(&lr->gdev->srcu); > > - if (!rcu_dereference(lr->gdev->chip)) > + if (!rcu_access_pointer(lr->gdev->chip)) > return EPOLLHUP | EPOLLERR; > > poll_wait(file, &lr->wait, wait); > @@ -1574,7 +1574,7 @@ static ssize_t linereq_read(struct file *file, char __user *buf, > > guard(srcu)(&lr->gdev->srcu); > > - if (!rcu_dereference(lr->gdev->chip)) > + if (!rcu_access_pointer(lr->gdev->chip)) > return -ENODEV; > > if (count < sizeof(le)) > @@ -1875,7 +1875,7 @@ static __poll_t lineevent_poll(struct file *file, > > guard(srcu)(&le->gdev->srcu); > > - if (!rcu_dereference(le->gdev->chip)) > + if (!rcu_access_pointer(le->gdev->chip)) > return EPOLLHUP | EPOLLERR; > > poll_wait(file, &le->wait, wait); > @@ -1913,7 +1913,7 @@ static ssize_t lineevent_read(struct file *file, char __user *buf, > > guard(srcu)(&le->gdev->srcu); > > - if (!rcu_dereference(le->gdev->chip)) > + if (!rcu_access_pointer(le->gdev->chip)) > return -ENODEV; > > /* > @@ -1996,7 +1996,7 @@ static long lineevent_ioctl(struct file *file, unsigned int cmd, > > guard(srcu)(&le->gdev->srcu); > > - if (!rcu_dereference(le->gdev->chip)) > + if (!rcu_access_pointer(le->gdev->chip)) > return -ENODEV; > > /* > @@ -2510,7 +2510,7 @@ static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) > guard(srcu)(&gdev->srcu); > > /* We fail any subsequent ioctl():s when the chip is gone */ > - if (!rcu_dereference(gdev->chip)) > + if (!rcu_access_pointer(gdev->chip)) > return -ENODEV; > > /* Fill in the struct and pass to userspace */ > @@ -2595,7 +2595,7 @@ static __poll_t lineinfo_watch_poll(struct file *file, > > guard(srcu)(&cdev->gdev->srcu); > > - if (!rcu_dereference(cdev->gdev->chip)) > + if (!rcu_access_pointer(cdev->gdev->chip)) > return EPOLLHUP | EPOLLERR; > > poll_wait(file, &cdev->wait, pollt); > @@ -2618,7 +2618,7 @@ static ssize_t lineinfo_watch_read(struct file *file, char __user *buf, > > guard(srcu)(&cdev->gdev->srcu); > > - if (!rcu_dereference(cdev->gdev->chip)) > + if (!rcu_access_pointer(cdev->gdev->chip)) > return -ENODEV; > > #ifndef CONFIG_GPIO_CDEV_V1 > @@ -2696,7 +2696,7 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file) > guard(srcu)(&gdev->srcu); > > /* Fail on open if the backing gpiochip is gone */ > - if (!rcu_dereference(gdev->chip)) > + if (!rcu_access_pointer(gdev->chip)) > return -ENODEV; > > cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); > @@ -2796,8 +2796,7 @@ int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt) > > guard(srcu)(&gdev->srcu); > > - gc = rcu_dereference(gdev->chip); > - if (!gc) > + if (!rcu_access_pointer(gdev->chip)) > return -ENODEV; > > chip_dbg(gc, "added GPIO chardev (%d:%d)\n", MAJOR(devt), gdev->id); Here 'gc' is left uninitialized and nukes if GPIO DEBUGs are enabled. Here is an example (captured on today's linux-next): 8<--- cut here --- Unable to handle kernel NULL pointer dereference at virtual address 00000000 when read [00000000] *pgd=00000000 Internal error: Oops: 5 [#1] PREEMPT SMP ARM Modules linked in: CPU: 1 PID: 1 Comm: swapper/0 Not tainted 6.8.0-rc4-next-20240216 #8096 Hardware name: Samsung Exynos (Flattened Device Tree) PC is at gpiolib_cdev_register+0xd4/0x170 LR is at chainhash_table+0x784/0x20000 pc : [<c05dbe54>] lr : [<c18bb74c>] psr: 20000013 ... Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none Control: 10c5387d Table: 4000404a DAC: 00000051 Register r0 information: non-slab/vmalloc memory Register r1 information: NULL pointer Register r2 information: non-paged memory Register r3 information: non-paged memory Register r4 information: slab kmalloc-1k start c1e5f800 pointer offset 0 size 1024 Register r5 information: NULL pointer Register r6 information: non-paged memory Register r7 information: slab kmalloc-1k start c1e5f800 pointer offset 952 size 1024 Register r8 information: NULL pointer Register r9 information: slab kmalloc-1k start c1e5f800 pointer offset 960 size 1024 Register r10 information: non-paged memory Register r11 information: non-slab/vmalloc memory Register r12 information: NULL pointer Process swapper/0 (pid: 1, stack limit = 0x(ptrval)) Stack: (0xf082db90 to 0xf082e000) ... gpiolib_cdev_register from gpiochip_setup_dev+0x44/0xb0 gpiochip_setup_dev from gpiochip_add_data_with_key+0x9ac/0xaac gpiochip_add_data_with_key from devm_gpiochip_add_data_with_key+0x20/0x5c devm_gpiochip_add_data_with_key from samsung_pinctrl_probe+0x938/0xb18 samsung_pinctrl_probe from platform_probe+0x5c/0xb8 platform_probe from really_probe+0xe0/0x400 really_probe from __driver_probe_device+0x9c/0x1f4 __driver_probe_device from driver_probe_device+0x30/0xc0 driver_probe_device from __device_attach_driver+0xa8/0x120 __device_attach_driver from bus_for_each_drv+0x80/0xcc bus_for_each_drv from __device_attach+0xac/0x1fc __device_attach from bus_probe_device+0x8c/0x90 bus_probe_device from device_add+0x5d4/0x7fc device_add from of_platform_device_create_pdata+0x94/0xc4 of_platform_device_create_pdata from of_platform_bus_create+0x1f8/0x4c0 of_platform_bus_create from of_platform_bus_create+0x268/0x4c0 of_platform_bus_create from of_platform_populate+0x80/0x110 of_platform_populate from of_platform_default_populate_init+0xd4/0xec of_platform_default_populate_init from do_one_initcall+0x64/0x2fc do_one_initcall from kernel_init_freeable+0x1c4/0x228 kernel_init_freeable from kernel_init+0x1c/0x12c kernel_init from ret_from_fork+0x14/0x28 Exception stack(0xf082dfb0 to 0xf082dff8) ... ---[ end trace 0000000000000000 ]--- Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ]--- Probably the easiest way to fix this issue is to replace chip_dbg with the following dev_dbg() call: dev_dbg(&gdev->dev, "(%s): added GPIO chardev (%d:%d)\n", gdev->label, MAJOR(devt), gdev->id); Best regards
On Fri, Feb 16, 2024 at 11:31 AM Marek Szyprowski <m.szyprowski@samsung.com> wrote: > [snip] > > Here 'gc' is left uninitialized and nukes if GPIO DEBUGs are enabled. > Here is an example (captured on today's linux-next): > > 8<--- cut here --- > Unable to handle kernel NULL pointer dereference at virtual address > 00000000 when read > [00000000] *pgd=00000000 > Internal error: Oops: 5 [#1] PREEMPT SMP ARM > Modules linked in: > CPU: 1 PID: 1 Comm: swapper/0 Not tainted 6.8.0-rc4-next-20240216 #8096 > Hardware name: Samsung Exynos (Flattened Device Tree) > PC is at gpiolib_cdev_register+0xd4/0x170 > LR is at chainhash_table+0x784/0x20000 > pc : [<c05dbe54>] lr : [<c18bb74c>] psr: 20000013 > ... > Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none > Control: 10c5387d Table: 4000404a DAC: 00000051 > Register r0 information: non-slab/vmalloc memory > Register r1 information: NULL pointer > Register r2 information: non-paged memory > Register r3 information: non-paged memory > Register r4 information: slab kmalloc-1k start c1e5f800 pointer offset 0 > size 1024 > Register r5 information: NULL pointer > Register r6 information: non-paged memory > Register r7 information: slab kmalloc-1k start c1e5f800 pointer offset > 952 size 1024 > Register r8 information: NULL pointer > Register r9 information: slab kmalloc-1k start c1e5f800 pointer offset > 960 size 1024 > Register r10 information: non-paged memory > Register r11 information: non-slab/vmalloc memory > Register r12 information: NULL pointer > Process swapper/0 (pid: 1, stack limit = 0x(ptrval)) > Stack: (0xf082db90 to 0xf082e000) > ... > gpiolib_cdev_register from gpiochip_setup_dev+0x44/0xb0 > gpiochip_setup_dev from gpiochip_add_data_with_key+0x9ac/0xaac > gpiochip_add_data_with_key from devm_gpiochip_add_data_with_key+0x20/0x5c > devm_gpiochip_add_data_with_key from samsung_pinctrl_probe+0x938/0xb18 > samsung_pinctrl_probe from platform_probe+0x5c/0xb8 > platform_probe from really_probe+0xe0/0x400 > really_probe from __driver_probe_device+0x9c/0x1f4 > __driver_probe_device from driver_probe_device+0x30/0xc0 > driver_probe_device from __device_attach_driver+0xa8/0x120 > __device_attach_driver from bus_for_each_drv+0x80/0xcc > bus_for_each_drv from __device_attach+0xac/0x1fc > __device_attach from bus_probe_device+0x8c/0x90 > bus_probe_device from device_add+0x5d4/0x7fc > device_add from of_platform_device_create_pdata+0x94/0xc4 > of_platform_device_create_pdata from of_platform_bus_create+0x1f8/0x4c0 > of_platform_bus_create from of_platform_bus_create+0x268/0x4c0 > of_platform_bus_create from of_platform_populate+0x80/0x110 > of_platform_populate from of_platform_default_populate_init+0xd4/0xec > of_platform_default_populate_init from do_one_initcall+0x64/0x2fc > do_one_initcall from kernel_init_freeable+0x1c4/0x228 > kernel_init_freeable from kernel_init+0x1c/0x12c > kernel_init from ret_from_fork+0x14/0x28 > Exception stack(0xf082dfb0 to 0xf082dff8) > ... > ---[ end trace 0000000000000000 ]--- > Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b > ---[ end Kernel panic - not syncing: Attempted to kill init! > exitcode=0x0000000b ]--- > > > Probably the easiest way to fix this issue is to replace chip_dbg with > the following dev_dbg() call: > > dev_dbg(&gdev->dev, "(%s): added GPIO chardev (%d:%d)\n", gdev->label, > MAJOR(devt), gdev->id); > Thanks for the report. Surprisingly there are no warnings about that with GCC. The best way is to use srcu_dereference() here and keep the same log message. Patch is on the way. Bart
Hello, kernel test robot noticed "BUG:unable_to_handle_page_fault_for_address" on: commit: ef4aabaa372144b2bfa9c4ddc83255831cff9ebd ("[PATCH v2 2/4] gpio: cdev: use correct pointer accessors with SRCU") url: https://github.com/intel-lab-lkp/linux/commits/Bartosz-Golaszewski/gpio-take-the-SRCU-read-lock-in-gpiod_hog/20240214-164752 base: https://git.kernel.org/cgit/linux/kernel/git/brgl/linux.git gpio/for-next patch link: https://lore.kernel.org/all/20240214084419.6194-3-brgl@bgdev.pl/ patch subject: [PATCH v2 2/4] gpio: cdev: use correct pointer accessors with SRCU in testcase: boot compiler: clang-17 test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G (please refer to attached dmesg/kmsg for entire log/backtrace) +----------------------------------------------------------------------------------+------------+------------+ | | 5c3cf44c4e | ef4aabaa37 | +----------------------------------------------------------------------------------+------------+------------+ | BUG:unable_to_handle_page_fault_for_address | 0 | 14 | | Oops:#[##] | 0 | 14 | | EIP:gpiolib_cdev_register | 0 | 14 | | Kernel_panic-not_syncing:Fatal_exception | 0 | 14 | +----------------------------------------------------------------------------------+------------+------------+ If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-lkp/202402262225.50983057-lkp@intel.com [ 57.990853][ T1] gpiochip_find_base_unlocked: found new base at 512 [ 57.991570][ T1] [ 57.991875][ T1] ============================= [ 57.992480][ T1] WARNING: suspicious RCU usage [ 57.992993][ T1] 6.8.0-rc4-00057-gef4aabaa3721 #1 Tainted: G TN [ 57.993787][ T1] ----------------------------- [ 57.994289][ T1] drivers/gpio/gpiolib.h:205 suspicious rcu_dereference_check() usage! [ 57.995135][ T1] [ 57.995135][ T1] other info that might help us debug this: [ 57.995135][ T1] [ 57.996198][ T1] [ 57.996198][ T1] rcu_scheduler_active = 2, debug_locks = 1 [ 57.997073][ T1] 2 locks held by swapper/1: [ 57.997559][ T1] #0: ea878e8c (&dev->mutex){....}-{3:3}, at: __driver_attach (drivers/base/dd.c:1216) [ 57.998494][ T1] #1: eb682f3c (&gdev->srcu){.+.+}-{0:0}, at: srcu_lock_acquire (include/linux/srcu.h:115) [ 57.999365][ T1] [ 57.999365][ T1] stack backtrace: [ 58.000005][ T1] CPU: 0 PID: 1 Comm: swapper Tainted: G TN 6.8.0-rc4-00057-gef4aabaa3721 #1 10e84cefff2a9bf1626b34c75cc7b6c846de4a3a [ 58.001317][ T1] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014 [ 58.002330][ T1] Call Trace: [ 58.002690][ T1] dump_stack_lvl (lib/dump_stack.c:107) [ 58.003158][ T1] dump_stack (lib/dump_stack.c:113) [ 58.003631][ T1] lockdep_rcu_suspicious (kernel/locking/lockdep.c:6714) [ 58.006180][ T1] gpiod_hog (drivers/gpio/gpiolib.h:?) [ 58.006632][ T1] of_gpiochip_add_hog (drivers/gpio/gpiolib-of.c:799) [ 58.007165][ T1] of_gpiochip_add (drivers/gpio/gpiolib-of.c:829 drivers/gpio/gpiolib-of.c:1144) [ 58.007663][ T1] gpiochip_add_data_with_key (drivers/gpio/gpiolib.c:1013) [ 58.008278][ T1] unittest_gpio_probe (drivers/of/unittest.c:1886) [ 58.008799][ T1] platform_probe (drivers/base/platform.c:1405) [ 58.009268][ T1] really_probe (drivers/base/dd.c:?) [ 58.009738][ T1] __driver_probe_device (drivers/base/dd.c:800) [ 58.010265][ T1] driver_probe_device (drivers/base/dd.c:830) [ 58.010776][ T1] __driver_attach (drivers/base/dd.c:1217) [ 58.011258][ T1] ? driver_attach (drivers/base/dd.c:1157) [ 58.011734][ T1] bus_for_each_dev (drivers/base/bus.c:367) [ 58.012234][ T1] driver_attach (drivers/base/dd.c:1233) [ 58.012692][ T1] ? driver_attach (drivers/base/dd.c:1157) [ 58.013168][ T1] bus_add_driver (drivers/base/bus.c:674) [ 58.013652][ T1] driver_register (drivers/base/driver.c:246) [ 58.014177][ T1] __platform_driver_register (drivers/base/platform.c:867) [ 58.014730][ T1] of_unittest_overlay_gpio (drivers/of/unittest.c:1969) [ 58.015285][ T1] of_unittest_overlay (drivers/of/unittest.c:3217) [ 58.015804][ T1] of_unittest (drivers/of/unittest.c:4129) [ 58.016264][ T1] do_one_initcall (init/main.c:1236) [ 58.016755][ T1] ? dt_alloc_memory (drivers/of/unittest.c:4080) [ 58.017247][ T1] ? kvm_sched_clock_read (arch/x86/kernel/kvmclock.c:91) [ 58.017766][ T1] ? sched_clock_noinstr (arch/x86/kernel/tsc.c:266) [ 58.018269][ T1] ? local_clock_noinstr (kernel/sched/clock.c:269 kernel/sched/clock.c:306) [ 58.018802][ T1] ? rcu_read_lock_any_held (kernel/rcu/update.c:386) [ 58.019348][ T1] ? __lock_acquire (kernel/locking/lockdep.c:3762) [ 58.019864][ T1] ? __lock_acquire (kernel/locking/lockdep.c:3762) [ 58.020382][ T1] ? kvm_sched_clock_read (arch/x86/kernel/kvmclock.c:91) [ 58.020900][ T1] ? sched_clock_noinstr (arch/x86/kernel/tsc.c:266) [ 58.021400][ T1] ? local_clock_noinstr (kernel/sched/clock.c:269 kernel/sched/clock.c:306) [ 58.021931][ T1] ? rcu_read_lock_any_held (kernel/rcu/update.c:386) [ 58.022471][ T1] ? __lock_acquire (kernel/locking/lockdep.c:3762) [ 58.022979][ T1] ? kvm_sched_clock_read (arch/x86/kernel/kvmclock.c:91) [ 58.023496][ T1] ? sched_clock_noinstr (arch/x86/kernel/tsc.c:266) [ 58.024000][ T1] ? local_clock_noinstr (kernel/sched/clock.c:269 kernel/sched/clock.c:306) [ 58.024526][ T1] ? local_clock (arch/x86/include/asm/preempt.h:84 kernel/sched/clock.c:316) [ 58.024982][ T1] ? irqtime_account_irq (kernel/sched/cputime.c:?) [ 58.025553][ T1] ? irqtime_account_delta (include/linux/seqlock.h:444 include/linux/seqlock.h:516 include/linux/u64_stats_sync.h:151 include/linux/u64_stats_sync.h:187 kernel/sched/cputime.c:46) [ 58.026091][ T1] ? trace_hardirqs_on (kernel/trace/trace_preemptirq.c:63) [ 58.026594][ T1] ? irqentry_exit (kernel/entry/common.c:?) [ 58.027070][ T1] ? common_interrupt (arch/x86/kernel/irq.c:247) [ 58.027567][ T1] ? asm_common_interrupt (arch/x86/entry/entry_32.S:640) [ 58.028119][ T1] ? strlen (arch/x86/lib/string_32.c:175) [ 58.028540][ T1] ? next_arg (lib/cmdline.c:273) [ 58.028991][ T1] ? parse_args (kernel/params.c:153) [ 58.029467][ T1] do_initcall_level (init/main.c:1297) [ 58.029957][ T1] ? rest_init (init/main.c:1433) [ 58.030398][ T1] do_initcalls (init/main.c:1311) [ 58.030846][ T1] ? rest_init (init/main.c:1433) [ 58.031299][ T1] do_basic_setup (init/main.c:1334) [ 58.031769][ T1] kernel_init_freeable (init/main.c:1555) [ 58.032283][ T1] kernel_init (init/main.c:1443) [ 58.032732][ T1] ret_from_fork (arch/x86/kernel/process.c:153) [ 58.033192][ T1] ret_from_fork_asm (arch/x86/entry/entry_32.S:741) [ 58.033680][ T1] entry_INT80_32 (arch/x86/entry/entry_32.S:947) [ 58.034672][ T1] gpio gpiochip0: Persistence not supported for GPIO 2 [ 58.035366][ T1] [ 58.035669][ T1] ============================= [ 58.036180][ T1] WARNING: suspicious RCU usage [ 58.036739][ T1] 6.8.0-rc4-00057-gef4aabaa3721 #1 Tainted: G TN [ 58.037546][ T1] ----------------------------- [ 58.038050][ T1] drivers/gpio/gpiolib.c:112 suspicious rcu_dereference_check() usage! [ 58.038893][ T1] [ 58.038893][ T1] other info that might help us debug this: [ 58.038893][ T1] [ 58.039950][ T1] [ 58.039950][ T1] rcu_scheduler_active = 2, debug_locks = 1 [ 58.040837][ T1] 3 locks held by swapper/1: [ 58.041318][ T1] #0: ea878e8c (&dev->mutex){....}-{3:3}, at: __driver_attach (drivers/base/dd.c:1216) [ 58.042234][ T1] #1: eb682f3c (&gdev->srcu){.+.+}-{0:0}, at: srcu_lock_acquire (include/linux/srcu.h:115) [ 58.043116][ T1] #2: eb6831dc (&desc->srcu){.+.+}-{0:0}, at: srcu_lock_acquire (include/linux/srcu.h:115) [ 58.043992][ T1] [ 58.043992][ T1] stack backtrace: [ 58.044685][ T1] CPU: 0 PID: 1 Comm: swapper Tainted: G TN 6.8.0-rc4-00057-gef4aabaa3721 #1 10e84cefff2a9bf1626b34c75cc7b6c846de4a3a [ 58.046006][ T1] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014 [ 58.047050][ T1] Call Trace: [ 58.047417][ T1] dump_stack_lvl (lib/dump_stack.c:107) [ 58.047896][ T1] dump_stack (lib/dump_stack.c:113) [ 58.048430][ T1] lockdep_rcu_suspicious (kernel/locking/lockdep.c:6714) [ 58.048974][ T1] gpiod_get_label (drivers/gpio/gpiolib.c:?) [ 58.049450][ T1] gpiod_hog (drivers/gpio/gpiolib.c:4519) [ 58.049901][ T1] of_gpiochip_add_hog (drivers/gpio/gpiolib-of.c:799) [ 58.050433][ T1] of_gpiochip_add (drivers/gpio/gpiolib-of.c:829 drivers/gpio/gpiolib-of.c:1144) [ 58.050933][ T1] gpiochip_add_data_with_key (drivers/gpio/gpiolib.c:1013) [ 58.051503][ T1] unittest_gpio_probe (drivers/of/unittest.c:1886) [ 58.052013][ T1] platform_probe (drivers/base/platform.c:1405) [ 58.052484][ T1] really_probe (drivers/base/dd.c:?) [ 58.052953][ T1] __driver_probe_device (drivers/base/dd.c:800) [ 58.053480][ T1] driver_probe_device (drivers/base/dd.c:830) [ 58.054001][ T1] __driver_attach (drivers/base/dd.c:1217) [ 58.054482][ T1] ? driver_attach (drivers/base/dd.c:1157) [ 58.054958][ T1] bus_for_each_dev (drivers/base/bus.c:367) [ 58.055451][ T1] driver_attach (drivers/base/dd.c:1233) [ 58.055908][ T1] ? driver_attach (drivers/base/dd.c:1157) [ 58.056386][ T1] bus_add_driver (drivers/base/bus.c:674) [ 58.056871][ T1] driver_register (drivers/base/driver.c:246) [ 58.057348][ T1] __platform_driver_register (drivers/base/platform.c:867) [ 58.057900][ T1] of_unittest_overlay_gpio (drivers/of/unittest.c:1969) [ 58.058450][ T1] of_unittest_overlay (drivers/of/unittest.c:3217) [ 58.058973][ T1] of_unittest (drivers/of/unittest.c:4129) [ 58.059476][ T1] do_one_initcall (init/main.c:1236) [ 58.059967][ T1] ? dt_alloc_memory (drivers/of/unittest.c:4080) [ 58.060472][ T1] ? kvm_sched_clock_read (arch/x86/kernel/kvmclock.c:91) [ 58.060994][ T1] ? sched_clock_noinstr (arch/x86/kernel/tsc.c:266) [ 58.061500][ T1] ? local_clock_noinstr (kernel/sched/clock.c:269 kernel/sched/clock.c:306) [ 58.062037][ T1] ? rcu_read_lock_any_held (kernel/rcu/update.c:386) [ 58.062580][ T1] ? __lock_acquire (kernel/locking/lockdep.c:3762) [ 58.063084][ T1] ? __lock_acquire (kernel/locking/lockdep.c:3762) [ 58.063595][ T1] ? kvm_sched_clock_read (arch/x86/kernel/kvmclock.c:91) [ 58.064122][ T1] ? sched_clock_noinstr (arch/x86/kernel/tsc.c:266) [ 58.064665][ T1] ? local_clock_noinstr (kernel/sched/clock.c:269 kernel/sched/clock.c:306) [ 58.065201][ T1] ? rcu_read_lock_any_held (kernel/rcu/update.c:386) [ 58.065742][ T1] ? __lock_acquire (kernel/locking/lockdep.c:3762) [ 58.066248][ T1] ? kvm_sched_clock_read (arch/x86/kernel/kvmclock.c:91) [ 58.066768][ T1] ? sched_clock_noinstr (arch/x86/kernel/tsc.c:266) [ 58.067271][ T1] ? local_clock_noinstr (kernel/sched/clock.c:269 kernel/sched/clock.c:306) [ 58.067805][ T1] ? local_clock (arch/x86/include/asm/preempt.h:84 kernel/sched/clock.c:316) [ 58.068268][ T1] ? irqtime_account_irq (kernel/sched/cputime.c:?) [ 58.068795][ T1] ? irqtime_account_delta (include/linux/seqlock.h:444 include/linux/seqlock.h:516 include/linux/u64_stats_sync.h:151 include/linux/u64_stats_sync.h:187 kernel/sched/cputime.c:46) [ 58.069333][ T1] ? trace_hardirqs_on (kernel/trace/trace_preemptirq.c:63) [ 58.069836][ T1] ? irqentry_exit (kernel/entry/common.c:?) [ 58.070341][ T1] ? common_interrupt (arch/x86/kernel/irq.c:247) [ 58.070842][ T1] ? asm_common_interrupt (arch/x86/entry/entry_32.S:640) [ 58.071388][ T1] ? strlen (arch/x86/lib/string_32.c:175) [ 58.071812][ T1] ? next_arg (lib/cmdline.c:273) [ 58.072278][ T1] ? parse_args (kernel/params.c:153) [ 58.072756][ T1] do_initcall_level (init/main.c:1297) [ 58.073247][ T1] ? rest_init (init/main.c:1433) [ 58.073693][ T1] do_initcalls (init/main.c:1311) [ 58.074142][ T1] ? rest_init (init/main.c:1433) [ 58.074585][ T1] do_basic_setup (init/main.c:1334) [ 58.075052][ T1] kernel_init_freeable (init/main.c:1555) [ 58.075573][ T1] kernel_init (init/main.c:1443) [ 58.076029][ T1] ret_from_fork (arch/x86/kernel/process.c:153) [ 58.076498][ T1] ret_from_fork_asm (arch/x86/entry/entry_32.S:741) [ 58.076989][ T1] entry_INT80_32 (arch/x86/entry/entry_32.S:947) [ 58.077544][ T1] gpio-514 (line-B-input): hogged as input [ 58.078433][ T1] BUG: unable to handle page fault for address: ffffffff [ 58.079116][ T1] #PF: supervisor read access in kernel mode [ 58.079703][ T1] #PF: error_code(0x0000) - not-present page [ 58.080316][ T1] *pde = 02e00067 *pte = 00000000 [ 58.080829][ T1] Oops: 0000 [#1] [ 58.081210][ T1] CPU: 0 PID: 1 Comm: swapper Tainted: G TN 6.8.0-rc4-00057-gef4aabaa3721 #1 10e84cefff2a9bf1626b34c75cc7b6c846de4a3a [ 58.082492][ T1] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014 [ 58.083471][ T1] EIP: gpiolib_cdev_register (drivers/gpio/gpiolib-cdev.c:2802) [ 58.084015][ T1] Code: ec e8 7a 10 00 00 89 f8 89 da e8 c1 c8 a5 ff 89 f0 83 c4 0c 5e 5f 5b 5d 31 c9 31 d2 c3 8b 45 f0 c1 e8 14 ff b7 d8 01 00 00 50 <ff> 35 ff ff ff ff 68 7c de 5c c2 ff 35 03 00 00 00 68 3d ad 57 c2 All code ======== 0: ec in (%dx),%al 1: e8 7a 10 00 00 call 0x1080 6: 89 f8 mov %edi,%eax 8: 89 da mov %ebx,%edx a: e8 c1 c8 a5 ff call 0xffffffffffa5c8d0 f: 89 f0 mov %esi,%eax 11: 83 c4 0c add $0xc,%esp 14: 5e pop %rsi 15: 5f pop %rdi 16: 5b pop %rbx 17: 5d pop %rbp 18: 31 c9 xor %ecx,%ecx 1a: 31 d2 xor %edx,%edx 1c: c3 ret 1d: 8b 45 f0 mov -0x10(%rbp),%eax 20: c1 e8 14 shr $0x14,%eax 23: ff b7 d8 01 00 00 push 0x1d8(%rdi) 29: 50 push %rax 2a:* ff 35 ff ff ff ff push -0x1(%rip) # 0x2f <-- trapping instruction 30: 68 7c de 5c c2 push $0xffffffffc25cde7c 35: ff 35 03 00 00 00 push 0x3(%rip) # 0x3e 3b: 68 3d ad 57 c2 push $0xffffffffc257ad3d Code starting with the faulting instruction =========================================== 0: ff 35 ff ff ff ff push -0x1(%rip) # 0x5 6: 68 7c de 5c c2 push $0xffffffffc25cde7c b: ff 35 03 00 00 00 push 0x3(%rip) # 0x14 11: 68 3d ad 57 c2 push $0xffffffffc257ad3d [ 58.085813][ T1] EAX: 000000fe EBX: 00000000 ECX: 00000000 EDX: 00000000 [ 58.086476][ T1] ESI: ffffffed EDI: eb682c00 EBP: c3e1baec ESP: c3e1bacc [ 58.087140][ T1] DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 0068 EFLAGS: 00010202 [ 58.087927][ T1] CR0: 80050033 CR2: ffffffff CR3: 02dfd000 CR4: 000406d0 [ 58.088601][ T1] Call Trace: [ 58.088950][ T1] ? __die_body (arch/x86/kernel/dumpstack.c:478 arch/x86/kernel/dumpstack.c:420) [ 58.089388][ T1] ? __die (arch/x86/kernel/dumpstack.c:434) [ 58.089790][ T1] ? page_fault_oops (arch/x86/mm/fault.c:703) [ 58.090279][ T1] ? kernelmode_fixup_or_oops (arch/x86/mm/fault.c:761) [ 58.090815][ T1] ? __bad_area_nosemaphore (arch/x86/mm/fault.c:817) [ 58.091344][ T1] ? bad_area_nosemaphore (arch/x86/mm/fault.c:866) [ 58.091846][ T1] ? do_kern_addr_fault (arch/x86/mm/fault.c:1226) [ 58.092347][ T1] ? exc_page_fault (arch/x86/mm/fault.c:?) [ 58.092822][ T1] ? pvclock_clocksource_read_nowd (arch/x86/mm/fault.c:1520) [ 58.093407][ T1] ? handle_exception (arch/x86/entry/entry_32.S:1049) [ 58.093964][ T1] ? pvclock_clocksource_read_nowd (arch/x86/mm/fault.c:1520) [ 58.094556][ T1] ? gpiolib_cdev_register (drivers/gpio/gpiolib-cdev.c:2802) [ 58.095076][ T1] ? pvclock_clocksource_read_nowd (arch/x86/mm/fault.c:1520) [ 58.095666][ T1] ? gpiolib_cdev_register (drivers/gpio/gpiolib-cdev.c:2802) [ 58.096187][ T1] gpiochip_setup_dev (drivers/gpio/gpiolib.c:740) [ 58.096665][ T1] gpiochip_add_data_with_key (drivers/gpio/gpiolib.c:1047) [ 58.099219][ T1] unittest_gpio_probe (drivers/of/unittest.c:1886) [ 58.099744][ T1] platform_probe (drivers/base/platform.c:1405) [ 58.100210][ T1] really_probe (drivers/base/dd.c:?) [ 58.100662][ T1] __driver_probe_device (drivers/base/dd.c:800) [ 58.101172][ T1] driver_probe_device (drivers/base/dd.c:830) [ 58.101667][ T1] __driver_attach (drivers/base/dd.c:1217) [ 58.102131][ T1] ? driver_attach (drivers/base/dd.c:1157) [ 58.102587][ T1] bus_for_each_dev (drivers/base/bus.c:367) [ 58.103061][ T1] driver_attach (drivers/base/dd.c:1233) [ 58.103505][ T1] ? driver_attach (drivers/base/dd.c:1157) [ 58.103962][ T1] bus_add_driver (drivers/base/bus.c:674) [ 58.104431][ T1] driver_register (drivers/base/driver.c:246) [ 58.104902][ T1] __platform_driver_register (drivers/base/platform.c:867) [ 58.105443][ T1] of_unittest_overlay_gpio (drivers/of/unittest.c:1969) [ 58.105976][ T1] of_unittest_overlay (drivers/of/unittest.c:3217) [ 58.106475][ T1] of_unittest (drivers/of/unittest.c:4129) [ 58.106911][ T1] do_one_initcall (init/main.c:1236) [ 58.107384][ T1] ? dt_alloc_memory (drivers/of/unittest.c:4080) [ 58.107860][ T1] ? kvm_sched_clock_read (arch/x86/kernel/kvmclock.c:91) [ 58.108367][ T1] ? sched_clock_noinstr (arch/x86/kernel/tsc.c:266) [ 58.108853][ T1] ? local_clock_noinstr (kernel/sched/clock.c:269 kernel/sched/clock.c:306) [ 58.109364][ T1] ? rcu_read_lock_any_held (kernel/rcu/update.c:386) [ 58.109889][ T1] ? __lock_acquire (kernel/locking/lockdep.c:3762) [ 58.110377][ T1] ? __lock_acquire (kernel/locking/lockdep.c:3762) [ 58.110926][ T1] ? kvm_sched_clock_read (arch/x86/kernel/kvmclock.c:91) [ 58.111428][ T1] ? sched_clock_noinstr (arch/x86/kernel/tsc.c:266) [ 58.111917][ T1] ? local_clock_noinstr (kernel/sched/clock.c:269 kernel/sched/clock.c:306) [ 58.112441][ T1] ? rcu_read_lock_any_held (kernel/rcu/update.c:386) [ 58.112964][ T1] ? __lock_acquire (kernel/locking/lockdep.c:3762) [ 58.113450][ T1] ? kvm_sched_clock_read (arch/x86/kernel/kvmclock.c:91) [ 58.113964][ T1] ? sched_clock_noinstr (arch/x86/kernel/tsc.c:266) [ 58.114454][ T1] ? local_clock_noinstr (kernel/sched/clock.c:269 kernel/sched/clock.c:306) [ 58.114963][ T1] ? local_clock (arch/x86/include/asm/preempt.h:84 kernel/sched/clock.c:316) [ 58.115399][ T1] ? irqtime_account_irq (kernel/sched/cputime.c:?) [ 58.115903][ T1] ? irqtime_account_delta (include/linux/seqlock.h:444 include/linux/seqlock.h:516 include/linux/u64_stats_sync.h:151 include/linux/u64_stats_sync.h:187 kernel/sched/cputime.c:46) [ 58.116430][ T1] ? trace_hardirqs_on (kernel/trace/trace_preemptirq.c:63) [ 58.116929][ T1] ? irqentry_exit (kernel/entry/common.c:?) [ 58.117391][ T1] ? common_interrupt (arch/x86/kernel/irq.c:247) [ 58.117869][ T1] ? asm_common_interrupt (arch/x86/entry/entry_32.S:640) [ 58.118390][ T1] ? strlen (arch/x86/lib/string_32.c:175) [ 58.118799][ T1] ? next_arg (lib/cmdline.c:273) [ 58.119238][ T1] ? parse_args (kernel/params.c:153) [ 58.119689][ T1] do_initcall_level (init/main.c:1297) [ 58.120167][ T1] ? rest_init (init/main.c:1433) [ 58.120596][ T1] do_initcalls (init/main.c:1311) [ 58.121033][ T1] ? rest_init (init/main.c:1433) [ 58.121460][ T1] do_basic_setup (init/main.c:1334) [ 58.121908][ T1] kernel_init_freeable (init/main.c:1555) [ 58.122401][ T1] kernel_init (init/main.c:1443) [ 58.122873][ T1] ret_from_fork (arch/x86/kernel/process.c:153) [ 58.123330][ T1] ret_from_fork_asm (arch/x86/entry/entry_32.S:741) [ 58.123804][ T1] entry_INT80_32 (arch/x86/entry/entry_32.S:947) [ 58.124281][ T1] Modules linked in: [ 58.124686][ T1] CR2: 00000000ffffffff [ 58.125108][ T1] ---[ end trace 0000000000000000 ]--- [ 58.125635][ T1] EIP: gpiolib_cdev_register (drivers/gpio/gpiolib-cdev.c:2802) [ 58.126171][ T1] Code: ec e8 7a 10 00 00 89 f8 89 da e8 c1 c8 a5 ff 89 f0 83 c4 0c 5e 5f 5b 5d 31 c9 31 d2 c3 8b 45 f0 c1 e8 14 ff b7 d8 01 00 00 50 <ff> 35 ff ff ff ff 68 7c de 5c c2 ff 35 03 00 00 00 68 3d ad 57 c2 All code ======== 0: ec in (%dx),%al 1: e8 7a 10 00 00 call 0x1080 6: 89 f8 mov %edi,%eax 8: 89 da mov %ebx,%edx a: e8 c1 c8 a5 ff call 0xffffffffffa5c8d0 f: 89 f0 mov %esi,%eax 11: 83 c4 0c add $0xc,%esp 14: 5e pop %rsi 15: 5f pop %rdi 16: 5b pop %rbx 17: 5d pop %rbp 18: 31 c9 xor %ecx,%ecx 1a: 31 d2 xor %edx,%edx 1c: c3 ret 1d: 8b 45 f0 mov -0x10(%rbp),%eax 20: c1 e8 14 shr $0x14,%eax 23: ff b7 d8 01 00 00 push 0x1d8(%rdi) 29: 50 push %rax 2a:* ff 35 ff ff ff ff push -0x1(%rip) # 0x2f <-- trapping instruction 30: 68 7c de 5c c2 push $0xffffffffc25cde7c 35: ff 35 03 00 00 00 push 0x3(%rip) # 0x3e 3b: 68 3d ad 57 c2 push $0xffffffffc257ad3d Code starting with the faulting instruction =========================================== 0: ff 35 ff ff ff ff push -0x1(%rip) # 0x5 6: 68 7c de 5c c2 push $0xffffffffc25cde7c b: ff 35 03 00 00 00 push 0x3(%rip) # 0x14 11: 68 3d ad 57 c2 push $0xffffffffc257ad3d The kernel config and materials to reproduce are available at: https://download.01.org/0day-ci/archive/20240226/202402262225.50983057-lkp@intel.com
On Mon, Feb 26, 2024 at 3:28 PM kernel test robot <oliver.sang@intel.com> wrote: > > > > Hello, > > kernel test robot noticed "BUG:unable_to_handle_page_fault_for_address" on: > > commit: ef4aabaa372144b2bfa9c4ddc83255831cff9ebd ("[PATCH v2 2/4] gpio: cdev: use correct pointer accessors with SRCU") > url: https://github.com/intel-lab-lkp/linux/commits/Bartosz-Golaszewski/gpio-take-the-SRCU-read-lock-in-gpiod_hog/20240214-164752 > base: https://git.kernel.org/cgit/linux/kernel/git/brgl/linux.git gpio/for-next > patch link: https://lore.kernel.org/all/20240214084419.6194-3-brgl@bgdev.pl/ > patch subject: [PATCH v2 2/4] gpio: cdev: use correct pointer accessors with SRCU > > in testcase: boot > > compiler: clang-17 > test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G > > (please refer to attached dmesg/kmsg for entire log/backtrace) > Please disregard this one, the issue is fixed in patch 3/4 which is already in next. Bart
diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 9323b357df43..85037fa4925e 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -206,7 +206,7 @@ static long linehandle_ioctl(struct file *file, unsigned int cmd, guard(srcu)(&lh->gdev->srcu); - if (!rcu_dereference(lh->gdev->chip)) + if (!rcu_access_pointer(lh->gdev->chip)) return -ENODEV; switch (cmd) { @@ -1521,7 +1521,7 @@ static long linereq_ioctl(struct file *file, unsigned int cmd, guard(srcu)(&lr->gdev->srcu); - if (!rcu_dereference(lr->gdev->chip)) + if (!rcu_access_pointer(lr->gdev->chip)) return -ENODEV; switch (cmd) { @@ -1552,7 +1552,7 @@ static __poll_t linereq_poll(struct file *file, guard(srcu)(&lr->gdev->srcu); - if (!rcu_dereference(lr->gdev->chip)) + if (!rcu_access_pointer(lr->gdev->chip)) return EPOLLHUP | EPOLLERR; poll_wait(file, &lr->wait, wait); @@ -1574,7 +1574,7 @@ static ssize_t linereq_read(struct file *file, char __user *buf, guard(srcu)(&lr->gdev->srcu); - if (!rcu_dereference(lr->gdev->chip)) + if (!rcu_access_pointer(lr->gdev->chip)) return -ENODEV; if (count < sizeof(le)) @@ -1875,7 +1875,7 @@ static __poll_t lineevent_poll(struct file *file, guard(srcu)(&le->gdev->srcu); - if (!rcu_dereference(le->gdev->chip)) + if (!rcu_access_pointer(le->gdev->chip)) return EPOLLHUP | EPOLLERR; poll_wait(file, &le->wait, wait); @@ -1913,7 +1913,7 @@ static ssize_t lineevent_read(struct file *file, char __user *buf, guard(srcu)(&le->gdev->srcu); - if (!rcu_dereference(le->gdev->chip)) + if (!rcu_access_pointer(le->gdev->chip)) return -ENODEV; /* @@ -1996,7 +1996,7 @@ static long lineevent_ioctl(struct file *file, unsigned int cmd, guard(srcu)(&le->gdev->srcu); - if (!rcu_dereference(le->gdev->chip)) + if (!rcu_access_pointer(le->gdev->chip)) return -ENODEV; /* @@ -2510,7 +2510,7 @@ static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) guard(srcu)(&gdev->srcu); /* We fail any subsequent ioctl():s when the chip is gone */ - if (!rcu_dereference(gdev->chip)) + if (!rcu_access_pointer(gdev->chip)) return -ENODEV; /* Fill in the struct and pass to userspace */ @@ -2595,7 +2595,7 @@ static __poll_t lineinfo_watch_poll(struct file *file, guard(srcu)(&cdev->gdev->srcu); - if (!rcu_dereference(cdev->gdev->chip)) + if (!rcu_access_pointer(cdev->gdev->chip)) return EPOLLHUP | EPOLLERR; poll_wait(file, &cdev->wait, pollt); @@ -2618,7 +2618,7 @@ static ssize_t lineinfo_watch_read(struct file *file, char __user *buf, guard(srcu)(&cdev->gdev->srcu); - if (!rcu_dereference(cdev->gdev->chip)) + if (!rcu_access_pointer(cdev->gdev->chip)) return -ENODEV; #ifndef CONFIG_GPIO_CDEV_V1 @@ -2696,7 +2696,7 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file) guard(srcu)(&gdev->srcu); /* Fail on open if the backing gpiochip is gone */ - if (!rcu_dereference(gdev->chip)) + if (!rcu_access_pointer(gdev->chip)) return -ENODEV; cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); @@ -2796,8 +2796,7 @@ int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt) guard(srcu)(&gdev->srcu); - gc = rcu_dereference(gdev->chip); - if (!gc) + if (!rcu_access_pointer(gdev->chip)) return -ENODEV; chip_dbg(gc, "added GPIO chardev (%d:%d)\n", MAJOR(devt), gdev->id);