aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2008-08-25 01:29:38 +0000
committerBen Elliston <bje@au.ibm.com>2008-08-25 01:29:38 +0000
commit6fd1a617c27239058fd06aa4da81c48c4506fa5e (patch)
tree5ff002cab95157a66601fbb1250c1f4c33e2e282
parent325cb4d4afbfa7d4f6a4cd26bd6d7fd027f2b81c (diff)
* gcc/config/spu/cachemgr.c: Make interrupt safe and respect tag
mask policy. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/cell-4_3-branch@139555 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--ChangeLog.cell5
-rw-r--r--gcc/config/spu/cachemgr.c44
2 files changed, 44 insertions, 5 deletions
diff --git a/ChangeLog.cell b/ChangeLog.cell
index 811020bd66a..11ec3eddc03 100644
--- a/ChangeLog.cell
+++ b/ChangeLog.cell
@@ -1,3 +1,8 @@
+2008-08-25 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * gcc/config/spu/cachemgr.c: Make interrupt safe and respect tag
+ mask policy.
+
2008-08-20 Ben Elliston <bje@au.ibm.com>
Backport from FSF mainline:
diff --git a/gcc/config/spu/cachemgr.c b/gcc/config/spu/cachemgr.c
index d2e87ea69f2..96d6e821a84 100644
--- a/gcc/config/spu/cachemgr.c
+++ b/gcc/config/spu/cachemgr.c
@@ -121,16 +121,28 @@ __cache_evict_entry (struct __cache_tag_array *entry, int way)
if ((CHECK_DIRTY (entry->dirty_bits[way])) && (!CHECK_IS_LS (entry, way)))
{
-/* Non-atomic writes. */
#ifdef NONATOMIC
+ /* Non-atomic writes. */
+ unsigned int oldmask, mach_stat;
char *line = ((void *) 0);
+ /* Enter critical section. */
+ mach_stat = spu_readch (SPU_RdMachStat);
+ spu_idisable ();
+
+ /* Issue DMA request. */
line = GET_CACHE_LINE (entry->tag_lo[way], way);
mfc_put (line, tag, LINE_SIZE, dma_tag, 0, 0);
/* Wait for DMA completion. */
+ oldmask = mfc_read_tag_mask ();
mfc_write_tag_mask (1 << dma_tag);
mfc_read_tag_status_all ();
+ mfc_write_tag_mask (oldmask);
+
+ /* Leave critical section. */
+ if (__builtin_expect (mach_stat & 1, 0))
+ spu_ienable ();
#else
/* Allocate a buffer large enough that we know it has 128 bytes
that are 128 byte aligned (for DMA). */
@@ -139,6 +151,11 @@ __cache_evict_entry (struct __cache_tag_array *entry, int way)
qword *buf_ptr = (qword *) (((unsigned int) (buffer) + 127) & ~127);
qword *line = GET_CACHE_LINE (entry->tag_lo[way], way);
qword bits;
+ unsigned int mach_stat;
+
+ /* Enter critical section. */
+ mach_stat = spu_readch (SPU_RdMachStat);
+ spu_idisable ();
do
{
@@ -183,6 +200,10 @@ __cache_evict_entry (struct __cache_tag_array *entry, int way)
mfc_putllc (buf_ptr, tag, 0, 0);
}
while (mfc_read_atomic_status ());
+
+ /* Leave critical section. */
+ if (__builtin_expect (mach_stat & 1, 0))
+ spu_ienable ();
#endif
}
@@ -213,18 +234,31 @@ __cache_evict (__ea void *ea)
static void *
__cache_fill (int way, addr tag)
{
+ unsigned int oldmask, mach_stat;
char *line = ((void *) 0);
- line = GET_CACHE_LINE (tag, way);
-
- /* This will use DMA to fill the cache line. */
-
+ /* Reserve our DMA tag. */
if (dma_tag == 32)
dma_tag = mfc_tag_reserve ();
+ /* Enter critical section. */
+ mach_stat = spu_readch (SPU_RdMachStat);
+ spu_idisable ();
+
+ /* Issue DMA request. */
+ line = GET_CACHE_LINE (tag, way);
mfc_get (line, tag, LINE_SIZE, dma_tag, 0, 0);
+
+ /* Wait for DMA completion. */
+ oldmask = mfc_read_tag_mask ();
mfc_write_tag_mask (1 << dma_tag);
mfc_read_tag_status_all ();
+ mfc_write_tag_mask (oldmask);
+
+ /* Leave critical section. */
+ if (__builtin_expect (mach_stat & 1, 0))
+ spu_ienable ();
+
return (void *) line;
}