mirror of
https://github.com/torvalds/linux
synced 2024-10-07 03:42:55 +00:00
MIPS: smp-cps: Support MIPSr6 Virtual Processors
Introduce support for bringing up Virtual Processors in MIPSr6 systems as CPUs, much like their VPE parallel from the now-deprecated MT ASE. The existing mips_cps_boot_vpes function fits the MIPSr6 architecture pretty well - it can now simply write the mask of running VPs to the VC_RUN register, rather than looping through each & starting or stopping as appropriate as is done for VPEs from the MT ASE. Thus the VP support is in general an extension & simplification of the existing MT ASE VPE (aka SMVP) support. Signed-off-by: Paul Burton <paul.burton@imgtec.com> Cc: Matt Redfearn <matt.redfearn@imgtec.com> Cc: Rusty Russell <rusty@rustcorp.com.au> Cc: Maciej W. Rozycki <macro@linux-mips.org> Cc: Niklas Cassel <niklas.cassel@axis.com> Cc: Ezequiel Garcia <ezequiel.garcia@imgtec.com> Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12339/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
87a70bcdb4
commit
5a3e7c02d8
|
@ -2282,7 +2282,7 @@ config MIPS_CMP
|
||||||
|
|
||||||
config MIPS_CPS
|
config MIPS_CPS
|
||||||
bool "MIPS Coherent Processing System support"
|
bool "MIPS Coherent Processing System support"
|
||||||
depends on SYS_SUPPORTS_MIPS_CPS && !CPU_MIPSR6
|
depends on SYS_SUPPORTS_MIPS_CPS
|
||||||
select MIPS_CM
|
select MIPS_CM
|
||||||
select MIPS_CPC
|
select MIPS_CPC
|
||||||
select MIPS_CPS_PM if HOTPLUG_CPU
|
select MIPS_CPS_PM if HOTPLUG_CPU
|
||||||
|
|
|
@ -68,7 +68,7 @@ struct cpuinfo_mips {
|
||||||
#ifdef CONFIG_64BIT
|
#ifdef CONFIG_64BIT
|
||||||
int vmbits; /* Virtual memory size in bits */
|
int vmbits; /* Virtual memory size in bits */
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_MIPS_MT_SMP
|
#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_CPU_MIPSR6)
|
||||||
/*
|
/*
|
||||||
* There is not necessarily a 1:1 mapping of VPE num to CPU number
|
* There is not necessarily a 1:1 mapping of VPE num to CPU number
|
||||||
* in particular on multi-core systems.
|
* in particular on multi-core systems.
|
||||||
|
@ -125,7 +125,7 @@ struct proc_cpuinfo_notifier_args {
|
||||||
unsigned long n;
|
unsigned long n;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_MIPS_MT_SMP
|
#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_CPU_MIPSR6)
|
||||||
# define cpu_vpe_id(cpuinfo) ((cpuinfo)->vpe_id)
|
# define cpu_vpe_id(cpuinfo) ((cpuinfo)->vpe_id)
|
||||||
#else
|
#else
|
||||||
# define cpu_vpe_id(cpuinfo) ({ (void)cpuinfo; 0; })
|
# define cpu_vpe_id(cpuinfo) ({ (void)cpuinfo; 0; })
|
||||||
|
|
|
@ -18,9 +18,12 @@
|
||||||
#include <asm/mipsmtregs.h>
|
#include <asm/mipsmtregs.h>
|
||||||
#include <asm/pm.h>
|
#include <asm/pm.h>
|
||||||
|
|
||||||
|
#define GCR_CPC_BASE_OFS 0x0088
|
||||||
#define GCR_CL_COHERENCE_OFS 0x2008
|
#define GCR_CL_COHERENCE_OFS 0x2008
|
||||||
#define GCR_CL_ID_OFS 0x2028
|
#define GCR_CL_ID_OFS 0x2028
|
||||||
|
|
||||||
|
#define CPC_CL_VC_RUN_OFS 0x2028
|
||||||
|
|
||||||
.extern mips_cm_base
|
.extern mips_cm_base
|
||||||
|
|
||||||
.set noreorder
|
.set noreorder
|
||||||
|
@ -60,6 +63,26 @@
|
||||||
nop
|
nop
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set dest to non-zero if the core supports MIPSr6 multithreading
|
||||||
|
* (ie. VPs), else zero. If MIPSr6 multithreading is not supported then
|
||||||
|
* branch to nomt.
|
||||||
|
*/
|
||||||
|
.macro has_vp dest, nomt
|
||||||
|
mfc0 \dest, CP0_CONFIG, 1
|
||||||
|
bgez \dest, \nomt
|
||||||
|
mfc0 \dest, CP0_CONFIG, 2
|
||||||
|
bgez \dest, \nomt
|
||||||
|
mfc0 \dest, CP0_CONFIG, 3
|
||||||
|
bgez \dest, \nomt
|
||||||
|
mfc0 \dest, CP0_CONFIG, 4
|
||||||
|
bgez \dest, \nomt
|
||||||
|
mfc0 \dest, CP0_CONFIG, 5
|
||||||
|
andi \dest, \dest, MIPS_CONF5_VP
|
||||||
|
beqz \dest, \nomt
|
||||||
|
nop
|
||||||
|
.endm
|
||||||
|
|
||||||
/* Calculate an uncached address for the CM GCRs */
|
/* Calculate an uncached address for the CM GCRs */
|
||||||
.macro cmgcrb dest
|
.macro cmgcrb dest
|
||||||
.set push
|
.set push
|
||||||
|
@ -296,7 +319,17 @@ LEAF(mips_cps_get_bootcfg)
|
||||||
|
|
||||||
/* Calculate this VPEs ID. If the core doesn't support MT use 0 */
|
/* Calculate this VPEs ID. If the core doesn't support MT use 0 */
|
||||||
li t9, 0
|
li t9, 0
|
||||||
#ifdef CONFIG_MIPS_MT_SMP
|
#if defined(CONFIG_CPU_MIPSR6)
|
||||||
|
has_vp ta2, 1f
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assume non-contiguous numbering. Perhaps some day we'll need
|
||||||
|
* to handle contiguous VP numbering, but no such systems yet
|
||||||
|
* exist.
|
||||||
|
*/
|
||||||
|
mfc0 t9, $3, 1
|
||||||
|
andi t9, t9, 0xff
|
||||||
|
#elif defined(CONFIG_MIPS_MT_SMP)
|
||||||
has_mt ta2, 1f
|
has_mt ta2, 1f
|
||||||
|
|
||||||
/* Find the number of VPEs present in the core */
|
/* Find the number of VPEs present in the core */
|
||||||
|
@ -332,7 +365,23 @@ LEAF(mips_cps_boot_vpes)
|
||||||
PTR_L ta2, COREBOOTCFG_VPEMASK(a0)
|
PTR_L ta2, COREBOOTCFG_VPEMASK(a0)
|
||||||
PTR_L ta3, COREBOOTCFG_VPECONFIG(a0)
|
PTR_L ta3, COREBOOTCFG_VPECONFIG(a0)
|
||||||
|
|
||||||
#ifdef CONFIG_MIPS_MT
|
#if defined(CONFIG_CPU_MIPSR6)
|
||||||
|
|
||||||
|
has_vp t0, 5f
|
||||||
|
|
||||||
|
/* Find base address of CPC */
|
||||||
|
cmgcrb t3
|
||||||
|
PTR_L t1, GCR_CPC_BASE_OFS(t3)
|
||||||
|
PTR_LI t2, ~0x7fff
|
||||||
|
and t1, t1, t2
|
||||||
|
PTR_LI t2, UNCAC_BASE
|
||||||
|
PTR_ADD t1, t1, t2
|
||||||
|
|
||||||
|
/* Set VC_RUN to the VPE mask */
|
||||||
|
PTR_S ta2, CPC_CL_VC_RUN_OFS(t1)
|
||||||
|
ehb
|
||||||
|
|
||||||
|
#elif defined(CONFIG_MIPS_MT)
|
||||||
|
|
||||||
.set push
|
.set push
|
||||||
.set mt
|
.set mt
|
||||||
|
|
|
@ -35,7 +35,8 @@ static unsigned core_vpe_count(unsigned core)
|
||||||
{
|
{
|
||||||
unsigned cfg;
|
unsigned cfg;
|
||||||
|
|
||||||
if (!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt)
|
if ((!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt)
|
||||||
|
&& (!config_enabled(CONFIG_CPU_MIPSR6) || !cpu_has_vp))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
mips_cm_lock_other(core, 0);
|
mips_cm_lock_other(core, 0);
|
||||||
|
@ -47,11 +48,12 @@ static unsigned core_vpe_count(unsigned core)
|
||||||
static void __init cps_smp_setup(void)
|
static void __init cps_smp_setup(void)
|
||||||
{
|
{
|
||||||
unsigned int ncores, nvpes, core_vpes;
|
unsigned int ncores, nvpes, core_vpes;
|
||||||
|
unsigned long core_entry;
|
||||||
int c, v;
|
int c, v;
|
||||||
|
|
||||||
/* Detect & record VPE topology */
|
/* Detect & record VPE topology */
|
||||||
ncores = mips_cm_numcores();
|
ncores = mips_cm_numcores();
|
||||||
pr_info("VPE topology ");
|
pr_info("%s topology ", cpu_has_mips_r6 ? "VP" : "VPE");
|
||||||
for (c = nvpes = 0; c < ncores; c++) {
|
for (c = nvpes = 0; c < ncores; c++) {
|
||||||
core_vpes = core_vpe_count(c);
|
core_vpes = core_vpe_count(c);
|
||||||
pr_cont("%c%u", c ? ',' : '{', core_vpes);
|
pr_cont("%c%u", c ? ',' : '{', core_vpes);
|
||||||
|
@ -62,7 +64,7 @@ static void __init cps_smp_setup(void)
|
||||||
|
|
||||||
for (v = 0; v < min_t(int, core_vpes, NR_CPUS - nvpes); v++) {
|
for (v = 0; v < min_t(int, core_vpes, NR_CPUS - nvpes); v++) {
|
||||||
cpu_data[nvpes + v].core = c;
|
cpu_data[nvpes + v].core = c;
|
||||||
#ifdef CONFIG_MIPS_MT_SMP
|
#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_CPU_MIPSR6)
|
||||||
cpu_data[nvpes + v].vpe_id = v;
|
cpu_data[nvpes + v].vpe_id = v;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -91,6 +93,11 @@ static void __init cps_smp_setup(void)
|
||||||
/* Make core 0 coherent with everything */
|
/* Make core 0 coherent with everything */
|
||||||
write_gcr_cl_coherence(0xff);
|
write_gcr_cl_coherence(0xff);
|
||||||
|
|
||||||
|
if (mips_cm_revision() >= CM_REV_CM3) {
|
||||||
|
core_entry = CKSEG1ADDR((unsigned long)mips_cps_core_entry);
|
||||||
|
write_gcr_bev_base(core_entry);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_MIPS_MT_FPAFF
|
#ifdef CONFIG_MIPS_MT_FPAFF
|
||||||
/* If we have an FPU, enroll ourselves in the FPU-full mask */
|
/* If we have an FPU, enroll ourselves in the FPU-full mask */
|
||||||
if (cpu_has_fpu)
|
if (cpu_has_fpu)
|
||||||
|
@ -213,6 +220,18 @@ static void boot_core(unsigned core)
|
||||||
if (mips_cpc_present()) {
|
if (mips_cpc_present()) {
|
||||||
/* Reset the core */
|
/* Reset the core */
|
||||||
mips_cpc_lock_other(core);
|
mips_cpc_lock_other(core);
|
||||||
|
|
||||||
|
if (mips_cm_revision() >= CM_REV_CM3) {
|
||||||
|
/* Run VP0 following the reset */
|
||||||
|
write_cpc_co_vp_run(0x1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure that the VP_RUN register is written before the
|
||||||
|
* core leaves reset.
|
||||||
|
*/
|
||||||
|
wmb();
|
||||||
|
}
|
||||||
|
|
||||||
write_cpc_co_cmd(CPC_Cx_CMD_RESET);
|
write_cpc_co_cmd(CPC_Cx_CMD_RESET);
|
||||||
|
|
||||||
timeout = 100;
|
timeout = 100;
|
||||||
|
@ -262,6 +281,7 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle)
|
||||||
unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]);
|
unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]);
|
||||||
struct core_boot_config *core_cfg = &mips_cps_core_bootcfg[core];
|
struct core_boot_config *core_cfg = &mips_cps_core_bootcfg[core];
|
||||||
struct vpe_boot_config *vpe_cfg = &core_cfg->vpe_config[vpe_id];
|
struct vpe_boot_config *vpe_cfg = &core_cfg->vpe_config[vpe_id];
|
||||||
|
unsigned long core_entry;
|
||||||
unsigned int remote;
|
unsigned int remote;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -279,6 +299,13 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cpu_has_vp) {
|
||||||
|
mips_cm_lock_other(core, vpe_id);
|
||||||
|
core_entry = CKSEG1ADDR((unsigned long)mips_cps_core_entry);
|
||||||
|
write_gcr_co_reset_base(core_entry);
|
||||||
|
mips_cm_unlock_other();
|
||||||
|
}
|
||||||
|
|
||||||
if (core != current_cpu_data.core) {
|
if (core != current_cpu_data.core) {
|
||||||
/* Boot a VPE on another powered up core */
|
/* Boot a VPE on another powered up core */
|
||||||
for (remote = 0; remote < NR_CPUS; remote++) {
|
for (remote = 0; remote < NR_CPUS; remote++) {
|
||||||
|
@ -296,7 +323,7 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
BUG_ON(!cpu_has_mipsmt);
|
BUG_ON(!cpu_has_mipsmt && !cpu_has_vp);
|
||||||
|
|
||||||
/* Boot a VPE on this core */
|
/* Boot a VPE on this core */
|
||||||
mips_cps_boot_vpes(core_cfg, vpe_id);
|
mips_cps_boot_vpes(core_cfg, vpe_id);
|
||||||
|
|
Loading…
Reference in a new issue