arch/mips/loongson64/cpucfg-emul.c

Source file repositories/reference/linux-study-clean/arch/mips/loongson64/cpucfg-emul.c

File Facts

System
Linux kernel
Corpus path
arch/mips/loongson64/cpucfg-emul.c
Extension
.c
Size
6237 bytes
Lines
228
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

// SPDX-License-Identifier: GPL-2.0

#include <linux/smp.h>
#include <linux/types.h>
#include <asm/cpu.h>
#include <asm/cpu-info.h>
#include <asm/elf.h>

#include <loongson_regs.h>
#include <cpucfg-emul.h>

static bool is_loongson(struct cpuinfo_mips *c)
{
	switch (c->processor_id & PRID_COMP_MASK) {
	case PRID_COMP_LEGACY:
		return ((c->processor_id & PRID_IMP_MASK) ==
			PRID_IMP_LOONGSON_64C);

	case PRID_COMP_LOONGSON:
		return true;

	default:
		return false;
	}
}

static u32 get_loongson_fprev(struct cpuinfo_mips *c)
{
	return c->fpu_id & LOONGSON_FPREV_MASK;
}

static bool cpu_has_uca(void)
{
	u32 diag = read_c0_diag();
	u32 new_diag;

	if (diag & LOONGSON_DIAG_UCAC)
		/* UCA is already enabled. */
		return true;

	/* See if UCAC bit can be flipped on. This should be safe. */
	new_diag = diag | LOONGSON_DIAG_UCAC;
	write_c0_diag(new_diag);
	new_diag = read_c0_diag();
	write_c0_diag(diag);

	return (new_diag & LOONGSON_DIAG_UCAC) != 0;
}

static void probe_uca(struct cpuinfo_mips *c)
{
	if (cpu_has_uca())
		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_LSUCA;
}

static void decode_loongson_config6(struct cpuinfo_mips *c)
{
	u32 config6 = read_c0_config6();

	if (config6 & LOONGSON_CONF6_SFBEN)
		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_SFBP;
	if (config6 & LOONGSON_CONF6_LLEXC)
		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_LLEXC;
	if (config6 & LOONGSON_CONF6_SCRAND)
		c->loongson3_cpucfg_data[0] |= LOONGSON_CFG1_SCRAND;
}

static void patch_cpucfg_sel1(struct cpuinfo_mips *c)
{
	u64 ases = c->ases;
	u64 options = c->options;
	u32 data = c->loongson3_cpucfg_data[0];

	if (options & MIPS_CPU_FPU) {
		data |= LOONGSON_CFG1_FP;
		data |= get_loongson_fprev(c) << LOONGSON_CFG1_FPREV_OFFSET;
	}
	if (ases & MIPS_ASE_LOONGSON_MMI)
		data |= LOONGSON_CFG1_MMI;
	if (ases & MIPS_ASE_MSA)
		data |= LOONGSON_CFG1_MSA1;

	c->loongson3_cpucfg_data[0] = data;
}

static void patch_cpucfg_sel2(struct cpuinfo_mips *c)
{
	u64 ases = c->ases;
	u64 options = c->options;
	u32 data = c->loongson3_cpucfg_data[1];

Annotation

Implementation Notes