arch/mips/kernel/smp-cps.c

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

File Facts

System
Linux kernel
Corpus path
arch/mips/kernel/smp-cps.c
Extension
.c
Size
25732 bytes
Lines
977
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 (timeout) {
			mdelay(1);
			timeout--;
		} else {
			pr_warn("Waiting for cluster %u CM to power up... STAT_CONF=0x%x\n",
				cluster, stat);
			mdelay(1000);
		}
	}

	mips_cm_unlock_other();
}

static unsigned __init core_vpe_count(unsigned int cluster, unsigned core)
{
	return min(smp_max_threads, mips_cps_numvps(cluster, core));
}

static void __init *mips_cps_build_core_entry(void *addr)
{
	extern void (*nmi_handler)(void);
	u32 *p = addr;
	u32 val;
	struct uasm_label labels[2];
	struct uasm_reloc relocs[2];
	struct uasm_label *l = labels;
	struct uasm_reloc *r = relocs;

	memset(labels, 0, sizeof(labels));
	memset(relocs, 0, sizeof(relocs));

	uasm_i_mfc0(&p, GPR_K0, C0_STATUS);
	UASM_i_LA(&p, GPR_T9, ST0_NMI);
	uasm_i_and(&p, GPR_K0, GPR_K0, GPR_T9);

	uasm_il_bnez(&p, &r, GPR_K0, label_not_nmi);
	uasm_i_nop(&p);
	UASM_i_LA(&p, GPR_K0, (long)&nmi_handler);

	uasm_l_not_nmi(&l, p);

	val = CAUSEF_IV;
	uasm_i_lui(&p, GPR_K0, val >> 16);
	uasm_i_ori(&p, GPR_K0, GPR_K0, val & 0xffff);
	uasm_i_mtc0(&p, GPR_K0, C0_CAUSE);
	val = ST0_CU1 | ST0_CU0 | ST0_BEV | ST0_KX_IF_64;
	uasm_i_lui(&p, GPR_K0, val >> 16);
	uasm_i_ori(&p, GPR_K0, GPR_K0, val & 0xffff);
	uasm_i_mtc0(&p, GPR_K0, C0_STATUS);
	uasm_i_ehb(&p);
	uasm_i_ori(&p, GPR_A0, 0, read_c0_config() & CONF_CM_CMASK);
	UASM_i_LA(&p, GPR_A1, (long)mips_gcr_base);
#if defined(KBUILD_64BIT_SYM32) || defined(CONFIG_32BIT)
	UASM_i_LA(&p, GPR_T9, CKSEG1ADDR(__pa_symbol(mips_cps_core_boot)));
#else
	UASM_i_LA(&p, GPR_T9, TO_UNCAC(__pa_symbol(mips_cps_core_boot)));
#endif
	uasm_i_jr(&p, GPR_T9);
	uasm_i_nop(&p);

	uasm_resolve_relocs(relocs, labels);

	return p;
}

static bool __init check_64bit_reset(void)
{
	bool cx_64bit_reset = false;

	mips_cm_lock_other(0, 0, 0, CM_GCR_Cx_OTHER_BLOCK_LOCAL);
	write_gcr_co_reset64_base(CM_GCR_Cx_RESET64_BASE_BEVEXCBASE);
	if ((read_gcr_co_reset64_base() & CM_GCR_Cx_RESET64_BASE_BEVEXCBASE) ==
	    CM_GCR_Cx_RESET64_BASE_BEVEXCBASE)
		cx_64bit_reset = true;
	mips_cm_unlock_other();

	return cx_64bit_reset;
}

static int __init allocate_cps_vecs(void)
{
	/* Try to allocate in KSEG1 first */
	cps_vec_pa = memblock_phys_alloc_range(BEV_VEC_SIZE, BEV_VEC_ALIGN,
						0x0, CSEGX_SIZE - 1);

	if (cps_vec_pa)
		core_entry_reg = CKSEG1ADDR(cps_vec_pa) &
					CM_GCR_Cx_RESET_BASE_BEVEXCBASE;

	if (!cps_vec_pa && mips_cm_is64) {

Annotation

Implementation Notes