diff options
author | Bjoern Brandenburg <bbb@mpi-sws.org> | 2015-12-16 05:16:05 -0500 |
---|---|---|
committer | Bjoern Brandenburg <bbb@mpi-sws.org> | 2016-03-08 09:21:31 -0500 |
commit | e2a78015a8ea4648a543d475fcfd3438b2c50dac (patch) | |
tree | 39fd753bc81169a202e2ead199f3d8d3f85ad08d | |
parent | a8037999bfc074ddfc231ae5af10be3da1511878 (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.h | 99 | ||||
-rw-r--r-- | include/litmus/litmus.h | 2 | ||||
-rw-r--r-- | include/litmus/rt_param.h | 55 | ||||
-rw-r--r-- | litmus/ctrldev.c | 97 |
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 | |||
6 | union 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 | */ | ||
30 | struct 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 | |||
63 | typedef 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 | |||
78 | union 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 | ||
86 | union 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 | */ | ||
110 | struct 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 | |||
123 | asmlinkage long sys_set_rt_task_param(pid_t pid, struct rt_task __user * param); | ||
124 | asmlinkage long sys_get_rt_task_param(pid_t pid, struct rt_task __user * param); | ||
125 | asmlinkage long sys_get_current_budget(lt_t __user * _expended, lt_t __user *_remaining); | ||
126 | asmlinkage long sys_null_call(cycles_t __user *ts); | ||
127 | asmlinkage long sys_od_open(int fd, int type, int obj_id, void* __user config); | ||
128 | asmlinkage long sys_od_close(int od); | ||
129 | asmlinkage long sys_complete_job(void); | ||
130 | asmlinkage long sys_litmus_lock(int lock_od); | ||
131 | asmlinkage long sys_litmus_unlock(int lock_od); | ||
132 | asmlinkage long sys_wait_for_job_release(unsigned int job); | ||
133 | asmlinkage long sys_wait_for_ts_release(void); | ||
134 | asmlinkage long sys_release_ts(lt_t __user *__delay); | ||
135 | |||
136 | static 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 | |||
119 | static struct file_operations litmus_ctrl_fops = { | 215 | static 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 | ||
124 | static struct miscdevice litmus_ctrl_dev = { | 221 | static struct miscdevice litmus_ctrl_dev = { |