diff options
| author | David S. Miller <davem@davemloft.net> | 2005-08-29 15:46:22 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2005-08-29 15:46:22 -0400 |
| commit | 4f07118f656c179740cad35b827032e2e29b1210 (patch) | |
| tree | 7ddeb17346fe25ae75aa5373659c053afb9ef5f5 /arch/sparc64/lib | |
| parent | 442464a50077ff00454ff8d7628cbe1b8eacc034 (diff) | |
[SPARC64]: More fully work around Spitfire Errata 51.
It appears that a memory barrier soon after a mispredicted
branch, not just in the delay slot, can cause the hang
condition of this cpu errata.
So move them out-of-line, and explicitly put them into
a "branch always, predict taken" delay slot which should
fully kill this problem.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/lib')
| -rw-r--r-- | arch/sparc64/lib/Makefile | 2 | ||||
| -rw-r--r-- | arch/sparc64/lib/debuglocks.c | 16 | ||||
| -rw-r--r-- | arch/sparc64/lib/mb.S | 73 |
3 files changed, 82 insertions, 9 deletions
diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile index 40dbeec7e5d6..6201f1040982 100644 --- a/arch/sparc64/lib/Makefile +++ b/arch/sparc64/lib/Makefile | |||
| @@ -12,7 +12,7 @@ lib-y := PeeCeeI.o copy_page.o clear_page.o strlen.o strncmp.o \ | |||
| 12 | U1memcpy.o U1copy_from_user.o U1copy_to_user.o \ | 12 | U1memcpy.o U1copy_from_user.o U1copy_to_user.o \ |
| 13 | U3memcpy.o U3copy_from_user.o U3copy_to_user.o U3patch.o \ | 13 | U3memcpy.o U3copy_from_user.o U3copy_to_user.o U3patch.o \ |
| 14 | copy_in_user.o user_fixup.o memmove.o \ | 14 | copy_in_user.o user_fixup.o memmove.o \ |
| 15 | mcount.o ipcsum.o rwsem.o xor.o find_bit.o delay.o | 15 | mcount.o ipcsum.o rwsem.o xor.o find_bit.o delay.o mb.o |
| 16 | 16 | ||
| 17 | lib-$(CONFIG_DEBUG_SPINLOCK) += debuglocks.o | 17 | lib-$(CONFIG_DEBUG_SPINLOCK) += debuglocks.o |
| 18 | lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o | 18 | lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o |
diff --git a/arch/sparc64/lib/debuglocks.c b/arch/sparc64/lib/debuglocks.c index 7f6ccc4114c5..f5f0b5586f01 100644 --- a/arch/sparc64/lib/debuglocks.c +++ b/arch/sparc64/lib/debuglocks.c | |||
| @@ -61,7 +61,7 @@ again: | |||
| 61 | : "=r" (val) | 61 | : "=r" (val) |
| 62 | : "r" (&(lock->lock)) | 62 | : "r" (&(lock->lock)) |
| 63 | : "memory"); | 63 | : "memory"); |
| 64 | membar("#StoreLoad | #StoreStore"); | 64 | membar_storeload_storestore(); |
| 65 | if (val) { | 65 | if (val) { |
| 66 | while (lock->lock) { | 66 | while (lock->lock) { |
| 67 | if (!--stuck) { | 67 | if (!--stuck) { |
| @@ -69,7 +69,7 @@ again: | |||
| 69 | show(str, lock, caller); | 69 | show(str, lock, caller); |
| 70 | stuck = INIT_STUCK; | 70 | stuck = INIT_STUCK; |
| 71 | } | 71 | } |
| 72 | membar("#LoadLoad"); | 72 | rmb(); |
| 73 | } | 73 | } |
| 74 | goto again; | 74 | goto again; |
| 75 | } | 75 | } |
| @@ -90,7 +90,7 @@ int _do_spin_trylock(spinlock_t *lock, unsigned long caller) | |||
| 90 | : "=r" (val) | 90 | : "=r" (val) |
| 91 | : "r" (&(lock->lock)) | 91 | : "r" (&(lock->lock)) |
| 92 | : "memory"); | 92 | : "memory"); |
| 93 | membar("#StoreLoad | #StoreStore"); | 93 | membar_storeload_storestore(); |
| 94 | if (!val) { | 94 | if (!val) { |
| 95 | lock->owner_pc = ((unsigned int)caller); | 95 | lock->owner_pc = ((unsigned int)caller); |
| 96 | lock->owner_cpu = cpu; | 96 | lock->owner_cpu = cpu; |
| @@ -107,7 +107,7 @@ void _do_spin_unlock(spinlock_t *lock) | |||
| 107 | { | 107 | { |
| 108 | lock->owner_pc = 0; | 108 | lock->owner_pc = 0; |
| 109 | lock->owner_cpu = NO_PROC_ID; | 109 | lock->owner_cpu = NO_PROC_ID; |
| 110 | membar("#StoreStore | #LoadStore"); | 110 | membar_storestore_loadstore(); |
| 111 | lock->lock = 0; | 111 | lock->lock = 0; |
| 112 | current->thread.smp_lock_count--; | 112 | current->thread.smp_lock_count--; |
| 113 | } | 113 | } |
| @@ -129,7 +129,7 @@ wlock_again: | |||
| 129 | show_read(str, rw, caller); | 129 | show_read(str, rw, caller); |
| 130 | stuck = INIT_STUCK; | 130 | stuck = INIT_STUCK; |
| 131 | } | 131 | } |
| 132 | membar("#LoadLoad"); | 132 | rmb(); |
| 133 | } | 133 | } |
| 134 | /* Try once to increment the counter. */ | 134 | /* Try once to increment the counter. */ |
| 135 | __asm__ __volatile__( | 135 | __asm__ __volatile__( |
| @@ -142,7 +142,7 @@ wlock_again: | |||
| 142 | "2:" : "=r" (val) | 142 | "2:" : "=r" (val) |
| 143 | : "0" (&(rw->lock)) | 143 | : "0" (&(rw->lock)) |
| 144 | : "g1", "g7", "memory"); | 144 | : "g1", "g7", "memory"); |
| 145 | membar("#StoreLoad | #StoreStore"); | 145 | membar_storeload_storestore(); |
| 146 | if (val) | 146 | if (val) |
| 147 | goto wlock_again; | 147 | goto wlock_again; |
| 148 | rw->reader_pc[cpu] = ((unsigned int)caller); | 148 | rw->reader_pc[cpu] = ((unsigned int)caller); |
| @@ -201,7 +201,7 @@ wlock_again: | |||
| 201 | show_write(str, rw, caller); | 201 | show_write(str, rw, caller); |
| 202 | stuck = INIT_STUCK; | 202 | stuck = INIT_STUCK; |
| 203 | } | 203 | } |
| 204 | membar("#LoadLoad"); | 204 | rmb(); |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | /* Try to acuire the write bit. */ | 207 | /* Try to acuire the write bit. */ |
| @@ -256,7 +256,7 @@ wlock_again: | |||
| 256 | show_write(str, rw, caller); | 256 | show_write(str, rw, caller); |
| 257 | stuck = INIT_STUCK; | 257 | stuck = INIT_STUCK; |
| 258 | } | 258 | } |
| 259 | membar("#LoadLoad"); | 259 | rmb(); |
| 260 | } | 260 | } |
| 261 | goto wlock_again; | 261 | goto wlock_again; |
| 262 | } | 262 | } |
diff --git a/arch/sparc64/lib/mb.S b/arch/sparc64/lib/mb.S new file mode 100644 index 000000000000..4004f748619f --- /dev/null +++ b/arch/sparc64/lib/mb.S | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | /* mb.S: Out of line memory barriers. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2005 David S. Miller (davem@davemloft.net) | ||
| 4 | */ | ||
| 5 | |||
| 6 | /* These are here in an effort to more fully work around | ||
| 7 | * Spitfire Errata #51. Essentially, if a memory barrier | ||
| 8 | * occurs soon after a mispredicted branch, the chip can stop | ||
| 9 | * executing instructions until a trap occurs. Therefore, if | ||
| 10 | * interrupts are disabled, the chip can hang forever. | ||
| 11 | * | ||
| 12 | * It used to be believed that the memory barrier had to be | ||
| 13 | * right in the delay slot, but a case has been traced | ||
| 14 | * recently wherein the memory barrier was one instruction | ||
| 15 | * after the branch delay slot and the chip still hung. The | ||
| 16 | * offending sequence was the following in sym_wakeup_done() | ||
| 17 | * of the sym53c8xx_2 driver: | ||
| 18 | * | ||
| 19 | * call sym_ccb_from_dsa, 0 | ||
| 20 | * movge %icc, 0, %l0 | ||
| 21 | * brz,pn %o0, .LL1303 | ||
| 22 | * mov %o0, %l2 | ||
| 23 | * membar #LoadLoad | ||
| 24 | * | ||
| 25 | * The branch has to be mispredicted for the bug to occur. | ||
| 26 | * Therefore, we put the memory barrier explicitly into a | ||
| 27 | * "branch always, predicted taken" delay slot to avoid the | ||
| 28 | * problem case. | ||
| 29 | */ | ||
| 30 | |||
| 31 | .text | ||
| 32 | |||
| 33 | 99: retl | ||
| 34 | nop | ||
| 35 | |||
| 36 | .globl mb | ||
| 37 | mb: ba,pt %xcc, 99b | ||
| 38 | membar #LoadLoad | #LoadStore | #StoreStore | #StoreLoad | ||
| 39 | .size mb, .-mb | ||
| 40 | |||
| 41 | .globl rmb | ||
| 42 | rmb: ba,pt %xcc, 99b | ||
| 43 | membar #LoadLoad | ||
| 44 | .size rmb, .-rmb | ||
| 45 | |||
| 46 | .globl wmb | ||
| 47 | wmb: ba,pt %xcc, 99b | ||
| 48 | membar #StoreStore | ||
| 49 | .size wmb, .-wmb | ||
| 50 | |||
| 51 | .globl membar_storeload | ||
| 52 | membar_storeload: | ||
| 53 | ba,pt %xcc, 99b | ||
| 54 | membar #StoreLoad | ||
| 55 | .size membar_storeload, .-membar_storeload | ||
| 56 | |||
| 57 | .globl membar_storeload_storestore | ||
| 58 | membar_storeload_storestore: | ||
| 59 | ba,pt %xcc, 99b | ||
| 60 | membar #StoreLoad | #StoreStore | ||
| 61 | .size membar_storeload_storestore, .-membar_storeload_storestore | ||
| 62 | |||
| 63 | .globl membar_storeload_loadload | ||
| 64 | membar_storeload_loadload: | ||
| 65 | ba,pt %xcc, 99b | ||
| 66 | membar #StoreLoad | #LoadLoad | ||
| 67 | .size membar_storeload_loadload, .-membar_storeload_loadload | ||
| 68 | |||
| 69 | .globl membar_storestore_loadstore | ||
| 70 | membar_storestore_loadstore: | ||
| 71 | ba,pt %xcc, 99b | ||
| 72 | membar #StoreStore | #LoadStore | ||
| 73 | .size membar_storestore_loadstore, .-membar_storestore_loadstore | ||
