]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge tag 'for-3.16' of git://git.linaro.org/people/ard.biesheuvel/linux-arm into...
authorCatalin Marinas <catalin.marinas@arm.com>
Fri, 16 May 2014 09:05:11 +0000 (10:05 +0100)
committerCatalin Marinas <catalin.marinas@arm.com>
Fri, 16 May 2014 09:05:11 +0000 (10:05 +0100)
FPSIMD register bank context switching and crypto algorithms
optimisations for arm64 from Ard Biesheuvel.

* tag 'for-3.16' of git://git.linaro.org/people/ard.biesheuvel/linux-arm:
  arm64/crypto: AES-ECB/CBC/CTR/XTS using ARMv8 NEON and Crypto Extensions
  arm64: pull in <asm/simd.h> from asm-generic
  arm64/crypto: AES in CCM mode using ARMv8 Crypto Extensions
  arm64/crypto: AES using ARMv8 Crypto Extensions
  arm64/crypto: GHASH secure hash using ARMv8 Crypto Extensions
  arm64/crypto: SHA-224/SHA-256 using ARMv8 Crypto Extensions
  arm64/crypto: SHA-1 using ARMv8 Crypto Extensions
  arm64: add support for kernel mode NEON in interrupt context
  arm64: defer reloading a task's FPSIMD state to userland resume
  arm64: add abstractions for FPSIMD state manipulation
  asm-generic: allow generic unaligned access if the arch supports it

Conflicts:
arch/arm64/include/asm/thread_info.h

1  2 
arch/arm64/Kconfig
arch/arm64/include/asm/thread_info.h
arch/arm64/kernel/entry.S
arch/arm64/kernel/process.c
arch/arm64/kernel/ptrace.c
arch/arm64/kernel/signal.c
arch/arm64/kernel/signal32.c

diff --combined arch/arm64/Kconfig
index 9a5b5fea86ba559c6c36cc1877a2128c6b0e70ca,1cefc6fe969a613f786cca6bc70f87c46de9fca3..78b356d079ddfa34aabfb67f3355724a5ea04b05
@@@ -242,9 -242,6 +242,9 @@@ config ARCH_WANT_HUGE_PMD_SHAR
  config HAVE_ARCH_TRANSPARENT_HUGEPAGE
        def_bool y
  
 +config ARCH_HAS_CACHE_LINE_SIZE
 +      def_bool y
 +
  source "mm/Kconfig"
  
  config XEN_DOM0
@@@ -326,6 -323,8 +326,6 @@@ menu "CPU Power Management
  
  source "drivers/cpuidle/Kconfig"
  
 -source "kernel/power/Kconfig"
 -
  source "drivers/cpufreq/Kconfig"
  
  endmenu
@@@ -343,5 -342,8 +343,8 @@@ source "arch/arm64/Kconfig.debug
  source "security/Kconfig"
  
  source "crypto/Kconfig"
+ if CRYPTO
+ source "arch/arm64/crypto/Kconfig"
+ endif
  
  source "lib/Kconfig"
index 0a8b2a97a32ea133ac1c3deb3deda14b145d250b,4a1ca1cfb2f8ef9d3502299c699835854ff85356..9c086c63f91133ae2d512058ebeec081bf83d08e
@@@ -91,9 -91,6 +91,9 @@@ static inline struct thread_info *curre
  /*
   * thread information flags:
   *  TIF_SYSCALL_TRACE - syscall trace active
 + *  TIF_SYSCALL_TRACEPOINT - syscall tracepoint for ftrace
 + *  TIF_SYSCALL_AUDIT - syscall auditing
 + *  TIF_SECOMP                - syscall secure computing
   *  TIF_SIGPENDING    - signal pending
   *  TIF_NEED_RESCHED  - rescheduling necessary
   *  TIF_NOTIFY_RESUME - callback before returning to user
  #define TIF_SIGPENDING                0
  #define TIF_NEED_RESCHED      1
  #define TIF_NOTIFY_RESUME     2       /* callback before returning to user */
