Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 889a4c7b authored by Steven J. Hill's avatar Steven J. Hill Committed by Ralf Baechle
Browse files

MIPS: SMTC: Support for Multi-threaded FPUs



Signed-off-by: default avatarSteven J. Hill <sjhill@mips.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/3603/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 2244f128
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -28,6 +28,9 @@
#define read_c0_vpeconf0()		__read_32bit_c0_register($1, 2)
#define write_c0_vpeconf0(val)		__write_32bit_c0_register($1, 2, val)

#define read_c0_vpeconf1()		__read_32bit_c0_register($1, 3)
#define write_c0_vpeconf1(val)		__write_32bit_c0_register($1, 3, val)

#define read_c0_tcstatus()		__read_32bit_c0_register($2, 1)
#define write_c0_tcstatus(val)		__write_32bit_c0_register($2, 1, val)

@@ -124,6 +127,14 @@
#define VPECONF0_XTC_SHIFT	21
#define VPECONF0_XTC		(_ULCAST_(0xff) << VPECONF0_XTC_SHIFT)

/* VPEConf1 fields (per VPE) */
#define VPECONF1_NCP1_SHIFT	0
#define VPECONF1_NCP1		(_ULCAST_(0xff) << VPECONF1_NCP1_SHIFT)
#define VPECONF1_NCP2_SHIFT	10
#define VPECONF1_NCP2		(_ULCAST_(0xff) << VPECONF1_NCP2_SHIFT)
#define VPECONF1_NCX_SHIFT	20
#define VPECONF1_NCX		(_ULCAST_(0xff) << VPECONF1_NCX_SHIFT)

/* TCStatus fields (per TC) */
#define TCSTATUS_TASID		(_ULCAST_(0xff))
#define TCSTATUS_IXMT_SHIFT	10
@@ -350,6 +361,8 @@ do { \
#define write_vpe_c0_vpecontrol(val)	mttc0(1, 1, val)
#define read_vpe_c0_vpeconf0()		mftc0(1, 2)
#define write_vpe_c0_vpeconf0(val)	mttc0(1, 2, val)
#define read_vpe_c0_vpeconf1()		mftc0(1, 3)
#define write_vpe_c0_vpeconf1(val)	mttc0(1, 3, val)
#define read_vpe_c0_count()		mftc0(9, 0)
#define write_vpe_c0_count(val)		mttc0(9, 0, val)
#define read_vpe_c0_status()		mftc0(12, 0)
+6 −0
Original line number Diff line number Diff line
@@ -33,6 +33,12 @@ typedef long asiduse;
#endif
#endif

/*
 * VPE Management information
 */

#define MAX_SMTC_VPES	MAX_SMTC_TLBS	/* FIXME: May not always be true. */

extern asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];

struct mm_struct;
+3 −1
Original line number Diff line number Diff line
@@ -102,7 +102,9 @@ asmlinkage __cpuinit void start_secondary(void)

#ifdef CONFIG_MIPS_MT_SMTC
	/* Only do cpu_probe for first TC of CPU */
	if ((read_c0_tcbind() & TCBIND_CURTC) == 0)
	if ((read_c0_tcbind() & TCBIND_CURTC) != 0)
		__cpu_name[smp_processor_id()] = __cpu_name[0];
	else
#endif /* CONFIG_MIPS_MT_SMTC */
	cpu_probe();
	cpu_report();
+68 −8
Original line number Diff line number Diff line
@@ -86,6 +86,13 @@ struct smtc_ipi_q IPIQ[NR_CPUS];
static struct smtc_ipi_q freeIPIq;


/*
 * Number of FPU contexts for each VPE
 */

static int smtc_nconf1[MAX_SMTC_VPES];


/* Forward declarations */

void ipi_decode(struct smtc_ipi *);
@@ -174,9 +181,9 @@ static int __init tintq(char *str)

__setup("tintq=", tintq);

