Skip to content

Commit

Permalink
ARC: [SMP] Enable icache coherency
Browse files Browse the repository at this point in the history
icaches are not snooped hence not cohrent in SMP setups which means
kernel has to do cross core calls to ensure the same.

The leaf routine __ic_line_inv_vaddr() now does cross core calls.

__sync_icache_dcache() is affected due to this:

* local dcache line flushed ahead of remote icache inv requests
* can't disable interrupts anymore, since
      __ic_line_inv_vaddr()->on_each_cpu() can deadlock.

| WARNING: CPU: 0 PID: 1 at kernel/smp.c:374
| smp_call_function_many+0x25a/0x2c4()
|
|  init_kprobes+0x90/0xc8
|     register_kprobe+0x1d6/0x510
|	__sync_icache_dcache+0x28/0x80
|
|	    DISABLE IRQ
|
|	    __ic_line_inv_vaddr
|		on_each_cpu
|		     smp_call_function_many+0x25a/0x2c4   --> WARN
|			__ic_line_inv_vaddr_local
|	    __dc_line_op

* TODO: Needs to use mask of relevant CPUs to avoid broadcasting

Signed-off-by: Noam Camus <noamc@ezchip.com>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
  • Loading branch information
Vineet Gupta committed Jun 26, 2014
1 parent 7e51221 commit 2328af0
Showing 1 changed file with 19 additions and 6 deletions.
25 changes: 19 additions & 6 deletions arch/arc/mm/cache_arc700.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ static inline void __dc_line_op(unsigned long paddr, unsigned long vaddr,
/***********************************************************
* Machine specific helper for per line I-Cache invalidate.
*/
static void __ic_line_inv_vaddr(unsigned long paddr, unsigned long vaddr,
static void __ic_line_inv_vaddr_local(unsigned long paddr, unsigned long vaddr,
unsigned long sz)
{
unsigned long flags;
Expand All @@ -405,6 +405,23 @@ static inline void __ic_entire_inv(void)
read_aux_reg(ARC_REG_IC_CTRL); /* blocks */
}

struct ic_line_inv_vaddr_ipi {
unsigned long paddr, vaddr;
int sz;
};

static void __ic_line_inv_vaddr_helper(void *info)
{
struct ic_line_inv_vaddr_ipi *ic_inv = (struct ic_line_inv_vaddr_ipi*) info;
__ic_line_inv_vaddr_local(ic_inv->paddr, ic_inv->vaddr, ic_inv->sz);
}

static void __ic_line_inv_vaddr(unsigned long paddr, unsigned long vaddr,
unsigned long sz)
{
struct ic_line_inv_vaddr_ipi ic_inv = { paddr, vaddr , sz};
on_each_cpu(__ic_line_inv_vaddr_helper, &ic_inv, 1);
}
#else

#define __ic_entire_inv()
Expand Down Expand Up @@ -553,12 +570,8 @@ void flush_icache_range(unsigned long kstart, unsigned long kend)
*/
void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len)
{
unsigned long flags;

local_irq_save(flags);
__ic_line_inv_vaddr(paddr, vaddr, len);
__dc_line_op(paddr, vaddr, len, OP_FLUSH_N_INV);
local_irq_restore(flags);
__ic_line_inv_vaddr(paddr, vaddr, len);
}

/* wrapper to compile time eliminate alignment checks in flush loop */
Expand Down

0 comments on commit 2328af0

Please sign in to comment.