u-boot-brain/arch
Eugeniy Paltsev c27814be33 ARC: Flush & invalidate D$ with a single command
We don't implement separate flush_dcache_all() intentionally as
entire data cache invalidation is dangerous operation even if we flush
data cache right before invalidation.

There is the real example:
We may get stuck in the following code if we store any context (like
BLINK register) on stack in invalidate_dcache_all() function.

BLINK register is the register where return address is automatically saved
when we do function call with instructions like 'bl'.

void flush_dcache_all() {
	__dc_entire_op(OP_FLUSH);
	// Other code //
}

void invalidate_dcache_all() {
	__dc_entire_op(OP_INV);
	// Other code //
}

void foo(void) {
	flush_dcache_all();
	invalidate_dcache_all();
}

Now let's see what really happens during that code execution:

foo()
  |->> call flush_dcache_all
  	[return address is saved to BLINK register]
  	[push BLINK] (save to stack)              ![point 1]
  	|->> call __dc_entire_op(OP_FLUSH)
  		[return address is saved to BLINK register]
  		[flush L1 D$]
  		return [jump to BLINK]
  	<<------
  	[other flush_dcache_all code]
  	[pop BLINK] (get from stack)
  	return [jump to BLINK]
  <<------
  |->> call invalidate_dcache_all
  	[return address is saved to BLINK register]
  	[push BLINK] (save to stack)               ![point 2]
  	|->> call __dc_entire_op(OP_FLUSH)
  		[return address is saved to BLINK register]
  		[invalidate L1 D$]                 ![point 3]
  		// Oops!!!
  		// We lose return address from invalidate_dcache_all function:
  		// we save it to stack and invalidate L1 D$ after that!
  		return [jump to BLINK]
  	<<------
  	[other invalidate_dcache_all code]
  	[pop BLINK] (get from stack)
  	// we don't have this data in L1 dcache as we invalidated it in [point 3]
  	// so we get it from next memory level (for example DDR memory)
  	// but in the memory we have value which we save in [point 1], which
  	// is return address from flush_dcache_all function (instead of
  	// address from current invalidate_dcache_all function which we
  	// saved in [point 2] !)
  	return [jump to BLINK]
  <<------
  // As BLINK points to invalidate_dcache_all, we call it again and
  // loop forever.

Fortunately we may do flush and invalidation of D$ with a single one
instruction which automatically mitigates a situation described above.

And because invalidate_dcache_all() isn't used in common U-Boot code we
implement "flush and invalidate dcache all" instead.

Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
2018-03-21 17:06:49 +03:00
..
arc ARC: Flush & invalidate D$ with a single command 2018-03-21 17:06:49 +03:00
arm Merge git://git.denx.de/u-boot-fsl-qoriq 2018-03-20 18:39:27 -04:00
m68k Convert CONFIG_SYS_BOOT_GET_{CMDLINE, KBD} to Kconfig 2018-01-30 12:52:57 -05:00
microblaze fdt: Implement weak arch_fixup_fdt() 2018-02-18 12:53:38 -07:00
mips fdt: Implement weak arch_fixup_fdt() 2018-02-18 12:53:38 -07:00
nds32 fdt: Implement weak arch_fixup_fdt() 2018-02-18 12:53:38 -07:00
nios2 nios2: 10m50: Add CPU pre-relocation in device tree 2017-11-17 10:51:24 -05:00
powerpc ppc: Remove orphan xilinx_irq.h file 2018-03-16 14:54:14 -04:00
riscv riscv: Add Kconfig to support RISC-V 2018-01-12 08:05:12 -05:00
sandbox libfdt: move headers to <linux/libfdt.h> and <linux/libfdt_env.h> 2018-03-05 10:16:28 -05:00
sh sh: Do not provide strncmp 2018-02-23 00:06:05 +01:00
x86 common: move init_helpers.h prototypes in init.h 2018-03-16 14:56:59 -04:00
xtensa xtensa: clean up CONFIG_SYS_TEXT_ADDR 2018-02-23 10:21:41 -05:00
.gitignore .gitignore: drop include/asm/proc from ignore pattern 2014-06-19 11:18:54 -04:00
Kconfig Move most CONFIG_HAVE_BLOCK_DEVICE to Kconfig 2018-02-08 19:09:03 -05:00