arch/arc/mm/cache.c

Source file repositories/reference/linux-study-clean/arch/arc/mm/cache.c

File Facts

System
Linux kernel
Corpus path
arch/arc/mm/cache.c
Extension
.c
Size
29641 bytes
Lines
1095
Domain
Architecture Layer
Bucket
arch/arc
Inferred role
Architecture Layer: syscall or user/kernel boundary
Status
core implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

SYSCALL_DEFINE3(cacheflush, uint32_t, start, uint32_t, sz, uint32_t, flags)
{
	/* TBD: optimize this */
	flush_cache_all();
	return 0;
}

/*
 * IO-Coherency (IOC) setup rules:
 *
 * 1. Needs to be at system level, so only once by Master core
 *    Non-Masters need not be accessing caches at that time
 *    - They are either HALT_ON_RESET and kick started much later or
 *    - if run on reset, need to ensure that arc_platform_smp_wait_to_boot()
 *      doesn't perturb caches or coherency unit
 *
 * 2. caches (L1 and SLC) need to be purged (flush+inv) before setting up IOC,
 *    otherwise any straggler data might behave strangely post IOC enabling
 *
 * 3. All Caches need to be disabled when setting up IOC to elide any in-flight
 *    Coherency transactions
 */
static noinline void __init arc_ioc_setup(void)
{
	unsigned int ioc_base, mem_sz;

	/*
	 * If IOC was already enabled (due to bootloader) it technically needs to
	 * be reconfigured with aperture base,size corresponding to Linux memory map
	 * which will certainly be different than uboot's. But disabling and
	 * reenabling IOC when DMA might be potentially active is tricky business.
	 * To avoid random memory issues later, just panic here and ask user to
	 * upgrade bootloader to one which doesn't enable IOC
	 */
	if (read_aux_reg(ARC_REG_IO_COH_ENABLE) & ARC_IO_COH_ENABLE_BIT)
		panic("IOC already enabled, please upgrade bootloader!\n");

	if (!ioc_enable)
		return;

	/* Flush + invalidate + disable L1 dcache */
	__dc_disable();

	/* Flush + invalidate SLC */
	if (read_aux_reg(ARC_REG_SLC_BCR))
		slc_entire_op(OP_FLUSH_N_INV);

	/*
	 * currently IOC Aperture covers entire DDR
	 * TBD: fix for PGU + 1GB of low mem
	 * TBD: fix for PAE
	 */
	mem_sz = arc_get_mem_sz();

	if (!is_power_of_2(mem_sz) || mem_sz < 4096)
		panic("IOC Aperture size must be power of 2 larger than 4KB");

	/*
	 * IOC Aperture size decoded as 2 ^ (SIZE + 2) KB,
	 * so setting 0x11 implies 512MB, 0x12 implies 1GB...
	 */
	write_aux_reg(ARC_REG_IO_COH_AP0_SIZE, order_base_2(mem_sz >> 10) - 2);

	/* for now assume kernel base is start of IOC aperture */
	ioc_base = CONFIG_LINUX_RAM_BASE;

	if (ioc_base % mem_sz != 0)
		panic("IOC Aperture start must be aligned to the size of the aperture");

	write_aux_reg(ARC_REG_IO_COH_AP0_BASE, ioc_base >> 12);
	write_aux_reg(ARC_REG_IO_COH_PARTIAL, ARC_IO_COH_PARTIAL_BIT);
	write_aux_reg(ARC_REG_IO_COH_ENABLE, ARC_IO_COH_ENABLE_BIT);

	/* Re-enable L1 dcache */
	__dc_enable();
}

/*
 * Cache related boot time checks/setups only needed on master CPU:
 *  - Geometry checks (kernel build and hardware agree: e.g. L1_CACHE_BYTES)
 *    Assume SMP only, so all cores will have same cache config. A check on
 *    one core suffices for all
 *  - IOC setup / dma callbacks only need to be done once
 */
static noinline void __init arc_cache_init_master(void)
{
	if (IS_ENABLED(CONFIG_ARC_HAS_ICACHE)) {
		struct cpuinfo_arc_cache *ic = &ic_info;

		if (!ic->line_len)

Annotation

Implementation Notes