arch/mips/kernel/pm-cps.c

Source file repositories/reference/linux-study-clean/arch/mips/kernel/pm-cps.c

File Facts

System
Linux kernel
Corpus path
arch/mips/kernel/pm-cps.c
Extension
.c
Size
21980 bytes
Lines
740
Domain
Architecture Layer
Bucket
arch/mips
Inferred role
Architecture Layer: implementation source
Status
source 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

if (cpu_has_mips_r6) {
			uasm_i_cache(pp, op, 0, GPR_T0);
			uasm_i_addiu(pp, GPR_T0, GPR_T0, cache->linesz);
		} else {
			uasm_i_cache(pp, op, i * cache->linesz, GPR_T0);
		}
	}

	if (!cpu_has_mips_r6)
		/* Update the base address */
		uasm_i_addiu(pp, GPR_T0, GPR_T0, unroll_lines * cache->linesz);

	/* Loop if we haven't reached the end address yet */
	uasm_il_bne(pp, pr, GPR_T0, GPR_T1, lbl);
	uasm_i_nop(pp);
}

static int cps_gen_flush_fsb(u32 **pp, struct uasm_label **pl,
			     struct uasm_reloc **pr,
			     const struct cpuinfo_mips *cpu_info,
			     int lbl)
{
	unsigned i, fsb_size = 8;
	unsigned num_loads = (fsb_size * 3) / 2;
	unsigned line_stride = 2;
	unsigned line_size = cpu_info->dcache.linesz;
	unsigned perf_counter, perf_event;
	unsigned revision = cpu_info->processor_id & PRID_REV_MASK;

	/*
	 * Determine whether this CPU requires an FSB flush, and if so which
	 * performance counter/event reflect stalls due to a full FSB.
	 */
	switch (__get_cpu_type(cpu_info->cputype)) {
	case CPU_INTERAPTIV:
		perf_counter = 1;
		perf_event = 51;
		break;

	case CPU_PROAPTIV:
		/* Newer proAptiv cores don't require this workaround */
		if (revision >= PRID_REV_ENCODE_332(1, 1, 0))
			return 0;

		/* On older ones it's unavailable */
		return -1;

	default:
		/* Assume that the CPU does not need this workaround */
		return 0;
	}

	/*
	 * Ensure that the fill/store buffer (FSB) is not holding the results
	 * of a prefetch, since if it is then the CPC sequencer may become
	 * stuck in the D3 (ClrBus) state whilst entering a low power state.
	 */

	/* Preserve perf counter setup */
	uasm_i_mfc0(pp, GPR_T2, 25, (perf_counter * 2) + 0); /* PerfCtlN */
	uasm_i_mfc0(pp, GPR_T3, 25, (perf_counter * 2) + 1); /* PerfCntN */

	/* Setup perf counter to count FSB full pipeline stalls */
	uasm_i_addiu(pp, GPR_T0, GPR_ZERO, (perf_event << 5) | 0xf);
	uasm_i_mtc0(pp, GPR_T0, 25, (perf_counter * 2) + 0); /* PerfCtlN */
	uasm_i_ehb(pp);
	uasm_i_mtc0(pp, GPR_ZERO, 25, (perf_counter * 2) + 1); /* PerfCntN */
	uasm_i_ehb(pp);

	/* Base address for loads */
	UASM_i_LA(pp, GPR_T0, (long)CKSEG0);

	/* Start of clear loop */
	uasm_build_label(pl, *pp, lbl);

	/* Perform some loads to fill the FSB */
	for (i = 0; i < num_loads; i++)
		uasm_i_lw(pp, GPR_ZERO, i * line_size * line_stride, GPR_T0);

	/*
	 * Invalidate the new D-cache entries so that the cache will need
	 * refilling (via the FSB) if the loop is executed again.
	 */
	for (i = 0; i < num_loads; i++) {
		uasm_i_cache(pp, Hit_Invalidate_D,
			     i * line_size * line_stride, GPR_T0);
		uasm_i_cache(pp, Hit_Writeback_Inv_SD,
			     i * line_size * line_stride, GPR_T0);
	}

Annotation

Implementation Notes