11965aae3SH. Peter Anvin #ifndef _ASM_X86_MMU_CONTEXT_H 21965aae3SH. Peter Anvin #define _ASM_X86_MMU_CONTEXT_H 3bb898558SAl Viro 4bb898558SAl Viro #include <asm/desc.h> 560063497SArun Sharma #include <linux/atomic.h> 6d17d8f9dSDave Hansen #include <linux/mm_types.h> 7d17d8f9dSDave Hansen 8d17d8f9dSDave Hansen #include <trace/events/tlb.h> 9d17d8f9dSDave Hansen 10bb898558SAl Viro #include <asm/pgalloc.h> 11bb898558SAl Viro #include <asm/tlbflush.h> 12bb898558SAl Viro #include <asm/paravirt.h> 13fe3d197fSDave Hansen #include <asm/mpx.h> 14bb898558SAl Viro #ifndef CONFIG_PARAVIRT 15bb898558SAl Viro #include <asm-generic/mm_hooks.h> 16bb898558SAl Viro 17bb898558SAl Viro static inline void paravirt_activate_mm(struct mm_struct *prev, 18bb898558SAl Viro struct mm_struct *next) 19bb898558SAl Viro { 20bb898558SAl Viro } 21bb898558SAl Viro #endif /* !CONFIG_PARAVIRT */ 22bb898558SAl Viro 23bb898558SAl Viro /* 24bb898558SAl Viro * Used for LDT copy/destruction. 25bb898558SAl Viro */ 26bb898558SAl Viro int init_new_context(struct task_struct *tsk, struct mm_struct *mm); 27bb898558SAl Viro void destroy_context(struct mm_struct *mm); 28bb898558SAl Viro 296826c8ffSBrian Gerst 306826c8ffSBrian Gerst static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) 316826c8ffSBrian Gerst { 326826c8ffSBrian Gerst #ifdef CONFIG_SMP 33c6ae41e7SAlex Shi if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) 34c6ae41e7SAlex Shi this_cpu_write(cpu_tlbstate.state, TLBSTATE_LAZY); 35bb898558SAl Viro #endif 366826c8ffSBrian Gerst } 376826c8ffSBrian Gerst 386826c8ffSBrian Gerst static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, 396826c8ffSBrian Gerst struct task_struct *tsk) 406826c8ffSBrian Gerst { 416826c8ffSBrian Gerst unsigned cpu = smp_processor_id(); 426826c8ffSBrian Gerst 436826c8ffSBrian Gerst if (likely(prev != next)) { 446826c8ffSBrian Gerst #ifdef CONFIG_SMP 45c6ae41e7SAlex Shi this_cpu_write(cpu_tlbstate.state, TLBSTATE_OK); 46c6ae41e7SAlex Shi this_cpu_write(cpu_tlbstate.active_mm, next); 476826c8ffSBrian Gerst #endif 4878f1c4d6SRusty Russell cpumask_set_cpu(cpu, mm_cpumask(next)); 496826c8ffSBrian Gerst 506826c8ffSBrian Gerst /* Re-load page tables */ 516826c8ffSBrian Gerst load_cr3(next->pgd); 52d17d8f9dSDave Hansen trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL); 536826c8ffSBrian Gerst 548f898fbbSRik van Riel /* Stop flush ipis for the previous mm */ 55831d52bcSSuresh Siddha cpumask_clear_cpu(cpu, mm_cpumask(prev)); 56831d52bcSSuresh Siddha 578f898fbbSRik van Riel /* Load the LDT, if the LDT is different: */ 586826c8ffSBrian Gerst if (unlikely(prev->context.ldt != next->context.ldt)) 596826c8ffSBrian Gerst load_LDT_nolock(&next->context); 606826c8ffSBrian Gerst } 616826c8ffSBrian Gerst #ifdef CONFIG_SMP 626826c8ffSBrian Gerst else { 63c6ae41e7SAlex Shi this_cpu_write(cpu_tlbstate.state, TLBSTATE_OK); 64c6ae41e7SAlex Shi BUG_ON(this_cpu_read(cpu_tlbstate.active_mm) != next); 656826c8ffSBrian Gerst 668f898fbbSRik van Riel if (!cpumask_test_cpu(cpu, mm_cpumask(next))) { 678f898fbbSRik van Riel /* 688f898fbbSRik van Riel * On established mms, the mm_cpumask is only changed 698f898fbbSRik van Riel * from irq context, from ptep_clear_flush() while in 708f898fbbSRik van Riel * lazy tlb mode, and here. Irqs are blocked during 718f898fbbSRik van Riel * schedule, protecting us from simultaneous changes. 728f898fbbSRik van Riel */ 738f898fbbSRik van Riel cpumask_set_cpu(cpu, mm_cpumask(next)); 748f898fbbSRik van Riel /* 758f898fbbSRik van Riel * We were in lazy tlb mode and leave_mm disabled 766826c8ffSBrian Gerst * tlb flush IPI delivery. We must reload CR3 776826c8ffSBrian Gerst * to make sure to use no freed page tables. 786826c8ffSBrian Gerst */ 796826c8ffSBrian Gerst load_cr3(next->pgd); 80d17d8f9dSDave Hansen trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL); 816826c8ffSBrian Gerst load_LDT_nolock(&next->context); 826826c8ffSBrian Gerst } 836826c8ffSBrian Gerst } 846826c8ffSBrian Gerst #endif 856826c8ffSBrian Gerst } 86bb898558SAl Viro 87bb898558SAl Viro #define activate_mm(prev, next) \ 88bb898558SAl Viro do { \ 89bb898558SAl Viro paravirt_activate_mm((prev), (next)); \ 90bb898558SAl Viro switch_mm((prev), (next), NULL); \ 91bb898558SAl Viro } while (0); 92bb898558SAl Viro 936826c8ffSBrian Gerst #ifdef CONFIG_X86_32 946826c8ffSBrian Gerst #define deactivate_mm(tsk, mm) \ 956826c8ffSBrian Gerst do { \ 96ccbeed3aSTejun Heo lazy_load_gs(0); \ 976826c8ffSBrian Gerst } while (0) 986826c8ffSBrian Gerst #else 996826c8ffSBrian Gerst #define deactivate_mm(tsk, mm) \ 1006826c8ffSBrian Gerst do { \ 1016826c8ffSBrian Gerst load_gs_index(0); \ 1026826c8ffSBrian Gerst loadsegment(fs, 0); \ 1036826c8ffSBrian Gerst } while (0) 1046826c8ffSBrian Gerst #endif 105bb898558SAl Viro 106fe3d197fSDave Hansen static inline void arch_bprm_mm_init(struct mm_struct *mm, 107fe3d197fSDave Hansen struct vm_area_struct *vma) 108fe3d197fSDave Hansen { 109fe3d197fSDave Hansen mpx_mm_init(mm); 110fe3d197fSDave Hansen } 111fe3d197fSDave Hansen 1121965aae3SH. Peter Anvin #endif /* _ASM_X86_MMU_CONTEXT_H */ 113