root/arch/arm64/kernel/ssbd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ssbd_ssbs_enable
  2. ssbd_ssbs_disable
  3. ssbd_prctl_set
  4. arch_prctl_spec_ctrl_set
  5. ssbd_prctl_get
  6. arch_prctl_spec_ctrl_get

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (C) 2018 ARM Ltd, All Rights Reserved.
   4  */
   5 
   6 #include <linux/compat.h>
   7 #include <linux/errno.h>
   8 #include <linux/prctl.h>
   9 #include <linux/sched.h>
  10 #include <linux/sched/task_stack.h>
  11 #include <linux/thread_info.h>
  12 
  13 #include <asm/cpufeature.h>
  14 
  15 static void ssbd_ssbs_enable(struct task_struct *task)
  16 {
  17         u64 val = is_compat_thread(task_thread_info(task)) ?
  18                   PSR_AA32_SSBS_BIT : PSR_SSBS_BIT;
  19 
  20         task_pt_regs(task)->pstate |= val;
  21 }
  22 
  23 static void ssbd_ssbs_disable(struct task_struct *task)
  24 {
  25         u64 val = is_compat_thread(task_thread_info(task)) ?
  26                   PSR_AA32_SSBS_BIT : PSR_SSBS_BIT;
  27 
  28         task_pt_regs(task)->pstate &= ~val;
  29 }
  30 
  31 /*
  32  * prctl interface for SSBD
  33  */
  34 static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl)
  35 {
  36         int state = arm64_get_ssbd_state();
  37 
  38         /* Unsupported */
  39         if (state == ARM64_SSBD_UNKNOWN)
  40                 return -EINVAL;
  41 
  42         /* Treat the unaffected/mitigated state separately */
  43         if (state == ARM64_SSBD_MITIGATED) {
  44                 switch (ctrl) {
  45                 case PR_SPEC_ENABLE:
  46                         return -EPERM;
  47                 case PR_SPEC_DISABLE:
  48                 case PR_SPEC_FORCE_DISABLE:
  49                         return 0;
  50                 }
  51         }
  52 
  53         /*
  54          * Things are a bit backward here: the arm64 internal API
  55          * *enables the mitigation* when the userspace API *disables
  56          * speculation*. So much fun.
  57          */
  58         switch (ctrl) {
  59         case PR_SPEC_ENABLE:
  60                 /* If speculation is force disabled, enable is not allowed */
  61                 if (state == ARM64_SSBD_FORCE_ENABLE ||
  62                     task_spec_ssb_force_disable(task))
  63                         return -EPERM;
  64                 task_clear_spec_ssb_disable(task);
  65                 clear_tsk_thread_flag(task, TIF_SSBD);
  66                 ssbd_ssbs_enable(task);
  67                 break;
  68         case PR_SPEC_DISABLE:
  69                 if (state == ARM64_SSBD_FORCE_DISABLE)
  70                         return -EPERM;
  71                 task_set_spec_ssb_disable(task);
  72                 set_tsk_thread_flag(task, TIF_SSBD);
  73                 ssbd_ssbs_disable(task);
  74                 break;
  75         case PR_SPEC_FORCE_DISABLE:
  76                 if (state == ARM64_SSBD_FORCE_DISABLE)
  77                         return -EPERM;
  78                 task_set_spec_ssb_disable(task);
  79                 task_set_spec_ssb_force_disable(task);
  80                 set_tsk_thread_flag(task, TIF_SSBD);
  81                 ssbd_ssbs_disable(task);
  82                 break;
  83         default:
  84                 return -ERANGE;
  85         }
  86 
  87         return 0;
  88 }
  89 
  90 int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
  91                              unsigned long ctrl)
  92 {
  93         switch (which) {
  94         case PR_SPEC_STORE_BYPASS:
  95                 return ssbd_prctl_set(task, ctrl);
  96         default:
  97                 return -ENODEV;
  98         }
  99 }
 100 
 101 static int ssbd_prctl_get(struct task_struct *task)
 102 {
 103         switch (arm64_get_ssbd_state()) {
 104         case ARM64_SSBD_UNKNOWN:
 105                 return -EINVAL;
 106         case ARM64_SSBD_FORCE_ENABLE:
 107                 return PR_SPEC_DISABLE;
 108         case ARM64_SSBD_KERNEL:
 109                 if (task_spec_ssb_force_disable(task))
 110                         return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
 111                 if (task_spec_ssb_disable(task))
 112                         return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
 113                 return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
 114         case ARM64_SSBD_FORCE_DISABLE:
 115                 return PR_SPEC_ENABLE;
 116         default:
 117                 return PR_SPEC_NOT_AFFECTED;
 118         }
 119 }
 120 
 121 int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
 122 {
 123         switch (which) {
 124         case PR_SPEC_STORE_BYPASS:
 125                 return ssbd_prctl_get(task);
 126         default:
 127                 return -ENODEV;
 128         }
 129 }

/* [<][>][^][v][top][bottom][index][help] */