2005-11-19 17:17:32 +08:00
|
|
|
#ifndef __ASM_POWERPC_MMU_CONTEXT_H
|
|
|
|
#define __ASM_POWERPC_MMU_CONTEXT_H
|
2005-12-17 05:43:46 +08:00
|
|
|
#ifdef __KERNEL__
|
2005-11-19 17:17:32 +08:00
|
|
|
|
2008-12-19 03:13:24 +08:00
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/mm.h>
|
|
|
|
#include <linux/sched.h>
|
|
|
|
#include <linux/spinlock.h>
|
2007-07-03 16:22:05 +08:00
|
|
|
#include <asm/mmu.h>
|
|
|
|
#include <asm/cputable.h>
|
2008-12-19 03:13:24 +08:00
|
|
|
#include <asm/cputhreads.h>
|
2007-07-03 16:22:05 +08:00
|
|
|
|
|
|
|
/*
|
2008-12-19 03:13:24 +08:00
|
|
|
* Most if the context management is out of line
|
2007-07-03 16:22:05 +08:00
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
|
|
|
|
extern void destroy_context(struct mm_struct *mm);
|
2015-06-05 14:35:24 +08:00
|
|
|
#ifdef CONFIG_SPAPR_TCE_IOMMU
|
|
|
|
struct mm_iommu_table_group_mem_t;
|
|
|
|
|
2016-09-06 14:27:31 +08:00
|
|
|
extern int isolate_lru_page(struct page *page); /* from internal.h */
|
2016-11-30 14:52:00 +08:00
|
|
|
extern bool mm_iommu_preregistered(struct mm_struct *mm);
|
|
|
|
extern long mm_iommu_get(struct mm_struct *mm,
|
|
|
|
unsigned long ua, unsigned long entries,
|
2015-06-05 14:35:24 +08:00
|
|
|
struct mm_iommu_table_group_mem_t **pmem);
|
2016-11-30 14:52:00 +08:00
|
|
|
extern long mm_iommu_put(struct mm_struct *mm,
|
|
|
|
struct mm_iommu_table_group_mem_t *mem);
|
2016-11-30 14:51:59 +08:00
|
|
|
extern void mm_iommu_init(struct mm_struct *mm);
|
|
|
|
extern void mm_iommu_cleanup(struct mm_struct *mm);
|
2016-11-30 14:52:00 +08:00
|
|
|
extern struct mm_iommu_table_group_mem_t *mm_iommu_lookup(struct mm_struct *mm,
|
|
|
|
unsigned long ua, unsigned long size);
|
|
|
|
extern struct mm_iommu_table_group_mem_t *mm_iommu_find(struct mm_struct *mm,
|
|
|
|
unsigned long ua, unsigned long entries);
|
2015-06-05 14:35:24 +08:00
|
|
|
extern long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem,
|
|
|
|
unsigned long ua, unsigned long *hpa);
|
|
|
|
extern long mm_iommu_mapped_inc(struct mm_iommu_table_group_mem_t *mem);
|
|
|
|
extern void mm_iommu_mapped_dec(struct mm_iommu_table_group_mem_t *mem);
|
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm);
|
2008-12-19 03:13:24 +08:00
|
|
|
extern void set_context(unsigned long id, pgd_t *pgd);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2009-07-24 07:15:26 +08:00
|
|
|
#ifdef CONFIG_PPC_BOOK3S_64
|
2016-04-29 21:26:02 +08:00
|
|
|
extern void radix__switch_mmu_context(struct mm_struct *prev,
|
|
|
|
struct mm_struct *next);
|
2016-04-29 21:26:01 +08:00
|
|
|
static inline void switch_mmu_context(struct mm_struct *prev,
|
|
|
|
struct mm_struct *next,
|
|
|
|
struct task_struct *tsk)
|
|
|
|
{
|
2016-04-29 21:26:02 +08:00
|
|
|
if (radix_enabled())
|
|
|
|
return radix__switch_mmu_context(prev, next);
|
2016-04-29 21:26:01 +08:00
|
|
|
return switch_slb(tsk, next);
|
|
|
|
}
|
|
|
|
|
2009-11-02 20:02:30 +08:00
|
|
|
extern int __init_new_context(void);
|
|
|
|
extern void __destroy_context(int context_id);
|
2009-07-24 07:15:26 +08:00
|
|
|
static inline void mmu_context_init(void) { }
|
|
|
|
#else
|
2016-04-29 21:26:01 +08:00
|
|
|
extern void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next,
|
|
|
|
struct task_struct *tsk);
|
2010-04-16 06:11:36 +08:00
|
|
|
extern unsigned long __init_new_context(void);
|
|
|
|
extern void __destroy_context(unsigned long context_id);
|
2009-07-24 07:15:26 +08:00
|
|
|
extern void mmu_context_init(void);
|
|
|
|
#endif
|
|
|
|
|
2011-05-03 04:43:04 +08:00
|
|
|
extern void switch_cop(struct mm_struct *next);
|
|
|
|
extern int use_cop(unsigned long acop, struct mm_struct *mm);
|
|
|
|
extern void drop_cop(unsigned long acop, struct mm_struct *mm);
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* switch_mm is the entry point called from the architecture independent
|
2013-06-04 15:40:24 +08:00
|
|
|
* code in kernel/sched/core.c
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
|
|
|
struct task_struct *tsk)
|
|
|
|
{
|
2008-12-19 03:13:24 +08:00
|
|
|
/* Mark this context has been used on the new CPU */
|
2016-10-03 14:40:29 +08:00
|
|
|
if (!cpumask_test_cpu(smp_processor_id(), mm_cpumask(next)))
|
|
|
|
cpumask_set_cpu(smp_processor_id(), mm_cpumask(next));
|
2008-12-19 03:13:24 +08:00
|
|
|
|
|
|
|
/* 32-bit keeps track of the current PGDIR in the thread struct */
|
|
|
|
#ifdef CONFIG_PPC32
|
|
|
|
tsk->thread.pgdir = next->pgd;
|
|
|
|
#endif /* CONFIG_PPC32 */
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2009-07-24 07:15:47 +08:00
|
|
|
/* 64-bit Book3E keeps track of current PGD in the PACA */
|
|
|
|
#ifdef CONFIG_PPC_BOOK3E_64
|
|
|
|
get_paca()->pgd = next->pgd;
|
|
|
|
#endif
|
2008-12-19 03:13:24 +08:00
|
|
|
/* Nothing else to do if we aren't actually switching */
|
2005-04-17 06:20:36 +08:00
|
|
|
if (prev == next)
|
|
|
|
return;
|
|
|
|
|
2011-05-03 04:43:04 +08:00
|
|
|
#ifdef CONFIG_PPC_ICSWX
|
|
|
|
/* Switch coprocessor context only if prev or next uses a coprocessor */
|
|
|
|
if (prev->context.acop || next->context.acop)
|
|
|
|
switch_cop(next);
|
|
|
|
#endif /* CONFIG_PPC_ICSWX */
|
|
|
|
|
2008-12-19 03:13:24 +08:00
|
|
|
/* We must stop all altivec streams before changing the HW
|
|
|
|
* context
|
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
#ifdef CONFIG_ALTIVEC
|
|
|
|
if (cpu_has_feature(CPU_FTR_ALTIVEC))
|
|
|
|
asm volatile ("dssall");
|
|
|
|
#endif /* CONFIG_ALTIVEC */
|
2016-04-29 21:26:01 +08:00
|
|
|
/*
|
|
|
|
* The actual HW switching method differs between the various
|
|
|
|
* sub architectures. Out of line for now
|
2008-12-19 03:13:24 +08:00
|
|
|
*/
|
2016-04-29 21:26:01 +08:00
|
|
|
switch_mmu_context(prev, next, tsk);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#define deactivate_mm(tsk,mm) do { } while (0)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* After we have set current->mm to a new value, this activates
|
|
|
|
* the context for the new mm so we see the new mappings.
|
|
|
|
*/
|
|
|
|
static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
local_irq_save(flags);
|
|
|
|
switch_mm(prev, next, current);
|
|
|
|
local_irq_restore(flags);
|
|
|
|
}
|
|
|
|
|
2008-12-19 03:13:24 +08:00
|
|
|
/* We don't currently use enter_lazy_tlb() for anything */
|
|
|
|
static inline void enter_lazy_tlb(struct mm_struct *mm,
|
|
|
|
struct task_struct *tsk)
|
|
|
|
{
|
2009-07-24 07:15:47 +08:00
|
|
|
/* 64-bit Book3E keeps track of current PGD in the PACA */
|
|
|
|
#ifdef CONFIG_PPC_BOOK3E_64
|
|
|
|
get_paca()->pgd = NULL;
|
|
|
|
#endif
|
2008-12-19 03:13:24 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 07:56:22 +08:00
|
|
|
static inline void arch_dup_mmap(struct mm_struct *oldmm,
|
|
|
|
struct mm_struct *mm)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void arch_exit_mmap(struct mm_struct *mm)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void arch_unmap(struct mm_struct *mm,
|
|
|
|
struct vm_area_struct *vma,
|
|
|
|
unsigned long start, unsigned long end)
|
|
|
|
{
|
|
|
|
if (start <= mm->context.vdso_base && mm->context.vdso_base < end)
|
|
|
|
mm->context.vdso_base = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void arch_bprm_mm_init(struct mm_struct *mm,
|
|
|
|
struct vm_area_struct *vma)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-02-13 05:02:21 +08:00
|
|
|
static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,
|
2016-02-13 05:02:24 +08:00
|
|
|
bool write, bool execute, bool foreign)
|
mm/gup, x86/mm/pkeys: Check VMAs and PTEs for protection keys
Today, for normal faults and page table walks, we check the VMA
and/or PTE to ensure that it is compatible with the action. For
instance, if we get a write fault on a non-writeable VMA, we
SIGSEGV.
We try to do the same thing for protection keys. Basically, we
try to make sure that if a user does this:
mprotect(ptr, size, PROT_NONE);
*ptr = foo;
they see the same effects with protection keys when they do this:
mprotect(ptr, size, PROT_READ|PROT_WRITE);
set_pkey(ptr, size, 4);
wrpkru(0xffffff3f); // access disable pkey 4
*ptr = foo;
The state to do that checking is in the VMA, but we also
sometimes have to do it on the page tables only, like when doing
a get_user_pages_fast() where we have no VMA.
We add two functions and expose them to generic code:
arch_pte_access_permitted(pte_flags, write)
arch_vma_access_permitted(vma, write)
These are, of course, backed up in x86 arch code with checks
against the PTE or VMA's protection key.
But, there are also cases where we do not want to respect
protection keys. When we ptrace(), for instance, we do not want
to apply the tracer's PKRU permissions to the PTEs from the
process being traced.
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Alexey Kardashevskiy <aik@ozlabs.ru>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Boaz Harrosh <boaz@plexistor.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Dave Hansen <dave@sr71.net>
Cc: David Gibson <david@gibson.dropbear.id.au>
Cc: David Hildenbrand <dahi@linux.vnet.ibm.com>
Cc: David Vrabel <david.vrabel@citrix.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Dominik Dingel <dingel@linux.vnet.ibm.com>
Cc: Dominik Vogt <vogt@linux.vnet.ibm.com>
Cc: Guan Xuetao <gxt@mprc.pku.edu.cn>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Jason Low <jason.low2@hp.com>
Cc: Jerome Marchand <jmarchan@redhat.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Laurent Dufour <ldufour@linux.vnet.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Matthew Wilcox <willy@linux.intel.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mikulas Patocka <mpatocka@redhat.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rik van Riel <riel@redhat.com>
Cc: Sasha Levin <sasha.levin@oracle.com>
Cc: Shachar Raindel <raindel@mellanox.com>
Cc: Stephen Smalley <sds@tycho.nsa.gov>
Cc: Toshi Kani <toshi.kani@hpe.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: linux-arch@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-mm@kvack.org
Cc: linux-s390@vger.kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
Link: http://lkml.kernel.org/r/20160212210219.14D5D715@viggo.jf.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2016-02-13 05:02:19 +08:00
|
|
|
{
|
|
|
|
/* by default, allow everything */
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool arch_pte_access_permitted(pte_t pte, bool write)
|
|
|
|
{
|
|
|
|
/* by default, allow everything */
|
|
|
|
return true;
|
|
|
|
}
|
2005-12-17 05:43:46 +08:00
|
|
|
#endif /* __KERNEL__ */
|
2005-11-19 17:17:32 +08:00
|
|
|
#endif /* __ASM_POWERPC_MMU_CONTEXT_H */
|