hwstub: add the possibility to flush caches before exec

This is needed on the jz4760b because if some data is loaded to DRAM, then it
is cached and a disaster lurks if dcaches/icache are not flushed. Targets that
needs this must define CONFIG_FLUSH_CACHES in target-config.h and implement
target_flush_caches(). Currently MIPS has some generic code for mips32r1 that
requires to define {D,I}CACHE_SIZE and {D,I}CACHE_LINE_SIZE in target-config.h

Change-Id: I5a3fc085de9445d8c8a2eb61ae4e2dc9bb6b4e8e
This commit is contained in:
Amaury Pouly 2016-08-02 15:18:41 +01:00
parent 83155f32bf
commit 56340f4cd0
4 changed files with 45 additions and 1 deletions

View file

@ -18,6 +18,7 @@
*
****************************************************************************/
#include "mips.h"
#include "target-config.h"
/* Handling of data abort:
* the code can register a "longjmp" buffer to restore the context in case of
@ -49,3 +50,27 @@ set_data_abort_jmp:
jr ra
move v0, zero
.set reorder
#ifdef CONFIG_FLUSH_CACHES
.set noreorder
.text
.global target_flush_caches
target_flush_caches:
/* commit dcache and invalidate icache */
la t0, 0x80000000 /* an idx op should use an unmappable address */
ori t1, t0, DCACHE_SIZE /* cache size */
reloc_dcache_loop:
cache DCIndexWBInv, 0(t0) /* invalidate and write-back dcache index */
addiu t0, t0, DCACHE_LINE_SIZE /* bytes per cache line */
bne t0, t1, reloc_dcache_loop
nop
la t0, 0x80000000 /* an idx op should use an unmappable address */
ori t1, t0, ICACHE_SIZE /* cache size */
reloc_icache_loop:
cache ICIndexInv, 0(t0) /* invalidate icache index */
addiu t0, t0, ICACHE_LINE_SIZE /* bytes per cache line */
bne t0, t1, reloc_icache_loop
nop
jr ra
nop
#endif

View file

@ -3,6 +3,12 @@
#define TCSM0_SIZE 0x4000
#define CPU_MIPS
#define STACK_SIZE 0x300
#define DCACHE_SIZE 0x4000 /* 16 kB */
#define DCACHE_LINE_SIZE 0x20 /* 32 B */
#define ICACHE_SIZE 0x4000 /* 16 kB */
#define ICACHE_LINE_SIZE 0x20 /* 32 B */
/* we need to flush caches before executing */
#define CONFIG_FLUSH_CACHES
/* something provides define
* #define mips 1

View file

@ -518,10 +518,17 @@ static void handle_exec(struct usb_ctrlrequest *req)
if(size != sizeof(struct hwstub_exec_req_t))
return usb_drv_stall(EP_CONTROL, true, true);
uint32_t addr = exec->dAddress;
#if defined(CPU_ARM)
if(exec->bmFlags & HWSTUB_EXEC_THUMB)
addr |= 1;
else
addr &= ~1;
#endif
#ifdef CONFIG_FLUSH_CACHES
target_flush_caches();
#endif
if(exec->bmFlags & HWSTUB_EXEC_CALL)
{
@ -540,11 +547,13 @@ static void handle_exec(struct usb_ctrlrequest *req)
else
{
/* in case of jump, respond immediately and disconnect usb */
#if defined(CPU_ARM)
usb_drv_send(EP_CONTROL, NULL, 0);
usb_drv_exit();
#if defined(CPU_ARM)
asm volatile("bx %0\n" : : "r" (addr) : "memory");
#elif defined(CPU_MIPS)
usb_drv_send(EP_CONTROL, NULL, 0);
usb_drv_exit();
asm volatile("jr %0\nnop\n" : : "r" (addr) : "memory");
#else
#warning jump is unsupported on this platform

View file

@ -41,6 +41,10 @@ uint32_t target_read32(const void *addr);
void target_write8(void *addr, uint8_t val);
void target_write16(void *addr, uint16_t val);
void target_write32(void *addr, uint32_t val);
#ifdef CONFIG_FLUSH_CACHES
/* flush cache: commit dcache and invalidate icache */
void target_flush_caches(void);
#endif
/* mandatory for all targets */
extern struct hwstub_target_desc_t target_descriptor;