aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/os-Linux')
-rw-r--r--arch/um/os-Linux/Makefile2
-rw-r--r--arch/um/os-Linux/helper.c4
-rw-r--r--arch/um/os-Linux/irq.c4
-rw-r--r--arch/um/os-Linux/sigio.c70
-rw-r--r--arch/um/os-Linux/signal.c22
-rw-r--r--arch/um/os-Linux/skas/process.c15
-rw-r--r--arch/um/os-Linux/time.c17
-rw-r--r--arch/um/os-Linux/umid.c17
8 files changed, 87 insertions, 64 deletions
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 839915b8c31c..77ac50baa3f8 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -10,6 +10,8 @@ obj-y = execvp.o file.o helper.o irq.o main.o mem.o process.o \
registers.o sigio.o signal.o start_up.o time.o tty.o \
umid.o user_syms.o util.o drivers/ skas/
+CFLAGS_signal.o += -Wframe-larger-than=4096
+
obj-$(CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA) += elf_aux.o
USER_OBJS := $(user-objs-y) elf_aux.o execvp.o file.o helper.o irq.o \
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 9fa6e4187d4f..feb48d796e00 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -45,7 +45,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
unsigned long stack, sp;
int pid, fds[2], ret, n;
- stack = alloc_stack(0, __cant_sleep());
+ stack = alloc_stack(__cant_sleep());
if (stack == 0)
return -ENOMEM;
@@ -116,7 +116,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
unsigned long stack, sp;
int pid, status, err;
- stack = alloc_stack(0, __cant_sleep());
+ stack = alloc_stack(__cant_sleep());
if (stack == 0)
return -ENOMEM;
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
index d508310ee5e1..98ea910ef87c 100644
--- a/arch/um/os-Linux/irq.c
+++ b/arch/um/os-Linux/irq.c
@@ -45,10 +45,10 @@ int os_epoll_triggered(int index, int events)
* access to the right includes/defines for EPOLL constants.
*/
-int os_event_mask(int irq_type)
+int os_event_mask(enum um_irq_type irq_type)
{
if (irq_type == IRQ_READ)
- return EPOLLIN | EPOLLPRI;
+ return EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP | EPOLLRDHUP;
if (irq_type == IRQ_WRITE)
return EPOLLOUT;
return 0;
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 75558080d0bf..6597ea1986ff 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -164,45 +164,55 @@ static void update_thread(void)
set_signals_trace(flags);
}
-int add_sigio_fd(int fd)
+int __add_sigio_fd(int fd)
{
struct pollfd *p;
- int err = 0, i, n;
+ int err, i, n;
- sigio_lock();
for (i = 0; i < all_sigio_fds.used; i++) {
if (all_sigio_fds.poll[i].fd == fd)
break;
}
if (i == all_sigio_fds.used)
- goto out;
+ return -ENOSPC;
p = &all_sigio_fds.poll[i];
for (i = 0; i < current_poll.used; i++) {
if (current_poll.poll[i].fd == fd)
- goto out;
+ return 0;
}
n = current_poll.used;
err = need_poll(&next_poll, n + 1);
if (err)
- goto out;
+ return err;
memcpy(next_poll.poll, current_poll.poll,
current_poll.used * sizeof(struct pollfd));
next_poll.poll[n] = *p;
next_poll.used = n + 1;
update_thread();
- out:
+
+ return 0;
+}
+
+
+int add_sigio_fd(int fd)
+{
+ int err;
+
+ sigio_lock();
+ err = __add_sigio_fd(fd);
sigio_unlock();
+
return err;
}
-int ignore_sigio_fd(int fd)
+int __ignore_sigio_fd(int fd)
{
struct pollfd *p;
- int err = 0, i, n = 0;
+ int err, i, n = 0;
/*
* This is called from exitcalls elsewhere in UML - if
@@ -212,17 +222,16 @@ int ignore_sigio_fd(int fd)
if (write_sigio_pid == -1)
return -EIO;
- sigio_lock();
for (i = 0; i < current_poll.used; i++) {
if (current_poll.poll[i].fd == fd)
break;
}
if (i == current_poll.used)
- goto out;
+ return -ENOENT;
err = need_poll(&next_poll, current_poll.used - 1);
if (err)
- goto out;
+ return err;
for (i = 0; i < current_poll.used; i++) {
p = &current_poll.poll[i];
@@ -232,8 +241,18 @@ int ignore_sigio_fd(int fd)
next_poll.used = current_poll.used - 1;
update_thread();
- out:
+
+ return 0;
+}
+
+int ignore_sigio_fd(int fd)
+{
+ int err;
+
+ sigio_lock();
+ err = __ignore_sigio_fd(fd);
sigio_unlock();
+
return err;
}
@@ -336,7 +355,7 @@ out_close1:
close(l_write_sigio_fds[1]);
}
-void sigio_broken(int fd, int read)
+void sigio_broken(int fd)
{
int err;
@@ -352,7 +371,7 @@ void sigio_broken(int fd, int read)
all_sigio_fds.poll[all_sigio_fds.used++] =
((struct pollfd) { .fd = fd,
- .events = read ? POLLIN : POLLOUT,
+ .events = POLLIN,
.revents = 0 });
out:
sigio_unlock();
@@ -360,17 +379,16 @@ out:
/* Changed during early boot */
static int pty_output_sigio;
-static int pty_close_sigio;
-void maybe_sigio_broken(int fd, int read)
+void maybe_sigio_broken(int fd)
{
if (!isatty(fd))
return;
- if ((read || pty_output_sigio) && (!read || pty_close_sigio))
+ if (pty_output_sigio)
return;
- sigio_broken(fd, read);
+ sigio_broken(fd);
}
static void sigio_cleanup(void)
@@ -514,19 +532,6 @@ static void tty_output(int master, int slave)
printk(UM_KERN_CONT "tty_output : read failed, err = %d\n", n);
}
-static void tty_close(int master, int slave)
-{
- printk(UM_KERN_INFO "Checking that host ptys support SIGIO on "
- "close...");
-
- close(slave);
- if (got_sigio) {
- printk(UM_KERN_CONT "Yes\n");
- pty_close_sigio = 1;
- } else
- printk(UM_KERN_CONT "No, enabling workaround\n");
-}
-
static void __init check_sigio(void)
{
if ((access("/dev/ptmx", R_OK) < 0) &&
@@ -536,7 +541,6 @@ static void __init check_sigio(void)
return;
}
check_one_sigio(tty_output);
- check_one_sigio(tty_close);
}
/* Here because it only does the SIGIO testing for now */
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index b58bc68cbe64..96f511d1aabe 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -136,6 +136,16 @@ void set_sigstack(void *sig_stack, int size)
panic("enabling signal stack failed, errno = %d\n", errno);
}
+static void sigusr1_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
+{
+ uml_pm_wake();
+}
+
+void register_pm_wake_signal(void)
+{
+ set_handler(SIGUSR1);
+}
+
static void (*handlers[_NSIG])(int sig, struct siginfo *si, mcontext_t *mc) = {
[SIGSEGV] = sig_handler,
[SIGBUS] = sig_handler,
@@ -145,7 +155,9 @@ static void (*handlers[_NSIG])(int sig, struct siginfo *si, mcontext_t *mc) = {
[SIGIO] = sig_handler,
[SIGWINCH] = sig_handler,
- [SIGALRM] = timer_alarm_handler
+ [SIGALRM] = timer_alarm_handler,
+
+ [SIGUSR1] = sigusr1_handler,
};
static void hard_handler(int sig, siginfo_t *si, void *p)
@@ -222,6 +234,11 @@ void set_handler(int sig)
panic("sigprocmask failed - errno = %d\n", errno);
}
+void send_sigio_to_self(void)
+{
+ kill(os_getpid(), SIGIO);
+}
+
int change_sig(int signal, int on)
{
sigset_t sigset;
@@ -254,6 +271,9 @@ void unblock_signals(void)
return;
signals_enabled = 1;
+#ifdef UML_CONFIG_UML_TIME_TRAVEL_SUPPORT
+ deliver_time_travel_irqs();
+#endif
/*
* We loop because the IRQ handler returns with interrupts off. So,
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 4fb877b99dde..0621d521208e 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -400,7 +400,20 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
if (WIFSTOPPED(status)) {
int sig = WSTOPSIG(status);
- ptrace(PTRACE_GETSIGINFO, pid, 0, (struct siginfo *)&si);
+ /* These signal handlers need the si argument.
+ * The SIGIO and SIGALARM handlers which constitute the
+ * majority of invocations, do not use it.
+ */
+ switch (sig) {
+ case SIGSEGV:
+ case SIGTRAP:
+ case SIGILL:
+ case SIGBUS:
+ case SIGFPE:
+ case SIGWINCH:
+ ptrace(PTRACE_GETSIGINFO, pid, 0, (struct siginfo *)&si);
+ break;
+ }
switch (sig) {
case SIGSEGV:
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index 90f6de224c70..a61cbf73a179 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -7,6 +7,7 @@
*/
#include <stddef.h>
+#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
@@ -99,19 +100,9 @@ long long os_nsecs(void)
}
/**
- * os_idle_sleep() - sleep for a given time of nsecs
- * @nsecs: nanoseconds to sleep
+ * os_idle_sleep() - sleep until interrupted
*/
-void os_idle_sleep(unsigned long long nsecs)
+void os_idle_sleep(void)
{
- struct timespec ts = {
- .tv_sec = nsecs / UM_NSEC_PER_SEC,
- .tv_nsec = nsecs % UM_NSEC_PER_SEC
- };
-
- /*
- * Relay the signal if clock_nanosleep is interrupted.
- */
- if (clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL))
- deliver_alarm();
+ pause();
}
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index 1d7558dac75f..a3dd61521d24 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -137,20 +137,13 @@ static inline int is_umdir_used(char *dir)
{
char pid[sizeof("nnnnnnnnn")], *end, *file;
int dead, fd, p, n, err;
- size_t filelen;
+ size_t filelen = strlen(dir) + sizeof("/pid") + 1;
- err = asprintf(&file, "%s/pid", dir);
- if (err < 0)
- return 0;
-
- filelen = strlen(file);
+ file = malloc(filelen);
+ if (!file)
+ return -ENOMEM;
- n = snprintf(file, filelen, "%s/pid", dir);
- if (n >= filelen) {
- printk(UM_KERN_ERR "is_umdir_used - pid filename too long\n");
- err = -E2BIG;
- goto out;
- }
+ snprintf(file, filelen, "%s/pid", dir);
dead = 0;
fd = open(file, O_RDONLY);