Commit 54be0b9c authored by Michael Ellerman's avatar Michael Ellerman

Revert "convert SLB miss handlers to C" and subsequent commits

This reverts commits:
  5e46e29e ("powerpc/64s/hash: convert SLB miss handlers to C")
  8fed04d0 ("powerpc/64s/hash: remove user SLB data from the paca")
  655deecf ("powerpc/64s/hash: SLB allocation status bitmaps")
  2e162674 ("powerpc/64s/hash: provide arch_setup_exec hooks for hash slice setup")
  89ca4e12 ("powerpc/64s/hash: Add a SLB preload cache")

This series had a few bugs, and the fixes are not all trivial. So
revert most of it for now.
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 0823c68b
...@@ -78,8 +78,6 @@ void kernel_bad_stack(struct pt_regs *regs); ...@@ -78,8 +78,6 @@ void kernel_bad_stack(struct pt_regs *regs);
void system_reset_exception(struct pt_regs *regs); void system_reset_exception(struct pt_regs *regs);
void machine_check_exception(struct pt_regs *regs); void machine_check_exception(struct pt_regs *regs);
void emulation_assist_interrupt(struct pt_regs *regs); void emulation_assist_interrupt(struct pt_regs *regs);
long do_slb_fault(struct pt_regs *regs, unsigned long ea);
void do_bad_slb_fault(struct pt_regs *regs, unsigned long ea, long err);
/* signals, syscalls and interrupts */ /* signals, syscalls and interrupts */
long sys_swapcontext(struct ucontext __user *old_ctx, long sys_swapcontext(struct ucontext __user *old_ctx,
......
...@@ -487,8 +487,6 @@ int htab_remove_mapping(unsigned long vstart, unsigned long vend, ...@@ -487,8 +487,6 @@ int htab_remove_mapping(unsigned long vstart, unsigned long vend,
extern void pseries_add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages); extern void pseries_add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages);
extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr); extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr);
extern void hash__setup_new_exec(void);
#ifdef CONFIG_PPC_PSERIES #ifdef CONFIG_PPC_PSERIES
void hpte_init_pseries(void); void hpte_init_pseries(void);
#else #else
...@@ -503,7 +501,6 @@ struct slb_entry { ...@@ -503,7 +501,6 @@ struct slb_entry {
}; };
extern void slb_initialize(void); extern void slb_initialize(void);
extern void core_flush_all_slbs(struct mm_struct *mm);
extern void slb_flush_and_rebolt(void); extern void slb_flush_and_rebolt(void);
void slb_flush_all_realmode(void); void slb_flush_all_realmode(void);
void __slb_restore_bolted_realmode(void); void __slb_restore_bolted_realmode(void);
......
...@@ -60,6 +60,14 @@ ...@@ -60,6 +60,14 @@
*/ */
#define MAX_MCE_DEPTH 4 #define MAX_MCE_DEPTH 4
/*
* EX_LR is only used in EXSLB and where it does not overlap with EX_DAR
* EX_CCR similarly with DSISR, but being 4 byte registers there is a hole
* in the save area so it's not necessary to overlap them. Could be used
* for future savings though if another 4 byte register was to be saved.
*/
#define EX_LR EX_DAR
/* /*
* EX_R3 is only used by the bad_stack handler. bad_stack reloads and * EX_R3 is only used by the bad_stack handler. bad_stack reloads and
* saves DAR from SPRN_DAR, and EX_DAR is not used. So EX_R3 can overlap * saves DAR from SPRN_DAR, and EX_DAR is not used. So EX_R3 can overlap
......
...@@ -113,10 +113,7 @@ struct paca_struct { ...@@ -113,10 +113,7 @@ struct paca_struct {
* on the linear mapping */ * on the linear mapping */
/* SLB related definitions */ /* SLB related definitions */
u16 vmalloc_sllp; u16 vmalloc_sllp;
u8 slb_cache_ptr; u16 slb_cache_ptr;
u8 stab_rr; /* stab/slb round-robin counter */
u32 slb_used_bitmap; /* Bitmaps for first 32 SLB entries. */
u32 slb_kern_bitmap;
u32 slb_cache[SLB_CACHE_ENTRIES]; u32 slb_cache[SLB_CACHE_ENTRIES];
#endif /* CONFIG_PPC_BOOK3S_64 */ #endif /* CONFIG_PPC_BOOK3S_64 */
...@@ -146,11 +143,24 @@ struct paca_struct { ...@@ -146,11 +143,24 @@ struct paca_struct {
struct tlb_core_data tcd; struct tlb_core_data tcd;
#endif /* CONFIG_PPC_BOOK3E */ #endif /* CONFIG_PPC_BOOK3E */
#ifdef CONFIG_PPC_BOOK3S
mm_context_id_t mm_ctx_id;
#ifdef CONFIG_PPC_MM_SLICES
unsigned char mm_ctx_low_slices_psize[BITS_PER_LONG / BITS_PER_BYTE];
unsigned char mm_ctx_high_slices_psize[SLICE_ARRAY_SIZE];
unsigned long mm_ctx_slb_addr_limit;
#else
u16 mm_ctx_user_psize;
u16 mm_ctx_sllp;
#endif
#endif
/* /*
* then miscellaneous read-write fields * then miscellaneous read-write fields
*/ */
struct task_struct *__current; /* Pointer to current */ struct task_struct *__current; /* Pointer to current */
u64 kstack; /* Saved Kernel stack addr */ u64 kstack; /* Saved Kernel stack addr */
u64 stab_rr; /* stab/slb round-robin counter */
u64 saved_r1; /* r1 save for RTAS calls or PM or EE=0 */ u64 saved_r1; /* r1 save for RTAS calls or PM or EE=0 */
u64 saved_msr; /* MSR saved here by enter_rtas */ u64 saved_msr; /* MSR saved here by enter_rtas */
u16 trap_save; /* Used when bad stack is encountered */ u16 trap_save; /* Used when bad stack is encountered */
...@@ -248,6 +258,7 @@ struct paca_struct { ...@@ -248,6 +258,7 @@ struct paca_struct {
#endif /* CONFIG_PPC_BOOK3S_64 */ #endif /* CONFIG_PPC_BOOK3S_64 */
} ____cacheline_aligned; } ____cacheline_aligned;
extern void copy_mm_to_paca(struct mm_struct *mm);
extern struct paca_struct **paca_ptrs; extern struct paca_struct **paca_ptrs;
extern void initialise_paca(struct paca_struct *new_paca, int cpu); extern void initialise_paca(struct paca_struct *new_paca, int cpu);
extern void setup_paca(struct paca_struct *new_paca); extern void setup_paca(struct paca_struct *new_paca);
......
...@@ -273,7 +273,6 @@ struct thread_struct { ...@@ -273,7 +273,6 @@ struct thread_struct {
#endif /* CONFIG_HAVE_HW_BREAKPOINT */ #endif /* CONFIG_HAVE_HW_BREAKPOINT */
struct arch_hw_breakpoint hw_brk; /* info on the hardware breakpoint */ struct arch_hw_breakpoint hw_brk; /* info on the hardware breakpoint */
unsigned long trap_nr; /* last trap # on this thread */ unsigned long trap_nr; /* last trap # on this thread */
u8 load_slb; /* Ages out SLB preload cache entries */
u8 load_fp; u8 load_fp;
#ifdef CONFIG_ALTIVEC #ifdef CONFIG_ALTIVEC
u8 load_vec; u8 load_vec;
......
...@@ -32,7 +32,6 @@ void slice_set_range_psize(struct mm_struct *mm, unsigned long start, ...@@ -32,7 +32,6 @@ void slice_set_range_psize(struct mm_struct *mm, unsigned long start,
unsigned long len, unsigned int psize); unsigned long len, unsigned int psize);
void slice_init_new_context_exec(struct mm_struct *mm); void slice_init_new_context_exec(struct mm_struct *mm);
void slice_setup_new_exec(void);
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include <asm/page.h> #include <asm/page.h>
#include <asm/accounting.h> #include <asm/accounting.h>
#define SLB_PRELOAD_NR 16U
/* /*
* low level task data. * low level task data.
*/ */
...@@ -45,10 +44,6 @@ struct thread_info { ...@@ -45,10 +44,6 @@ struct thread_info {
#if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE) && defined(CONFIG_PPC32) #if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE) && defined(CONFIG_PPC32)
struct cpu_accounting_data accounting; struct cpu_accounting_data accounting;
#endif #endif
u8 slb_preload_nr;
u8 slb_preload_tail;
u32 slb_preload_esid[SLB_PRELOAD_NR];
/* low level flags - has atomic operations done on it */ /* low level flags - has atomic operations done on it */
unsigned long flags ____cacheline_aligned_in_smp; unsigned long flags ____cacheline_aligned_in_smp;
}; };
...@@ -77,12 +72,6 @@ static inline struct thread_info *current_thread_info(void) ...@@ -77,12 +72,6 @@ static inline struct thread_info *current_thread_info(void)
} }
extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
#ifdef CONFIG_PPC_BOOK3S_64
void arch_setup_new_exec(void);
#define arch_setup_new_exec arch_setup_new_exec
#endif
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
/* /*
......
...@@ -173,6 +173,7 @@ int main(void) ...@@ -173,6 +173,7 @@ int main(void)
OFFSET(PACAKSAVE, paca_struct, kstack); OFFSET(PACAKSAVE, paca_struct, kstack);
OFFSET(PACACURRENT, paca_struct, __current); OFFSET(PACACURRENT, paca_struct, __current);
OFFSET(PACASAVEDMSR, paca_struct, saved_msr); OFFSET(PACASAVEDMSR, paca_struct, saved_msr);
OFFSET(PACASTABRR, paca_struct, stab_rr);
OFFSET(PACAR1, paca_struct, saved_r1); OFFSET(PACAR1, paca_struct, saved_r1);
OFFSET(PACATOC, paca_struct, kernel_toc); OFFSET(PACATOC, paca_struct, kernel_toc);
OFFSET(PACAKBASE, paca_struct, kernelbase); OFFSET(PACAKBASE, paca_struct, kernelbase);
...@@ -180,6 +181,15 @@ int main(void) ...@@ -180,6 +181,15 @@ int main(void)
OFFSET(PACAIRQSOFTMASK, paca_struct, irq_soft_mask); OFFSET(PACAIRQSOFTMASK, paca_struct, irq_soft_mask);
OFFSET(PACAIRQHAPPENED, paca_struct, irq_happened); OFFSET(PACAIRQHAPPENED, paca_struct, irq_happened);
OFFSET(PACA_FTRACE_ENABLED, paca_struct, ftrace_enabled); OFFSET(PACA_FTRACE_ENABLED, paca_struct, ftrace_enabled);
#ifdef CONFIG_PPC_BOOK3S
OFFSET(PACACONTEXTID, paca_struct, mm_ctx_id);
#ifdef CONFIG_PPC_MM_SLICES
OFFSET(PACALOWSLICESPSIZE, paca_struct, mm_ctx_low_slices_psize);
OFFSET(PACAHIGHSLICEPSIZE, paca_struct, mm_ctx_high_slices_psize);
OFFSET(PACA_SLB_ADDR_LIMIT, paca_struct, mm_ctx_slb_addr_limit);
DEFINE(MMUPSIZEDEFSIZE, sizeof(struct mmu_psize_def));
#endif /* CONFIG_PPC_MM_SLICES */
#endif
#ifdef CONFIG_PPC_BOOK3E #ifdef CONFIG_PPC_BOOK3E
OFFSET(PACAPGD, paca_struct, pgd); OFFSET(PACAPGD, paca_struct, pgd);
...@@ -202,7 +212,6 @@ int main(void) ...@@ -202,7 +212,6 @@ int main(void)
#ifdef CONFIG_PPC_BOOK3S_64 #ifdef CONFIG_PPC_BOOK3S_64
OFFSET(PACASLBCACHE, paca_struct, slb_cache); OFFSET(PACASLBCACHE, paca_struct, slb_cache);
OFFSET(PACASLBCACHEPTR, paca_struct, slb_cache_ptr); OFFSET(PACASLBCACHEPTR, paca_struct, slb_cache_ptr);
OFFSET(PACASTABRR, paca_struct, stab_rr);
OFFSET(PACAVMALLOCSLLP, paca_struct, vmalloc_sllp); OFFSET(PACAVMALLOCSLLP, paca_struct, vmalloc_sllp);
#ifdef CONFIG_PPC_MM_SLICES #ifdef CONFIG_PPC_MM_SLICES
OFFSET(MMUPSIZESLLP, mmu_psize_def, sllp); OFFSET(MMUPSIZESLLP, mmu_psize_def, sllp);
......
...@@ -596,36 +596,28 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) ...@@ -596,36 +596,28 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
EXC_REAL_BEGIN(data_access_slb, 0x380, 0x80) EXC_REAL_BEGIN(data_access_slb, 0x380, 0x80)
EXCEPTION_PROLOG(PACA_EXSLB, data_access_slb_common, EXC_STD, KVMTEST_PR, 0x380); SET_SCRATCH0(r13)
EXCEPTION_PROLOG_0(PACA_EXSLB)
EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x380)
mr r12,r3 /* save r3 */
mfspr r3,SPRN_DAR
mfspr r11,SPRN_SRR1
crset 4*cr6+eq
BRANCH_TO_COMMON(r10, slb_miss_common)
EXC_REAL_END(data_access_slb, 0x380, 0x80) EXC_REAL_END(data_access_slb, 0x380, 0x80)
EXC_VIRT_BEGIN(data_access_slb, 0x4380, 0x80) EXC_VIRT_BEGIN(data_access_slb, 0x4380, 0x80)
EXCEPTION_RELON_PROLOG(PACA_EXSLB, data_access_slb_common, EXC_STD, NOTEST, 0x380); SET_SCRATCH0(r13)
EXCEPTION_PROLOG_0(PACA_EXSLB)
EXCEPTION_PROLOG_1(PACA_EXSLB, NOTEST, 0x380)
mr r12,r3 /* save r3 */
mfspr r3,SPRN_DAR
mfspr r11,SPRN_SRR1
crset 4*cr6+eq
BRANCH_TO_COMMON(r10, slb_miss_common)
EXC_VIRT_END(data_access_slb, 0x4380, 0x80) EXC_VIRT_END(data_access_slb, 0x4380, 0x80)
TRAMP_KVM_SKIP(PACA_EXSLB, 0x380) TRAMP_KVM_SKIP(PACA_EXSLB, 0x380)
EXC_COMMON_BEGIN(data_access_slb_common)
mfspr r10,SPRN_DAR
std r10,PACA_EXSLB+EX_DAR(r13)
EXCEPTION_PROLOG_COMMON(0x380, PACA_EXSLB)
ld r4,PACA_EXSLB+EX_DAR(r13)
std r4,_DAR(r1)
addi r3,r1,STACK_FRAME_OVERHEAD
bl do_slb_fault
cmpdi r3,0
bne- 1f
b fast_exception_return
1: /* Error case */
std r3,RESULT(r1)
bl save_nvgprs
RECONCILE_IRQ_STATE(r10, r11)
ld r4,_DAR(r1)
ld r5,RESULT(r1)
addi r3,r1,STACK_FRAME_OVERHEAD
bl do_bad_slb_fault
b ret_from_except
EXC_REAL(instruction_access, 0x400, 0x80) EXC_REAL(instruction_access, 0x400, 0x80)
EXC_VIRT(instruction_access, 0x4400, 0x80, 0x400) EXC_VIRT(instruction_access, 0x4400, 0x80, 0x400)
...@@ -648,34 +640,160 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) ...@@ -648,34 +640,160 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
EXC_REAL_BEGIN(instruction_access_slb, 0x480, 0x80) EXC_REAL_BEGIN(instruction_access_slb, 0x480, 0x80)
EXCEPTION_PROLOG(PACA_EXSLB, instruction_access_slb_common, EXC_STD, KVMTEST_PR, 0x480); SET_SCRATCH0(r13)
EXCEPTION_PROLOG_0(PACA_EXSLB)
EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x480)
mr r12,r3 /* save r3 */
mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */
mfspr r11,SPRN_SRR1
crclr 4*cr6+eq
BRANCH_TO_COMMON(r10, slb_miss_common)
EXC_REAL_END(instruction_access_slb, 0x480, 0x80) EXC_REAL_END(instruction_access_slb, 0x480, 0x80)
EXC_VIRT_BEGIN(instruction_access_slb, 0x4480, 0x80) EXC_VIRT_BEGIN(instruction_access_slb, 0x4480, 0x80)
EXCEPTION_RELON_PROLOG(PACA_EXSLB, instruction_access_slb_common, EXC_STD, NOTEST, 0x480); SET_SCRATCH0(r13)
EXCEPTION_PROLOG_0(PACA_EXSLB)
EXCEPTION_PROLOG_1(PACA_EXSLB, NOTEST, 0x480)
mr r12,r3 /* save r3 */
mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */
mfspr r11,SPRN_SRR1
crclr 4*cr6+eq
BRANCH_TO_COMMON(r10, slb_miss_common)
EXC_VIRT_END(instruction_access_slb, 0x4480, 0x80) EXC_VIRT_END(instruction_access_slb, 0x4480, 0x80)
TRAMP_KVM(PACA_EXSLB, 0x480) TRAMP_KVM(PACA_EXSLB, 0x480)
EXC_COMMON_BEGIN(instruction_access_slb_common)
EXCEPTION_PROLOG_COMMON(0x480, PACA_EXSLB) /*
ld r4,_NIP(r1) * This handler is used by the 0x380 and 0x480 SLB miss interrupts, as well as
addi r3,r1,STACK_FRAME_OVERHEAD * the virtual mode 0x4380 and 0x4480 interrupts if AIL is enabled.
bl do_slb_fault */
cmpdi r3,0 EXC_COMMON_BEGIN(slb_miss_common)
bne- 1f /*
b fast_exception_return * r13 points to the PACA, r9 contains the saved CR,
1: /* Error case */ * r12 contains the saved r3,
std r3,RESULT(r1) * r11 contain the saved SRR1, SRR0 is still ready for return
* r3 has the faulting address
* r9 - r13 are saved in paca->exslb.
* cr6.eq is set for a D-SLB miss, clear for a I-SLB miss
* We assume we aren't going to take any exceptions during this
* procedure.
*/
mflr r10
stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */
std r10,PACA_EXSLB+EX_LR(r13) /* save LR */
andi. r9,r11,MSR_PR // Check for exception from userspace
cmpdi cr4,r9,MSR_PR // And save the result in CR4 for later
/*
* Test MSR_RI before calling slb_allocate_realmode, because the
* MSR in r11 gets clobbered. However we still want to allocate
* SLB in case MSR_RI=0, to minimise the risk of getting stuck in
* recursive SLB faults. So use cr5 for this, which is preserved.
*/
andi. r11,r11,MSR_RI /* check for unrecoverable exception */
cmpdi cr5,r11,MSR_RI
crset 4*cr0+eq
#ifdef CONFIG_PPC_BOOK3S_64
BEGIN_MMU_FTR_SECTION
bl slb_allocate
END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX)
#endif
ld r10,PACA_EXSLB+EX_LR(r13)
lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */
mtlr r10
/*
* Large address, check whether we have to allocate new contexts.
*/
beq- 8f
bne- cr5,2f /* if unrecoverable exception, oops */
/* All done -- return from exception. */
bne cr4,1f /* returning to kernel */
mtcrf 0x80,r9
mtcrf 0x08,r9 /* MSR[PR] indication is in cr4 */
mtcrf 0x04,r9 /* MSR[RI] indication is in cr5 */
mtcrf 0x02,r9 /* I/D indication is in cr6 */
mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */
RESTORE_CTR(r9, PACA_EXSLB)
RESTORE_PPR_PACA(PACA_EXSLB, r9)
mr r3,r12
ld r9,PACA_EXSLB+EX_R9(r13)
ld r10,PACA_EXSLB+EX_R10(r13)
ld r11,PACA_EXSLB+EX_R11(r13)
ld r12,PACA_EXSLB+EX_R12(r13)
ld r13,PACA_EXSLB+EX_R13(r13)
RFI_TO_USER
b . /* prevent speculative execution */
1:
mtcrf 0x80,r9
mtcrf 0x08,r9 /* MSR[PR] indication is in cr4 */
mtcrf 0x04,r9 /* MSR[RI] indication is in cr5 */
mtcrf 0x02,r9 /* I/D indication is in cr6 */
mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */
RESTORE_CTR(r9, PACA_EXSLB)
RESTORE_PPR_PACA(PACA_EXSLB, r9)
mr r3,r12
ld r9,PACA_EXSLB+EX_R9(r13)
ld r10,PACA_EXSLB+EX_R10(r13)
ld r11,PACA_EXSLB+EX_R11(r13)
ld r12,PACA_EXSLB+EX_R12(r13)
ld r13,PACA_EXSLB+EX_R13(r13)
RFI_TO_KERNEL
b . /* prevent speculative execution */
2: std r3,PACA_EXSLB+EX_DAR(r13)
mr r3,r12
mfspr r11,SPRN_SRR0
mfspr r12,SPRN_SRR1
LOAD_HANDLER(r10,unrecov_slb)
mtspr SPRN_SRR0,r10
ld r10,PACAKMSR(r13)
mtspr SPRN_SRR1,r10
RFI_TO_KERNEL
b .
8: std r3,PACA_EXSLB+EX_DAR(r13)
mr r3,r12
mfspr r11,SPRN_SRR0
mfspr r12,SPRN_SRR1
LOAD_HANDLER(r10, large_addr_slb)
mtspr SPRN_SRR0,r10
ld r10,PACAKMSR(r13)
mtspr SPRN_SRR1,r10
RFI_TO_KERNEL
b .
EXC_COMMON_BEGIN(unrecov_slb)
EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)
RECONCILE_IRQ_STATE(r10, r11)
bl save_nvgprs bl save_nvgprs
1: addi r3,r1,STACK_FRAME_OVERHEAD
bl unrecoverable_exception
b 1b
EXC_COMMON_BEGIN(large_addr_slb)
EXCEPTION_PROLOG_COMMON(0x380, PACA_EXSLB)
RECONCILE_IRQ_STATE(r10, r11) RECONCILE_IRQ_STATE(r10, r11)
ld r4,_NIP(r1) ld r3, PACA_EXSLB+EX_DAR(r13)
ld r5,RESULT(r1) std r3, _DAR(r1)
addi r3,r1,STACK_FRAME_OVERHEAD beq cr6, 2f
bl do_bad_slb_fault li r10, 0x481 /* fix trap number for I-SLB miss */
std r10, _TRAP(r1)
2: bl save_nvgprs
addi r3, r1, STACK_FRAME_OVERHEAD
bl slb_miss_large_addr
b ret_from_except b ret_from_except
EXC_REAL_BEGIN(hardware_interrupt, 0x500, 0x100) EXC_REAL_BEGIN(hardware_interrupt, 0x500, 0x100)
.globl hardware_interrupt_hv; .globl hardware_interrupt_hv;
hardware_interrupt_hv: hardware_interrupt_hv:
......
...@@ -258,3 +258,25 @@ void __init free_unused_pacas(void) ...@@ -258,3 +258,25 @@ void __init free_unused_pacas(void)
printk(KERN_DEBUG "Allocated %u bytes for %u pacas\n", printk(KERN_DEBUG "Allocated %u bytes for %u pacas\n",
paca_ptrs_size + paca_struct_size, nr_cpu_ids); paca_ptrs_size + paca_struct_size, nr_cpu_ids);
} }
void copy_mm_to_paca(struct mm_struct *mm)
{
#ifdef CONFIG_PPC_BOOK3S
mm_context_t *context = &mm->context;
get_paca()->mm_ctx_id = context->id;
#ifdef CONFIG_PPC_MM_SLICES
VM_BUG_ON(!mm->context.slb_addr_limit);
get_paca()->mm_ctx_slb_addr_limit = mm->context.slb_addr_limit;
memcpy(&get_paca()->mm_ctx_low_slices_psize,
&context->low_slices_psize, sizeof(context->low_slices_psize));
memcpy(&get_paca()->mm_ctx_high_slices_psize,
&context->high_slices_psize, TASK_SLICE_ARRAY_SZ(mm));
#else /* CONFIG_PPC_MM_SLICES */
get_paca()->mm_ctx_user_psize = context->user_psize;
get_paca()->mm_ctx_sllp = context->sllp;
#endif
#else /* !CONFIG_PPC_BOOK3S */
return;
#endif
}
...@@ -1482,15 +1482,6 @@ void flush_thread(void) ...@@ -1482,15 +1482,6 @@ void flush_thread(void)
#endif /* CONFIG_HAVE_HW_BREAKPOINT */ #endif /* CONFIG_HAVE_HW_BREAKPOINT */
} }
#ifdef CONFIG_PPC_BOOK3S_64
void arch_setup_new_exec(void)
{
if (radix_enabled())
return;
hash__setup_new_exec();
}
#endif
int set_thread_uses_vas(void) int set_thread_uses_vas(void)
{ {
#ifdef CONFIG_PPC_BOOK3S_64 #ifdef CONFIG_PPC_BOOK3S_64
...@@ -1719,8 +1710,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, ...@@ -1719,8 +1710,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
return 0; return 0;
} }
void preload_new_slb_context(unsigned long start, unsigned long sp);
/* /*
* Set up a thread for executing a new program * Set up a thread for executing a new program
*/ */
...@@ -1728,10 +1717,6 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) ...@@ -1728,10 +1717,6 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
{ {
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
unsigned long load_addr = regs->gpr[2]; /* saved by ELF_PLAT_INIT */ unsigned long load_addr = regs->gpr[2]; /* saved by ELF_PLAT_INIT */
#ifdef CONFIG_PPC_BOOK3S_64
preload_new_slb_context(start, sp);
#endif
#endif #endif
/* /*
...@@ -1822,7 +1807,6 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) ...@@ -1822,7 +1807,6 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
#ifdef CONFIG_VSX #ifdef CONFIG_VSX
current->thread.used_vsr = 0; current->thread.used_vsr = 0;
#endif #endif
current->thread.load_slb = 0;
current->thread.load_fp = 0; current->thread.load_fp = 0;
memset(&current->thread.fp_state, 0, sizeof(current->thread.fp_state)); memset(&current->thread.fp_state, 0, sizeof(current->thread.fp_state));
current->thread.fp_save_area = NULL; current->thread.fp_save_area = NULL;
......
...@@ -15,7 +15,7 @@ obj-$(CONFIG_PPC_MMU_NOHASH) += mmu_context_nohash.o tlb_nohash.o \ ...@@ -15,7 +15,7 @@ obj-$(CONFIG_PPC_MMU_NOHASH) += mmu_context_nohash.o tlb_nohash.o \
obj-$(CONFIG_PPC_BOOK3E) += tlb_low_$(BITS)e.o obj-$(CONFIG_PPC_BOOK3E) += tlb_low_$(BITS)e.o
hash64-$(CONFIG_PPC_NATIVE) := hash_native_64.o hash64-$(CONFIG_PPC_NATIVE) := hash_native_64.o
obj-$(CONFIG_PPC_BOOK3E_64) += pgtable-book3e.o obj-$(CONFIG_PPC_BOOK3E_64) += pgtable-book3e.o
obj-$(CONFIG_PPC_BOOK3S_64) += pgtable-hash64.o hash_utils_64.o slb.o $(hash64-y) mmu_context_book3s64.o pgtable-book3s64.o obj-$(CONFIG_PPC_BOOK3S_64) += pgtable-hash64.o hash_utils_64.o slb_low.o slb.o $(hash64-y) mmu_context_book3s64.o pgtable-book3s64.o
obj-$(CONFIG_PPC_RADIX_MMU) += pgtable-radix.o tlb-radix.o obj-$(CONFIG_PPC_RADIX_MMU) += pgtable-radix.o tlb-radix.o
obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o hash_low_32.o mmu_context_hash32.o obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o hash_low_32.o mmu_context_hash32.o
obj-$(CONFIG_PPC_STD_MMU) += tlb_hash$(BITS).o obj-$(CONFIG_PPC_STD_MMU) += tlb_hash$(BITS).o
......
...@@ -1088,16 +1088,16 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap) ...@@ -1088,16 +1088,16 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
} }
#ifdef CONFIG_PPC_MM_SLICES #ifdef CONFIG_PPC_MM_SLICES
static unsigned int get_psize(struct mm_struct *mm, unsigned long addr) static unsigned int get_paca_psize(unsigned long addr)
{ {
unsigned char *psizes; unsigned char *psizes;
unsigned long index, mask_index; unsigned long index, mask_index;
if (addr < SLICE_LOW_TOP) { if (addr < SLICE_LOW_TOP) {
psizes = mm->context.low_slices_psize; psizes = get_paca()->mm_ctx_low_slices_psize;
index = GET_LOW_SLICE_INDEX(addr); index = GET_LOW_SLICE_INDEX(addr);
} else { } else {
psizes = mm->context.high_slices_psize; psizes = get_paca()->mm_ctx_high_slices_psize;
index = GET_HIGH_SLICE_INDEX(addr); index = GET_HIGH_SLICE_INDEX(addr);
} }
mask_index = index & 0x1; mask_index = index & 0x1;
...@@ -1105,9 +1105,9 @@ static unsigned int get_psize(struct mm_struct *mm, unsigned long addr) ...@@ -1105,9 +1105,9 @@ static unsigned int get_psize(struct mm_struct *mm, unsigned long addr)
} }
#else #else
unsigned int get_psize(struct mm_struct *mm, unsigned long addr) unsigned int get_paca_psize(unsigned long addr)
{ {
return mm->context.user_psize; return get_paca()->mm_ctx_user_psize;
} }
#endif #endif
...@@ -1118,11 +1118,15 @@ unsigned int get_psize(struct mm_struct *mm, unsigned long addr) ...@@ -1118,11 +1118,15 @@ unsigned int get_psize(struct mm_struct *mm, unsigned long addr)
#ifdef CONFIG_PPC_64K_PAGES #ifdef CONFIG_PPC_64K_PAGES
void demote_segment_4k(struct mm_struct *mm, unsigned long addr) void demote_segment_4k(struct mm_struct *mm, unsigned long addr)
{ {
if (get_psize(mm, addr) == MMU_PAGE_4K) if (get_slice_psize(mm, addr) == MMU_PAGE_4K)
return; return;
slice_set_range_psize(mm, addr, 1, MMU_PAGE_4K); slice_set_range_psize(mm, addr, 1, MMU_PAGE_4K);
copro_flush_all_slbs(mm); copro_flush_all_slbs(mm);
core_flush_all_slbs(mm); if ((get_paca_psize(addr) != MMU_PAGE_4K) && (current->mm == mm)) {
copy_mm_to_paca(mm);
slb_flush_and_rebolt();
}
} }
#endif /* CONFIG_PPC_64K_PAGES */ #endif /* CONFIG_PPC_64K_PAGES */
...@@ -1187,6 +1191,22 @@ void hash_failure_debug(unsigned long ea, unsigned long access, ...@@ -1187,6 +1191,22 @@ void hash_failure_debug(unsigned long ea, unsigned long access,
trap, vsid, ssize, psize, lpsize, pte); trap, vsid, ssize, psize, lpsize, pte);
} }
static void check_paca_psize(unsigned long ea, struct mm_struct *mm,
int psize, bool user_region)
{
if (user_region) {
if (psize != get_paca_psize(ea)) {
copy_mm_to_paca(mm);
slb_flush_and_rebolt();
}
} else if (get_paca()->vmalloc_sllp !=
mmu_psize_defs[mmu_vmalloc_psize].sllp) {
get_paca()->vmalloc_sllp =
mmu_psize_defs[mmu_vmalloc_psize].sllp;
slb_vmalloc_update();
}
}
/* Result code is: /* Result code is:
* 0 - handled * 0 - handled
* 1 - normal page fault * 1 - normal page fault
...@@ -1219,7 +1239,7 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea, ...@@ -1219,7 +1239,7 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea,
rc = 1; rc = 1;
goto bail; goto bail;
} }
psize = get_psize(mm, ea); psize = get_slice_psize(mm, ea);
ssize = user_segment_size(ea); ssize = user_segment_size(ea);
vsid = get_user_vsid(&mm->context, ea, ssize); vsid = get_user_vsid(&mm->context, ea, ssize);
break; break;
...@@ -1307,6 +1327,9 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea, ...@@ -1307,6 +1327,9 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea,
WARN_ON(1); WARN_ON(1);
} }
#endif #endif
if (current->mm == mm)
check_paca_psize(ea, mm, psize, user_region);
goto bail; goto bail;
} }
...@@ -1341,14 +1364,15 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea, ...@@ -1341,14 +1364,15 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea,
"to 4kB pages because of " "to 4kB pages because of "
"non-cacheable mapping\n"); "non-cacheable mapping\n");
psize = mmu_vmalloc_psize = MMU_PAGE_4K; psize = mmu_vmalloc_psize = MMU_PAGE_4K;
slb_vmalloc_update();
copro_flush_all_slbs(mm); copro_flush_all_slbs(mm);
core_flush_all_slbs(mm);
} }
} }
#endif /* CONFIG_PPC_64K_PAGES */ #endif /* CONFIG_PPC_64K_PAGES */
if (current->mm == mm)
check_paca_psize(ea, mm, psize, user_region);
#ifdef CONFIG_PPC_64K_PAGES #ifdef CONFIG_PPC_64K_PAGES
if (psize == MMU_PAGE_64K) if (psize == MMU_PAGE_64K)
rc = __hash_page_64K(ea, access, vsid, ptep, trap, rc = __hash_page_64K(ea, access, vsid, ptep, trap,
...@@ -1436,7 +1460,7 @@ int __hash_page(unsigned long ea, unsigned long msr, unsigned long trap, ...@@ -1436,7 +1460,7 @@ int __hash_page(unsigned long ea, unsigned long msr, unsigned long trap,
#ifdef CONFIG_PPC_MM_SLICES #ifdef CONFIG_PPC_MM_SLICES
static bool should_hash_preload(struct mm_struct *mm, unsigned long ea) static bool should_hash_preload(struct mm_struct *mm, unsigned long ea)
{ {
int psize = get_psize(mm, ea); int psize = get_slice_psize(mm, ea);
/* We only prefault standard pages for now */ /* We only prefault standard pages for now */
if (unlikely(psize != mm->context.user_psize)) if (unlikely(psize != mm->context.user_psize))
......
...@@ -54,7 +54,8 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, ...@@ -54,7 +54,8 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
* MMU context id, which is then moved to SPRN_PID. * MMU context id, which is then moved to SPRN_PID.
* *
* For the hash MMU it is either the first load from slb_cache * For the hash MMU it is either the first load from slb_cache
* in switch_slb(), and/or load of MMU context id. * in switch_slb(), and/or the store of paca->mm_ctx_id in
* copy_mm_to_paca().
* *
* On the other side, the barrier is in mm/tlb-radix.c for * On the other side, the barrier is in mm/tlb-radix.c for
* radix which orders earlier stores to clear the PTEs vs * radix which orders earlier stores to clear the PTEs vs
......
...@@ -53,8 +53,6 @@ int hash__alloc_context_id(void) ...@@ -53,8 +53,6 @@ int hash__alloc_context_id(void)
} }
EXPORT_SYMBOL_GPL(hash__alloc_context_id); EXPORT_SYMBOL_GPL(hash__alloc_context_id);
void slb_setup_new_exec(void);
static int hash__init_new_context(struct mm_struct *mm) static int hash__init_new_context(struct mm_struct *mm)
{ {
int index; int index;
...@@ -86,13 +84,6 @@ static int hash__init_new_context(struct mm_struct *mm) ...@@ -86,13 +84,6 @@ static int hash__init_new_context(struct mm_struct *mm)
return index; return index;
} }
void hash__setup_new_exec(void)
{
slice_setup_new_exec();
slb_setup_new_exec();
}
static int radix__init_new_context(struct mm_struct *mm) static int radix__init_new_context(struct mm_struct *mm)
{ {
unsigned long rts_field; unsigned long rts_field;
......
This diff is collapsed.
This diff is collapsed.
...@@ -207,6 +207,23 @@ static bool slice_check_range_fits(struct mm_struct *mm, ...@@ -207,6 +207,23 @@ static bool slice_check_range_fits(struct mm_struct *mm,
return true; return true;
} }
static void slice_flush_segments(void *parm)
{
#ifdef CONFIG_PPC64
struct mm_struct *mm = parm;
unsigned long flags;
if (mm != current->active_mm)
return;
copy_mm_to_paca(current->active_mm);
local_irq_save(flags);
slb_flush_and_rebolt();
local_irq_restore(flags);
#endif
}
static void slice_convert(struct mm_struct *mm, static void slice_convert(struct mm_struct *mm,
const struct slice_mask *mask, int psize) const struct slice_mask *mask, int psize)
{ {
...@@ -272,9 +289,6 @@ static void slice_convert(struct mm_struct *mm, ...@@ -272,9 +289,6 @@ static void slice_convert(struct mm_struct *mm,
spin_unlock_irqrestore(&slice_convert_lock, flags); spin_unlock_irqrestore(&slice_convert_lock, flags);
copro_flush_all_slbs(mm); copro_flush_all_slbs(mm);
#ifdef CONFIG_PPC64
core_flush_all_slbs(mm);
#endif
} }
/* /*
...@@ -488,9 +502,8 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len, ...@@ -488,9 +502,8 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
* be already initialised beyond the old address limit. * be already initialised beyond the old address limit.
*/ */
mm->context.slb_addr_limit = high_limit; mm->context.slb_addr_limit = high_limit;
#ifdef CONFIG_PPC64
core_flush_all_slbs(mm); on_each_cpu(slice_flush_segments, mm, 1);
#endif
} }
/* Sanity checks */ /* Sanity checks */
...@@ -652,10 +665,8 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len, ...@@ -652,10 +665,8 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
(SLICE_NUM_HIGH && (SLICE_NUM_HIGH &&
!bitmap_empty(potential_mask.high_slices, SLICE_NUM_HIGH))) { !bitmap_empty(potential_mask.high_slices, SLICE_NUM_HIGH))) {
slice_convert(mm, &potential_mask, psize); slice_convert(mm, &potential_mask, psize);
#ifdef CONFIG_PPC64
if (psize > MMU_PAGE_BASE) if (psize > MMU_PAGE_BASE)
core_flush_all_slbs(mm); on_each_cpu(slice_flush_segments, mm, 1);
#endif
} }
return newaddr; return newaddr;
...@@ -746,20 +757,6 @@ void slice_init_new_context_exec(struct mm_struct *mm) ...@@ -746,20 +757,6 @@ void slice_init_new_context_exec(struct mm_struct *mm)
bitmap_fill(mask->high_slices, SLICE_NUM_HIGH); bitmap_fill(mask->high_slices, SLICE_NUM_HIGH);
} }
#ifdef CONFIG_PPC_BOOK3S_64
void slice_setup_new_exec(void)
{
struct mm_struct *mm = current->mm;
slice_dbg("slice_setup_new_exec(mm=%p)\n", mm);
if (!is_32bit_task())
return;
mm->context.slb_addr_limit = DEFAULT_MAP_WINDOW;
}
#endif
void slice_set_range_psize(struct mm_struct *mm, unsigned long start, void slice_set_range_psize(struct mm_struct *mm, unsigned long start,
unsigned long len, unsigned int psize) unsigned long len, unsigned int psize)
{ {
......
...@@ -2394,9 +2394,7 @@ static void dump_one_paca(int cpu) ...@@ -2394,9 +2394,7 @@ static void dump_one_paca(int cpu)
} }
} }
DUMP(p, vmalloc_sllp, "%#-*x"); DUMP(p, vmalloc_sllp, "%#-*x");
DUMP(p, stab_rr, "%#-*x"); DUMP(p, stab_rr, "%#-*llx");
DUMP(p, slb_used_bitmap, "%#-*x");
DUMP(p, slb_kern_bitmap, "%#-*x");
if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) { if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) {
DUMP(p, slb_cache_ptr, "%#-*x"); DUMP(p, slb_cache_ptr, "%#-*x");
......
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