Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 04407050 authored by Mahesh Salgaonkar's avatar Mahesh Salgaonkar Committed by Benjamin Herrenschmidt
Browse files

powerpc/book3s: Add flush_tlb operation in cpu_spec.



This patch introduces flush_tlb operation in cpu_spec structure. This will
help us to invoke appropriate CPU-side flush tlb routine. This patch
adds the foundation to invoke CPU specific flush routine for respective
architectures. Currently this patch introduce flush_tlb for p7 and p8.

Signed-off-by: default avatarMahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Acked-by: default avatarPaul Mackerras <paulus@samba.org>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 4c703416
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -97,6 +97,11 @@ struct cpu_spec {
	 */
	long		(*machine_check_early)(struct pt_regs *regs);

	/*
	 * Processor specific routine to flush tlbs.
	 */
	void		(*flush_tlb)(unsigned long inval_selector);

};

extern struct cpu_spec		*cur_cpu_spec;
+27 −11
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ _GLOBAL(__setup_cpu_power7)
	mtspr	SPRN_LPID,r0
	mfspr	r3,SPRN_LPCR
	bl	__init_LPCR
	bl	__init_TLB
	bl	__init_tlb_power7
	mtlr	r11
	blr

@@ -42,7 +42,7 @@ _GLOBAL(__restore_cpu_power7)
	mtspr	SPRN_LPID,r0
	mfspr	r3,SPRN_LPCR
	bl	__init_LPCR
	bl	__init_TLB
	bl	__init_tlb_power7
	mtlr	r11
	blr

@@ -59,7 +59,7 @@ _GLOBAL(__setup_cpu_power8)
	oris	r3, r3, LPCR_AIL_3@h
	bl	__init_LPCR
	bl	__init_HFSCR
	bl	__init_TLB
	bl	__init_tlb_power8
	bl	__init_PMU_HV
	mtlr	r11
	blr
@@ -78,7 +78,7 @@ _GLOBAL(__restore_cpu_power8)
	oris	r3, r3, LPCR_AIL_3@h
	bl	__init_LPCR
	bl	__init_HFSCR
	bl	__init_TLB
	bl	__init_tlb_power8
	bl	__init_PMU_HV
	mtlr	r11
	blr
@@ -134,15 +134,31 @@ __init_HFSCR:
	mtspr	SPRN_HFSCR,r3
	blr

__init_TLB:
/*
	 * Clear the TLB using the "IS 3" form of tlbiel instruction
	 * (invalidate by congruence class). P7 has 128 CCs, P8 has 512
	 * so we just always do 512
 * Clear the TLB using the specified IS form of tlbiel instruction
 * (invalidate by congruence class). P7 has 128 CCs., P8 has 512.
 *
 * r3 = IS field
 */
__init_tlb_power7:
	li	r3,0xc00	/* IS field = 0b11 */
_GLOBAL(__flush_tlb_power7)
	li	r6,128
	mtctr	r6
	mr	r7,r3		/* IS field */
	ptesync
2:	tlbiel	r7
	addi	r7,r7,0x1000
	bdnz	2b
	ptesync
1:	blr

__init_tlb_power8:
	li	r3,0xc00	/* IS field = 0b11 */
_GLOBAL(__flush_tlb_power8)
	li	r6,512
	mtctr	r6
	li	r7,0xc00	/* IS field = 0b11 */
	mr	r7,r3		/* IS field */
	ptesync
2:	tlbiel	r7
	addi	r7,r7,0x1000
+8 −0
Original line number Diff line number Diff line
@@ -71,6 +71,8 @@ extern void __restore_cpu_power7(void);
extern void __setup_cpu_power8(unsigned long offset, struct cpu_spec* spec);
extern void __restore_cpu_power8(void);
extern void __restore_cpu_a2(void);
extern void __flush_tlb_power7(unsigned long inval_selector);
extern void __flush_tlb_power8(unsigned long inval_selector);
#endif /* CONFIG_PPC64 */
#if defined(CONFIG_E500)
extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec);
@@ -440,6 +442,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
		.oprofile_cpu_type	= "ppc64/ibm-compat-v1",
		.cpu_setup		= __setup_cpu_power7,
		.cpu_restore		= __restore_cpu_power7,
		.flush_tlb		= __flush_tlb_power7,
		.platform		= "power7",
	},
	{	/* 2.07-compliant processor, i.e. Power8 "architected" mode */
@@ -456,6 +459,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
		.oprofile_cpu_type	= "ppc64/ibm-compat-v1",
		.cpu_setup		= __setup_cpu_power8,
		.cpu_restore		= __restore_cpu_power8,
		.flush_tlb		= __flush_tlb_power8,
		.platform		= "power8",
	},
	{	/* Power7 */
@@ -474,6 +478,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
		.oprofile_type		= PPC_OPROFILE_POWER4,
		.cpu_setup		= __setup_cpu_power7,
		.cpu_restore		= __restore_cpu_power7,
		.flush_tlb		= __flush_tlb_power7,
		.platform		= "power7",
	},
	{	/* Power7+ */
@@ -492,6 +497,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
		.oprofile_type		= PPC_OPROFILE_POWER4,
		.cpu_setup		= __setup_cpu_power7,
		.cpu_restore		= __restore_cpu_power7,
		.flush_tlb		= __flush_tlb_power7,
		.platform		= "power7+",
	},
	{	/* Power8E */
@@ -510,6 +516,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
		.oprofile_type		= PPC_OPROFILE_INVALID,
		.cpu_setup		= __setup_cpu_power8,
		.cpu_restore		= __restore_cpu_power8,
		.flush_tlb		= __flush_tlb_power8,
		.platform		= "power8",
	},
	{	/* Power8 */
@@ -528,6 +535,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
		.oprofile_type		= PPC_OPROFILE_INVALID,
		.cpu_setup		= __setup_cpu_power8,
		.cpu_restore		= __restore_cpu_power8,
		.flush_tlb		= __flush_tlb_power8,
		.platform		= "power8",
	},
	{	/* Cell Broadband Engine */
+4 −14
Original line number Diff line number Diff line
@@ -58,18 +58,6 @@ static void reload_slb(struct kvm_vcpu *vcpu)
	}
}

/* POWER7 TLB flush */
static void flush_tlb_power7(struct kvm_vcpu *vcpu)
{
	unsigned long i, rb;

	rb = TLBIEL_INVAL_SET_LPID;
	for (i = 0; i < POWER7_TLB_SETS; ++i) {
		asm volatile("tlbiel %0" : : "r" (rb));
		rb += 1 << TLBIEL_INVAL_SET_SHIFT;
	}
}

/*
 * On POWER7, see if we can handle a machine check that occurred inside
 * the guest in real mode, without switching to the host partition.
@@ -96,7 +84,8 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
				   DSISR_MC_SLB_PARITY | DSISR_MC_DERAT_MULTI);
		}
		if (dsisr & DSISR_MC_TLB_MULTI) {
			flush_tlb_power7(vcpu);
			if (cur_cpu_spec && cur_cpu_spec->flush_tlb)
				cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET_LPID);
			dsisr &= ~DSISR_MC_TLB_MULTI;
		}
		/* Any other errors we don't understand? */
@@ -113,7 +102,8 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
		reload_slb(vcpu);
		break;
	case SRR1_MC_IFETCH_TLBMULTI:
		flush_tlb_power7(vcpu);
		if (cur_cpu_spec && cur_cpu_spec->flush_tlb)
			cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET_LPID);
		break;
	default:
		handled = 0;