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

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
...@@ -97,6 +97,11 @@ struct cpu_spec { ...@@ -97,6 +97,11 @@ struct cpu_spec {
*/ */
long (*machine_check_early)(struct pt_regs *regs); 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; extern struct cpu_spec *cur_cpu_spec;
......
...@@ -29,7 +29,7 @@ _GLOBAL(__setup_cpu_power7) ...@@ -29,7 +29,7 @@ _GLOBAL(__setup_cpu_power7)
mtspr SPRN_LPID,r0 mtspr SPRN_LPID,r0
mfspr r3,SPRN_LPCR mfspr r3,SPRN_LPCR
bl __init_LPCR bl __init_LPCR
bl __init_TLB bl __init_tlb_power7
mtlr r11 mtlr r11
blr blr
...@@ -42,7 +42,7 @@ _GLOBAL(__restore_cpu_power7) ...@@ -42,7 +42,7 @@ _GLOBAL(__restore_cpu_power7)
mtspr SPRN_LPID,r0 mtspr SPRN_LPID,r0
mfspr r3,SPRN_LPCR mfspr r3,SPRN_LPCR
bl __init_LPCR bl __init_LPCR
bl __init_TLB bl __init_tlb_power7
mtlr r11 mtlr r11
blr blr
...@@ -59,7 +59,7 @@ _GLOBAL(__setup_cpu_power8) ...@@ -59,7 +59,7 @@ _GLOBAL(__setup_cpu_power8)
oris r3, r3, LPCR_AIL_3@h oris r3, r3, LPCR_AIL_3@h
bl __init_LPCR bl __init_LPCR
bl __init_HFSCR bl __init_HFSCR
bl __init_TLB bl __init_tlb_power8
bl __init_PMU_HV bl __init_PMU_HV
mtlr r11 mtlr r11
blr blr
...@@ -78,7 +78,7 @@ _GLOBAL(__restore_cpu_power8) ...@@ -78,7 +78,7 @@ _GLOBAL(__restore_cpu_power8)
oris r3, r3, LPCR_AIL_3@h oris r3, r3, LPCR_AIL_3@h
bl __init_LPCR bl __init_LPCR
bl __init_HFSCR bl __init_HFSCR
bl __init_TLB bl __init_tlb_power8
bl __init_PMU_HV bl __init_PMU_HV
mtlr r11 mtlr r11
blr blr
...@@ -134,15 +134,31 @@ __init_HFSCR: ...@@ -134,15 +134,31 @@ __init_HFSCR:
mtspr SPRN_HFSCR,r3 mtspr SPRN_HFSCR,r3
blr blr
__init_TLB: /*
/* * Clear the TLB using the specified IS form of tlbiel instruction
* Clear the TLB using the "IS 3" form of tlbiel instruction * (invalidate by congruence class). P7 has 128 CCs., P8 has 512.
* (invalidate by congruence class). P7 has 128 CCs, P8 has 512 *
* so we just always do 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 li r6,512
mtctr r6 mtctr r6
li r7,0xc00 /* IS field = 0b11 */ mr r7,r3 /* IS field */
ptesync ptesync
2: tlbiel r7 2: tlbiel r7
addi r7,r7,0x1000 addi r7,r7,0x1000
......
...@@ -71,6 +71,8 @@ extern void __restore_cpu_power7(void); ...@@ -71,6 +71,8 @@ extern void __restore_cpu_power7(void);
extern void __setup_cpu_power8(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_power8(unsigned long offset, struct cpu_spec* spec);
extern void __restore_cpu_power8(void); extern void __restore_cpu_power8(void);
extern void __restore_cpu_a2(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 */ #endif /* CONFIG_PPC64 */
#if defined(CONFIG_E500) #if defined(CONFIG_E500)
extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec);
...@@ -440,6 +442,7 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -440,6 +442,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.oprofile_cpu_type = "ppc64/ibm-compat-v1", .oprofile_cpu_type = "ppc64/ibm-compat-v1",
.cpu_setup = __setup_cpu_power7, .cpu_setup = __setup_cpu_power7,
.cpu_restore = __restore_cpu_power7, .cpu_restore = __restore_cpu_power7,
.flush_tlb = __flush_tlb_power7,
.platform = "power7", .platform = "power7",
}, },
{ /* 2.07-compliant processor, i.e. Power8 "architected" mode */ { /* 2.07-compliant processor, i.e. Power8 "architected" mode */
...@@ -456,6 +459,7 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -456,6 +459,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.oprofile_cpu_type = "ppc64/ibm-compat-v1", .oprofile_cpu_type = "ppc64/ibm-compat-v1",
.cpu_setup = __setup_cpu_power8, .cpu_setup = __setup_cpu_power8,
.cpu_restore = __restore_cpu_power8, .cpu_restore = __restore_cpu_power8,
.flush_tlb = __flush_tlb_power8,
.platform = "power8", .platform = "power8",
}, },
{ /* Power7 */ { /* Power7 */
...@@ -474,6 +478,7 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -474,6 +478,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.oprofile_type = PPC_OPROFILE_POWER4, .oprofile_type = PPC_OPROFILE_POWER4,
.cpu_setup = __setup_cpu_power7, .cpu_setup = __setup_cpu_power7,
.cpu_restore = __restore_cpu_power7, .cpu_restore = __restore_cpu_power7,
.flush_tlb = __flush_tlb_power7,
.platform = "power7", .platform = "power7",
}, },
{ /* Power7+ */ { /* Power7+ */
...@@ -492,6 +497,7 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -492,6 +497,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.oprofile_type = PPC_OPROFILE_POWER4, .oprofile_type = PPC_OPROFILE_POWER4,
.cpu_setup = __setup_cpu_power7, .cpu_setup = __setup_cpu_power7,
.cpu_restore = __restore_cpu_power7, .cpu_restore = __restore_cpu_power7,
.flush_tlb = __flush_tlb_power7,
.platform = "power7+", .platform = "power7+",
}, },
{ /* Power8E */ { /* Power8E */
...@@ -510,6 +516,7 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -510,6 +516,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.oprofile_type = PPC_OPROFILE_INVALID, .oprofile_type = PPC_OPROFILE_INVALID,
.cpu_setup = __setup_cpu_power8, .cpu_setup = __setup_cpu_power8,
.cpu_restore = __restore_cpu_power8, .cpu_restore = __restore_cpu_power8,
.flush_tlb = __flush_tlb_power8,
.platform = "power8", .platform = "power8",
}, },
{ /* Power8 */ { /* Power8 */
...@@ -528,6 +535,7 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -528,6 +535,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.oprofile_type = PPC_OPROFILE_INVALID, .oprofile_type = PPC_OPROFILE_INVALID,
.cpu_setup = __setup_cpu_power8, .cpu_setup = __setup_cpu_power8,
.cpu_restore = __restore_cpu_power8, .cpu_restore = __restore_cpu_power8,
.flush_tlb = __flush_tlb_power8,
.platform = "power8", .platform = "power8",
}, },
{ /* Cell Broadband Engine */ { /* Cell Broadband Engine */
......
...@@ -58,18 +58,6 @@ static void reload_slb(struct kvm_vcpu *vcpu) ...@@ -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 * On POWER7, see if we can handle a machine check that occurred inside
* the guest in real mode, without switching to the host partition. * 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) ...@@ -96,7 +84,8 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
DSISR_MC_SLB_PARITY | DSISR_MC_DERAT_MULTI); DSISR_MC_SLB_PARITY | DSISR_MC_DERAT_MULTI);
} }
if (dsisr & DSISR_MC_TLB_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; dsisr &= ~DSISR_MC_TLB_MULTI;
} }
/* Any other errors we don't understand? */ /* Any other errors we don't understand? */
...@@ -113,7 +102,8 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu) ...@@ -113,7 +102,8 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
reload_slb(vcpu); reload_slb(vcpu);
break; break;
case SRR1_MC_IFETCH_TLBMULTI: 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; break;
default: default:
handled = 0; handled = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment