forked from mirrors/linux
		
	powerpc: Define set_thread_uses_vas()
A CP_ABORT instruction is required in processes that have mapped a VAS "paste address" with the intention of using COPY/PASTE instructions. But since CP_ABORT is expensive, we want to restrict it to only processes that use/intend to use COPY/PASTE. Define an interface, set_thread_uses_vas(), that VAS can use to indicate that the current process opened a send window. During context switch, issue CP_ABORT only for processes that have the flag set. Thanks for input from Nick Piggin, Michael Ellerman. Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> [mpe: Fix to not use new_thread after _switch() returns] Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
		
							parent
							
								
									ec233ede4c
								
							
						
					
					
						commit
						9d2a4d7133
					
				
					 3 changed files with 35 additions and 10 deletions
				
			
		|  | @ -341,7 +341,9 @@ struct thread_struct { | |||
| 	unsigned long	sier; | ||||
| 	unsigned long	mmcr2; | ||||
| 	unsigned 	mmcr0; | ||||
| 
 | ||||
| 	unsigned 	used_ebb; | ||||
| 	unsigned int	used_vas; | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -91,6 +91,8 @@ static inline void clear_task_ebb(struct task_struct *t) | |||
| #endif | ||||
| } | ||||
| 
 | ||||
| extern int set_thread_uses_vas(void); | ||||
| 
 | ||||
| extern int set_thread_tidr(struct task_struct *t); | ||||
| extern void clear_thread_tidr(struct task_struct *t); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1244,17 +1244,17 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
| 		 * The copy-paste buffer can only store into foreign real | ||||
| 		 * addresses, so unprivileged processes can not see the | ||||
| 		 * data or use it in any way unless they have foreign real | ||||
| 		 * mappings. We don't have a VAS driver that allocates those | ||||
| 		 * yet, so no cpabort is required. | ||||
| 		 * mappings. If the new process has the foreign real address | ||||
| 		 * mappings, we must issue a cp_abort to clear any state and | ||||
| 		 * prevent snooping, corruption or a covert channel. | ||||
| 		 * | ||||
| 		 * DD1 allows paste into normal system memory so we do an | ||||
| 		 * unpaired copy, rather than cp_abort, to clear the buffer, | ||||
| 		 * since cp_abort is quite expensive. | ||||
| 		 */ | ||||
| 		if (cpu_has_feature(CPU_FTR_POWER9_DD1)) { | ||||
| 			/*
 | ||||
| 			 * DD1 allows paste into normal system memory, so we | ||||
| 			 * do an unpaired copy here to clear the buffer and | ||||
| 			 * prevent a covert channel being set up. | ||||
| 			 * | ||||
| 			 * cpabort is not used because it is quite expensive. | ||||
| 			 */ | ||||
| 		if (current_thread_info()->task->thread.used_vas) { | ||||
| 			asm volatile(PPC_CP_ABORT); | ||||
| 		} else if (cpu_has_feature(CPU_FTR_POWER9_DD1)) { | ||||
| 			asm volatile(PPC_COPY(%0, %1) | ||||
| 					: : "r"(dummy_copy_buffer), "r"(0)); | ||||
| 		} | ||||
|  | @ -1455,6 +1455,27 @@ void flush_thread(void) | |||
| #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | ||||
| } | ||||
| 
 | ||||
| int set_thread_uses_vas(void) | ||||
| { | ||||
| #ifdef CONFIG_PPC_BOOK3S_64 | ||||
| 	if (!cpu_has_feature(CPU_FTR_ARCH_300)) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	current->thread.used_vas = 1; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Even a process that has no foreign real address mapping can use | ||||
| 	 * an unpaired COPY instruction (to no real effect). Issue CP_ABORT | ||||
| 	 * to clear any pending COPY and prevent a covert channel. | ||||
| 	 * | ||||
| 	 * __switch_to() will issue CP_ABORT on future context switches. | ||||
| 	 */ | ||||
| 	asm volatile(PPC_CP_ABORT); | ||||
| 
 | ||||
| #endif /* CONFIG_PPC_BOOK3S_64 */ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_PPC64 | ||||
| static DEFINE_SPINLOCK(vas_thread_id_lock); | ||||
| static DEFINE_IDA(vas_thread_ida); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Sukadev Bhattiprolu
						Sukadev Bhattiprolu