Skip to content

Commit

Permalink
MIPS: Coherent Processing System SMP implementation
Browse files Browse the repository at this point in the history
This patch introduces a new SMP implementation for systems implementing
the MIPS Coherent Processing System architecture. The kernel will make
use of the Coherence Manager, Cluster Power Controller & Global
Interrupt Controller in order to detect, bring up & make use of other
cores in the system. SMTC is not supported, so only a single TC per VPE
in the system is used. That is, this option enables an SMVP style setup
but across multiple cores.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/6362/
Patchwork: https://patchwork.linux-mips.org/patch/6611/
Patchwork: https://patchwork.linux-mips.org/patch/6651/
Patchwork: https://patchwork.linux-mips.org/patch/6652/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
Paul Burton authored and Ralf Baechle committed Mar 26, 2014
1 parent b86c224 commit 0ee958e
Show file tree
Hide file tree
Showing 9 changed files with 606 additions and 1 deletion.
21 changes: 21 additions & 0 deletions arch/mips/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1887,6 +1887,7 @@ config MIPS_MT_SMTC
bool "Use all TCs on all VPEs for SMP (DEPRECATED)"
depends on CPU_MIPS32_R2
depends on SYS_SUPPORTS_MULTITHREADING
depends on !MIPS_CPS
select CPU_MIPSR2_IRQ_VI
select CPU_MIPSR2_IRQ_EI
select MIPS_MT
Expand Down Expand Up @@ -2003,6 +2004,23 @@ config MIPS_CMP
help
Enable Coherency Manager processor (CMP) support.

config MIPS_CPS
bool "MIPS Coherent Processing System support"
depends on SYS_SUPPORTS_MIPS_CPS
select MIPS_CM
select MIPS_CPC
select MIPS_GIC_IPI
select SMP
select SYNC_R4K if (CEVT_R4K || CSRC_R4K)
select SYS_SUPPORTS_SMP
select WEAK_ORDERING
help
Select this if you wish to run an SMP kernel across multiple cores
within a MIPS Coherent Processing System. When this option is
enabled the kernel will probe for other cores and boot them with
no external assistance. It is safe to enable this when hardware
support is unavailable.

config MIPS_GIC_IPI
bool

Expand Down Expand Up @@ -2191,6 +2209,9 @@ config SMP_UP
config SYS_SUPPORTS_MIPS_CMP
bool

config SYS_SUPPORTS_MIPS_CPS
bool

config SYS_SUPPORTS_SMP
bool

Expand Down
33 changes: 33 additions & 0 deletions arch/mips/include/asm/smp-cps.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (C) 2013 Imagination Technologies
* Author: Paul Burton <paul.burton@imgtec.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/

#ifndef __MIPS_ASM_SMP_CPS_H__
#define __MIPS_ASM_SMP_CPS_H__

#ifndef __ASSEMBLY__

struct boot_config {
unsigned int core;
unsigned int vpe;
unsigned long pc;
unsigned long sp;
unsigned long gp;
};

extern struct boot_config mips_cps_bootcfg;

extern void mips_cps_core_entry(void);

#else /* __ASSEMBLY__ */

.extern mips_cps_bootcfg;

#endif /* __ASSEMBLY__ */
#endif /* __MIPS_ASM_SMP_CPS_H__ */
9 changes: 9 additions & 0 deletions arch/mips/include/asm/smp-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,13 @@ static inline int register_vsmp_smp_ops(void)
#endif
}

#ifdef CONFIG_MIPS_CPS
extern int register_cps_smp_ops(void);
#else
static inline int register_cps_smp_ops(void)
{
return -ENODEV;
}
#endif

#endif /* __ASM_SMP_OPS_H */
1 change: 1 addition & 0 deletions arch/mips/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ obj-$(CONFIG_MIPS_MT_FPAFF) += mips-mt-fpaff.o
obj-$(CONFIG_MIPS_MT_SMTC) += smtc.o smtc-asm.o smtc-proc.o
obj-$(CONFIG_MIPS_MT_SMP) += smp-mt.o
obj-$(CONFIG_MIPS_CMP) += smp-cmp.o
obj-$(CONFIG_MIPS_CPS) += smp-cps.o cps-vec.o
obj-$(CONFIG_MIPS_GIC_IPI) += smp-gic.o
obj-$(CONFIG_CPU_MIPSR2) += spram.o

Expand Down
13 changes: 13 additions & 0 deletions arch/mips/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <linux/suspend.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
#include <asm/smp-cps.h>

#include <linux/kvm_host.h>

Expand Down Expand Up @@ -397,3 +398,15 @@ void output_kvm_defines(void)
OFFSET(COP0_STATUS, mips_coproc, reg[MIPS_CP0_STATUS][0]);
BLANK();
}

#ifdef CONFIG_MIPS_CPS
void output_cps_defines(void)
{
COMMENT(" MIPS CPS offsets. ");
OFFSET(BOOTCFG_CORE, boot_config, core);
OFFSET(BOOTCFG_VPE, boot_config, vpe);
OFFSET(BOOTCFG_PC, boot_config, pc);
OFFSET(BOOTCFG_SP, boot_config, sp);
OFFSET(BOOTCFG_GP, boot_config, gp);
}
#endif
191 changes: 191 additions & 0 deletions arch/mips/kernel/cps-vec.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
/*
* Copyright (C) 2013 Imagination Technologies
* Author: Paul Burton <paul.burton@imgtec.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/

#include <asm/addrspace.h>
#include <asm/asm.h>
#include <asm/asm-offsets.h>
#include <asm/asmmacro.h>
#include <asm/cacheops.h>
#include <asm/mipsregs.h>

#define GCR_CL_COHERENCE_OFS 0x2008

.section .text.cps-vec
.balign 0x1000
.set noreorder

LEAF(mips_cps_core_entry)
/*
* These first 8 bytes will be patched by cps_smp_setup to load the
* base address of the CM GCRs into register v1.
*/
.quad 0

