aboutsummaryrefslogtreecommitdiff
path: root/arch/um
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/drivers/mconsole_kern.c3
-rw-r--r--arch/um/drivers/ubd_kern.c76
-rw-r--r--arch/um/include/irq_user.h15
-rw-r--r--arch/um/include/kern.h2
-rw-r--r--arch/um/include/misc_constants.h6
-rw-r--r--arch/um/include/os.h36
-rw-r--r--arch/um/include/sigio.h3
-rw-r--r--arch/um/include/skas/mode-skas.h1
-rw-r--r--arch/um/include/skas/skas.h1
-rw-r--r--arch/um/include/user_util.h1
-rw-r--r--arch/um/kernel/Makefile9
-rw-r--r--arch/um/kernel/exec_kern.c2
-rw-r--r--arch/um/kernel/irq.c294
-rw-r--r--arch/um/kernel/irq_user.c412
-rw-r--r--arch/um/kernel/physmem.c3
-rw-r--r--arch/um/kernel/sigio_kern.c10
-rw-r--r--arch/um/kernel/smp.c14
-rw-r--r--arch/um/kernel/um_arch.c12
-rw-r--r--arch/um/os-Linux/Makefile13
-rw-r--r--arch/um/os-Linux/irq.c162
-rw-r--r--arch/um/os-Linux/sigio.c (renamed from arch/um/kernel/sigio_user.c)233
-rw-r--r--arch/um/os-Linux/start_up.c128
-rw-r--r--arch/um/os-Linux/tt.c10
-rw-r--r--arch/um/os-Linux/tty_log.c (renamed from arch/um/kernel/tty_log.c)18
-rw-r--r--arch/um/os-Linux/umid.c33
-rw-r--r--arch/um/sys-i386/ptrace.c15
-rw-r--r--arch/um/sys-i386/signal.c59
-rw-r--r--arch/um/sys-i386/user-offsets.c10
-rw-r--r--arch/um/sys-x86_64/ptrace.c22
-rw-r--r--arch/um/sys-x86_64/signal.c56
-rw-r--r--arch/um/sys-x86_64/user-offsets.c6
31 files changed, 930 insertions, 735 deletions
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 54388d10bcf..1488816588e 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -762,7 +762,8 @@ static struct notifier_block panic_exit_notifier = {
static int add_notifier(void)
{
- notifier_chain_register(&panic_notifier_list, &panic_exit_notifier);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &panic_exit_notifier);
return(0);
}
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index fa617e0719a..0336575d244 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -71,7 +71,7 @@ struct io_thread_req {
int error;
};
-extern int open_ubd_file(char *file, struct openflags *openflags,
+extern int open_ubd_file(char *file, struct openflags *openflags, int shared,
char **backing_file_out, int *bitmap_offset_out,
unsigned long *bitmap_len_out, int *data_offset_out,
int *create_cow_out);
@@ -137,7 +137,7 @@ static int fake_major = MAJOR_NR;
static struct gendisk *ubd_gendisk[MAX_DEV];
static struct gendisk *fake_gendisk[MAX_DEV];
-
+
#ifdef CONFIG_BLK_DEV_UBD_SYNC
#define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 1, .c = 0, \
.cl = 1 })
@@ -168,6 +168,7 @@ struct ubd {
__u64 size;
struct openflags boot_openflags;
struct openflags openflags;
+ int shared;
int no_cow;
struct cow cow;
struct platform_device pdev;
@@ -189,6 +190,7 @@ struct ubd {
.boot_openflags = OPEN_FLAGS, \
.openflags = OPEN_FLAGS, \
.no_cow = 0, \
+ .shared = 0, \
.cow = DEFAULT_COW, \
}
@@ -305,7 +307,7 @@ static int ubd_setup_common(char *str, int *index_out)
}
major = simple_strtoul(str, &end, 0);
if((*end != '\0') || (end == str)){
- printk(KERN_ERR
+ printk(KERN_ERR
"ubd_setup : didn't parse major number\n");
return(1);
}
@@ -316,7 +318,7 @@ static int ubd_setup_common(char *str, int *index_out)
printk(KERN_ERR "Can't assign a fake major twice\n");
goto out1;
}
-
+
fake_major = major;
printk(KERN_INFO "Setting extra ubd major number to %d\n",
@@ -351,7 +353,7 @@ static int ubd_setup_common(char *str, int *index_out)
if (index_out)
*index_out = n;
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < sizeof("rscd="); i++) {
switch (*str) {
case 'r':
flags.w = 0;
@@ -362,11 +364,14 @@ static int ubd_setup_common(char *str, int *index_out)
case 'd':
dev->no_cow = 1;
break;
+ case 'c':
+ dev->shared = 1;
+ break;
case '=':
str++;
goto break_loop;
default:
- printk(KERN_ERR "ubd_setup : Expected '=' or flag letter (r,s or d)\n");
+ printk(KERN_ERR "ubd_setup : Expected '=' or flag letter (r, s, c, or d)\n");
goto out;
}
str++;
@@ -515,7 +520,7 @@ static void ubd_handler(void)
spin_unlock(&ubd_io_lock);
return;
}
-
+
ubd_finish(rq, req.error);
reactivate_fd(thread_fd, UBD_IRQ);
do_ubd_request(ubd_queue);
@@ -532,7 +537,7 @@ static int io_pid = -1;
void kill_io_thread(void)
{
- if(io_pid != -1)
+ if(io_pid != -1)
os_kill_process(io_pid, 1);
}
@@ -567,14 +572,15 @@ static int ubd_open_dev(struct ubd *dev)
create_cow = 0;
create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL;
back_ptr = dev->no_cow ? NULL : &dev->cow.file;
- dev->fd = open_ubd_file(dev->file, &dev->openflags, back_ptr,
- &dev->cow.bitmap_offset, &dev->cow.bitmap_len,
- &dev->cow.data_offset, create_ptr);
+ dev->fd = open_ubd_file(dev->file, &dev->openflags, dev->shared,
+ back_ptr, &dev->cow.bitmap_offset,
+ &dev->cow.bitmap_len, &dev->cow.data_offset,
+ create_ptr);
if((dev->fd == -ENOENT) && create_cow){
- dev->fd = create_cow_file(dev->file, dev->cow.file,
+ dev->fd = create_cow_file(dev->file, dev->cow.file,
dev->openflags, 1 << 9, PAGE_SIZE,
- &dev->cow.bitmap_offset,
+ &dev->cow.bitmap_offset,
&dev->cow.bitmap_len,
&dev->cow.data_offset);
if(dev->fd >= 0){
@@ -598,16 +604,16 @@ static int ubd_open_dev(struct ubd *dev)
}
flush_tlb_kernel_vm();
- err = read_cow_bitmap(dev->fd, dev->cow.bitmap,
- dev->cow.bitmap_offset,
+ err = read_cow_bitmap(dev->fd, dev->cow.bitmap,
+ dev->cow.bitmap_offset,
dev->cow.bitmap_len);
if(err < 0)
goto error;
flags = dev->openflags;
flags.w = 0;
- err = open_ubd_file(dev->cow.file, &flags, NULL, NULL, NULL,
- NULL, NULL);
+ err = open_ubd_file(dev->cow.file, &flags, dev->shared, NULL,
+ NULL, NULL, NULL, NULL);
if(err < 0) goto error;
dev->cow.fd = err;
}
@@ -685,11 +691,11 @@ static int ubd_add(int n)
dev->size = ROUND_BLOCK(dev->size);
err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]);
- if(err)
+ if(err)
goto out_close;
-
+
if(fake_major != MAJOR_NR)
- ubd_new_disk(fake_major, dev->size, n,
+ ubd_new_disk(fake_major, dev->size, n,
&fake_gendisk[n]);
/* perhaps this should also be under the "if (fake_major)" above */
@@ -854,7 +860,7 @@ int ubd_init(void)
return -1;
}
platform_driver_register(&ubd_driver);
- for (i = 0; i < MAX_DEV; i++)
+ for (i = 0; i < MAX_DEV; i++)
ubd_add(i);
return 0;
}
@@ -872,16 +878,16 @@ int ubd_driver_init(void){
* enough. So use anyway the io thread. */
}
stack = alloc_stack(0, 0);
- io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *),
+ io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *),
&thread_fd);
if(io_pid < 0){
- printk(KERN_ERR
+ printk(KERN_ERR
"ubd : Failed to start I/O thread (errno = %d) - "
"falling back to synchronous I/O\n", -io_pid);
io_pid = -1;
return(0);
}
- err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr,
+ err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr,
SA_INTERRUPT, "ubd", ubd_dev);
if(err != 0)
printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
@@ -978,7 +984,7 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
if(req->op == UBD_READ) {
for(i = 0; i < req->length >> 9; i++){
if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
- ubd_set_bit(i, (unsigned char *)
+ ubd_set_bit(i, (unsigned char *)
&req->sector_mask);
}
}
@@ -999,7 +1005,7 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
/* This should be impossible now */
if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
- printk("Write attempted on readonly ubd device %s\n",
+ printk("Write attempted on readonly ubd device %s\n",
disk->disk_name);
end_request(req, 0);
return(1);
@@ -1182,7 +1188,7 @@ int read_cow_bitmap(int fd, void *buf, int offset, int len)
return(0);
}
-int open_ubd_file(char *file, struct openflags *openflags,
+int open_ubd_file(char *file, struct openflags *openflags, int shared,
char **backing_file_out, int *bitmap_offset_out,
unsigned long *bitmap_len_out, int *data_offset_out,
int *create_cow_out)
@@ -1206,10 +1212,14 @@ int open_ubd_file(char *file, struct openflags *openflags,
return fd;
}
- err = os_lock_file(fd, openflags->w);
- if(err < 0){
- printk("Failed to lock '%s', err = %d\n", file, -err);
- goto out_close;
+ if(shared)
+ printk("Not locking \"%s\" on the host\n", file);
+ else {
+ err = os_lock_file(fd, openflags->w);
+ if(err < 0){
+ printk("Failed to lock '%s', err = %d\n", file, -err);
+ goto out_close;
+ }
}
/* Succesful return case! */
@@ -1260,7 +1270,7 @@ int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
int err, fd;
flags.c = 1;
- fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL);
+ fd = open_ubd_file(cow_file, &flags, 0, NULL, NULL, NULL, NULL, NULL);
if(fd < 0){
err = fd;
printk("Open of COW file '%s' failed, errno = %d\n", cow_file,
diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h
index b61deb8b362..69a93c804f0 100644
--- a/arch/um/include/irq_user.h
+++ b/arch/um/include/irq_user.h
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -6,6 +6,17 @@
#ifndef __IRQ_USER_H__
#define __IRQ_USER_H__
+struct irq_fd {
+ struct irq_fd *next;
+ void *id;
+ int fd;
+ int type;
+ int irq;
+ int pid;
+ int events;
+ int current_events;
+};
+
enum { IRQ_READ, IRQ_WRITE };
extern void sigio_handler(int sig, union uml_pt_regs *regs);
@@ -16,8 +27,6 @@ extern void reactivate_fd(int fd, int irqnum);
extern void deactivate_fd(int fd, int irqnum);
extern int deactivate_all_fds(void);
extern void forward_interrupts(int pid);
-extern void init_irq_signals(int on_sigstack);
-extern void forward_ipi(int fd, int pid);
extern int activate_ipi(int fd, int pid);
extern unsigned long irq_lock(void);
extern void irq_unlock(unsigned long flags);
diff --git a/arch/um/include/kern.h b/arch/um/include/kern.h
index 7d223beccbc..4ce3fc650e5 100644
--- a/arch/um/include/kern.h
+++ b/arch/um/include/kern.h
@@ -29,7 +29,7 @@ extern int getuid(void);
extern int getgid(void);
extern int pause(void);
extern int write(int, const void *, int);
-extern int exit(int);
+extern void exit(int);
extern int close(int);
extern int read(unsigned int, char *, int);
extern int pipe(int *);
diff --git a/arch/um/include/misc_constants.h b/arch/um/include/misc_constants.h
new file mode 100644
index 00000000000..989bc08de36
--- /dev/null
+++ b/arch/um/include/misc_constants.h
@@ -0,0 +1,6 @@
+#ifndef __MISC_CONSTANT_H_
+#define __MISC_CONSTANT_H_
+
+#include <user_constants.h>
+
+#endif
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 2a1c64d8d0b..d3d1bc6074e 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -12,6 +12,7 @@
#include "sysdep/ptrace.h"
#include "kern_util.h"
#include "skas/mm_id.h"
+#include "irq_user.h"
#define OS_TYPE_FILE 1
#define OS_TYPE_DIR 2
@@ -121,6 +122,7 @@ static inline struct openflags of_cloexec(struct openflags flags)
return(flags);
}
+/* file.c */
extern int os_stat_file(const char *file_name, struct uml_stat *buf);
extern int os_stat_fd(const int fd, struct uml_stat *buf);
extern int os_access(const char *file, int mode);
@@ -156,10 +158,20 @@ extern int os_connect_socket(char *name);
extern int os_file_type(char *file);
extern int os_file_mode(char *file, struct openflags *mode_out);
extern int os_lock_file(int fd, int excl);
+extern void os_flush_stdout(void);
+extern int os_stat_filesystem(char *path, long *bsize_out,
+ long long *blocks_out, long long *bfree_out,
+ long long *bavail_out, long long *files_out,
+ long long *ffree_out, void *fsid_out,
+ int fsid_size, long *namelen_out,
+ long *spare_out);
+extern int os_change_dir(char *dir);
+extern int os_fchange_dir(int fd);
/* start_up.c */
extern void os_early_checks(void);
extern int can_do_skas(void);
+extern void os_check_bugs(void);
/* Make sure they are clear when running in TT mode. Required by
* SEGV_MAYBE_FIXABLE */
@@ -198,6 +210,8 @@ extern void os_flush_stdout(void);
/* tt.c
* for tt mode only (will be deleted in future...)
*/
+extern void forward_ipi(int fd, int pid);
+extern void kill_child_dead(int pid);
extern void stop(void);
extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
extern int protect_memory(unsigned long addr, unsigned long len,
@@ -294,4 +308,26 @@ extern void initial_thread_cb_skas(void (*proc)(void *),
extern void halt_skas(void);
extern void reboot_skas(void);
+/* irq.c */
+extern int os_waiting_for_events(struct irq_fd *active_fds);
+extern int os_isatty(int fd);
+extern int os_create_pollfd(int fd, int events, void *tmp_pfd, int size_tmpfds);
+extern void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg,
+ struct irq_fd *active_fds, struct irq_fd ***last_irq_ptr2);
+extern void os_free_irq_later(struct irq_fd *active_fds,
+ int irq, void *dev_id);
+extern int os_get_pollfd(int i);
+extern void os_set_pollfd(int i, int fd);
+extern void os_set_ioignore(void);
+extern void init_irq_signals(int on_sigstack);
+
+/* sigio.c */
+extern void write_sigio_workaround(void);
+extern int add_sigio_fd(int fd, int read);
+extern int ignore_sigio_fd(int fd);
+
+/* skas/trap */
+extern void sig_handler_common_skas(int sig, void *sc_ptr);
+extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
+
#endif
diff --git a/arch/um/include/sigio.h b/arch/um/include/sigio.h
index 37d76e29a14..fe99ea163c2 100644
--- a/arch/um/include/sigio.h
+++ b/arch/um/include/sigio.h
@@ -8,9 +8,6 @@
extern int write_sigio_irq(int fd);
extern int register_sigio_fd(int fd);
-extern int read_sigio_fd(int fd);
-extern int add_sigio_fd(int fd, int read);
-extern int ignore_sigio_fd(int fd);
extern void sigio_lock(void);
extern void sigio_unlock(void);
diff --git a/arch/um/include/skas/mode-skas.h b/arch/um/include/skas/mode-skas.h
index 260065cfeef..8bc6916bbbb 100644
--- a/arch/um/include/skas/mode-skas.h
+++ b/arch/um/include/skas/mode-skas.h
@@ -13,7 +13,6 @@ extern unsigned long exec_fp_regs[];
extern unsigned long exec_fpx_regs[];
extern int have_fpx_regs;
-extern void sig_handler_common_skas(int sig, void *sc_ptr);
extern void kill_off_processes_skas(void);
#endif
diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h
index 86357282d68..853b26f148c 100644
--- a/arch/um/include/skas/skas.h
+++ b/arch/um/include/skas/skas.h
@@ -17,7 +17,6 @@ extern int user_thread(unsigned long stack, int flags);
extern void new_thread_proc(void *stack, void (*handler)(int sig));
extern void new_thread_handler(int sig);
extern void handle_syscall(union uml_pt_regs *regs);
-extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
extern int new_mm(unsigned long stack);
extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
extern long execute_syscall_skas(void *r);
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index a6f1f176cf8..992a7e1e0fc 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -58,7 +58,6 @@ extern int attach(int pid);
extern void kill_child_dead(int pid);
extern int cont(int pid);
extern void check_sigio(void);
-extern void write_sigio_workaround(void);
extern void arch_check_bugs(void);
extern int cpu_feature(char *what, char *buf, int len);
extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 693018ba80f..fe08971b64c 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -7,23 +7,20 @@ extra-y := vmlinux.lds
clean-files :=
obj-y = config.o exec_kern.o exitcode.o \
- init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \
- process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \
+ init_task.o irq.o ksyms.o mem.o physmem.o \
+ process_kern.o ptrace.o reboot.o resource.o sigio_kern.o \
signal_kern.o smp.o syscall_kern.o sysrq.o \
time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o
obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
obj-$(CONFIG_GPROF) += gprof_syms.o
obj-$(CONFIG_GCOV) += gmon_syms.o
-obj-$(CONFIG_TTY_LOG) += tty_log.o
obj-$(CONFIG_SYSCALL_DEBUG) += syscall.o
obj-$(CONFIG_MODE_TT) += tt/
obj-$(CONFIG_MODE_SKAS) += skas/
-user-objs-$(CONFIG_TTY_LOG) += tty_log.o
-
-USER_OBJS := $(user-objs-y) config.o tty_log.o
+USER_OBJS := config.o
include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c
index c264e1c05ab..1ca84319317 100644
--- a/arch/um/kernel/exec_kern.c
+++ b/arch/um/kernel/exec_kern.c
@@ -30,8 +30,6 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp);
}
-extern void log_exec(char **argv, void *tty);
-
static long execve1(char *file, char __user * __user *argv,
char __user *__user *env)
{
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index bbf94bf2921..c39ea3abeda 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -31,6 +31,8 @@
#include "irq_user.h"
#include "irq_kern.h"
#include "os.h"
+#include "sigio.h"
+#include "misc_constants.h"
/*
* Generic, controller-independent functions:
@@ -77,6 +79,298 @@ skip:
return 0;
}
+struct irq_fd *active_fds = NULL;
+static struct irq_fd **last_irq_ptr = &active_fds;
+
+extern void free_irqs(void);
+
+void sigio_handler(int sig, union uml_pt_regs *regs)
+{
+ struct irq_fd *irq_fd;
+ int n;
+
+ if(smp_sigio_handler()) return;
+ while(1){
+ n = os_waiting_for_events(active_fds);
+ if (n <= 0) {
+ if(n == -EINTR) continue;
+ else break;
+ }
+
+ for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
+ if(irq_fd->current_events != 0){
+ irq_fd->current_events = 0;
+ do_IRQ(irq_fd->irq, regs);
+ }
+ }
+ }
+
+ free_irqs();
+}
+
+static void maybe_sigio_broken(int fd, int type)
+{
+ if(os_isatty(fd)){
+ if((type == IRQ_WRITE) && !pty_output_sigio){
+ write_sigio_workaround();
+ add_sigio_fd(fd, 0);
+ }
+ else if((type == IRQ_READ) && !pty_close_sigio){
+ write_sigio_workaround();
+ add_sigio_fd(fd, 1);
+ }
+ }
+}
+
+
+int activate_fd(int irq, int fd, int type, void *dev_id)
+{
+ struct pollfd *tmp_pfd;
+ struct irq_fd *new_fd, *irq_fd;
+ unsigned long flags;
+ int pid, events, err, n;
+
+ pid = os_getpid();
+ err = os_set_fd_async(fd, pid);
+ if(err < 0)
+ goto out;
+
+ new_fd = um_kmalloc(sizeof(*new_fd));
+ err = -ENOMEM;
+ if(new_fd == NULL)
+ goto out;
+
+ if(type == IRQ_READ) events = UM_POLLIN | UM_POLLPRI;
+ else events = UM_POLLOUT;
+ *new_fd = ((struct irq_fd) { .next = NULL,
+ .id = dev_id,
+ .fd = fd,
+ .type = type,
+ .irq = irq,
+ .pid = pid,
+ .events = events,
+ .current_events = 0 } );
+
+ /* Critical section - locked by a spinlock because this stuff can
+ * be changed from interrupt handlers. The stuff above is done
+ * outside the lock because it allocates memory.
+ */
+
+ /* Actually, it only looks like it can be called from interrupt
+ * context. The culprit is reactivate_fd, which calls
+ * maybe_sigio_broken, which calls write_sigio_workaround,
+ * which calls activate_fd. However, write_sigio_workaround should
+ * only be called once, at boot time. That would make it clear that
+ * this is called only from process context, and can be locked with
+ * a semaphore.
+ */
+ flags = irq_lock();
+ for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
+ if((irq_fd->fd == fd) && (irq_fd->type == type)){
+ printk("Registering fd %d twice\n", fd);
+ printk("Irqs : %d, %d\n", irq_fd->irq, irq);
+ printk("Ids : 0x%p, 0x%p\n", irq_fd->id, dev_id);
+ goto out_unlock;
+ }
+ }
+
+ /*-------------*/
+ if(type == IRQ_WRITE)
+ fd = -1;
+
+ tmp_pfd = NULL;
+ n = 0;
+
+ while(1){
+ n = os_create_pollfd(fd, events, tmp_pfd, n);
+ if (n == 0)
+ break;
+
+ /* n > 0
+ * It means we couldn't put new pollfd to current pollfds
+ * and tmp_fds is NULL or too small for new pollfds array.
+ * Needed size is equal to n as minimum.
+ *
+ * Here we have to drop the lock in order to call
+ * kmalloc, which might sleep.
+ * If something else came in and changed the pollfds array
+ * so we will not be able to put new pollfd struct to pollfds
+ * then we free the buffer tmp_fds and try again.
+ */
+ irq_unlock(flags);
+ if (tmp_pfd != NULL) {
+ kfree(tmp_pfd);
+ tmp_pfd = NULL;
+ }
+
+ tmp_pfd = um_kmalloc(n);
+ if (tmp_pfd == NULL)
+ goto out_kfree;
+
+ flags = irq_lock();
+ }
+ /*-------------*/
+
+ *last_irq_ptr = new_fd;
+ last_irq_ptr = &new_fd->next;
+
+ irq_unlock(flags);
+
+ /* This calls activate_fd, so it has to be outside the critical
+ * section.
+ */
+ maybe_sigio_broken(fd, type);
+
+ return(0);
+
+ out_unlock:
+ irq_unlock(flags);
+ out_kfree:
+ kfree(new_fd);
+ out:
+ return(err);
+}
+
+static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
+{
+ unsigned long flags;
+
+ flags = irq_lock();
+ os_free_irq_by_cb(test, arg, active_fds, &last_irq_ptr);
+ irq_unlock(flags);
+}
+
+struct irq_and_dev {
+ int irq;
+ void *dev;
+};
+
+static int same_irq_and_dev(struct irq_fd *irq, void *d)
+{
+ struct irq_and_dev *data = d;
+
+ return((irq->irq == data->irq) && (irq->id == data->dev));
+}
+
+void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
+{
+ struct irq_and_dev data = ((struct irq_and_dev) { .irq = irq,
+ .dev = dev });
+
+ free_irq_by_cb(same_irq_and_dev, &data);
+}
+
+static int same_fd(struct irq_fd *irq, void *fd)
+{
+ return(irq->fd == *((int *) fd));
+}
+
+void free_irq_by_fd(int fd)
+{
+ free_irq_by_cb(same_fd, &fd);
+}
+
+static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
+{
+ struct irq_fd *irq;
+ int i = 0;
+ int fdi;
+
+ for(irq=active_fds; irq != NULL; irq = irq->next){
+ if((irq->fd == fd) && (irq->irq == irqnum)) break;
+ i++;
+ }
+ if(irq == NULL){
+ printk("find_irq_by_fd doesn't have descriptor %d\n", fd);
+ goto out;
+ }
+ fdi = os_get_pollfd(i);
+ if((fdi != -1) && (fdi != fd)){
+ printk("find_irq_by_fd - mismatch between active_fds and "
+ "pollfds, fd %d vs %d, need %d\n", irq->fd,
+ fdi, fd);
+ irq = NULL;
+ goto out;
+ }
+ *index_out = i;
+ out:
+ return(irq);
+}
+
+void reactivate_fd(int fd, int irqnum)
+{
+ struct irq_fd *irq;
+ unsigned long flags;
+ int i;
+
+ flags = irq_lock();
+ irq = find_irq_by_fd(fd, irqnum, &i);
+ if(irq == NULL){
+ irq_unlock(flags);
+ return;
+ }
+ os_set_pollfd(i, irq->fd);
+ irq_unlock(flags);
+
+ /* This calls activate_fd, so it has to be outside the critical
+ * section.
+ */
+ maybe_sigio_broken(fd, irq->type);
+}
+
+void deactivate_fd(int fd, int irqnum)
+{
+ struct irq_fd *irq;
+ unsigned long flags;
+ int i;
+
+ flags = irq_lock();
+ irq = find_irq_by_fd(fd, irqnum, &i);
+ if(irq == NULL)
+ goto out;
+ os_set_pollfd(i, -1);
+ out:
+ irq_unlock(flags);
+}
+
+int deactivate_all_fds(void)
+{
+ struct irq_fd *irq;
+ int err;
+
+ for(irq=active_fds;irq != NULL;irq = irq->next){
+ err = os_clear_fd_async(irq->fd);
+ if(err)
+ return(err);
+ }
+ /* If there is a signal already queued, after unblocking ignore it */
+ os_set_ioignore();
+
+ return(0);
+}
+
+void forward_interrupts(int pid)
+{
+ struct irq_fd *irq;
+ unsigned long flags;
+ int err;
+
+ flags = irq_lock();
+ for(irq=active_fds;irq != NULL;irq = irq->next){
+ err = os_set_owner(irq->fd, pid);
+ if(err < 0){
+ /* XXX Just remove the irq rather than
+ * print out an infinite stream of these
+ */
+ printk("Failed to forward %d to pid %d, err = %d\n",
+ irq->fd, pid, -err);
+ }
+
+ irq->pid = pid;
+ }
+ irq_unlock(flags);
+}
+
/*
* do_IRQ handles all normal device IRQ's (the special
* SMP cross-CPU interrupts have their own specific
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
deleted file mode 100644
index 0e32f5f4a88..00000000000
--- a/arch/um/kernel/irq_user.c
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-#include <sys/poll.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include "user_util.h"
-#include "kern_util.h"
-#include "user.h"
-#include "process.h"
-#include "sigio.h"
-#include "irq_user.h"
-#include "os.h"
-
-struct irq_fd {
- struct irq_fd *next;
- void *id;
- int fd;
- int type;
- int irq;
- int pid;
- int events;
- int current_events;
-};
-
-static struct irq_fd *active_fds = NULL;
-static struct irq_fd **last_irq_ptr = &active_fds;
-
-static struct pollfd *pollfds = NULL;
-static int pollfds_num = 0;
-static int pollfds_size = 0;
-
-extern int io_count, intr_count;
-
-extern void free_irqs(void);
-
-void sigio_handler(int sig, union uml_pt_regs *regs)
-{
- struct irq_fd *irq_fd;
- int i, n;
-
- if(smp_sigio_handler()) return;
- while(1){
- n = poll(pollfds, pollfds_num, 0);
- if(n < 0){
- if(errno == EINTR) continue;
- printk("sigio_handler : poll returned %d, "
- "errno = %d\n", n, errno);
- break;
- }
- if(n == 0) break;
-
- irq_fd = active_fds;
- for(i = 0; i < pollfds_num; i++){
- if(pollfds[i].revents != 0){
- irq_fd->current_events = pollfds[i].revents;
- pollfds[i].fd = -1;
- }
- irq_fd = irq_fd->next;
- }
-
- for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
- if(irq_fd->current_events != 0){
- irq_fd->current_events = 0;
- do_IRQ(irq_fd->irq, regs);
- }
- }
- }
-
- free_irqs();
-}
-
-int activate_ipi(int fd, int pid)
-{
- return(os_set_fd_async(fd, pid));
-}
-
-static void maybe_sigio_broken(int fd, int type)
-{
- if(isatty(fd)){
- if((type == IRQ_WRITE) && !pty_output_sigio){
- write_sigio_workaround();
- add_sigio_fd(fd, 0);
- }
- else if((type