diff options
author | Jack Steiner <steiner@sgi.com> | 2009-12-16 01:48:11 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 16:20:15 +0100 |
commit | 67bf04a5c2574e9495f660f418f6df776821d578 (patch) | |
tree | ff28ab4983b007136da88786c8966ea1598841a0 /drivers/misc/sgi-gru/grumain.c | |
parent | gru: check for valid vma (diff) | |
download | linux-67bf04a5c2574e9495f660f418f6df776821d578.tar.xz linux-67bf04a5c2574e9495f660f418f6df776821d578.zip |
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 '')
-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, memset(cbe + i * GRU_HANDLE_STRIDE, 0, GRU_CACHE_LINE_BYTES); } + /* Flush CBE to hide race in context restart */ + mb(); + gru_flush_cache(cbe + i * GRU_HANDLE_STRIDE); cb += GRU_HANDLE_STRIDE; } @@ -519,6 +522,12 @@ static void gru_unload_context_data(void *save, void *grubase, int ctxnum, cb = gseg + GRU_CB_BASE; cbe = grubase + GRU_CBE_BASE; length = hweight64(dsrmap) * GRU_DSR_AU_BYTES; + + /* CBEs may not be coherent. Flush them from cache */ + for_each_cbr_in_allocation_map(i, &cbrmap, scr) + gru_flush_cache(cbe + i * GRU_HANDLE_STRIDE); + mb(); /* Let the CL flush complete */ + gru_prefetch_context(gseg, cb, cbe, cbrmap, length); for_each_cbr_in_allocation_map(i, &cbrmap, scr) { |