0001
0002
0003
0004
0005
0006 #include <linux/cpu.h>
0007 #include <linux/cpuset.h>
0008 #include <linux/cpumask.h>
0009 #include <linux/delay.h>
0010 #include <linux/kernel.h>
0011 #include <linux/init.h>
0012 #include <linux/sched.h>
0013 #include <linux/sched/task.h>
0014 #include <linux/cred.h>
0015 #include <linux/security.h>
0016 #include <linux/types.h>
0017 #include <linux/uaccess.h>
0018
0019
0020
0021
0022 cpumask_t mt_fpu_cpumask;
0023
0024 static int fpaff_threshold = -1;
0025 unsigned long mt_fpemul_threshold;
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 static inline struct task_struct *find_process_by_pid(pid_t pid)
0042 {
0043 return pid ? find_task_by_vpid(pid) : current;
0044 }
0045
0046
0047
0048
0049 static bool check_same_owner(struct task_struct *p)
0050 {
0051 const struct cred *cred = current_cred(), *pcred;
0052 bool match;
0053
0054 rcu_read_lock();
0055 pcred = __task_cred(p);
0056 match = (uid_eq(cred->euid, pcred->euid) ||
0057 uid_eq(cred->euid, pcred->uid));
0058 rcu_read_unlock();
0059 return match;
0060 }
0061
0062
0063
0064
0065 asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
0066 unsigned long __user *user_mask_ptr)
0067 {
0068 cpumask_var_t cpus_allowed, new_mask, effective_mask;
0069 struct thread_info *ti;
0070 struct task_struct *p;
0071 int retval;
0072
0073 if (len < sizeof(new_mask))
0074 return -EINVAL;
0075
0076 if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
0077 return -EFAULT;
0078
0079 cpus_read_lock();
0080 rcu_read_lock();
0081
0082 p = find_process_by_pid(pid);
0083 if (!p) {
0084 rcu_read_unlock();
0085 cpus_read_unlock();
0086 return -ESRCH;
0087 }
0088
0089
0090 get_task_struct(p);
0091 rcu_read_unlock();
0092
0093 if (!alloc_cpumask_var(&cpus_allowed, GFP_KERNEL)) {
0094 retval = -ENOMEM;
0095 goto out_put_task;
0096 }
0097 if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) {
0098 retval = -ENOMEM;
0099 goto out_free_cpus_allowed;
0100 }
0101 if (!alloc_cpumask_var(&effective_mask, GFP_KERNEL)) {
0102 retval = -ENOMEM;
0103 goto out_free_new_mask;
0104 }
0105 if (!check_same_owner(p) && !capable(CAP_SYS_NICE)) {
0106 retval = -EPERM;
0107 goto out_unlock;
0108 }
0109
0110 retval = security_task_setscheduler(p);
0111 if (retval)
0112 goto out_unlock;
0113
0114
0115 cpumask_copy(&p->thread.user_cpus_allowed, new_mask);
0116
0117 again:
0118
0119 ti = task_thread_info(p);
0120 if (test_ti_thread_flag(ti, TIF_FPUBOUND) &&
0121 cpumask_intersects(new_mask, &mt_fpu_cpumask)) {
0122 cpumask_and(effective_mask, new_mask, &mt_fpu_cpumask);
0123 retval = set_cpus_allowed_ptr(p, effective_mask);
0124 } else {
0125 cpumask_copy(effective_mask, new_mask);
0126 clear_ti_thread_flag(ti, TIF_FPUBOUND);
0127 retval = set_cpus_allowed_ptr(p, new_mask);
0128 }
0129
0130 if (!retval) {
0131 cpuset_cpus_allowed(p, cpus_allowed);
0132 if (!cpumask_subset(effective_mask, cpus_allowed)) {
0133
0134
0135
0136
0137
0138 cpumask_copy(new_mask, cpus_allowed);
0139 goto again;
0140 }
0141 }
0142 out_unlock:
0143 free_cpumask_var(effective_mask);
0144 out_free_new_mask:
0145 free_cpumask_var(new_mask);
0146 out_free_cpus_allowed:
0147 free_cpumask_var(cpus_allowed);
0148 out_put_task:
0149 put_task_struct(p);
0150 cpus_read_unlock();
0151 return retval;
0152 }
0153
0154
0155
0156
0157 asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
0158 unsigned long __user *user_mask_ptr)
0159 {
0160 unsigned int real_len;
0161 cpumask_t allowed, mask;
0162 int retval;
0163 struct task_struct *p;
0164
0165 real_len = sizeof(mask);
0166 if (len < real_len)
0167 return -EINVAL;
0168
0169 cpus_read_lock();
0170 rcu_read_lock();
0171
0172 retval = -ESRCH;
0173 p = find_process_by_pid(pid);
0174 if (!p)
0175 goto out_unlock;
0176 retval = security_task_getscheduler(p);
0177 if (retval)
0178 goto out_unlock;
0179
0180 cpumask_or(&allowed, &p->thread.user_cpus_allowed, p->cpus_ptr);
0181 cpumask_and(&mask, &allowed, cpu_active_mask);
0182
0183 out_unlock:
0184 rcu_read_unlock();
0185 cpus_read_unlock();
0186 if (retval)
0187 return retval;
0188 if (copy_to_user(user_mask_ptr, &mask, real_len))
0189 return -EFAULT;
0190 return real_len;
0191 }
0192
0193
0194 static int __init fpaff_thresh(char *str)
0195 {
0196 get_option(&str, &fpaff_threshold);
0197 return 1;
0198 }
0199 __setup("fpaff=", fpaff_thresh);
0200
0201
0202
0203
0204 #define FPUSEFACTOR 2000
0205
0206 static __init int mt_fp_affinity_init(void)
0207 {
0208 if (fpaff_threshold >= 0) {
0209 mt_fpemul_threshold = fpaff_threshold;
0210 } else {
0211 mt_fpemul_threshold =
0212 (FPUSEFACTOR * (loops_per_jiffy/(500000/HZ))) / HZ;
0213 }
0214 printk(KERN_DEBUG "FPU Affinity set after %ld emulations\n",
0215 mt_fpemul_threshold);
0216
0217 return 0;
0218 }
0219 arch_initcall(mt_fp_affinity_init);