mirror of
https://github.com/torvalds/linux.git
synced 2024-11-01 01:31:44 +00:00
a741e67969
The current tlb flush code on powerpc 64 bits has a subtle race since we lost the page table lock due to the possible faulting in of new PTEs after a previous one has been removed but before the corresponding hash entry has been evicted, which can leads to all sort of fatal problems. This patch reworks the batch code completely. It doesn't use the mmu_gather stuff anymore. Instead, we use the lazy mmu hooks that were added by the paravirt code. They have the nice property that the enter/leave lazy mmu mode pair is always fully contained by the PTE lock for a given range of PTEs. Thus we can guarantee that all batches are flushed on a given CPU before it drops that lock. We also generalize batching for any PTE update that require a flush. Batching is now enabled on a CPU by arch_enter_lazy_mmu_mode() and disabled by arch_leave_lazy_mmu_mode(). The code epects that this is always contained within a PTE lock section so no preemption can happen and no PTE insertion in that range from another CPU. When batching is enabled on a CPU, every PTE updates that need a hash flush will use the batch for that flush. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
71 lines
1.6 KiB
C
71 lines
1.6 KiB
C
/*
|
|
* TLB shootdown specifics for powerpc
|
|
*
|
|
* Copyright (C) 2002 Anton Blanchard, IBM Corp.
|
|
* Copyright (C) 2002 Paul Mackerras, IBM Corp.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
*/
|
|
#ifndef _ASM_POWERPC_TLB_H
|
|
#define _ASM_POWERPC_TLB_H
|
|
#ifdef __KERNEL__
|
|
|
|
#ifndef __powerpc64__
|
|
#include <asm/pgtable.h>
|
|
#endif
|
|
#include <asm/pgalloc.h>
|
|
#include <asm/tlbflush.h>
|
|
#ifndef __powerpc64__
|
|
#include <asm/page.h>
|
|
#include <asm/mmu.h>
|
|
#endif
|
|
|
|
struct mmu_gather;
|
|
|
|
#define tlb_start_vma(tlb, vma) do { } while (0)
|
|
#define tlb_end_vma(tlb, vma) do { } while (0)
|
|
|
|
#if !defined(CONFIG_PPC_STD_MMU)
|
|
|
|
#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
|
|
|
|
#elif defined(__powerpc64__)
|
|
|
|
extern void pte_free_finish(void);
|
|
|
|
static inline void tlb_flush(struct mmu_gather *tlb)
|
|
{
|
|
pte_free_finish();
|
|
}
|
|
|
|
#else
|
|
|
|
extern void tlb_flush(struct mmu_gather *tlb);
|
|
|
|
#endif
|
|
|
|
/* Get the generic bits... */
|
|
#include <asm-generic/tlb.h>
|
|
|
|
#if !defined(CONFIG_PPC_STD_MMU) || defined(__powerpc64__)
|
|
|
|
#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0)
|
|
|
|
#else
|
|
extern void flush_hash_entry(struct mm_struct *mm, pte_t *ptep,
|
|
unsigned long address);
|
|
|
|
static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep,
|
|
unsigned long address)
|
|
{
|
|
if (pte_val(*ptep) & _PAGE_HASHPTE)
|
|
flush_hash_entry(tlb->mm, ptep, address);
|
|
}
|
|
|
|
#endif
|
|
#endif /* __KERNEL__ */
|
|
#endif /* __ASM_POWERPC_TLB_H */
|