aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2015-12-16 05:16:05 -0500
committerBjoern Brandenburg <bbb@mpi-sws.org>2016-03-08 09:21:31 -0500
commite2a78015a8ea4648a543d475fcfd3438b2c50dac (patch)
tree39fd753bc81169a202e2ead199f3d8d3f85ad08d
parenta8037999bfc074ddfc231ae5af10be3da1511878 (diff)
Expose LITMUS^RT system calls via control page ioctl()
Rationale: make LITMUS^RT ops available in a way that does not create merge conflicts each time we rebase LITMUS^RT on top of a new kernel version. This also helps with portability to different architectures, as we no longer need to patch each architecture's syscall table.
-rw-r--r--include/litmus/ctrlpage.h99
-rw-r--r--include/litmus/litmus.h2
-rw-r--r--include/litmus/rt_param.h55
-rw-r--r--litmus/ctrldev.c97
4 files changed, 198 insertions, 55 deletions
diff --git a/include/litmus/ctrlpage.h b/include/litmus/ctrlpage.h
new file mode 100644
index 000000000000..d86857605ace
--- /dev/null
+++ b/include/litmus/ctrlpage.h
@@ -0,0 +1,99 @@
1#ifndef _LITMUS_CTRLPAGE_H_
2#define _LITMUS_CTRLPAGE_H_
3
4#include <litmus/rt_param.h>
5
6union np_flag {
7 uint32_t raw;
8 struct {
9 /* Is the task currently in a non-preemptive section? */
10 uint32_t flag:31;
11 /* Should the task call into the scheduler? */
12 uint32_t preempt:1;
13 } np;
14};
15
16/* The definition of the data that is shared between the kernel and real-time
17 * tasks via a shared page (see litmus/ctrldev.c).
18 *
19 * WARNING: User space can write to this, so don't trust
20 * the correctness of the fields!
21 *
22 * This servees two purposes: to enable efficient signaling
23 * of non-preemptive sections (user->kernel) and
24 * delayed preemptions (kernel->user), and to export
25 * some real-time relevant statistics such as preemption and
26 * migration data to user space. We can't use a device to export
27 * statistics because we want to avoid system call overhead when
28 * determining preemption/migration overheads).
29 */
30struct control_page {
31 /* This flag is used by userspace to communicate non-preempive
32 * sections. */
33 volatile __attribute__ ((aligned (8))) union np_flag sched;
34
35 /* Incremented by the kernel each time an IRQ is handled. */
36 volatile __attribute__ ((aligned (8))) uint64_t irq_count;
37
38 /* Locking overhead tracing: userspace records here the time stamp
39 * and IRQ counter prior to starting the system call. */
40 uint64_t ts_syscall_start; /* Feather-Trace cycles */
41 uint64_t irq_syscall_start; /* Snapshot of irq_count when the syscall
42 * started. */
43
44 lt_t deadline; /* Deadline for the currently executing job */
45 lt_t release; /* Release time of current job */
46 uint64_t job_index; /* Job sequence number of current job */
47
48 /* to be extended */
49};
50
51/* Expected offsets within the control page. */
52
53#define LITMUS_CP_OFFSET_SCHED 0
54#define LITMUS_CP_OFFSET_IRQ_COUNT 8
55#define LITMUS_CP_OFFSET_TS_SC_START 16
56#define LITMUS_CP_OFFSET_IRQ_SC_START 24
57#define LITMUS_CP_OFFSET_DEADLINE 32
58#define LITMUS_CP_OFFSET_RELEASE 40
59#define LITMUS_CP_OFFSET_JOB_INDEX 48
60
61/* System call emulation via ioctl() */
62
63typedef enum {
64 LRT_null_call,
65 LRT_set_rt_task_param,
66 LRT_get_rt_task_param,
67 LRT_complete_job,
68 LRT_od_open,
69 LRT_od_close,
70 LRT_litmus_lock,
71 LRT_litmus_unlock,
72 LRT_wait_for_job_release,
73 LRT_wait_for_ts_release,
74 LRT_release_ts,
75 LRT_get_current_budget,
76} litmus_syscall_id_t;
77
78union litmus_syscall_args {
79 struct {
80 pid_t pid;
81 struct rt_task __user *param;
82 } get_set_task_param;
83
84 struct {
85 uint32_t fd;
86 uint32_t obj_type;
87 uint32_t obj_id;
88 void __user *config;
89 } od_open;
90
91 struct {
92 lt_t __user *expended;
93 lt_t __user *remaining;
94 } get_current_budget;
95};
96
97
98#endif
99
diff --git a/include/litmus/litmus.h b/include/litmus/litmus.h
index c3a52aea60fb..787bc2e2a6d8 100644
--- a/include/litmus/litmus.h
+++ b/include/litmus/litmus.h
@@ -6,6 +6,8 @@
6#ifndef _LINUX_LITMUS_H_ 6#ifndef _LINUX_LITMUS_H_
7#define _LINUX_LITMUS_H_ 7#define _LINUX_LITMUS_H_
8 8
9#include <litmus/ctrlpage.h>
10
9#include <litmus/debug_trace.h> 11#include <litmus/debug_trace.h>
10 12
11#ifdef CONFIG_RELEASE_MASTER 13#ifdef CONFIG_RELEASE_MASTER
diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h
index db133ac0e237..3f29d8c25d94 100644
--- a/include/litmus/rt_param.h
+++ b/include/litmus/rt_param.h
@@ -83,61 +83,6 @@ struct rt_task {
83 release_policy_t release_policy; 83 release_policy_t release_policy;
84}; 84};
85 85
86union np_flag {
87 uint32_t raw;
88 struct {
89 /* Is the task currently in a non-preemptive section? */
90 uint32_t flag:31;
91 /* Should the task call into the scheduler? */
92 uint32_t preempt:1;
93 } np;
94};
95
96/* The definition of the data that is shared between the kernel and real-time
97 * tasks via a shared page (see litmus/ctrldev.c).
98 *
99 * WARNING: User space can write to this, so don't trust
100 * the correctness of the fields!
101 *
102 * This servees two purposes: to enable efficient signaling
103 * of non-preemptive sections (user->kernel) and
104 * delayed preemptions (kernel->user), and to export
105 * some real-time relevant statistics such as preemption and
106 * migration data to user space. We can't use a device to export
107 * statistics because we want to avoid system call overhead when
108 * determining preemption/migration overheads).
109 */
110struct control_page {
111 /* This flag is used by userspace to communicate non-preempive
112 * sections. */
113 volatile __attribute__ ((aligned (8))) union np_flag sched;
114
115 /* Incremented by the kernel each time an IRQ is handled. */
116 volatile __attribute__ ((aligned (8))) uint64_t irq_count;
117
118 /* Locking overhead tracing: userspace records here the time stamp
119 * and IRQ counter prior to starting the system call. */
120 uint64_t ts_syscall_start; /* Feather-Trace cycles */
121 uint64_t irq_syscall_start; /* Snapshot of irq_count when the syscall
122 * started. */
123
124 lt_t deadline; /* Deadline for the currently executing job */
125 lt_t release; /* Release time of current job */
126 uint64_t job_index; /* Job sequence number of current job */
127
128 /* to be extended */
129};
130
131/* Expected offsets within the control page. */
132
133#define LITMUS_CP_OFFSET_SCHED 0
134#define LITMUS_CP_OFFSET_IRQ_COUNT 8
135#define LITMUS_CP_OFFSET_TS_SC_START 16
136#define LITMUS_CP_OFFSET_IRQ_SC_START 24
137#define LITMUS_CP_OFFSET_DEADLINE 32
138#define LITMUS_CP_OFFSET_RELEASE 40
139#define LITMUS_CP_OFFSET_JOB_INDEX 48
140
141/* don't export internal data structures to user space (liblitmus) */ 86/* don't export internal data structures to user space (liblitmus) */
142#ifdef __KERNEL__ 87#ifdef __KERNEL__
143 88
diff --git a/litmus/ctrldev.c b/litmus/ctrldev.c
index 877f2786b4c8..3c8bbdb7c782 100644
--- a/litmus/ctrldev.c
+++ b/litmus/ctrldev.c
@@ -3,6 +3,8 @@
3#include <linux/fs.h> 3#include <linux/fs.h>
4#include <linux/miscdevice.h> 4#include <linux/miscdevice.h>
5#include <linux/module.h> 5#include <linux/module.h>
6#include <linux/uaccess.h>
7
6 8
7#include <litmus/litmus.h> 9#include <litmus/litmus.h>
8 10
@@ -116,9 +118,104 @@ static int litmus_ctrl_mmap(struct file* filp, struct vm_area_struct* vma)
116 return err; 118 return err;
117} 119}
118 120
121/* LITMUS^RT system calls */
122
123asmlinkage long sys_set_rt_task_param(pid_t pid, struct rt_task __user * param);
124asmlinkage long sys_get_rt_task_param(pid_t pid, struct rt_task __user * param);
125asmlinkage long sys_get_current_budget(lt_t __user * _expended, lt_t __user *_remaining);
126asmlinkage long sys_null_call(cycles_t __user *ts);
127asmlinkage long sys_od_open(int fd, int type, int obj_id, void* __user config);
128asmlinkage long sys_od_close(int od);
129asmlinkage long sys_complete_job(void);
130asmlinkage long sys_litmus_lock(int lock_od);
131asmlinkage long sys_litmus_unlock(int lock_od);
132asmlinkage long sys_wait_for_job_release(unsigned int job);
133asmlinkage long sys_wait_for_ts_release(void);
134asmlinkage long sys_release_ts(lt_t __user *__delay);
135
136static long litmus_ctrl_ioctl(struct file *filp,
137 unsigned int cmd, unsigned long arg)
138{
139 long err = -ENOIOCTLCMD;
140
141 /* LITMUS^RT syscall emulation: we expose LITMUS^RT-specific operations
142 * via ioctl() to avoid merge conflicts with the syscall tables when
143 * rebasing LITMUS^RT. Whi this is not the most elegant way to expose
144 * syscall-like functionality, it helps with reducing the effort
145 * required to maintain LITMUS^RT out of tree.
146 */
147
148 union litmus_syscall_args syscall_args;
149
150 switch (cmd) {
151 case LRT_set_rt_task_param:
152 case LRT_get_rt_task_param:
153 case LRT_get_current_budget:
154 case LRT_od_open:
155 /* multiple arguments => need to get args via pointer */
156 /* get syscall parameters */
157 if (copy_from_user(&syscall_args, (void*) arg,
158 sizeof(syscall_args))) {
159 return -EFAULT;
160 }
161
162 switch (cmd) {
163 case LRT_set_rt_task_param:
164 return sys_set_rt_task_param(
165 syscall_args.get_set_task_param.pid,
166 syscall_args.get_set_task_param.param);
167 case LRT_get_rt_task_param:
168 return sys_get_rt_task_param(
169 syscall_args.get_set_task_param.pid,
170 syscall_args.get_set_task_param.param);
171 case LRT_get_current_budget:
172 return sys_get_current_budget(
173 syscall_args.get_current_budget.expended,
174 syscall_args.get_current_budget.remaining);
175 case LRT_od_open:
176 return sys_od_open(
177 syscall_args.od_open.fd,
178 syscall_args.od_open.obj_type,
179 syscall_args.od_open.obj_id,
180 syscall_args.od_open.config);
181 }
182
183
184 case LRT_null_call:
185 return sys_null_call((cycles_t __user *) arg);
186
187 case LRT_od_close:
188 return sys_od_close(arg);
189
190 case LRT_complete_job:
191 return sys_complete_job();
192
193 case LRT_litmus_lock:
194 return sys_litmus_lock(arg);
195
196 case LRT_litmus_unlock:
197 return sys_litmus_unlock(arg);
198
199 case LRT_wait_for_job_release:
200 return sys_wait_for_job_release(arg);
201
202 case LRT_wait_for_ts_release:
203 return sys_wait_for_ts_release();
204
205 case LRT_release_ts:
206 return sys_release_ts((lt_t __user *) arg);
207
208 default:
209 printk(KERN_DEBUG "ctrldev: strange ioctl (%u, %lu)\n", cmd, arg);
210 };
211
212 return err;
213}
214
119static struct file_operations litmus_ctrl_fops = { 215static struct file_operations litmus_ctrl_fops = {
120 .owner = THIS_MODULE, 216 .owner = THIS_MODULE,
121 .mmap = litmus_ctrl_mmap, 217 .mmap = litmus_ctrl_mmap,
218 .unlocked_ioctl = litmus_ctrl_ioctl,
122}; 219};
123 220
124static struct miscdevice litmus_ctrl_dev = { 221static struct miscdevice litmus_ctrl_dev = {