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/gruhandles.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/gruhandles.c')
-rw-r--r-- | drivers/misc/sgi-gru/gruhandles.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/drivers/misc/sgi-gru/gruhandles.c b/drivers/misc/sgi-gru/gruhandles.c index 806419a6b44c..f1117a7637a2 100644 --- a/drivers/misc/sgi-gru/gruhandles.c +++ b/drivers/misc/sgi-gru/gruhandles.c | |||
@@ -91,9 +91,18 @@ static int wait_instruction_complete(void *h, enum mcs_op opc) | |||
91 | 91 | ||
92 | int cch_allocate(struct gru_context_configuration_handle *cch) | 92 | int cch_allocate(struct gru_context_configuration_handle *cch) |
93 | { | 93 | { |
94 | int ret; | ||
95 | |||
94 | cch->opc = CCHOP_ALLOCATE; | 96 | cch->opc = CCHOP_ALLOCATE; |
95 | start_instruction(cch); | 97 | start_instruction(cch); |
96 | return wait_instruction_complete(cch, cchop_allocate); | 98 | ret = wait_instruction_complete(cch, cchop_allocate); |
99 | |||
100 | /* | ||
101 | * Stop speculation into the GSEG being mapped by the previous ALLOCATE. | ||
102 | * The GSEG memory does not exist until the ALLOCATE completes. | ||
103 | */ | ||
104 | sync_core(); | ||
105 | return ret; | ||
97 | } | 106 | } |
98 | 107 | ||
99 | int cch_start(struct gru_context_configuration_handle *cch) | 108 | int cch_start(struct gru_context_configuration_handle *cch) |
@@ -112,9 +121,18 @@ int cch_interrupt(struct gru_context_configuration_handle *cch) | |||
112 | 121 | ||
113 | int cch_deallocate(struct gru_context_configuration_handle *cch) | 122 | int cch_deallocate(struct gru_context_configuration_handle *cch) |
114 | { | 123 | { |
124 | int ret; | ||
125 | |||
115 | cch->opc = CCHOP_DEALLOCATE; | 126 | cch->opc = CCHOP_DEALLOCATE; |
116 | start_instruction(cch); | 127 | start_instruction(cch); |
117 | return wait_instruction_complete(cch, cchop_deallocate); | 128 | ret = wait_instruction_complete(cch, cchop_deallocate); |
129 | |||
130 | /* | ||
131 | * Stop speculation into the GSEG being unmapped by the previous | ||
132 | * DEALLOCATE. | ||
133 | */ | ||
134 | sync_core(); | ||
135 | return ret; | ||
118 | } | 136 | } |
119 | 137 | ||
120 | int cch_interrupt_sync(struct gru_context_configuration_handle | 138 | int cch_interrupt_sync(struct gru_context_configuration_handle |