aboutsummaryrefslogtreecommitdiff
path: root/arch/um
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/Kconfig.char6
-rw-r--r--arch/um/drivers/chan_user.c1
-rw-r--r--arch/um/drivers/cow_sys.h2
-rw-r--r--arch/um/drivers/daemon_user.c4
-rw-r--r--arch/um/drivers/fd.c2
-rw-r--r--arch/um/drivers/hostaudio_kern.c2
-rw-r--r--arch/um/drivers/line.c4
-rw-r--r--arch/um/drivers/mcast_user.c3
-rw-r--r--arch/um/drivers/net_user.c2
-rw-r--r--arch/um/drivers/port_user.c2
-rw-r--r--arch/um/drivers/pty.c2
-rw-r--r--arch/um/drivers/random.c122
-rw-r--r--arch/um/drivers/slip_user.c2
-rw-r--r--arch/um/drivers/tty.c2
-rw-r--r--arch/um/drivers/ubd_kern.c4
-rw-r--r--arch/um/drivers/xterm.c2
-rw-r--r--arch/um/include/as-layout.h14
-rw-r--r--arch/um/include/line.h6
-rw-r--r--arch/um/include/os.h1
-rw-r--r--arch/um/include/process.h20
-rw-r--r--arch/um/include/skas_ptrace.h13
-rw-r--r--arch/um/include/sysdep-i386/ptrace_user.h30
-rw-r--r--arch/um/include/sysdep-i386/sigcontext.h2
-rw-r--r--arch/um/include/sysdep-x86_64/ptrace_user.h17
-rw-r--r--arch/um/include/um_malloc.h9
-rw-r--r--arch/um/kernel/dyn.lds.S7
-rw-r--r--arch/um/kernel/exitcode.c2
-rw-r--r--arch/um/kernel/mem.c5
-rw-r--r--arch/um/kernel/process.c2
-rw-r--r--arch/um/kernel/syscall.c17
-rw-r--r--arch/um/kernel/time.c7
-rw-r--r--arch/um/kernel/um_arch.c7
-rw-r--r--arch/um/kernel/uml.lds.S7
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c4
-rw-r--r--arch/um/os-Linux/helper.c4
-rw-r--r--arch/um/os-Linux/main.c2
-rw-r--r--arch/um/os-Linux/sigio.c39
-rw-r--r--arch/um/os-Linux/signal.c1
-rw-r--r--arch/um/os-Linux/skas/process.c2
-rw-r--r--arch/um/os-Linux/start_up.c81
-rw-r--r--arch/um/os-Linux/sys-i386/registers.c5
-rw-r--r--arch/um/os-Linux/time.c54
-rw-r--r--arch/um/sys-i386/ptrace.c30
-rw-r--r--arch/um/sys-i386/user-offsets.c2
-rw-r--r--arch/um/sys-x86_64/user-offsets.c1
45 files changed, 289 insertions, 264 deletions
diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char
index 3a4b396d797..1b238ebae6b 100644
--- a/arch/um/Kconfig.char
+++ b/arch/um/Kconfig.char
@@ -145,14 +145,14 @@ config LEGACY_PTYS
systems, it is safe to say N.
config RAW_DRIVER
- tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)"
+ tristate "RAW driver (/dev/raw/rawN)"
+ depends on BLOCK
help
The raw driver permits block devices to be bound to /dev/raw/rawN.
Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O.
See the raw(8) manpage for more details.
- The raw driver is deprecated and will be removed soon.
- Applications should simply open the device (eg /dev/hda1)
+ Applications should preferably open the device (eg /dev/hda1)
with the O_DIRECT flag.
config MAX_RAW_DEVS
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index 025764089ac..cfeb3f4a44a 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -11,6 +11,7 @@
#include <termios.h>
#include <sys/ioctl.h>
#include "chan_user.h"
+#include "kern_constants.h"
#include "os.h"
#include "um_malloc.h"
#include "user.h"
diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h
index ca8c9e11a39..f5701fd2ef9 100644
--- a/arch/um/drivers/cow_sys.h
+++ b/arch/um/drivers/cow_sys.h
@@ -8,7 +8,7 @@
static inline void *cow_malloc(int size)
{
- return kmalloc(size, UM_GFP_KERNEL);
+ return uml_kmalloc(size, UM_GFP_KERNEL);
}
static inline void cow_free(void *ptr)
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index f23c109a055..f8e85e0bdac 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -34,7 +34,7 @@ static struct sockaddr_un *new_addr(void *name, int len)
{
struct sockaddr_un *sun;
- sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
+ sun = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
if (sun == NULL) {
printk(UM_KERN_ERR "new_addr: allocation of sockaddr_un "
"failed\n");
@@ -83,7 +83,7 @@ static int connect_to_switch(struct daemon_data *pri)
goto out_close;
}
- sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
+ sun = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
if (sun == NULL) {
printk(UM_KERN_ERR "new_addr: allocation of sockaddr_un "
"failed\n");
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index 0a2bb5b64b8..f5a981a1624 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -40,7 +40,7 @@ static void *fd_init(char *str, int device, const struct chan_opts *opts)
return NULL;
}
- data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
+ data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
if (data == NULL)
return NULL;
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
index ff1b22b69e9..368219cc236 100644
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -154,7 +154,7 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file,
case SNDCTL_DSP_SUBDIVIDE:
case SNDCTL_DSP_SETFRAGMENT:
if (get_user(data, (int __user *) arg))
- return EFAULT;
+ return -EFAULT;
break;
default:
break;
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 10b86e1cc65..5047490fc29 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -191,9 +191,9 @@ void line_flush_chars(struct tty_struct *tty)
line_flush_buffer(tty);
}
-void line_put_char(struct tty_struct *tty, unsigned char ch)
+int line_put_char(struct tty_struct *tty, unsigned char ch)
{
- line_write(tty, &ch, sizeof(ch));
+ return line_write(tty, &ch, sizeof(ch));
}
int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
index 5f647d7a729..ee19e91568a 100644
--- a/arch/um/drivers/mcast_user.c
+++ b/arch/um/drivers/mcast_user.c
@@ -15,6 +15,7 @@
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
+#include "kern_constants.h"
#include "mcast.h"
#include "net_user.h"
#include "um_malloc.h"
@@ -24,7 +25,7 @@ static struct sockaddr_in *new_addr(char *addr, unsigned short port)
{
struct sockaddr_in *sin;
- sin = kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL);
+ sin = uml_kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL);
if (sin == NULL) {
printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in "
"failed\n");
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index abf2653f551..9415dd9e63e 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -222,7 +222,7 @@ static void change(char *dev, char *what, unsigned char *addr,
netmask[2], netmask[3]);
output_len = UM_KERN_PAGE_SIZE;
- output = kmalloc(output_len, UM_GFP_KERNEL);
+ output = uml_kmalloc(output_len, UM_GFP_KERNEL);
if (output == NULL)
printk(UM_KERN_ERR "change : failed to allocate output "
"buffer\n");
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index d269ca387f1..b49bf56a56a 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -47,7 +47,7 @@ static void *port_init(char *str, int device, const struct chan_opts *opts)
if (kern_data == NULL)
return NULL;
- data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
+ data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
if (data == NULL)
goto err;
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
index 49c79dda604..1113911dcb2 100644
--- a/arch/um/drivers/pty.c
+++ b/arch/um/drivers/pty.c
@@ -29,7 +29,7 @@ static void *pty_chan_init(char *str, int device, const struct chan_opts *opts)
{
struct pty_chan *data;
- data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
+ data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
if (data == NULL)
return NULL;
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index 71f0959c153..4949044773b 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2005 Jeff Dike <jdike@addtoit.com> */
+/* Copyright (C) 2005 - 2008 Jeff Dike <jdike@{linux.intel,addtoit}.com> */
+
/* Much of this ripped from drivers/char/hw_random.c, see there for other
* copyright.
*
@@ -8,16 +9,18 @@
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/fs.h>
+#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
+#include "irq_kern.h"
#include "os.h"
/*
* core module and version information
*/
#define RNG_VERSION "1.0.0"
-#define RNG_MODULE_NAME "random"
+#define RNG_MODULE_NAME "hw_random"
#define RNG_MISCDEV_MINOR 183 /* official */
@@ -26,47 +29,67 @@
* protects against a module being loaded twice at the same time.
*/
static int random_fd = -1;
+static DECLARE_WAIT_QUEUE_HEAD(host_read_wait);
static int rng_dev_open (struct inode *inode, struct file *filp)
{
/* enforce read-only access to this chrdev */
if ((filp->f_mode & FMODE_READ) == 0)
return -EINVAL;
- if (filp->f_mode & FMODE_WRITE)
+ if ((filp->f_mode & FMODE_WRITE) != 0)
return -EINVAL;
return 0;
}
+static atomic_t host_sleep_count = ATOMIC_INIT(0);
+
static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
- loff_t * offp)
+ loff_t *offp)
{
- u32 data;
- int n, ret = 0, have_data;
-
- while(size){
- n = os_read_file(random_fd, &data, sizeof(data));
- if(n > 0){
- have_data = n;
- while (have_data && size) {
- if (put_user((u8)data, buf++)) {
- ret = ret ? : -EFAULT;
- break;
- }
- size--;
- ret++;
- have_data--;
- data>>=8;
- }
- }
- else if(n == -EAGAIN){
- if (filp->f_flags & O_NONBLOCK)
- return ret ? : -EAGAIN;
-
- if(need_resched())
- schedule_timeout_interruptible(1);
- }
- else return n;
+ u32 data;
+ int n, ret = 0, have_data;
+
+ while (size) {
+ n = os_read_file(random_fd, &data, sizeof(data));
+ if (n > 0) {
+ have_data = n;
+ while (have_data && size) {
+ if (put_user((u8) data, buf++)) {
+ ret = ret ? : -EFAULT;
+ break;
+ }
+ size--;
+ ret++;
+ have_data--;
+ data >>= 8;
+ }
+ }
+ else if (n == -EAGAIN) {
+ DECLARE_WAITQUEUE(wait, current);
+
+ if (filp->f_flags & O_NONBLOCK)
+ return ret ? : -EAGAIN;
+
+ atomic_inc(&host_sleep_count);
+ reactivate_fd(random_fd, RANDOM_IRQ);
+ add_sigio_fd(random_fd);
+
+ add_wait_queue(&host_read_wait, &wait);
+ set_task_state(current, TASK_INTERRUPTIBLE);
+
+ schedule();
+ set_task_state(current, TASK_RUNNING);
+ remove_wait_queue(&host_read_wait, &wait);
+
+ if (atomic_dec_and_test(&host_sleep_count)) {
+ ignore_sigio_fd(random_fd);
+ deactivate_fd(random_fd, RANDOM_IRQ);
+ }
+ }
+ else
+ return n;
+
if (signal_pending (current))
return ret ? : -ERESTARTSYS;
}
@@ -86,6 +109,13 @@ static struct miscdevice rng_miscdev = {
&rng_chrdev_ops,
};
+static irqreturn_t random_interrupt(int irq, void *data)
+{
+ wake_up(&host_read_wait);
+
+ return IRQ_HANDLED;
+}
+
/*
* rng_init - initialize RNG module
*/
@@ -93,28 +123,33 @@ static int __init rng_init (void)
{
int err;
- err = os_open_file("/dev/random", of_read(OPENFLAGS()), 0);
- if(err < 0)
- goto out;
+ err = os_open_file("/dev/random", of_read(OPENFLAGS()), 0);
+ if (err < 0)
+ goto out;
- random_fd = err;
+ random_fd = err;
- err = os_set_fd_block(random_fd, 0);
- if(err)
+ err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt,
+ IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "random",
+ NULL);
+ if (err)
goto err_out_cleanup_hw;
+ sigio_broken(random_fd, 1);
+
err = misc_register (&rng_miscdev);
if (err) {
- printk (KERN_ERR RNG_MODULE_NAME ": misc device register failed\n");
+ printk (KERN_ERR RNG_MODULE_NAME ": misc device register "
+ "failed\n");
goto err_out_cleanup_hw;
}
+out:
+ return err;
- out:
- return err;
-
- err_out_cleanup_hw:
- random_fd = -1;
- goto out;
+err_out_cleanup_hw:
+ os_close_file(random_fd);
+ random_fd = -1;
+ goto out;
}
/*
@@ -122,6 +157,7 @@ static int __init rng_init (void)
*/
static void __exit rng_cleanup (void)
{
+ os_close_file(random_fd);
misc_deregister (&rng_miscdev);
}
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index 8b80505a3fb..a1c2d2c98a9 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -96,7 +96,7 @@ static int slip_tramp(char **argv, int fd)
pid = err;
output_len = UM_KERN_PAGE_SIZE;
- output = kmalloc(output_len, UM_GFP_KERNEL);
+ output = uml_kmalloc(output_len, UM_GFP_KERNEL);
if (output == NULL) {
printk(UM_KERN_ERR "slip_tramp : failed to allocate output "
"buffer\n");
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c
index c930fedc517..495858a090e 100644
--- a/arch/um/drivers/tty.c
+++ b/arch/um/drivers/tty.c
@@ -29,7 +29,7 @@ static void *tty_chan_init(char *str, int device, const struct chan_opts *opts)
}
str++;
- data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
+ data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
if (data == NULL)
return NULL;
*data = ((struct tty_chan) { .dev = str,
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 5e45e39a8a8..44ad1607be2 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -1178,8 +1178,8 @@ static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask,
* by one word. Thanks to Lynn Kerby for the fix and James McMechan
* for the original diagnosis.
*/
- if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) /
- sizeof(unsigned long) - 1))
+ if (*cow_offset == (DIV_ROUND_UP(bitmap_len,
+ sizeof(unsigned long)) - 1))
(*cow_offset)--;
bitmap_words[0] = bitmap[*cow_offset];
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index 8a1c18a9b24..da2caa5a21e 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -30,7 +30,7 @@ static void *xterm_init(char *str, int device, const struct chan_opts *opts)
{
struct xterm_chan *data;
- data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
+ data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
if (data == NULL)
return NULL;
*data = ((struct xterm_chan) { .pid = -1,
diff --git a/arch/um/include/as-layout.h b/arch/um/include/as-layout.h
index cac542d8ff7..58e852dfb0c 100644
--- a/arch/um/include/as-layout.h
+++ b/arch/um/include/as-layout.h
@@ -23,16 +23,16 @@
*/
#ifdef __ASSEMBLY__
-#define _AC(X, Y) (Y)
+#define _UML_AC(X, Y) (Y)
#else
-#define __AC(X, Y) (X (Y))
-#define _AC(X, Y) __AC(X, Y)
+#define __UML_AC(X, Y) (X(Y))
+#define _UML_AC(X, Y) __UML_AC(X, Y)
#endif
-#define STUB_START _AC(, 0x100000)
-#define STUB_CODE _AC((unsigned long), STUB_START)
-#define STUB_DATA _AC((unsigned long), STUB_CODE + UM_KERN_PAGE_SIZE)
-#define STUB_END _AC((unsigned long), STUB_DATA + UM_KERN_PAGE_SIZE)
+#define STUB_START _UML_AC(, 0x100000)
+#define STUB_CODE _UML_AC((unsigned long), STUB_START)
+#define STUB_DATA _UML_AC((unsigned long), STUB_CODE + UM_KERN_PAGE_SIZE)
+#define STUB_END _UML_AC((unsigned long), STUB_DATA + UM_KERN_PAGE_SIZE)
#ifndef __ASSEMBLY__
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 1223f2c844b..311a0d3d93a 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -58,11 +58,11 @@ struct line {
};
#define LINE_INIT(str, d) \
- { .count_lock = SPIN_LOCK_UNLOCKED, \
+ { .count_lock = __SPIN_LOCK_UNLOCKED((str).count_lock), \
.init_str = str, \
.init_pri = INIT_STATIC, \
.valid = 1, \
- .lock = SPIN_LOCK_UNLOCKED, \
+ .lock = __SPIN_LOCK_UNLOCKED((str).lock), \
.driver = d }
extern void line_close(struct tty_struct *tty, struct file * filp);
@@ -71,7 +71,7 @@ extern int line_setup(struct line *lines, unsigned int sizeof_lines,
char *init, char **error_out);
extern int line_write(struct tty_struct *tty, const unsigned char *buf,
int len);
-extern void line_put_char(struct tty_struct *tty, unsigned char ch);
+extern int line_put_char(struct tty_struct *tty, unsigned char ch);
extern void line_set_termios(struct tty_struct *tty, struct ktermios * old);
extern int line_chars_in_buffer(struct tty_struct *tty);
extern void line_flush_buffer(struct tty_struct *tty);
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 32c799e3a49..e2716ac8889 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -290,6 +290,7 @@ extern void os_set_ioignore(void);
extern int add_sigio_fd(int fd);
extern int ignore_sigio_fd(int fd);
extern void maybe_sigio_broken(int fd, int read);
+extern void sigio_broken(int fd, int read);
/* sys-x86_64/prctl.c */
extern int os_arch_prctl(int pid, int code, unsigned long *addr);
diff --git a/arch/um/include/process.h b/arch/um/include/process.h
index 5af9157ff54..bb873a51262 100644
--- a/arch/um/include/process.h
+++ b/arch/um/include/process.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -8,18 +8,10 @@
#include <signal.h>
-extern void sig_handler(int sig, struct sigcontext sc);
-extern void alarm_handler(int sig, struct sigcontext sc);
+/* Copied from linux/compiler-gcc.h since we can't include it directly */
+#define barrier() __asm__ __volatile__("": : :"memory")
-#endif
+extern void sig_handler(int sig, struct sigcontext *sc);
+extern void alarm_handler(int sig, struct sigcontext *sc);
-/*
- * 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:
- */
+#endif
diff --git a/arch/um/include/skas_ptrace.h b/arch/um/include/skas_ptrace.h
index cd2327d09c8..3d31bbacd01 100644
--- a/arch/um/include/skas_ptrace.h
+++ b/arch/um/include/skas_ptrace.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -12,14 +12,3 @@
#include "sysdep/skas_ptrace.h"
#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-i386/ptrace_user.h b/arch/um/include/sysdep-i386/ptrace_user.h
index 75650723c38..ef56247e414 100644
--- a/arch/um/include/sysdep-i386/ptrace_user.h
+++ b/arch/um/include/sysdep-i386/ptrace_user.h
@@ -41,38 +41,10 @@
#define PT_SP_OFFSET PT_OFFSET(UESP)
#define PT_SP(regs) ((regs)[UESP])
-#define FP_SIZE ((HOST_XFP_SIZE > HOST_FP_SIZE) ? HOST_XFP_SIZE : HOST_FP_SIZE)
+#define FP_SIZE ((HOST_FPX_SIZE > HOST_FP_SIZE) ? HOST_FPX_SIZE : HOST_FP_SIZE)
#ifndef FRAME_SIZE
#define FRAME_SIZE (17)
#endif
-#define FRAME_SIZE_OFFSET (FRAME_SIZE * sizeof(unsigned long))
-
-#define FP_FRAME_SIZE (27)
-#define FPX_FRAME_SIZE (128)
-
-#ifdef PTRACE_GETREGS
-#define UM_HAVE_GETREGS
-#endif
-
-#ifdef PTRACE_SETREGS
-#define UM_HAVE_SETREGS
-#endif
-
-#ifdef PTRACE_GETFPREGS
-#define UM_HAVE_GETFPREGS
-#endif
-
-#ifdef PTRACE_SETFPREGS
-#define UM_HAVE_SETFPREGS
-#endif
-
-#ifdef PTRACE_GETFPXREGS
-#define UM_HAVE_GETFPXREGS
-#endif
-
-#ifdef PTRACE_SETFPXREGS
-#define UM_HAVE_SETFPXREGS
-#endif
#endif
diff --git a/arch/um/include/sysdep-i386/sigcontext.h b/arch/um/include/sysdep-i386/sigcontext.h
index 67e77122aa4..f583c87111a 100644
--- a/arch/um/include/sysdep-i386/sigcontext.h
+++ b/arch/um/include/sysdep-i386/sigcontext.h
@@ -10,7 +10,7 @@
#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
-#define GET_FAULTINFO_FROM_SC(fi,sc) \
+#define GET_FAULTINFO_FROM_SC(fi, sc) \
{ \
(fi).cr2 = SC_CR2(sc); \
(fi).error_code = SC_ERR(sc); \
diff --git a/arch/um/include/sysdep-x86_64/ptrace_user.h b/arch/um/include/sysdep-x86_64/ptrace_user.h
index 45c0bd881cb..4dbccdb58f4 100644
--- a/arch/um/include/sysdep-x86_64/ptrace_user.h
+++ b/arch/um/include/sysdep-x86_64/ptrace_user.h
@@ -48,7 +48,8 @@
#define PT_ORIG_RAX_OFFSET (ORIG_RAX)
#define PT_ORIG_RAX(regs) ((regs)[PT_INDEX(ORIG_RAX)])
-/* x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though
+/*
+ * x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though
* it's defined in the kernel's include/linux/ptrace.h. Additionally, use the
* 2.4 name and value for 2.4 host compatibility.
*/
@@ -56,7 +57,8 @@
#define PTRACE_OLDSETOPTIONS 21
#endif
-/* These are before the system call, so the system call number is RAX
+/*
+ * These are before the system call, so the system call number is RAX
* rather than ORIG_RAX, and arg4 is R10 rather than RCX
*/
#define REGS_SYSCALL_NR PT_INDEX(RAX)
@@ -73,14 +75,3 @@
#define FP_SIZE (HOST_FP_SIZE)
#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/um_malloc.h b/arch/um/include/um_malloc.h
index 0ad17cb83d9..c554d706d10 100644
--- a/arch/um/include/um_malloc.h
+++ b/arch/um/include/um_malloc.h
@@ -8,15 +8,12 @@
#include "kern_constants.h"
-extern void *__kmalloc(int size, int flags);
-static inline void *kmalloc(int size, int flags)
-{
- return __kmalloc(size, flags);
-}
-
+extern void *uml_kmalloc(int size, int flags);
extern void kfree(const void *ptr);
extern void *vmalloc(unsigned long size);
extern void vfree(void *ptr);
#endif /* __UM_MALLOC_H__ */
+
+
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index 26090b7f323..9975e1ab44f 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -1,4 +1,5 @@
#include <asm-generic/vmlinux.lds.h>
+#include <asm/page.h>
OUTPUT_FORMAT(ELF_FORMAT)
OUTPUT_ARCH(ELF_ARCH)
@@ -21,7 +22,7 @@ SECTIONS
_einittext = .;
}
- . = ALIGN(4096);
+ . = ALIGN(PAGE_SIZE);
/* Read-only sections, merged into text segment: */
.hash : { *(.hash) }
@@ -68,9 +69,9 @@ SECTIONS
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
- . = ALIGN(4096);
+ . = ALIGN(PAGE_SIZE);
} =0x90909090
- . = ALIGN(4096);
+ . = ALIGN(PAGE_SIZE);
.syscall_stub : {
__syscall_stub_start = .;
*(.__syscall_stub*)
diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c
index 984f80e668c..6540d2c9fbb 100644
--- a/arch/um/kernel/exitcode.c
+++ b/arch/um/kernel/exitcode.c
@@ -59,7 +59,7 @@ static int make_proc_exitcode(void)
{
struct proc_dir_entry *ent;
- ent = create_proc_entry("exitcode", 0600, &proc_root);
+ ent = create_proc_entry("exitcode", 0600, NULL);
if (ent == NULL) {
printk(KERN_WARNING "make_proc_exitcode : Failed to register "
"/proc/exitcode\n");
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 2eea1ff235e..b0ee64622ff 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -375,3 +375,8 @@ pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
return pmd;
}
#endif
+
+void *uml_kmalloc(int size, int flags)
+{
+ return kmalloc(size, flags);
+}
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index e8cb9ff183e..83603cfbde8 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -364,7 +364,7 @@ int __init make_proc_sysemu(void)
if (!sysemu_supported)
return 0;
- ent = create_proc_entry("sysemu", 0600, &proc_root);
+ ent = create_proc_entry("sysemu", 0600, NULL);
if (ent == NULL)
{
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index 9cffc628a37..128ee85bc8d 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -73,23 +73,6 @@ long old_mmap(unsigned long addr, unsigned long len,
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)
{
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index e066e84493b..c3e2f369c33 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -4,6 +4,7 @@
*/
#include <linux/clockchips.h>
+#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/threads.h>
@@ -74,7 +75,7 @@ static irqreturn_t um_timer(int irq, void *dev)
static cycle_t itimer_read(void)
{
- return os_nsecs();
+ return os_nsecs() / 1000;
}
static struct clocksource itimer_clocksource = {
@@ -82,7 +83,7 @@ static struct clocksource itimer_clocksource = {
.rating = 300,
.read = itimer_read,
.mask = CLOCKSOURCE_MASK(64),
- .mult = 1,
+ .mult = 1000,
.shift = 0,
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
@@ -109,8 +110,6 @@ static void __init setup_itimer(void)
clockevents_register_device(&itimer_clockevent);
}
-extern void (*late_time_init)(void);
-
void __init time_init(void)
{
long long nsecs;
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 56deed62344..9db85b2ce69 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -150,7 +150,7 @@ __uml_setup("root=", uml_root_setup,
static int __init no_skas_debug_setup(char *line, int *add)
{
printf("'debug' is not necessary to gdb UML in skas mode - run \n");
- printf("'gdb linux'");
+ printf("'gdb linux'\n");
return 0;
}
@@ -258,6 +258,7 @@ int __init linux_main(int argc, char **argv)
{
unsigned long avail, diff;
unsigned long virtmem_size, max_physmem;
+ unsigned long stack;
unsigned int i;
int add;
char * mode;
@@ -348,7 +349,9 @@ int __init linux_main(int argc, char **argv)
}
virtmem_size = physmem_size;
- avail = TASK_SIZE - start_vm;
+ stack = (unsigned long) argv;
+ stack &= ~(1024 * 1024 - 1);
+ avail = stack - start_vm;
if (physmem_size > avail)
virtmem_size = avail;
end_vm = start_vm + virtmem_size;
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index 5828c1d5450..11b835248b8 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -1,4 +1,5 @@
#include <asm-generic/vmlinux.lds.h>
+#include <asm/page.h>
OUTPUT_FORMAT(ELF_FORMAT)
OUTPUT_ARCH(ELF_ARCH)
@@ -26,7 +27,7 @@ SECTIONS
INIT_TEXT
_einittext = .;
}
- . = ALIGN(4096);
+ . = ALIGN(PAGE_SIZE);
.text :
{
@@ -39,7 +40,7 @@ SECTIONS
*(.gnu.linkonce.t*)
}
- . = ALIGN(4096);
+ . = ALIGN(PAGE_SIZE);
.syscall_stub : {
__syscall_stub_start = .;
*(.__syscall_stub*)
@@ -79,7 +80,7 @@ SECTIONS
.sdata : { *(.sdata) }
_edata = .;
PROVIDE (edata = .);
- . = ALIGN(0x1000);
+ . = ALIGN(PAGE_SIZE);
.sbss :
{
__bss_start = .;
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index 6fb0b174f53..cc72cb2c1af 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -52,7 +52,7 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask,
return;
}
- output = kmalloc(UM_KERN_PAGE_SIZE, UM_GFP_KERNEL);
+ output = uml_kmalloc(UM_KERN_PAGE_SIZE, UM_GFP_KERNEL);
if (output == NULL)
printk(UM_KERN_ERR "etap_change : Failed to allocate output "
"buffer\n");
@@ -165,7 +165,7 @@ static int etap_open(void *data)
err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0],
control_fds[1], data_fds[0], data_fds[1]);
output_len = UM_KERN_PAGE_SIZE;
- output = kmalloc(output_len, UM_GFP_KERNEL);
+ output = uml_kmalloc(output_len, UM_GFP_KERNEL);
read_output(control_fds[0], output, output_len);
if (output == NULL)
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index f25c29a12d0..74ca7aabf4e 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -71,8 +71,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
data.pre_data = pre_data;
data.argv = argv;
data.fd = fds[1];
- data.buf = __cant_sleep() ? kmalloc(PATH_MAX, UM_GFP_ATOMIC) :
- kmalloc(PATH_MAX, UM_GFP_KERNEL);
+ data.buf = __cant_sleep() ? uml_kmalloc(PATH_MAX, UM_GFP_ATOMIC) :
+ uml_kmalloc(PATH_MAX, UM_GFP_KERNEL);
pid = clone(helper_child, (void *) sp, CLONE_VM, &data);
if (pid < 0) {
ret = -errno;
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index abb9b0ffd96..eee69b9f52c 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -199,7 +199,7 @@ void *__wrap_malloc(int size)
return __real_malloc(size);
else if (size <= UM_KERN_PAGE_SIZE)
/* finding contiguous pages can be hard*/
- ret = kmalloc(size, UM_GFP_KERNEL);
+ ret = uml_kmalloc(size, UM_GFP_KERNEL);
else ret = vmalloc(size);
/*
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index abf47a7c4ab..eb8f2e4be19 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Copyright (C) 2002 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -15,6 +15,7 @@
#include "kern_util.h"
#include "init.h"
#include "os.h"
+#include "process.h"
#include "sigio.h"
#include "um_malloc.h"
#include "user.h"
@@ -109,7 +110,7 @@ static int need_poll(struct pollfds *polls, int n)
if (n <= polls->size)
return 0;
- new = kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC);
+ new = uml_kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC);
if (new == NULL) {
printk(UM_KERN_ERR "need_poll : failed to allocate new "
"pollfds\n");
@@ -243,7 +244,7 @@ static struct pollfd *setup_initial_poll(int fd)
{
struct pollfd *p;
- p = kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL);
+ p = uml_kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL);
if (p == NULL) {
printk(UM_KERN_ERR "setup_initial_poll : failed to allocate "
"poll\n");
@@ -338,20 +339,10 @@ out_close1:
close(l_write_sigio_fds[1]);
}
-/* Changed during early boot */
-static int pty_output_sigio = 0;
-static int pty_close_sigio = 0;
-
-void maybe_sigio_broken(int fd, int read)
+void 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();
@@ -370,6 +361,21 @@ out:
sigio_unlock();
}
+/* Changed during early boot */
+static int pty_output_sigio;
+static int pty_close_sigio;
+
+void maybe_sigio_broken(int fd, int read)
+{
+ if (!isatty(fd))
+ return;
+
+ if ((read || pty_output_sigio) && (!read || pty_close_sigio))
+ return;
+
+ sigio_broken(fd, read);
+}
+
static void sigio_cleanup(void)
{
if (write_sigio_pid == -1)
@@ -383,7 +389,7 @@ static void sigio_cleanup(void)
__uml_exitcall(sigio_cleanup);
/* Used as a flag during SIGIO testing early in boot */
-static volatile int got_sigio = 0;
+static int got_sigio;
static void __init handler(int sig)
{
@@ -498,7 +504,8 @@ static void tty_output(int master, int slave)
if (errno != EAGAIN)
printk(UM_KERN_ERR "tty_output : write failed, errno = %d\n",
errno);
- while (((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio)
+ while (((n = read(slave, buf, sizeof(buf))) > 0) &&
+ !({ barrier(); got_sigio; }))
;
if (got_sigio) {
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 3f1694b134c..5aade6027e4 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -12,6 +12,7 @@
#include "as-layout.h"
#include "kern_util.h"
#include "os.h"
+#include "process.h"
#include "sysdep/barrier.h"
#include "sysdep/sigcontext.h"
#include "user.h"
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 1e8cba6550a..6be028ca181 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -442,7 +442,7 @@ void userspace(struct uml_pt_regs *regs)
unblock_signals();
break;
default:
- printk(UM_KERN_ERR "userspace - child stopped "
+ printk(UM_KERN_ERR "userspace - child stopped "
"with signal %d\n", sig);
fatal_sigsegv();
}
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 997d01944f9..b4b36e0f2e8 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -23,6 +23,7 @@
#include "mem_user.h"
#include "ptrace_user.h"
#include "registers.h"
+#include "skas.h"
#include "skas_ptrace.h"
static void ptrace_child(void)
@@ -140,14 +141,27 @@ static int stop_ptraced_child(int pid, int exitcode, int mustexit)
}
/* Changed only during early boot */
-int ptrace_faultinfo = 1;
-int ptrace_ldt = 1;
-int proc_mm = 1;
-int skas_needs_stub = 0;
+int ptrace_faultinfo;
+static int disable_ptrace_faultinfo;
+
+int ptrace_ldt;
+static int disable_ptrace_ldt;
+
+int proc_mm;
+static int disable_proc_mm;
+
+int have_switch_mm;
+static int disable_switch_mm;
+
+int skas_needs_stub;
static int __init skas0_cmd_param(char *str, int* add)
{
- ptrace_faultinfo = proc_mm = 0;
+ disable_ptrace_faultinfo = 1;
+ disable_ptrace_ldt = 1;
+ disable_proc_mm = 1;
+ disable_switch_mm = 1;
+
return 0;
}
@@ -157,15 +171,12 @@ static int __init mode_skas0_cmd_param(char *str, int* add)
__attribute__((alias("skas0_cmd_param")));
__uml_setup("skas0", skas0_cmd_param,
- "skas0\n"
- " Disables SKAS3 usage, so that SKAS0 is used, unless \n"
- " you specify mode=tt.\n\n");
+"skas0\n"
+" Disables SKAS3 and SKAS4 usage, so that SKAS0 is used\n\n");
__uml_setup("mode=skas0", mode_skas0_cmd_param,
- "mode=skas0\n"
- " Disables SKAS3 usage, so that SKAS0 is used, unless you \n"
- " specify mode=tt. Note that this was recently added - on \n"
- " older kernels you must use simply \"skas0\".\n\n");
+"mode=skas0\n"
+" Disables SKAS3 and SKAS4 usage, so that SKAS0 is used.\n\n");
/* Changed only during early boot */
static int force_sysemu_disabled = 0;
@@ -360,7 +371,7 @@ void __init os_early_checks(void)
static int __init noprocmm_cmd_param(char *str, int* add)
{
- proc_mm = 0;
+ disable_proc_mm = 1;
return 0;
}
@@ -372,7 +383,7 @@ __uml_setup("noprocmm", noprocmm_cmd_param,
static int __init noptracefaultinfo_cmd_param(char *str, int* add)
{
- ptrace_faultinfo = 0;
+ disable_ptrace_faultinfo = 1;
return 0;
}
@@ -384,7 +395,7 @@ __uml_setup("noptracefaultinfo", noptracefaultinfo_cmd_param,
static int __init noptraceldt_cmd_param(char *str, int* add)
{
- ptrace_ldt = 0;
+ disable_ptrace_ldt = 1;
return 0;
}
@@ -404,17 +415,15 @@ static inline void check_skas3_ptrace_faultinfo(void)
n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi);
if (n < 0) {
- ptrace_faultinfo = 0;
if (errno == EIO)
non_fatal("not found\n");
else
perror("not found");
- }
+ } else if (disable_ptrace_faultinfo)
+ non_fatal("found but disabled on command line\n");
else {
- if (!ptrace_faultinfo)
- non_fatal("found but disabled on command line\n");
- else
- non_fatal("found\n");
+ ptrace_faultinfo = 1;
+ non_fatal("found\n");
}
stop_ptraced_child(pid, 1, 1);
@@ -437,38 +446,30 @@ static inline void check_skas3_ptrace_ldt(void)
if (n < 0) {
if (errno == EIO)
non_fatal("not found\n");
- else {
+ else
perror("not found");
- }
- ptrace_ldt = 0;
- }
+ } else if (disable_ptrace_ldt)
+ non_fatal("found, but use is disabled\n");
else {
- if (ptrace_ldt)
- non_fatal("found\n");
- else
- non_fatal("found, but use is disabled\n");
+ ptrace_ldt = 1;
+ non_fatal("found\n");
}
stop_ptraced_child(pid, 1, 1);
-#else
- /* PTRACE_LDT might be disabled via cmdline option.
- * We want to override this, else we might use the stub
- * without real need
- */
- ptrace_ldt = 1;
#endif
}
static inline void check_skas3_proc_mm(void)
{
non_fatal(" - /proc/mm...");
- if (access("/proc/mm", W_OK) < 0) {
- proc_mm = 0;
+ if (access("/proc/mm", W_OK) < 0)
perror("not found");
- }
- else if (!proc_mm)
+ else if (disable_proc_mm)
non_fatal("found but disabled on command line\n");
- else non_fatal("found\n");
+ else {
+ proc_mm = 1;
+ non_fatal("found\n");
+ }
}
void can_do_skas(void)
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
index b613473b3ec..c6183e7aec3 100644
--- a/arch/um/os-Linux/sys-i386/registers.c
+++ b/arch/um/os-Linux/sys-i386/registers.c
@@ -5,6 +5,7 @@
*/
#include <errno.h>
+#include <asm/user.h>
#include "kern_constants.h"
#include "longjmp.h"
#include "user.h"
@@ -74,10 +75,10 @@ int put_fp_registers(int pid, unsigned long *regs)
void arch_init_registers(int pid)
{
- unsigned long fpx_regs[HOST_XFP_SIZE];
+ struct user_fxsr_struct fpx_regs;
int err;
- err = ptrace(PTRACE_GETFPXREGS, pid, 0, fpx_regs);
+ err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs);
if (!err)
return;
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index e4928059946..bee98f466d6 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -9,7 +9,9 @@
#include <time.h>
#include <sys/time.h>
#include "kern_constants.h"
+#include "kern_util.h"
#include "os.h"
+#include "process.h"
#include "user.h"
int set_interval(void)
@@ -58,12 +60,17 @@ static inline long long timeval_to_ns(const struct timeval *tv)
long long disable_timer(void)
{
struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } });
+ int remain, max = UM_NSEC_PER_SEC / UM_HZ;
if (setitimer(ITIMER_VIRTUAL, &time, &time) < 0)
printk(UM_KERN_ERR "disable_timer - setitimer failed, "
"errno = %d\n", errno);
- return timeval_to_ns(&time.it_value);
+ remain = timeval_to_ns(&time.it_value);
+ if (remain > max)
+ remain = max;
+
+ return remain;
}
long long os_nsecs(void)
@@ -79,7 +86,44 @@ static int after_sleep_interval(struct timespec *ts)
{
return 0;
}
+
+static void deliver_alarm(void)
+{
+ alarm_handler(SIGVTALRM, NULL);
+}
+
+static unsigned long long sleep_time(unsigned long long nsecs)
+{
+ return nsecs;
+}
+
#else
+unsigned long long last_tick;
+unsigned long long skew;
+
+static void deliver_alarm(void)
+{
+ unsigned long long this_tick = os_nsecs();
+ int one_tick = UM_NSEC_PER_SEC / UM_HZ;
+
+ if (last_tick == 0)
+ last_tick = this_tick - one_tick;
+
+ skew += this_tick - last_tick;
+
+ while (skew >= one_tick) {
+ alarm_handler(SIGVTALRM, NULL);
+ skew -= one_tick;
+ }
+
+ last_tick = this_tick;
+}
+
+static unsigned long long sleep_time(unsigned long long nsecs)
+{
+ return nsecs > skew ? nsecs - skew : 0;
+}
+
static inline long long timespec_to_us(const struct timespec *ts)
{
return ((long long) ts->tv_sec * UM_USEC_PER_SEC) +
@@ -102,6 +146,8 @@ static int after_sleep_interval(struct timespec *ts)
*/
if (start_usecs > usec)
start_usecs = usec;
+
+ start_usecs -= skew / UM_NSEC_PER_USEC;
tv = ((struct timeval) { .tv_sec = start_usecs / UM_USEC_PER_SEC,
.tv_usec = start_usecs % UM_USEC_PER_SEC });
interval = ((struct itimerval) { { 0, usec }, tv });
@@ -113,8 +159,6 @@ static int after_sleep_interval(struct timespec *ts)
}
#endif
-extern void alarm_handler(int sig, struct sigcontext *sc);
-
void idle_sleep(unsigned long long nsecs)
{
struct timespec ts;
@@ -126,10 +170,12 @@ void idle_sleep(unsigned long long nsecs)
*/
if (nsecs == 0)
nsecs = UM_NSEC_PER_SEC / UM_HZ;
+
+ nsecs = sleep_time(nsecs);
ts = ((struct timespec) { .tv_sec = nsecs / UM_NSEC_PER_SEC,
.tv_nsec = nsecs % UM_NSEC_PER_SEC });
if (nanosleep(&ts, &ts) == 0)
- alarm_handler(SIGVTALRM, NULL);
+ deliver_alarm();
after_sleep_interval(&ts);
}
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c
index 6b4499906a6..c9b176534d6 100644
--- a/arch/um/sys-i386/ptrace.c
+++ b/arch/um/sys-i386/ptrace.c
@@ -148,14 +148,13 @@ int peek_user(struct task_struct *child, long addr, long data)
int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
{
int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
- long fpregs[HOST_FP_SIZE];
+ struct user_i387_struct fpregs;
- BUG_ON(sizeof(*buf) != sizeof(fpregs));
- err = save_fp_registers(userspace_pid[cpu], fpregs);
+ err = save_fp_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
if (err)
return err;
- n = copy_to_user(buf, fpregs, sizeof(fpregs));
+ n = copy_to_user(buf, &fpregs, sizeof(fpregs));
if(n > 0)
return -EFAULT;
@@ -165,27 +164,26 @@ int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
{
int n, cpu = ((struct thread_info *) child->stack)->cpu;
- long fpregs[HOST_FP_SIZE];
+ struct user_i387_struct fpregs;
- BUG_ON(sizeof(*buf) != sizeof(fpregs));
- n = copy_from_user(fpregs, buf, sizeof(fpregs));
+ n = copy_from_user(&fpregs, buf, sizeof(fpregs));
if (n > 0)
return -EFAULT;
- return restore_fp_registers(userspace_pid[cpu], fpregs);
+ return restore_fp_registers(userspace_pid[cpu],
+ (unsigned long *) &fpregs);
}
int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
{
int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
- long fpregs[HOST_XFP_SIZE];
+ struct user_fxsr_struct fpregs;
- BUG_ON(sizeof(*buf) != sizeof(fpregs));
- err = save_fpx_registers(userspace_pid[cpu], fpregs);
+ err = save_fpx_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
if (err)
return err;
- n = copy_to_user(buf, fpregs, sizeof(fpregs));
+ n = copy_to_user(buf, &fpregs, sizeof(fpregs));
if(n > 0)
return -EFAULT;
@@ -195,14 +193,14 @@ int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
{
int n, cpu = ((struct thread_info *) child->stack)->cpu;
- long fpregs[HOST_XFP_SIZE];
+ struct user_fxsr_struct fpregs;
- BUG_ON(sizeof(*buf) != sizeof(fpregs));
- n = copy_from_user(fpregs, buf, sizeof(fpregs));
+ n = copy_from_user(&fpregs, buf, sizeof(fpregs));
if (n > 0)
return -EFAULT;
- return restore_fpx_registers(userspace_pid[cpu], fpregs);
+ return restore_fpx_registers(userspace_pid[cpu],
+ (unsigned long *) &fpregs);
}
long subarch_ptrace(struct task_struct *child, long request, long addr,
diff --git a/arch/um/sys-i386/user-offsets.c b/arch/um/sys-i386/user-offsets.c
index 39bd32bf84f..5f883bfe773 100644
--- a/arch/um/sys-i386/user-offsets.c
+++ b/arch/um/sys-i386/user-offsets.c
@@ -22,7 +22,7 @@ void foo(void)
OFFSET(HOST_SC_CR2, sigcontext, cr2);
DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_fpregs_struct));
- DEFINE_LONGS(HOST_XFP_SIZE, sizeof(struct user_fpxregs_struct));
+ DEFINE_LONGS(HOST_FPX_SIZE, sizeof(struct user_fpxregs_struct));
DEFINE(HOST_IP, EIP);
DEFINE(HOST_SP, UESP);
diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c
index 2f3443c6e85..973585414a6 100644
--- a/arch/um/sys-x86_64/user-offsets.c
+++ b/arch/um/sys-x86_64/user-offsets.c
@@ -24,7 +24,6 @@ void foo(void)
OFFSET(HOST_SC_TRAPNO, sigcontext, trapno);
DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long));
- DEFINE(HOST_XFP_SIZE, 0);
DEFINE_LONGS(HOST_RBX, RBX);
DEFINE_LONGS(HOST_RCX, RCX);
DEFINE_LONGS(HOST_RDI, RDI);