summaryrefslogtreecommitdiff
path: root/cesar/hal
diff options
context:
space:
mode:
authorOlivier Dufour2013-01-07 16:23:28 +0100
committerOlivier Dufour2013-01-14 14:52:33 +0100
commit7d6572abc93fc41b0c5b247250b40dfc9dcb2eec (patch)
treea770f522026ad6cf3e5971d09074a1ace7d2b1cb /cesar/hal
parent4f0b396281407b880956a040c21af2006c5c4130 (diff)
cesar/hal/arch/dlink: do not flush memory cache in local ram, closes #3652
SPARC Architecture Manual Version 8, appendix G.7 strongly advises to call flush after modifying an instruction in memory. The flush instruction will discard two words at least from the processor cache, starting at the adress given to the instruction. However this does not apply to non-cached memory, such as local ram. Moreover, in the specific case of local ram, it could insert a bug. Leon2 XST User's Manual, in section 4.7.1 states that write access to local ram must be word sized. Any other access will generate a data exception trap (0x09). The bug described in #3652 appears to be caused by the flush instruction when executed on a local ram address, as the DSU catched a 0x09 trap, and stalled the CPU, causing the Leon watchdog to expire and Linux to request a reboot.
Diffstat (limited to 'cesar/hal')
-rw-r--r--cesar/hal/arch/dlink/dlink.h4
-rw-r--r--cesar/hal/arch/dlink/src/dlink.c7
-rw-r--r--cesar/hal/arch/dlink/test/src/test_dlink_host.c2
-rw-r--r--cesar/hal/arch/dlink/test/src/test_dlink_sparc.c4
4 files changed, 11 insertions, 6 deletions
diff --git a/cesar/hal/arch/dlink/dlink.h b/cesar/hal/arch/dlink/dlink.h
index 38c8045ac3..1a0b1323ea 100644
--- a/cesar/hal/arch/dlink/dlink.h
+++ b/cesar/hal/arch/dlink/dlink.h
@@ -44,6 +44,7 @@ hal_arch_dlink_copy_ram_to_ilram (
* \param zb the begin zone to modify the call instruction
* \param ze the end zone to modify the call instruction
* \param zn the new zone base address to use
+ * \param do_flush do we need to flush data cache
*
* This function should modify the call instructions which points to an
* address function which has moved from RAM to ILRAM.
@@ -57,7 +58,8 @@ hal_arch_dlink_copy_ram_to_ilram (
void
hal_arch_dlink_patch_ram_call_inst (
unsigned long *sw, unsigned long *endw,
- unsigned long *zb, unsigned long *ze, unsigned long *zn);
+ unsigned long *zb, unsigned long *ze, unsigned long *zn,
+ bool do_flush);
/**
* Patch callbacks section
diff --git a/cesar/hal/arch/dlink/src/dlink.c b/cesar/hal/arch/dlink/src/dlink.c
index 377578ce4f..8144f99e3e 100644
--- a/cesar/hal/arch/dlink/src/dlink.c
+++ b/cesar/hal/arch/dlink/src/dlink.c
@@ -78,7 +78,7 @@ hal_arch_dlink_copy_ram_to_ilram (
void
hal_arch_dlink_patch_ram_call_inst (
unsigned long *sw, unsigned long *endw, unsigned long *zb,
- unsigned long *ze, unsigned long *zn)
+ unsigned long *ze, unsigned long *zn, bool do_flush)
{
unsigned long zone_offset = (unsigned long) zn - (unsigned long) zb;
unsigned long *addr;
@@ -101,7 +101,10 @@ hal_arch_dlink_patch_ram_call_inst (
addr_offset = zone_offset + addr_offset;
*sw = HAL_ARCH_DLINK_SPARC_CALL_OP_CODE
| (addr_offset >> HAL_ARCH_DLINK_IS_SPARC_CALL_INST_OFFSET);
- hal_arch_dlink_flush_addr (sw);
+ if (do_flush)
+ {
+ hal_arch_dlink_flush_addr (sw);
+ }
}
}
}
diff --git a/cesar/hal/arch/dlink/test/src/test_dlink_host.c b/cesar/hal/arch/dlink/test/src/test_dlink_host.c
index d9318a8f23..330538cf95 100644
--- a/cesar/hal/arch/dlink/test/src/test_dlink_host.c
+++ b/cesar/hal/arch/dlink/test/src/test_dlink_host.c
@@ -95,7 +95,7 @@ test_dlink_host_patch_ram_call_inst (test_t test)
*sw = 0x40000000 | ((offset + i * 4) >> 2);
}
/* Call the function. */
- hal_arch_dlink_patch_ram_call_inst (start, end, zb, ze, zn);
+ hal_arch_dlink_patch_ram_call_inst (start, end, zb, ze, zn, false);
/* verify. */
unsigned long addr;
for (sw = start; sw < end; sw++)
diff --git a/cesar/hal/arch/dlink/test/src/test_dlink_sparc.c b/cesar/hal/arch/dlink/test/src/test_dlink_sparc.c
index e089805eb6..3d5f35752d 100644
--- a/cesar/hal/arch/dlink/test/src/test_dlink_sparc.c
+++ b/cesar/hal/arch/dlink/test/src/test_dlink_sparc.c
@@ -90,11 +90,11 @@ test_case_dlink_sparc_ilram (test_t test)
/* Patch the TEXT call to the ILRAM2 section to the ILRAM section. */
hal_arch_dlink_patch_ram_call_inst (
- pstext, petext, ilram2_start, ilram2_end, ilram2_real_start);
+ pstext, petext, ilram2_start, ilram2_end, ilram2_real_start, true);
hal_arch_dlink_patch_ram_call_inst (
ilram_start, ilram_end, ilram2_start,
- ilram2_end, ilram2_real_start);
+ ilram2_end, ilram2_real_start, false);
hal_arch_dlink_patch_callbacks (
cb_start, cb_end, ilram2_start,