MIPS: Support extended ASIDs

Add support for extended ASIDs as determined by the Config4.AE bit.
Since the only supported CPUs known to implement this are Netlogic XLP
and MIPS I6400, select this variable ASID support based upon
CONFIG_CPU_XLP and CONFIG_CPU_MIPSR6.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Jayachandran C. <jchandra@broadcom.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <rkrcmar@redhat.com>
Cc: linux-mips@linux-mips.org
Cc: kvm@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/13211/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
Paul Burton 2016-05-06 14:36:24 +01:00 committed by Ralf Baechle
parent 4edf00a46b
commit 2db003a5dd
6 changed files with 58 additions and 1 deletions

View File

@ -1706,6 +1706,7 @@ config CPU_XLP
select CPU_HAS_PREFETCH
select CPU_MIPSR2
select CPU_SUPPORTS_HUGEPAGES
select MIPS_ASID_BITS_VARIABLE
help
Netlogic Microsystems XLP processors.
endchoice
@ -2001,6 +2002,7 @@ config CPU_MIPSR6
bool
default y if CPU_MIPS32_R6 || CPU_MIPS64_R6
select HAVE_ARCH_BITREVERSE
select MIPS_ASID_BITS_VARIABLE
select MIPS_SPRAM
config EVA
@ -2457,9 +2459,13 @@ config MIPS_ASID_SHIFT
config MIPS_ASID_BITS
int
default 0 if MIPS_ASID_BITS_VARIABLE
default 6 if CPU_R3000 || CPU_TX39XX
default 8
config MIPS_ASID_BITS_VARIABLE
bool
#
# - Highmem only makes sense for the 32-bit kernel.
# - The current highmem code will only work properly on physically indexed

View File

@ -40,6 +40,9 @@ struct cache_desc {
struct cpuinfo_mips {
unsigned long asid_cache;
#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
unsigned long asid_mask;
#endif
/*
* Capability and feature descriptor structure for MIPS CPU
@ -139,7 +142,18 @@ static inline unsigned long cpu_asid_inc(void)
static inline unsigned long cpu_asid_mask(struct cpuinfo_mips *cpuinfo)
{
#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
return cpuinfo->asid_mask;
#endif
return ((1 << CONFIG_MIPS_ASID_BITS) - 1) << CONFIG_MIPS_ASID_SHIFT;
}
static inline void set_cpu_asid_mask(struct cpuinfo_mips *cpuinfo,
unsigned long asid_mask)
{
#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
cpuinfo->asid_mask = asid_mask;
#endif
}
#endif /* __ASM_CPU_INFO_H */

View File

@ -14,6 +14,7 @@
#include <linux/mm.h>
#include <linux/kbuild.h>
#include <linux/suspend.h>
#include <asm/cpu-info.h>
#include <asm/pm.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
@ -338,6 +339,15 @@ void output_pm_defines(void)
}
#endif
void output_cpuinfo_defines(void)
{
COMMENT(" MIPS cpuinfo offsets. ");
DEFINE(CPUINFO_SIZE, sizeof(struct cpuinfo_mips));
#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
OFFSET(CPUINFO_ASID_MASK, cpuinfo_mips, asid_mask);
#endif
}
void output_kvm_defines(void)
{
COMMENT(" KVM/MIPS Specfic offsets. ");

View File

@ -732,6 +732,7 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c)
unsigned int newcf4;
unsigned int mmuextdef;
unsigned int ftlb_page = MIPS_CONF4_FTLBPAGESIZE;
unsigned long asid_mask;
config4 = read_c0_config4();
@ -792,6 +793,18 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c)
c->kscratch_mask = (config4 >> 16) & 0xff;
asid_mask = MIPS_ENTRYHI_ASID;
if (config4 & MIPS_CONF4_AE)
asid_mask |= MIPS_ENTRYHI_ASIDX;
set_cpu_asid_mask(c, asid_mask);
/*
* Warn if the computed ASID mask doesn't match the mask the kernel
* is built for. This may indicate either a serious problem or an
* easy optimisation opportunity, but either way should be addressed.
*/
WARN_ON(asid_mask != cpu_asid_mask(c));
return config4 & MIPS_CONF_M;
}

View File

@ -455,7 +455,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
.set noreorder
/* check if TLB contains a entry for EPC */
MFC0 k1, CP0_ENTRYHI
andi k1, MIPS_ENTRYHI_ASID
andi k1, MIPS_ENTRYHI_ASID | MIPS_ENTRYHI_ASIDX
MFC0 k0, CP0_EPC
PTR_SRL k0, _PAGE_SHIFT + 1
PTR_SLL k0, _PAGE_SHIFT + 1

View File

@ -137,7 +137,14 @@ FEXPORT(__kvm_mips_load_asid)
INT_SLL t2, t2, 2 /* x4 */
REG_ADDU t3, t1, t2
LONG_L k0, (t3)
#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
li t3, CPUINFO_SIZE/4
mul t2, t2, t3 /* x sizeof(struct cpuinfo_mips)/4 */
LONG_L t2, (cpu_data + CPUINFO_ASID_MASK)(t2)
and k0, k0, t2
#else
andi k0, k0, MIPS_ENTRYHI_ASID
#endif
mtc0 k0, CP0_ENTRYHI
ehb
@ -449,7 +456,14 @@ __kvm_mips_return_to_guest:
INT_SLL t2, t2, 2 /* x4 */
REG_ADDU t3, t1, t2
LONG_L k0, (t3)
#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
li t3, CPUINFO_SIZE/4
mul t2, t2, t3 /* x sizeof(struct cpuinfo_mips)/4 */
LONG_L t2, (cpu_data + CPUINFO_ASID_MASK)(t2)
and k0, k0, t2
#else
andi k0, k0, MIPS_ENTRYHI_ASID
#endif
mtc0 k0, CP0_ENTRYHI
ehb