aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/um/drivers/line.c4
-rw-r--r--arch/um/drivers/port_user.c2
-rw-r--r--arch/um/drivers/vector_kern.c15
-rw-r--r--arch/um/drivers/vector_user.c6
-rw-r--r--arch/um/include/shared/aio.h28
-rw-r--r--arch/um/kernel/irq.c3
-rw-r--r--arch/um/kernel/trap.c2
-rw-r--r--arch/um/os-Linux/Makefile8
-rw-r--r--arch/um/os-Linux/aio.c390
-rw-r--r--arch/um/os-Linux/skas/process.c5
-rw-r--r--arch/x86/um/shared/sysdep/ptrace_32.h12
11 files changed, 19 insertions, 456 deletions
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 8d80b27502e6..7e524efed584 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -261,7 +261,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
261 if (err == 0) { 261 if (err == 0) {
262 spin_unlock(&line->lock); 262 spin_unlock(&line->lock);
263 return IRQ_NONE; 263 return IRQ_NONE;
264 } else if (err < 0) { 264 } else if ((err < 0) && (err != -EAGAIN)) {
265 line->head = line->buffer; 265 line->head = line->buffer;
266 line->tail = line->buffer; 266 line->tail = line->buffer;
267 } 267 }
@@ -284,7 +284,7 @@ int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
284 if (err) 284 if (err)
285 return err; 285 return err;
286 if (output) 286 if (output)
287 err = um_request_irq(driver->write_irq, fd, IRQ_NONE, 287 err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
288 line_write_interrupt, IRQF_SHARED, 288 line_write_interrupt, IRQF_SHARED,
289 driver->write_irq_name, data); 289 driver->write_irq_name, data);
290 return err; 290 return err;
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index 9a8e1b64c22e..5f56d11b886f 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -168,7 +168,7 @@ int port_connection(int fd, int *socket, int *pid_out)
168{ 168{
169 int new, err; 169 int new, err;
170 char *argv[] = { "/usr/sbin/in.telnetd", "-L", 170 char *argv[] = { "/usr/sbin/in.telnetd", "-L",
171 "/usr/lib/uml/port-helper", NULL }; 171 OS_LIB_PATH "/uml/port-helper", NULL };
172 struct port_pre_exec_data data; 172 struct port_pre_exec_data data;
173 173
174 new = accept(fd, NULL, 0); 174 new = accept(fd, NULL, 0);
diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index 10d8d20eb9ec..046fa9ea0ccc 100644
--- a/arch/um/drivers/vector_kern.c
+++ b/arch/um/drivers/vector_kern.c
@@ -1118,16 +1118,11 @@ static int vector_net_close(struct net_device *dev)
1118 os_close_file(vp->fds->tx_fd); 1118 os_close_file(vp->fds->tx_fd);
1119 vp->fds->tx_fd = -1; 1119 vp->fds->tx_fd = -1;
1120 } 1120 }
1121 if (vp->bpf != NULL) 1121 kfree(vp->bpf);
1122 kfree(vp->bpf); 1122 kfree(vp->fds->remote_addr);
1123 if (vp->fds->remote_addr != NULL) 1123 kfree(vp->transport_data);
1124 kfree(vp->fds->remote_addr); 1124 kfree(vp->header_rxbuffer);
1125 if (vp->transport_data != NULL) 1125 kfree(vp->header_txbuffer);
1126 kfree(vp->transport_data);
1127 if (vp->header_rxbuffer != NULL)
1128 kfree(vp->header_rxbuffer);
1129 if (vp->header_txbuffer != NULL)
1130 kfree(vp->header_txbuffer);
1131 if (vp->rx_queue != NULL) 1126 if (vp->rx_queue != NULL)
1132 destroy_queue(vp->rx_queue); 1127 destroy_queue(vp->rx_queue);
1133 if (vp->tx_queue != NULL) 1128 if (vp->tx_queue != NULL)
diff --git a/arch/um/drivers/vector_user.c b/arch/um/drivers/vector_user.c
index 4d6a78e31089..3d8cdbdb4e66 100644
--- a/arch/um/drivers/vector_user.c
+++ b/arch/um/drivers/vector_user.c
@@ -267,8 +267,7 @@ cleanup:
267 os_close_file(rxfd); 267 os_close_file(rxfd);
268 if (txfd >= 0) 268 if (txfd >= 0)
269 os_close_file(txfd); 269 os_close_file(txfd);
270 if (result != NULL) 270 kfree(result);
271 kfree(result);
272 return NULL; 271 return NULL;
273} 272}
274 273
@@ -434,8 +433,7 @@ cleanup:
434 if (fd >= 0) 433 if (fd >= 0)
435 os_close_file(fd); 434 os_close_file(fd);
436 if (result != NULL) { 435 if (result != NULL) {
437 if (result->remote_addr != NULL) 436 kfree(result->remote_addr);
438 kfree(result->remote_addr);
439 kfree(result); 437 kfree(result);
440 } 438 }
441 return NULL; 439 return NULL;
diff --git a/arch/um/include/shared/aio.h b/arch/um/include/shared/aio.h
deleted file mode 100644
index 423bae9153f8..000000000000
--- a/arch/um/include/shared/aio.h
+++ /dev/null
@@ -1,28 +0,0 @@
1/*
2 * Copyright (C) 2004 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef AIO_H__
7#define AIO_H__
8
9enum aio_type { AIO_READ, AIO_WRITE, AIO_MMAP };
10
11struct aio_thread_reply {
12 void *data;
13 int err;
14};
15
16struct aio_context {
17 int reply_fd;
18 struct aio_context *next;
19};
20
21#define INIT_AIO_CONTEXT { .reply_fd = -1, \
22 .next = NULL }
23
24extern int submit_aio(enum aio_type type, int fd, char *buf, int len,
25 unsigned long long offset, int reply_fd,
26 struct aio_context *aio);
27
28#endif
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 6b7f3827d6e4..8360fa3f676d 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -244,8 +244,7 @@ static void garbage_collect_irq_entries(void)
244 to_free = NULL; 244 to_free = NULL;
245 } 245 }
246 walk = walk->next; 246 walk = walk->next;
247 if (to_free != NULL) 247 kfree(to_free);
248 kfree(to_free);
249 } 248 }
250} 249}
251 250
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index cced82946042..0e8b6158f224 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -19,7 +19,7 @@
19#include <skas.h> 19#include <skas.h>
20 20
21/* 21/*
22 * Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by 22 * Note this is constrained to return 0, -EFAULT, -EACCES, -ENOMEM by
23 * segv(). 23 * segv().
24 */ 24 */
25int handle_page_fault(unsigned long address, unsigned long ip, 25int handle_page_fault(unsigned long address, unsigned long ip,
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index ada473bf6f46..455b500afe97 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -6,18 +6,14 @@
6# Don't instrument UML-specific code 6# Don't instrument UML-specific code
7KCOV_INSTRUMENT := n 7KCOV_INSTRUMENT := n
8 8
9obj-y = aio.o execvp.o file.o helper.o irq.o main.o mem.o process.o \ 9obj-y = execvp.o file.o helper.o irq.o main.o mem.o process.o \
10 registers.o sigio.o signal.o start_up.o time.o tty.o \ 10 registers.o sigio.o signal.o start_up.o time.o tty.o \
11 umid.o user_syms.o util.o drivers/ skas/ 11 umid.o user_syms.o util.o drivers/ skas/
12 12
13obj-$(CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA) += elf_aux.o 13obj-$(CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA) += elf_aux.o
14 14
15USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \ 15USER_OBJS := $(user-objs-y) elf_aux.o execvp.o file.o helper.o irq.o \
16 main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \ 16 main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \
17 tty.o umid.o util.o 17 tty.o umid.o util.o
18 18
19HAVE_AIO_ABI := $(shell [ -r /usr/include/linux/aio_abi.h ] && \
20 echo -DHAVE_AIO_ABI )
21CFLAGS_aio.o += $(HAVE_AIO_ABI)
22
23include arch/um/scripts/Makefile.rules 19include arch/um/scripts/Makefile.rules
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
deleted file mode 100644
index 014eb35fd13b..000000000000
--- a/arch/um/os-Linux/aio.c
+++ /dev/null
@@ -1,390 +0,0 @@
1/*
2 * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL
4 */
5
6#include <unistd.h>
7#include <sched.h>
8#include <signal.h>
9#include <errno.h>
10#include <sys/time.h>
11#include <asm/unistd.h>
12#include <aio.h>
13#include <init.h>
14#include <kern_util.h>
15#include <os.h>
16
17struct aio_thread_req {
18 enum aio_type type;
19 int io_fd;
20 unsigned long long offset;
21 char *buf;
22 int len;
23 struct aio_context *aio;
24};
25
26#if defined(HAVE_AIO_ABI)
27#include <linux/aio_abi.h>
28
29/*
30 * If we have the headers, we are going to build with AIO enabled.
31 * If we don't have aio in libc, we define the necessary stubs here.
32 */
33
34#if !defined(HAVE_AIO_LIBC)
35
36static long io_setup(int n, aio_context_t *ctxp)
37{
38 return syscall(__NR_io_setup, n, ctxp);
39}
40
41static long io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp)
42{
43 return syscall(__NR_io_submit, ctx, nr, iocbpp);
44}
45
46static long io_getevents(aio_context_t ctx_id, long min_nr, long nr,
47 struct io_event *events, struct timespec *timeout)
48{
49 return syscall(__NR_io_getevents, ctx_id, min_nr, nr, events, timeout);
50}
51
52#endif
53
54/*
55 * The AIO_MMAP cases force the mmapped page into memory here
56 * rather than in whatever place first touches the data. I used
57 * to do this by touching the page, but that's delicate because
58 * gcc is prone to optimizing that away. So, what's done here
59 * is we read from the descriptor from which the page was
60 * mapped. The caller is required to pass an offset which is
61 * inside the page that was mapped. Thus, when the read
62 * returns, we know that the page is in the page cache, and
63 * that it now backs the mmapped area.
64 */
65
66static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf,
67 int len, unsigned long long offset, struct aio_context *aio)
68{
69 struct iocb *iocbp = & ((struct iocb) {
70 .aio_data = (unsigned long) aio,
71 .aio_fildes = fd,
72 .aio_buf = (unsigned long) buf,
73 .aio_nbytes = len,
74 .aio_offset = offset
75 });
76 char c;
77
78 switch (type) {
79 case AIO_READ:
80 iocbp->aio_lio_opcode = IOCB_CMD_PREAD;
81 break;
82 case AIO_WRITE:
83 iocbp->aio_lio_opcode = IOCB_CMD_PWRITE;
84 break;
85 case AIO_MMAP:
86 iocbp->aio_lio_opcode = IOCB_CMD_PREAD;
87 iocbp->aio_buf = (unsigned long) &c;
88 iocbp->aio_nbytes = sizeof(c);
89 break;
90 default:
91 printk(UM_KERN_ERR "Bogus op in do_aio - %d\n", type);
92 return -EINVAL;
93 }
94
95 return (io_submit(ctx, 1, &iocbp) > 0) ? 0 : -errno;
96}
97
98/* Initialized in an initcall and unchanged thereafter */
99static aio_context_t ctx = 0;
100
101static int aio_thread(void *arg)
102{
103 struct aio_thread_reply reply;
104 struct io_event event;
105 int err, n, reply_fd;
106
107 os_fix_helper_signals();
108 while (1) {
109 n = io_getevents(ctx, 1, 1, &event, NULL);
110 if (n < 0) {
111 if (errno == EINTR)
112 continue;
113 printk(UM_KERN_ERR "aio_thread - io_getevents failed, "
114 "errno = %d\n", errno);
115 }
116 else {
117 reply = ((struct aio_thread_reply)
118 { .data = (void *) (long) event.data,
119 .err = event.res });
120 reply_fd = ((struct aio_context *) reply.data)->reply_fd;
121 err = write(reply_fd, &reply, sizeof(reply));
122 if (err != sizeof(reply))
123 printk(UM_KERN_ERR "aio_thread - write failed, "
124 "fd = %d, err = %d\n", reply_fd, errno);
125 }
126 }
127 return 0;
128}
129
130#endif
131
132static int do_not_aio(struct aio_thread_req *req)
133{
134 char c;
135 unsigned long long actual;
136 int n;
137
138 actual = lseek64(req->io_fd, req->offset, SEEK_SET);
139 if (actual != req->offset)
140 return -errno;
141
142 switch (req->type) {
143 case AIO_READ:
144 n = read(req->io_fd, req->buf, req->len);
145 break;
146 case AIO_WRITE:
147 n = write(req->io_fd, req->buf, req->len);
148 break;
149 case AIO_MMAP:
150 n = read(req->io_fd, &c, sizeof(c));
151 break;
152 default:
153 printk(UM_KERN_ERR "do_not_aio - bad request type : %d\n",
154 req->type);
155 return -EINVAL;
156 }
157
158 if (n < 0)
159 return -errno;
160 return 0;
161}
162
163/* These are initialized in initcalls and not changed */
164static int aio_req_fd_r = -1;
165static int aio_req_fd_w = -1;
166static int aio_pid = -1;
167static unsigned long aio_stack;
168
169static int not_aio_thread(void *arg)
170{
171 struct aio_thread_req req;
172 struct aio_thread_reply reply;
173 int err;
174
175 os_fix_helper_signals();
176 while (1) {
177 err = read(aio_req_fd_r, &req, sizeof(req));
178 if (err != sizeof(req)) {
179 if (err < 0)
180 printk(UM_KERN_ERR "not_aio_thread - "
181 "read failed, fd = %d, err = %d\n",
182 aio_req_fd_r,
183 errno);
184 else {
185 printk(UM_KERN_ERR "not_aio_thread - short "
186 "read, fd = %d, length = %d\n",
187 aio_req_fd_r, err);
188 }
189 continue;
190 }
191 err = do_not_aio(&req);
192 reply = ((struct aio_thread_reply) { .data = req.aio,
193 .err = err });
194 err = write(req.aio->reply_fd, &reply, sizeof(reply));
195 if (err != sizeof(reply))
196 printk(UM_KERN_ERR "not_aio_thread - write failed, "
197 "fd = %d, err = %d\n", req.aio->reply_fd, errno);
198 }
199
200 return 0;
201}
202
203static int init_aio_24(void)
204{
205 int fds[2], err;
206
207 err = os_pipe(fds, 1, 1);
208 if (err)
209 goto out;
210
211 aio_req_fd_w = fds[0];
212 aio_req_fd_r = fds[1];
213
214 err = os_set_fd_block(aio_req_fd_w, 0);
215 if (err)
216 goto out_close_pipe;
217
218 err = run_helper_thread(not_aio_thread, NULL,
219 CLONE_FILES | CLONE_VM, &aio_stack);
220 if (err < 0)
221 goto out_close_pipe;
222
223 aio_pid = err;
224 goto out;
225
226out_close_pipe:
227 close(fds[0]);
228 close(fds[1]);
229 aio_req_fd_w = -1;
230 aio_req_fd_r = -1;
231out:
232#ifndef HAVE_AIO_ABI
233 printk(UM_KERN_INFO "/usr/include/linux/aio_abi.h not present during "
234 "build\n");
235#endif
236 printk(UM_KERN_INFO "2.6 host AIO support not used - falling back to "
237 "I/O thread\n");
238 return 0;
239}
240
241#ifdef HAVE_AIO_ABI
242#define DEFAULT_24_AIO 0
243static int init_aio_26(void)
244{
245 int err;
246
247 if (io_setup(256, &ctx)) {
248 err = -errno;
249 printk(UM_KERN_ERR "aio_thread failed to initialize context, "
250 "err = %d\n", errno);
251 return err;
252 }
253
254 err = run_helper_thread(aio_thread, NULL,
255 CLONE_FILES | CLONE_VM, &aio_stack);
256 if (err < 0)
257 return err;
258
259 aio_pid = err;
260
261 printk(UM_KERN_INFO "Using 2.6 host AIO\n");
262 return 0;
263}
264
265static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
266 unsigned long long offset, struct aio_context *aio)
267{
268 struct aio_thread_reply reply;
269 int err;
270
271 err = do_aio(ctx, type, io_fd, buf, len, offset, aio);
272 if (err) {
273 reply = ((struct aio_thread_reply) { .data = aio,
274 .err = err });
275 err = write(aio->reply_fd, &reply, sizeof(reply));
276 if (err != sizeof(reply)) {
277 err = -errno;
278 printk(UM_KERN_ERR "submit_aio_26 - write failed, "
279 "fd = %d, err = %d\n", aio->reply_fd, -err);
280 }
281 else err = 0;
282 }
283
284 return err;
285}
286
287#else
288#define DEFAULT_24_AIO 1
289static int init_aio_26(void)
290{
291 return -ENOSYS;
292}
293
294static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
295 unsigned long long offset, struct aio_context *aio)
296{
297 return -ENOSYS;
298}
299#endif
300
301/* Initialized in an initcall and unchanged thereafter */
302static int aio_24 = DEFAULT_24_AIO;
303
304static int __init set_aio_24(char *name, int *add)
305{
306 aio_24 = 1;
307 return 0;
308}
309
310__uml_setup("aio=2.4", set_aio_24,
311"aio=2.4\n"
312" This is used to force UML to use 2.4-style AIO even when 2.6 AIO is\n"
313" available. 2.4 AIO is a single thread that handles one request at a\n"
314" time, synchronously. 2.6 AIO is a thread which uses the 2.6 AIO \n"
315" interface to handle an arbitrary number of pending requests. 2.6 AIO \n"
316" is not available in tt mode, on 2.4 hosts, or when UML is built with\n"
317" /usr/include/linux/aio_abi.h not available. Many distributions don't\n"
318" include aio_abi.h, so you will need to copy it from a kernel tree to\n"
319" your /usr/include/linux in order to build an AIO-capable UML\n\n"
320);
321
322static int init_aio(void)
323{
324 int err;
325
326 if (!aio_24) {
327 err = init_aio_26();
328 if (err && (errno == ENOSYS)) {
329 printk(UM_KERN_INFO "2.6 AIO not supported on the "
330 "host - reverting to 2.4 AIO\n");
331 aio_24 = 1;
332 }
333 else return err;
334 }
335
336 if (aio_24)
337 return init_aio_24();
338
339 return 0;
340}
341
342/*
343 * The reason for the __initcall/__uml_exitcall asymmetry is that init_aio
344 * needs to be called when the kernel is running because it calls run_helper,
345 * which needs get_free_page. exit_aio is a __uml_exitcall because the generic
346 * kernel does not run __exitcalls on shutdown, and can't because many of them
347 * break when called outside of module unloading.
348 */
349__initcall(init_aio);
350
351static void exit_aio(void)
352{
353 if (aio_pid != -1) {
354 os_kill_process(aio_pid, 1);
355 free_stack(aio_stack, 0);
356 }
357}
358
359__uml_exitcall(exit_aio);
360
361static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len,
362 unsigned long long offset, struct aio_context *aio)
363{
364 struct aio_thread_req req = { .type = type,
365 .io_fd = io_fd,
366 .offset = offset,
367 .buf = buf,
368 .len = len,
369 .aio = aio,
370 };
371 int err;
372
373 err = write(aio_req_fd_w, &req, sizeof(req));
374 if (err == sizeof(req))
375 err = 0;
376 else err = -errno;
377
378 return err;
379}
380
381int submit_aio(enum aio_type type, int io_fd, char *buf, int len,
382 unsigned long long offset, int reply_fd,
383 struct aio_context *aio)
384{
385 aio->reply_fd = reply_fd;
386 if (aio_24)
387 return submit_aio_24(type, io_fd, buf, len, offset, aio);
388 else
389 return submit_aio_26(type, io_fd, buf, len, offset, aio);
390}
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index c94c3bd70ccd..df4a985716eb 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -610,6 +610,11 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
610 fatal_sigsegv(); 610 fatal_sigsegv();
611 } 611 }
612 longjmp(*switch_buf, 1); 612 longjmp(*switch_buf, 1);
613
614 /* unreachable */
615 printk(UM_KERN_ERR "impossible long jump!");
616 fatal_sigsegv();
617 return 0;
613} 618}
614 619
615void initial_thread_cb_skas(void (*proc)(void *), void *arg) 620void initial_thread_cb_skas(void (*proc)(void *), void *arg)
diff --git a/arch/x86/um/shared/sysdep/ptrace_32.h b/arch/x86/um/shared/sysdep/ptrace_32.h
index b94a108de1dc..db8478a83a09 100644
--- a/arch/x86/um/shared/sysdep/ptrace_32.h
+++ b/arch/x86/um/shared/sysdep/ptrace_32.h
@@ -8,22 +8,10 @@
8 8
9#define MAX_FP_NR HOST_FPX_SIZE 9#define MAX_FP_NR HOST_FPX_SIZE
10 10
11static inline void update_debugregs(int seq) {}
12
13/* syscall emulation path in ptrace */
14
15#ifndef PTRACE_SYSEMU
16#define PTRACE_SYSEMU 31
17#endif
18
19void set_using_sysemu(int value); 11void set_using_sysemu(int value);
20int get_using_sysemu(void); 12int get_using_sysemu(void);
21extern int sysemu_supported; 13extern int sysemu_supported;
22 14
23#ifndef PTRACE_SYSEMU_SINGLESTEP
24#define PTRACE_SYSEMU_SINGLESTEP 32
25#endif
26
27#define UPT_SYSCALL_ARG1(r) UPT_BX(r) 15#define UPT_SYSCALL_ARG1(r) UPT_BX(r)
28#define UPT_SYSCALL_ARG2(r) UPT_CX(r) 16#define UPT_SYSCALL_ARG2(r) UPT_CX(r)
29#define UPT_SYSCALL_ARG3(r) UPT_DX(r) 17#define UPT_SYSCALL_ARG3(r) UPT_DX(r)