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: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> Acked-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
4c703416ef
commit
0440705049
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue