summaryrefslogtreecommitdiff
path: root/arch/um
diff options
context:
space:
mode:
authorAndi Kleen <andi@basil.nowhere.org>2006-11-21 10:22:09 +0100
committerAndi Kleen <andi@basil.nowhere.org>2006-11-21 10:22:09 +0100
commit1b7f6a626f0ff511c3840678466cbfe1d62c0b29 (patch)
tree415e8c838c0067bff384afb8a2c91e5f7c6d11d3 /arch/um
parentb3edc9cec07ade41aaf1804f7c9e876afa90c862 (diff)
parent3f5a6ca31c334011fd929501a078424c0d3f71be (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/Makefile21
-rw-r--r--arch/um/Makefile-i3864
-rw-r--r--arch/um/Makefile-x86_644
-rw-r--r--arch/um/drivers/mconsole_kern.c23
-rw-r--r--arch/um/drivers/mconsole_user.c1
-rw-r--r--arch/um/drivers/ubd_kern.c319
-rw-r--r--arch/um/include/mconsole.h1
-rw-r--r--arch/um/include/mconsole_kern.h1
-rw-r--r--arch/um/include/sysdep-i386/barrier.h9
-rw-r--r--arch/um/include/sysdep-x86_64/barrier.h7
-rw-r--r--arch/um/kernel/dyn.lds.S1
-rw-r--r--arch/um/kernel/tt/tracer.c1
-rw-r--r--arch/um/kernel/uml.lds.S1
-rw-r--r--arch/um/os-Linux/process.c1
-rw-r--r--arch/um/os-Linux/signal.c31
-rw-r--r--arch/um/os-Linux/skas/process.c2
-rw-r--r--arch/um/os-Linux/sys-i386/tls.c3
-rw-r--r--arch/um/os-Linux/tls.c1
-rw-r--r--arch/um/sys-i386/unmap.c11
-rw-r--r--arch/um/sys-x86_64/unmap.c11
20 files changed, 274 insertions, 179 deletions
diff --git a/arch/um/Makefile b/arch/um/Makefile
index c8016a98483b..5d5ed726faa0 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -64,9 +64,14 @@ CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
AFLAGS += $(ARCH_INCLUDE)
-USER_CFLAGS := $(patsubst -I%,,$(CFLAGS))
-USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
- $(MODE_INCLUDE) -D_FILE_OFFSET_BITS=64
+USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\
+ $(patsubst -I%,,$(CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \
+ -D_FILE_OFFSET_BITS=64
+
+include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
+
+#This will adjust *FLAGS accordingly to the platform.
+include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS)
# -Derrno=kernel_errno - This turns all kernel references to errno into
# kernel_errno to separate them from the libc errno. This allows -fno-common
@@ -74,15 +79,11 @@ USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
# errnos.
# These apply to kernelspace only.
-CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \
- -Dmktime=kernel_mktime
+KERNEL_DEFINES = -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \
+ -Dmktime=kernel_mktime $(ARCH_KERNEL_DEFINES)
+CFLAGS += $(KERNEL_DEFINES)
CFLAGS += $(call cc-option,-fno-unit-at-a-time,)
-include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
-
-#This will adjust *FLAGS accordingly to the platform.
-include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS)
-
# These are needed for clean and mrproper, since in that case .config is not
# included; the values here are meaningless
diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386
index b65ca115ef77..c9f1c5b24c9a 100644
--- a/arch/um/Makefile-i386
+++ b/arch/um/Makefile-i386
@@ -16,7 +16,6 @@ OBJCOPYFLAGS := -O binary -R .note -R .comment -S
ifeq ("$(origin SUBARCH)", "command line")
ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)")
CFLAGS += $(call cc-option,-m32)
-USER_CFLAGS += $(call cc-option,-m32)
AFLAGS += $(call cc-option,-m32)
LINK-y += $(call cc-option,-m32)
UML_OBJCOPYFLAGS += -F $(ELF_FORMAT)
@@ -25,7 +24,7 @@ export LDFLAGS HOSTCFLAGS HOSTLDFLAGS UML_OBJCOPYFLAGS
endif
endif
-CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH)
+ARCH_KERNEL_DEFINES += -U__$(SUBARCH)__ -U$(SUBARCH)
# First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y.
include $(srctree)/arch/i386/Makefile.cpu
@@ -38,4 +37,3 @@ cflags-y += $(call cc-option,-mpreferred-stack-boundary=2)
cflags-y += -ffreestanding
CFLAGS += $(cflags-y)
-USER_CFLAGS += $(cflags-y)
diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64
index d278682dd799..69ecea63fdae 100644
--- a/arch/um/Makefile-x86_64
+++ b/arch/um/Makefile-x86_64
@@ -8,8 +8,8 @@ _extra_flags_ = -fno-builtin -m64
#We #undef __x86_64__ for kernelspace, not for userspace where
#it's needed for headers to work!
-CFLAGS += -U__$(SUBARCH)__ $(_extra_flags_)
-USER_CFLAGS += $(_extra_flags_)
+ARCH_KERNEL_DEFINES = -U__$(SUBARCH)__
+CFLAGS += $(_extra_flags_)
CHECKFLAGS += -m64
AFLAGS += -m64
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index d08bd036ccb8..7b172160fe04 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -79,7 +79,7 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id)
/* long to avoid size mismatch warnings from gcc */
long fd;
struct mconsole_entry *new;
- struct mc_request req;
+ static struct mc_request req; /* that's OK */
fd = (long) dev_id;
while (mconsole_get_request(fd, &req)){
@@ -91,6 +91,7 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id)
mconsole_reply(&req, "Out of memory", 1, 0);
else {
new->request = req;
+ new->request.regs = get_irq_regs()->regs;
list_add(&new->list, &mc_requests);
}
}
@@ -314,9 +315,21 @@ void mconsole_stop(struct mc_request *req)
{
deactivate_fd(req->originating_fd, MCONSOLE_IRQ);
os_set_fd_block(req->originating_fd, 1);
- mconsole_reply(req, "", 0, 0);
- while(mconsole_get_request(req->originating_fd, req)){
- if(req->cmd->handler == mconsole_go) break;
+ mconsole_reply(req, "stopped", 0, 0);
+ while (mconsole_get_request(req->originating_fd, req)) {
+ if (req->cmd->handler == mconsole_go)
+ break;
+ if (req->cmd->handler == mconsole_stop) {
+ mconsole_reply(req, "Already stopped", 1, 0);
+ continue;
+ }
+ if (req->cmd->handler == mconsole_sysrq) {
+ struct pt_regs *old_regs;
+ old_regs = set_irq_regs((struct pt_regs *)&req->regs);
+ mconsole_sysrq(req);
+ set_irq_regs(old_regs);
+ continue;
+ }
(*req->cmd->handler)(req);
}
os_set_fd_block(req->originating_fd, 0);
@@ -673,9 +686,7 @@ static void with_console(struct mc_request *req, void (*proc)(void *),
static void sysrq_proc(void *arg)
{
char *op = arg;
- struct pt_regs *old_regs = set_irq_regs(&current->thread.regs);
handle_sysrq(*op, NULL);
- set_irq_regs(old_regs);
}
void mconsole_sysrq(struct mc_request *req)
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 17068eb746c0..75aef6f7ef6e 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -14,6 +14,7 @@
#include <sys/un.h>
#include <unistd.h>
#include "user.h"
+#include "sysdep/ptrace.h"
#include "mconsole.h"
#include "umid.h"
#include "user_util.h"
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index bc458f57921b..49c047b75cc5 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -106,10 +106,15 @@ static inline void ubd_set_bit(__u64 bit, unsigned char *data)
#define DRIVER_NAME "uml-blkdev"
+/* Can be taken in interrupt context, and is passed to the block layer to lock
+ * the request queue. Kernel side code knows that. */
static DEFINE_SPINLOCK(ubd_io_lock);
-static DEFINE_SPINLOCK(ubd_lock);
-static void (*do_ubd)(void);
+static DEFINE_MUTEX(ubd_lock);
+
+/* XXX - this made sense in 2.4 days, now it's only used as a boolean, and
+ * probably it doesn't make sense even for that. */
+static int do_ubd;
static int ubd_open(struct inode * inode, struct file * filp);
static int ubd_release(struct inode * inode, struct file * file);
@@ -117,7 +122,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg);
static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo);
-#define MAX_DEV (8)
+#define MAX_DEV (16)
static struct block_device_operations ubd_blops = {
.owner = THIS_MODULE,
@@ -150,8 +155,9 @@ static struct gendisk *fake_gendisk[MAX_DEV];
static struct openflags global_openflags = OPEN_FLAGS;
struct cow {
- /* This is the backing file, actually */
+ /* backing file name */
char *file;
+ /* backing file fd */
int fd;
unsigned long *bitmap;
unsigned long bitmap_len;
@@ -160,14 +166,16 @@ struct cow {
};
struct ubd {
+ /* name (and fd, below) of the file opened for writing, either the
+ * backing or the cow file. */
char *file;
int count;
int fd;
__u64 size;
struct openflags boot_openflags;
struct openflags openflags;
- int shared;
- int no_cow;
+ unsigned shared:1;
+ unsigned no_cow:1;
struct cow cow;
struct platform_device pdev;
};
@@ -192,18 +200,7 @@ struct ubd {
.cow = DEFAULT_COW, \
}
-struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };
-
-static int ubd0_init(void)
-{
- struct ubd *dev = &ubd_dev[0];
-
- if(dev->file == NULL)
- dev->file = "root_fs";
- return(0);
-}
-
-__initcall(ubd0_init);
+struct ubd ubd_devs[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };
/* Only changed by fake_ide_setup which is a setup */
static int fake_ide = 0;
@@ -277,7 +274,7 @@ static int parse_unit(char **ptr)
return(-1);
*ptr = end;
}
- else if (('a' <= *str) && (*str <= 'h')) {
+ else if (('a' <= *str) && (*str <= 'z')) {
n = *str - 'a';
str++;
*ptr = str;
@@ -285,9 +282,13 @@ static int parse_unit(char **ptr)
return(n);
}
+/* If *index_out == -1 at exit, the passed option was a general one;
+ * otherwise, the str pointer is used (and owned) inside ubd_devs array, so it
+ * should not be freed on exit.
+ */
static int ubd_setup_common(char *str, int *index_out)
{
- struct ubd *dev;
+ struct ubd *ubd_dev;
struct openflags flags = global_openflags;
char *backing_file;
int n, err, i;
@@ -311,7 +312,7 @@ static int ubd_setup_common(char *str, int *index_out)
}
err = 1;
- spin_lock(&ubd_lock);
+ mutex_lock(&ubd_lock);
if(fake_major != MAJOR_NR){
printk(KERN_ERR "Can't assign a fake major twice\n");
goto out1;
@@ -323,7 +324,7 @@ static int ubd_setup_common(char *str, int *index_out)
major);
err = 0;
out1:
- spin_unlock(&ubd_lock);
+ mutex_unlock(&ubd_lock);
return(err);
}
@@ -340,10 +341,10 @@ static int ubd_setup_common(char *str, int *index_out)
}
err = 1;
- spin_lock(&ubd_lock);
+ mutex_lock(&ubd_lock);
- dev = &ubd_dev[n];
- if(dev->file != NULL){
+ ubd_dev = &ubd_devs[n];
+ if(ubd_dev->file != NULL){
printk(KERN_ERR "ubd_setup : device already configured\n");
goto out;
}
@@ -360,10 +361,10 @@ static int ubd_setup_common(char *str, int *index_out)
flags.s = 1;
break;
case 'd':
- dev->no_cow = 1;
+ ubd_dev->no_cow = 1;
break;
case 'c':
- dev->shared = 1;
+ ubd_dev->shared = 1;
break;
case '=':
str++;
@@ -390,7 +391,7 @@ break_loop:
}
if(backing_file){
- if(dev->no_cow)
+ if(ubd_dev->no_cow)
printk(KERN_ERR "Can't specify both 'd' and a "
"cow file\n");
else {
@@ -398,11 +399,11 @@ break_loop:
backing_file++;
}
}
- dev->file = str;
- dev->cow.file = backing_file;
- dev->boot_openflags = flags;
+ ubd_dev->file = str;
+ ubd_dev->cow.file = backing_file;
+ ubd_dev->boot_openflags = flags;
out:
- spin_unlock(&ubd_lock);
+ mutex_unlock(&ubd_lock);
return(err);
}
@@ -472,8 +473,9 @@ int thread_fd = -1;
/* Changed by ubd_handler, which is serialized because interrupts only
* happen on CPU 0.
+ * XXX: currently unused.
*/
-int intr_count = 0;
+static int intr_count = 0;
/* call ubd_finish if you need to serialize */
static void __ubd_finish(struct request *req, int error)
@@ -493,6 +495,8 @@ static void __ubd_finish(struct request *req, int error)
end_request(req, 1);
}
+/* Callable only from interrupt context - otherwise you need to do
+ * spin_lock_irq()/spin_lock_irqsave() */
static inline void ubd_finish(struct request *req, int error)
{
spin_lock(&ubd_io_lock);
@@ -500,14 +504,15 @@ static inline void ubd_finish(struct request *req, int error)
spin_unlock(&ubd_io_lock);
}
-/* Called without ubd_io_lock held */
+/* XXX - move this inside ubd_intr. */
+/* Called without ubd_io_lock held, and only in interrupt context. */
static void ubd_handler(void)
{
struct io_thread_req req;
struct request *rq = elv_next_request(ubd_queue);
int n;
- do_ubd = NULL;
+ do_ubd = 0;
intr_count++;
n = os_read_file(thread_fd, &req, sizeof(req));
if(n != sizeof(req)){
@@ -521,7 +526,9 @@ static void ubd_handler(void)
ubd_finish(rq, req.error);
reactivate_fd(thread_fd, UBD_IRQ);
+ spin_lock(&ubd_io_lock);
do_ubd_request(ubd_queue);
+ spin_unlock(&ubd_io_lock);
}
static irqreturn_t ubd_intr(int irq, void *dev)
@@ -541,87 +548,90 @@ void kill_io_thread(void)
__uml_exitcall(kill_io_thread);
-static int ubd_file_size(struct ubd *dev, __u64 *size_out)
+static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out)
{
char *file;
- file = dev->cow.file ? dev->cow.file : dev->file;
+ file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file;
return(os_file_size(file, size_out));
}
-static void ubd_close(struct ubd *dev)
+static void ubd_close_dev(struct ubd *ubd_dev)
{
- os_close_file(dev->fd);
- if(dev->cow.file == NULL)
+ os_close_file(ubd_dev->fd);
+ if(ubd_dev->cow.file == NULL)
return;
- os_close_file(dev->cow.fd);
- vfree(dev->cow.bitmap);
- dev->cow.bitmap = NULL;
+ os_close_file(ubd_dev->cow.fd);
+ vfree(ubd_dev->cow.bitmap);
+ ubd_dev->cow.bitmap = NULL;
}
-static int ubd_open_dev(struct ubd *dev)
+static int ubd_open_dev(struct ubd *ubd_dev)
{
struct openflags flags;
char **back_ptr;
int err, create_cow, *create_ptr;
+ int fd;
- dev->openflags = dev->boot_openflags;
+ ubd_dev->openflags = ubd_dev->boot_openflags;
create_cow = 0;
- create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL;
- back_ptr = dev->no_cow ? NULL : &dev->cow.file;
- dev->fd = open_ubd_file(dev->file, &dev->openflags, dev->shared,
- back_ptr, &dev->cow.bitmap_offset,
- &dev->cow.bitmap_len, &dev->cow.data_offset,
+ create_ptr = (ubd_dev->cow.file != NULL) ? &create_cow : NULL;
+ back_ptr = ubd_dev->no_cow ? NULL : &ubd_dev->cow.file;
+
+ fd = open_ubd_file(ubd_dev->file, &ubd_dev->openflags, ubd_dev->shared,
+ back_ptr, &ubd_dev->cow.bitmap_offset,
+ &ubd_dev->cow.bitmap_len, &ubd_dev->cow.data_offset,
create_ptr);
- if((dev->fd == -ENOENT) && create_cow){
- dev->fd = create_cow_file(dev->file, dev->cow.file,
- dev->openflags, 1 << 9, PAGE_SIZE,
- &dev->cow.bitmap_offset,
- &dev->cow.bitmap_len,
- &dev->cow.data_offset);
- if(dev->fd >= 0){
+ if((fd == -ENOENT) && create_cow){
+ fd = create_cow_file(ubd_dev->file, ubd_dev->cow.file,
+ ubd_dev->openflags, 1 << 9, PAGE_SIZE,
+ &ubd_dev->cow.bitmap_offset,
+ &ubd_dev->cow.bitmap_len,
+ &ubd_dev->cow.data_offset);
+ if(fd >= 0){
printk(KERN_INFO "Creating \"%s\" as COW file for "
- "\"%s\"\n", dev->file, dev->cow.file);
+ "\"%s\"\n", ubd_dev->file, ubd_dev->cow.file);
}
}
- if(dev->fd < 0){
- printk("Failed to open '%s', errno = %d\n", dev->file,
- -dev->fd);
- return(dev->fd);
+ if(fd < 0){
+ printk("Failed to open '%s', errno = %d\n", ubd_dev->file,
+ -fd);
+ return fd;
}
+ ubd_dev->fd = fd;
- if(dev->cow.file != NULL){
+ if(ubd_dev->cow.file != NULL){
err = -ENOMEM;
- dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len);
- if(dev->cow.bitmap == NULL){
+ ubd_dev->cow.bitmap = (void *) vmalloc(ubd_dev->cow.bitmap_len);
+ if(ubd_dev->cow.bitmap == NULL){
printk(KERN_ERR "Failed to vmalloc COW bitmap\n");
goto error;
}
flush_tlb_kernel_vm();
- err = read_cow_bitmap(dev->fd, dev->cow.bitmap,
- dev->cow.bitmap_offset,
- dev->cow.bitmap_len);
+ err = read_cow_bitmap(ubd_dev->fd, ubd_dev->cow.bitmap,
+ ubd_dev->cow.bitmap_offset,
+ ubd_dev->cow.bitmap_len);
if(err < 0)
goto error;
- flags = dev->openflags;
+ flags = ubd_dev->openflags;
flags.w = 0;
- err = open_ubd_file(dev->cow.file, &flags, dev->shared, NULL,
+ err = open_ubd_file(ubd_dev->cow.file, &flags, ubd_dev->shared, NULL,
NULL, NULL, NULL, NULL);
if(err < 0) goto error;
- dev->cow.fd = err;
+ ubd_dev->cow.fd = err;
}
return(0);
error:
- os_close_file(dev->fd);
+ os_close_file(ubd_dev->fd);
return(err);
}
-static int ubd_new_disk(int major, u64 size, int unit,
+static int ubd_disk_register(int major, u64 size, int unit,
struct gendisk **disk_out)
{
@@ -642,13 +652,13 @@ static int ubd_new_disk(int major, u64 size, int unit,
/* sysfs register (not for ide fake devices) */
if (major == MAJOR_NR) {
- ubd_dev[unit].pdev.id = unit;
- ubd_dev[unit].pdev.name = DRIVER_NAME;
- platform_device_register(&ubd_dev[unit].pdev);
- disk->driverfs_dev = &ubd_dev[unit].pdev.dev;
+ ubd_devs[unit].pdev.id = unit;
+ ubd_devs[unit].pdev.name = DRIVER_NAME;
+ platform_device_register(&ubd_devs[unit].pdev);
+ disk->driverfs_dev = &ubd_devs[unit].pdev.dev;
}
- disk->private_data = &ubd_dev[unit];
+ disk->private_data = &ubd_devs[unit];
disk->queue = ubd_queue;
add_disk(disk);
@@ -660,25 +670,25 @@ static int ubd_new_disk(int major, u64 size, int unit,
static int ubd_add(int n)
{
- struct ubd *dev = &ubd_dev[n];
+ struct ubd *ubd_dev = &ubd_devs[n];
int err;
err = -ENODEV;
- if(dev->file == NULL)
+ if(ubd_dev->file == NULL)
goto out;
- err = ubd_file_size(dev, &dev->size);
+ err = ubd_file_size(ubd_dev, &ubd_dev->size);
if(err < 0)
goto out;
- dev->size = ROUND_BLOCK(dev->size);
+ ubd_dev->size = ROUND_BLOCK(ubd_dev->size);
- err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]);
+ err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]);
if(err)
goto out;
if(fake_major != MAJOR_NR)
- ubd_new_disk(fake_major, dev->size, n,
+ ubd_disk_register(fake_major, ubd_dev->size, n,
&fake_gendisk[n]);
/* perhaps this should also be under the "if (fake_major)" above */
@@ -693,32 +703,41 @@ out:
static int ubd_config(char *str)
{
- int n, err;
+ int n, ret;
str = kstrdup(str, GFP_KERNEL);
- if(str == NULL){
+ if (str == NULL) {
printk(KERN_ERR "ubd_config failed to strdup string\n");
- return(1);
+ ret = 1;
+ goto out;
}
- err = ubd_setup_common(str, &n);
- if(err){
- kfree(str);
- return(-1);
+ ret = ubd_setup_common(str, &n);
+ if (ret) {
+ ret = -1;
+ goto err_free;
+ }
+ if (n == -1) {
+ ret = 0;
+ goto err_free;
}
- if(n == -1) return(0);
- spin_lock(&ubd_lock);
- err = ubd_add(n);
- if(err)
- ubd_dev[n].file = NULL;
- spin_unlock(&ubd_lock);
+ mutex_lock(&ubd_lock);
+ ret = ubd_add(n);
+ if (ret)
+ ubd_devs[n].file = NULL;
+ mutex_unlock(&ubd_lock);
- return(err);
+out:
+ return ret;
+
+err_free:
+ kfree(str);
+ goto out;
}
static int ubd_get_config(char *name, char *str, int size, char **error_out)
{
- struct ubd *dev;
+ struct ubd *ubd_dev;
int n, len = 0;
n = parse_unit(&name);
@@ -727,24 +746,24 @@ static int ubd_get_config(char *name, char *str, int size, char **error_out)
return(-1);
}
- dev = &ubd_dev[n];
- spin_lock(&ubd_lock);
+ ubd_dev = &ubd_devs[n];
+ mutex_lock(&ubd_lock);
- if(dev->file == NULL){
+ if(ubd_dev->file == NULL){
CONFIG_CHUNK(str, size, len, "", 1);
goto out;
}
- CONFIG_CHUNK(str, size, len, dev->file, 0);
+ CONFIG_CHUNK(str, size, len, ubd_dev->file, 0);
- if(dev->cow.file != NULL){
+ if(ubd_dev->cow.file != NULL){
CONFIG_CHUNK(str, size, len, ",", 0);
- CONFIG_CHUNK(str, size, len, dev->cow.file, 1);
+ CONFIG_CHUNK(str, size, len, ubd_dev->cow.file, 1);
}
else CONFIG_CHUNK(str, size, len, "", 1);
out:
- spin_unlock(&ubd_lock);
+ mutex_unlock(&ubd_lock);
return(len);
}
@@ -760,22 +779,22 @@ static int ubd_id(char **str, int *start_out, int *end_out)
static int ubd_remove(int n)
{
- struct ubd *dev;
+ struct ubd *ubd_dev;
int err = -ENODEV;
- spin_lock(&ubd_lock);
+ mutex_lock(&ubd_lock);
if(ubd_gendisk[n] == NULL)
goto out;
- dev = &ubd_dev[n];
+ ubd_dev = &ubd_devs[n];
- if(dev->file == NULL)
+ if(ubd_dev->file == NULL)
goto out;
/* you cannot remove a open disk */
err = -EBUSY;
- if(dev->count > 0)
+ if(ubd_dev->count > 0)
goto out;
del_gendisk(ubd_gendisk[n]);
@@ -788,14 +807,15 @@ static int ubd_remove(int n)
fake_gendisk[n] = NULL;
}
- platform_device_unregister(&dev->pdev);
- *dev = ((struct ubd) DEFAULT_UBD);
+ platform_device_unregister(&ubd_dev->pdev);
+ *ubd_dev = ((struct ubd) DEFAULT_UBD);
err = 0;
out:
- spin_unlock(&ubd_lock);
+ mutex_unlock(&ubd_lock);
return err;
}
+/* All these are called by mconsole in process context and without ubd-specific locks. */
static struct mc_device ubd_mc = {
.name = "ubd",
.config = ubd_config,
@@ -804,7 +824,7 @@ static struct mc_device ubd_mc = {
.remove = ubd_remove,
};
-static int ubd_mc_init(void)
+static int __init ubd_mc_init(void)
{
mconsole_register_dev(&ubd_mc);
return 0;
@@ -812,13 +832,24 @@ static int ubd_mc_init(void)
__initcall(ubd_mc_init);
+static int __init ubd0_init(void)
+{
+ struct ubd *ubd_dev = &ubd_devs[0];
+
+ if(ubd_dev->file == NULL)
+ ubd_dev->file = "root_fs";
+ return(0);
+}
+
+__initcall(ubd0_init);
+
static struct platform_driver ubd_driver = {
.driver = {
.name = DRIVER_NAME,
},
};
-int ubd_init(void)
+static int __init ubd_init(void)
{
int i;
@@ -846,7 +877,7 @@ int ubd_init(void)
late_initcall(ubd_init);
-int ubd_driver_init(void){
+static int __init ubd_driver_init(void){
unsigned long stack;
int err;
@@ -867,7 +898,7 @@ int ubd_driver_init(void){
return(0);
}
err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr,
- IRQF_DISABLED, "ubd", ubd_dev);
+ IRQF_DISABLED, "ubd", ubd_devs);
if(err != 0)
printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
return 0;
@@ -878,24 +909,24 @@ device_initcall(ubd_driver_init);
static int ubd_open(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
- struct ubd *dev = disk->private_data;
+ struct ubd *ubd_dev = disk->private_data;
int err = 0;
- if(dev->count == 0){
- err = ubd_open_dev(dev);
+ if(ubd_dev->count == 0){
+ err = ubd_open_dev(ubd_dev);
if(err){
printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n",
- disk->disk_name, dev->file, -err);
+ disk->disk_name, ubd_dev->file, -err);
goto out;
}
}
- dev->count++;
- set_disk_ro(disk, !dev->openflags.w);
+ ubd_dev->count++;
+ set_disk_ro(disk, !ubd_dev->openflags.w);
/* This should no more be needed. And it didn't work anyway to exclude
* read-write remounting of filesystems.*/
- /*if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){
- if(--dev->count == 0) ubd_close(dev);
+ /*if((filp->f_mode & FMODE_WRITE) && !ubd_dev->openflags.w){
+ if(--ubd_dev->count == 0) ubd_close_dev(ubd_dev);
err = -EROFS;
}*/
out:
@@ -905,10 +936,10 @@ static int ubd_open(struct inode *inode, struct file *filp)
static int ubd_release(struct inode * inode, struct file * file)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
- struct ubd *dev = disk->private_data;
+ struct ubd *ubd_dev = disk->private_data;
- if(--dev->count == 0)
- ubd_close(dev);
+ if(--ubd_dev->count == 0)
+ ubd_close_dev(ubd_dev);
return(0);
}
@@ -976,12 +1007,12 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
static int prepare_request(struct request *req, struct io_thread_req *io_req)
{
struct gendisk *disk = req->rq_disk;
- struct ubd *dev = disk->private_data;
+ struct ubd *ubd_dev = disk->private_data;
__u64 offset;
int len;
/* This should be impossible now */
- if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
+ if((rq_data_dir(req) == WRITE) && !ubd_dev->openflags.w){
printk("Write attempted on readonly ubd device %s\n",
disk->disk_name);
end_request(req, 0);
@@ -991,8 +1022,8 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
offset = ((__u64) req->sector) << 9;
len = req->current_nr_sectors << 9;
- io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
- io_req->fds[1] = dev->fd;
+ io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd : ubd_dev->fd;
+ io_req->fds[1] = ubd_dev->fd;
io_req->cow_offset = -1;
io_req->offset = offset;
io_req->length = len;
@@ -1001,13 +1032,13 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
io_req->offsets[0] = 0;
- io_req->offsets[1] = dev->cow.data_offset;
+ io_req->offsets[1] = ubd_dev->cow.data_offset;
io_req->buffer = req->buffer;
io_req->sectorsize = 1 << 9;
- if(dev->cow.file != NULL)
- cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset,
- dev->cow.bitmap_len);
+ if(ubd_dev->cow.file != NULL)
+ cowify_req(io_req, ubd_dev->cow.bitmap, ubd_dev->cow.bitmap_offset,
+ ubd_dev->cow.bitmap_len);
return(0);
}
@@ -1033,7 +1064,7 @@ static void do_ubd_request(request_queue_t *q)
return;
err = prepare_request(req, &io_req);
if(!err){
- do_ubd = ubd_handler;
+ do_ubd = 1;
n = os_write_file(thread_fd, (char *) &io_req,
sizeof(io_req));
if(n != sizeof(io_req))
@@ -1045,18 +1076,18 @@ static void do_ubd_request(request_queue_t *q)
static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct ubd *dev = bdev->bd_disk->private_data;
+ struct ubd *ubd_dev = bdev->bd_disk->private_data;
geo->heads = 128;
geo->sectors = 32;
- geo->cylinders = dev->size / (128 * 32 * 512);
+ geo->cylinders = ubd_dev->size / (128 * 32 * 512);
return 0;
}
static int ubd_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg)
{
- struct ubd *dev = inode->i_bdev->bd_disk->private_data;
+ struct ubd *ubd_dev = inode->i_bdev->bd_disk->private_data;
struct hd_driveid ubd_id = {
.cyls = 0,
.heads = 128,
@@ -1066,7 +1097,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
switch (cmd) {
struct cdrom_volctrl volume;
case HDIO_GET_IDENTITY:
- ubd_id.cyls = dev->size / (128 * 32 * 512);
+ ubd_id.cyls = ubd_dev->size / (128 * 32 * 512);
if(copy_to_user((char __user *) arg, (char *) &ubd_id,
sizeof(ubd_id)))
return(-EFAULT);
@@ -1353,8 +1384,8 @@ void do_io(struct io_thread_req *req)
*/
int kernel_fd = -1;
-/* Only changed by the io thread */
-int io_count = 0;
+/* Only changed by the io thread. XXX: currently unused. */
+static int io_count = 0;
int io_thread(void *arg)
{
diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h
index 58f67d391105..2666815b6af5 100644
--- a/arch/um/include/mconsole.h
+++ b/arch/um/include/mconsole.h
@@ -61,6 +61,7 @@ struct mc_request
struct mconsole_request request;
struct mconsole_command *cmd;
+ union uml_pt_regs regs;
};
extern char mconsole_socket_name[];
diff --git a/arch/um/include/mconsole_kern.h b/arch/um/include/mconsole_kern.h
index d0b690197fd7..1ea6d928e1cd 100644
--- a/arch/um/include/mconsole_kern.h
+++ b/arch/um/include/mconsole_kern.h
@@ -14,6 +14,7 @@ struct mconsole_entry {
struct mc_request request;
};
+/* All these methods are called in process context. */
struct mc_device {
struct list_head list;
char *name;
diff --git a/arch/um/include/sysdep-i386/barrier.h b/arch/um/include/sysdep-i386/barrier.h
new file mode 100644
index 000000000000..b58d52c5b2f4
--- /dev/null
+++ b/arch/um/include/sysdep-i386/barrier.h
@@ -0,0 +1,9 @@
+#ifndef __SYSDEP_I386_BARRIER_H
+#define __SYSDEP_I386_BARRIER_H
+
+/* Copied from include/asm-i386 for use by userspace. i386 has the option
+ * of using mfence, but I'm just using this, which works everywhere, for now.
+ */
+#define mb() asm volatile("lock; addl $0,0(%esp)")
+
+#endif
diff --git a/arch/um/include/sysdep-x86_64/barrier.h b/arch/um/include/sysdep-x86_64/barrier.h
new file mode 100644
index 000000000000..7b610befdc8f
--- /dev/null
+++ b/arch/um/include/sysdep-x86_64/barrier.h
@@ -0,0 +1,7 @@
+#ifndef __SYSDEP_X86_64_BARRIER_H
+#define __SYSDEP_X86_64_BARRIER_H
+
+/* Copied from include/asm-x86_64 for use by userspace. */
+#define mb() asm volatile("mfence":::"memory")
+
+#endif
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index 68ed24df5c8f..e36f92b463ce 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -14,6 +14,7 @@ SECTIONS
* is remapped.*/
__binary_start = .;
. = ALIGN(4096); /* Init code and data */
+ _text = .;
_stext = .;
__init_begin = .;
.init.text : {
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
index 9882342206ec..b9195355075a 100644
--- a/arch/um/kernel/tt/tracer.c
+++ b/arch/um/kernel/tt/tracer.c
@@ -176,7 +176,6 @@ struct {
int signal_index[32];
int nsignals = 0;
int debug_trace = 0;
-extern int io_nsignals, io_count, intr_count;
extern void signal_usr1(int sig);
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index 8eca47a6ff08..f6301274cf3c 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -25,6 +25,7 @@ SECTIONS
. = ALIGN(4096); /* Init code and data */
#endif
+ _text = .;
_stext = .;
__init_begin = .;
.init.text : {
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 51f0893640a6..c692a192957a 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 <linux/unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/mman.h>
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 6b81739279d1..b897e8592d77 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -15,6 +15,7 @@
#include "user.h"
#include "signal_kern.h"
#include "sysdep/sigcontext.h"
+#include "sysdep/barrier.h"
#include "sigcontext.h"
#include "mode.h"
#include "os.h"
@@ -34,8 +35,12 @@
#define SIGALRM_BIT 2
#define SIGALRM_MASK (1 << SIGALRM_BIT)
-static int signals_enabled = 1;
-static int pending = 0;
+/* These are used by both the signal handlers and
+ * block/unblock_signals. I don't want modifications cached in a
+ * register - they must go straight to memory.
+ */
+static volatile int signals_enabled = 1;
+static volatile int pending = 0;
void sig_handler(int sig, struct sigcontext *sc)
{
@@ -152,6 +157,12 @@ int change_sig(int signal, int on)
void block_signals(void)
{
signals_enabled = 0;
+ /* This must return with signals disabled, so this barrier
+ * ensures that writes are flushed out before the return.
+ * This might matter if gcc figures out how to inline this and
+ * decides to shuffle this code into the caller.
+ */
+ mb();
}
void unblock_signals(void)
@@ -171,9 +182,23 @@ void unblock_signals(void)
*/
signals_enabled = 1;
+ /* Setting signals_enabled and reading pending must
+ * happen in this order.
+ */
+ mb();
+
save_pending = pending;
- if(save_pending == 0)
+ if(save_pending == 0){
+ /* This must return with signals enabled, so
+ * this barrier ensures that writes are
+ * flushed out before the return. This might
+ * matter if gcc figures out how to inline
+ * this (unlikely, given its size) and decides
+ * to shuffle this code into the caller.
+ */
+ mb();
return;
+ }
pending = 0;
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index cb9ab54146cc..9b34fe65949a 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -14,7 +14,7 @@
#include <sys/mman.h>
#include <sys/user.h>
#include <sys/time.h>
-#include <asm/unistd.h>
+#include <sys/syscall.h>
#include <asm/types.h>
#include "user.h"
#include "sysdep/ptrace.h"
diff --git a/arch/um/os-Linux/sys-i386/tls.c b/arch/um/os-Linux/sys-i386/tls.c
index 6e945ab45843..256532034c62 100644
--- a/arch/um/os-Linux/sys-i386/tls.c
+++ b/arch/um/os-Linux/sys-i386/tls.c
@@ -1,6 +1,9 @@
#include <errno.h>
#include <linux/unistd.h>
+
#include <sys/syscall.h>
+#include <unistd.h>
+
#include "sysdep/tls.h"
#include "user_util.h"
diff --git a/arch/um/os-Linux/tls.c b/arch/um/os-Linux/tls.c
index a2de2580b8af..16215b990804 100644
--- a/arch/um/os-Linux/tls.c
+++ b/arch/um/os-Linux/tls.c
@@ -1,4 +1,5 @@
#include <errno.h>
+#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/syscall.h>
#include <asm/ldt.h>
diff --git a/arch/um/sys-i386/unmap.c b/arch/um/sys-i386/unmap.c
index 8e55cd5d3d07..1b0ad0e4adcd 100644
--- a/arch/um/sys-i386/unmap.c
+++ b/arch/um/sys-i386/unmap.c
@@ -5,17 +5,20 @@
#include <linux/mman.h>
#include <asm/unistd.h>
-#include <sys/syscall.h>
+static int errno;
+
+static inline _syscall2(int,munmap,void *,start,size_t,len)
+static inline _syscall6(void *,mmap2,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset)
int switcheroo(int fd, int prot, void *from, void *to, int size)
{
- if (syscall(__NR_munmap, to, size) < 0){
+ if(munmap(to, size) < 0){
return(-1);
}
- if (syscall(__NR_mmap2, to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1 ){
+ if(mmap2(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1 ){
return(-1);
}
- if (syscall(__NR_munmap, from, size) < 0){
+ if(munmap(from, size) < 0){
return(-1);
}
return(0);
diff --git a/arch/um/sys-x86_64/unmap.c b/arch/um/sys-x86_64/unmap.c
index 57c9286a701b..f4a4bffd8a18 100644
--- a/arch/um/sys-x86_64/unmap.c
+++ b/arch/um/sys-x86_64/unmap.c
@@ -5,17 +5,20 @@
#include <linux/mman.h>
#include <asm/unistd.h>
-#include <sys/syscall.h>
+static int errno;
+
+static inline _syscall2(int,munmap,void *,start,size_t,len)
+static inline _syscall6(void *,mmap,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset)
int switcheroo(int fd, int prot, void *from, void *to, int size)
{
- if (syscall(__NR_munmap, to, size) < 0){
+ if(munmap(to, size) < 0){
return(-1);
}
- if (syscall(__NR_mmap, to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1){
+ if(mmap(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1){
return(-1);
}
- if (syscall(__NR_munmap, from, size) < 0){
+ if(munmap(from, size) < 0){
return(-1);
}
return(0);