18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) IBM Corporation, 2011 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Authors: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> 78c2ecf20Sopenharmony_ci * Anton Blanchard <anton@au.ibm.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 108c2ecf20Sopenharmony_ci#include <linux/hardirq.h> 118c2ecf20Sopenharmony_ci#include <asm/switch_to.h> 128c2ecf20Sopenharmony_ci#include <asm/asm-prototypes.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ciint enter_vmx_usercopy(void) 158c2ecf20Sopenharmony_ci{ 168c2ecf20Sopenharmony_ci if (in_interrupt()) 178c2ecf20Sopenharmony_ci return 0; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci preempt_disable(); 208c2ecf20Sopenharmony_ci /* 218c2ecf20Sopenharmony_ci * We need to disable page faults as they can call schedule and 228c2ecf20Sopenharmony_ci * thus make us lose the VMX context. So on page faults, we just 238c2ecf20Sopenharmony_ci * fail which will cause a fallback to the normal non-vmx copy. 248c2ecf20Sopenharmony_ci */ 258c2ecf20Sopenharmony_ci pagefault_disable(); 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci enable_kernel_altivec(); 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci return 1; 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* 338c2ecf20Sopenharmony_ci * This function must return 0 because we tail call optimise when calling 348c2ecf20Sopenharmony_ci * from __copy_tofrom_user_power7 which returns 0 on success. 358c2ecf20Sopenharmony_ci */ 368c2ecf20Sopenharmony_ciint exit_vmx_usercopy(void) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci disable_kernel_altivec(); 398c2ecf20Sopenharmony_ci pagefault_enable(); 408c2ecf20Sopenharmony_ci preempt_enable(); 418c2ecf20Sopenharmony_ci return 0; 428c2ecf20Sopenharmony_ci} 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ciint enter_vmx_ops(void) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci if (in_interrupt()) 478c2ecf20Sopenharmony_ci return 0; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci preempt_disable(); 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci enable_kernel_altivec(); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci return 1; 548c2ecf20Sopenharmony_ci} 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci/* 578c2ecf20Sopenharmony_ci * All calls to this function will be optimised into tail calls. We are 588c2ecf20Sopenharmony_ci * passed a pointer to the destination which we return as required by a 598c2ecf20Sopenharmony_ci * memcpy implementation. 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_civoid *exit_vmx_ops(void *dest) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci disable_kernel_altivec(); 648c2ecf20Sopenharmony_ci preempt_enable(); 658c2ecf20Sopenharmony_ci return dest; 668c2ecf20Sopenharmony_ci} 67