static int imstuckcount[2][8];
static int imstuckcount[MAX_SMTC_VPES][8];
/* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */
static int vpemask[2][8] = {
static int vpemask[MAX_SMTC_VPES][8] = {
	{0, 0, 1, 0, 0, 0, 0, 1},
	{0, 0, 0, 0, 0, 0, 0, 1}
};
@@ -331,6 +338,22 @@ int __init smtc_build_cpu_map(int start_cpu_slot)

static void smtc_tc_setup(int vpe, int tc, int cpu)
{
	static int cp1contexts[MAX_SMTC_VPES];

	/*
	 * Make a local copy of the available FPU contexts in order
	 * to keep track of TCs that can have one.
	 */
	if (tc == 1)
	{
		/*
		 * FIXME: Multi-core SMTC hasn't been tested and the
		 *        maximum number of VPEs may change.
		 */
		cp1contexts[0] = smtc_nconf1[0] - 1;
		cp1contexts[1] = smtc_nconf1[1];
	}

	settc(tc);
	write_tc_c0_tchalt(TCHALT_H);
	mips_ihb();
@@ -343,22 +366,29 @@ static void smtc_tc_setup(int vpe, int tc, int cpu)
	 * an active IPI queue.
	 */
	write_tc_c0_tccontext((sizeof(struct smtc_ipi_q) * cpu) << 16);
	/* Bind tc to vpe */

	/* Bind TC to VPE. */
	write_tc_c0_tcbind(vpe);

	/* In general, all TCs should have the same cpu_data indications. */
	memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips));
	/* For 34Kf, start with TC/CPU 0 as sole owner of single FPU context */
	if (cpu_data[0].cputype == CPU_34K ||
	    cpu_data[0].cputype == CPU_1004K)

	/* Check to see if there is a FPU context available for this TC. */
	if (!cp1contexts[vpe])
		cpu_data[cpu].options &= ~MIPS_CPU_FPU;
	else
		cp1contexts[vpe]--;

	/* Store the TC and VPE into the cpu_data structure. */
	cpu_data[cpu].vpe_id = vpe;
	cpu_data[cpu].tc_id = tc;
	/* Multi-core SMTC hasn't been tested, but be prepared */

	/* FIXME: Multi-core SMTC hasn't been tested, but be prepared. */
	cpu_data[cpu].core = (read_vpe_c0_ebase() >> 1) & 0xff;
}

/*
 * Tweak to get Count registes in as close a sync as possible.  The
 * Tweak to get Count registers synced as closely as possible. The
 * value seems good for 34K-class cores.
 */

@@ -466,6 +496,24 @@ void smtc_prepare_cpus(int cpus)
	smtc_configure_tlb();

	for (tc = 0, vpe = 0 ; (vpe < nvpe) && (tc < ntc) ; vpe++) {
		/* Get number of CP1 contexts for each VPE. */
		if (tc == 0)
		{
			/*
			 * Do not call settc() for TC0 or the FPU context
			 * value will be incorrect. Besides, we know that
			 * we are TC0 anyway.
			 */
			smtc_nconf1[0] = ((read_vpe_c0_vpeconf1() &
				VPECONF1_NCP1) >> VPECONF1_NCP1_SHIFT);
			if (nvpe == 2)
			{
				settc(1);
				smtc_nconf1[1] = ((read_vpe_c0_vpeconf1() &
					VPECONF1_NCP1) >> VPECONF1_NCP1_SHIFT);
				settc(0);
			}
		}
		if (tcpervpe[vpe] == 0)
			continue;
		if (vpe != 0)
@@ -479,6 +527,18 @@ void smtc_prepare_cpus(int cpus)
			 */
			if (tc != 0) {
				smtc_tc_setup(vpe, tc, cpu);
				if (vpe != 0) {
					/*
					 * Set MVP bit (possibly again).  Do it
					 * here to catch CPUs that have no TCs
					 * bound to the VPE at reset.  In that
					 * case, a TC must be bound to the VPE
					 * before we can set VPEControl[MVP]
					 */
					write_vpe_c0_vpeconf0(
						read_vpe_c0_vpeconf0() |
						VPECONF0_MVP);
				}
				cpu++;
			}
			printk(" %d", tc);