diff options
author | Jack Steiner <steiner@sgi.com> | 2009-12-15 19:48:11 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 10:20:15 -0500 |
commit | 67bf04a5c2574e9495f660f418f6df776821d578 (patch) | |
tree | ff28ab4983b007136da88786c8966ea1598841a0 /drivers/misc/sgi-gru/grumain.c | |
parent | e006043a4d2da52bba9fd9cb7e5a22e2951ff69b (diff) |
gru: fix prefetch and speculation bugs
Fix several bugs related to prefetch, ordering & speculation:
- GRU cch_allocate() instruction causes cacheable memory
to be created. Add a barriers to prevent speculation
from prefetching data before it exists.
- Add memory barriers before cache-flush instructions to ensure
that previously stored data is included in the line flushed to memory.
Signed-off-by: Jack Steiner <steiner@sgi.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/misc/sgi-gru/grumain.c')
-rw-r--r-- | drivers/misc/sgi-gru/grumain.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c index 944028871884..a383271d3912 100644 --- a/drivers/misc/sgi-gru/grumain.c +++ b/drivers/misc/sgi-gru/grumain.c | |||
@@ -499,6 +499,9 @@ static void gru_load_context_data(void *save, void *grubase, int ctxnum, | |||
499 | memset(cbe + i * GRU_HANDLE_STRIDE, 0, | 499 | memset(cbe + i * GRU_HANDLE_STRIDE, 0, |
500 | GRU_CACHE_LINE_BYTES); | 500 | GRU_CACHE_LINE_BYTES); |
501 | } | 501 | } |
502 | /* Flush CBE to hide race in context restart */ | ||
503 | mb(); | ||
504 | gru_flush_cache(cbe + i * GRU_HANDLE_STRIDE); | ||
502 | cb += GRU_HANDLE_STRIDE; | 505 | cb += GRU_HANDLE_STRIDE; |
503 | } | 506 | } |
504 | 507 | ||
@@ -519,6 +522,12 @@ static void gru_unload_context_data(void *save, void *grubase, int ctxnum, | |||
519 | cb = gseg + GRU_CB_BASE; | 522 | cb = gseg + GRU_CB_BASE; |
520 | cbe = grubase + GRU_CBE_BASE; | 523 | cbe = grubase + GRU_CBE_BASE; |
521 | length = hweight64(dsrmap) * GRU_DSR_AU_BYTES; | 524 | length = hweight64(dsrmap) * GRU_DSR_AU_BYTES; |
525 | |||
526 | /* CBEs may not be coherent. Flush them from cache */ | ||
527 | for_each_cbr_in_allocation_map(i, &cbrmap, scr) | ||
528 | gru_flush_cache(cbe + i * GRU_HANDLE_STRIDE); | ||
529 | mb(); /* Let the CL flush complete */ | ||
530 | |||
522 | gru_prefetch_context(gseg, cb, cbe, cbrmap, length); | 531 | gru_prefetch_context(gseg, cb, cbe, cbrmap, length); |
523 | 532 | ||
524 | for_each_cbr_in_allocation_map(i, &cbrmap, scr) { | 533 | for_each_cbr_in_allocation_map(i, &cbrmap, scr) { |