summaryrefslogtreecommitdiff
path: root/arch/um
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/Kconfig.debug9
-rw-r--r--arch/um/Makefile-x86_6411
-rw-r--r--arch/um/defconfig1
-rw-r--r--arch/um/drivers/chan_kern.c18
-rw-r--r--arch/um/drivers/daemon.h2
-rw-r--r--arch/um/drivers/daemon_kern.c2
-rw-r--r--arch/um/drivers/daemon_user.c2
-rw-r--r--arch/um/drivers/fd.c4
-rw-r--r--arch/um/drivers/harddog_kern.c1
-rw-r--r--arch/um/drivers/hostaudio_kern.c4
-rw-r--r--arch/um/drivers/line.c14
-rw-r--r--arch/um/drivers/mcast.h2
-rw-r--r--arch/um/drivers/mcast_kern.c2
-rw-r--r--arch/um/drivers/mcast_user.c2
-rw-r--r--arch/um/drivers/mconsole_kern.c21
-rw-r--r--arch/um/drivers/mconsole_user.c18
-rw-r--r--arch/um/drivers/mmapper_kern.c4
-rw-r--r--arch/um/drivers/net_kern.c139
-rw-r--r--arch/um/drivers/net_user.c81
-rw-r--r--arch/um/drivers/null.c5
-rw-r--r--arch/um/drivers/pcap_kern.c4
-rw-r--r--arch/um/drivers/pcap_user.c2
-rw-r--r--arch/um/drivers/port_kern.c4
-rw-r--r--arch/um/drivers/port_user.c4
-rw-r--r--arch/um/drivers/pty.c6
-rw-r--r--arch/um/drivers/random.c6
-rw-r--r--arch/um/drivers/slip.h2
-rw-r--r--arch/um/drivers/slip_kern.c2
-rw-r--r--arch/um/drivers/slip_user.c2
-rw-r--r--arch/um/drivers/slirp.h2
-rw-r--r--arch/um/drivers/slirp_kern.c2
-rw-r--r--arch/um/drivers/slirp_user.c2
-rw-r--r--arch/um/drivers/ssl.c5
-rw-r--r--arch/um/drivers/stderr_console.c22
-rw-r--r--arch/um/drivers/stdio_console.c4
-rw-r--r--arch/um/drivers/tty.c35
-rw-r--r--arch/um/drivers/ubd_kern.c32
-rw-r--r--arch/um/drivers/xterm.c4
-rw-r--r--arch/um/drivers/xterm_kern.c2
-rw-r--r--arch/um/include/chan_kern.h6
-rw-r--r--arch/um/include/chan_user.h6
-rw-r--r--arch/um/include/irq_user.h9
-rw-r--r--arch/um/include/kern_util.h5
-rw-r--r--arch/um/include/line.h5
-rw-r--r--arch/um/include/longjmp.h9
-rw-r--r--arch/um/include/net_kern.h18
-rw-r--r--arch/um/include/net_user.h19
-rw-r--r--arch/um/include/os.h92
-rw-r--r--arch/um/include/registers.h3
-rw-r--r--arch/um/include/skas/mode_kern_skas.h3
-rw-r--r--arch/um/include/skas/skas.h3
-rw-r--r--arch/um/include/sysdep-i386/archsetjmp.h22
-rw-r--r--arch/um/include/sysdep-i386/signal.h27
-rw-r--r--arch/um/include/sysdep-x86_64/archsetjmp.h24
-rw-r--r--arch/um/include/sysdep-x86_64/kernel-offsets.h1
-rw-r--r--arch/um/include/sysdep-x86_64/ptrace.h43
-rw-r--r--arch/um/include/sysdep-x86_64/sc.h2
-rw-r--r--arch/um/include/sysdep-x86_64/signal.h29
-rw-r--r--arch/um/include/sysdep-x86_64/syscalls.h2
-rw-r--r--arch/um/include/tt/mode_kern_tt.h3
-rw-r--r--arch/um/kernel/Makefile10
-rw-r--r--arch/um/kernel/dyn.lds.S1
-rw-r--r--arch/um/kernel/exec.c (renamed from arch/um/kernel/exec_kern.c)15
-rw-r--r--arch/um/kernel/exitcode.c8
-rw-r--r--arch/um/kernel/gmon_syms.c13
-rw-r--r--arch/um/kernel/irq.c102
-rw-r--r--arch/um/kernel/ksyms.c9
-rw-r--r--arch/um/kernel/mem.c21
-rw-r--r--arch/um/kernel/physmem.c2
-rw-r--r--arch/um/kernel/process.c (renamed from arch/um/kernel/process_kern.c)36
-rw-r--r--arch/um/kernel/reboot.c13
-rw-r--r--arch/um/kernel/sigio.c (renamed from arch/um/kernel/sigio_kern.c)16
-rw-r--r--arch/um/kernel/signal.c (renamed from arch/um/kernel/signal_kern.c)10
-rw-r--r--arch/um/kernel/skas/Makefile3
-rw-r--r--arch/um/kernel/skas/exec.c30
-rw-r--r--arch/um/kernel/skas/exec_kern.c41
-rw-r--r--arch/um/kernel/skas/mem.c24
-rw-r--r--arch/um/kernel/skas/mmu.c10
-rw-r--r--arch/um/kernel/skas/process.c (renamed from arch/um/kernel/skas/process_kern.c)42
-rw-r--r--arch/um/kernel/skas/syscall.c7
-rw-r--r--arch/um/kernel/skas/uaccess.c15
-rw-r--r--arch/um/kernel/syscall.c174
-rw-r--r--arch/um/kernel/syscall_kern.c166
-rw-r--r--arch/um/kernel/time.c256
-rw-r--r--arch/um/kernel/time_kern.c222
-rw-r--r--arch/um/kernel/tlb.c370
-rw-r--r--arch/um/kernel/trap.c (renamed from arch/um/kernel/trap_kern.c)48
-rw-r--r--arch/um/kernel/tt/exec_kern.c2
-rw-r--r--arch/um/kernel/tt/mem.c21
-rw-r--r--arch/um/kernel/tt/process_kern.c4
-rw-r--r--arch/um/kernel/tt/syscall_kern.c12
-rw-r--r--arch/um/kernel/tt/tracer.c22
-rw-r--r--arch/um/kernel/um_arch.c13
-rw-r--r--arch/um/kernel/uml.lds.S13
-rw-r--r--arch/um/kernel/vmlinux.lds.S1
-rw-r--r--arch/um/os-Linux/Makefile8
-rw-r--r--arch/um/os-Linux/drivers/etap.h2
-rw-r--r--arch/um/os-Linux/drivers/ethertap_kern.c2
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c2
-rw-r--r--arch/um/os-Linux/drivers/tuntap.h2
-rw-r--r--arch/um/os-Linux/drivers/tuntap_kern.c2
-rw-r--r--arch/um/os-Linux/drivers/tuntap_user.c2
-rw-r--r--arch/um/os-Linux/file.c143
-rw-r--r--arch/um/os-Linux/helper.c22
-rw-r--r--arch/um/os-Linux/irq.c18
-rw-r--r--arch/um/os-Linux/main.c34
-rw-r--r--arch/um/os-Linux/mem.c33
-rw-r--r--arch/um/os-Linux/process.c40
-rw-r--r--arch/um/os-Linux/sigio.c128
-rw-r--r--arch/um/os-Linux/signal.c61
-rw-r--r--arch/um/os-Linux/skas/process.c104
-rw-r--r--arch/um/os-Linux/start_up.c1
-rw-r--r--arch/um/os-Linux/sys-i386/Makefile2
-rw-r--r--arch/um/os-Linux/sys-i386/registers.c17
-rw-r--r--arch/um/os-Linux/sys-i386/signal.c15
-rw-r--r--arch/um/os-Linux/sys-x86_64/Makefile2
-rw-r--r--arch/um/os-Linux/sys-x86_64/registers.c17
-rw-r--r--arch/um/os-Linux/sys-x86_64/signal.c16
-rw-r--r--arch/um/os-Linux/time.c45
-rw-r--r--arch/um/os-Linux/trap.c1
-rw-r--r--arch/um/os-Linux/uaccess.c6
-rw-r--r--arch/um/os-Linux/umid.c97
-rw-r--r--arch/um/os-Linux/util.c5
-rw-r--r--arch/um/scripts/Makefile.rules4
-rw-r--r--arch/um/sys-i386/Makefile4
-rw-r--r--arch/um/sys-i386/bugs.c9
-rw-r--r--arch/um/sys-i386/checksum.S1
-rw-r--r--arch/um/sys-i386/ldt.c3
-rw-r--r--arch/um/sys-i386/ptrace.c1
-rw-r--r--arch/um/sys-i386/ptrace_user.c5
-rw-r--r--arch/um/sys-i386/setjmp.S58
-rw-r--r--arch/um/sys-i386/sys_call_table.S2
-rw-r--r--arch/um/sys-ppc/misc.S1
-rw-r--r--arch/um/sys-x86_64/Makefile4
-rw-r--r--arch/um/sys-x86_64/setjmp.S54
-rw-r--r--arch/um/sys-x86_64/syscall_table.c7
136 files changed, 1639 insertions, 1908 deletions
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
index bab51d619173..09c1aca6339f 100644
--- a/arch/um/Kconfig.debug
+++ b/arch/um/Kconfig.debug
@@ -47,13 +47,4 @@ config GCOV
If you're involved in UML kernel development and want to use gcov,
say Y. If you're unsure, say N.
-config SYSCALL_DEBUG
- bool "Enable system call debugging"
- depends on DEBUG_INFO
- help
- This adds some system debugging to UML, including keeping a ring buffer
- with recent system calls and some global and per-task statistics.
-
- If unsure, say N
-
endmenu
diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64
index dfd88b652fbe..11154b6773ec 100644
--- a/arch/um/Makefile-x86_64
+++ b/arch/um/Makefile-x86_64
@@ -4,11 +4,17 @@
core-y += arch/um/sys-x86_64/
START := 0x60000000
+_extra_flags_ = -fno-builtin -m64 -mcmodel=kernel
+
#We #undef __x86_64__ for kernelspace, not for userspace where
#it's needed for headers to work!
-CFLAGS += -U__$(SUBARCH)__ -fno-builtin
-USER_CFLAGS += -fno-builtin
+CFLAGS += -U__$(SUBARCH)__ $(_extra_flags_)
+USER_CFLAGS += $(_extra_flags_)
+
CHECKFLAGS += -m64
+AFLAGS += -m64
+LDFLAGS += -m elf_x86_64
+CPPFLAGS += -m64
ELF_ARCH := i386:x86-64
ELF_FORMAT := elf64-x86-64
@@ -16,3 +22,4 @@ ELF_FORMAT := elf64-x86-64
# Not on all 64-bit distros /lib is a symlink to /lib64. PLD is an example.
LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib64
+LINK-y += -m64
diff --git a/arch/um/defconfig b/arch/um/defconfig
index 402a74dc5026..780cc0a4a128 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -526,4 +526,3 @@ CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_GPROF is not set
# CONFIG_GCOV is not set
-# CONFIG_SYSCALL_DEBUG is not set
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 7218c754505b..3576b3cc505e 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -110,7 +110,7 @@ static void not_configged_free(void *data)
"UML\n");
}
-static struct chan_ops not_configged_ops = {
+static const struct chan_ops not_configged_ops = {
.init = not_configged_init,
.open = not_configged_open,
.close = not_configged_close,
@@ -373,7 +373,7 @@ int console_write_chan(struct list_head *chans, const char *buf, int len)
}
int console_open_chan(struct line *line, struct console *co,
- struct chan_opts *opts)
+ const struct chan_opts *opts)
{
int err;
@@ -494,10 +494,10 @@ int chan_config_string(struct list_head *chans, char *str, int size,
struct chan_type {
char *key;
- struct chan_ops *ops;
+ const struct chan_ops *ops;
};
-static struct chan_type chan_table[] = {
+static const struct chan_type chan_table[] = {
{ "fd", &fd_ops },
#ifdef CONFIG_NULL_CHAN
@@ -534,17 +534,17 @@ static struct chan_type chan_table[] = {
};
static struct chan *parse_chan(struct line *line, char *str, int device,
- struct chan_opts *opts)
+ const struct chan_opts *opts)
{
- struct chan_type *entry;
- struct chan_ops *ops;
+ const struct chan_type *entry;
+ const struct chan_ops *ops;
struct chan *chan;
void *data;
int i;
ops = NULL;
data = NULL;
- for(i = 0; i < sizeof(chan_table)/sizeof(chan_table[0]); i++){
+ for(i = 0; i < ARRAY_SIZE(chan_table); i++){
entry = &chan_table[i];
if(!strncmp(str, entry->key, strlen(entry->key))){
ops = entry->ops;
@@ -582,7 +582,7 @@ static struct chan *parse_chan(struct line *line, char *str, int device,
}
int parse_chan_pair(char *str, struct line *line, int device,
- struct chan_opts *opts)
+ const struct chan_opts *opts)
{
struct list_head *chans = &line->chan_list;
struct chan *new, *chan;
diff --git a/arch/um/drivers/daemon.h b/arch/um/drivers/daemon.h
index 7326c42f7ef9..3bc3cf6b94aa 100644
--- a/arch/um/drivers/daemon.h
+++ b/arch/um/drivers/daemon.h
@@ -18,7 +18,7 @@ struct daemon_data {
void *dev;
};
-extern struct net_user_info daemon_user_info;
+extern const struct net_user_info daemon_user_info;
extern int daemon_user_write(int fd, void *buf, int len,
struct daemon_data *pri);
diff --git a/arch/um/drivers/daemon_kern.c b/arch/um/drivers/daemon_kern.c
index 53d09ed78b42..824386974f88 100644
--- a/arch/um/drivers/daemon_kern.c
+++ b/arch/um/drivers/daemon_kern.c
@@ -57,7 +57,7 @@ static int daemon_write(int fd, struct sk_buff **skb,
(struct daemon_data *) &lp->user));
}
-static struct net_kern_info daemon_kern_info = {
+static const struct net_kern_info daemon_kern_info = {
.init = daemon_init,
.protocol = eth_protocol,
.read = daemon_read,
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index c944265955e2..77954ea77043 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -182,7 +182,7 @@ static int daemon_set_mtu(int mtu, void *data)
return(mtu);
}
-struct net_user_info daemon_user_info = {
+const struct net_user_info daemon_user_info = {
.init = daemon_user_init,
.open = daemon_open,
.close = NULL,
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index c41f75e4acb5..108b7dafbd0e 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -20,7 +20,7 @@ struct fd_chan {
char str[sizeof("1234567890\0")];
};
-static void *fd_init(char *str, int device, struct chan_opts *opts)
+static void *fd_init(char *str, int device, const struct chan_opts *opts)
{
struct fd_chan *data;
char *end;
@@ -77,7 +77,7 @@ static void fd_close(int fd, void *d)
}
}
-struct chan_ops fd_ops = {
+const struct chan_ops fd_ops = {
.type = "fd",
.init = fd_init,
.open = fd_open,
diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c
index d18a974735e6..64ff22aa077b 100644
--- a/arch/um/drivers/harddog_kern.c
+++ b/arch/um/drivers/harddog_kern.c
@@ -35,7 +35,6 @@
*/
#include <linux/module.h>
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
index 37232f908cd7..d247ef45c374 100644
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -280,7 +280,7 @@ static int hostmixer_release(struct inode *inode, struct file *file)
/* kernel module operations */
-static struct file_operations hostaudio_fops = {
+static const struct file_operations hostaudio_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = hostaudio_read,
@@ -292,7 +292,7 @@ static struct file_operations hostaudio_fops = {
.release = hostaudio_release,
};
-static struct file_operations hostmixer_fops = {
+static const struct file_operations hostmixer_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.ioctl = hostmixer_ioctl_mixdev,
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 6c2d4ccaf20f..563ce7690a1e 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -8,7 +8,6 @@
#include "linux/list.h"
#include "linux/kd.h"
#include "linux/interrupt.h"
-#include "linux/devfs_fs_kernel.h"
#include "asm/uaccess.h"
#include "chan_kern.h"
#include "irq_user.h"
@@ -252,7 +251,7 @@ void line_set_termios(struct tty_struct *tty, struct termios * old)
/* nothing */
}
-static struct {
+static const struct {
int cmd;
char *level;
char *name;
@@ -374,7 +373,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
int err;
/* Interrupts are enabled here because we registered the interrupt with
- * SA_INTERRUPT (see line_setup_irq).*/
+ * IRQF_DISABLED (see line_setup_irq).*/
spin_lock_irq(&line->lock);
err = flush_buffer(line);
@@ -406,8 +405,8 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
{
- struct line_driver *driver = line->driver;
- int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM;
+ const struct line_driver *driver = line->driver;
+ int err = 0, flags = IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM;
if (input)
err = um_request_irq(driver->read_irq, fd, IRQ_READ,
@@ -559,7 +558,7 @@ int line_setup(struct line *lines, unsigned int num, char *init)
}
int line_config(struct line *lines, unsigned int num, char *str,
- struct chan_opts *opts)
+ const struct chan_opts *opts)
{
struct line *line;
char *new;
@@ -655,7 +654,6 @@ struct tty_driver *line_register_devfs(struct lines *set,
driver->driver_name = line_driver->name;
driver->name = line_driver->device_name;
- driver->devfs_name = line_driver->devfs_name;
driver->major = line_driver->major;
driver->minor_start = line_driver->minor_start;
driver->type = line_driver->type;
@@ -769,7 +767,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty)
spin_unlock(&winch_handler_lock);
if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
- SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
+ IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
"winch", winch) < 0)
printk("register_winch_irq - failed to register IRQ\n");
}
diff --git a/arch/um/drivers/mcast.h b/arch/um/drivers/mcast.h
index a2c6db243458..bc56af9d3e53 100644
--- a/arch/um/drivers/mcast.h
+++ b/arch/um/drivers/mcast.h
@@ -13,7 +13,7 @@ struct mcast_data {
void *dev;
};
-extern struct net_user_info mcast_user_info;
+extern const struct net_user_info mcast_user_info;
extern int mcast_user_write(int fd, void *buf, int len,
struct mcast_data *pri);
diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c
index 3a7af18cf944..c090fbd464e7 100644
--- a/arch/um/drivers/mcast_kern.c
+++ b/arch/um/drivers/mcast_kern.c
@@ -61,7 +61,7 @@ static int mcast_write(int fd, struct sk_buff **skb,
(struct mcast_data *) &lp->user);
}
-static struct net_kern_info mcast_kern_info = {
+static const struct net_kern_info mcast_kern_info = {
.init = mcast_init,
.protocol = eth_protocol,
.read = mcast_read,
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
index afe85bfa66e0..4d2bd39a85bc 100644
--- a/arch/um/drivers/mcast_user.c
+++ b/arch/um/drivers/mcast_user.c
@@ -152,7 +152,7 @@ static int mcast_set_mtu(int mtu, void *data)
return(mtu);
}
-struct net_user_info mcast_user_info = {
+const struct net_user_info mcast_user_info = {
.init = mcast_user_init,
.open = mcast_open,
.close = mcast_close,
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 6d7173fc55a3..773a134e7fdb 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -300,8 +300,6 @@ void mconsole_reboot(struct mc_request *req)
machine_restart(NULL);
}
-extern void ctrl_alt_del(void);
-
void mconsole_cad(struct mc_request *req)
{
mconsole_reply(req, "", 0, 0);
@@ -499,7 +497,7 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int,
}
error = NULL;
- size = sizeof(default_buf)/sizeof(default_buf[0]);
+ size = ARRAY_SIZE(default_buf);
buf = default_buf;
while(1){
@@ -600,6 +598,11 @@ out:
mconsole_reply(req, err_msg, err, 0);
}
+struct mconsole_output {
+ struct list_head list;
+ struct mc_request *req;
+};
+
static DEFINE_SPINLOCK(console_lock);
static LIST_HEAD(clients);
static char console_buf[MCONSOLE_MAX_DATA];
@@ -624,10 +627,10 @@ static void console_write(struct console *console, const char *string,
return;
list_for_each(ele, &clients){
- struct mconsole_entry *entry;
+ struct mconsole_output *entry;
- entry = list_entry(ele, struct mconsole_entry, list);
- mconsole_reply_len(&entry->request, console_buf,
+ entry = list_entry(ele, struct mconsole_output, list);
+ mconsole_reply_len(entry->req, console_buf,
console_index, 0, 1);
}
@@ -651,10 +654,10 @@ late_initcall(mc_add_console);
static void with_console(struct mc_request *req, void (*proc)(void *),
void *arg)
{
- struct mconsole_entry entry;
+ struct mconsole_output entry;
unsigned long flags;
- entry.request = *req;
+ entry.req = req;
list_add(&entry.list, &clients);
spin_lock_irqsave(&console_lock, flags);
@@ -779,7 +782,7 @@ static int mconsole_init(void)
register_reboot_notifier(&reboot_notifier);
err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt,
- SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
+ IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
"mconsole", (void *)sock);
if (err){
printk("Failed to get IRQ for management console\n");
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 4b109fe7fff8..17068eb746c0 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -16,9 +16,15 @@
#include "user.h"
#include "mconsole.h"
#include "umid.h"
+#include "user_util.h"
static struct mconsole_command commands[] = {
- { "version", mconsole_version, MCONSOLE_INTR },
+ /* With uts namespaces, uts information becomes process-specific, so
+ * we need a process context. If we try handling this in interrupt
+ * context, we may hit an exiting process without a valid uts
+ * namespace.
+ */
+ { "version", mconsole_version, MCONSOLE_PROC },
{ "halt", mconsole_halt, MCONSOLE_PROC },
{ "reboot", mconsole_reboot, MCONSOLE_PROC },
{ "config", mconsole_config, MCONSOLE_PROC },
@@ -60,14 +66,14 @@ static struct mconsole_command *mconsole_parse(struct mc_request *req)
struct mconsole_command *cmd;
int i;
- for(i=0;i<sizeof(commands)/sizeof(commands[0]);i++){
+ for(i = 0; i < ARRAY_SIZE(commands); i++){
cmd = &commands[i];
if(!strncmp(req->request.data, cmd->command,
strlen(cmd->command))){
- return(cmd);
+ return cmd;
}
}
- return(NULL);
+ return NULL;
}
#define MIN(a,b) ((a)<(b) ? (a):(b))
@@ -125,6 +131,10 @@ int mconsole_get_request(int fd, struct mc_request *req)
int mconsole_reply_len(struct mc_request *req, const char *str, int total,
int err, int more)
{
+ /* XXX This is a stack consumption problem. It'd be nice to
+ * make it global and serialize access to it, but there are a
+ * ton of callers to this function.
+ */
struct mconsole_reply reply;
int len, n;
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c
index 022f67bb6873..9a3b5daf6250 100644
--- a/arch/um/drivers/mmapper_kern.c
+++ b/arch/um/drivers/mmapper_kern.c
@@ -85,7 +85,7 @@ mmapper_release(struct inode *inode, struct file *file)
return 0;
}
-static struct file_operations mmapper_fops = {
+static const struct file_operations mmapper_fops = {
.owner = THIS_MODULE,
.read = mmapper_read,
.write = mmapper_write,
@@ -95,7 +95,7 @@ static struct file_operations mmapper_fops = {
.release = mmapper_release,
};
-static struct miscdevice mmapper_dev = {
+static const struct miscdevice mmapper_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "mmapper",
.fops = &mmapper_fops
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 8c7279bb353b..300a54a6523e 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -31,6 +31,11 @@
#include "irq_user.h"
#include "irq_kern.h"
+static inline void set_ether_mac(struct net_device *dev, unsigned char *addr)
+{
+ memcpy(dev->dev_addr, addr, ETH_ALEN);
+}
+
#define DRIVER_NAME "uml-netdev"
static DEFINE_SPINLOCK(opened_lock);
@@ -109,18 +114,11 @@ static int uml_net_open(struct net_device *dev)
struct uml_net_private *lp = dev->priv;
int err;
- spin_lock(&lp->lock);
-
if(lp->fd >= 0){
err = -ENXIO;
goto out;
}
- if(!lp->have_mac){
- dev_ip_addr(dev, &lp->mac[2]);
- set_ether_mac(dev, lp->mac);
- }
-
lp->fd = (*lp->open)(&lp->user);
if(lp->fd < 0){
err = lp->fd;
@@ -128,7 +126,7 @@ static int uml_net_open(struct net_device *dev)
}
err = um_request_irq(dev->irq, lp->fd, IRQ_READ, uml_net_interrupt,
- SA_INTERRUPT | SA_SHIRQ, dev->name, dev);
+ IRQF_DISABLED | IRQF_SHARED, dev->name, dev);
if(err != 0){
printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err);
err = -ENETUNREACH;
@@ -144,8 +142,6 @@ static int uml_net_open(struct net_device *dev)
*/
while((err = uml_net_rx(dev)) > 0) ;
- spin_unlock(&lp->lock);
-
spin_lock(&opened_lock);
list_add(&lp->list, &opened);
spin_unlock(&opened_lock);
@@ -155,7 +151,6 @@ out_close:
if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
lp->fd = -1;
out:
- spin_unlock(&lp->lock);
return err;
}
@@ -164,15 +159,12 @@ static int uml_net_close(struct net_device *dev)
struct uml_net_private *lp = dev->priv;
netif_stop_queue(dev);
- spin_lock(&lp->lock);
free_irq(dev->irq, dev);
if(lp->close != NULL)
(*lp->close)(lp->fd, &lp->user);
lp->fd = -1;
- spin_unlock(&lp->lock);
-
spin_lock(&opened_lock);
list_del(&lp->list);
spin_unlock(&opened_lock);
@@ -241,9 +233,9 @@ static int uml_net_set_mac(struct net_device *dev, void *addr)
struct uml_net_private *lp = dev->priv;
struct sockaddr *hwaddr = addr;
- spin_lock(&lp->lock);
- memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN);
- spin_unlock(&lp->lock);
+ spin_lock_irq(&lp->lock);
+ set_ether_mac(dev, hwaddr->sa_data);
+ spin_unlock_irq(&lp->lock);
return(0);
}
@@ -253,7 +245,7 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
struct uml_net_private *lp = dev->priv;
int err = 0;
- spin_lock(&lp->lock);
+ spin_lock_irq(&lp->lock);
new_mtu = (*lp->set_mtu)(new_mtu, &lp->user);
if(new_mtu < 0){
@@ -264,7 +256,7 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
dev->mtu = new_mtu;
out:
- spin_unlock(&lp->lock);
+ spin_unlock_irq(&lp->lock);
return err;
}
@@ -290,6 +282,37 @@ void uml_net_user_timer_expire(unsigned long _conn)
#endif
}
+static void setup_etheraddr(char *str, unsigned char *addr)
+{
+ char *end;
+ int i;
+
+ if(str == NULL)
+ goto random;
+
+ for(i=0;i<6;i++){
+ addr[i] = simple_strtoul(str, &end, 16);
+ if((end == str) ||
+ ((*end != ':') && (*end != ',') && (*end != '\0'))){
+ printk(KERN_ERR
+ "setup_etheraddr: failed to parse '%s' "
+ "as an ethernet address\n", str);
+ goto random;
+ }
+ str = end + 1;
+ }
+ if(addr[0] & 1){
+ printk(KERN_ERR
+ "Attempt to assign a broadcast ethernet address to a "
+ "device disallowed\n");
+ goto random;
+ }
+ return;
+
+random:
+ random_ether_addr(addr);
+}
+
static DEFINE_SPINLOCK(devices_lock);
static LIST_HEAD(devices);
@@ -325,15 +348,13 @@ static int eth_configure(int n, void *init, char *mac,
list_add(&device->list, &devices);
spin_unlock(&devices_lock);
- if (setup_etheraddr(mac, device->mac))
- device->have_mac = 1;
+ setup_etheraddr(mac, device->mac);
printk(KERN_INFO "Netdevice %d ", n);
- if (device->have_mac)
- printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
- device->mac[0], device->mac[1],
- device->mac[2], device->mac[3],
- device->mac[4], device->mac[5]);
+ printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
+ device->mac[0], device->mac[1],
+ device->mac[2], device->mac[3],
+ device->mac[4], device->mac[5]);
printk(": ");
dev = alloc_etherdev(size);
if (dev == NULL) {
@@ -399,7 +420,6 @@ static int eth_configure(int n, void *init, char *mac,
.dev = dev,
.fd = -1,
.mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0},
- .have_mac = device->have_mac,
.protocol = transport->kern->protocol,
.open = transport->user->open,
.close = transport->user->close,
@@ -414,14 +434,12 @@ static int eth_configure(int n, void *init, char *mac,
init_timer(&lp->tl);
spin_lock_init(&lp->lock);
lp->tl.function = uml_net_user_timer_expire;
- if (lp->have_mac)
- memcpy(lp->mac, device->mac, sizeof(lp->mac));
+ memcpy(lp->mac, device->mac, sizeof(lp->mac));
if (transport->user->init)
(*transport->user->init)(&lp->user, dev);
- if (device->have_mac)
- set_ether_mac(dev, device->mac);
+ set_ether_mac(dev, device->mac);
return 0;
}
@@ -564,12 +582,13 @@ static int eth_setup(char *str)
int n, err;
err = eth_parse(str, &n, &str);
- if(err) return(1);
+ if(err)
+ return 1;
- new = alloc_bootmem(sizeof(new));
+ new = alloc_bootmem(sizeof(*new));
if (new == NULL){
printk("eth_init : alloc_bootmem failed\n");
- return(1);
+ return 1;
}
INIT_LIST_HEAD(&new->list);
@@ -577,7 +596,7 @@ static int eth_setup(char *str)
new->init = str;
list_add_tail(&new->list, &eth_cmd_line);
- return(1);
+ return 1;
}
__setup("eth", eth_setup);
@@ -749,54 +768,6 @@ static void close_devices(void)
__uml_exitcall(close_devices);
-int setup_etheraddr(char *str, unsigned char *addr)
-{
- char *end;
- int i;
-
- if(str == NULL)
- return(0);
- for(i=0;i<6;i++){
- addr[i] = simple_strtoul(str, &end, 16);
- if((end == str) ||
- ((*end != ':') && (*end != ',') && (*end != '\0'))){
- printk(KERN_ERR
- "setup_etheraddr: failed to parse '%s' "
- "as an ethernet address\n", str);
- return(0);
- }
- str = end + 1;
- }
- if(addr[0] & 1){
- printk(KERN_ERR
- "Attempt to assign a broadcast ethernet address to a "
- "device disallowed\n");
- return(0);
- }
- return(1);
-}
-
-void dev_ip_addr(void *d, unsigned char *bin_buf)
-{
- struct net_device *dev = d;
- struct in_device *ip = dev->ip_ptr;
- struct in_ifaddr *in;
-
- if((ip == NULL) || ((in = ip->ifa_list) == NULL)){
- printk(KERN_WARNING "dev_ip_addr - device not assigned an "
- "IP address\n");
- return;
- }
- memcpy(bin_buf, &in->ifa_address, sizeof(in->ifa_address));
-}
-
-void set_ether_mac(void *d, unsigned char *addr)
-{
- struct net_device *dev = d;
-
- memcpy(dev->dev_addr, addr, ETH_ALEN);
-}
-
struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra)
{
if((skb != NULL) && (skb_tailroom(skb) < extra)){
@@ -834,7 +805,7 @@ int dev_netmask(void *d, void *m)
struct net_device *dev = d;
struct in_device *ip = dev->ip_ptr;
struct in_ifaddr *in;
- __u32 *mask_out = m;
+ __be32 *mask_out = m;
if(ip == NULL)
return(1);
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 0a7786e00cfb..f3a3f8a29c7a 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -12,6 +12,7 @@
#include <string.h>
#include <sys/socket.h>
#include <sys/wait.h>
+#include <sys/time.h>
#include "user.h"
#include "user_util.h"
#include "kern_util.h"
@@ -22,13 +23,14 @@ int tap_open_common(void *dev, char *gate_addr)
{
int tap_addr[4];
- if(gate_addr == NULL) return(0);
+ if(gate_addr == NULL)
+ return 0;
if(sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0],
&tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4){
printk("Invalid tap IP address - '%s'\n", gate_addr);
- return(-EINVAL);
+ return -EINVAL;
}
- return(0);
+ return 0;
}
void tap_check_ips(char *gate_addr, unsigned char *eth_addr)
@@ -94,25 +96,25 @@ int net_read(int fd, void *buf, int len)
n = os_read_file(fd, buf, len);
if(n == -EAGAIN)
- return(0);
+ return 0;
else if(n == 0)
- return(-ENOTCONN);
- return(n);
+ return -ENOTCONN;
+ return n;
}
int net_recvfrom(int fd, void *buf, int len)
{
int n;
- while(((n = recvfrom(fd, buf, len, 0, NULL, NULL)) < 0) &&
- (errno == EINTR)) ;
-
+ CATCH_EINTR(n = recvfrom(fd, buf, len, 0, NULL, NULL));
if(n < 0){
- if(errno == EAGAIN) return(0);
- return(-errno);
+ if(errno == EAGAIN)
+ return 0;
+ return -errno;
}
- else if(n == 0) return(-ENOTCONN);
- return(n);
+ else if(n == 0)
+ return -ENOTCONN;
+ return n;
}
int net_write(int fd, void *buf, int len)
@@ -122,37 +124,41 @@ int net_write(int fd, void *buf, int len)
n = os_write_file(fd, buf, len);
if(n == -EAGAIN)
- return(0);
+ return 0;
else if(n == 0)
- return(-ENOTCONN);
- return(n);
+ return -ENOTCONN;
+ return n;
}
int net_send(int fd, void *buf, int len)
{
int n;
- while(((n = send(fd, buf, len, 0)) < 0) && (errno == EINTR)) ;
+ CATCH_EINTR(n = send(fd, buf, len, 0));
if(n < 0){
- if(errno == EAGAIN) return(0);
- return(-errno);
+ if(errno == EAGAIN)
+ return 0;
+ return -errno;
}
- else if(n == 0) return(-ENOTCONN);
- return(n);
+ else if(n == 0)
+ return -ENOTCONN;
+ return n;
}
int net_sendto(int fd, void *buf, int len, void *to, int sock_len)
{
int n;
- while(((n = sendto(fd, buf, len, 0, (struct sockaddr *) to,
- sock_len)) < 0) && (errno == EINTR)) ;
+ CATCH_EINTR(n = sendto(fd, buf, len, 0, (struct sockaddr *) to,
+ sock_len));
if(n < 0){
- if(errno == EAGAIN) return(0);
- return(-errno);
+ if(errno == EAGAIN)
+ return 0;
+ return -errno;
}
- else if(n == 0) return(-ENOTCONN);
- return(n);
+ else if(n == 0)
+ return -ENOTCONN;
+ return n;
}
struct change_pre_exec_data {
@@ -176,7 +182,7 @@ static int change_tramp(char **argv, char *output, int output_len)
err = os_pipe(fds, 1, 0);
if(err < 0){
printk("change_tramp - pipe failed, err = %d\n", -err);
- return(err);
+ return err;
}
pe_data.close_me = fds[0];
pe_data.stdout = fds[1];
@@ -190,7 +196,7 @@ static int change_tramp(char **argv, char *output, int output_len)
if (pid > 0)
CATCH_EINTR(err = waitpid(pid, NULL, 0));
- return(pid);
+ return pid;
}
static void change(char *dev, char *what, unsigned char *addr,
@@ -241,26 +247,15 @@ char *split_if_spec(char *str, ...)
va_start(ap, str);
while((arg = va_arg(ap, char **)) != NULL){
if(*str == '\0')
- return(NULL);
+ return NULL;
end = strchr(str, ',');
if(end != str)
*arg = str;
if(end == NULL)
- return(NULL);
+ return NULL;
*end++ = '\0';
str = end;
}
va_end(ap);
- return(str);
+ return str;
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/null.c b/arch/um/drivers/null.c
index 14cc5f78398a..9016c68beee8 100644
--- a/arch/um/drivers/null.c
+++ b/arch/um/drivers/null.c
@@ -8,9 +8,10 @@
#include "chan_user.h"
#include "os.h"
+/* This address is used only as a unique identifer */
static int null_chan;
-static void *null_init(char *str, int device, struct chan_opts *opts)
+static void *null_init(char *str, int device, const struct chan_opts *opts)
{
return(&null_chan);
}
@@ -31,7 +32,7 @@ static void null_free(void *data)
{
}
-struct chan_ops null_ops = {
+const struct chan_ops null_ops = {
.type = "null",
.init = null_init,
.open = null_open,
diff --git a/arch/um/drivers/pcap_kern.c b/arch/um/drivers/pcap_kern.c
index 466ff2c2f918..6e1ef8558283 100644
--- a/arch/um/drivers/pcap_kern.c
+++ b/arch/um/drivers/pcap_kern.c
@@ -46,7 +46,7 @@ static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
return(-EPERM);
}
-static struct net_kern_info pcap_kern_info = {
+static const struct net_kern_info pcap_kern_info = {
.init = pcap_init,
.protocol = eth_protocol,
.read = pcap_read,
@@ -76,7 +76,7 @@ int pcap_setup(char *str, char **mac_out, void *data)
if(host_if != NULL)
init->host_if = host_if;
- for(i = 0; i < sizeof(options)/sizeof(options[0]); i++){
+ for(i = 0; i < ARRAY_SIZE(options); i++){
if(options[i] == NULL)
continue;
if(!strcmp(options[i], "promisc"))
diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c
index edfcb29273e1..2ef641ded960 100644
--- a/arch/um/drivers/pcap_user.c
+++ b/arch/um/drivers/pcap_user.c
@@ -120,7 +120,7 @@ int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri)
return(hdata.len);
}
-struct net_user_info pcap_user_info = {
+const struct net_user_info pcap_user_info = {
.init = pcap_user_init,
.open = pcap_open,
.close = NULL,
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index 189839e4f1d4..73755f37a8a8 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -105,7 +105,7 @@ static int port_accept(struct port_list *port)
.port = port });
if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt,
- SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
+ IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
"telnetd", conn)){
printk(KERN_ERR "port_accept : failed to get IRQ for "
"telnetd\n");
@@ -186,7 +186,7 @@ void *port_data(int port_num)
goto out_free;
}
if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt,
- SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, "port",
+ IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, "port",
port)){
printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num);
goto out_close;
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index c43e8bb32502..f2e8fc42ecc2 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -27,7 +27,7 @@ struct port_chan {
char dev[sizeof("32768\0")];
};
-static void *port_init(char *str, int device, struct chan_opts *opts)
+static void *port_init(char *str, int device, const struct chan_opts *opts)
{
struct port_chan *data;
void *kern_data;
@@ -100,7 +100,7 @@ static void port_close(int fd, void *d)
os_close_file(fd);
}
-struct chan_ops port_ops = {
+const struct chan_ops port_ops = {
.type = "port",
.init = port_init,
.open = port_open,
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
index 1c555c38de4d..abec620e8380 100644
--- a/arch/um/drivers/pty.c
+++ b/arch/um/drivers/pty.c
@@ -22,7 +22,7 @@ struct pty_chan {
char dev_name[sizeof("/dev/pts/0123456\0")];
};
-static void *pty_chan_init(char *str, int device, struct chan_opts *opts)
+static void *pty_chan_init(char *str, int device, const struct chan_opts *opts)
{
struct pty_chan *data;
@@ -118,7 +118,7 @@ static int pty_open(int input, int output, int primary, void *d,
return(fd);
}
-struct chan_ops pty_ops = {
+const struct chan_ops pty_ops = {
.type = "pty",
.init = pty_chan_init,
.open = pty_open,
@@ -131,7 +131,7 @@ struct chan_ops pty_ops = {
.winch = 0,
};
-struct chan_ops pts_ops = {
+const struct chan_ops pts_ops = {
.type = "pts",
.init = pty_chan_init,
.open = pts_open,
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index ba471f5864a6..73b2bdd6d2d3 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -20,6 +20,10 @@
#define RNG_MISCDEV_MINOR 183 /* official */
+/* Changed at init time, in the non-modular case, and at module load
+ * time, in the module case. Presumably, the module subsystem
+ * protects against a module being loaded twice at the same time.
+ */
static int random_fd = -1;
static int rng_dev_open (struct inode *inode, struct file *filp)
@@ -68,7 +72,7 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
return ret;
}
-static struct file_operations rng_chrdev_ops = {
+static const struct file_operations rng_chrdev_ops = {
.owner = THIS_MODULE,
.open = rng_dev_open,
.read = rng_dev_read,
diff --git a/arch/um/drivers/slip.h b/arch/um/drivers/slip.h
index bb0dab41c2e4..c64f8c61d274 100644
--- a/arch/um/drivers/slip.h
+++ b/arch/um/drivers/slip.h
@@ -12,7 +12,7 @@ struct slip_data {
struct slip_proto slip;
};
-extern struct net_user_info slip_user_info;
+extern const struct net_user_info slip_user_info;
extern int slip_user_read(int fd, void *buf, int len, struct slip_data *pri);
extern int slip_user_write(int fd, void *buf, int len, struct slip_data *pri);
diff --git a/arch/um/drivers/slip_kern.c b/arch/um/drivers/slip_kern.c
index 163ee0d5f75e..ccea2d7885e5 100644
--- a/arch/um/drivers/slip_kern.c
+++ b/arch/um/drivers/slip_kern.c
@@ -61,7 +61,7 @@ static int slip_write(int fd, struct sk_buff **skb,
(struct slip_data *) &lp->user));
}
-struct net_kern_info slip_kern_info = {
+const struct net_kern_info slip_kern_info = {
.init = slip_init,
.protocol = slip_protocol,
.read = slip_read,
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index 89fbec185cc1..8460285c69a5 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -241,7 +241,7 @@ static void slip_del_addr(unsigned char *addr, unsigned char *netmask,
close_addr(addr, netmask, pri->name);
}
-struct net_user_info slip_user_info = {
+const struct net_user_info slip_user_info = {
.init = slip_user_init,
.open = slip_open,
.close = slip_close,
diff --git a/arch/um/drivers/slirp.h b/arch/um/drivers/slirp.h
index 6cf88ab580c9..89ccf83b7577 100644
--- a/arch/um/drivers/slirp.h
+++ b/arch/um/drivers/slirp.h
@@ -24,7 +24,7 @@ struct slirp_data {
struct slip_proto slip;
};
-extern struct net_user_info slirp_user_info;
+extern const struct net_user_info slirp_user_info;
extern int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri);
extern int slirp_user_write(int fd, void *buf, int len,
diff --git a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c
index 95e50c943e14..ae322e1c8a87 100644
--- a/arch/um/drivers/slirp_kern.c
+++ b/arch/um/drivers/slirp_kern.c
@@ -64,7 +64,7 @@ static int slirp_write(int fd, struct sk_buff **skb,
(struct slirp_data *) &lp->user));
}
-struct net_kern_info slirp_kern_info = {
+const struct net_kern_info slirp_kern_info = {
.init = slirp_init,
.protocol = slirp_protocol,
.read = slirp_read,
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index 33c5f6e625e8..ce5e85d1de3d 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -126,7 +126,7 @@ static int slirp_set_mtu(int mtu, void *data)
return(mtu);
}
-struct net_user_info slirp_user_info = {
+const struct net_user_info slirp_user_info = {
.init = slirp_user_init,
.open = slirp_open,
.close = slirp_close,
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index a4d6415bc8c4..6f13e7c71a82 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -23,7 +23,7 @@
#include "irq_user.h"
#include "mconsole_kern.h"
-static int ssl_version = 1;
+static const int ssl_version = 1;
/* Referenced only by tty_driver below - presumably it's locked correctly
* by the tty driver.
@@ -54,7 +54,6 @@ static int ssl_remove(int n);
static struct line_driver driver = {
.name = "UML serial line",
.device_name = "ttyS",
- .devfs_name = "tts/",
.major = TTY_MAJOR,
.minor_start = 64,
.type = TTY_DRIVER_TYPE_SERIAL,
@@ -124,7 +123,7 @@ void ssl_hangup(struct tty_struct *tty)
}
#endif
-static struct tty_operations ssl_ops = {
+static const struct tty_operations ssl_ops = {
.open = ssl_open,
.close = line_close,
.write = line_write,
diff --git a/arch/um/drivers/stderr_console.c b/arch/um/drivers/stderr_console.c
index 429ae8e6c7e5..911539293871 100644
--- a/arch/um/drivers/stderr_console.c
+++ b/arch/um/drivers/stderr_console.c
@@ -8,10 +8,9 @@
/*
* Don't register by default -- as this registeres very early in the
- * boot process it becomes the default console. And as this isn't a
- * real tty driver init isn't able to open /dev/console then.
+ * boot process it becomes the default console.
*
- * In most cases this isn't what you want ...
+ * Initialized at init time.
*/
static int use_stderr_console = 0;
@@ -43,3 +42,20 @@ static int stderr_setup(char *str)
return 1;
}
__setup("stderr=", stderr_setup);
+
+/* The previous behavior of not unregistering led to /dev/console being
+ * impossible to open. My FC5 filesystem started having init die, and the
+ * system panicing because of this. Unregistering causes the real
+ * console to become the default console, and /dev/console can then be
+ * opened. Making this an initcall makes this happen late enough that
+ * there is no added value in dumping everything to stderr, and the
+ * normal console is good enough to show you all available output.
+ */
+static int __init unregister_stderr(void)
+{
+ unregister_console(&stderr_console);
+
+ return 0;
+}
+
+__initcall(unregister_stderr);
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 61db8b2fc83f..e4bfcfe8550b 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -60,7 +60,6 @@ static int con_remove(int n);
static struct line_driver driver = {
.name = "UML console",
.device_name = "tty",
- .devfs_name = "vc/",
.major = TTY_MAJOR,
.minor_start = 0,
.type = TTY_DRIVER_TYPE_CONSOLE,
@@ -109,9 +108,10 @@ static int con_open(struct tty_struct *tty, struct file *filp)
return line_open(vts, tty);
}
+/* Set in an initcall, checked in an exitcall */
static int con_init_done = 0;
-static struct tty_operations console_ops = {
+static const struct tty_operations console_ops = {
.open = con_open,
.close = line_close,
.write = line_write,
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c
index 94c9265a4f2c..11de3ac1eb5c 100644
--- a/arch/um/drivers/tty.c
+++ b/arch/um/drivers/tty.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -18,24 +18,24 @@ struct tty_chan {
struct termios tt;
};
-static void *tty_chan_init(char *str, int device, struct chan_opts *opts)
+static void *tty_chan_init(char *str, int device, const struct chan_opts *opts)
{
struct tty_chan *data;
if(*str != ':'){
printk("tty_init : channel type 'tty' must specify "
"a device\n");
- return(NULL);
+ return NULL;
}
str++;
data = um_kmalloc(sizeof(*data));
if(data == NULL)
- return(NULL);
+ return NULL;
*data = ((struct tty_chan) { .dev = str,
.raw = opts->raw });
-
- return(data);
+
+ return data;
}
static int tty_open(int input, int output, int primary, void *d,
@@ -45,22 +45,24 @@ static int tty_open(int input, int output, int primary, void *d,
int fd, err;
fd = os_open_file(data->dev, of_set_rw(OPENFLAGS(), input, output), 0);
- if(fd < 0) return(fd);
+ if(fd < 0)
+ return fd;
+
if(data->raw){
CATCH_EINTR(err = tcgetattr(fd, &data->tt));
if(err)
- return(err);
+ return err;
err = raw(fd);
if(err)
- return(err);
+ return err;
}
*dev_out = data->dev;
- return(fd);
+ return fd;
}
-struct chan_ops tty_ops = {
+const struct chan_ops tty_ops = {
.type = "tty",
.init = tty_chan_init,
.open = tty_open,
@@ -72,14 +74,3 @@ struct chan_ops tty_ops = {
.free = generic_free,
.winch = 0,
};
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 0897852b09a3..5fa4c8e258a4 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -25,7 +25,6 @@
#include "linux/blkdev.h"
#include "linux/hdreg.h"
#include "linux/init.h"
-#include "linux/devfs_fs_kernel.h"
#include "linux/cdrom.h"
#include "linux/proc_fs.h"
#include "linux/ctype.h"
@@ -628,8 +627,6 @@ static int ubd_new_disk(int major, u64 size, int unit,
{
struct gendisk *disk;
- char from[sizeof("ubd/nnnnn\0")], to[sizeof("discnnnnn/disc\0")];
- int err;
disk = alloc_disk(1 << UBD_SHIFT);
if(disk == NULL)
@@ -639,20 +636,10 @@ static int ubd_new_disk(int major, u64 size, int unit,
disk->first_minor = unit << UBD_SHIFT;
disk->fops = &ubd_blops;
set_capacity(disk, size / 512);
- if(major == MAJOR_NR){
+ if(major == MAJOR_NR)
sprintf(disk->disk_name, "ubd%c", 'a' + unit);
- sprintf(disk->devfs_name, "ubd/disc%d", unit);
- sprintf(from, "ubd/%d", unit);
- sprintf(to, "disc%d/disc", unit);
- err = devfs_mk_symlink(from, to);
- if(err)
- printk("ubd_new_disk failed to make link from %s to "
- "%s, error = %d\n", from, to, err);
- }
- else {
+ else
sprintf(disk->disk_name, "ubd_fake%d", unit);
- sprintf(disk->devfs_name, "ubd_fake/disc%d", unit);
- }
/* sysfs register (not for ide fake devices) */
if (major == MAJOR_NR) {
@@ -681,18 +668,15 @@ static int ubd_add(int n)
if(dev->file == NULL)
goto out;
- if (ubd_open_dev(dev))
- goto out;
-
err = ubd_file_size(dev, &dev->size);
if(err < 0)
- goto out_close;
+ goto out;
dev->size = ROUND_BLOCK(dev->size);
err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]);
if(err)
- goto out_close;
+ goto out;
if(fake_major != MAJOR_NR)
ubd_new_disk(fake_major, dev->size, n,
@@ -704,8 +688,6 @@ static int ubd_add(int n)
make_ide_entries(ubd_gendisk[n]->disk_name);
err = 0;
-out_close:
- ubd_close(dev);
out:
return err;
}
@@ -841,7 +823,6 @@ int ubd_init(void)
{
int i;
- devfs_mk_dir("ubd");
if (register_blkdev(MAJOR_NR, "ubd"))
return -1;
@@ -855,7 +836,6 @@ int ubd_init(void)
char name[sizeof("ubd_nnn\0")];
snprintf(name, sizeof(name), "ubd_%d", fake_major);
- devfs_mk_dir(name);
if (register_blkdev(fake_major, "ubd"))
return -1;
}
@@ -888,7 +868,7 @@ int ubd_driver_init(void){
return(0);
}
err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr,
- SA_INTERRUPT, "ubd", ubd_dev);
+ IRQF_DISABLED, "ubd", ubd_dev);
if(err != 0)
printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
return 0;
@@ -1222,7 +1202,7 @@ int open_ubd_file(char *file, struct openflags *openflags, int shared,
}
}
- /* Succesful return case! */
+ /* Successful return case! */
if(backing_file_out == NULL)
return(fd);
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index aaa636661043..386f8b952982 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -31,7 +31,7 @@ struct xterm_chan {
};
/* Not static because it's called directly by the tt mode gdb code */
-void *xterm_init(char *str, int device, struct chan_opts *opts)
+void *xterm_init(char *str, int device, const struct chan_opts *opts)
{
struct xterm_chan *data;
@@ -194,7 +194,7 @@ static void xterm_free(void *d)
free(d);
}
-struct chan_ops xterm_ops = {
+const struct chan_ops xterm_ops = {
.type = "xterm",
.init = xterm_init,
.open = xterm_open,
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
index d269a80f4b0c..6036ec85895a 100644
--- a/arch/um/drivers/xterm_kern.c
+++ b/arch/um/drivers/xterm_kern.c
@@ -54,7 +54,7 @@ int xterm_fd(int socket, int *pid_out)
init_completion(&data->ready);
err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt,
- SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
+ IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
"xterm", data);
if (err){
printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, "
diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h
index 1bb5e9d94270..572d286ed2c6 100644
--- a/arch/um/include/chan_kern.h
+++ b/arch/um/include/chan_kern.h
@@ -23,21 +23,21 @@ struct chan {
unsigned int opened:1;
unsigned int enabled:1;
int fd;
- struct chan_ops *ops;
+ const struct chan_ops *ops;
void *data;
};
extern void chan_interrupt(struct list_head *chans, struct work_struct *task,
struct tty_struct *tty, int irq);
extern int parse_chan_pair(char *str, struct line *line, int device,
- struct chan_opts *opts);
+ const struct chan_opts *opts);
extern int open_chan(struct list_head *chans);
extern int write_chan(struct list_head *chans, const char *buf, int len,
int write_irq);
extern int console_write_chan(struct list_head *chans, const char *buf,
int len);
extern int console_open_chan(struct line *line, struct console *co,
- struct chan_opts *opts);
+ const struct chan_opts *opts);
extern void deactivate_chan(struct list_head *chans, int irq);
extern void reactivate_chan(struct list_head *chans, int irq);
extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h
index 659bb3cac32f..a795547a1dbd 100644
--- a/arch/um/include/chan_user.h
+++ b/arch/um/include/chan_user.h
@@ -20,7 +20,7 @@ enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
struct chan_ops {
char *type;
- void *(*init)(char *, int, struct chan_opts *);
+ void *(*init)(char *, int, const struct chan_opts *);
int (*open)(int, int, int, void *, char **);
void (*close)(int, void *);
int (*read)(int, char *, void *);
@@ -31,8 +31,8 @@ struct chan_ops {
int winch;
};
-extern struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops, tty_ops,
- xterm_ops;
+extern const struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops,
+ tty_ops, xterm_ops;
extern void generic_close(int fd, void *unused);
extern int generic_read(int fd, char *c_out, void *unused);
diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h
index 69a93c804f0e..15d311b9be9e 100644
--- a/arch/um/include/irq_user.h
+++ b/arch/um/include/irq_user.h
@@ -6,6 +6,8 @@
#ifndef __IRQ_USER_H__
#define __IRQ_USER_H__
+#include "uml-config.h"
+
struct irq_fd {
struct irq_fd *next;
void *id;
@@ -26,9 +28,10 @@ extern void free_irq_by_fd(int fd);
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 int activate_ipi(int fd, int pid);
-extern unsigned long irq_lock(void);
-extern void irq_unlock(unsigned long flags);
+
+#ifdef CONFIG_MODE_TT
+extern void forward_interrupts(int pid);
+#endif
#endif
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 310980b32173..59cfa9e0cad0 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -21,13 +21,12 @@ struct kern_handlers {
kern_hndl timer_handler;
};
-extern struct kern_handlers handlinfo_kern;
+extern const struct kern_handlers handlinfo_kern;
extern int ncpus;
extern char *linux_prog;
extern char *gdb_init;
extern int kmalloc_ok;
-extern int timer_irq_inited;
extern int jail;
extern int nsyscalls;
@@ -72,10 +71,8 @@ extern void init_flush_vm(void);
extern void *syscall_sp(void *t);
extern void syscall_trace(union uml_pt_regs *regs, int entryexit);
extern int hz(void);
-extern void uml_idle_timer(void);
extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs);
extern int external_pid(void *t);
-extern void boot_timer_handler(int sig);
extern void interrupt_end(void);
extern void initial_thread_cb(void (*proc)(void *), void *arg);
extern int debugger_signal(int status, int pid);
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 6ac0f8252e21..642c9a0320f9 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -17,7 +17,6 @@
struct line_driver {
char *name;
char *device_name;
- char *devfs_name;
short major;
short minor_start;
short type;
@@ -53,7 +52,7 @@ struct line {
int sigio;
struct work_struct task;
- struct line_driver *driver;
+ const struct line_driver *driver;
int have_irq;
};
@@ -100,7 +99,7 @@ extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
extern void close_lines(struct line *lines, int nlines);
extern int line_config(struct line *lines, unsigned int sizeof_lines,
- char *str, struct chan_opts *opts);
+ char *str, const struct chan_opts *opts);
extern int line_id(char **str, int *start_out, int *end_out);
extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n);
extern int line_get_config(char *dev, struct line *lines,
diff --git a/arch/um/include/longjmp.h b/arch/um/include/longjmp.h
index 8e7053013f7b..e93c6d3e893b 100644
--- a/arch/um/include/longjmp.h
+++ b/arch/um/include/longjmp.h
@@ -1,15 +1,18 @@
#ifndef __UML_LONGJMP_H
#define __UML_LONGJMP_H
-#include <setjmp.h>
+#include "sysdep/archsetjmp.h"
#include "os.h"
+extern int setjmp(jmp_buf);
+extern void longjmp(jmp_buf, int);
+
#define UML_LONGJMP(buf, val) do { \
longjmp(*buf, val); \
} while(0)
-#define UML_SETJMP(buf, enable) ({ \
- int n; \
+#define UML_SETJMP(buf) ({ \
+ int n, enable; \
enable = get_signals(); \
n = setjmp(*buf); \
if(n != 0) \
diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h
index f7de6df60dd7..280459fb0b26 100644
--- a/arch/um/include/net_kern.h
+++ b/arch/um/include/net_kern.h
@@ -18,7 +18,6 @@ struct uml_net {
struct platform_device pdev;
int index;
unsigned char mac[ETH_ALEN];
- int have_mac;
};
struct uml_net_private {
@@ -29,7 +28,6 @@ struct uml_net_private {
struct net_device_stats stats;
int fd;
unsigned char mac[ETH_ALEN];
- int have_mac;
unsigned short (*protocol)(struct sk_buff *);
int (*open)(void *);
void (*close)(int, void *);
@@ -54,15 +52,14 @@ struct transport {
struct list_head list;
char *name;
int (*setup)(char *, char **, void *);
- struct net_user_info *user;
- struct net_kern_info *kern;
+ const struct net_user_info *user;
+ const struct net_kern_info *kern;
int private_size;
int setup_size;
};
extern struct net_device *ether_init(int);
extern unsigned short ether_protocol(struct sk_buff *);
-extern int setup_etheraddr(char *str, unsigned char *addr);
extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra);
extern int tap_setup_common(char *str, char *type, char **dev_name,
char **mac_out, char **gate_addr);
@@ -70,14 +67,3 @@ extern void register_transport(struct transport *new);
extern unsigned short eth_protocol(struct sk_buff *skb);
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/net_user.h b/arch/um/include/net_user.h
index 800c403920bc..19f207cd70fe 100644
--- a/arch/um/include/net_user.h
+++ b/arch/um/include/net_user.h
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -25,10 +25,8 @@ struct net_user_info {
};
extern void ether_user_init(void *data, void *dev);
-extern void dev_ip_addr(void *d, unsigned char *bin_buf);
-extern void set_ether_mac(void *d, unsigned char *addr);
-extern void iter_addresses(void *d, void (*cb)(unsigned char *,
- unsigned char *, void *),
+extern void iter_addresses(void *d, void (*cb)(unsigned char *,
+ unsigned char *, void *),
void *arg);
extern void *get_output_buffer(int *len_out);
@@ -53,14 +51,3 @@ extern char *split_if_spec(char *str, ...);
extern int dev_netmask(void *d, void *m);
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index f88856c28a66..120ca21a513a 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -14,10 +14,11 @@
#include "skas/mm_id.h"
#include "irq_user.h"
#include "sysdep/tls.h"
+#include "sysdep/archsetjmp.h"
-#define OS_TYPE_FILE 1
-#define OS_TYPE_DIR 2
-#define OS_TYPE_SYMLINK 3
+#define OS_TYPE_FILE 1
+#define OS_TYPE_DIR 2
+#define OS_TYPE_SYMLINK 3
#define OS_TYPE_CHARDEV 4
#define OS_TYPE_BLOCKDEV 5
#define OS_TYPE_FIFO 6
@@ -61,68 +62,68 @@ struct openflags {
};
#define OPENFLAGS() ((struct openflags) { .r = 0, .w = 0, .s = 0, .c = 0, \
- .t = 0, .a = 0, .e = 0, .cl = 0 })
+ .t = 0, .a = 0, .e = 0, .cl = 0 })
static inline struct openflags of_read(struct openflags flags)
{
- flags.r = 1;
- return(flags);
+ flags.r = 1;
+ return flags;
}
static inline struct openflags of_write(struct openflags flags)
{
- flags.w = 1;
- return(flags);
+ flags.w = 1;
+ return flags;
}
static inline struct openflags of_rdwr(struct openflags flags)
{
- return(of_read(of_write(flags)));
+ return of_read(of_write(flags));
}
static inline struct openflags of_set_rw(struct openflags flags, int r, int w)
{
flags.r = r;
flags.w = w;
- return(flags);
+ return flags;
}
static inline struct openflags of_sync(struct openflags flags)
-{
- flags.s = 1;
- return(flags);
+{
+ flags.s = 1;
+ return flags;
}
static inline struct openflags of_create(struct openflags flags)
-{
- flags.c = 1;
- return(flags);
+{
+ flags.c = 1;
+ return flags;
}
-
+
static inline struct openflags of_trunc(struct openflags flags)
-{
- flags.t = 1;
- return(flags);
+{
+ flags.t = 1;
+ return flags;
}
-
+
static inline struct openflags of_append(struct openflags flags)
-{
- flags.a = 1;
- return(flags);
+{
+ flags.a = 1;
+ return flags;
}
-
+
static inline struct openflags of_excl(struct openflags flags)
-{
- flags.e = 1;
- return(flags);
+{
+ flags.e = 1;
+ return flags;
}
static inline struct openflags of_cloexec(struct openflags flags)
-{
- flags.cl = 1;
- return(flags);
+{
+ flags.cl = 1;
+ 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);
@@ -198,13 +199,15 @@ extern long os_ptrace_ldt(long pid, long addr, long data);
extern int os_getpid(void);
extern int os_getpgrp(void);
+#ifdef UML_CONFIG_MODE_TT
extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int));
-extern void init_new_thread_signals(int altstack);
+#endif
+extern void init_new_thread_signals(void);
extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr);
extern int os_map_memory(void *virt, int fd, unsigned long long off,
unsigned long len, int r, int w, int x);
-extern int os_protect_memory(void *addr, unsigned long len,
+extern int os_protect_memory(void *addr, unsigned long len,
int r, int w, int x);
extern int os_unmap_memory(void *addr, int len);
extern int os_drop_memory(void *addr, int length);
@@ -216,7 +219,6 @@ extern void os_flush_stdout(void);
*/
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,
int r, int w, int x, int must_succeed);
@@ -276,9 +278,11 @@ extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
extern void switch_timers(int to_real);
extern void idle_sleep(int secs);
+extern int set_interval(int is_virtual);
+#ifdef CONFIG_MODE_TT
extern void enable_timer(void);
+#endif
extern void disable_timer(void);
-extern void user_time_init(void);
extern void uml_idle_timer(void);
extern unsigned long long os_nsecs(void);
@@ -305,12 +309,9 @@ extern int copy_context_skas0(unsigned long stack, int pid);
extern void userspace(union uml_pt_regs *regs);
extern void map_stub_pages(int fd, unsigned long code,
unsigned long data, unsigned long stack);
-extern void new_thread(void *stack, void **switch_buf_ptr,
- void **fork_buf_ptr, void (*handler)(int));
-extern void thread_wait(void *sw, void *fb);
-extern void switch_threads(void *me, void *next);
-extern int start_idle_thread(void *stack, void *switch_buf_ptr,
- void **fork_buf_ptr);
+extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void));
+extern void switch_threads(jmp_buf *me, jmp_buf *you);
+extern int start_idle_thread(void *stack, jmp_buf *switch_buf);
extern void initial_thread_cb_skas(void (*proc)(void *),
void *arg);
extern void halt_skas(void);
@@ -318,7 +319,6 @@ 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);
@@ -330,9 +330,9 @@ 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 add_sigio_fd(int fd);
extern int ignore_sigio_fd(int fd);
+extern void maybe_sigio_broken(int fd, int read);
/* skas/trap */
extern void sig_handler_common_skas(int sig, void *sc_ptr);
diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h
index 83b688ca198f..f845b3629a6d 100644
--- a/arch/um/include/registers.h
+++ b/arch/um/include/registers.h
@@ -7,6 +7,7 @@
#define __REGISTERS_H
#include "sysdep/ptrace.h"
+#include "sysdep/archsetjmp.h"
extern void init_thread_registers(union uml_pt_regs *to);
extern int save_fp_registers(int pid, unsigned long *fp_regs);
@@ -15,6 +16,6 @@ extern void save_registers(int pid, union uml_pt_regs *regs);
extern void restore_registers(int pid, union uml_pt_regs *regs);
extern void init_registers(int pid);
extern void get_safe_registers(unsigned long * regs, unsigned long * fp_regs);
-extern void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer);
+extern unsigned long get_thread_reg(int reg, jmp_buf *buf);
#endif
diff --git a/arch/um/include/skas/mode_kern_skas.h b/arch/um/include/skas/mode_kern_skas.h
index 63c58739bde0..9cd9c6ec9a63 100644
--- a/arch/um/include/skas/mode_kern_skas.h
+++ b/arch/um/include/skas/mode_kern_skas.h
@@ -29,8 +29,7 @@ extern void flush_tlb_mm_skas(struct mm_struct *mm);
extern void force_flush_all_skas(void);
extern long execute_syscall_skas(void *r);
extern void before_mem_skas(unsigned long unused);
-extern unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
- unsigned long *task_size_out);
+extern unsigned long set_task_sizes_skas(unsigned long *task_size_out);
extern int start_uml_skas(void);
extern int external_pid_skas(struct task_struct *task);
extern int thread_pid_skas(struct task_struct *task);
diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h
index 853b26f148c5..e88926b16072 100644
--- a/arch/um/include/skas/skas.h
+++ b/arch/um/include/skas/skas.h
@@ -14,8 +14,7 @@ extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
extern int skas_needs_stub;
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 new_thread_handler(void);
extern void handle_syscall(union uml_pt_regs *regs);
extern int new_mm(unsigned long stack);
extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
diff --git a/arch/um/include/sysdep-i386/archsetjmp.h b/arch/um/include/sysdep-i386/archsetjmp.h
new file mode 100644
index 000000000000..11bafab669e9
--- /dev/null
+++ b/arch/um/include/sysdep-i386/archsetjmp.h
@@ -0,0 +1,22 @@
+/*
+ * arch/i386/include/klibc/archsetjmp.h
+ */
+
+#ifndef _KLIBC_ARCHSETJMP_H
+#define _KLIBC_ARCHSETJMP_H
+
+struct __jmp_buf {
+ unsigned int __ebx;
+ unsigned int __esp;
+ unsigned int __ebp;
+ unsigned int __esi;
+ unsigned int __edi;
+ unsigned int __eip;
+};
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#define JB_IP __eip
+#define JB_SP __esp
+
+#endif /* _SETJMP_H */
diff --git a/arch/um/include/sysdep-i386/signal.h b/arch/um/include/sysdep-i386/signal.h
deleted file mode 100644
index 07518b162136..000000000000
--- a/arch/um/include/sysdep-i386/signal.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2004 PathScale, Inc
- * Licensed under the GPL
- */
-
-#ifndef __I386_SIGNAL_H_
-#define __I386_SIGNAL_H_
-
-#include <signal.h>
-
-#define ARCH_SIGHDLR_PARAM int sig
-
-#define ARCH_GET_SIGCONTEXT(sc, sig) \
- do sc = (struct sigcontext *) (&sig + 1); while(0)
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/sysdep-x86_64/archsetjmp.h b/arch/um/include/sysdep-x86_64/archsetjmp.h
new file mode 100644
index 000000000000..9a5e1a6ec800
--- /dev/null
+++ b/arch/um/include/sysdep-x86_64/archsetjmp.h
@@ -0,0 +1,24 @@
+/*
+ * arch/x86_64/include/klibc/archsetjmp.h
+ */
+
+#ifndef _KLIBC_ARCHSETJMP_H
+#define _KLIBC_ARCHSETJMP_H
+
+struct __jmp_buf {
+ unsigned long __rbx;
+ unsigned long __rsp;
+ unsigned long __rbp;
+ unsigned long __r12;
+ unsigned long __r13;
+ unsigned long __r14;
+ unsigned long __r15;
+ unsigned long __rip;
+};
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#define JB_IP __rip
+#define JB_SP __rsp
+
+#endif /* _SETJMP_H */
diff --git a/arch/um/include/sysdep-x86_64/kernel-offsets.h b/arch/um/include/sysdep-x86_64/kernel-offsets.h
index 939cc475757a..91d129fb3930 100644
--- a/arch/um/include/sysdep-x86_64/kernel-offsets.h
+++ b/arch/um/include/sysdep-x86_64/kernel-offsets.h
@@ -1,4 +1,3 @@
-#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/sched.h>
#include <linux/time.h>
diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h
index 8d353f0feec1..617bb9efc934 100644
--- a/arch/um/include/sysdep-x86_64/ptrace.h
+++ b/arch/um/include/sysdep-x86_64/ptrace.h
@@ -50,6 +50,21 @@
#define HOST_FS 25
#define HOST_GS 26
+/* Also defined in asm/ptrace-x86_64.h, but not in libc headers. So, these
+ * are already defined for kernel code, but not for userspace code.
+ */
+#ifndef FS_BASE
+/* These aren't defined in ptrace.h, but exist in struct user_regs_struct,
+ * which is what x86_64 ptrace actually uses.
+ */
+#define FS_BASE (HOST_FS_BASE * sizeof(long))
+#define GS_BASE (HOST_GS_BASE * sizeof(long))
+#define DS (HOST_DS * sizeof(long))
+#define ES (HOST_ES * sizeof(long))
+#define FS (HOST_FS * sizeof(long))
+#define GS (HOST_GS * sizeof(long))
+#endif
+
#define REGS_FS_BASE(r) ((r)[HOST_FS_BASE])
#define REGS_GS_BASE(r) ((r)[HOST_GS_BASE])
#define REGS_DS(r) ((r)[HOST_DS])
@@ -89,9 +104,12 @@ union uml_pt_regs {
#endif
#ifdef UML_CONFIG_MODE_SKAS
struct skas_regs {
- /* XXX */
- unsigned long regs[27];
- unsigned long fp[65];
+ /* x86_64 ptrace uses sizeof(user_regs_struct) as its register
+ * file size, while i386 uses FRAME_SIZE. Therefore, we need
+ * to use UM_FRAME_SIZE here instead of HOST_FRAME_SIZE.
+ */
+ unsigned long regs[UM_FRAME_SIZE];
+ unsigned long fp[HOST_FP_SIZE];
struct faultinfo faultinfo;
long syscall;
int is_user;
@@ -120,11 +138,16 @@ extern int mode_tt;
#define UPT_R14(r) __CHOOSE_MODE(SC_R14(UPT_SC(r)), REGS_R14((r)->skas.regs))
#define UPT_R15(r) __CHOOSE_MODE(SC_R15(UPT_SC(r)), REGS_R15((r)->skas.regs))
#define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
+#define UPT_FS_BASE(r) \
+ __CHOOSE_MODE(SC_FS_BASE(UPT_SC(r)), REGS_FS_BASE((r)->skas.regs))
#define UPT_FS(r) __CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs))
+#define UPT_GS_BASE(r) \
+ __CHOOSE_MODE(SC_GS_BASE(UPT_SC(r)), REGS_GS_BASE((r)->skas.regs))
#define UPT_GS(r) __CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs))
#define UPT_DS(r) __CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs))
#define UPT_ES(r) __CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs))
#define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
+#define UPT_SS(r) __CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs))
#define UPT_ORIG_RAX(r) \
__CHOOSE_MODE((r)->tt.orig_rax, REGS_ORIG_RAX((r)->skas.regs))
@@ -183,6 +206,13 @@ struct syscall_args {
case RBP: val = UPT_RBP(regs); break; \
case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \
case CS: val = UPT_CS(regs); break; \
+ case SS: val = UPT_SS(regs); break; \
+ case FS_BASE: val = UPT_FS_BASE(regs); break; \
+ case GS_BASE: val = UPT_GS_BASE(regs); break; \
+ case DS: val = UPT_DS(regs); break; \
+ case ES: val = UPT_ES(regs); break; \
+ case FS : val = UPT_FS (regs); break; \
+ case GS: val = UPT_GS(regs); break; \
case EFLAGS: val = UPT_EFLAGS(regs); break; \
default : \
panic("Bad register in UPT_REG : %d\n", reg); \
@@ -214,6 +244,13 @@ struct syscall_args {
case RBP: UPT_RBP(regs) = __upt_val; break; \
case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \
case CS: UPT_CS(regs) = __upt_val; break; \
+ case SS: UPT_SS(regs) = __upt_val; break; \
+ case FS_BASE: UPT_FS_BASE(regs) = __upt_val; break; \
+ case GS_BASE: UPT_GS_BASE(regs) = __upt_val; break; \
+ case DS: UPT_DS(regs) = __upt_val; break; \
+ case ES: UPT_ES(regs) = __upt_val; break; \
+ case FS: UPT_FS(regs) = __upt_val; break; \
+ case GS: UPT_GS(regs) = __upt_val; break; \
case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \
default : \
panic("Bad register in UPT_SET : %d\n", reg); \
diff --git a/arch/um/include/sysdep-x86_64/sc.h b/arch/um/include/sysdep-x86_64/sc.h
index a160d9fcc596..8aee45b07434 100644
--- a/arch/um/include/sysdep-x86_64/sc.h
+++ b/arch/um/include/sysdep-x86_64/sc.h
@@ -35,11 +35,11 @@
#define SC_GS(sc) SC_OFFSET(sc, SC_GS)
#define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS)
#define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK)
+#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
#if 0
#define SC_ORIG_RAX(sc) SC_OFFSET(sc, SC_ORIG_RAX)
#define SC_DS(sc) SC_OFFSET(sc, SC_DS)
#define SC_ES(sc) SC_OFFSET(sc, SC_ES)
-#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
#endif
#endif
diff --git a/arch/um/include/sysdep-x86_64/signal.h b/arch/um/include/sysdep-x86_64/signal.h
deleted file mode 100644
index 6142897af3d1..000000000000
--- a/arch/um/include/sysdep-x86_64/signal.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2004 PathScale, Inc
- * Licensed under the GPL
- */
-
-#ifndef __X86_64_SIGNAL_H_
-#define __X86_64_SIGNAL_H_
-
-#define ARCH_SIGHDLR_PARAM int sig
-
-#define ARCH_GET_SIGCONTEXT(sc, sig_addr) \
- do { \
- struct ucontext *__uc; \
- asm("movq %%rdx, %0" : "=r" (__uc)); \
- sc = (struct sigcontext *) &__uc->uc_mcontext; \
- } while(0)
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/sysdep-x86_64/syscalls.h b/arch/um/include/sysdep-x86_64/syscalls.h
index e06f83e80f4a..5e86aa047b2b 100644
--- a/arch/um/include/sysdep-x86_64/syscalls.h
+++ b/arch/um/include/sysdep-x86_64/syscalls.h
@@ -12,8 +12,6 @@
typedef long syscall_handler_t(void);
-extern syscall_handler_t *ia32_sys_call_table[];
-
extern syscall_handler_t *sys_call_table[];
#define EXECUTE_SYSCALL(syscall, regs) \
diff --git a/arch/um/include/tt/mode_kern_tt.h b/arch/um/include/tt/mode_kern_tt.h
index efa0012550d0..a4fc63057195 100644
--- a/arch/um/include/tt/mode_kern_tt.h
+++ b/arch/um/include/tt/mode_kern_tt.h
@@ -30,8 +30,7 @@ extern void flush_tlb_mm_tt(struct mm_struct *mm);
extern void force_flush_all_tt(void);
extern long execute_syscall_tt(void *r);
extern void before_mem_tt(unsigned long brk_start);
-extern unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out,
- unsigned long *task_size_out);
+extern unsigned long set_task_sizes_tt(unsigned long *task_size_out);
extern int start_uml_tt(void);
extern int external_pid_tt(struct task_struct *task);
extern int thread_pid_tt(struct task_struct *task);
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index fe08971b64cf..6fa63a2a89e3 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -6,16 +6,14 @@
extra-y := vmlinux.lds
clean-files :=
-obj-y = config.o exec_kern.o exitcode.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-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \
+ physmem.o process.o ptrace.o reboot.o resource.o sigio.o \
+ signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.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_SYSCALL_DEBUG) += syscall.o
obj-$(CONFIG_MODE_TT) += tt/
obj-$(CONFIG_MODE_SKAS) += skas/
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index 2517ecb8bf27..68ed24df5c8f 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -26,6 +26,7 @@ SECTIONS
/* Read-only sections, merged into text segment: */
.hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec.c
index c0cb627bf594..0561c43b4685 100644
--- a/arch/um/kernel/exec_kern.c
+++ b/arch/um/kernel/exec.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -31,18 +31,29 @@ 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);
}
+#ifdef CONFIG_TTY_LOG
+extern void log_exec(char **argv, void *tty);
+#endif
+
static long execve1(char *file, char __user * __user *argv,
char __user *__user *env)
{
long error;
#ifdef CONFIG_TTY_LOG
- log_exec(argv, current->tty);
+ mutex_lock(&tty_mutex);
+ task_lock(current); /* FIXME: is this needed ? */
+ log_exec(argv, current->signal->tty);
+ task_unlock(current);
+ mutex_unlock(&tty_mutex);
#endif
error = do_execve(file, argv, env, &current->thread.regs);
if (error == 0){
task_lock(current);
current->ptrace &= ~PT_DTRACE;
+#ifdef SUBARCH_EXECVE1
+ SUBARCH_EXECVE1(&current->thread.regs.regs);
+#endif
task_unlock(current);
set_cmdline(current_cmd());
}
diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c
index d21ebad666b4..8b7f2cdedf94 100644
--- a/arch/um/kernel/exitcode.c
+++ b/arch/um/kernel/exitcode.c
@@ -16,9 +16,13 @@ int uml_exitcode = 0;
static int read_proc_exitcode(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
- int len;
+ int len, val;
- len = sprintf(page, "%d\n", uml_exitcode);
+ /* Save uml_exitcode in a local so that we don't need to guarantee
+ * that sprintf accesses it atomically.
+ */
+ val = uml_exitcode;
+ len = sprintf(page, "%d\n", val);
len -= off;
if(len <= off+count) *eof = 1;
*start = page + off;
diff --git a/arch/um/kernel/gmon_syms.c b/arch/um/kernel/gmon_syms.c
index 2c86e7fdb014..13aa115cd1b4 100644
--- a/arch/um/kernel/gmon_syms.c
+++ b/arch/um/kernel/gmon_syms.c
@@ -5,7 +5,7 @@
#include "linux/module.h"
-extern void __bb_init_func(void *);
+extern void __bb_init_func(void *) __attribute__((weak));
EXPORT_SYMBOL(__bb_init_func);
/* This is defined (and referred to in profiling stub code) only by some GCC
@@ -21,14 +21,3 @@ EXPORT_SYMBOL(__gcov_init);
extern void __gcov_merge_add(void *) __attribute__((weak));
EXPORT_SYMBOL(__gcov_merge_add);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 2ffda012385e..ce7f233fc490 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -63,7 +63,7 @@ int show_interrupts(struct seq_file *p, void *v)
for_each_online_cpu(j)
seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
#endif
- seq_printf(p, " %14s", irq_desc[i].handler->typename);
+ seq_printf(p, " %14s", irq_desc[i].chip->typename);
seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next)
@@ -110,18 +110,7 @@ void sigio_handler(int sig, union uml_pt_regs *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);
- }
- }
-}
+static DEFINE_SPINLOCK(irq_lock);
int activate_fd(int irq, int fd, int type, void *dev_id)
{
@@ -153,20 +142,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
.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();
+ spin_lock_irqsave(&irq_lock, flags);
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);
@@ -176,7 +152,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
}
}
- /*-------------*/
if (type == IRQ_WRITE)
fd = -1;
@@ -199,7 +174,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
* 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);
+ spin_unlock_irqrestore(&irq_lock, flags);
kfree(tmp_pfd);
tmp_pfd = NULL;
@@ -207,37 +182,36 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
if (tmp_pfd == NULL)
goto out_kfree;
- flags = irq_lock();
+ spin_lock_irqsave(&irq_lock, flags);
}
- /*-------------*/
*last_irq_ptr = new_fd;
last_irq_ptr = &new_fd->next;
- irq_unlock(flags);
+ spin_unlock_irqrestore(&irq_lock, flags);
/* This calls activate_fd, so it has to be outside the critical
* section.
*/
- maybe_sigio_broken(fd, type);
+ maybe_sigio_broken(fd, (type == IRQ_READ));
- return(0);
+ return 0;
out_unlock:
- irq_unlock(flags);
+ spin_unlock_irqrestore(&irq_lock, flags);
out_kfree:
kfree(new_fd);
out:
- return(err);
+ return err;
}
static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
{
unsigned long flags;
- flags = irq_lock();
+ spin_lock_irqsave(&irq_lock, flags);
os_free_irq_by_cb(test, arg, active_fds, &last_irq_ptr);
- irq_unlock(flags);
+ spin_unlock_irqrestore(&irq_lock, flags);
}
struct irq_and_dev {
@@ -304,19 +278,16 @@ void reactivate_fd(int fd, int irqnum)
unsigned long flags;
int i;
- flags = irq_lock();
+ spin_lock_irqsave(&irq_lock, flags);
irq = find_irq_by_fd(fd, irqnum, &i);
if (irq == NULL) {
- irq_unlock(flags);
+ spin_unlock_irqrestore(&irq_lock, flags);
return;
}
os_set_pollfd(i, irq->fd);
- irq_unlock(flags);
+ spin_unlock_irqrestore(&irq_lock, flags);
- /* This calls activate_fd, so it has to be outside the critical
- * section.
- */
- maybe_sigio_broken(fd, irq->type);
+ add_sigio_fd(fd);
}
void deactivate_fd(int fd, int irqnum)
@@ -325,13 +296,17 @@ void deactivate_fd(int fd, int irqnum)
unsigned long flags;
int i;
- flags = irq_lock();
+ spin_lock_irqsave(&irq_lock, flags);
irq = find_irq_by_fd(fd, irqnum, &i);
- if (irq == NULL)
- goto out;
+ if(irq == NULL){
+ spin_unlock_irqrestore(&irq_lock, flags);
+ return;
+ }
+
os_set_pollfd(i, -1);
- out:
- irq_unlock(flags);
+ spin_unlock_irqrestore(&irq_lock, flags);
+
+ ignore_sigio_fd(fd);
}
int deactivate_all_fds(void)
@@ -350,13 +325,14 @@ int deactivate_all_fds(void)
return 0;
}
+#ifdef CONFIG_MODE_TT
void forward_interrupts(int pid)
{
struct irq_fd *irq;
unsigned long flags;
int err;
- flags = irq_lock();
+ spin_lock_irqsave(&irq_lock, flags);
for (irq = active_fds; irq != NULL; irq = irq->next) {
err = os_set_owner(irq->fd, pid);
if (err < 0) {
@@ -369,8 +345,9 @@ void forward_interrupts(int pid)
irq->pid = pid;
}
- irq_unlock(flags);
+ spin_unlock_irqrestore(&irq_lock, flags);
}
+#endif
/*
* do_IRQ handles all normal device IRQ's (the special
@@ -403,21 +380,6 @@ int um_request_irq(unsigned int irq, int fd, int type,
EXPORT_SYMBOL(um_request_irq);
EXPORT_SYMBOL(reactivate_fd);
-static DEFINE_SPINLOCK(irq_spinlock);
-
-unsigned long irq_lock(void)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&irq_spinlock, flags);
- return flags;
-}
-
-void irq_unlock(unsigned long flags)
-{
- spin_unlock_irqrestore(&irq_spinlock, flags);
-}
-
/* hw_interrupt_type must define (startup || enable) &&
* (shutdown || disable) && end */
static void dummy(unsigned int irq)
@@ -451,13 +413,13 @@ void __init init_IRQ(void)
irq_desc[TIMER_IRQ].status = IRQ_DISABLED;
irq_desc[TIMER_IRQ].action = NULL;
irq_desc[TIMER_IRQ].depth = 1;
- irq_desc[TIMER_IRQ].handler = &SIGVTALRM_irq_type;
+ irq_desc[TIMER_IRQ].chip = &SIGVTALRM_irq_type;
enable_irq(TIMER_IRQ);
for (i = 1; i < NR_IRQS; i++) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = NULL;
irq_desc[i].depth = 1;
- irq_desc[i].handler = &normal_irq_type;
+ irq_desc[i].chip = &normal_irq_type;
enable_irq(i);
}
}
@@ -474,7 +436,7 @@ int init_aio_irq(int irq, char *name, irqreturn_t (*handler)(int, void *,
}
err = um_request_irq(irq, fds[0], IRQ_READ, handler,
- SA_INTERRUPT | SA_SAMPLE_RANDOM, name,
+ IRQF_DISABLED | IRQF_SAMPLE_RANDOM, name,
(void *) (long) fds[0]);
if (err) {
printk("init_aio_irq - : um_request_irq failed, err = %d\n",
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 432cf0b97a13..f030e44262ba 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -21,7 +21,6 @@
#include "mem_user.h"
#include "os.h"
-EXPORT_SYMBOL(stop);
EXPORT_SYMBOL(uml_physmem);
EXPORT_SYMBOL(set_signals);
EXPORT_SYMBOL(get_signals);
@@ -41,12 +40,14 @@ EXPORT_SYMBOL(handle_page_fault);
EXPORT_SYMBOL(find_iomem);
#ifdef CONFIG_MODE_TT
+EXPORT_SYMBOL(stop);
EXPORT_SYMBOL(strncpy_from_user_tt);
EXPORT_SYMBOL(copy_from_user_tt);
EXPORT_SYMBOL(copy_to_user_tt);
#endif
#ifdef CONFIG_MODE_SKAS
+EXPORT_SYMBOL(strnlen_user_skas);
EXPORT_SYMBOL(strncpy_from_user_skas);
EXPORT_SYMBOL(copy_to_user_skas);
EXPORT_SYMBOL(copy_from_user_skas);
@@ -88,12 +89,6 @@ EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(do_gettimeofday);
EXPORT_SYMBOL(do_settimeofday);
-/* This is here because UML expands lseek to sys_lseek, not to a system
- * call instruction.
- */
-EXPORT_SYMBOL(sys_lseek);
-EXPORT_SYMBOL(sys_wait4);
-
#ifdef CONFIG_SMP
/* required for SMP */
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 44e41a35f000..c95855ba6ab5 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -24,8 +24,6 @@
#include "init.h"
#include "kern_constants.h"
-extern char __binary_start;
-
/* Changed during early boot */
unsigned long *empty_zero_page = NULL;
unsigned long *empty_bad_page = NULL;
@@ -65,8 +63,6 @@ static void setup_highmem(unsigned long highmem_start,
void mem_init(void)
{
- unsigned long start;
-
max_low_pfn = (high_physmem - uml_physmem) >> PAGE_SHIFT;
/* clear the zero-page */
@@ -81,17 +77,12 @@ void mem_init(void)
free_bootmem(__pa(brk_end), uml_reserved - brk_end);
uml_reserved = brk_end;
- /* Fill in any hole at the start of the binary */
- start = (unsigned long) &__binary_start & PAGE_MASK;
- if(uml_physmem != start){
- map_memory(uml_physmem, __pa(uml_physmem), start - uml_physmem,
- 1, 1, 0);
- }
-
/* this will put all low memory onto the freelists */
totalram_pages = free_all_bootmem();
+#ifdef CONFIG_HIGHMEM
totalhigh_pages = highmem >> PAGE_SHIFT;
totalram_pages += totalhigh_pages;
+#endif
num_physpages = totalram_pages;
max_pfn = totalram_pages;
printk(KERN_INFO "Memory: %luk available\n",
@@ -232,10 +223,14 @@ void paging_init(void)
empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
- for(i=0;i<sizeof(zones_size)/sizeof(zones_size[0]);i++)
+ for(i = 0; i < ARRAY_SIZE(zones_size); i++)
zones_size[i] = 0;
- zones_size[ZONE_DMA] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT);
+
+ zones_size[ZONE_NORMAL] = (end_iomem >> PAGE_SHIFT) -
+ (uml_physmem >> PAGE_SHIFT);
+#ifdef CONFIG_HIGHMEM
zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT;
+#endif
free_area_init(zones_size);
/*
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index 166cb09cae4c..abafa64b8727 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -317,7 +317,7 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
}
}
-extern int __syscall_stub_start, __binary_start;
+extern int __syscall_stub_start;
void setup_physmem(unsigned long start, unsigned long reserve_end,
unsigned long len, unsigned long long highmem)
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process.c
index f6a5a502120b..fe6c64abda5b 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process.c
@@ -1,10 +1,9 @@
-/*
+/*
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
* Copyright 2003 PathScale, Inc.
* Licensed under the GPL
*/
-#include "linux/config.h"
#include "linux/kernel.h"
#include "linux/sched.h"
#include "linux/interrupt.h"
@@ -23,6 +22,7 @@
#include "linux/proc_fs.h"
#include "linux/ptrace.h"
#include "linux/random.h"
+#include "linux/personality.h"
#include "asm/unistd.h"
#include "asm/mman.h"
#include "asm/segment.h"
@@ -112,11 +112,11 @@ void set_current(void *t)
void *_switch_to(void *prev, void *next, void *last)
{
- struct task_struct *from = prev;
- struct task_struct *to= next;
+ struct task_struct *from = prev;
+ struct task_struct *to= next;
- to->thread.prev_sched = from;
- set_current(to);
+ to->thread.prev_sched = from;
+ set_current(to);
do {
current->thread.saved_task = NULL ;
@@ -127,7 +127,7 @@ void *_switch_to(void *prev, void *next, void *last)
prev= current;
} while(current->thread.saved_task);
- return(current->thread.prev_sched);
+ return(current->thread.prev_sched);
}
@@ -141,19 +141,19 @@ void release_thread(struct task_struct *task)
{
CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task));
}
-
+
void exit_thread(void)
{
unprotect_stack((unsigned long) current_thread);
}
-
+
void *get_current(void)
{
return(current);
}
int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
- unsigned long stack_top, struct task_struct * p,
+ unsigned long stack_top, struct task_struct * p,
struct pt_regs *regs)
{
int ret;
@@ -182,11 +182,11 @@ void initial_thread_cb(void (*proc)(void *), void *arg)
int save_kmalloc_ok = kmalloc_ok;
kmalloc_ok = 0;
- CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc,
+ CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc,
arg);
kmalloc_ok = save_kmalloc_ok;
}
-
+
unsigned long stack_sp(unsigned long page)
{
return(page + PAGE_SIZE - sizeof(void *));
@@ -210,7 +210,7 @@ void default_idle(void)
*/
if(need_resched())
schedule();
-
+
idle_sleep(10);
}
}
@@ -225,7 +225,7 @@ int page_size(void)
return(PAGE_SIZE);
}
-void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
+void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
pte_t *pte_out)
{
pgd_t *pgd;
@@ -234,7 +234,7 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
pte_t *pte;
pte_t ptent;
- if(task->mm == NULL)
+ if(task->mm == NULL)
return(ERR_PTR(-EINVAL));
pgd = pgd_offset(task->mm, addr);
if(!pgd_present(*pgd))
@@ -245,7 +245,7 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
return(ERR_PTR(-EINVAL));
pmd = pmd_offset(pud, addr);
- if(!pmd_present(*pmd))
+ if(!pmd_present(*pmd))
return(ERR_PTR(-EINVAL));
pte = pte_offset_kernel(pmd, addr);
@@ -270,7 +270,7 @@ char *current_cmd(void)
void force_sigbus(void)
{
- printk(KERN_ERR "Killing pid %d because of a lack of memory\n",
+ printk(KERN_ERR "Killing pid %d because of a lack of memory\n",
current->pid);
lock_kernel();
sigaddset(&current->pending.signal, SIGBUS);
@@ -476,7 +476,7 @@ int singlestepping(void * t)
#ifndef arch_align_stack
unsigned long arch_align_stack(unsigned long sp)
{
- if (randomize_va_space)
+ if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 3ef73bf2e781..f602623644aa 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -22,7 +22,7 @@ static void kill_idlers(int me)
struct task_struct *p;
int i;
- for(i = 0; i < sizeof(idle_threads)/sizeof(idle_threads[0]); i++){
+ for(i = 0; i < ARRAY_SIZE(idle_threads); i++){
p = idle_threads[i];
if((p != NULL) && (p->thread.mode.tt.extern_pid != me))
os_kill_process(p->thread.mode.tt.extern_pid, 0);
@@ -62,14 +62,3 @@ void machine_halt(void)
{
machine_power_off();
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/sigio_kern.c b/arch/um/kernel/sigio.c
index 1c1300fb1e95..0ad755ceb212 100644
--- a/arch/um/kernel/sigio_kern.c
+++ b/arch/um/kernel/sigio.c
@@ -31,7 +31,7 @@ int write_sigio_irq(int fd)
int err;
err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt,
- SA_INTERRUPT | SA_SAMPLE_RANDOM, "write sigio",
+ IRQF_DISABLED|IRQF_SAMPLE_RANDOM, "write sigio",
NULL);
if(err){
printk("write_sigio_irq : um_request_irq failed, err = %d\n",
@@ -53,17 +53,3 @@ void sigio_unlock(void)
{
spin_unlock(&sigio_spinlock);
}
-
-extern void sigio_cleanup(void);
-__uml_exitcall(sigio_cleanup);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal.c
index da17b7541e08..4aa9808ba264 100644
--- a/arch/um/kernel/signal_kern.c
+++ b/arch/um/kernel/signal.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -36,7 +36,7 @@ EXPORT_SYMBOL(unblock_signals);
/*
* OK, we're invoking a handler
- */
+ */
static int handle_signal(struct pt_regs *regs, unsigned long signr,
struct k_sigaction *ka, siginfo_t *info,
sigset_t *oldset)
@@ -88,7 +88,7 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
force_sigsegv(signr, current);
} else {
spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked,
+ sigorsets(&current->blocked, &current->blocked,
&ka->sa.sa_mask);
if(!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked, signr);
@@ -136,7 +136,7 @@ static int kern_do_signal(struct pt_regs *regs)
PT_REGS_RESTART_SYSCALL(regs);
break;
case -ERESTART_RESTARTBLOCK:
- PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall;
+ PT_REGS_ORIG_SYSCALL(regs) = __NR_restart_syscall;
PT_REGS_RESTART_SYSCALL(regs);
break;
}
@@ -146,7 +146,7 @@ static int kern_do_signal(struct pt_regs *regs)
* you set a breakpoint on a system call instruction and singlestep
* from it, the tracing thread used to PTRACE_SINGLESTEP the process
* rather than PTRACE_SYSCALL it, allowing the system call to execute
- * on the host. The tracing thread will check this flag and
+ * on the host. The tracing thread will check this flag and
* PTRACE_SYSCALL if necessary.
*/
if(current->ptrace & PT_DTRACE)
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index ea3a8e409a6e..3e3fa7e7e3cf 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -3,8 +3,7 @@
# Licensed under the GPL
#
-obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \
- syscall.o tlb.o uaccess.o
+obj-y := clone.o exec.o mem.o mmu.o process.o syscall.o tlb.o uaccess.o
# clone.o is in the stub, so it can't be built with profiling
# GCC hardened also auto-enables -fpic, but we need %ebx so it can't work ->
diff --git a/arch/um/kernel/skas/exec.c b/arch/um/kernel/skas/exec.c
new file mode 100644
index 000000000000..54b795951372
--- /dev/null
+++ b/arch/um/kernel/skas/exec.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/kernel.h"
+#include "asm/current.h"
+#include "asm/page.h"
+#include "asm/signal.h"
+#include "asm/ptrace.h"
+#include "asm/uaccess.h"
+#include "asm/mmu_context.h"
+#include "tlb.h"
+#include "skas.h"
+#include "um_mmu.h"
+#include "os.h"
+
+void flush_thread_skas(void)
+{
+ force_flush_all();
+ switch_mm_skas(&current->mm->context.skas.id);
+}
+
+void start_thread_skas(struct pt_regs *regs, unsigned long eip,
+ unsigned long esp)
+{
+ set_fs(USER_DS);
+ PT_REGS_IP(regs) = eip;
+ PT_REGS_SP(regs) = esp;
+}
diff --git a/arch/um/kernel/skas/exec_kern.c b/arch/um/kernel/skas/exec_kern.c
deleted file mode 100644
index 77ed7bbab219..000000000000
--- a/arch/um/kernel/skas/exec_kern.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/kernel.h"
-#include "asm/current.h"
-#include "asm/page.h"
-#include "asm/signal.h"
-#include "asm/ptrace.h"
-#include "asm/uaccess.h"
-#include "asm/mmu_context.h"
-#include "tlb.h"
-#include "skas.h"
-#include "um_mmu.h"
-#include "os.h"
-
-void flush_thread_skas(void)
-{
- force_flush_all();
- switch_mm_skas(&current->mm->context.skas.id);
-}
-
-void start_thread_skas(struct pt_regs *regs, unsigned long eip,
- unsigned long esp)
-{
- set_fs(USER_DS);
- PT_REGS_IP(regs) = eip;
- PT_REGS_SP(regs) = esp;
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c
index 88ab96c609ce..27bbf54b1e52 100644
--- a/arch/um/kernel/skas/mem.c
+++ b/arch/um/kernel/skas/mem.c
@@ -9,31 +9,19 @@
#include "mem_user.h"
#include "skas.h"
-unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
- unsigned long *task_size_out)
+unsigned long set_task_sizes_skas(unsigned long *task_size_out)
{
/* Round up to the nearest 4M */
- unsigned long top = ROUND_4M((unsigned long) &arg);
+ unsigned long host_task_size = ROUND_4M((unsigned long)
+ &host_task_size);
#ifdef CONFIG_HOST_TASK_SIZE
- *host_size_out = CONFIG_HOST_TASK_SIZE;
+ *host_size_out = ROUND_4M(CONFIG_HOST_TASK_SIZE);
*task_size_out = CONFIG_HOST_TASK_SIZE;
#else
- *host_size_out = top;
if (!skas_needs_stub)
- *task_size_out = top;
+ *task_size_out = host_task_size;
else *task_size_out = CONFIG_STUB_START & PGDIR_MASK;
#endif
- return(((unsigned long) set_task_sizes_skas) & ~0xffffff);
+ return host_task_size;
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index c5c9885a8297..4cd2ff546ef6 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -55,14 +55,16 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
* destroy_context_skas.
*/
- mm->context.skas.last_page_table = pmd_page_kernel(*pmd);
+ mm->context.skas.last_page_table = pmd_page_vaddr(*pmd);
#ifdef CONFIG_3_LEVEL_PGTABLES
mm->context.skas.last_pmd = (unsigned long) __va(pud_val(*pud));
#endif
*pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
- *pte = pte_mkexec(*pte);
- *pte = pte_wrprotect(*pte);
+ /* This is wrong for the code page, but it doesn't matter since the
+ * stub is mapped by hand with the correct permissions.
+ */
+ *pte = pte_mkwrite(*pte);
return(0);
out_pmd:
@@ -152,7 +154,7 @@ void destroy_context_skas(struct mm_struct *mm)
free_page(mmu->id.stack);
pte_lock_deinit(virt_to_page(mmu->last_page_table));
pte_free_kernel((pte_t *) mmu->last_page_table);
- dec_page_state(nr_page_table_pages);
+ dec_zone_page_state(virt_to_page(mmu->last_page_table), NR_PAGETABLE);
#ifdef CONFIG_3_LEVEL_PGTABLES
pmd_free((pmd_t *) mmu->last_pmd);
#endif
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process.c
index 2135eaf98a93..ae4fa71d3b8b 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process.c
@@ -33,7 +33,7 @@ void switch_to_skas(void *prev, void *next)
switch_timers(0);
switch_threads(&from->thread.mode.skas.switch_buf,
- to->thread.mode.skas.switch_buf);
+ &to->thread.mode.skas.switch_buf);
arch_switch_to_skas(current->thread.prev_sched, current);
@@ -43,21 +43,21 @@ void switch_to_skas(void *prev, void *next)
extern void schedule_tail(struct task_struct *prev);
-void new_thread_handler(int sig)
+/* This is called magically, by its address being stuffed in a jmp_buf
+ * and being longjmp-d to.
+ */
+void new_thread_handler(void)
{
int (*fn)(void *), n;
void *arg;
- fn = current->thread.request.u.thread.proc;
- arg = current->thread.request.u.thread.arg;
- os_usr1_signal(1);
- thread_wait(&current->thread.mode.skas.switch_buf,
- current->thread.mode.skas.fork_buf);
-
if(current->thread.prev_sched != NULL)
schedule_tail(current->thread.prev_sched);
current->thread.prev_sched = NULL;
+ fn = current->thread.request.u.thread.proc;
+ arg = current->thread.request.u.thread.arg;
+
/* The return value is 1 if the kernel thread execs a process,
* 0 if it just exits
*/
@@ -70,22 +70,13 @@ void new_thread_handler(int sig)
else do_exit(0);
}
-void new_thread_proc(void *stack, void (*handler)(int sig))
-{
- init_new_thread_stack(stack, handler);
- os_usr1_process(os_getpid());
-}
-
void release_thread_skas(struct task_struct *task)
{
}
-void fork_handler(int sig)
+/* Called magically, see new_thread_handler above */
+void fork_handler(void)
{
- os_usr1_signal(1);
- thread_wait(&current->thread.mode.skas.switch_buf,
- current->thread.mode.skas.fork_buf);
-
force_flush_all();
if(current->thread.prev_sched == NULL)
panic("blech");
@@ -109,7 +100,7 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
unsigned long stack_top, struct task_struct * p,
struct pt_regs *regs)
{
- void (*handler)(int);
+ void (*handler)(void);
if(current->thread.forking){
memcpy(&p->thread.regs.regs.skas, &regs->regs.skas,
@@ -123,12 +114,12 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
}
else {
init_thread_registers(&p->thread.regs.regs);
- p->thread.request.u.thread = current->thread.request.u.thread;
+ p->thread.request.u.thread = current->thread.request.u.thread;
handler = new_thread_handler;
}
new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf,
- &p->thread.mode.skas.fork_buf, handler);
+ handler);
return(0);
}
@@ -164,7 +155,7 @@ static int start_kernel_proc(void *unused)
cpu_tasks[0].pid = pid;
cpu_tasks[0].task = current;
#ifdef CONFIG_SMP
- cpu_online_map = cpumask_of_cpu(0);
+ cpu_online_map = cpumask_of_cpu(0);
#endif
start_kernel();
return(0);
@@ -177,13 +168,12 @@ int start_uml_skas(void)
if(proc_mm)
userspace_pid[0] = start_userspace(0);
- init_new_thread_signals(1);
+ init_new_thread_signals();
init_task.thread.request.u.thread.proc = start_kernel_proc;
init_task.thread.request.u.thread.arg = NULL;
return(start_idle_thread(task_stack_page(&init_task),
- &init_task.thread.mode.skas.switch_buf,
- &init_task.thread.mode.skas.fork_buf));
+ &init_task.thread.mode.skas.switch_buf));
}
int external_pid_skas(struct task_struct *task)
diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c
index 51fb94076fcf..0ae4eea21be4 100644
--- a/arch/um/kernel/skas/syscall.c
+++ b/arch/um/kernel/skas/syscall.c
@@ -18,11 +18,7 @@ void handle_syscall(union uml_pt_regs *r)
struct pt_regs *regs = container_of(r, struct pt_regs, regs);
long result;
int syscall;
-#ifdef UML_CONFIG_SYSCALL_DEBUG
- int index;
- index = record_syscall_start(UPT_SYSCALL_NR(r));
-#endif
syscall_trace(r, 0);
current->thread.nsyscalls++;
@@ -44,7 +40,4 @@ void handle_syscall(union uml_pt_regs *r)
REGS_SET_SYSCALL_RETURN(r->skas.regs, result);
syscall_trace(r, 1);
-#ifdef UML_CONFIG_SYSCALL_DEBUG
- record_syscall_end(index, result);
-#endif
}
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index 5992c3257167..8912cec0fe43 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -8,6 +8,7 @@
#include "linux/kernel.h"
#include "linux/string.h"
#include "linux/fs.h"
+#include "linux/hardirq.h"
#include "linux/highmem.h"
#include "asm/page.h"
#include "asm/pgtable.h"
@@ -38,7 +39,7 @@ static unsigned long maybe_map(unsigned long virt, int is_write)
return((unsigned long) phys);
}
-static int do_op(unsigned long addr, int len, int is_write,
+static int do_op_one_page(unsigned long addr, int len, int is_write,
int (*op)(unsigned long addr, int len, void *arg), void *arg)
{
struct page *page;
@@ -49,9 +50,11 @@ static int do_op(unsigned long addr, int len, int is_write,
return(-1);
page = phys_to_page(addr);
- addr = (unsigned long) kmap(page) + (addr & ~PAGE_MASK);
+ addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) + (addr & ~PAGE_MASK);
+
n = (*op)(addr, len, arg);
- kunmap(page);
+
+ kunmap_atomic(page, KM_UML_USERCOPY);
return(n);
}
@@ -77,7 +80,7 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr)
remain = len;
current->thread.fault_catcher = jmpbuf;
- n = do_op(addr, size, is_write, op, arg);
+ n = do_op_one_page(addr, size, is_write, op, arg);
if(n != 0){
*res = (n < 0 ? remain : 0);
goto out;
@@ -91,7 +94,7 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr)
}
while(addr < ((addr + remain) & PAGE_MASK)){
- n = do_op(addr, PAGE_SIZE, is_write, op, arg);
+ n = do_op_one_page(addr, PAGE_SIZE, is_write, op, arg);
if(n != 0){
*res = (n < 0 ? remain : 0);
goto out;
@@ -105,7 +108,7 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr)
goto out;
}
- n = do_op(addr, remain, is_write, op, arg);
+ n = do_op_one_page(addr, remain, is_write, op, arg);
if(n != 0)
*res = (n < 0 ? remain : 0);
else *res = 0;
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index 1731d90e6850..48cf88dd02d4 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -1,36 +1,166 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
+#include "linux/sched.h"
+#include "linux/file.h"
+#include "linux/smp_lock.h"
+#include "linux/mm.h"
+#include "linux/utsname.h"
+#include "linux/msg.h"
+#include "linux/shm.h"
+#include "linux/sys.h"
+#include "linux/syscalls.h"
+#include "linux/unistd.h"
+#include "linux/slab.h"
+#include "linux/utime.h"
+#include "asm/mman.h"
+#include "asm/uaccess.h"
#include "kern_util.h"
-#include "syscall.h"
-#include "os.h"
+#include "user_util.h"
+#include "sysdep/syscalls.h"
+#include "mode_kern.h"
+#include "choose-mode.h"
-struct {
- int syscall;
- int pid;
- long result;
- unsigned long long start;
- unsigned long long end;
-} syscall_record[1024];
+/* Unlocked, I don't care if this is a bit off */
+int nsyscalls = 0;
-int record_syscall_start(int syscall)
+long sys_fork(void)
{
- int max, index;
+ long ret;
- max = sizeof(syscall_record)/sizeof(syscall_record[0]);
- index = next_syscall_index(max);
+ current->thread.forking = 1;
+ ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
+ &current->thread.regs, 0, NULL, NULL);
+ current->thread.forking = 0;
+ return(ret);
+}
+
+long sys_vfork(void)
+{
+ long ret;
+
+ current->thread.forking = 1;
+ ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
+ UPT_SP(&current->thread.regs.regs),
+ &current->thread.regs, 0, NULL, NULL);
+ current->thread.forking = 0;
+ return(ret);
+}
+
+/* common code for old and new mmaps */
+long sys_mmap2(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff)
+{
+ long error = -EBADF;
+ struct file * file = NULL;
+
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ if (!(flags & MAP_ANONYMOUS)) {
+ file = fget(fd);
+ if (!file)
+ goto out;
+ }
+
+ down_write(&current->mm->mmap_sem);
+ error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+ up_write(&current->mm->mmap_sem);
+
+ if (file)
+ fput(file);
+ out:
+ return error;
+}
+
+long old_mmap(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long offset)
+{
+ long err = -EINVAL;
+ if (offset & ~PAGE_MASK)
+ goto out;
+
+ err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+ out:
+ return err;
+}
+/*
+ * sys_pipe() is the normal C calling standard for creating
+ * a pipe. It's not the way unix traditionally does this, though.
+ */
+long sys_pipe(unsigned long __user * fildes)
+{
+ int fd[2];
+ long error;
+
+ error = do_pipe(fd);
+ if (!error) {
+ if (copy_to_user(fildes, fd, sizeof(fd)))
+ error = -EFAULT;
+ }
+ return error;
+}
- syscall_record[index].syscall = syscall;
- syscall_record[index].pid = current_pid();
- syscall_record[index].result = 0xdeadbeef;
- syscall_record[index].start = os_nsecs();
- return(index);
+
+long sys_uname(struct old_utsname __user * name)
+{
+ long err;
+ if (!name)
+ return -EFAULT;
+ down_read(&uts_sem);
+ err = copy_to_user(name, &system_utsname, sizeof (*name));
+ up_read(&uts_sem);
+ return err?-EFAULT:0;
}
-void record_syscall_end(int index, long result)
+long sys_olduname(struct oldold_utsname __user * name)
{
- syscall_record[index].result = result;
- syscall_record[index].end = os_nsecs();
+ long error;
+
+ if (!name)
+ return -EFAULT;
+ if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
+ return -EFAULT;
+
+ down_read(&uts_sem);
+
+ error = __copy_to_user(&name->sysname,&system_utsname.sysname,
+ __OLD_UTS_LEN);
+ error |= __put_user(0,name->sysname+__OLD_UTS_LEN);
+ error |= __copy_to_user(&name->nodename,&system_utsname.nodename,
+ __OLD_UTS_LEN);
+ error |= __put_user(0,name->nodename+__OLD_UTS_LEN);
+ error |= __copy_to_user(&name->release,&system_utsname.release,
+ __OLD_UTS_LEN);
+ error |= __put_user(0,name->release+__OLD_UTS_LEN);
+ error |= __copy_to_user(&name->version,&system_utsname.version,
+ __OLD_UTS_LEN);
+ error |= __put_user(0,name->version+__OLD_UTS_LEN);
+ error |= __copy_to_user(&name->machine,&system_utsname.machine,
+ __OLD_UTS_LEN);
+ error |= __put_user(0,name->machine+__OLD_UTS_LEN);
+
+ up_read(&uts_sem);
+
+ error = error ? -EFAULT : 0;
+
+ return error;
+}
+
+DEFINE_SPINLOCK(syscall_lock);
+
+static int syscall_index = 0;
+
+int next_syscall_index(int limit)
+{
+ int ret;
+
+ spin_lock(&syscall_lock);
+ ret = syscall_index;
+ if(++syscall_index == limit)
+ syscall_index = 0;
+ spin_unlock(&syscall_lock);
+ return(ret);
}
diff --git a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c
deleted file mode 100644
index 37d3978337d8..000000000000
--- a/arch/um/kernel/syscall_kern.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#include "linux/sched.h"
-#include "linux/file.h"
-#include "linux/smp_lock.h"
-#include "linux/mm.h"
-#include "linux/utsname.h"
-#include "linux/msg.h"
-#include "linux/shm.h"
-#include "linux/sys.h"
-#include "linux/syscalls.h"
-#include "linux/unistd.h"
-#include "linux/slab.h"
-#include "linux/utime.h"
-#include "asm/mman.h"
-#include "asm/uaccess.h"
-#include "kern_util.h"
-#include "user_util.h"
-#include "sysdep/syscalls.h"
-#include "mode_kern.h"
-#include "choose-mode.h"
-
-/* Unlocked, I don't care if this is a bit off */
-int nsyscalls = 0;
-
-long sys_fork(void)
-{
- long ret;
-
- current->thread.forking = 1;
- ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
- &current->thread.regs, 0, NULL, NULL);
- current->thread.forking = 0;
- return(ret);
-}
-
-long sys_vfork(void)
-{
- long ret;
-
- current->thread.forking = 1;
- ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
- UPT_SP(&current->thread.regs.regs),
- &current->thread.regs, 0, NULL, NULL);
- current->thread.forking = 0;
- return(ret);
-}
-
-/* common code for old and new mmaps */
-long sys_mmap2(unsigned long addr, unsigned long len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, unsigned long pgoff)
-{
- long error = -EBADF;
- struct file * file = NULL;
-
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
- if (!(flags & MAP_ANONYMOUS)) {
- file = fget(fd);
- if (!file)
- goto out;
- }
-
- down_write(&current->mm->mmap_sem);
- error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
- up_write(&current->mm->mmap_sem);
-
- if (file)
- fput(file);
- out:
- return error;
-}
-
-long old_mmap(unsigned long addr, unsigned long len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, unsigned long offset)
-{
- long err = -EINVAL;
- if (offset & ~PAGE_MASK)
- goto out;
-
- err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
- out:
- return err;
-}
-/*
- * sys_pipe() is the normal C calling standard for creating
- * a pipe. It's not the way unix traditionally does this, though.
- */
-long sys_pipe(unsigned long __user * fildes)
-{
- int fd[2];
- long error;
-
- error = do_pipe(fd);
- if (!error) {
- if (copy_to_user(fildes, fd, sizeof(fd)))
- error = -EFAULT;
- }
- return error;
-}
-
-
-long sys_uname(struct old_utsname __user * name)
-{
- long err;
- if (!name)
- return -EFAULT;
- down_read(&uts_sem);
- err=copy_to_user(name, &system_utsname, sizeof (*name));
- up_read(&uts_sem);
- return err?-EFAULT:0;
-}
-
-long sys_olduname(struct oldold_utsname __user * name)
-{
- long error;
-
- if (!name)
- return -EFAULT;
- if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
- return -EFAULT;
-
- down_read(&uts_sem);
-
- error = __copy_to_user(&name->sysname,&system_utsname.sysname,
- __OLD_UTS_LEN);
- error |= __put_user(0,name->sysname+__OLD_UTS_LEN);
- error |= __copy_to_user(&name->nodename,&system_utsname.nodename,
- __OLD_UTS_LEN);
- error |= __put_user(0,name->nodename+__OLD_UTS_LEN);
- error |= __copy_to_user(&name->release,&system_utsname.release,
- __OLD_UTS_LEN);
- error |= __put_user(0,name->release+__OLD_UTS_LEN);
- error |= __copy_to_user(&name->version,&system_utsname.version,
- __OLD_UTS_LEN);
- error |= __put_user(0,name->version+__OLD_UTS_LEN);
- error |= __copy_to_user(&name->machine,&system_utsname.machine,
- __OLD_UTS_LEN);
- error |= __put_user(0,name->machine+__OLD_UTS_LEN);
-
- up_read(&uts_sem);
-
- error = error ? -EFAULT : 0;
-
- return error;
-}
-
-DEFINE_SPINLOCK(syscall_lock);
-
-static int syscall_index = 0;
-
-int next_syscall_index(int limit)
-{
- int ret;
-
- spin_lock(&syscall_lock);
- ret = syscall_index;
- if(++syscall_index == limit)
- syscall_index = 0;
- spin_unlock(&syscall_lock);
- return(ret);
-}
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 8fa2ae7f3026..a92965f8f9cd 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -1,172 +1,180 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <time.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-#include "user_util.h"
+#include "linux/kernel.h"
+#include "linux/module.h"
+#include "linux/unistd.h"
+#include "linux/stddef.h"
+#include "linux/spinlock.h"
+#include "linux/time.h"
+#include "linux/sched.h"
+#include "linux/interrupt.h"
+#include "linux/init.h"
+#include "linux/delay.h"
+#include "linux/hrtimer.h"
+#include "asm/irq.h"
+#include "asm/param.h"
+#include "asm/current.h"
#include "kern_util.h"
-#include "user.h"
-#include "process.h"
-#include "time_user.h"
-#include "kern_constants.h"
+#include "user_util.h"
+#include "mode.h"
#include "os.h"
-/* XXX This really needs to be declared and initialized in a kernel file since
- * it's in <linux/time.h>
- */
-extern struct timespec wall_to_monotonic;
-
-extern struct timeval xtime;
-
-struct timeval local_offset = { 0, 0 };
-
-void timer(void)
+int hz(void)
{
- gettimeofday(&xtime, NULL);
- timeradd(&xtime, &local_offset, &xtime);
+ return(HZ);
}
-static void set_interval(int timer_type)
+/*
+ * Scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
{
- int usec = 1000000/hz();
- struct itimerval interval = ((struct itimerval) { { 0, usec },
- { 0, usec } });
-
- if(setitimer(timer_type, &interval, NULL) == -1)
- panic("setitimer failed - errno = %d\n", errno);
+ return (unsigned long long)jiffies_64 * (1000000000 / HZ);
}
-void enable_timer(void)
-{
- set_interval(ITIMER_VIRTUAL);
-}
+static unsigned long long prev_nsecs;
+#ifdef CONFIG_UML_REAL_TIME_CLOCK
+static long long delta; /* Deviation per interval */
+#endif
-void prepare_timer(void * ptr)
+void timer_irq(union uml_pt_regs *regs)
{
- int usec = 1000000/hz();
- *(struct itimerval *)ptr = ((struct itimerval) { { 0, usec },
- { 0, usec }});
+ unsigned long long ticks = 0;
+
+#ifdef CONFIG_UML_REAL_TIME_CLOCK
+ if(prev_nsecs){
+ /* We've had 1 tick */
+ unsigned long long nsecs = os_nsecs();
+
+ delta += nsecs - prev_nsecs;
+ prev_nsecs = nsecs;
+
+ /* Protect against the host clock being set backwards */
+ if(delta < 0)
+ delta = 0;
+
+ ticks += (delta * HZ) / BILLION;
+ delta -= (ticks * BILLION) / HZ;
+ }
+ else prev_nsecs = os_nsecs();
+#else
+ ticks = 1;
+#endif
+ while(ticks > 0){
+ do_IRQ(TIMER_IRQ, regs);
+ ticks--;
+ }
}
-void disable_timer(void)
+static DEFINE_SPINLOCK(timer_spinlock);
+
+static unsigned long long local_offset = 0;
+
+static inline unsigned long long get_time(void)
{
- struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
- if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) ||
- (setitimer(ITIMER_REAL, &disable, NULL) < 0))
- printk("disnable_timer - setitimer failed, errno = %d\n",
- errno);
- /* If there are signals already queued, after unblocking ignore them */
- set_handler(SIGALRM, SIG_IGN, 0, -1);
- set_handler(SIGVTALRM, SIG_IGN, 0, -1);
+ unsigned long long nsecs;
+ unsigned long flags;
+
+ spin_lock_irqsave(&timer_spinlock, flags);
+ nsecs = os_nsecs();
+ nsecs += local_offset;
+ spin_unlock_irqrestore(&timer_spinlock, flags);
+
+ return nsecs;
}
-void switch_timers(int to_real)
+irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
{
- struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
- struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() },
- { 0, 1000000/hz() }});
- int old, new;
-
- if(to_real){
- old = ITIMER_VIRTUAL;
- new = ITIMER_REAL;
- }
- else {
- old = ITIMER_REAL;
- new = ITIMER_VIRTUAL;
- }
+ unsigned long long nsecs;
+ unsigned long flags;
+
+ write_seqlock_irqsave(&xtime_lock, flags);
+
+ do_timer(1);
- if((setitimer(old, &disable, NULL) < 0) ||
- (setitimer(new, &enable, NULL)))
- printk("switch_timers - setitimer failed, errno = %d\n",
- errno);
+ nsecs = get_time();
+ xtime.tv_sec = nsecs / NSEC_PER_SEC;
+ xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC;
+
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+
+ return IRQ_HANDLED;
}
-void uml_idle_timer(void)
+static void register_timer(void)
{
- if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
- panic("Couldn't unset SIGVTALRM handler");
-
- set_handler(SIGALRM, (__sighandler_t) alarm_handler,
- SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
- set_interval(ITIMER_REAL);
+ int err;
+
+ err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL);
+ if(err != 0)
+ printk(KERN_ERR "register_timer : request_irq failed - "
+ "errno = %d\n", -err);
+
+ err = set_interval(1);
+ if(err != 0)
+ printk(KERN_ERR "register_timer : set_interval failed - "
+ "errno = %d\n", -err);
}
-extern void ktime_get_ts(struct timespec *ts);
-#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
+extern void (*late_time_init)(void);
void time_init(void)
{
- struct timespec now;
-
- if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR)
- panic("Couldn't set SIGVTALRM handler");
- set_interval(ITIMER_VIRTUAL);
+ long long nsecs;
- do_posix_clock_monotonic_gettime(&now);
- wall_to_monotonic.tv_sec = -now.tv_sec;
- wall_to_monotonic.tv_nsec = -now.tv_nsec;
+ nsecs = os_nsecs();
+ set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION,
+ -nsecs % BILLION);
+ late_time_init = register_timer;
}
-/* Defined in linux/ktimer.h, which can't be included here */
-#define clock_was_set() do { } while (0)
-
void do_gettimeofday(struct timeval *tv)
{
- unsigned long flags;
-
- flags = time_lock();
- gettimeofday(tv, NULL);
- timeradd(tv, &local_offset, tv);
- time_unlock(flags);
- clock_was_set();
+ unsigned long long nsecs = get_time();
+
+ tv->tv_sec = nsecs / NSEC_PER_SEC;
+ /* Careful about calculations here - this was originally done as
+ * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC
+ * which gave bogus (> 1000000) values. Dunno why, suspect gcc
+ * (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion
+ * problem that I missed.
+ */
+ nsecs -= tv->tv_sec * NSEC_PER_SEC;
+ tv->tv_usec = (unsigned long) nsecs / NSEC_PER_USEC;
}
-int do_settimeofday(struct timespec *tv)
+static inline void set_time(unsigned long long nsecs)
{
- struct timeval now;
+ unsigned long long now;
unsigned long flags;
- struct timeval tv_in;
- if ((unsigned long) tv->tv_nsec >= UM_NSEC_PER_SEC)
- return -EINVAL;
+ spin_lock_irqsave(&timer_spinlock, flags);
+ now = os_nsecs();
+ local_offset = nsecs - now;
+ spin_unlock_irqrestore(&timer_spinlock, flags);
- tv_in.tv_sec = tv->tv_sec;
- tv_in.tv_usec = tv->tv_nsec / 1000;
-
- flags = time_lock();
- gettimeofday(&now, NULL);
- timersub(&tv_in, &now, &local_offset);
- time_unlock(flags);
-
- return(0);
+ clock_was_set();
}
-void idle_sleep(int secs)
+int do_settimeofday(struct timespec *tv)
{
- struct timespec ts;
+ set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec);
- ts.tv_sec = secs;
- ts.tv_nsec = 0;
- nanosleep(&ts, NULL);
+ return 0;
}
-/* XXX This partly duplicates init_irq_signals */
-
-void user_time_init(void)
+void timer_handler(int sig, union uml_pt_regs *regs)
{
- set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
- SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
- SIGALRM, SIGUSR2, -1);
- set_handler(SIGALRM, (__sighandler_t) alarm_handler,
- SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
- SIGVTALRM, SIGUSR2, -1);
- set_interval(ITIMER_VIRTUAL);
+ local_irq_disable();
+ irq_enter();
+ update_process_times(CHOOSE_MODE(
+ (UPT_SC(regs) && user_context(UPT_SP(regs))),
+ (regs)->skas.is_user));
+ irq_exit();
+ local_irq_enable();
+ if(current_thread->cpu == 0)
+ timer_irq(regs);
}
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
deleted file mode 100644
index 87cdbc560d36..000000000000
--- a/arch/um/kernel/time_kern.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/kernel.h"
-#include "linux/module.h"
-#include "linux/unistd.h"
-#include "linux/stddef.h"
-#include "linux/spinlock.h"
-#include "linux/time.h"
-#include "linux/sched.h"
-#include "linux/interrupt.h"
-#include "linux/init.h"
-#include "linux/delay.h"
-#include "linux/hrtimer.h"
-#include "asm/irq.h"
-#include "asm/param.h"
-#include "asm/current.h"
-#include "kern_util.h"
-#include "user_util.h"
-#include "mode.h"
-#include "os.h"
-
-int hz(void)
-{
- return(HZ);
-}
-
-/*
- * Scheduler clock - returns current time in nanosec units.
- */
-unsigned long long sched_clock(void)
-{
- return (unsigned long long)jiffies_64 * (1000000000 / HZ);
-}
-
-/* Changed at early boot */
-int timer_irq_inited = 0;
-
-static int first_tick;
-static unsigned long long prev_nsecs;
-#ifdef CONFIG_UML_REAL_TIME_CLOCK
-static long long delta; /* Deviation per interval */
-#endif
-
-void timer_irq(union uml_pt_regs *regs)
-{
- unsigned long long ticks = 0;
-
- if(!timer_irq_inited){
- /* This is to ensure that ticks don't pile up when
- * the timer handler is suspended */
- first_tick = 0;
- return;
- }
-
- if(first_tick){
-#ifdef CONFIG_UML_REAL_TIME_CLOCK
- /* We've had 1 tick */
- unsigned long long nsecs = os_nsecs();
-
- delta += nsecs - prev_nsecs;
- prev_nsecs = nsecs;
-
- /* Protect against the host clock being set backwards */
- if(delta < 0)
- delta = 0;
-
- ticks += (delta * HZ) / BILLION;
- delta -= (ticks * BILLION) / HZ;
-#else
- ticks = 1;
-#endif
- }
- else {
- prev_nsecs = os_nsecs();
- first_tick = 1;
- }
-
- while(ticks > 0){
- do_IRQ(TIMER_IRQ, regs);
- ticks--;
- }
-}
-
-
-void time_init_kern(void)
-{
- long long nsecs;
-
- nsecs = os_nsecs();
- set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION,
- -nsecs % BILLION);
-}
-
-void do_boot_timer_handler(struct sigcontext * sc)
-{
- struct pt_regs regs;
-
- CHOOSE_MODE((void) (UPT_SC(&regs.regs) = sc),
- (void) (regs.regs.skas.is_user = 0));
- do_timer(&regs);
-}
-
-static DEFINE_SPINLOCK(timer_spinlock);
-
-static unsigned long long local_offset = 0;
-
-static inline unsigned long long get_time(void)
-{
- unsigned long long nsecs;
- unsigned long flags;
-
- spin_lock_irqsave(&timer_spinlock, flags);
- nsecs = os_nsecs();
- nsecs += local_offset;
- spin_unlock_irqrestore(&timer_spinlock, flags);
-
- return nsecs;
-}
-
-irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
-{
- unsigned long long nsecs;
- unsigned long flags;
-
- do_timer(regs);
-
- write_seqlock_irqsave(&xtime_lock, flags);
- nsecs = get_time() + local_offset;
- xtime.tv_sec = nsecs / NSEC_PER_SEC;
- xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC;
- write_sequnlock_irqrestore(&xtime_lock, flags);
-
- return(IRQ_HANDLED);
-}
-
-long um_time(int __user *tloc)
-{
- long ret = get_time() / NSEC_PER_SEC;
-
- if((tloc != NULL) && put_user(ret, tloc))
- return -EFAULT;
-
- return ret;
-}
-
-void do_gettimeofday(struct timeval *tv)
-{
- unsigned long long nsecs = get_time();
-
- tv->tv_sec = nsecs / NSEC_PER_SEC;
- /* Careful about calculations here - this was originally done as
- * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC
- * which gave bogus (> 1000000) values. Dunno why, suspect gcc
- * (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion
- * problem that I missed.
- */
- nsecs -= tv->tv_sec * NSEC_PER_SEC;
- tv->tv_usec = (unsigned long) nsecs / NSEC_PER_USEC;
-}
-
-static inline void set_time(unsigned long long nsecs)
-{
- unsigned long long now;
- unsigned long flags;
-
- spin_lock_irqsave(&timer_spinlock, flags);
- now = os_nsecs();
- local_offset = nsecs - now;
- spin_unlock_irqrestore(&timer_spinlock, flags);
-
- clock_was_set();
-}
-
-long um_stime(int __user *tptr)
-{
- int value;
-
- if (get_user(value, tptr))
- return -EFAULT;
-
- set_time((unsigned long long) value * NSEC_PER_SEC);
-
- return 0;
-}
-
-int do_settimeofday(struct timespec *tv)
-{
- set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec);
-
- return 0;
-}
-
-void timer_handler(int sig, union uml_pt_regs *regs)
-{
- local_irq_disable();
- irq_enter();
- update_process_times(CHOOSE_MODE(
- (UPT_SC(regs) && user_context(UPT_SP(regs))),
- (regs)->skas.is_user));
- irq_exit();
- local_irq_enable();
- if(current_thread->cpu == 0)
- timer_irq(regs);
-}
-
-int __init timer_init(void)
-{
- int err;
-
- user_time_init();
- err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", NULL);
- if(err != 0)
- printk(KERN_ERR "timer_init : request_irq failed - "
- "errno = %d\n", -err);
- timer_irq_inited = 1;
- return(0);
-}
-
-arch_initcall(timer_init);
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index f5b0636f9ad7..54a5ff25645a 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -16,12 +16,12 @@
#include "os.h"
static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
- int r, int w, int x, struct host_vm_op *ops, int *index,
+ int r, int w, int x, struct host_vm_op *ops, int *index,
int last_filled, union mm_context *mmu, void **flush,
int (*do_ops)(union mm_context *, struct host_vm_op *,
int, int, void **))
{
- __u64 offset;
+ __u64 offset;
struct host_vm_op *last;
int fd, ret = 0;
@@ -89,7 +89,7 @@ static int add_munmap(unsigned long addr, unsigned long len,
static int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
int x, struct host_vm_op *ops, int *index,
int last_filled, union mm_context *mmu, void **flush,
- int (*do_ops)(union mm_context *, struct host_vm_op *,
+ int (*do_ops)(union mm_context *, struct host_vm_op *,
int, int, void **))
{
struct host_vm_op *last;
@@ -124,105 +124,105 @@ static int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
#define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1))
void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
- unsigned long end_addr, int force,
+ unsigned long end_addr, int force,
int (*do_ops)(union mm_context *, struct host_vm_op *,
int, int, void **))
{
- pgd_t *npgd;
- pud_t *npud;
- pmd_t *npmd;
- pte_t *npte;
- union mm_context *mmu = &mm->context;
- unsigned long addr, end;
- int r, w, x;
- struct host_vm_op ops[1];
- void *flush = NULL;
- int op_index = -1, last_op = sizeof(ops) / sizeof(ops[0]) - 1;
- int ret = 0;
-
- if(mm == NULL) return;
-
- ops[0].type = NONE;
- for(addr = start_addr; addr < end_addr && !ret;){
- npgd = pgd_offset(mm, addr);
- if(!pgd_present(*npgd)){
- end = ADD_ROUND(addr, PGDIR_SIZE);
- if(end > end_addr)
- end = end_addr;
- if(force || pgd_newpage(*npgd)){
- ret = add_munmap(addr, end - addr, ops,
- &op_index, last_op, mmu,
- &flush, do_ops);
- pgd_mkuptodate(*npgd);
- }
- addr = end;
- continue;
- }
-
- npud = pud_offset(npgd, addr);
- if(!pud_present(*npud)){
- end = ADD_ROUND(addr, PUD_SIZE);
- if(end > end_addr)
- end = end_addr;
- if(force || pud_newpage(*npud)){
- ret = add_munmap(addr, end - addr, ops,
- &op_index, last_op, mmu,
- &flush, do_ops);
- pud_mkuptodate(*npud);
- }
- addr = end;
- continue;
- }
-
- npmd = pmd_offset(npud, addr);
- if(!pmd_present(*npmd)){
- end = ADD_ROUND(addr, PMD_SIZE);
- if(end > end_addr)
- end = end_addr;
- if(force || pmd_newpage(*npmd)){
- ret = add_munmap(addr, end - addr, ops,
- &op_index, last_op, mmu,
- &flush, do_ops);
- pmd_mkuptodate(*npmd);
- }
- addr = end;
- continue;
- }
-
- npte = pte_offset_kernel(npmd, addr);
- r = pte_read(*npte);
- w = pte_write(*npte);
- x = pte_exec(*npte);
+ pgd_t *npgd;
+ pud_t *npud;
+ pmd_t *npmd;
+ pte_t *npte;
+ union mm_context *mmu = &mm->context;
+ unsigned long addr, end;
+ int r, w, x;
+ struct host_vm_op ops[1];
+ void *flush = NULL;
+ int op_index = -1, last_op = ARRAY_SIZE(ops) - 1;
+ int ret = 0;
+
+ if(mm == NULL)
+ return;
+
+ ops[0].type = NONE;
+ for(addr = start_addr; addr < end_addr && !ret;){
+ npgd = pgd_offset(mm, addr);
+ if(!pgd_present(*npgd)){
+ end = ADD_ROUND(addr, PGDIR_SIZE);
+ if(end > end_addr)
+ end = end_addr;
+ if(force || pgd_newpage(*npgd)){
+ ret = add_munmap(addr, end - addr, ops,
+ &op_index, last_op, mmu,
+ &flush, do_ops);
+ pgd_mkuptodate(*npgd);
+ }
+ addr = end;
+ continue;
+ }
+
+ npud = pud_offset(npgd, addr);
+ if(!pud_present(*npud)){
+ end = ADD_ROUND(addr, PUD_SIZE);
+ if(end > end_addr)
+ end = end_addr;
+ if(force || pud_newpage(*npud)){
+ ret = add_munmap(addr, end - addr, ops,
+ &op_index, last_op, mmu,
+ &flush, do_ops);
+ pud_mkuptodate(*npud);
+ }
+ addr = end;
+ continue;
+ }
+
+ npmd = pmd_offset(npud, addr);
+ if(!pmd_present(*npmd)){
+ end = ADD_ROUND(addr, PMD_SIZE);
+ if(end > end_addr)
+ end = end_addr;
+ if(force || pmd_newpage(*npmd)){
+ ret = add_munmap(addr, end - addr, ops,
+ &op_index, last_op, mmu,
+ &flush, do_ops);
+ pmd_mkuptodate(*npmd);
+ }
+ addr = end;
+ continue;
+ }
+
+ npte = pte_offset_kernel(npmd, addr);
+ r = pte_read(*npte);
+ w = pte_write(*npte);
+ x = pte_exec(*npte);
if (!pte_young(*npte)) {
r = 0;
w = 0;
} else if (!pte_dirty(*npte)) {
w = 0;
}
- if(force || pte_newpage(*npte)){
- if(pte_present(*npte))
- ret = add_mmap(addr,
- pte_val(*npte) & PAGE_MASK,
- PAGE_SIZE, r, w, x, ops,
- &op_index, last_op, mmu,
- &flush, do_ops);
+ if(force || pte_newpage(*npte)){
+ if(pte_present(*npte))
+ ret = add_mmap(addr,
+ pte_val(*npte) & PAGE_MASK,
+ PAGE_SIZE, r, w, x, ops,
+ &op_index, last_op, mmu,
+ &flush, do_ops);
else ret = add_munmap(addr, PAGE_SIZE, ops,
&op_index, last_op, mmu,
&flush, do_ops);
- }
- else if(pte_newprot(*npte))
+ }
+ else if(pte_newprot(*npte))
ret = add_mprotect(addr, PAGE_SIZE, r, w, x, ops,
&op_index, last_op, mmu,
&flush, do_ops);
- *npte = pte_mkuptodate(*npte);
- addr += PAGE_SIZE;
- }
-
+ *npte = pte_mkuptodate(*npte);
+ addr += PAGE_SIZE;
+ }
if(!ret)
ret = (*do_ops)(mmu, ops, op_index, 1, &flush);
- /* This is not an else because ret is modified above */
+/* This is not an else because ret is modified above */
if(ret) {
printk("fix_range_common: failed, killing current process\n");
force_sig(SIGKILL, current);
@@ -231,160 +231,160 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
{
- struct mm_struct *mm;
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- unsigned long addr, last;
- int updated = 0, err;
-
- mm = &init_mm;
- for(addr = start; addr < end;){
- pgd = pgd_offset(mm, addr);
- if(!pgd_present(*pgd)){
- last = ADD_ROUND(addr, PGDIR_SIZE);
- if(last > end)
- last = end;
- if(pgd_newpage(*pgd)){
- updated = 1;
- err = os_unmap_memory((void *) addr,
- last - addr);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- }
- addr = last;
- continue;
- }
-
- pud = pud_offset(pgd, addr);
- if(!pud_present(*pud)){
- last = ADD_ROUND(addr, PUD_SIZE);
- if(last > end)
- last = end;
- if(pud_newpage(*pud)){
- updated = 1;
- err = os_unmap_memory((void *) addr,
- last - addr);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- }
- addr = last;
- continue;
- }
-
- pmd = pmd_offset(pud, addr);
- if(!pmd_present(*pmd)){
- last = ADD_ROUND(addr, PMD_SIZE);
- if(last > end)
- last = end;
- if(pmd_newpage(*pmd)){
- updated = 1;
- err = os_unmap_memory((void *) addr,
- last - addr);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- }
- addr = last;
- continue;
- }
-
- pte = pte_offset_kernel(pmd, addr);
- if(!pte_present(*pte) || pte_newpage(*pte)){
- updated = 1;
- err = os_unmap_memory((void *) addr,
- PAGE_SIZE);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- if(pte_present(*pte))
- map_memory(addr,
- pte_val(*pte) & PAGE_MASK,
- PAGE_SIZE, 1, 1, 1);
- }
- else if(pte_newprot(*pte)){
- updated = 1;
- os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1);
- }
- addr += PAGE_SIZE;
- }
- return(updated);
+ struct mm_struct *mm;
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long addr, last;
+ int updated = 0, err;
+
+ mm = &init_mm;
+ for(addr = start; addr < end;){
+ pgd = pgd_offset(mm, addr);
+ if(!pgd_present(*pgd)){
+ last = ADD_ROUND(addr, PGDIR_SIZE);
+ if(last > end)
+ last = end;
+ if(pgd_newpage(*pgd)){
+ updated = 1;
+ err = os_unmap_memory((void *) addr,
+ last - addr);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ }
+ addr = last;
+ continue;
+ }
+
+ pud = pud_offset(pgd, addr);
+ if(!pud_present(*pud)){
+ last = ADD_ROUND(addr, PUD_SIZE);
+ if(last > end)
+ last = end;
+ if(pud_newpage(*pud)){
+ updated = 1;
+ err = os_unmap_memory((void *) addr,
+ last - addr);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ }
+ addr = last;
+ continue;
+ }
+
+ pmd = pmd_offset(pud, addr);
+ if(!pmd_present(*pmd)){
+ last = ADD_ROUND(addr, PMD_SIZE);
+ if(last > end)
+ last = end;
+ if(pmd_newpage(*pmd)){
+ updated = 1;
+ err = os_unmap_memory((void *) addr,
+ last - addr);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ }
+ addr = last;
+ continue;
+ }
+
+ pte = pte_offset_kernel(pmd, addr);
+ if(!pte_present(*pte) || pte_newpage(*pte)){
+ updated = 1;
+ err = os_unmap_memory((void *) addr,
+ PAGE_SIZE);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ if(pte_present(*pte))
+ map_memory(addr,
+ pte_val(*pte) & PAGE_MASK,
+ PAGE_SIZE, 1, 1, 1);
+ }
+ else if(pte_newprot(*pte)){
+ updated = 1;
+ os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1);
+ }
+ addr += PAGE_SIZE;
+ }
+ return(updated);
}
pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address)
{
- return(pgd_offset(mm, address));
+ return(pgd_offset(mm, address));
}
pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address)
{
- return(pud_offset(pgd, address));
+ return(pud_offset(pgd, address));
}
pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address)
{
- return(pmd_offset(pud, address));
+ return(pmd_offset(pud, address));
}
pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address)
{
- return(pte_offset_kernel(pmd, address));
+ return(pte_offset_kernel(pmd, address));
}
pte_t *addr_pte(struct task_struct *task, unsigned long addr)
{
- pgd_t *pgd = pgd_offset(task->mm, addr);
- pud_t *pud = pud_offset(pgd, addr);
- pmd_t *pmd = pmd_offset(pud, addr);
+ pgd_t *pgd = pgd_offset(task->mm, addr);
+ pud_t *pud = pud_offset(pgd, addr);
+ pmd_t *pmd = pmd_offset(pud, addr);
- return(pte_offset_map(pmd, addr));
+ return(pte_offset_map(pmd, addr));
}
void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
{
- address &= PAGE_MASK;
- flush_tlb_range(vma, address, address + PAGE_SIZE);
+ address &= PAGE_MASK;
+ flush_tlb_range(vma, address, address + PAGE_SIZE);
}
void flush_tlb_all(void)
{
- flush_tlb_mm(current->mm);
+ flush_tlb_mm(current->mm);
}
void flush_tlb_kernel_range(unsigned long start, unsigned long end)
{
- CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt,
- flush_tlb_kernel_range_common, start, end);
+ CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt,
+ flush_tlb_kernel_range_common, start, end);
}
void flush_tlb_kernel_vm(void)
{
- CHOOSE_MODE(flush_tlb_kernel_vm_tt(),
- flush_tlb_kernel_range_common(start_vm, end_vm));
+ CHOOSE_MODE(flush_tlb_kernel_vm_tt(),
+ flush_tlb_kernel_range_common(start_vm, end_vm));
}
void __flush_tlb_one(unsigned long addr)
{
- CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr);
+ CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr);
}
void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end)
{
- CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start,
- end);
+ CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start,
+ end);
}
void flush_tlb_mm(struct mm_struct *mm)
{
- CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm);
+ CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm);
}
void force_flush_all(void)
{
- CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas());
+ CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas());
}
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap.c
index 02f6d4d8dc3a..c7b195c7e51f 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap.c
@@ -35,7 +35,7 @@
#include "os.h"
/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */
-int handle_page_fault(unsigned long address, unsigned long ip,
+int handle_page_fault(unsigned long address, unsigned long ip,
int is_write, int is_user, int *code_out)
{
struct mm_struct *mm = current->mm;
@@ -55,20 +55,20 @@ int handle_page_fault(unsigned long address, unsigned long ip,
down_read(&mm->mmap_sem);
vma = find_vma(mm, address);
- if(!vma)
+ if(!vma)
goto out;
- else if(vma->vm_start <= address)
+ else if(vma->vm_start <= address)
goto good_area;
- else if(!(vma->vm_flags & VM_GROWSDOWN))
+ else if(!(vma->vm_flags & VM_GROWSDOWN))
goto out;
else if(is_user && !ARCH_IS_STACKGROW(address))
goto out;
- else if(expand_stack(vma, address))
+ else if(expand_stack(vma, address))
goto out;
good_area:
*code_out = SEGV_ACCERR;
- if(is_write && !(vma->vm_flags & VM_WRITE))
+ if(is_write && !(vma->vm_flags & VM_WRITE))
goto out;
/* Don't require VM_READ|VM_EXEC for write faults! */
@@ -120,7 +120,7 @@ out_nosemaphore:
* us unable to handle the page fault gracefully.
*/
out_of_memory:
- if (current->pid == 1) {
+ if (is_init(current)) {
up_read(&mm->mmap_sem);
yield();
down_read(&mm->mmap_sem);
@@ -140,14 +140,6 @@ void segv_handler(int sig, union uml_pt_regs *regs)
segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
}
-struct kern_handlers handlinfo_kern = {
- .relay_signal = relay_signal,
- .winch = winch,
- .bus_handler = relay_signal,
- .page_fault = segv_handler,
- .sigio_handler = sigio_handler,
- .timer_handler = timer_handler
-};
/*
* We give a *copy* of the faultinfo in the regs to segv.
* This must be done, since nesting SEGVs could overwrite
@@ -184,14 +176,14 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
else if(catcher != NULL){
current->thread.fault_addr = (void *) address;
do_longjmp(catcher, 1);
- }
+ }
else if(current->thread.fault_addr != NULL)
panic("fault_addr set but no fault catcher");
else if(!is_user && arch_fixup(ip, sc))
return(0);
- if(!is_user)
- panic("Kernel mode fault at addr 0x%lx, ip 0x%lx",
+ if(!is_user)
+ panic("Kernel mode fault at addr 0x%lx, ip 0x%lx",
address, ip);
if (err == -EACCES) {
@@ -227,9 +219,16 @@ void bad_segv(struct faultinfo fi, unsigned long ip)
void relay_signal(int sig, union uml_pt_regs *regs)
{
- if(arch_handle_signal(sig, regs)) return;
- if(!UPT_IS_USER(regs))
+ if(arch_handle_signal(sig, regs))
+ return;
+
+ if(!UPT_IS_USER(regs)){
+ if(sig == SIGBUS)
+ printk("Bus error - the /dev/shm or /tmp mount likely "
+ "just ran out of space\n");
panic("Kernel mode signal %d", sig);
+ }
+
current->thread.arch.faultinfo = *UPT_FAULTINFO(regs);
force_sig(sig, current);
}
@@ -246,6 +245,15 @@ void winch(int sig, union uml_pt_regs *regs)
do_IRQ(WINCH_IRQ, regs);
}
+const struct kern_handlers handlinfo_kern = {
+ .relay_signal = relay_signal,
+ .winch = winch,
+ .bus_handler = bus_handler,
+ .page_fault = segv_handler,
+ .sigio_handler = sigio_handler,
+ .timer_handler = timer_handler
+};
+
void trap_init(void)
{
}
diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c
index 5c1e4cc1c049..ad66df17d9d7 100644
--- a/arch/um/kernel/tt/exec_kern.c
+++ b/arch/um/kernel/tt/exec_kern.c
@@ -21,7 +21,7 @@
static int exec_tramp(void *sig_stack)
{
init_new_thread_stack(sig_stack, NULL);
- init_new_thread_signals(1);
+ init_new_thread_signals();
os_stop_process(os_getpid());
return(0);
}
diff --git a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c
index bcb8796c3cb1..84a23b14f770 100644
--- a/arch/um/kernel/tt/mem.c
+++ b/arch/um/kernel/tt/mem.c
@@ -24,22 +24,13 @@ void before_mem_tt(unsigned long brk_start)
#define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000)
#define START (CONFIG_TOP_ADDR - SIZE)
-unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out,
- unsigned long *task_size_out)
+unsigned long set_task_sizes_tt(unsigned long *task_size_out)
{
+ unsigned long host_task_size;
+
/* Round up to the nearest 4M */
- *host_size_out = ROUND_4M((unsigned long) &arg);
+ host_task_size = ROUND_4M((unsigned long) &host_task_size);
*task_size_out = START;
- return(START);
-}
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+ return host_task_size;
+}
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index a9c1443fc548..1e86f0bfef72 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -119,7 +119,7 @@ void suspend_new_thread(int fd)
panic("read failed in suspend_new_thread, err = %d", -err);
}
-void schedule_tail(task_t *prev);
+void schedule_tail(struct task_struct *prev);
static void new_thread_handler(int sig)
{
@@ -142,7 +142,7 @@ static void new_thread_handler(int sig)
schedule_tail(current->thread.prev_sched);
current->thread.prev_sched = NULL;
- init_new_thread_signals(1);
+ init_new_thread_signals();
enable_timer();
free_page(current->thread.temp_stack);
set_cmdline("(kernel thread)");
diff --git a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c
index 3fda9a03c59a..293caa6d0c2d 100644
--- a/arch/um/kernel/tt/syscall_kern.c
+++ b/arch/um/kernel/tt/syscall_kern.c
@@ -21,18 +21,11 @@ void syscall_handler_tt(int sig, struct pt_regs *regs)
void *sc;
long result;
int syscall;
-#ifdef CONFIG_SYSCALL_DEBUG
- int index;
-#endif
+
sc = UPT_SC(&regs->regs);
SC_START_SYSCALL(sc);
syscall = UPT_SYSCALL_NR(&regs->regs);
-
-#ifdef CONFIG_SYSCALL_DEBUG
- index = record_syscall_start(syscall);
-#endif
-
syscall_trace(&regs->regs, 0);
current->thread.nsyscalls++;
@@ -50,7 +43,4 @@ void syscall_handler_tt(int sig, struct pt_regs *regs)
SC_SET_SYSCALL_RETURN(sc, result);
syscall_trace(&regs->regs, 1);
-#ifdef CONFIG_SYSCALL_DEBUG
- record_syscall_end(index, result);
-#endif
}
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
index 71daae24e48a..9882342206ec 100644
--- a/arch/um/kernel/tt/tracer.c
+++ b/arch/um/kernel/tt/tracer.c
@@ -188,10 +188,7 @@ int tracer(int (*init_proc)(void *), void *sp)
int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0;
int proc_id = 0, n, err, old_tracing = 0, strace = 0;
int local_using_sysemu = 0;
-#ifdef UML_CONFIG_SYSCALL_DEBUG
- unsigned long eip = 0;
- int last_index;
-#endif
+
signal(SIGPIPE, SIG_IGN);
setup_tracer_winch();
tracing_pid = os_getpid();
@@ -282,23 +279,6 @@ int tracer(int (*init_proc)(void *), void *sp)
else if(WIFSTOPPED(status)){
proc_id = pid_to_processor_id(pid);
sig = WSTOPSIG(status);
-#ifdef UML_CONFIG_SYSCALL_DEBUG
- if(signal_index[proc_id] == 1024){
- signal_index[proc_id] = 0;
- last_index = 1023;
- }
- else last_index = signal_index[proc_id] - 1;
- if(((sig == SIGPROF) || (sig == SIGVTALRM) ||
- (sig == SIGALRM)) &&
- (signal_record[proc_id][last_index].signal == sig)&&
- (signal_record[proc_id][last_index].pid == pid))
- signal_index[proc_id] = last_index;
- signal_record[proc_id][signal_index[proc_id]].pid = pid;
- gettimeofday(&signal_record[proc_id][signal_index[proc_id]].time, NULL);
- eip = ptrace(PTRACE_PEEKUSR, pid, PT_IP_OFFSET, 0);
- signal_record[proc_id][signal_index[proc_id]].addr = eip;
- signal_record[proc_id][signal_index[proc_id]++].signal = sig;
-#endif
if(proc_id == -1){
sleeping_process_signal(pid, sig);
continue;
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 7d51dd7201c3..55005710dcbb 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -106,7 +106,7 @@ static void c_stop(struct seq_file *m, void *v)
{
}
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
.start = c_start,
.next = c_next,
.stop = c_stop,
@@ -330,6 +330,8 @@ EXPORT_SYMBOL(end_iomem);
#define MIN_VMALLOC (32 * 1024 * 1024)
+extern char __binary_start;
+
int linux_main(int argc, char **argv)
{
unsigned long avail, diff;
@@ -374,8 +376,9 @@ int linux_main(int argc, char **argv)
printf("UML running in %s mode\n", mode);
- uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0,
- &host_task_size, &task_size);
+ uml_start = (unsigned long) &__binary_start;
+ host_task_size = CHOOSE_MODE_PROC(set_task_sizes_tt,
+ set_task_sizes_skas, &task_size);
/*
* Setting up handlers to 'sig_info' struct
@@ -395,7 +398,7 @@ int linux_main(int argc, char **argv)
physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
}
- uml_physmem = uml_start;
+ uml_physmem = uml_start & PAGE_MASK;
/* Reserve up to 4M after the current brk */
uml_reserved = ROUND_4M(brk_start) + (1 << 22);
@@ -495,6 +498,7 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
{
}
+#ifdef CONFIG_SMP
void alternatives_smp_module_add(struct module *mod, char *name,
void *locks, void *locks_end,
void *text, void *text_end)
@@ -504,3 +508,4 @@ void alternatives_smp_module_add(struct module *mod, char *name,
void alternatives_smp_module_del(struct module *mod)
{
}
+#endif
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index af11915ce0a8..8eca47a6ff08 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -7,13 +7,16 @@ jiffies = jiffies_64;
SECTIONS
{
- /*This must contain the right address - not quite the default ELF one.*/
+ /* This must contain the right address - not quite the default ELF one.*/
PROVIDE (__executable_start = START);
- . = START + SIZEOF_HEADERS;
+ /* Static binaries stick stuff here, like the sigreturn trampoline,
+ * invisibly to objdump. So, just make __binary_start equal to the very
+ * beginning of the executable, and if there are unmapped pages after this,
+ * they are forever unusable.
+ */
+ __binary_start = START;
- /* Used in arch/um/kernel/mem.c. Any memory between START and __binary_start
- * is remapped.*/
- __binary_start = .;
+ . = START + SIZEOF_HEADERS;
#ifdef MODE_TT
.remap_data : { UNMAP_PATH (.data .bss) }
diff --git a/arch/um/kernel/vmlinux.lds.S b/arch/um/kernel/vmlinux.lds.S
index 1660a769674b..f8aeb448aab6 100644
--- a/arch/um/kernel/vmlinux.lds.S
+++ b/arch/um/kernel/vmlinux.lds.S
@@ -1,4 +1,3 @@
-#include <linux/config.h>
#ifdef CONFIG_LD_SCRIPT_STATIC
#include "uml.lds.S"
#else
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index f4bfc4c7ccac..b4183929b32c 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -4,15 +4,19 @@
#
obj-y = aio.o elf_aux.o file.o helper.o irq.o main.o mem.o process.o sigio.o \
- signal.o start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o tls.o \
+ signal.o start_up.o time.o trap.o tty.o uaccess.o umid.o tls.o \
user_syms.o util.o drivers/ sys-$(SUBARCH)/
obj-$(CONFIG_MODE_SKAS) += skas/
+
+obj-$(CONFIG_MODE_TT) += tt.o
+user-objs-$(CONFIG_MODE_TT) += tt.o
+
obj-$(CONFIG_TTY_LOG) += tty_log.o
user-objs-$(CONFIG_TTY_LOG) += tty_log.o
USER_OBJS := $(user-objs-y) aio.o elf_aux.o file.o helper.o irq.o main.o mem.o \
- process.o sigio.o signal.o start_up.o time.o trap.o tt.o tty.o tls.o \
+ process.o sigio.o signal.o start_up.o time.o trap.o tty.o tls.o \
uaccess.o umid.o util.o
CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
diff --git a/arch/um/os-Linux/drivers/etap.h b/arch/um/os-Linux/drivers/etap.h
index b84f6c4740f7..57ecdaf2f67e 100644
--- a/arch/um/os-Linux/drivers/etap.h
+++ b/arch/um/os-Linux/drivers/etap.h
@@ -13,7 +13,7 @@ struct ethertap_data {
void *dev;
};
-extern struct net_user_info ethertap_user_info;
+extern const struct net_user_info ethertap_user_info;
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/arch/um/os-Linux/drivers/ethertap_kern.c b/arch/um/os-Linux/drivers/ethertap_kern.c
index 768606bec233..16385e2ada85 100644
--- a/arch/um/os-Linux/drivers/ethertap_kern.c
+++ b/arch/um/os-Linux/drivers/ethertap_kern.c
@@ -65,7 +65,7 @@ static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
return(net_send(fd, (*skb)->data, (*skb)->len));
}
-struct net_kern_info ethertap_kern_info = {
+const struct net_kern_info ethertap_kern_info = {
.init = etap_init,
.protocol = eth_protocol,
.read = etap_read,
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index 8f49507e64ef..f559bdf746e6 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -216,7 +216,7 @@ static void etap_del_addr(unsigned char *addr, unsigned char *netmask,
etap_close_addr(addr, netmask, &pri->control_fd);
}
-struct net_user_info ethertap_user_info = {
+const struct net_user_info ethertap_user_info = {
.init = etap_user_init,
.open = etap_open,
.close = etap_close,
diff --git a/arch/um/os-Linux/drivers/tuntap.h b/arch/um/os-Linux/drivers/tuntap.h
index 25d4a2868814..d3e8d3af6245 100644
--- a/arch/um/os-Linux/drivers/tuntap.h
+++ b/arch/um/os-Linux/drivers/tuntap.h
@@ -16,7 +16,7 @@ struct tuntap_data {
void *dev;
};
-extern struct net_user_info tuntap_user_info;
+extern const struct net_user_info tuntap_user_info;
#endif
diff --git a/arch/um/os-Linux/drivers/tuntap_kern.c b/arch/um/os-Linux/drivers/tuntap_kern.c
index 190009a6f89c..0edbac63c527 100644
--- a/arch/um/os-Linux/drivers/tuntap_kern.c
+++ b/arch/um/os-Linux/drivers/tuntap_kern.c
@@ -53,7 +53,7 @@ static int tuntap_write(int fd, struct sk_buff **skb,
return(net_write(fd, (*skb)->data, (*skb)->len));
}
-struct net_kern_info tuntap_kern_info = {
+const struct net_kern_info tuntap_kern_info = {
.init = tuntap_init,
.protocol = eth_protocol,
.read = tuntap_read,
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 87c3aa0252db..e846b23f7558 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -205,7 +205,7 @@ static int tuntap_set_mtu(int mtu, void *data)
return(mtu);
}
-struct net_user_info tuntap_user_info = {
+const struct net_user_info tuntap_user_info = {
.init = tuntap_user_init,
.open = tuntap_open,
.close = tuntap_close,
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index 09251338d99e..189fa677085a 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -18,6 +18,7 @@
#include "os.h"
#include "user.h"
#include "kern_util.h"
+#include "user_util.h"
static void copy_stat(struct uml_stat *dst, struct stat64 *src)
{
@@ -42,16 +43,13 @@ int os_stat_fd(const int fd, struct uml_stat *ubuf)
struct stat64 sbuf;
int err;
- do {
- err = fstat64(fd, &sbuf);
- } while((err < 0) && (errno == EINTR)) ;
-
+ CATCH_EINTR(err = fstat64(fd, &sbuf));
if(err < 0)
- return(-errno);
+ return -errno;
if(ubuf != NULL)
copy_stat(ubuf, &sbuf);
- return(err);
+ return err;
}
int os_stat_file(const char *file_name, struct uml_stat *ubuf)
@@ -64,11 +62,11 @@ int os_stat_file(const char *file_name, struct uml_stat *ubuf)
} while((err < 0) && (errno == EINTR)) ;
if(err < 0)
- return(-errno);
+ return -errno;
if(ubuf != NULL)
copy_stat(ubuf, &sbuf);
- return(err);
+ return err;
}
int os_access(const char* file, int mode)
@@ -80,9 +78,9 @@ int os_access(const char* file, int mode)
err = access(file, amode);
if(err < 0)
- return(-errno);
+ return -errno;
- return(0);
+ return 0;
}
void os_print_error(int error, const char* str)
@@ -99,9 +97,9 @@ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
err = ioctl(fd, cmd, arg);
if(err < 0)
- return(-errno);
+ return -errno;
- return(err);
+ return err;
}
int os_window_size(int fd, int *rows, int *cols)
@@ -109,12 +107,12 @@ int os_window_size(int fd, int *rows, int *cols)
struct winsize size;
if(ioctl(fd, TIOCGWINSZ, &size) < 0)
- return(-errno);
+ return -errno;
*rows = size.ws_row;
*cols = size.ws_col;
- return(0);
+ return 0;
}
int os_new_tty_pgrp(int fd, int pid)
@@ -125,16 +123,16 @@ int os_new_tty_pgrp(int fd, int pid)
if(tcsetpgrp(fd, pid) < 0)
return -errno;
- return(0);
+ return 0;
}
/* FIXME: ensure namebuf in os_get_if_name is big enough */
int os_get_ifname(int fd, char* namebuf)
{
if(ioctl(fd, SIOCGIFNAME, namebuf) < 0)
- return(-errno);
+ return -errno;
- return(0);
+ return 0;
}
int os_set_slip(int fd)
@@ -149,7 +147,7 @@ int os_set_slip(int fd)
if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
return -errno;
- return(0);
+ return 0;
}
int os_set_owner(int fd, int pid)
@@ -158,10 +156,10 @@ int os_set_owner(int fd, int pid)
int save_errno = errno;
if(fcntl(fd, F_GETOWN, 0) != pid)
- return(-save_errno);
+ return -save_errno;
}
- return(0);
+ return 0;
}
/* FIXME? moved wholesale from sigio_user.c to get fcntls out of that file */
@@ -192,9 +190,9 @@ int os_mode_fd(int fd, int mode)
} while((err < 0) && (errno==EINTR)) ;
if(err < 0)
- return(-errno);
+ return -errno;
- return(0);
+ return 0;
}
int os_file_type(char *file)
@@ -204,15 +202,21 @@ int os_file_type(char *file)
err = os_stat_file(file, &buf);
if(err < 0)
- return(err);
+ return err;
- if(S_ISDIR(buf.ust_mode)) return(OS_TYPE_DIR);
- else if(S_ISLNK(buf.ust_mode)) return(OS_TYPE_SYMLINK);
- else if(S_ISCHR(buf.ust_mode)) return(OS_TYPE_CHARDEV);
- else if(S_ISBLK(buf.ust_mode)) return(OS_TYPE_BLOCKDEV);
- else if(S_ISFIFO(buf.ust_mode)) return(OS_TYPE_FIFO);
- else if(S_ISSOCK(buf.ust_mode)) return(OS_TYPE_SOCK);
- else return(OS_TYPE_FILE);
+ if(S_ISDIR(buf.ust_mode))
+ return OS_TYPE_DIR;
+ else if(S_ISLNK(buf.ust_mode))
+ return OS_TYPE_SYMLINK;
+ else if(S_ISCHR(buf.ust_mode))
+ return OS_TYPE_CHARDEV;
+ else if(S_ISBLK(buf.ust_mode))
+ return OS_TYPE_BLOCKDEV;
+ else if(S_ISFIFO(buf.ust_mode))
+ return OS_TYPE_FIFO;
+ else if(S_ISSOCK(buf.ust_mode))
+ return OS_TYPE_SOCK;
+ else return OS_TYPE_FILE;
}
int os_file_mode(char *file, struct openflags *mode_out)
@@ -302,8 +306,8 @@ int os_seek_file(int fd, __u64 offset)
actual = lseek64(fd, offset, SEEK_SET);
if(actual != offset)
- return(-errno);
- return(0);
+ return -errno;
+ return 0;
}
static int fault_buffer(void *start, int len,
@@ -314,13 +318,13 @@ static int fault_buffer(void *start, int len,
for(i = 0; i < len; i += page){
if((*copy_proc)(start + i, &c, sizeof(c)))
- return(-EFAULT);
+ return -EFAULT;
}
if((len % page) != 0){
if((*copy_proc)(start + len - 1, &c, sizeof(c)))
- return(-EFAULT);
+ return -EFAULT;
}
- return(0);
+ return 0;
}
static int file_io(int fd, void *buf, int len,
@@ -334,26 +338,26 @@ static int file_io(int fd, void *buf, int len,
if((n < 0) && (errno == EFAULT)){
err = fault_buffer(buf, len, copy_user_proc);
if(err)
- return(err);
+ return err;
n = (*io_proc)(fd, buf, len);
}
} while((n < 0) && (errno == EINTR));
if(n < 0)
- return(-errno);
- return(n);
+ return -errno;
+ return n;
}
int os_read_file(int fd, void *buf, int len)
{
- return(file_io(fd, buf, len, (int (*)(int, void *, int)) read,
- copy_from_user_proc));
+ return file_io(fd, buf, len, (int (*)(int, void *, int)) read,
+ copy_from_user_proc);
}
int os_write_file(int fd, const void *buf, int len)
{
- return(file_io(fd, (void *) buf, len,
- (int (*)(int, void *, int)) write, copy_to_user_proc));
+ return file_io(fd, (void *) buf, len,
+ (int (*)(int, void *, int)) write, copy_to_user_proc);
}
int os_file_size(char *file, unsigned long long *size_out)
@@ -398,11 +402,11 @@ int os_file_modtime(char *file, unsigned long *modtime)
err = os_stat_file(file, &buf);
if(err < 0){
printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
- return(err);
+ return err;
}
*modtime = buf.ust_mtime;
- return(0);
+ return 0;
}
int os_get_exec_close(int fd, int* close_on_exec)
@@ -455,7 +459,7 @@ int os_pipe(int *fds, int stream, int close_on_exec)
if(err < 0)
goto error;
- return(0);
+ return 0;
error:
printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err);
@@ -486,12 +490,12 @@ int os_set_fd_async(int fd, int owner)
(fcntl(fd, F_SETOWN, owner) < 0)){
err = -errno;
printk("os_set_fd_async : Failed to fcntl F_SETOWN "
- "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd,
+ "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd,
owner, errno);
return err;
}
- return(0);
+ return 0;
}
int os_clear_fd_async(int fd)
@@ -500,8 +504,8 @@ int os_clear_fd_async(int fd)
flags &= ~(O_ASYNC | O_NONBLOCK);
if(fcntl(fd, F_SETFL, flags) < 0)
- return(-errno);
- return(0);
+ return -errno;
+ return 0;
}
int os_set_fd_block(int fd, int blocking)
@@ -516,7 +520,7 @@ int os_set_fd_block(int fd, int blocking)
if(fcntl(fd, F_SETFL, flags) < 0)
return -errno;
- return(0);
+ return 0;
}
int os_accept_connection(int fd)
@@ -524,9 +528,9 @@ int os_accept_connection(int fd)
int new;
new = accept(fd, NULL, 0);
- if(new < 0)
- return(-errno);
- return(new);
+ if(new < 0)
+ return -errno;
+ return new;
}
#ifndef SHUT_RD
@@ -550,12 +554,12 @@ int os_shutdown_socket(int fd, int r, int w)
else if(w) what = SHUT_WR;
else {
printk("os_shutdown_socket : neither r or w was set\n");
- return(-EINVAL);
+ return -EINVAL;
}
err = shutdown(fd, what);
if(err < 0)
- return(-errno);
- return(0);
+ return -errno;
+ return 0;
}
int os_rcv_fd(int fd, int *helper_pid_out)
@@ -578,7 +582,7 @@ int os_rcv_fd(int fd, int *helper_pid_out)
n = recvmsg(fd, &msg, 0);
if(n < 0)
- return(-errno);
+ return -errno;
else if(n != sizeof(iov.iov_len))
*helper_pid_out = -1;
@@ -586,16 +590,16 @@ int os_rcv_fd(int fd, int *helper_pid_out)
cmsg = CMSG_FIRSTHDR(&msg);
if(cmsg == NULL){
printk("rcv_fd didn't receive anything, error = %d\n", errno);
- return(-1);
+ return -1;
}
- if((cmsg->cmsg_level != SOL_SOCKET) ||
+ if((cmsg->cmsg_level != SOL_SOCKET) ||
(cmsg->cmsg_type != SCM_RIGHTS)){
printk("rcv_fd didn't receive a descriptor\n");
- return(-1);
+ return -1;
}
new = ((int *) CMSG_DATA(cmsg))[0];
- return(new);
+ return new;
}
int os_create_unix_socket(char *file, int len, int close_on_exec)
@@ -623,7 +627,7 @@ int os_create_unix_socket(char *file, int len, int close_on_exec)
if(err < 0)
return -errno;
- return(sock);
+ return sock;
}
void os_flush_stdout(void)
@@ -654,16 +658,5 @@ int os_lock_file(int fd, int excl)
printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid);
err = save;
out:
- return(err);
+ return err;
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 6987d1d247a2..cd15b9df5b5c 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -42,7 +42,7 @@ static int helper_child(void *arg)
if(data->pre_exec != NULL)
(*data->pre_exec)(data->pre_data);
execvp(argv[0], argv);
- errval = errno;
+ errval = -errno;
printk("helper_child - execve of '%s' failed - errno = %d\n", argv[0], errno);
os_write_file(data->fd, &errval, sizeof(errval));
kill(os_getpid(), SIGKILL);
@@ -62,7 +62,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
stack = *stack_out;
else stack = alloc_stack(0, __cant_sleep());
if(stack == 0)
- return(-ENOMEM);
+ return -ENOMEM;
ret = os_pipe(fds, 1, 0);
if(ret < 0){
@@ -95,16 +95,16 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
/* Read the errno value from the child, if the exec failed, or get 0 if
* the exec succeeded because the pipe fd was set as close-on-exec. */
n = os_read_file(fds[0], &ret, sizeof(ret));
- if (n < 0) {
- printk("run_helper : read on pipe failed, ret = %d\n", -n);
- ret = n;
- kill(pid, SIGKILL);
- CATCH_EINTR(waitpid(pid, NULL, 0));
- } else if(n != 0){
- CATCH_EINTR(n = waitpid(pid, NULL, 0));
- ret = -errno;
- } else {
+ if(n == 0)
ret = pid;
+ else {
+ if(n < 0){
+ printk("run_helper : read on pipe failed, ret = %d\n",
+ -n);
+ ret = n;
+ kill(pid, SIGKILL);
+ }
+ CATCH_EINTR(waitpid(pid, NULL, 0));
}
out_close:
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
index 3788d4568d33..a97206df5b52 100644
--- a/arch/um/os-Linux/irq.c
+++ b/arch/um/os-Linux/irq.c
@@ -52,11 +52,6 @@ int os_waiting_for_events(struct irq_fd *active_fds)
return n;
}
-int os_isatty(int fd)
-{
- return isatty(fd);
-}
-
int os_create_pollfd(int fd, int events, void *tmp_pfd, int size_tmpfds)
{
if (pollfds_num == pollfds_size) {
@@ -137,22 +132,19 @@ void os_set_pollfd(int i, int fd)
void os_set_ioignore(void)
{
- set_handler(SIGIO, SIG_IGN, 0, -1);
+ signal(SIGIO, SIG_IGN);
}
void init_irq_signals(int on_sigstack)
{
- __sighandler_t h;
int flags;
flags = on_sigstack ? SA_ONSTACK : 0;
- if (timer_irq_inited)
- h = (__sighandler_t)alarm_handler;
- else
- h = boot_timer_handler;
- set_handler(SIGVTALRM, h, flags | SA_RESTART,
- SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1);
+ set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
+ flags | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1);
+ set_handler(SIGALRM, (__sighandler_t) alarm_handler,
+ flags | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1);
set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
signal(SIGWINCH, SIG_IGN);
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 90912aaca7aa..d1c5670787dc 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -67,13 +67,32 @@ static __init void do_uml_initcalls(void)
static void last_ditch_exit(int sig)
{
- signal(SIGINT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
- signal(SIGHUP, SIG_DFL);
uml_cleanup();
exit(1);
}
+static void install_fatal_handler(int sig)
+{
+ struct sigaction action;
+
+ /* All signals are enabled in this handler ... */
+ sigemptyset(&action.sa_mask);
+
+ /* ... including the signal being handled, plus we want the
+ * handler reset to the default behavior, so that if an exit
+ * handler is hanging for some reason, the UML will just die
+ * after this signal is sent a second time.
+ */
+ action.sa_flags = SA_RESETHAND | SA_NODEFER;
+ action.sa_restorer = NULL;
+ action.sa_handler = last_ditch_exit;
+ if(sigaction(sig, &action, NULL) < 0){
+ printf("failed to install handler for signal %d - errno = %d\n",
+ errno);
+ exit(1);
+ }
+}
+
#define UML_LIB_PATH ":/usr/lib/uml"
static void setup_env_path(void)
@@ -158,9 +177,12 @@ int main(int argc, char **argv, char **envp)
}
new_argv[argc] = NULL;
- set_handler(SIGINT, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
- set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
- set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
+ /* Allow these signals to bring down a UML if all other
+ * methods of control fail.
+ */
+ install_fatal_handler(SIGINT);
+ install_fatal_handler(SIGTERM);
+ install_fatal_handler(SIGHUP);
scan_elf_aux( envp);
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index c6432e729241..4203681e508d 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -55,7 +55,7 @@ static void __init find_tempdir(void)
*/
static int next(int fd, char *buf, int size, char c)
{
- int n;
+ int n, len;
char *ptr;
while((ptr = strchr(buf, c)) == NULL){
@@ -69,7 +69,17 @@ static int next(int fd, char *buf, int size, char c)
}
ptr++;
- memmove(buf, ptr, strlen(ptr) + 1);
+ len = strlen(ptr);
+ memmove(buf, ptr, len + 1);
+
+ /* Refill the buffer so that if there's a partial string that we care
+ * about, it will be completed, and we can recognize it.
+ */
+ n = read(fd, &buf[len], size - len - 1);
+ if(n < 0)
+ return -errno;
+
+ buf[len + n] = '\0';
return 1;
}
@@ -104,14 +114,14 @@ static void which_tmpdir(void)
}
while(1){
- found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
+ found = next(fd, buf, ARRAY_SIZE(buf), ' ');
if(found != 1)
break;
if(!strncmp(buf, "/dev/shm", strlen("/dev/shm")))
goto found;
- found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), '\n');
+ found = next(fd, buf, ARRAY_SIZE(buf), '\n');
if(found != 1)
break;
}
@@ -122,20 +132,24 @@ err:
else if(found < 0)
printf("read returned errno %d\n", -found);
+out:
+ close(fd);
+
return;
found:
- found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
+ found = next(fd, buf, ARRAY_SIZE(buf), ' ');
if(found != 1)
goto err;
if(strncmp(buf, "tmpfs", strlen("tmpfs"))){
printf("not tmpfs\n");
- return;
+ goto out;
}
printf("OK\n");
default_tmpdir = "/dev/shm";
+ goto out;
}
/*
@@ -200,8 +214,11 @@ int create_tmp_file(unsigned long long len)
exit(1);
}
- if (lseek64(fd, len, SEEK_SET) < 0) {
- perror("os_seek_file");
+ /* Seek to len - 1 because writing a character there will
+ * increase the file size by one byte, to the desired length.
+ */
+ if (lseek64(fd, len - 1, SEEK_SET) < 0) {
+ perror("os_seek_file");
exit(1);
}
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 233be2f4f8cb..ff203625a4bd 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -7,7 +7,6 @@
#include <stdio.h>
#include <errno.h>
#include <signal.h>
-#include <setjmp.h>
#include <linux/unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
@@ -247,39 +246,48 @@ void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
set_sigstack(sig_stack, pages * page_size());
flags = SA_ONSTACK;
}
- if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1);
+ if(usr1_handler){
+ struct sigaction sa;
+
+ sa.sa_handler = usr1_handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = flags;
+ sa.sa_restorer = NULL;
+ if(sigaction(SIGUSR1, &sa, NULL) < 0)
+ panic("init_new_thread_stack - sigaction failed - "
+ "errno = %d\n", errno);
+ }
}
-void init_new_thread_signals(int altstack)
+void init_new_thread_signals(void)
{
- int flags = altstack ? SA_ONSTACK : 0;
-
- set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags,
+ set_handler(SIGSEGV, (__sighandler_t) sig_handler, SA_ONSTACK,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
- set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags,
+ set_handler(SIGTRAP, (__sighandler_t) sig_handler, SA_ONSTACK,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
- set_handler(SIGFPE, (__sighandler_t) sig_handler, flags,
+ set_handler(SIGFPE, (__sighandler_t) sig_handler, SA_ONSTACK,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
- set_handler(SIGILL, (__sighandler_t) sig_handler, flags,
+ set_handler(SIGILL, (__sighandler_t) sig_handler, SA_ONSTACK,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
- set_handler(SIGBUS, (__sighandler_t) sig_handler, flags,
+ set_handler(SIGBUS, (__sighandler_t) sig_handler, SA_ONSTACK,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
set_handler(SIGUSR2, (__sighandler_t) sig_handler,
- flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
+ SA_ONSTACK, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM,
+ -1);
signal(SIGHUP, SIG_IGN);
- init_irq_signals(altstack);
+ init_irq_signals(1);
}
int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
{
jmp_buf buf;
- int n, enable;
+ int n;
*jmp_ptr = &buf;
- n = UML_SETJMP(&buf, enable);
+ n = UML_SETJMP(&buf);
if(n != 0)
- return(n);
+ return n;
(*fn)(arg);
- return(0);
+ return 0;
}
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 00e9388e947a..f6457765b17d 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -43,17 +43,9 @@ struct pollfds {
/* Protected by sigio_lock(). Used by the sigio thread, but the UML thread
* synchronizes with it.
*/
-struct pollfds current_poll = {
- .poll = NULL,
- .size = 0,
- .used = 0
-};
-
-struct pollfds next_poll = {
- .poll = NULL,
- .size = 0,
- .used = 0
-};
+static struct pollfds current_poll;
+static struct pollfds next_poll;
+static struct pollfds all_sigio_fds;
static int write_sigio_thread(void *unused)
{
@@ -78,7 +70,8 @@ static int write_sigio_thread(void *unused)
n = os_read_file(sigio_private[1], &c, sizeof(c));
if(n != sizeof(c))
printk("write_sigio_thread : "
- "read failed, err = %d\n", -n);
+ "read on socket failed, "
+ "err = %d\n", -n);
tmp = current_poll;
current_poll = next_poll;
next_poll = tmp;
@@ -93,35 +86,36 @@ static int write_sigio_thread(void *unused)
n = os_write_file(respond_fd, &c, sizeof(c));
if(n != sizeof(c))
- printk("write_sigio_thread : write failed, "
- "err = %d\n", -n);
+ printk("write_sigio_thread : write on socket "
+ "failed, err = %d\n", -n);
}
}
return 0;
}
-static int need_poll(int n)
+static int need_poll(struct pollfds *polls, int n)
{
- if(n <= next_poll.size){
- next_poll.used = n;
- return(0);
+ if(n <= polls->size){
+ polls->used = n;
+ return 0;
}
- kfree(next_poll.poll);
- next_poll.poll = um_kmalloc_atomic(n * sizeof(struct pollfd));
- if(next_poll.poll == NULL){
+ kfree(polls->poll);
+ polls->poll = um_kmalloc_atomic(n * sizeof(struct pollfd));
+ if(polls->poll == NULL){
printk("need_poll : failed to allocate new pollfds\n");
- next_poll.size = 0;
- next_poll.used = 0;
- return(-1);
+ polls->size = 0;
+ polls->used = 0;
+ return -ENOMEM;
}
- next_poll.size = n;
- next_poll.used = n;
- return(0);
+ polls->size = n;
+ polls->used = n;
+ return 0;
}
/* Must be called with sigio_lock held, because it's needed by the marked
- * critical section. */
+ * critical section.
+ */
static void update_thread(void)
{
unsigned long flags;
@@ -156,34 +150,39 @@ static void update_thread(void)
set_signals(flags);
}
-int add_sigio_fd(int fd, int read)
+int add_sigio_fd(int fd)
{
- int err = 0, i, n, events;
+ struct pollfd *p;
+ int err = 0, 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;
+
+ p = &all_sigio_fds.poll[i];
+
for(i = 0; i < current_poll.used; i++){
if(current_poll.poll[i].fd == fd)
goto out;
}
n = current_poll.used + 1;
- err = need_poll(n);
+ err = need_poll(&next_poll, n);
if(err)
goto out;
for(i = 0; i < current_poll.used; i++)
next_poll.poll[i] = current_poll.poll[i];
- if(read) events = POLLIN;
- else events = POLLOUT;
-
- next_poll.poll[n - 1] = ((struct pollfd) { .fd = fd,
- .events = events,
- .revents = 0 });
+ next_poll.poll[n - 1] = *p;
update_thread();
out:
sigio_unlock();
- return(err);
+ return err;
}
int ignore_sigio_fd(int fd)
@@ -191,6 +190,13 @@ int ignore_sigio_fd(int fd)
struct pollfd *p;
int err = 0, i, n = 0;
+ /* This is called from exitcalls elsewhere in UML - if
+ * sigio_cleanup has already run, then update_thread will hang
+ * or fail because the thread is no longer running.
+ */
+ 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;
@@ -198,24 +204,20 @@ int ignore_sigio_fd(int fd)
if(i == current_poll.used)
goto out;
- err = need_poll(current_poll.used - 1);
+ err = need_poll(&next_poll, current_poll.used - 1);
if(err)
goto out;
for(i = 0; i < current_poll.used; i++){
p = &current_poll.poll[i];
- if(p->fd != fd) next_poll.poll[n++] = current_poll.poll[i];
- }
- if(n == i){
- printk("ignore_sigio_fd : fd %d not found\n", fd);
- err = -1;
- goto out;
+ if(p->fd != fd)
+ next_poll.poll[n++] = *p;
}
update_thread();
out:
sigio_unlock();
- return(err);
+ return err;
}
static struct pollfd *setup_initial_poll(int fd)
@@ -227,13 +229,13 @@ static struct pollfd *setup_initial_poll(int fd)
printk("setup_initial_poll : failed to allocate poll\n");
return NULL;
}
- *p = ((struct pollfd) { .fd = fd,
+ *p = ((struct pollfd) { .fd = fd,
.events = POLLIN,
.revents = 0 });
return p;
}
-void write_sigio_workaround(void)
+static void write_sigio_workaround(void)
{
unsigned long stack;
struct pollfd *p;
@@ -314,10 +316,38 @@ out_close1:
close(l_write_sigio_fds[1]);
}
-void sigio_cleanup(void)
+void maybe_sigio_broken(int fd, int read)
+{
+ int err;
+
+ if(!isatty(fd))
+ return;
+
+ if((read || pty_output_sigio) && (!read || pty_close_sigio))
+ return;
+
+ write_sigio_workaround();
+
+ sigio_lock();
+ err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1);
+ if(err){
+ printk("maybe_sigio_broken - failed to add pollfd\n");
+ goto out;
+ }
+ all_sigio_fds.poll[all_sigio_fds.used++] =
+ ((struct pollfd) { .fd = fd,
+ .events = read ? POLLIN : POLLOUT,
+ .revents = 0 });
+out:
+ sigio_unlock();
+}
+
+static void sigio_cleanup(void)
{
if(write_sigio_pid != -1){
os_kill_process(write_sigio_pid, 1);
write_sigio_pid = -1;
}
}
+
+__uml_exitcall(sigio_cleanup);
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index f11b3124a0c8..6b81739279d1 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -15,7 +15,6 @@
#include "user.h"
#include "signal_kern.h"
#include "sysdep/sigcontext.h"
-#include "sysdep/signal.h"
#include "sigcontext.h"
#include "mode.h"
#include "os.h"
@@ -38,18 +37,10 @@
static int signals_enabled = 1;
static int pending = 0;
-void sig_handler(ARCH_SIGHDLR_PARAM)
+void sig_handler(int sig, struct sigcontext *sc)
{
- struct sigcontext *sc;
int enabled;
- /* Must be the first thing that this handler does - x86_64 stores
- * the sigcontext in %rdx, and we need to save it before it has a
- * chance to get trashed.
- */
-
- ARCH_GET_SIGCONTEXT(sc, sig);
-
enabled = signals_enabled;
if(!enabled && (sig == SIGIO)){
pending |= SIGIO_MASK;
@@ -64,15 +55,8 @@ void sig_handler(ARCH_SIGHDLR_PARAM)
set_signals(enabled);
}
-extern int timer_irq_inited;
-
static void real_alarm_handler(int sig, struct sigcontext *sc)
{
- if(!timer_irq_inited){
- signals_enabled = 1;
- return;
- }
-
if(sig == SIGALRM)
switch_timers(0);
@@ -84,13 +68,10 @@ static void real_alarm_handler(int sig, struct sigcontext *sc)
}
-void alarm_handler(ARCH_SIGHDLR_PARAM)
+void alarm_handler(int sig, struct sigcontext *sc)
{
- struct sigcontext *sc;
int enabled;
- ARCH_GET_SIGCONTEXT(sc, sig);
-
enabled = signals_enabled;
if(!signals_enabled){
if(sig == SIGVTALRM)
@@ -106,29 +87,6 @@ void alarm_handler(ARCH_SIGHDLR_PARAM)
set_signals(enabled);
}
-extern void do_boot_timer_handler(struct sigcontext * sc);
-
-void boot_timer_handler(ARCH_SIGHDLR_PARAM)
-{
- struct sigcontext *sc;
- int enabled;
-
- ARCH_GET_SIGCONTEXT(sc, sig);
-
- enabled = signals_enabled;
- if(!enabled){
- if(sig == SIGVTALRM)
- pending |= SIGVTALRM_MASK;
- else pending |= SIGALRM_MASK;
- return;
- }
-
- block_signals();
-
- do_boot_timer_handler(sc);
- set_signals(enabled);
-}
-
void set_sigstack(void *sig_stack, int size)
{
stack_t stack = ((stack_t) { .ss_flags = 0,
@@ -149,6 +107,10 @@ void remove_sigstack(void)
panic("disabling signal stack failed, errno = %d\n", errno);
}
+void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
+
+extern void hard_handler(int sig);
+
void set_handler(int sig, void (*handler)(int), int flags, ...)
{
struct sigaction action;
@@ -156,13 +118,16 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
sigset_t sig_mask;
int mask;
- va_start(ap, flags);
- action.sa_handler = handler;
+ handlers[sig] = (void (*)(int, struct sigcontext *)) handler;
+ action.sa_handler = hard_handler;
+
sigemptyset(&action.sa_mask);
- while((mask = va_arg(ap, int)) != -1){
+
+ va_start(ap, flags);
+ while((mask = va_arg(ap, int)) != -1)
sigaddset(&action.sa_mask, mask);
- }
va_end(ap);
+
action.sa_flags = flags;
action.sa_restorer = NULL;
if(sigaction(sig, &action, NULL) < 0)
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index bd89c6b99d5d..cb9ab54146cc 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -8,7 +8,6 @@
#include <unistd.h>
#include <errno.h>
#include <signal.h>
-#include <setjmp.h>
#include <sched.h>
#include "ptrace_user.h"
#include <sys/wait.h>
@@ -156,11 +155,15 @@ extern int __syscall_stub_start;
static int userspace_tramp(void *stack)
{
void *addr;
+ int err;
ptrace(PTRACE_TRACEME, 0, 0, 0);
- init_new_thread_signals(1);
- enable_timer();
+ init_new_thread_signals();
+ err = set_interval(1);
+ if(err)
+ panic("userspace_tramp - setting timer failed, errno = %d\n",
+ err);
if(!proc_mm){
/* This has a pte, but it can't be mapped in with the usual
@@ -190,14 +193,25 @@ static int userspace_tramp(void *stack)
}
}
if(!ptrace_faultinfo && (stack != NULL)){
+ struct sigaction sa;
+
unsigned long v = UML_CONFIG_STUB_CODE +
(unsigned long) stub_segv_handler -
(unsigned long) &__syscall_stub_start;
set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size());
- set_handler(SIGSEGV, (void *) v, SA_ONSTACK,
- SIGIO, SIGWINCH, SIGALRM, SIGVTALRM,
- SIGUSR1, -1);
+ sigemptyset(&sa.sa_mask);
+ sigaddset(&sa.sa_mask, SIGIO);
+ sigaddset(&sa.sa_mask, SIGWINCH);
+ sigaddset(&sa.sa_mask, SIGALRM);
+ sigaddset(&sa.sa_mask, SIGVTALRM);
+ sigaddset(&sa.sa_mask, SIGUSR1);
+ sa.sa_flags = SA_ONSTACK;
+ sa.sa_handler = (void *) v;
+ sa.sa_restorer = NULL;
+ if(sigaction(SIGSEGV, &sa, NULL) < 0)
+ panic("userspace_tramp - setting SIGSEGV handler "
+ "failed - errno = %d\n", errno);
}
os_stop_process(os_getpid());
@@ -430,59 +444,22 @@ void map_stub_pages(int fd, unsigned long code,
}
}
-void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
- void (*handler)(int))
+void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
{
- unsigned long flags;
- jmp_buf switch_buf, fork_buf;
- int enable;
-
- *switch_buf_ptr = &switch_buf;
- *fork_buf_ptr = &fork_buf;
-
- /* Somewhat subtle - siglongjmp restores the signal mask before doing
- * the longjmp. This means that when jumping from one stack to another
- * when the target stack has interrupts enabled, an interrupt may occur
- * on the source stack. This is bad when starting up a process because
- * it's not supposed to get timer ticks until it has been scheduled.
- * So, we disable interrupts around the sigsetjmp to ensure that
- * they can't happen until we get back here where they are safe.
- */
- flags = get_signals();
- block_signals();
- if(UML_SETJMP(&fork_buf, enable) == 0)
- new_thread_proc(stack, handler);
-
- remove_sigstack();
-
- set_signals(flags);
+ (*buf)[0].JB_IP = (unsigned long) handler;
+ (*buf)[0].JB_SP = (unsigned long) stack +
+ (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - sizeof(void *);
}
#define INIT_JMP_NEW_THREAD 0
-#define INIT_JMP_REMOVE_SIGSTACK 1
-#define INIT_JMP_CALLBACK 2
-#define INIT_JMP_HALT 3
-#define INIT_JMP_REBOOT 4
+#define INIT_JMP_CALLBACK 1
+#define INIT_JMP_HALT 2
+#define INIT_JMP_REBOOT 3
-void thread_wait(void *sw, void *fb)
+void switch_threads(jmp_buf *me, jmp_buf *you)
{
- jmp_buf buf, **switch_buf = sw, *fork_buf;
- int enable;
-
- *switch_buf = &buf;
- fork_buf = fb;
- if(UML_SETJMP(&buf, enable) == 0)
- siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
-}
-
-void switch_threads(void *me, void *next)
-{
- jmp_buf my_buf, **me_ptr = me, *next_buf = next;
- int enable;
-
- *me_ptr = &my_buf;
- if(UML_SETJMP(&my_buf, enable) == 0)
- UML_LONGJMP(next_buf, 1);
+ if(UML_SETJMP(me) == 0)
+ UML_LONGJMP(you, 1);
}
static jmp_buf initial_jmpbuf;
@@ -492,23 +469,21 @@ static void (*cb_proc)(void *arg);
static void *cb_arg;
static jmp_buf *cb_back;
-int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
+int start_idle_thread(void *stack, jmp_buf *switch_buf)
{
- jmp_buf **switch_buf = switch_buf_ptr;
- int n, enable;
+ int n;
set_handler(SIGWINCH, (__sighandler_t) sig_handler,
SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
SIGVTALRM, -1);
- *fork_buf_ptr = &initial_jmpbuf;
- n = UML_SETJMP(&initial_jmpbuf, enable);
+ n = UML_SETJMP(&initial_jmpbuf);
switch(n){
case INIT_JMP_NEW_THREAD:
- new_thread_proc((void *) stack, new_thread_handler);
- break;
- case INIT_JMP_REMOVE_SIGSTACK:
- remove_sigstack();
+ (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler;
+ (*switch_buf)[0].JB_SP = (unsigned long) stack +
+ (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) -
+ sizeof(void *);
break;
case INIT_JMP_CALLBACK:
(*cb_proc)(cb_arg);
@@ -523,20 +498,19 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
default:
panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
}
- UML_LONGJMP(*switch_buf, 1);
+ UML_LONGJMP(switch_buf, 1);
}
void initial_thread_cb_skas(void (*proc)(void *), void *arg)
{
jmp_buf here;
- int enable;
cb_proc = proc;
cb_arg = arg;
cb_back = &here;
block_signals();
- if(UML_SETJMP(&here, enable) == 0)
+ if(UML_SETJMP(&here) == 0)
UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
unblock_signals();
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 503148504009..7fe92680c7dd 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -14,7 +14,6 @@
#include <sched.h>
#include <fcntl.h>
#include <errno.h>
-#include <setjmp.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/mman.h>
diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile
index b3213613c41c..37806621b25d 100644
--- a/arch/um/os-Linux/sys-i386/Makefile
+++ b/arch/um/os-Linux/sys-i386/Makefile
@@ -3,7 +3,7 @@
# Licensed under the GPL
#
-obj-$(CONFIG_MODE_SKAS) = registers.o tls.o
+obj-$(CONFIG_MODE_SKAS) = registers.o signal.o tls.o
USER_OBJS := $(obj-y)
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
index 516f66dd87e3..7cd0369e02b3 100644
--- a/arch/um/os-Linux/sys-i386/registers.c
+++ b/arch/um/os-Linux/sys-i386/registers.c
@@ -5,12 +5,12 @@
#include <errno.h>
#include <string.h>
-#include <setjmp.h>
#include "sysdep/ptrace_user.h"
#include "sysdep/ptrace.h"
#include "uml-config.h"
#include "skas_ptregs.h"
#include "registers.h"
+#include "longjmp.h"
#include "user.h"
/* These are set once at boot time and not changed thereafter */
@@ -130,11 +130,14 @@ void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)
HOST_FP_SIZE * sizeof(unsigned long));
}
-void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer)
+unsigned long get_thread_reg(int reg, jmp_buf *buf)
{
- struct __jmp_buf_tag *jmpbuf = buffer;
-
- UPT_SET(uml_regs, EIP, jmpbuf->__jmpbuf[JB_PC]);
- UPT_SET(uml_regs, UESP, jmpbuf->__jmpbuf[JB_SP]);
- UPT_SET(uml_regs, EBP, jmpbuf->__jmpbuf[JB_BP]);
+ switch(reg){
+ case EIP: return buf[0]->__eip;
+ case UESP: return buf[0]->__esp;
+ case EBP: return buf[0]->__ebp;
+ default:
+ printk("get_thread_regs - unknown register %d\n", reg);
+ return 0;
+ }
}
diff --git a/arch/um/os-Linux/sys-i386/signal.c b/arch/um/os-Linux/sys-i386/signal.c
new file mode 100644
index 000000000000..0d3eae518352
--- /dev/null
+++ b/arch/um/os-Linux/sys-i386/signal.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include <signal.h>
+
+extern void (*handlers[])(int sig, struct sigcontext *sc);
+
+void hard_handler(int sig)
+{
+ struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
+
+ (*handlers[sig])(sig, sc);
+}
diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile
index 340ef26f5944..f67842a7735b 100644
--- a/arch/um/os-Linux/sys-x86_64/Makefile
+++ b/arch/um/os-Linux/sys-x86_64/Makefile
@@ -3,7 +3,7 @@
# Licensed under the GPL
#
-obj-$(CONFIG_MODE_SKAS) = registers.o
+obj-$(CONFIG_MODE_SKAS) = registers.o signal.o
USER_OBJS := $(obj-y)
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
index becd898d9398..cb8e8a263280 100644
--- a/arch/um/os-Linux/sys-x86_64/registers.c
+++ b/arch/um/os-Linux/sys-x86_64/registers.c
@@ -5,11 +5,11 @@
#include <errno.h>
#include <string.h>
-#include <setjmp.h>
#include "ptrace_user.h"
#include "uml-config.h"
#include "skas_ptregs.h"
#include "registers.h"
+#include "longjmp.h"
#include "user.h"
/* These are set once at boot time and not changed thereafter */
@@ -78,11 +78,14 @@ void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)
HOST_FP_SIZE * sizeof(unsigned long));
}
-void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer)
+unsigned long get_thread_reg(int reg, jmp_buf *buf)
{
- struct __jmp_buf_tag *jmpbuf = buffer;
-
- UPT_SET(uml_regs, RIP, jmpbuf->__jmpbuf[JB_PC]);
- UPT_SET(uml_regs, RSP, jmpbuf->__jmpbuf[JB_RSP]);
- UPT_SET(uml_regs, RBP, jmpbuf->__jmpbuf[JB_RBP]);
+ switch(reg){
+ case RIP: return buf[0]->__rip;
+ case RSP: return buf[0]->__rsp;
+ case RBP: return buf[0]->__rbp;
+ default:
+ printk("get_thread_regs - unknown register %d\n", reg);
+ return 0;
+ }
}
diff --git a/arch/um/os-Linux/sys-x86_64/signal.c b/arch/um/os-Linux/sys-x86_64/signal.c
new file mode 100644
index 000000000000..3f369e5f976b
--- /dev/null
+++ b/arch/um/os-Linux/sys-x86_64/signal.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include <signal.h>
+
+extern void (*handlers[])(int sig, struct sigcontext *sc);
+
+void hard_handler(int sig)
+{
+ struct ucontext *uc;
+ asm("movq %%rdx, %0" : "=r" (uc));
+
+ (*handlers[sig])(sig, (struct sigcontext *) &uc->uc_mcontext);
+}
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index 280c4fb9b585..38be096e750f 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -17,25 +17,25 @@
#include "kern_constants.h"
#include "os.h"
-/* XXX This really needs to be declared and initialized in a kernel file since
- * it's in <linux/time.h>
- */
-extern struct timespec wall_to_monotonic;
-
-static void set_interval(int timer_type)
+int set_interval(int is_virtual)
{
int usec = 1000000/hz();
+ int timer_type = is_virtual ? ITIMER_VIRTUAL : ITIMER_REAL;
struct itimerval interval = ((struct itimerval) { { 0, usec },
{ 0, usec } });
if(setitimer(timer_type, &interval, NULL) == -1)
- panic("setitimer failed - errno = %d\n", errno);
+ return -errno;
+
+ return 0;
}
+#ifdef CONFIG_MODE_TT
void enable_timer(void)
{
- set_interval(ITIMER_VIRTUAL);
+ set_interval(1);
}
+#endif
void disable_timer(void)
{
@@ -45,8 +45,8 @@ void disable_timer(void)
printk("disnable_timer - setitimer failed, errno = %d\n",
errno);
/* If there are signals already queued, after unblocking ignore them */
- set_handler(SIGALRM, SIG_IGN, 0, -1);
- set_handler(SIGVTALRM, SIG_IGN, 0, -1);
+ signal(SIGALRM, SIG_IGN);
+ signal(SIGVTALRM, SIG_IGN);
}
void switch_timers(int to_real)
@@ -71,6 +71,7 @@ void switch_timers(int to_real)
errno);
}
+#ifdef UML_CONFIG_MODE_TT
void uml_idle_timer(void)
{
if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
@@ -78,16 +79,9 @@ void uml_idle_timer(void)
set_handler(SIGALRM, (__sighandler_t) alarm_handler,
SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
- set_interval(ITIMER_REAL);
-}
-
-void time_init(void)
-{
- if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR)
- panic("Couldn't set SIGVTALRM handler");
- set_interval(ITIMER_VIRTUAL);
- time_init_kern();
+ set_interval(0);
}
+#endif
unsigned long long os_nsecs(void)
{
@@ -105,16 +99,3 @@ void idle_sleep(int secs)
ts.tv_nsec = 0;
nanosleep(&ts, NULL);
}
-
-/* XXX This partly duplicates init_irq_signals */
-
-void user_time_init(void)
-{
- set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
- SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
- SIGALRM, SIGUSR2, -1);
- set_handler(SIGALRM, (__sighandler_t) alarm_handler,
- SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
- SIGVTALRM, SIGUSR2, -1);
- set_interval(ITIMER_VIRTUAL);
-}
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
index 90b29ae9af46..1df231a26244 100644
--- a/arch/um/os-Linux/trap.c
+++ b/arch/um/os-Linux/trap.c
@@ -5,7 +5,6 @@
#include <stdlib.h>
#include <signal.h>
-#include <setjmp.h>
#include "kern_util.h"
#include "user_util.h"
#include "os.h"
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
index e523719330b2..bbb73a650370 100644
--- a/arch/um/os-Linux/uaccess.c
+++ b/arch/um/os-Linux/uaccess.c
@@ -4,8 +4,7 @@
* Licensed under the GPL
*/
-#include <setjmp.h>
-#include <string.h>
+#include <stddef.h>
#include "longjmp.h"
unsigned long __do_user_copy(void *to, const void *from, int n,
@@ -14,11 +13,10 @@ unsigned long __do_user_copy(void *to, const void *from, int n,
int n), int *faulted_out)
{
unsigned long *faddrp = (unsigned long *) fault_addr, ret;
- int enable;
jmp_buf jbuf;
*fault_catcher = &jbuf;
- if(UML_SETJMP(&jbuf, enable) == 0){
+ if(UML_SETJMP(&jbuf) == 0){
(*op)(to, from, n);
ret = 0;
*faulted_out = 0;
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index 362db059fe30..48092b95c8ab 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -67,32 +67,53 @@ err:
return err;
}
-static int actually_do_remove(char *dir)
+/*
+ * Unlinks the files contained in @dir and then removes @dir.
+ * Doesn't handle directory trees, so it's not like rm -rf, but almost such. We
+ * ignore ENOENT errors for anything (they happen, strangely enough - possibly due
+ * to races between multiple dying UML threads).
+ */
+static int remove_files_and_dir(char *dir)
{
DIR *directory;
struct dirent *ent;
int len;
char file[256];
+ int ret;
directory = opendir(dir);
- if(directory == NULL)
- return -errno;
+ if (directory == NULL) {
+ if (errno != ENOENT)
+ return -errno;
+ else
+ return 0;
+ }
- while((ent = readdir(directory)) != NULL){
- if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
+ while ((ent = readdir(directory)) != NULL) {
+ if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
continue;
len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1;
- if(len > sizeof(file))
- return -E2BIG;
+ if (len > sizeof(file)) {
+ ret = -E2BIG;
+ goto out;
+ }
sprintf(file, "%s/%s", dir, ent->d_name);
- if(unlink(file) < 0)
- return -errno;
+ if (unlink(file) < 0 && errno != ENOENT) {
+ ret = -errno;
+ goto out;
+ }
}
- if(rmdir(dir) < 0)
- return -errno;
- return 0;
+ if (rmdir(dir) < 0 && errno != ENOENT) {
+ ret = -errno;
+ goto out;
+ }
+
+ ret = 0;
+out:
+ closedir(directory);
+ return ret;
}
/* This says that there isn't already a user of the specified directory even if
@@ -103,9 +124,10 @@ static int actually_do_remove(char *dir)
* something other than UML sticking stuff in the directory
* this boot racing with a shutdown of the other UML
* In any of these cases, the directory isn't useful for anything else.
+ *
+ * Boolean return: 1 if in use, 0 otherwise.
*/
-
-static int not_dead_yet(char *dir)
+static inline int is_umdir_used(char *dir)
{
char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
char pid[sizeof("nnnnn\0")], *end;
@@ -113,7 +135,7 @@ static int not_dead_yet(char *dir)
n = snprintf(file, sizeof(file), "%s/pid", dir);
if(n >= sizeof(file)){
- printk("not_dead_yet - pid filename too long\n");
+ printk("is_umdir_used - pid filename too long\n");
err = -E2BIG;
goto out;
}
@@ -123,7 +145,7 @@ static int not_dead_yet(char *dir)
if(fd < 0) {
fd = -errno;
if(fd != -ENOENT){
- printk("not_dead_yet : couldn't open pid file '%s', "
+ printk("is_umdir_used : couldn't open pid file '%s', "
"err = %d\n", file, -fd);
}
goto out;
@@ -132,18 +154,18 @@ static int not_dead_yet(char *dir)
err = 0;
n = read(fd, pid, sizeof(pid));
if(n < 0){
- printk("not_dead_yet : couldn't read pid file '%s', "
+ printk("is_umdir_used : couldn't read pid file '%s', "
"err = %d\n", file, errno);
goto out_close;
} else if(n == 0){
- printk("not_dead_yet : couldn't read pid file '%s', "
+ printk("is_umdir_used : couldn't read pid file '%s', "
"0-byte read\n", file);
goto out_close;
}
p = strtoul(pid, &end, 0);
if(end == pid){
- printk("not_dead_yet : couldn't parse pid file '%s', "
+ printk("is_umdir_used : couldn't parse pid file '%s', "
"errno = %d\n", file, errno);
goto out_close;
}
@@ -153,19 +175,32 @@ static int not_dead_yet(char *dir)
return 1;
}
- err = actually_do_remove(dir);
- if(err)
- printk("not_dead_yet - actually_do_remove failed with "
- "err = %d\n", err);
-
- return err;
-
out_close:
close(fd);
out:
return 0;
}
+/*
+ * Try to remove the directory @dir unless it's in use.
+ * Precondition: @dir exists.
+ * Returns 0 for success, < 0 for failure in removal or if the directory is in
+ * use.
+ */
+static int umdir_take_if_dead(char *dir)
+{
+ int ret;
+ if (is_umdir_used(dir))
+ return -EEXIST;
+
+ ret = remove_files_and_dir(dir);
+ if (ret) {
+ printk("is_umdir_used - remove_files_and_dir failed with "
+ "err = %d\n", ret);
+ }
+ return ret;
+}
+
static void __init create_pid_file(void)
{
char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
@@ -244,11 +279,7 @@ int __init make_umid(void)
if(err != -EEXIST)
goto err;
- /* 1 -> this umid is already in use
- * < 0 -> we couldn't remove the umid directory
- * In either case, we can't use this umid, so return -EEXIST.
- */
- if(not_dead_yet(tmp) != 0)
+ if (umdir_take_if_dead(tmp) < 0)
goto err;
err = mkdir(tmp, 0777);
@@ -344,9 +375,9 @@ static void remove_umid_dir(void)
char dir[strlen(uml_dir) + UMID_LEN + 1], err;
sprintf(dir, "%s%s", uml_dir, umid);
- err = actually_do_remove(dir);
+ err = remove_files_and_dir(dir);
if(err)
- printf("remove_umid_dir - actually_do_remove failed with "
+ printf("remove_umid_dir - remove_files_and_dir failed with "
"err = %d\n", err);
}
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index c47a2a7ce70e..3f5b1514e8a7 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -7,7 +7,6 @@
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
-#include <setjmp.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/utsname.h>
@@ -107,11 +106,11 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...)
jmp_buf buf;
int n;
- n = sigsetjmp(buf, 1);
+ n = UML_SETJMP(&buf);
if(n == 0){
va_start(args, proc);
(*proc)(&buf, &args);
}
va_end(args);
- return(n);
+ return n;
}
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index 1347dc6d5218..813077fb1e5b 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -8,7 +8,7 @@ USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS))
USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
$(USER_OBJS:.o=.%): \
- c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(*F).o)
+ c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(basetarget).o)
$(USER_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
-Dunix -D__unix__ -D__$(SUBARCH)__
@@ -17,7 +17,7 @@ $(USER_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
UNPROFILE_OBJS := $(foreach file,$(UNPROFILE_OBJS),$(obj)/$(file))
$(UNPROFILE_OBJS:.o=.%): \
- c_flags = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS)) $(CFLAGS_$(*F).o)
+ c_flags = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS)) $(CFLAGS_$(basetarget).o)
$(UNPROFILE_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
-Dunix -D__unix__ -D__$(SUBARCH)__
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 374d61a19439..0e32adf03be1 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -1,10 +1,10 @@
obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
- ptrace_user.o signal.o sigcontext.o syscalls.o sysrq.o \
+ ptrace_user.o setjmp.o signal.o sigcontext.o syscalls.o sysrq.o \
sys_call_table.o tls.o
obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
-subarch-obj-y = lib/bitops.o kernel/semaphore.o
+subarch-obj-y = lib/bitops.o lib/semaphore.o
subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem.o
subarch-obj-$(CONFIG_MODULES) += kernel/module.o
diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c
index 41b0ab2fe830..f1bcd399ac90 100644
--- a/arch/um/sys-i386/bugs.c
+++ b/arch/um/sys-i386/bugs.c
@@ -13,6 +13,7 @@
#include "sysdep/ptrace.h"
#include "task.h"
#include "os.h"
+#include "user_util.h"
#define MAXTOKEN 64
@@ -104,17 +105,17 @@ int cpu_feature(char *what, char *buf, int len)
static int check_cpu_flag(char *feature, int *have_it)
{
char buf[MAXTOKEN], c;
- int fd, len = sizeof(buf)/sizeof(buf[0]);
+ int fd, len = ARRAY_SIZE(buf);
printk("Checking for host processor %s support...", feature);
fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
if(fd < 0){
printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
- return(0);
+ return 0;
}
*have_it = 0;
- if(!find_cpuinfo_line(fd, "flags", buf, sizeof(buf) / sizeof(buf[0])))
+ if(!find_cpuinfo_line(fd, "flags", buf, ARRAY_SIZE(buf)))
goto out;
c = token(fd, buf, len - 1, ' ');
@@ -138,7 +139,7 @@ static int check_cpu_flag(char *feature, int *have_it)
if(*have_it == 0) printk("No\n");
else if(*have_it == 1) printk("Yes\n");
os_close_file(fd);
- return(1);
+ return 1;
}
#if 0 /* This doesn't work in tt mode, plus it's causing compilation problems
diff --git a/arch/um/sys-i386/checksum.S b/arch/um/sys-i386/checksum.S
index d98b2fff3d08..62c7e564f22e 100644
--- a/arch/um/sys-i386/checksum.S
+++ b/arch/um/sys-i386/checksum.S
@@ -25,7 +25,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <asm/errno.h>
/*
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index fe0877b3509c..69971b78beaf 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -424,9 +424,8 @@ void ldt_get_host_info(void)
size++;
}
- if(size < sizeof(dummy_list)/sizeof(dummy_list[0])) {
+ if(size < ARRAY_SIZE(dummy_list))
host_ldt_entries = dummy_list;
- }
else {
size = (size + 1) * sizeof(dummy_list[0]);
host_ldt_entries = (short *)kmalloc(size, GFP_KERNEL);
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c
index 6028bc7cc01b..28bf01150323 100644
--- a/arch/um/sys-i386/ptrace.c
+++ b/arch/um/sys-i386/ptrace.c
@@ -3,7 +3,6 @@
* Licensed under the GPL
*/
-#include <linux/config.h>
#include <linux/compiler.h>
#include "linux/sched.h"
#include "linux/mm.h"
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c
index 40aa88531446..5f3cc6685820 100644
--- a/arch/um/sys-i386/ptrace_user.c
+++ b/arch/um/sys-i386/ptrace_user.c
@@ -15,6 +15,7 @@
#include "user.h"
#include "os.h"
#include "uml-config.h"
+#include "user_util.h"
int ptrace_getregs(long pid, unsigned long *regs_out)
{
@@ -51,7 +52,7 @@ static void write_debugregs(int pid, unsigned long *regs)
int nregs, i;
dummy = NULL;
- nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]);
+ nregs = ARRAY_SIZE(dummy->u_debugreg);
for(i = 0; i < nregs; i++){
if((i == 4) || (i == 5)) continue;
if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i],
@@ -68,7 +69,7 @@ static void read_debugregs(int pid, unsigned long *regs)
int nregs, i;
dummy = NULL;
- nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]);
+ nregs = ARRAY_SIZE(dummy->u_debugreg);
for(i = 0; i < nregs; i++){
regs[i] = ptrace(PTRACE_PEEKUSR, pid,
&dummy->u_debugreg[i], 0);
diff --git a/arch/um/sys-i386/setjmp.S b/arch/um/sys-i386/setjmp.S
new file mode 100644
index 000000000000..b766792c9933
--- /dev/null
+++ b/arch/um/sys-i386/setjmp.S
@@ -0,0 +1,58 @@
+#
+# arch/i386/setjmp.S
+#
+# setjmp/longjmp for the i386 architecture
+#
+
+#
+# The jmp_buf is assumed to contain the following, in order:
+# %ebx
+# %esp
+# %ebp
+# %esi
+# %edi
+# <return address>
+#
+
+ .text
+ .align 4
+ .globl setjmp
+ .type setjmp, @function
+setjmp:
+#ifdef _REGPARM
+ movl %eax,%edx
+#else
+ movl 4(%esp),%edx
+#endif
+ popl %ecx # Return address, and adjust the stack
+ xorl %eax,%eax # Return value
+ movl %ebx,(%edx)
+ movl %esp,4(%edx) # Post-return %esp!
+ pushl %ecx # Make the call/return stack happy
+ movl %ebp,8(%edx)
+ movl %esi,12(%edx)
+ movl %edi,16(%edx)
+ movl %ecx,20(%edx) # Return address
+ ret
+
+ .size setjmp,.-setjmp
+
+ .text
+ .align 4
+ .globl longjmp
+ .type longjmp, @function
+longjmp:
+#ifdef _REGPARM
+ xchgl %eax,%edx
+#else
+ movl 4(%esp),%edx # jmp_ptr address
+ movl 8(%esp),%eax # Return value
+#endif
+ movl (%edx),%ebx
+ movl 4(%edx),%esp
+ movl 8(%edx),%ebp
+ movl 12(%edx),%esi
+ movl 16(%edx),%edi
+ jmp *20(%edx)
+
+ .size longjmp,.-longjmp
diff --git a/arch/um/sys-i386/sys_call_table.S b/arch/um/sys-i386/sys_call_table.S
index 1ff61474b25c..2497554b7b95 100644
--- a/arch/um/sys-i386/sys_call_table.S
+++ b/arch/um/sys-i386/sys_call_table.S
@@ -7,8 +7,6 @@
#define sys_vm86old sys_ni_syscall
#define sys_vm86 sys_ni_syscall
-#define sys_stime um_stime
-#define sys_time um_time
#define old_mmap old_mmap_i386
#include "../../i386/kernel/syscall_table.S"
diff --git a/arch/um/sys-ppc/misc.S b/arch/um/sys-ppc/misc.S
index f0c971db47e4..1364b7da578c 100644
--- a/arch/um/sys-ppc/misc.S
+++ b/arch/um/sys-ppc/misc.S
@@ -15,7 +15,6 @@
*
*/
-#include <linux/config.h>
#include <asm/processor.h>
#include "ppc_asm.h"
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index c19794d435d6..f41768b8e25e 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -5,8 +5,8 @@
#
obj-y = bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \
- sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o ksyms.o \
- tls.o
+ setjmp.o sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o \
+ ksyms.o tls.o
obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
obj-$(CONFIG_MODULES) += um_module.o
diff --git a/arch/um/sys-x86_64/setjmp.S b/arch/um/sys-x86_64/setjmp.S
new file mode 100644
index 000000000000..45f547b4043e
--- /dev/null
+++ b/arch/um/sys-x86_64/setjmp.S
@@ -0,0 +1,54 @@
+#
+# arch/x86_64/setjmp.S
+#
+# setjmp/longjmp for the x86-64 architecture
+#
+
+#
+# The jmp_buf is assumed to contain the following, in order:
+# %rbx
+# %rsp (post-return)
+# %rbp
+# %r12
+# %r13
+# %r14
+# %r15
+# <return address>
+#
+
+ .text
+ .align 4
+ .globl setjmp
+ .type setjmp, @function
+setjmp:
+ pop %rsi # Return address, and adjust the stack
+ xorl %eax,%eax # Return value
+ movq %rbx,(%rdi)
+ movq %rsp,8(%rdi) # Post-return %rsp!
+ push %rsi # Make the call/return stack happy
+ movq %rbp,16(%rdi)
+ movq %r12,24(%rdi)
+ movq %r13,32(%rdi)
+ movq %r14,40(%rdi)
+ movq %r15,48(%rdi)
+ movq %rsi,56(%rdi) # Return address
+ ret
+
+ .size setjmp,.-setjmp
+
+ .text
+ .align 4
+ .globl longjmp
+ .type longjmp, @function
+longjmp:
+ movl %esi,%eax # Return value (int)
+ movq (%rdi),%rbx
+ movq 8(%rdi),%rsp
+ movq 16(%rdi),%rbp
+ movq 24(%rdi),%r12
+ movq 32(%rdi),%r13
+ movq 40(%rdi),%r14
+ movq 48(%rdi),%r15
+ jmp *56(%rdi)
+
+ .size longjmp,.-longjmp
diff --git a/arch/um/sys-x86_64/syscall_table.c b/arch/um/sys-x86_64/syscall_table.c
index 34b2e842864f..9e9ad72c2ba4 100644
--- a/arch/um/sys-x86_64/syscall_table.c
+++ b/arch/um/sys-x86_64/syscall_table.c
@@ -4,7 +4,6 @@
#include <linux/linkage.h>
#include <linux/sys.h>
#include <linux/cache.h>
-#include <linux/config.h>
#define __NO_STUBS
@@ -20,12 +19,6 @@
/*#define sys_set_thread_area sys_ni_syscall
#define sys_get_thread_area sys_ni_syscall*/
-/* For __NR_time. The x86-64 name hopefully will change from sys_time64 to
- * sys_time (since the current situation is bogus). I've sent a patch to cleanup
- * this. Remove below the obsoleted line. */
-#define sys_time64 um_time
-#define sys_time um_time
-
/* On UML we call it this way ("old" means it's not mmap2) */
#define sys_mmap old_mmap
/* On x86-64 sys_uname is actually sys_newuname plus a compatibility trick.