| 
									
										
										
										
											2008-10-22 22:26:29 -07:00
										 |  |  | #ifndef _ASM_X86_MMU_CONTEXT_H
 | 
					
						
							|  |  |  | #define _ASM_X86_MMU_CONTEXT_H
 | 
					
						
							| 
									
										
										
										
											2008-06-25 00:19:07 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <asm/desc.h>
 | 
					
						
							| 
									
										
										
										
											2011-07-26 16:09:06 -07:00
										 |  |  | #include <linux/atomic.h>
 | 
					
						
							| 
									
										
										
										
											2008-06-25 00:19:07 -04:00
										 |  |  | #include <asm/pgalloc.h>
 | 
					
						
							|  |  |  | #include <asm/tlbflush.h>
 | 
					
						
							|  |  |  | #include <asm/paravirt.h>
 | 
					
						
							|  |  |  | #ifndef CONFIG_PARAVIRT
 | 
					
						
							|  |  |  | #include <asm-generic/mm_hooks.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void paravirt_activate_mm(struct mm_struct *prev, | 
					
						
							|  |  |  | 					struct mm_struct *next) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif	/* !CONFIG_PARAVIRT */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Used for LDT copy/destruction. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int init_new_context(struct task_struct *tsk, struct mm_struct *mm); | 
					
						
							|  |  |  | void destroy_context(struct mm_struct *mm); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-21 17:26:06 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifdef CONFIG_SMP
 | 
					
						
							| 
									
										
										
										
											2012-05-11 15:35:27 +08:00
										 |  |  | 	if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) | 
					
						
							|  |  |  | 		this_cpu_write(cpu_tlbstate.state, TLBSTATE_LAZY); | 
					
						
							| 
									
										
										
										
											2009-01-21 17:26:06 +09:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, | 
					
						
							|  |  |  | 			     struct task_struct *tsk) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned cpu = smp_processor_id(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (likely(prev != next)) { | 
					
						
							|  |  |  | #ifdef CONFIG_SMP
 | 
					
						
							| 
									
										
										
										
											2012-05-11 15:35:27 +08:00
										 |  |  | 		this_cpu_write(cpu_tlbstate.state, TLBSTATE_OK); | 
					
						
							|  |  |  | 		this_cpu_write(cpu_tlbstate.active_mm, next); | 
					
						
							| 
									
										
										
										
											2007-10-11 11:20:03 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-09-24 09:34:51 -06:00
										 |  |  | 		cpumask_set_cpu(cpu, mm_cpumask(next)); | 
					
						
							| 
									
										
										
										
											2009-01-21 17:26:06 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* Re-load page tables */ | 
					
						
							|  |  |  | 		load_cr3(next->pgd); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-03 12:20:04 -08:00
										 |  |  | 		/* stop flush ipis for the previous mm */ | 
					
						
							|  |  |  | 		cpumask_clear_cpu(cpu, mm_cpumask(prev)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-21 17:26:06 +09:00
										 |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * load the LDT, if the LDT is different: | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		if (unlikely(prev->context.ldt != next->context.ldt)) | 
					
						
							|  |  |  | 			load_LDT_nolock(&next->context); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #ifdef CONFIG_SMP
 | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-05-11 15:35:27 +08:00
										 |  |  | 		this_cpu_write(cpu_tlbstate.state, TLBSTATE_OK); | 
					
						
							|  |  |  | 		BUG_ON(this_cpu_read(cpu_tlbstate.active_mm) != next); | 
					
						
							| 
									
										
										
										
											2009-01-21 17:26:06 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 09:34:51 -06:00
										 |  |  | 		if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next))) { | 
					
						
							| 
									
										
										
										
											2009-01-21 17:26:06 +09:00
										 |  |  | 			/* We were in lazy tlb mode and leave_mm disabled
 | 
					
						
							|  |  |  | 			 * tlb flush IPI delivery. We must reload CR3 | 
					
						
							|  |  |  | 			 * to make sure to use no freed page tables. | 
					
						
							|  |  |  | 			 */ | 
					
						
							|  |  |  | 			load_cr3(next->pgd); | 
					
						
							|  |  |  | 			load_LDT_nolock(&next->context); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-06-25 00:19:07 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define activate_mm(prev, next)			\
 | 
					
						
							|  |  |  | do {						\ | 
					
						
							|  |  |  | 	paravirt_activate_mm((prev), (next));	\ | 
					
						
							|  |  |  | 	switch_mm((prev), (next), NULL);	\ | 
					
						
							|  |  |  | } while (0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-21 17:26:06 +09:00
										 |  |  | #ifdef CONFIG_X86_32
 | 
					
						
							|  |  |  | #define deactivate_mm(tsk, mm)			\
 | 
					
						
							|  |  |  | do {						\ | 
					
						
							| 
									
										
										
										
											2009-02-09 22:17:40 +09:00
										 |  |  | 	lazy_load_gs(0);			\ | 
					
						
							| 
									
										
										
										
											2009-01-21 17:26:06 +09:00
										 |  |  | } while (0) | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define deactivate_mm(tsk, mm)			\
 | 
					
						
							|  |  |  | do {						\ | 
					
						
							|  |  |  | 	load_gs_index(0);			\ | 
					
						
							|  |  |  | 	loadsegment(fs, 0);			\ | 
					
						
							|  |  |  | } while (0) | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-06-25 00:19:07 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-22 22:26:29 -07:00
										 |  |  | #endif /* _ASM_X86_MMU_CONTEXT_H */
 |