Commit 06e4814e authored by Huacai Chen's avatar Huacai Chen Committed by Ralf Baechle
Browse files

MIPS: Loongson: Invalidate special TLBs when needed



Loongson-2 has a 4 entry itlb which is a subset of jtlb, Loongson-3 has
a 4 entry itlb and a 4 entry dtlb which are subsets of jtlb. We should
write diag register to invalidate itlb/dtlb when flushing jtlb because
itlb/dtlb are not totally transparent to software.

For Loongson-3A R2 (and newer), we should invalidate ITLB, DTLB, VTLB
and FTLB before we enable/disable FTLB.

Signed-off-by: default avatarHuacai Chen <chenhc@lemote.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Steven J . Hill <sjhill@realitydiluted.com>
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/12753/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 37fbe8fa
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -780,6 +780,15 @@
/* Disable Branch Return Cache */
#define R10K_DIAG_D_BRC		(_ULCAST_(1) << 22)

/* Flush ITLB */
#define LOONGSON_DIAG_ITLB	(_ULCAST_(1) << 2)
/* Flush DTLB */
#define LOONGSON_DIAG_DTLB	(_ULCAST_(1) << 3)
/* Flush VTLB */
#define LOONGSON_DIAG_VTLB	(_ULCAST_(1) << 12)
/* Flush FTLB */
#define LOONGSON_DIAG_FTLB	(_ULCAST_(1) << 13)

/*
 * Coprocessor 1 (FPU) register names
 */
+3 −0
Original line number Diff line number Diff line
@@ -563,6 +563,9 @@ static int set_ftlb_enable(struct cpuinfo_mips *c, int enable)
					   << MIPS_CONF7_FTLBP_SHIFT));
		break;
	case CPU_LOONGSON3:
		/* Flush ITLB, DTLB, VTLB and FTLB */
		write_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB |
			      LOONGSON_DIAG_VTLB | LOONGSON_DIAG_FTLB);
		/* Loongson-3 cores use Config6 to enable the FTLB */
		config = read_c0_config6();
		if (enable)
+15 −12
Original line number Diff line number Diff line
@@ -28,25 +28,28 @@
extern void build_tlb_refill_handler(void);

/*
 * LOONGSON2/3 has a 4 entry itlb which is a subset of dtlb,
 * unfortunately, itlb is not totally transparent to software.
 * LOONGSON-2 has a 4 entry itlb which is a subset of jtlb, LOONGSON-3 has
 * a 4 entry itlb and a 4 entry dtlb which are subsets of jtlb. Unfortunately,
 * itlb/dtlb are not totally transparent to software.
 */
static inline void flush_itlb(void)
static inline void flush_micro_tlb(void)
{
	switch (current_cpu_type()) {
	case CPU_LOONGSON2:
		write_c0_diag(LOONGSON_DIAG_ITLB);
		break;
	case CPU_LOONGSON3:
		write_c0_diag(4);
		write_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB);
		break;
	default:
		break;
	}
}

static inline void flush_itlb_vm(struct vm_area_struct *vma)
static inline void flush_micro_tlb_vm(struct vm_area_struct *vma)
{
	if (vma->vm_flags & VM_EXEC)
		flush_itlb();
		flush_micro_tlb();
}

void local_flush_tlb_all(void)
@@ -93,7 +96,7 @@ void local_flush_tlb_all(void)
	tlbw_use_hazard();
	write_c0_entryhi(old_ctx);
	htw_start();
	flush_itlb();
	flush_micro_tlb();
	local_irq_restore(flags);
}
EXPORT_SYMBOL(local_flush_tlb_all);
@@ -159,7 +162,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
		} else {
			drop_mmu_context(mm, cpu);
		}
		flush_itlb();
		flush_micro_tlb();
		local_irq_restore(flags);
	}
}
@@ -205,7 +208,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
	} else {
		local_flush_tlb_all();
	}
	flush_itlb();
	flush_micro_tlb();
	local_irq_restore(flags);
}

@@ -240,7 +243,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
	finish:
		write_c0_entryhi(oldpid);
		htw_start();
		flush_itlb_vm(vma);
		flush_micro_tlb_vm(vma);
		local_irq_restore(flags);
	}
}
@@ -274,7 +277,7 @@ void local_flush_tlb_one(unsigned long page)
	}
	write_c0_entryhi(oldpid);
	htw_start();
	flush_itlb();
	flush_micro_tlb();
	local_irq_restore(flags);
}

@@ -357,7 +360,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
	}
	tlbw_use_hazard();
	htw_start();
	flush_itlb_vm(vma);
	flush_micro_tlb_vm(vma);
	local_irq_restore(flags);
}