Files
kernel_arpi/include/linux
Russell King 32385c7cf6 kernel: fix hlist_bl again
__d_rehash is dereferencing an almost-NULL pointer on my ARM926.
CONFIG_SMP=n and CONFIG_DEBUG_SPINLOCK=y.

The faulting instruction is:    strne   r3, [r2, #4]
and as can be seen from the register dump below, r2 is 0x00000001, hence
the faulting 0x00000005 address.

__d_rehash is essentially:

       spin_lock_bucket(b);
       entry->d_flags &= ~DCACHE_UNHASHED;
       hlist_bl_add_head_rcu(&entry->d_hash, &b->head);
       spin_unlock_bucket(b);

which is:

       bit_spin_lock(0, (unsigned long *)&b->head.first);
       entry->d_flags &= ~DCACHE_UNHASHED;
       hlist_bl_add_head_rcu(&entry->d_hash, &b->head);
       __bit_spin_unlock(0, (unsigned long *)&b->head.first);

bit_spin_lock(0, ptr) sets bit 0 of *ptr, in this case b->head.first if
CONFIG_SMP or CONFIG_DEBUG_SPINLOCK is set:

#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
       while (unlikely(test_and_set_bit_lock(bitnum, addr))) {
               while (test_bit(bitnum, addr)) {
                       preempt_enable();
                       cpu_relax();
                       preempt_disable();
               }
       }
#endif

So, b->head.first starts off NULL, and becomes a non-NULL (address 1).
hlist_bl_add_head_rcu() does this:

static inline void hlist_bl_add_head_rcu(struct hlist_bl_node *n,
                                       struct hlist_bl_head *h)
{
       first = hlist_bl_first(h);
       n->next = first;
       if (first)
               first->pprev = &n->next;

It is the store to first->pprev which is faulting.

hlist_bl_first():

static inline struct hlist_bl_node *hlist_bl_first(struct hlist_bl_head *h)
{
       return (struct hlist_bl_node *)
               ((unsigned long)h->first & ~LIST_BL_LOCKMASK);
}

but:
#if defined(CONFIG_SMP)
#define LIST_BL_LOCKMASK        1UL
#else
#define LIST_BL_LOCKMASK        0UL
#endif

So, we have one piece of code which sets bit 0 of addresses, and another
bit of code which doesn't clear it before dereferencing the pointer if
!CONFIG_SMP && CONFIG_DEBUG_SPINLOCK.  With the patch below, I can again
sucessfully boot the kernel on my Versatile PB/926 platform.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2011-01-14 13:12:45 +00:00
..
2010-11-15 20:44:26 -05:00
2010-10-30 08:31:35 -07:00
2008-02-06 10:41:02 -08:00
2010-10-15 21:18:59 +02:00
2010-12-11 01:28:58 -05:00
2009-09-08 17:42:50 -07:00
2010-10-30 08:45:43 -04:00
2005-04-16 15:20:36 -07:00
2010-11-10 14:54:09 +01:00
2008-06-06 11:29:10 -07:00
2010-11-10 14:54:09 +01:00
2009-01-04 13:33:20 -08:00
2010-12-13 16:11:13 -08:00
2005-04-16 15:20:36 -07:00
2010-10-25 21:18:20 -04:00
2009-06-11 21:36:09 -04:00
2005-04-16 15:20:36 -07:00
2009-01-30 23:44:08 +05:30
2005-04-16 15:20:36 -07:00
2010-10-25 08:02:40 -07:00
2005-04-16 15:20:36 -07:00
2005-04-16 15:20:36 -07:00
2011-01-07 17:50:32 +11:00
2010-05-19 22:41:57 -04:00
2010-08-04 11:00:45 +02:00
2007-05-08 11:15:26 -07:00
2007-02-09 17:39:36 -05:00
2009-11-04 09:50:58 -08:00
2010-10-22 15:55:22 +02:00
2010-10-21 14:47:59 +02:00
2009-01-30 23:46:40 +05:30
2008-01-28 23:21:18 +01:00
2009-11-04 09:50:58 -08:00
2010-09-23 14:33:39 -07:00
2010-11-17 14:55:45 +09:00
2011-01-07 17:50:27 +11:00
2011-01-07 17:50:31 +11:00
2011-01-07 17:50:23 +11:00
2010-09-09 20:46:30 +02:00
2010-07-12 14:41:40 +02:00
2006-10-02 07:57:12 -07:00
2010-10-25 14:11:37 -07:00
2010-10-23 22:49:32 +02:00
2010-03-07 22:17:09 +01:00
2010-10-12 16:53:37 +02:00
2010-11-15 22:40:38 +01:00
2010-11-15 22:40:38 +01:00
2009-11-04 09:50:58 -08:00
2010-09-21 18:04:47 -07:00
2010-02-02 07:32:29 -08:00
2008-08-02 18:36:10 +01:00
2010-09-30 21:16:05 -07:00
2010-10-26 16:52:08 -07:00
2005-04-16 15:20:36 -07:00
2010-03-12 15:52:40 -08:00
2009-04-21 13:41:48 -07:00
2006-10-04 00:31:09 -07:00
2009-01-30 23:59:44 +05:30
2010-10-07 14:08:55 +01:00
2010-08-10 11:49:21 -07:00
2010-10-28 17:22:13 -04:00
2010-10-22 15:34:12 -05:00
2010-08-19 17:18:00 -07:00
2010-05-21 09:37:29 -07:00
2010-09-09 18:57:24 -07:00
2010-12-22 10:27:53 +01:00
2005-04-16 15:20:36 -07:00
2010-11-12 07:55:32 -08:00
2010-11-16 13:33:23 -08:00
2007-07-17 10:23:03 -07:00
2011-01-14 13:12:45 +00:00
2010-10-25 21:24:15 -04:00
2009-04-28 07:37:28 +02:00
2010-06-16 18:03:15 +02:00
2010-10-28 09:08:47 -05:00
2010-08-09 16:48:45 -04:00
2007-05-09 12:30:49 -07:00
2009-09-22 07:17:35 -07:00
2009-06-16 08:40:20 +02:00
2010-10-26 16:52:05 -07:00
2011-01-07 17:50:33 +11:00
2006-11-30 04:40:22 +01:00
2008-06-06 11:29:12 -07:00
2010-10-12 16:53:34 +02:00
2011-01-07 17:50:27 +11:00
2010-10-04 21:10:52 +02:00
2011-01-07 17:50:19 +11:00
2010-10-07 18:48:49 -04:00
2010-08-19 17:18:02 -07:00
2010-10-15 12:45:44 +02:00
2009-04-01 08:59:13 -07:00
2005-04-16 15:20:36 -07:00
2011-01-07 17:50:33 +11:00
2010-10-17 20:03:03 -07:00
2010-10-17 20:03:06 -07:00
2005-04-16 15:20:36 -07:00
2010-10-24 15:07:11 -07:00
2009-01-08 08:31:12 -08:00
2006-10-03 23:01:26 +02:00
2008-06-11 21:00:38 -07:00
2009-06-18 13:04:04 -07:00
2009-07-29 19:10:36 -07:00
2010-11-12 07:55:32 -08:00
2010-10-29 04:16:31 -04:00
2010-02-10 17:47:17 -08:00
2011-01-14 02:36:43 +00:00
2010-09-08 18:16:55 -07:00
2008-01-30 13:31:47 +01:00
2010-10-27 18:03:16 -07:00
2010-03-12 15:53:10 -08:00
2011-01-07 17:50:27 +11:00
2010-10-30 12:12:50 +02:00
2011-01-07 17:50:27 +11:00
2008-02-07 08:42:34 -08:00
2010-10-20 03:02:23 -07:00
2010-10-27 17:28:36 +01:00
2005-04-16 15:20:36 -07:00
2010-10-07 14:08:55 +01:00
2007-05-08 11:15:18 -07:00
2010-09-24 21:27:41 -07:00
2010-01-14 22:38:09 -05:00
2005-04-16 15:20:36 -07:00
2010-05-15 23:28:39 -07:00
2008-10-13 09:51:40 -07:00
2009-02-18 15:37:53 -08:00
2010-10-21 04:11:07 -07:00
2009-10-29 11:17:40 +11:00
2010-10-22 10:20:04 -07:00
2010-10-26 16:52:03 -07:00
2005-04-16 15:20:36 -07:00
2007-12-26 19:36:35 -08:00
2010-05-19 22:15:46 +09:30
2010-10-26 16:52:14 -07:00