/* Check whether we're here due to an NMI */
mfc0 k0, CP0_STATUS
and k0, k0, ST0_NMI
beqz k0, not_nmi
nop

/* This is an NMI */
la k0, nmi_handler
jr k0
nop

not_nmi:
/* Setup Cause */
li t0, CAUSEF_IV
mtc0 t0, CP0_CAUSE

/* Setup Status */
li t0, ST0_CU1 | ST0_CU0
mtc0 t0, CP0_STATUS

/*
* Clear the bits used to index the caches. Note that the architecture
* dictates that writing to any of TagLo or TagHi selects 0 or 2 should
* be valid for all MIPS32 CPUs, even those for which said writes are
* unnecessary.
*/
mtc0 zero, CP0_TAGLO, 0
mtc0 zero, CP0_TAGHI, 0
mtc0 zero, CP0_TAGLO, 2
mtc0 zero, CP0_TAGHI, 2
ehb

/* Primary cache configuration is indicated by Config1 */
mfc0 v0, CP0_CONFIG, 1

/* Detect I-cache line size */
_EXT t0, v0, MIPS_CONF1_IL_SHF, MIPS_CONF1_IL_SZ
beqz t0, icache_done
li t1, 2
sllv t0, t1, t0

/* Detect I-cache size */
_EXT t1, v0, MIPS_CONF1_IS_SHF, MIPS_CONF1_IS_SZ
xori t2, t1, 0x7
beqz t2, 1f
li t3, 32
addi t1, t1, 1
sllv t1, t3, t1
1: /* At this point t1 == I-cache sets per way */
_EXT t2, v0, MIPS_CONF1_IA_SHF, MIPS_CONF1_IA_SZ
addi t2, t2, 1
mul t1, t1, t0
mul t1, t1, t2

li a0, KSEG0
add a1, a0, t1
1: cache Index_Store_Tag_I, 0(a0)
add a0, a0, t0
bne a0, a1, 1b
nop
icache_done:

/* Detect D-cache line size */
_EXT t0, v0, MIPS_CONF1_DL_SHF, MIPS_CONF1_DL_SZ
beqz t0, dcache_done
li t1, 2
sllv t0, t1, t0

/* Detect D-cache size */
_EXT t1, v0, MIPS_CONF1_DS_SHF, MIPS_CONF1_DS_SZ
xori t2, t1, 0x7
beqz t2, 1f
li t3, 32
addi t1, t1, 1
sllv t1, t3, t1
1: /* At this point t1 == D-cache sets per way */
_EXT t2, v0, MIPS_CONF1_DA_SHF, MIPS_CONF1_DA_SZ
addi t2, t2, 1
mul t1, t1, t0
mul t1, t1, t2

li a0, KSEG0
addu a1, a0, t1
subu a1, a1, t0
1: cache Index_Store_Tag_D, 0(a0)
bne a0, a1, 1b
add a0, a0, t0
dcache_done:

/* Set Kseg0 cacheable, coherent, write-back, write-allocate */
mfc0 t0, CP0_CONFIG
ori t0, 0x7
xori t0, 0x2
mtc0 t0, CP0_CONFIG
ehb

/* Enter the coherent domain */
li t0, 0xff
sw t0, GCR_CL_COHERENCE_OFS(v1)
ehb

/* Jump to kseg0 */
la t0, 1f
jr t0
nop

1: /* We're up, cached & coherent */

/*
* TODO: We should check the VPE number we intended to boot here, and
* if non-zero we should start that VPE and stop this one. For
* the moment this doesn't matter since CPUs are brought up
* sequentially and in order, but once hotplug is implemented
* this will need revisiting.
*/

/* Off we go! */
la t0, mips_cps_bootcfg
lw t1, BOOTCFG_PC(t0)
lw gp, BOOTCFG_GP(t0)
lw sp, BOOTCFG_SP(t0)
jr t1
nop
END(mips_cps_core_entry)

.org 0x200
LEAF(excep_tlbfill)
b .
nop
END(excep_tlbfill)

.org 0x280
LEAF(excep_xtlbfill)
b .
nop
END(excep_xtlbfill)

.org 0x300
LEAF(excep_cache)
b .
nop
END(excep_cache)

.org 0x380
LEAF(excep_genex)
b .
nop
END(excep_genex)

.org 0x400
LEAF(excep_intex)
b .
nop
END(excep_intex)

.org 0x480
LEAF(excep_ejtag)
la k0, ejtag_debug_handler
jr k0
nop
END(excep_ejtag)
2 changes: 2 additions & 0 deletions arch/mips/kernel/cpu-probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,10 @@ static void decode_configs(struct cpuinfo_mips *c)

mips_probe_watch_registers(c);

#ifndef CONFIG_MIPS_CPS
if (cpu_has_mips_r2)
c->core = read_c0_ebase() & 0x3ff;
#endif
}

#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \
Expand Down
Loading

0 comments on commit 0ee958e

Please sign in to comment.