From 2f6f31363cb7890784458d7805140687b4de5b59 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Thu, 17 Sep 2015 17:49:20 +0100 Subject: MIPS: cpu-features: Add cpu_has_ftlb Add cpu_has_ftlb, which specifies that an FTLB is present in addition to the VTLB, probed based on whether Config.MT == 4 (rather than 1 for standard JTLB). This is necessary since MIPS release 6 removes Config4.MMUExtDef, so the presence of the FTLB fields in Config4 must be determined from Config.MT instead. Signed-off-by: James Hogan Cc: Markos Chandras Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11159/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 3 +++ arch/mips/include/asm/cpu.h | 1 + arch/mips/include/asm/mipsregs.h | 2 ++ 3 files changed, 6 insertions(+) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 9801ac982655..fe67f12ac239 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -20,6 +20,9 @@ #ifndef cpu_has_tlb #define cpu_has_tlb (cpu_data[0].options & MIPS_CPU_TLB) #endif +#ifndef cpu_has_ftlb +#define cpu_has_ftlb (cpu_data[0].options & MIPS_CPU_FTLB) +#endif #ifndef cpu_has_tlbinv #define cpu_has_tlbinv (cpu_data[0].options & MIPS_CPU_TLBINV) #endif diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index cd89e9855775..82ad15f11049 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -385,6 +385,7 @@ enum cpu_type_enum { #define MIPS_CPU_CDMM 0x4000000000ull /* CPU has Common Device Memory Map */ #define MIPS_CPU_BP_GHIST 0x8000000000ull /* R12K+ Branch Prediction Global History */ #define MIPS_CPU_SP 0x10000000000ull /* Small (1KB) page support */ +#define MIPS_CPU_FTLB 0x20000000000ull /* CPU has Fixed-page-size TLB */ /* * CPU ASE encodings diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index d3cd8eac81e3..c64781cf649f 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -487,6 +487,8 @@ /* Bits specific to the MIPS32/64 PRA. */ #define MIPS_CONF_MT (_ULCAST_(7) << 7) +#define MIPS_CONF_MT_TLB (_ULCAST_(1) << 7) +#define MIPS_CONF_MT_FTLB (_ULCAST_(4) << 7) #define MIPS_CONF_AR (_ULCAST_(7) << 10) #define MIPS_CONF_AT (_ULCAST_(3) << 13) #define MIPS_CONF_M (_ULCAST_(1) << 31) -- cgit v1.2.3 From 7573b94e08aeb5b814e2f277210bdcdf21a83869 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:29:09 -0700 Subject: MIPS: CM: Provide a function to map from CPU to VP ID. The VP ID of a given CPU may not match up with the CPU number used by Linux. For example, if the width of the VP part of the VP ID is wider than log2(number of VPs per core) and the system has multiple cores then this will be the case. Alternatively, if a pre-r6 system implements the MT ASE with multiple VPEs per core and Linux is built without support for the MT ASE then the numbers won't match up either. Provide a function to convert from CPU number to VP ID. Signed-off-by: Paul Burton Acked-by: Thomas Gleixner Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: James Hogan Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11211/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-cm.h | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index d75b75e78ebb..1f1927ab4269 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -194,6 +194,7 @@ BUILD_CM_RW(reg3_mask, MIPS_CM_GCB_OFS + 0xc8) BUILD_CM_R_(gic_status, MIPS_CM_GCB_OFS + 0xd0) BUILD_CM_R_(cpc_status, MIPS_CM_GCB_OFS + 0xf0) BUILD_CM_RW(l2_config, MIPS_CM_GCB_OFS + 0x130) +BUILD_CM_RW(sys_config2, MIPS_CM_GCB_OFS + 0x150) /* Core Local & Core Other register accessor functions */ BUILD_CM_Cx_RW(reset_release, 0x00) @@ -316,6 +317,10 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80) #define CM_GCR_L2_CONFIG_ASSOC_SHF 0 #define CM_GCR_L2_CONFIG_ASSOC_MSK (_ULCAST_(0xff) << 0) +/* GCR_SYS_CONFIG2 register fields */ +#define CM_GCR_SYS_CONFIG2_MAXVPW_SHF 0 +#define CM_GCR_SYS_CONFIG2_MAXVPW_MSK (_ULCAST_(0xf) << 0) + /* GCR_Cx_COHERENCE register fields */ #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_SHF 0 #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_MSK (_ULCAST_(0xff) << 0) @@ -405,4 +410,38 @@ static inline int mips_cm_revision(void) return read_gcr_rev(); } +/** + * mips_cm_max_vp_width() - return the width in bits of VP indices + * + * Return: the width, in bits, of VP indices in fields that combine core & VP + * indices. + */ +static inline unsigned int mips_cm_max_vp_width(void) +{ + extern int smp_num_siblings; + + if (mips_cm_revision() >= CM_REV_CM3) + return read_gcr_sys_config2() & CM_GCR_SYS_CONFIG2_MAXVPW_MSK; + + return smp_num_siblings; +} + +/** + * mips_cm_vp_id() - calculate the hardware VP ID for a CPU + * @cpu: the CPU whose VP ID to calculate + * + * Hardware such as the GIC uses identifiers for VPs which may not match the + * CPU numbers used by Linux. This function calculates the hardware VP + * identifier corresponding to a given CPU. + * + * Return: the VP ID for the CPU. + */ +static inline unsigned int mips_cm_vp_id(unsigned int cpu) +{ + unsigned int core = cpu_data[cpu].core; + unsigned int vp = cpu_vpe_id(&cpu_data[cpu]); + + return (core * mips_cm_max_vp_width()) + vp; +} + #endif /* __MIPS_ASM_MIPS_CM_H__ */ -- cgit v1.2.3 From e060f6ed281669b6d2f22d8dafd664b532386918 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 25 Sep 2015 08:59:38 -0700 Subject: MIPS: Initialise MAARs on secondary CPUs MAARs should be initialised on each CPU (or rather, core) in the system in order to achieve consistent behaviour & performance. Previously they have only been initialised on the boot CPU which leads to performance problems if tasks are later scheduled on a secondary CPU, particularly if those tasks make use of unaligned vector accesses where some CPUs don't handle any cases in hardware for non-speculative memory regions. Fix this by recording the MAAR configuration from the boot CPU and applying it to secondary CPUs as part of their bringup. Reported-by: Doug Gilmore Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Rusty Russell Cc: Steven J. Hill Cc: Andrew Bresticker Cc: Bjorn Helgaas Cc: David Hildenbrand Cc: linux-kernel@vger.kernel.org Cc: Aaro Koskinen Cc: James Hogan Cc: Ingo Molnar Cc: Markos Chandras Cc: Hemmo Nieminen Cc: Alex Smith Cc: Peter Zijlstra (Intel) Patchwork: https://patchwork.linux-mips.org/patch/11239/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/maar.h | 9 +++++++++ arch/mips/kernel/smp.c | 2 ++ arch/mips/mm/init.c | 28 +++++++++++++++++++++++++--- 3 files changed, 36 insertions(+), 3 deletions(-) (limited to 'arch/mips/include/asm') diff --git a/arch/mips/include/asm/maar.h b/arch/mips/include/asm/maar.h index b02891f9caaf..21d9607c80d7 100644 --- a/arch/mips/include/asm/maar.h +++ b/arch/mips/include/asm/maar.h @@ -65,6 +65,15 @@ static inline void write_maar_pair(unsigned idx, phys_addr_t lower, back_to_back_c0_hazard(); } +/** + * maar_init() - initialise MAARs + * + * Performs initialisation of MAARs for the current CPU, making use of the + * platforms implementation of platform_maar_init where necessary and + * duplicating the setup it provides on secondary CPUs. + */ +extern void maar_init(void); + /** * struct maar_config - MAAR configuration data * @lower: The lowest address that the MAAR pair will affect. Must be diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index a31896c33716..bd4385a8e6e8 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -42,6 +42,7 @@ #include #include #include +#include cpumask_t cpu_callin_map; /* Bitmask of started secondaries */ @@ -157,6 +158,7 @@ asmlinkage void start_secondary(void) mips_clockevent_init(); mp_ops->init_secondary(); cpu_report(); + maar_init(); /* * XXX parity protection should be folded in here when it's converted diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 023c164b9eb6..8770e619185e 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -44,6 +44,7 @@ #include #include #include +#include /* * We have up to 8 empty zeroed pages so we can map one of the right colour @@ -288,10 +289,14 @@ unsigned __weak platform_maar_init(unsigned num_pairs) return num_configured; } -static void maar_init(void) +void maar_init(void) { unsigned num_maars, used, i; phys_addr_t lower, upper, attr; + static struct { + struct maar_config cfgs[3]; + unsigned used; + } recorded = { { { 0 } }, 0 }; if (!cpu_has_maar) return; @@ -304,8 +309,14 @@ static void maar_init(void) /* MAARs should be in pairs */ WARN_ON(num_maars % 2); - /* Configure the required MAARs */ - used = platform_maar_init(num_maars / 2); + /* Set MAARs using values we recorded already */ + if (recorded.used) { + used = maar_config(recorded.cfgs, recorded.used, num_maars / 2); + BUG_ON(used != recorded.used); + } else { + /* Configure the required MAARs */ + used = platform_maar_init(num_maars / 2); + } /* Disable any further MAARs */ for (i = (used * 2); i < num_maars; i++) { @@ -315,6 +326,9 @@ static void maar_init(void) back_to_back_c0_hazard(); } + if (recorded.used) + return; + pr_info("MAAR configuration:\n"); for (i = 0; i < num_maars; i += 2) { write_c0_maari(i); @@ -341,6 +355,14 @@ static void maar_init(void) pr_cont(" speculate"); pr_cont("\n"); + + /* Record the setup for use on secondary CPUs */ + if (used <= ARRAY_SIZE(recorded.cfgs)) { + recorded.cfgs[recorded.used].lower = lower; + recorded.cfgs[recorded.used].upper = upper; + recorded.cfgs[recorded.used].attrs = attr; + recorded.used++; + } } } -- cgit v1.2.3