+ #define TIF_FOREIGN_FPSTATE   3       /* CPU's FP state is not current's */
  #define TIF_SYSCALL_TRACE     8
 +#define TIF_SYSCALL_AUDIT     9
 +#define TIF_SYSCALL_TRACEPOINT        10
 +#define TIF_SECCOMP           11
  #define TIF_POLLING_NRFLAG    16
  #define TIF_MEMDIE            18      /* is terminating due to OOM killer */
  #define TIF_FREEZE            19
  #define _TIF_SIGPENDING               (1 << TIF_SIGPENDING)
  #define _TIF_NEED_RESCHED     (1 << TIF_NEED_RESCHED)
  #define _TIF_NOTIFY_RESUME    (1 << TIF_NOTIFY_RESUME)
+ #define _TIF_FOREIGN_FPSTATE  (1 << TIF_FOREIGN_FPSTATE)
 +#define _TIF_SYSCALL_TRACE    (1 << TIF_SYSCALL_TRACE)
 +#define _TIF_SYSCALL_AUDIT    (1 << TIF_SYSCALL_AUDIT)
 +#define _TIF_SYSCALL_TRACEPOINT       (1 << TIF_SYSCALL_TRACEPOINT)
 +#define _TIF_SECCOMP          (1 << TIF_SECCOMP)
  #define _TIF_32BIT            (1 << TIF_32BIT)
  
  #define _TIF_WORK_MASK                (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
-                                _TIF_NOTIFY_RESUME)
+                                _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE)
  
 +#define _TIF_SYSCALL_WORK     (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
 +                               _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP)
 +
  #endif /* __KERNEL__ */
  #endif /* __ASM_THREAD_INFO_H */
index a670d0a98c89b179a0ca884bf7bfb0a9eaa4e0dd,80464e2fb1a59e2fc1159c262ebcee9aa9ac0f7c..bf017f4ffb4fb074283a1c8807aa40033b5bedf6
@@@ -60,9 -60,6 +60,9 @@@
        push    x0, x1
        .if     \el == 0
        mrs     x21, sp_el0
 +      get_thread_info tsk                     // Ensure MDSCR_EL1.SS is clear,
 +      ldr     x19, [tsk, #TI_FLAGS]           // since we can unmask debug
 +      disable_step_tsk x19, x20               // exceptions when scheduling.
        .else
        add     x21, sp, #S_FRAME_SIZE
        .endif
@@@ -262,7 -259,7 +262,7 @@@ el1_da
         * Data abort handling
         */
        mrs     x0, far_el1
 -      enable_dbg_if_not_stepping x2
 +      enable_dbg
        // re-enable interrupts if they were enabled in the aborted context
        tbnz    x23, #7, 1f                     // PSR_I_BIT
        enable_irq
@@@ -278,7 -275,6 +278,7 @@@ el1_sp_pc
         * Stack or PC alignment exception handling
         */
        mrs     x0, far_el1
 +      enable_dbg
        mov     x1, x25
        mov     x2, sp
        b       do_sp_pc_abort
@@@ -286,7 -282,6 +286,7 @@@ el1_undef
        /*
         * Undefined instruction
         */
 +      enable_dbg
        mov     x0, sp
        b       do_undefinstr
  el1_dbg:
        mrs     x0, far_el1
        mov     x2, sp                          // struct pt_regs
        bl      do_debug_exception
 -
 +      enable_dbg
        kernel_exit 1
  el1_inv:
        // TODO: add support for undefined instructions in kernel mode
 +      enable_dbg
        mov     x0, sp
        mov     x1, #BAD_SYNC
        mrs     x2, esr_el1
@@@ -313,7 -307,7 +313,7 @@@ ENDPROC(el1_sync
        .align  6
  el1_irq:
        kernel_entry 1
 -      enable_dbg_if_not_stepping x0
 +      enable_dbg
  #ifdef CONFIG_TRACE_IRQFLAGS
        bl      trace_hardirqs_off
  #endif
@@@ -338,7 -332,8 +338,7 @@@ ENDPROC(el1_irq
  #ifdef CONFIG_PREEMPT
  el1_preempt:
        mov     x24, lr
 -1:    enable_dbg
 -      bl      preempt_schedule_irq            // irq en/disable is done inside
 +1:    bl      preempt_schedule_irq            // irq en/disable is done inside
        ldr     x0, [tsk, #TI_FLAGS]            // get new tasks TI_FLAGS
        tbnz    x0, #TIF_NEED_RESCHED, 1b       // needs rescheduling?
        ret     x24
@@@ -354,7 -349,7 +354,7 @@@ el0_sync
        lsr     x24, x25, #ESR_EL1_EC_SHIFT     // exception class
        cmp     x24, #ESR_EL1_EC_SVC64          // SVC in 64-bit state
        b.eq    el0_svc
 -      adr     lr, ret_from_exception
 +      adr     lr, ret_to_user
        cmp     x24, #ESR_EL1_EC_DABT_EL0       // data abort in EL0
        b.eq    el0_da
        cmp     x24, #ESR_EL1_EC_IABT_EL0       // instruction abort in EL0
@@@ -383,7 -378,7 +383,7 @@@ el0_sync_compat
        lsr     x24, x25, #ESR_EL1_EC_SHIFT     // exception class
        cmp     x24, #ESR_EL1_EC_SVC32          // SVC in 32-bit state
        b.eq    el0_svc_compat
 -      adr     lr, ret_from_exception
 +      adr     lr, ret_to_user
        cmp     x24, #ESR_EL1_EC_DABT_EL0       // data abort in EL0
        b.eq    el0_da
        cmp     x24, #ESR_EL1_EC_IABT_EL0       // instruction abort in EL0
@@@ -428,8 -423,11 +428,8 @@@ el0_da
         */
        mrs     x0, far_el1
        bic     x0, x0, #(0xff << 56)
 -      disable_step x1
 -      isb
 -      enable_dbg
        // enable interrupts before calling the main handler
 -      enable_irq
 +      enable_dbg_and_irq
        mov     x1, x25
        mov     x2, sp
        b       do_mem_abort
@@@ -438,8 -436,11 +438,8 @@@ el0_ia
         * Instruction abort handling
         */
        mrs     x0, far_el1
 -      disable_step x1
 -      isb
 -      enable_dbg
        // enable interrupts before calling the main handler
 -      enable_irq
 +      enable_dbg_and_irq
        orr     x1, x25, #1 << 24               // use reserved ISS bit for instruction aborts
        mov     x2, sp
        b       do_mem_abort
@@@ -447,7 -448,6 +447,7 @@@ el0_fpsimd_acc
        /*
         * Floating Point or Advanced SIMD access
         */
 +      enable_dbg
        mov     x0, x25
        mov     x1, sp
        b       do_fpsimd_acc
@@@ -455,7 -455,6 +455,7 @@@ el0_fpsimd_exc
        /*
         * Floating Point or Advanced SIMD exception
         */
 +      enable_dbg
        mov     x0, x25
        mov     x1, sp
        b       do_fpsimd_exc
@@@ -464,8 -463,11 +464,8 @@@ el0_sp_pc
         * Stack or PC alignment exception handling
         */
        mrs     x0, far_el1
 -      disable_step x1
 -      isb
 -      enable_dbg
        // enable interrupts before calling the main handler
 -      enable_irq
 +      enable_dbg_and_irq
        mov     x1, x25
        mov     x2, sp
        b       do_sp_pc_abort
@@@ -473,9 -475,9 +473,9 @@@ el0_undef
        /*
         * Undefined instruction
         */
 -      mov     x0, sp
        // enable interrupts before calling the main handler
 -      enable_irq
 +      enable_dbg_and_irq
 +      mov     x0, sp
        b       do_undefinstr
  el0_dbg:
        /*
         */
        tbnz    x24, #0, el0_inv                // EL0 only
        mrs     x0, far_el1
 -      disable_step x1
        mov     x1, x25
        mov     x2, sp
 -      b       do_debug_exception
 +      bl      do_debug_exception
 +      enable_dbg
 +      b       ret_to_user
  el0_inv:
 +      enable_dbg
        mov     x0, sp
        mov     x1, #BAD_SYNC
        mrs     x2, esr_el1
@@@ -500,12 -500,15 +500,12 @@@ ENDPROC(el0_sync
  el0_irq:
        kernel_entry 0
  el0_irq_naked:
 -      disable_step x1
 -      isb
        enable_dbg
  #ifdef CONFIG_TRACE_IRQFLAGS
        bl      trace_hardirqs_off
  #endif
  
        irq_handler
 -      get_thread_info tsk
  
  #ifdef CONFIG_TRACE_IRQFLAGS
        bl      trace_hardirqs_on
        b       ret_to_user
  ENDPROC(el0_irq)
  
 -/*
 - * This is the return code to user mode for abort handlers
 - */
 -ret_from_exception:
 -      get_thread_info tsk
 -      b       ret_to_user
 -ENDPROC(ret_from_exception)
 -
  /*
   * Register switch for AArch64. The callee-saved registers need to be saved
   * and restored. On entry:
@@@ -552,7 -563,10 +552,7 @@@ ret_fast_syscall
        ldr     x1, [tsk, #TI_FLAGS]
        and     x2, x1, #_TIF_WORK_MASK
        cbnz    x2, fast_work_pending
 -      tbz     x1, #TIF_SINGLESTEP, fast_exit
 -      disable_dbg
 -      enable_step x2
 -fast_exit:
 +      enable_step_tsk x1, x2
        kernel_exit 0, ret = 1
  
  /*
@@@ -562,7 -576,7 +562,7 @@@ fast_work_pending
        str     x0, [sp, #S_X0]                 // returned x0
  work_pending:
        tbnz    x1, #TIF_NEED_RESCHED, work_resched
-       /* TIF_SIGPENDING or TIF_NOTIFY_RESUME case */
+       /* TIF_SIGPENDING, TIF_NOTIFY_RESUME or TIF_FOREIGN_FPSTATE case */
        ldr     x2, [sp, #S_PSTATE]
        mov     x0, sp                          // 'regs'
        tst     x2, #PSR_MODE_MASK              // user mode regs?
        bl      do_notify_resume
        b       ret_to_user
  work_resched:
 -      enable_dbg
        bl      schedule
  
  /*
@@@ -581,7 -596,9 +581,7 @@@ ret_to_user
        ldr     x1, [tsk, #TI_FLAGS]
        and     x2, x1, #_TIF_WORK_MASK
        cbnz    x2, work_pending
 -      tbz     x1, #TIF_SINGLESTEP, no_work_pending
 -      disable_dbg
 -      enable_step x2
 +      enable_step_tsk x1, x2
  no_work_pending:
        kernel_exit 0, ret = 0
  ENDPROC(ret_to_user)
@@@ -608,11 -625,14 +608,11 @@@ el0_svc
        mov     sc_nr, #__NR_syscalls
  el0_svc_naked:                                        // compat entry point
        stp     x0, scno, [sp, #S_ORIG_X0]      // save the original x0 and syscall number
 -      disable_step x16
 -      isb
 -      enable_dbg
 -      enable_irq
 +      enable_dbg_and_irq
  
 -      get_thread_info tsk
 -      ldr     x16, [tsk, #TI_FLAGS]           // check for syscall tracing
 -      tbnz    x16, #TIF_SYSCALL_TRACE, __sys_trace // are we tracing syscalls?
 +      ldr     x16, [tsk, #TI_FLAGS]           // check for syscall hooks
 +      tst     x16, #_TIF_SYSCALL_WORK
 +      b.ne    __sys_trace
        adr     lr, ret_fast_syscall            // return address
        cmp     scno, sc_nr                     // check upper syscall limit
        b.hs    ni_sys
@@@ -628,8 -648,9 +628,8 @@@ ENDPROC(el0_svc
         * switches, and waiting for our parent to respond.
         */
  __sys_trace:
 -      mov     x1, sp
 -      mov     w0, #0                          // trace entry
 -      bl      syscall_trace
 +      mov     x0, sp
 +      bl      syscall_trace_enter
        adr     lr, __sys_trace_return          // return address
        uxtw    scno, w0                        // syscall number (possibly new)
        mov     x1, sp                          // pointer to regs
  
  __sys_trace_return:
        str     x0, [sp]                        // save returned x0
 -      mov     x1, sp
 -      mov     w0, #1                          // trace exit
 -      bl      syscall_trace
 +      mov     x0, sp
 +      bl      syscall_trace_exit
        b       ret_to_user
  
  /*
index d04eb871cb0e8bcf3fd2cf5b262995bc072980d9,c5693163408c3bb9ab967dc7819ee9ae14282c0d..9f2d6020b6c2d8a40b4b7cee1d2b07d7882ff168
@@@ -20,7 -20,6 +20,7 @@@
  
  #include <stdarg.h>
  
 +#include <linux/compat.h>
  #include <linux/export.h>
  #include <linux/sched.h>
  #include <linux/kernel.h>
@@@ -206,7 -205,7 +206,7 @@@ void release_thread(struct task_struct 
  
  int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
  {
-       fpsimd_save_state(&current->thread.fpsimd_state);
+       fpsimd_preserve_current_state();
        *dst = *src;
        return 0;
  }
@@@ -301,7 -300,7 +301,7 @@@ struct task_struct *__switch_to(struct 
         * Complete any pending TLB or cache maintenance on this CPU in case
         * the thread migrates to a different CPU.
         */
 -      dsb();
 +      dsb(ish);
  
        /* the actual thread switch */
        last = cpu_switch_to(prev, next);
index 4b58e812cf674c9a2025e4a731fcaae9e961c21f,f8700eca24e781fe548786da280218be6403c331..32d52d3b079cca761cf0edaad4c74a2fca86115e
@@@ -19,7 -19,6 +19,7 @@@
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  
 +#include <linux/compat.h>
  #include <linux/kernel.h>
  #include <linux/sched.h>
  #include <linux/mm.h>
@@@ -518,6 -517,7 +518,7 @@@ static int fpr_set(struct task_struct *
                return ret;
  
        target->thread.fpsimd_state.user_fpsimd = newstate;
+       fpsimd_flush_task_state(target);
        return ret;
  }
  
@@@ -765,6 -765,7 +766,7 @@@ static int compat_vfp_set(struct task_s
                uregs->fpcr = fpscr & VFP_FPSCR_CTRL_MASK;
        }
  
+       fpsimd_flush_task_state(target);
        return ret;
  }
  
@@@ -1059,43 -1060,35 +1061,43 @@@ long arch_ptrace(struct task_struct *ch
        return ptrace_request(child, request, addr, data);
  }
  
 -asmlinkage int syscall_trace(int dir, struct pt_regs *regs)
 +enum ptrace_syscall_dir {
 +      PTRACE_SYSCALL_ENTER = 0,
 +      PTRACE_SYSCALL_EXIT,
 +};
 +
 +static void tracehook_report_syscall(struct pt_regs *regs,
 +                                   enum ptrace_syscall_dir dir)
  {
 +      int regno;
        unsigned long saved_reg;
  
 -      if (!test_thread_flag(TIF_SYSCALL_TRACE))
 -              return regs->syscallno;
 -
 -      if (is_compat_task()) {
 -              /* AArch32 uses ip (r12) for scratch */
 -              saved_reg = regs->regs[12];
 -              regs->regs[12] = dir;
 -      } else {
 -              /*
 -               * Save X7. X7 is used to denote syscall entry/exit:
 -               *   X7 = 0 -> entry, = 1 -> exit
 -               */
 -              saved_reg = regs->regs[7];
 -              regs->regs[7] = dir;
 -      }
 +      /*
 +       * A scratch register (ip(r12) on AArch32, x7 on AArch64) is
 +       * used to denote syscall entry/exit:
 +       */
 +      regno = (is_compat_task() ? 12 : 7);
 +      saved_reg = regs->regs[regno];
 +      regs->regs[regno] = dir;
  
 -      if (dir)
 +      if (dir == PTRACE_SYSCALL_EXIT)
                tracehook_report_syscall_exit(regs, 0);
        else if (tracehook_report_syscall_entry(regs))
                regs->syscallno = ~0UL;
  
 -      if (is_compat_task())
 -              regs->regs[12] = saved_reg;
 -      else
 -              regs->regs[7] = saved_reg;
 +      regs->regs[regno] = saved_reg;
 +}
 +
 +asmlinkage int syscall_trace_enter(struct pt_regs *regs)
 +{
 +      if (test_thread_flag(TIF_SYSCALL_TRACE))
 +              tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
  
        return regs->syscallno;
  }
 +
 +asmlinkage void syscall_trace_exit(struct pt_regs *regs)
 +{
 +      if (test_thread_flag(TIF_SYSCALL_TRACE))
 +              tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
 +}
index 2ba72a11629f083795f509965bd0c0c21f28b037,882f01774365671f5a8fbe096514db81805c9286..6357b9c6c90e7c72ef20e97c6459113c11cc53cf
@@@ -17,7 -17,6 +17,7 @@@
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  
 +#include <linux/compat.h>
  #include <linux/errno.h>
  #include <linux/signal.h>
  #include <linux/personality.h>
@@@ -26,6 -25,7 +26,6 @@@
  #include <linux/tracehook.h>
  #include <linux/ratelimit.h>
  
 -#include <asm/compat.h>
  #include <asm/debug-monitors.h>
  #include <asm/elf.h>
  #include <asm/cacheflush.h>
@@@ -51,7 -51,7 +51,7 @@@ static int preserve_fpsimd_context(stru
        int err;
  
        /* dump the hardware registers to the fpsimd_state structure */
-       fpsimd_save_state(fpsimd);
+       fpsimd_preserve_current_state();
  
        /* copy the FP and status/control registers */
        err = __copy_to_user(ctx->vregs, fpsimd->vregs, sizeof(fpsimd->vregs));
@@@ -86,11 -86,8 +86,8 @@@ static int restore_fpsimd_context(struc
        __get_user_error(fpsimd.fpcr, &ctx->fpcr, err);
  
        /* load the hardware registers from the fpsimd_state structure */
-       if (!err) {
-               preempt_disable();
-               fpsimd_load_state(&fpsimd);
-               preempt_enable();
-       }
+       if (!err)
+               fpsimd_update_current_state(&fpsimd);
  
        return err ? -EFAULT : 0;
  }
@@@ -100,7 -97,8 +97,7 @@@ static int restore_sigframe(struct pt_r
  {
        sigset_t set;
        int i, err;
 -      struct aux_context __user *aux =
 -              (struct aux_context __user *)sf->uc.uc_mcontext.__reserved;
 +      void *aux = sf->uc.uc_mcontext.__reserved;
  
        err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
        if (err == 0)
  
        err |= !valid_user_regs(&regs->user_regs);
  
 -      if (err == 0)
 -              err |= restore_fpsimd_context(&aux->fpsimd);
 +      if (err == 0) {
 +              struct fpsimd_context *fpsimd_ctx =
 +                      container_of(aux, struct fpsimd_context, head);
 +              err |= restore_fpsimd_context(fpsimd_ctx);
 +      }
  
        return err;
  }
@@@ -169,8 -164,8 +166,8 @@@ static int setup_sigframe(struct rt_sig
                          struct pt_regs *regs, sigset_t *set)
  {
        int i, err = 0;
 -      struct aux_context __user *aux =
 -              (struct aux_context __user *)sf->uc.uc_mcontext.__reserved;
 +      void *aux = sf->uc.uc_mcontext.__reserved;
 +      struct _aarch64_ctx *end;
  
        /* set up the stack frame for unwinding */
        __put_user_error(regs->regs[29], &sf->fp, err);
  
        err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
  
 -      if (err == 0)
 -              err |= preserve_fpsimd_context(&aux->fpsimd);
 +      if (err == 0) {
 +              struct fpsimd_context *fpsimd_ctx =
 +                      container_of(aux, struct fpsimd_context, head);
 +              err |= preserve_fpsimd_context(fpsimd_ctx);
 +              aux += sizeof(*fpsimd_ctx);
 +      }
 +
 +      /* fault information, if valid */
 +      if (current->thread.fault_code) {
 +              struct esr_context *esr_ctx =
 +                      container_of(aux, struct esr_context, head);
 +              __put_user_error(ESR_MAGIC, &esr_ctx->head.magic, err);
 +              __put_user_error(sizeof(*esr_ctx), &esr_ctx->head.size, err);
 +              __put_user_error(current->thread.fault_code, &esr_ctx->esr, err);
 +              aux += sizeof(*esr_ctx);
 +      }
  
        /* set the "end" magic */
 -      __put_user_error(0, &aux->end.magic, err);
 -      __put_user_error(0, &aux->end.size, err);
 +      end = aux;
 +      __put_user_error(0, &end->magic, err);
 +      __put_user_error(0, &end->size, err);
  
        return err;
  }
@@@ -433,4 -413,8 +430,8 @@@ asmlinkage void do_notify_resume(struc
                clear_thread_flag(TIF_NOTIFY_RESUME);
                tracehook_notify_resume(regs);
        }
+       if (thread_flags & _TIF_FOREIGN_FPSTATE)
+               fpsimd_restore_current_state();
  }
index 050c1c2af777212f2b0eaab0150348b12b561ebc,ac7e237d0bda50aa9bb426509fc5689acbecfce0..3491c638f17216d542e7297f2b41867434eccde4
@@@ -23,7 -23,6 +23,7 @@@
  #include <linux/syscalls.h>
  #include <linux/ratelimit.h>
  
 +#include <asm/esr.h>
  #include <asm/fpsimd.h>
  #include <asm/signal32.h>
  #include <asm/uaccess.h>
@@@ -82,8 -81,6 +82,8 @@@ struct compat_vfp_sigframe 
  #define VFP_MAGIC             0x56465001
  #define VFP_STORAGE_SIZE      sizeof(struct compat_vfp_sigframe)
  
 +#define FSR_WRITE_SHIFT               (11)
 +
  struct compat_aux_sigframe {
        struct compat_vfp_sigframe      vfp;
  
@@@ -222,7 -219,7 +222,7 @@@ static int compat_preserve_vfp_context(
         * Note that this also saves V16-31, which aren't visible
         * in AArch32.
         */
-       fpsimd_save_state(fpsimd);
+       fpsimd_preserve_current_state();
  
        /* Place structure header on the stack */
        __put_user_error(magic, &frame->magic, err);
@@@ -285,11 -282,8 +285,8 @@@ static int compat_restore_vfp_context(s
         * We don't need to touch the exception register, so
         * reload the hardware state.
         */
-       if (!err) {
-               preempt_disable();
-               fpsimd_load_state(&fpsimd);
-               preempt_enable();
-       }
+       if (!err)
+               fpsimd_update_current_state(&fpsimd);
  
        return err ? -EFAULT : 0;
  }
@@@ -503,9 -497,7 +500,9 @@@ static int compat_setup_sigframe(struc
        __put_user_error(regs->pstate, &sf->uc.uc_mcontext.arm_cpsr, err);
  
        __put_user_error((compat_ulong_t)0, &sf->uc.uc_mcontext.trap_no, err);
 -      __put_user_error((compat_ulong_t)0, &sf->uc.uc_mcontext.error_code, err);
 +      /* set the compat FSR WnR */
 +      __put_user_error(!!(current->thread.fault_code & ESR_EL1_WRITE) <<
 +                       FSR_WRITE_SHIFT, &sf->uc.uc_mcontext.error_code, err);
        __put_user_error(current->thread.fault_address, &sf->uc.uc_mcontext.fault_address, err);
        __put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err);