aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2006-01-20 03:59:41 -0500
committerSteven Whitehouse <steve@chygwyn.com>2006-01-20 03:59:41 -0500
commit044399b2cb6ad2d7f63cfca945268853d7443a4d (patch)
tree5f96eb307b0389ac0b919a4744a40862b615e9da /arch/um
parent901359256b2666f52a3a7d3f31927677e91b3a2a (diff)
parent18a4144028f056b77d6576d4eb284246e9c7ea97 (diff)
Merge branch 'master'
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/Kconfig27
-rw-r--r--arch/um/Kconfig.i3866
-rw-r--r--arch/um/Makefile2
-rw-r--r--arch/um/drivers/daemon_kern.c4
-rw-r--r--arch/um/drivers/daemon_user.c6
-rw-r--r--arch/um/drivers/fd.c1
-rw-r--r--arch/um/drivers/net_kern.c21
-rw-r--r--arch/um/drivers/ubd_kern.c59
-rw-r--r--arch/um/include/kern_util.h4
-rw-r--r--arch/um/include/longjmp.h19
-rw-r--r--arch/um/include/mode_kern.h15
-rw-r--r--arch/um/include/os.h58
-rw-r--r--arch/um/include/skas/mm_id.h (renamed from arch/um/kernel/skas/include/mm_id.h)0
-rw-r--r--arch/um/include/skas/mmu-skas.h24
-rw-r--r--arch/um/include/skas/mode-skas.h19
-rw-r--r--arch/um/include/skas/mode_kern_skas.h (renamed from arch/um/kernel/skas/include/mode_kern-skas.h)12
-rw-r--r--arch/um/include/skas/proc_mm.h (renamed from arch/um/kernel/skas/include/proc_mm.h)17
-rw-r--r--arch/um/include/skas/skas.h26
-rw-r--r--arch/um/include/skas/stub-data.h (renamed from arch/um/kernel/skas/include/stub-data.h)0
-rw-r--r--arch/um/include/skas/uaccess-skas.h (renamed from arch/um/kernel/skas/include/uaccess-skas.h)11
-rw-r--r--arch/um/include/time_user.h19
-rw-r--r--arch/um/include/tt/debug.h (renamed from arch/um/kernel/tt/include/debug.h)2
-rw-r--r--arch/um/include/tt/mmu-tt.h12
-rw-r--r--arch/um/include/tt/mode-tt.h23
-rw-r--r--arch/um/include/tt/mode_kern_tt.h41
-rw-r--r--arch/um/include/tt/tt.h (renamed from arch/um/kernel/tt/include/tt.h)12
-rw-r--r--arch/um/include/tt/uaccess-tt.h (renamed from arch/um/kernel/tt/include/uaccess-tt.h)11
-rw-r--r--arch/um/include/user.h1
-rw-r--r--arch/um/include/user_util.h18
-rw-r--r--arch/um/kernel/Makefile7
-rw-r--r--arch/um/kernel/exec_kern.c1
-rw-r--r--arch/um/kernel/process_kern.c22
-rw-r--r--arch/um/kernel/sigio_user.c83
-rw-r--r--arch/um/kernel/signal_kern.c91
-rw-r--r--arch/um/kernel/skas/Makefile6
-rw-r--r--arch/um/kernel/skas/include/mmu-skas.h35
-rw-r--r--arch/um/kernel/skas/include/mode-skas.h33
-rw-r--r--arch/um/kernel/skas/include/skas.h49
-rw-r--r--arch/um/kernel/skas/mmu.c8
-rw-r--r--arch/um/kernel/skas/process.c1
-rw-r--r--arch/um/kernel/skas/process_kern.c35
-rw-r--r--arch/um/kernel/skas/uaccess.c2
-rw-r--r--arch/um/kernel/syscall.c4
-rw-r--r--arch/um/kernel/time_kern.c132
-rw-r--r--arch/um/kernel/tt/exec_kern.c1
-rw-r--r--arch/um/kernel/tt/gdb.c1
-rw-r--r--arch/um/kernel/tt/include/mmu-tt.h23
-rw-r--r--arch/um/kernel/tt/process_kern.c1
-rw-r--r--arch/um/kernel/tt/ptproxy/ptrace.c1
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.c1
-rw-r--r--arch/um/kernel/tt/trap_user.c5
-rw-r--r--arch/um/os-Linux/Makefile4
-rw-r--r--arch/um/os-Linux/helper.c4
-rw-r--r--arch/um/os-Linux/main.c13
-rw-r--r--arch/um/os-Linux/process.c30
-rw-r--r--arch/um/os-Linux/signal.c218
-rw-r--r--arch/um/os-Linux/skas/Makefile4
-rw-r--r--arch/um/os-Linux/skas/mem.c (renamed from arch/um/kernel/skas/mem_user.c)202
-rw-r--r--arch/um/os-Linux/skas/process.c566
-rw-r--r--arch/um/os-Linux/start_up.c1
-rw-r--r--arch/um/os-Linux/time.c131
-rw-r--r--arch/um/os-Linux/trap.c3
-rw-r--r--arch/um/os-Linux/tt.c49
-rw-r--r--arch/um/os-Linux/uaccess.c4
-rw-r--r--arch/um/os-Linux/util.c (renamed from arch/um/kernel/user_util.c)69
-rw-r--r--arch/um/sys-i386/ldt.c26
66 files changed, 1558 insertions, 778 deletions
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 8ff3bcbce5fc..5982fe2753e0 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -143,6 +143,7 @@ config HOSTFS
143 143
144config HPPFS 144config HPPFS
145 tristate "HoneyPot ProcFS (EXPERIMENTAL)" 145 tristate "HoneyPot ProcFS (EXPERIMENTAL)"
146 depends on EXPERIMENTAL
146 help 147 help
147 hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc 148 hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
148 entries to be overridden, removed, or fabricated from the host. 149 entries to be overridden, removed, or fabricated from the host.
@@ -155,10 +156,6 @@ config HPPFS
155 You only need this if you are setting up a UML honeypot. Otherwise, 156 You only need this if you are setting up a UML honeypot. Otherwise,
156 it is safe to say 'N' here. 157 it is safe to say 'N' here.
157 158
158 If you are actively using it, please report any problems, since it's
159 getting fixed. In this moment, it is experimental on 2.6 (it works on
160 2.4).
161
162config MCONSOLE 159config MCONSOLE
163 bool "Management console" 160 bool "Management console"
164 default y 161 default y
@@ -243,8 +240,16 @@ config NEST_LEVEL
243 Only change this if you are running nested UMLs. 240 Only change this if you are running nested UMLs.
244 241
245config HIGHMEM 242config HIGHMEM
246 bool "Highmem support" 243 bool "Highmem support (EXPERIMENTAL)"
247 depends on !64BIT 244 depends on !64BIT && EXPERIMENTAL
245 default n
246 help
247 This was used to allow UML to run with big amounts of memory.
248 Currently it is unstable, so if unsure say N.
249
250 To use big amounts of memory, it is recommended to disable TT mode (i.e.
251 CONFIG_MODE_TT) and enable static linking (i.e. CONFIG_STATIC_LINK) -
252 this should allow the guest to use up to 2.75G of memory.
248 253
249config KERNEL_STACK_ORDER 254config KERNEL_STACK_ORDER
250 int "Kernel stack size order" 255 int "Kernel stack size order"
@@ -269,17 +274,13 @@ endmenu
269 274
270source "init/Kconfig" 275source "init/Kconfig"
271 276
272source "net/Kconfig" 277source "drivers/block/Kconfig"
273
274source "drivers/base/Kconfig"
275 278
276source "arch/um/Kconfig.char" 279source "arch/um/Kconfig.char"
277 280
278source "drivers/block/Kconfig" 281source "drivers/base/Kconfig"
279 282
280config NETDEVICES 283source "net/Kconfig"
281 bool
282 default NET
283 284
284source "arch/um/Kconfig.net" 285source "arch/um/Kconfig.net"
285 286
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386
index c71b39a677aa..ef79ed25aecd 100644
--- a/arch/um/Kconfig.i386
+++ b/arch/um/Kconfig.i386
@@ -22,13 +22,17 @@ config TOP_ADDR
22 default 0x80000000 if HOST_2G_2G 22 default 0x80000000 if HOST_2G_2G
23 23
24config 3_LEVEL_PGTABLES 24config 3_LEVEL_PGTABLES
25 bool "Three-level pagetables" 25 bool "Three-level pagetables (EXPERIMENTAL)"
26 default n 26 default n
27 depends on EXPERIMENTAL
27 help 28 help
28 Three-level pagetables will let UML have more than 4G of physical 29 Three-level pagetables will let UML have more than 4G of physical
29 memory. All the memory that can't be mapped directly will be treated 30 memory. All the memory that can't be mapped directly will be treated
30 as high memory. 31 as high memory.
31 32
33 However, this it experimental on 32-bit architectures, so if unsure say
34 N (on x86-64 it's automatically enabled, instead, as it's safe there).
35
32config STUB_CODE 36config STUB_CODE
33 hex 37 hex
34 default 0xbfffe000 38 default 0xbfffe000
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 45435ff589c1..6430a6383853 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -32,7 +32,7 @@ um-modes-$(CONFIG_MODE_TT) += tt
32um-modes-$(CONFIG_MODE_SKAS) += skas 32um-modes-$(CONFIG_MODE_SKAS) += skas
33 33
34MODE_INCLUDE += $(foreach mode,$(um-modes-y),\ 34MODE_INCLUDE += $(foreach mode,$(um-modes-y),\
35 -I$(srctree)/$(ARCH_DIR)/kernel/$(mode)/include) 35 -I$(srctree)/$(ARCH_DIR)/include/$(mode))
36 36
37MAKEFILES-INCL += $(foreach mode,$(um-modes-y),\ 37MAKEFILES-INCL += $(foreach mode,$(um-modes-y),\
38 $(srctree)/$(ARCH_DIR)/Makefile-$(mode)) 38 $(srctree)/$(ARCH_DIR)/Makefile-$(mode))
diff --git a/arch/um/drivers/daemon_kern.c b/arch/um/drivers/daemon_kern.c
index 30d285b266af..507e3cbac9d3 100644
--- a/arch/um/drivers/daemon_kern.c
+++ b/arch/um/drivers/daemon_kern.c
@@ -31,6 +31,10 @@ void daemon_init(struct net_device *dev, void *data)
31 dpri->fd = -1; 31 dpri->fd = -1;
32 dpri->control = -1; 32 dpri->control = -1;
33 dpri->dev = dev; 33 dpri->dev = dev;
34 /* We will free this pointer. If it contains crap we're burned. */
35 dpri->ctl_addr = NULL;
36 dpri->data_addr = NULL;
37 dpri->local_addr = NULL;
34 38
35 printk("daemon backend (uml_switch version %d) - %s:%s", 39 printk("daemon backend (uml_switch version %d) - %s:%s",
36 SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock); 40 SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock);
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index 1bb085b2824d..c944265955e2 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -158,10 +158,16 @@ static void daemon_remove(void *data)
158 struct daemon_data *pri = data; 158 struct daemon_data *pri = data;
159 159
160 os_close_file(pri->fd); 160 os_close_file(pri->fd);
161 pri->fd = -1;
161 os_close_file(pri->control); 162 os_close_file(pri->control);
163 pri->control = -1;
164
162 kfree(pri->data_addr); 165 kfree(pri->data_addr);
166 pri->data_addr = NULL;
163 kfree(pri->ctl_addr); 167 kfree(pri->ctl_addr);
168 pri->ctl_addr = NULL;
164 kfree(pri->local_addr); 169 kfree(pri->local_addr);
170 pri->local_addr = NULL;
165} 171}
166 172
167int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri) 173int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri)
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index 3296e86a03a5..c41f75e4acb5 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -11,6 +11,7 @@
11#include "user.h" 11#include "user.h"
12#include "user_util.h" 12#include "user_util.h"
13#include "chan_user.h" 13#include "chan_user.h"
14#include "os.h"
14 15
15struct fd_chan { 16struct fd_chan {
16 int fd; 17 int fd;
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index fb1f9fb9b871..8ebb2241ad42 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -68,6 +68,11 @@ static int uml_net_rx(struct net_device *dev)
68 return pkt_len; 68 return pkt_len;
69} 69}
70 70
71static void uml_dev_close(void* dev)
72{
73 dev_close( (struct net_device *) dev);
74}
75
71irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs) 76irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
72{ 77{
73 struct net_device *dev = dev_id; 78 struct net_device *dev = dev_id;
@@ -80,15 +85,21 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
80 spin_lock(&lp->lock); 85 spin_lock(&lp->lock);
81 while((err = uml_net_rx(dev)) > 0) ; 86 while((err = uml_net_rx(dev)) > 0) ;
82 if(err < 0) { 87 if(err < 0) {
88 DECLARE_WORK(close_work, uml_dev_close, dev);
83 printk(KERN_ERR 89 printk(KERN_ERR
84 "Device '%s' read returned %d, shutting it down\n", 90 "Device '%s' read returned %d, shutting it down\n",
85 dev->name, err); 91 dev->name, err);
86 dev_close(dev); 92 /* dev_close can't be called in interrupt context, and takes
93 * again lp->lock.
94 * And dev_close() can be safely called multiple times on the
95 * same device, since it tests for (dev->flags & IFF_UP). So
96 * there's no harm in delaying the device shutdown. */
97 schedule_work(&close_work);
87 goto out; 98 goto out;
88 } 99 }
89 reactivate_fd(lp->fd, UM_ETH_IRQ); 100 reactivate_fd(lp->fd, UM_ETH_IRQ);
90 101
91 out: 102out:
92 spin_unlock(&lp->lock); 103 spin_unlock(&lp->lock);
93 return(IRQ_HANDLED); 104 return(IRQ_HANDLED);
94} 105}
@@ -317,6 +328,11 @@ static int eth_configure(int n, void *init, char *mac,
317 return 1; 328 return 1;
318 } 329 }
319 330
331 lp = dev->priv;
332 /* This points to the transport private data. It's still clear, but we
333 * must memset it to 0 *now*. Let's help the drivers. */
334 memset(lp, 0, size);
335
320 /* sysfs register */ 336 /* sysfs register */
321 if (!driver_registered) { 337 if (!driver_registered) {
322 platform_driver_register(&uml_net_driver); 338 platform_driver_register(&uml_net_driver);
@@ -358,7 +374,6 @@ static int eth_configure(int n, void *init, char *mac,
358 free_netdev(dev); 374 free_netdev(dev);
359 return 1; 375 return 1;
360 } 376 }
361 lp = dev->priv;
362 377
363 /* lp.user is the first four bytes of the transport data, which 378 /* lp.user is the first four bytes of the transport data, which
364 * has already been initialized. This structure assignment will 379 * has already been initialized. This structure assignment will
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 7696f8d2d89c..101efd26d467 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -1103,31 +1103,33 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
1103 return(-EINVAL); 1103 return(-EINVAL);
1104} 1104}
1105 1105
1106static int same_backing_files(char *from_cmdline, char *from_cow, char *cow) 1106static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow)
1107{ 1107{
1108 struct uml_stat buf1, buf2; 1108 struct uml_stat buf1, buf2;
1109 int err; 1109 int err;
1110 1110
1111 if(from_cmdline == NULL) return(1); 1111 if(from_cmdline == NULL)
1112 if(!strcmp(from_cmdline, from_cow)) return(1); 1112 return 0;
1113 if(!strcmp(from_cmdline, from_cow))
1114 return 0;
1113 1115
1114 err = os_stat_file(from_cmdline, &buf1); 1116 err = os_stat_file(from_cmdline, &buf1);
1115 if(err < 0){ 1117 if(err < 0){
1116 printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err); 1118 printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err);
1117 return(1); 1119 return 0;
1118 } 1120 }
1119 err = os_stat_file(from_cow, &buf2); 1121 err = os_stat_file(from_cow, &buf2);
1120 if(err < 0){ 1122 if(err < 0){
1121 printk("Couldn't stat '%s', err = %d\n", from_cow, -err); 1123 printk("Couldn't stat '%s', err = %d\n", from_cow, -err);
1122 return(1); 1124 return 1;
1123 } 1125 }
1124 if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino)) 1126 if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino))
1125 return(1); 1127 return 0;
1126 1128
1127 printk("Backing file mismatch - \"%s\" requested,\n" 1129 printk("Backing file mismatch - \"%s\" requested,\n"
1128 "\"%s\" specified in COW header of \"%s\"\n", 1130 "\"%s\" specified in COW header of \"%s\"\n",
1129 from_cmdline, from_cow, cow); 1131 from_cmdline, from_cow, cow);
1130 return(0); 1132 return 1;
1131} 1133}
1132 1134
1133static int backing_file_mismatch(char *file, __u64 size, time_t mtime) 1135static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
@@ -1189,18 +1191,19 @@ int open_ubd_file(char *file, struct openflags *openflags,
1189 unsigned long long size; 1191 unsigned long long size;
1190 __u32 version, align; 1192 __u32 version, align;
1191 char *backing_file; 1193 char *backing_file;
1192 int fd, err, sectorsize, same, mode = 0644; 1194 int fd, err, sectorsize, asked_switch, mode = 0644;
1193 1195
1194 fd = os_open_file(file, *openflags, mode); 1196 fd = os_open_file(file, *openflags, mode);
1195 if(fd < 0){ 1197 if (fd < 0) {
1196 if((fd == -ENOENT) && (create_cow_out != NULL)) 1198 if ((fd == -ENOENT) && (create_cow_out != NULL))
1197 *create_cow_out = 1; 1199 *create_cow_out = 1;
1198 if(!openflags->w || 1200 if (!openflags->w ||
1199 ((fd != -EROFS) && (fd != -EACCES))) return(fd); 1201 ((fd != -EROFS) && (fd != -EACCES)))
1202 return fd;
1200 openflags->w = 0; 1203 openflags->w = 0;
1201 fd = os_open_file(file, *openflags, mode); 1204 fd = os_open_file(file, *openflags, mode);
1202 if(fd < 0) 1205 if (fd < 0)
1203 return(fd); 1206 return fd;
1204 } 1207 }
1205 1208
1206 err = os_lock_file(fd, openflags->w); 1209 err = os_lock_file(fd, openflags->w);
@@ -1209,7 +1212,9 @@ int open_ubd_file(char *file, struct openflags *openflags,
1209 goto out_close; 1212 goto out_close;
1210 } 1213 }
1211 1214
1212 if(backing_file_out == NULL) return(fd); 1215 /* Succesful return case! */
1216 if(backing_file_out == NULL)
1217 return(fd);
1213 1218
1214 err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime, 1219 err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
1215 &size, &sectorsize, &align, bitmap_offset_out); 1220 &size, &sectorsize, &align, bitmap_offset_out);
@@ -1218,34 +1223,34 @@ int open_ubd_file(char *file, struct openflags *openflags,
1218 "errno = %d\n", file, -err); 1223 "errno = %d\n", file, -err);
1219 goto out_close; 1224 goto out_close;
1220 } 1225 }
1221 if(err) return(fd); 1226 if(err)
1222 1227 return(fd);
1223 if(backing_file_out == NULL) return(fd);
1224 1228
1225 same = same_backing_files(*backing_file_out, backing_file, file); 1229 asked_switch = path_requires_switch(*backing_file_out, backing_file, file);
1226 1230
1227 if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){ 1231 /* Allow switching only if no mismatch. */
1232 if (asked_switch && !backing_file_mismatch(*backing_file_out, size, mtime)) {
1228 printk("Switching backing file to '%s'\n", *backing_file_out); 1233 printk("Switching backing file to '%s'\n", *backing_file_out);
1229 err = write_cow_header(file, fd, *backing_file_out, 1234 err = write_cow_header(file, fd, *backing_file_out,
1230 sectorsize, align, &size); 1235 sectorsize, align, &size);
1231 if(err){ 1236 if (err) {
1232 printk("Switch failed, errno = %d\n", -err); 1237 printk("Switch failed, errno = %d\n", -err);
1233 return(err); 1238 goto out_close;
1234 } 1239 }
1235 } 1240 } else {
1236 else {
1237 *backing_file_out = backing_file; 1241 *backing_file_out = backing_file;
1238 err = backing_file_mismatch(*backing_file_out, size, mtime); 1242 err = backing_file_mismatch(*backing_file_out, size, mtime);
1239 if(err) goto out_close; 1243 if (err)
1244 goto out_close;
1240 } 1245 }
1241 1246
1242 cow_sizes(version, size, sectorsize, align, *bitmap_offset_out, 1247 cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
1243 bitmap_len_out, data_offset_out); 1248 bitmap_len_out, data_offset_out);
1244 1249
1245 return(fd); 1250 return fd;
1246 out_close: 1251 out_close:
1247 os_close_file(fd); 1252 os_close_file(fd);
1248 return(err); 1253 return err;
1249} 1254}
1250 1255
1251int create_cow_file(char *cow_file, char *backing_file, struct openflags flags, 1256int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 8f4e46d677ab..c649108a9e9f 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -120,8 +120,10 @@ extern void machine_halt(void);
120extern int is_syscall(unsigned long addr); 120extern int is_syscall(unsigned long addr);
121extern void arch_switch(void); 121extern void arch_switch(void);
122extern void free_irq(unsigned int, void *); 122extern void free_irq(unsigned int, void *);
123extern int um_in_interrupt(void);
124extern int cpu(void); 123extern int cpu(void);
124
125/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */
126extern int __cant_sleep(void);
125extern void segv_handler(int sig, union uml_pt_regs *regs); 127extern void segv_handler(int sig, union uml_pt_regs *regs);
126extern void sigio_handler(int sig, union uml_pt_regs *regs); 128extern void sigio_handler(int sig, union uml_pt_regs *regs);
127 129
diff --git a/arch/um/include/longjmp.h b/arch/um/include/longjmp.h
new file mode 100644
index 000000000000..018b3819ab0b
--- /dev/null
+++ b/arch/um/include/longjmp.h
@@ -0,0 +1,19 @@
1#ifndef __UML_LONGJMP_H
2#define __UML_LONGJMP_H
3
4#include <setjmp.h>
5#include "os.h"
6
7#define UML_SIGLONGJMP(buf, val) do { \
8 longjmp(*buf, val); \
9} while(0)
10
11#define UML_SIGSETJMP(buf, enable) ({ \
12 int n; \
13 enable = get_signals(); \
14 n = setjmp(*buf); \
15 if(n != 0) \
16 set_signals(enable); \
17 n; })
18
19#endif
diff --git a/arch/um/include/mode_kern.h b/arch/um/include/mode_kern.h
index 2d88afd0cf16..e7539a8451ef 100644
--- a/arch/um/include/mode_kern.h
+++ b/arch/um/include/mode_kern.h
@@ -9,22 +9,11 @@
9#include "linux/config.h" 9#include "linux/config.h"
10 10
11#ifdef CONFIG_MODE_TT 11#ifdef CONFIG_MODE_TT
12#include "mode_kern-tt.h" 12#include "mode_kern_tt.h"
13#endif 13#endif
14 14
15#ifdef CONFIG_MODE_SKAS 15#ifdef CONFIG_MODE_SKAS
16#include "mode_kern-skas.h" 16#include "mode_kern_skas.h"
17#endif 17#endif
18 18
19#endif 19#endif
20
21/*
22 * Overrides for Emacs so that we follow Linus's tabbing style.
23 * Emacs will notice this stuff at the end of the file and automatically
24 * adjust the settings for this buffer only. This must remain at the end
25 * of the file.
26 * ---------------------------------------------------------------------------
27 * Local variables:
28 * c-file-style: "linux"
29 * End:
30 */
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index dd72d66cf0ed..eb1710b81255 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -11,6 +11,7 @@
11#include "../os/include/file.h" 11#include "../os/include/file.h"
12#include "sysdep/ptrace.h" 12#include "sysdep/ptrace.h"
13#include "kern_util.h" 13#include "kern_util.h"
14#include "skas/mm_id.h"
14 15
15#define OS_TYPE_FILE 1 16#define OS_TYPE_FILE 1
16#define OS_TYPE_DIR 2 17#define OS_TYPE_DIR 2
@@ -190,11 +191,12 @@ extern int os_protect_memory(void *addr, unsigned long len,
190 int r, int w, int x); 191 int r, int w, int x);
191extern int os_unmap_memory(void *addr, int len); 192extern int os_unmap_memory(void *addr, int len);
192extern void os_flush_stdout(void); 193extern void os_flush_stdout(void);
193extern unsigned long long os_usecs(void);
194 194
195/* tt.c 195/* tt.c
196 * for tt mode only (will be deleted in future...) 196 * for tt mode only (will be deleted in future...)
197 */ 197 */
198extern void stop(void);
199extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
198extern int protect_memory(unsigned long addr, unsigned long len, 200extern int protect_memory(unsigned long addr, unsigned long len,
199 int r, int w, int x, int must_succeed); 201 int r, int w, int x, int must_succeed);
200extern void forward_pending_sigio(int target); 202extern void forward_pending_sigio(int target);
@@ -230,9 +232,63 @@ extern void block_signals(void);
230extern void unblock_signals(void); 232extern void unblock_signals(void);
231extern int get_signals(void); 233extern int get_signals(void);
232extern int set_signals(int enable); 234extern int set_signals(int enable);
235extern void os_usr1_signal(int on);
233 236
234/* trap.c */ 237/* trap.c */
235extern void os_fill_handlinfo(struct kern_handlers h); 238extern void os_fill_handlinfo(struct kern_handlers h);
236extern void do_longjmp(void *p, int val); 239extern void do_longjmp(void *p, int val);
237 240
241/* util.c */
242extern void stack_protections(unsigned long address);
243extern void task_protections(unsigned long address);
244extern int raw(int fd);
245extern void setup_machinename(char *machine_out);
246extern void setup_hostinfo(void);
247extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
248
249/* time.c */
250#define BILLION (1000 * 1000 * 1000)
251
252extern void switch_timers(int to_real);
253extern void idle_sleep(int secs);
254extern void enable_timer(void);
255extern void disable_timer(void);
256extern void user_time_init(void);
257extern void uml_idle_timer(void);
258extern unsigned long long os_nsecs(void);
259
260/* skas/mem.c */
261extern long run_syscall_stub(struct mm_id * mm_idp,
262 int syscall, unsigned long *args, long expected,
263 void **addr, int done);
264extern long syscall_stub_data(struct mm_id * mm_idp,
265 unsigned long *data, int data_count,
266 void **addr, void **stub_addr);
267extern int map(struct mm_id * mm_idp, unsigned long virt,
268 unsigned long len, int r, int w, int x, int phys_fd,
269 unsigned long long offset, int done, void **data);
270extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len,
271 int done, void **data);
272extern int protect(struct mm_id * mm_idp, unsigned long addr,
273 unsigned long len, int r, int w, int x, int done,
274 void **data);
275
276/* skas/process.c */
277extern int is_skas_winch(int pid, int fd, void *data);
278extern int start_userspace(unsigned long stub_stack);
279extern int copy_context_skas0(unsigned long stack, int pid);
280extern void userspace(union uml_pt_regs *regs);
281extern void map_stub_pages(int fd, unsigned long code,
282 unsigned long data, unsigned long stack);
283extern void new_thread(void *stack, void **switch_buf_ptr,
284 void **fork_buf_ptr, void (*handler)(int));
285extern void thread_wait(void *sw, void *fb);
286extern void switch_threads(void *me, void *next);
287extern int start_idle_thread(void *stack, void *switch_buf_ptr,
288 void **fork_buf_ptr);
289extern void initial_thread_cb_skas(void (*proc)(void *),
290 void *arg);
291extern void halt_skas(void);
292extern void reboot_skas(void);
293
238#endif 294#endif
diff --git a/arch/um/kernel/skas/include/mm_id.h b/arch/um/include/skas/mm_id.h
index 48dd0989ddaa..48dd0989ddaa 100644
--- a/arch/um/kernel/skas/include/mm_id.h
+++ b/arch/um/include/skas/mm_id.h
diff --git a/arch/um/include/skas/mmu-skas.h b/arch/um/include/skas/mmu-skas.h
new file mode 100644
index 000000000000..d8869a6ef1b4
--- /dev/null
+++ b/arch/um/include/skas/mmu-skas.h
@@ -0,0 +1,24 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SKAS_MMU_H
7#define __SKAS_MMU_H
8
9#include "linux/config.h"
10#include "mm_id.h"
11#include "asm/ldt.h"
12
13struct mmu_context_skas {
14 struct mm_id id;
15 unsigned long last_page_table;
16#ifdef CONFIG_3_LEVEL_PGTABLES
17 unsigned long last_pmd;
18#endif
19 uml_ldt_t ldt;
20};
21
22extern void switch_mm_skas(struct mm_id * mm_idp);
23
24#endif
diff --git a/arch/um/include/skas/mode-skas.h b/arch/um/include/skas/mode-skas.h
new file mode 100644
index 000000000000..260065cfeef1
--- /dev/null
+++ b/arch/um/include/skas/mode-skas.h
@@ -0,0 +1,19 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __MODE_SKAS_H__
7#define __MODE_SKAS_H__
8
9#include <sysdep/ptrace.h>
10
11extern unsigned long exec_regs[];
12extern unsigned long exec_fp_regs[];
13extern unsigned long exec_fpx_regs[];
14extern int have_fpx_regs;
15
16extern void sig_handler_common_skas(int sig, void *sc_ptr);
17extern void kill_off_processes_skas(void);
18
19#endif
diff --git a/arch/um/kernel/skas/include/mode_kern-skas.h b/arch/um/include/skas/mode_kern_skas.h
index c97a80dfe370..63c58739bde0 100644
--- a/arch/um/kernel/skas/include/mode_kern-skas.h
+++ b/arch/um/include/skas/mode_kern_skas.h
@@ -18,7 +18,6 @@ extern int copy_thread_skas(int nr, unsigned long clone_flags,
18 unsigned long sp, unsigned long stack_top, 18 unsigned long sp, unsigned long stack_top,
19 struct task_struct *p, struct pt_regs *regs); 19 struct task_struct *p, struct pt_regs *regs);
20extern void release_thread_skas(struct task_struct *task); 20extern void release_thread_skas(struct task_struct *task);
21extern void initial_thread_cb_skas(void (*proc)(void *), void *arg);
22extern void init_idle_skas(void); 21extern void init_idle_skas(void);
23extern void flush_tlb_kernel_range_skas(unsigned long start, 22extern void flush_tlb_kernel_range_skas(unsigned long start,
24 unsigned long end); 23 unsigned long end);
@@ -39,14 +38,3 @@ extern int thread_pid_skas(struct task_struct *task);
39#define kmem_end_skas (host_task_size - 1024 * 1024) 38#define kmem_end_skas (host_task_size - 1024 * 1024)
40 39
41#endif 40#endif
42
43/*
44 * Overrides for Emacs so that we follow Linus's tabbing style.
45 * Emacs will notice this stuff at the end of the file and automatically
46 * adjust the settings for this buffer only. This must remain at the end
47 * of the file.
48 * ---------------------------------------------------------------------------
49 * Local variables:
50 * c-file-style: "linux"
51 * End:
52 */
diff --git a/arch/um/kernel/skas/include/proc_mm.h b/arch/um/include/skas/proc_mm.h
index cce61a679052..902809209603 100644
--- a/arch/um/kernel/skas/include/proc_mm.h
+++ b/arch/um/include/skas/proc_mm.h
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -22,13 +22,13 @@ struct mm_mmap {
22 22
23struct mm_munmap { 23struct mm_munmap {
24 unsigned long addr; 24 unsigned long addr;
25 unsigned long len; 25 unsigned long len;
26}; 26};
27 27
28struct mm_mprotect { 28struct mm_mprotect {
29 unsigned long addr; 29 unsigned long addr;
30 unsigned long len; 30 unsigned long len;
31 unsigned int prot; 31 unsigned int prot;
32}; 32};
33 33
34struct proc_mm_op { 34struct proc_mm_op {
@@ -42,14 +42,3 @@ struct proc_mm_op {
42}; 42};
43 43
44#endif 44#endif
45
46/*
47 * Overrides for Emacs so that we follow Linus's tabbing style.
48 * Emacs will notice this stuff at the end of the file and automatically
49 * adjust the settings for this buffer only. This must remain at the end
50 * of the file.
51 * ---------------------------------------------------------------------------
52 * Local variables:
53 * c-file-style: "linux"
54 * End:
55 */
diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h
new file mode 100644
index 000000000000..86357282d681
--- /dev/null
+++ b/arch/um/include/skas/skas.h
@@ -0,0 +1,26 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SKAS_H
7#define __SKAS_H
8
9#include "mm_id.h"
10#include "sysdep/ptrace.h"
11
12extern int userspace_pid[];
13extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
14extern int skas_needs_stub;
15
16extern int user_thread(unsigned long stack, int flags);
17extern void new_thread_proc(void *stack, void (*handler)(int sig));
18extern void new_thread_handler(int sig);
19extern void handle_syscall(union uml_pt_regs *regs);
20extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
21extern int new_mm(unsigned long stack);
22extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
23extern long execute_syscall_skas(void *r);
24extern unsigned long current_stub_stack(void);
25
26#endif
diff --git a/arch/um/kernel/skas/include/stub-data.h b/arch/um/include/skas/stub-data.h
index f6ed92c3727d..f6ed92c3727d 100644
--- a/arch/um/kernel/skas/include/stub-data.h
+++ b/arch/um/include/skas/stub-data.h
diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/include/skas/uaccess-skas.h
index 64516c556cdf..224a75f4c025 100644
--- a/arch/um/kernel/skas/include/uaccess-skas.h
+++ b/arch/um/include/skas/uaccess-skas.h
@@ -19,14 +19,3 @@ extern int clear_user_skas(void __user *mem, int len);
19extern int strnlen_user_skas(const void __user *str, int len); 19extern int strnlen_user_skas(const void __user *str, int len);
20 20
21#endif 21#endif
22
23/*
24 * Overrides for Emacs so that we follow Linus's tabbing style.
25 * Emacs will notice this stuff at the end of the file and automatically
26 * adjust the settings for this buffer only. This must remain at the end
27 * of the file.
28 * ---------------------------------------------------------------------------
29 * Local variables:
30 * c-file-style: "linux"
31 * End:
32 */
diff --git a/arch/um/include/time_user.h b/arch/um/include/time_user.h
deleted file mode 100644
index 17d7ef2141f4..000000000000
--- a/arch/um/include/time_user.h
+++ /dev/null
@@ -1,19 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __TIME_USER_H__
7#define __TIME_USER_H__
8
9extern void timer(void);
10extern void switch_timers(int to_real);
11extern void idle_sleep(int secs);
12extern void enable_timer(void);
13extern void prepare_timer(void * ptr);
14extern void disable_timer(void);
15extern unsigned long time_lock(void);
16extern void time_unlock(unsigned long);
17extern void user_time_init(void);
18
19#endif
diff --git a/arch/um/kernel/tt/include/debug.h b/arch/um/include/tt/debug.h
index 738435461e13..9778fa838296 100644
--- a/arch/um/kernel/tt/include/debug.h
+++ b/arch/um/include/tt/debug.h
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) and 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) and
3 * Lars Brinkhoff. 3 * Lars Brinkhoff.
4 * Licensed under the GPL 4 * Licensed under the GPL
diff --git a/arch/um/include/tt/mmu-tt.h b/arch/um/include/tt/mmu-tt.h
new file mode 100644
index 000000000000..572a78b22587
--- /dev/null
+++ b/arch/um/include/tt/mmu-tt.h
@@ -0,0 +1,12 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __TT_MMU_H
7#define __TT_MMU_H
8
9struct mmu_context_tt {
10};
11
12#endif
diff --git a/arch/um/include/tt/mode-tt.h b/arch/um/include/tt/mode-tt.h
new file mode 100644
index 000000000000..2823cd56eea2
--- /dev/null
+++ b/arch/um/include/tt/mode-tt.h
@@ -0,0 +1,23 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __MODE_TT_H__
7#define __MODE_TT_H__
8
9#include "sysdep/ptrace.h"
10
11enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
12
13extern int tracing_pid;
14
15extern int tracer(int (*init_proc)(void *), void *sp);
16extern void sig_handler_common_tt(int sig, void *sc);
17extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
18extern void reboot_tt(void);
19extern void halt_tt(void);
20extern int is_tracer_winch(int pid, int fd, void *data);
21extern void kill_off_processes_tt(void);
22
23#endif
diff --git a/arch/um/include/tt/mode_kern_tt.h b/arch/um/include/tt/mode_kern_tt.h
new file mode 100644
index 000000000000..efa0012550d0
--- /dev/null
+++ b/arch/um/include/tt/mode_kern_tt.h
@@ -0,0 +1,41 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __TT_MODE_KERN_H__
7#define __TT_MODE_KERN_H__
8
9#include "linux/sched.h"
10#include "asm/page.h"
11#include "asm/ptrace.h"
12#include "asm/uaccess.h"
13
14extern void switch_to_tt(void *prev, void *next);
15extern void flush_thread_tt(void);
16extern void start_thread_tt(struct pt_regs *regs, unsigned long eip,
17 unsigned long esp);
18extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
19 unsigned long stack_top, struct task_struct *p,
20 struct pt_regs *regs);
21extern void release_thread_tt(struct task_struct *task);
22extern void initial_thread_cb_tt(void (*proc)(void *), void *arg);
23extern void init_idle_tt(void);
24extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end);
25extern void flush_tlb_kernel_vm_tt(void);
26extern void __flush_tlb_one_tt(unsigned long addr);
27extern void flush_tlb_range_tt(struct vm_area_struct *vma,
28 unsigned long start, unsigned long end);
29extern void flush_tlb_mm_tt(struct mm_struct *mm);
30extern void force_flush_all_tt(void);
31extern long execute_syscall_tt(void *r);
32extern void before_mem_tt(unsigned long brk_start);
33extern unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out,
34 unsigned long *task_size_out);
35extern int start_uml_tt(void);
36extern int external_pid_tt(struct task_struct *task);
37extern int thread_pid_tt(struct task_struct *task);
38
39#define kmem_end_tt (host_task_size - ABOVE_KMEM)
40
41#endif
diff --git a/arch/um/kernel/tt/include/tt.h b/arch/um/include/tt/tt.h
index c667b67af405..808521980186 100644
--- a/arch/um/kernel/tt/include/tt.h
+++ b/arch/um/include/tt/tt.h
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -34,13 +34,3 @@ extern long execute_syscall_tt(void *r);
34 34
35#endif 35#endif
36 36
37/*
38 * Overrides for Emacs so that we follow Linus's tabbing style.
39 * Emacs will notice this stuff at the end of the file and automatically
40 * adjust the settings for this buffer only. This must remain at the end
41 * of the file.
42 * ---------------------------------------------------------------------------
43 * Local variables:
44 * c-file-style: "linux"
45 * End:
46 */
diff --git a/arch/um/kernel/tt/include/uaccess-tt.h b/arch/um/include/tt/uaccess-tt.h
index b9bfe9c481c4..b19645f32f24 100644
--- a/arch/um/kernel/tt/include/uaccess-tt.h
+++ b/arch/um/include/tt/uaccess-tt.h
@@ -46,14 +46,3 @@ extern int clear_user_tt(void __user *mem, int len);
46extern int strnlen_user_tt(const void __user *str, int len); 46extern int strnlen_user_tt(const void __user *str, int len);
47 47
48#endif 48#endif
49
50/*
51 * Overrides for Emacs so that we follow Linus's tabbing style.
52 * Emacs will notice this stuff at the end of the file and automatically
53 * adjust the settings for this buffer only. This must remain at the end
54 * of the file.
55 * ---------------------------------------------------------------------------
56 * Local variables:
57 * c-file-style: "linux"
58 * End:
59 */
diff --git a/arch/um/include/user.h b/arch/um/include/user.h
index 0f865ef46918..91b0ac4ad88c 100644
--- a/arch/um/include/user.h
+++ b/arch/um/include/user.h
@@ -18,6 +18,7 @@ extern int open_gdb_chan(void);
18extern unsigned long strlcpy(char *, const char *, unsigned long); 18extern unsigned long strlcpy(char *, const char *, unsigned long);
19extern unsigned long strlcat(char *, const char *, unsigned long); 19extern unsigned long strlcat(char *, const char *, unsigned long);
20extern void *um_vmalloc(int size); 20extern void *um_vmalloc(int size);
21extern void *um_vmalloc_atomic(int size);
21extern void vfree(void *ptr); 22extern void vfree(void *ptr);
22 23
23#endif 24#endif
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index c1dbd77b073f..a6f1f176cf84 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -44,10 +44,6 @@ extern unsigned long brk_start;
44extern int pty_output_sigio; 44extern int pty_output_sigio;
45extern int pty_close_sigio; 45extern int pty_close_sigio;
46 46
47extern void stop(void);
48extern void stack_protections(unsigned long address);
49extern void task_protections(unsigned long address);
50extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
51extern void *add_signal_handler(int sig, void (*handler)(int)); 47extern void *add_signal_handler(int sig, void (*handler)(int));
52extern int linux_main(int argc, char **argv); 48extern int linux_main(int argc, char **argv);
53extern void set_cmdline(char *cmd); 49extern void set_cmdline(char *cmd);
@@ -55,8 +51,6 @@ extern void input_cb(void (*proc)(void *), void *arg, int arg_len);
55extern int get_pty(void); 51extern int get_pty(void);
56extern void *um_kmalloc(int size); 52extern void *um_kmalloc(int size);
57extern int switcheroo(int fd, int prot, void *from, void *to, int size); 53extern int switcheroo(int fd, int prot, void *from, void *to, int size);
58extern void setup_machinename(char *machine_out);
59extern void setup_hostinfo(void);
60extern void do_exec(int old_pid, int new_pid); 54extern void do_exec(int old_pid, int new_pid);
61extern void tracer_panic(char *msg, ...); 55extern void tracer_panic(char *msg, ...);
62extern int detach(int pid, int sig); 56extern int detach(int pid, int sig);
@@ -70,18 +64,6 @@ extern int cpu_feature(char *what, char *buf, int len);
70extern int arch_handle_signal(int sig, union uml_pt_regs *regs); 64extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
71extern int arch_fixup(unsigned long address, void *sc_ptr); 65extern int arch_fixup(unsigned long address, void *sc_ptr);
72extern void arch_init_thread(void); 66extern void arch_init_thread(void);
73extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
74extern int raw(int fd); 67extern int raw(int fd);
75 68
76#endif 69#endif
77
78/*
79 * Overrides for Emacs so that we follow Linus's tabbing style.
80 * Emacs will notice this stuff at the end of the file and automatically
81 * adjust the settings for this buffer only. This must remain at the end
82 * of the file.
83 * ---------------------------------------------------------------------------
84 * Local variables:
85 * c-file-style: "linux"
86 * End:
87 */
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 193cc2b7448d..693018ba80f1 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -9,9 +9,8 @@ clean-files :=
9obj-y = config.o exec_kern.o exitcode.o \ 9obj-y = config.o exec_kern.o exitcode.o \
10 init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \ 10 init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \
11 process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ 11 process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \
12 signal_kern.o smp.o syscall_kern.o sysrq.o time.o \ 12 signal_kern.o smp.o syscall_kern.o sysrq.o \
13 time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o \ 13 time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o
14 user_util.o
15 14
16obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o 15obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
17obj-$(CONFIG_GPROF) += gprof_syms.o 16obj-$(CONFIG_GPROF) += gprof_syms.o
@@ -24,7 +23,7 @@ obj-$(CONFIG_MODE_SKAS) += skas/
24 23
25user-objs-$(CONFIG_TTY_LOG) += tty_log.o 24user-objs-$(CONFIG_TTY_LOG) += tty_log.o
26 25
27USER_OBJS := $(user-objs-y) config.o time.o tty_log.o user_util.o 26USER_OBJS := $(user-objs-y) config.o tty_log.o
28 27
29include arch/um/scripts/Makefile.rules 28include arch/um/scripts/Makefile.rules
30 29
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c
index efd222ffe20e..569fe8b9b053 100644
--- a/arch/um/kernel/exec_kern.c
+++ b/arch/um/kernel/exec_kern.c
@@ -17,7 +17,6 @@
17#include "irq_user.h" 17#include "irq_user.h"
18#include "tlb.h" 18#include "tlb.h"
19#include "os.h" 19#include "os.h"
20#include "time_user.h"
21#include "choose-mode.h" 20#include "choose-mode.h"
22#include "mode_kern.h" 21#include "mode_kern.h"
23 22
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index 7f13b85d2656..3113cab8675e 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -39,7 +39,6 @@
39#include "init.h" 39#include "init.h"
40#include "irq_user.h" 40#include "irq_user.h"
41#include "mem_user.h" 41#include "mem_user.h"
42#include "time_user.h"
43#include "tlb.h" 42#include "tlb.h"
44#include "frame_kern.h" 43#include "frame_kern.h"
45#include "sigcontext.h" 44#include "sigcontext.h"
@@ -288,17 +287,27 @@ EXPORT_SYMBOL(disable_hlt);
288 287
289void *um_kmalloc(int size) 288void *um_kmalloc(int size)
290{ 289{
291 return(kmalloc(size, GFP_KERNEL)); 290 return kmalloc(size, GFP_KERNEL);
292} 291}
293 292
294void *um_kmalloc_atomic(int size) 293void *um_kmalloc_atomic(int size)
295{ 294{
296 return(kmalloc(size, GFP_ATOMIC)); 295 return kmalloc(size, GFP_ATOMIC);
297} 296}
298 297
299void *um_vmalloc(int size) 298void *um_vmalloc(int size)
300{ 299{
301 return(vmalloc(size)); 300 return vmalloc(size);
301}
302
303void *um_vmalloc_atomic(int size)
304{
305 return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL);
306}
307
308int __cant_sleep(void) {
309 return in_atomic() || irqs_disabled() || in_interrupt();
310 /* Is in_interrupt() really needed? */
302} 311}
303 312
304unsigned long get_fault_addr(void) 313unsigned long get_fault_addr(void)
@@ -370,11 +379,6 @@ int smp_sigio_handler(void)
370 return(0); 379 return(0);
371} 380}
372 381
373int um_in_interrupt(void)
374{
375 return(in_interrupt());
376}
377
378int cpu(void) 382int cpu(void)
379{ 383{
380 return(current_thread->cpu); 384 return(current_thread->cpu);
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index 62e5cfdf2188..f7b18e157d35 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -337,70 +337,103 @@ int ignore_sigio_fd(int fd)
337 return(err); 337 return(err);
338} 338}
339 339
340static int setup_initial_poll(int fd) 340static struct pollfd* setup_initial_poll(int fd)
341{ 341{
342 struct pollfd *p; 342 struct pollfd *p;
343 343
344 p = um_kmalloc_atomic(sizeof(struct pollfd)); 344 p = um_kmalloc(sizeof(struct pollfd));
345 if(p == NULL){ 345 if (p == NULL) {
346 printk("setup_initial_poll : failed to allocate poll\n"); 346 printk("setup_initial_poll : failed to allocate poll\n");
347 return(-1); 347 return NULL;
348 } 348 }
349 *p = ((struct pollfd) { .fd = fd, 349 *p = ((struct pollfd) { .fd = fd,
350 .events = POLLIN, 350 .events = POLLIN,
351 .revents = 0 }); 351 .revents = 0 });
352 current_poll = ((struct pollfds) { .poll = p, 352 return p;
353 .used = 1,
354 .size = 1 });
355 return(0);
356} 353}
357 354
358void write_sigio_workaround(void) 355void write_sigio_workaround(void)
359{ 356{
360 unsigned long stack; 357 unsigned long stack;
358 struct pollfd *p;
361 int err; 359 int err;
360 int l_write_sigio_fds[2];
361 int l_sigio_private[2];
362 int l_write_sigio_pid;
362 363
364 /* We call this *tons* of times - and most ones we must just fail. */
363 sigio_lock(); 365 sigio_lock();
364 if(write_sigio_pid != -1) 366 l_write_sigio_pid = write_sigio_pid;
365 goto out; 367 sigio_unlock();
366 368
367 err = os_pipe(write_sigio_fds, 1, 1); 369 if (l_write_sigio_pid != -1)
370 return;
371
372 err = os_pipe(l_write_sigio_fds, 1, 1);
368 if(err < 0){ 373 if(err < 0){
369 printk("write_sigio_workaround - os_pipe 1 failed, " 374 printk("write_sigio_workaround - os_pipe 1 failed, "
370 "err = %d\n", -err); 375 "err = %d\n", -err);
371 goto out; 376 return;
372 } 377 }
373 err = os_pipe(sigio_private, 1, 1); 378 err = os_pipe(l_sigio_private, 1, 1);
374 if(err < 0){ 379 if(err < 0){
375 printk("write_sigio_workaround - os_pipe 2 failed, " 380 printk("write_sigio_workaround - os_pipe 1 failed, "
376 "err = %d\n", -err); 381 "err = %d\n", -err);
377 goto out_close1; 382 goto out_close1;
378 } 383 }
379 if(setup_initial_poll(sigio_private[1])) 384
385 p = setup_initial_poll(l_sigio_private[1]);
386 if(!p)
380 goto out_close2; 387 goto out_close2;
381 388
382 write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, 389 sigio_lock();
390
391 /* Did we race? Don't try to optimize this, please, it's not so likely
392 * to happen, and no more than once at the boot. */
393 if(write_sigio_pid != -1)
394 goto out_unlock;
395
396 write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
383 CLONE_FILES | CLONE_VM, &stack, 0); 397 CLONE_FILES | CLONE_VM, &stack, 0);
384 398
385 if(write_sigio_pid < 0) goto out_close2; 399 if (write_sigio_pid < 0)
400 goto out_clear;
386 401
387 if(write_sigio_irq(write_sigio_fds[0])) 402 if (write_sigio_irq(l_write_sigio_fds[0]))
388 goto out_kill; 403 goto out_kill;
389 404
390 out: 405 /* Success, finally. */
406 memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds));
407 memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private));
408
409 current_poll = ((struct pollfds) { .poll = p,
410 .used = 1,
411 .size = 1 });
412
391 sigio_unlock(); 413 sigio_unlock();
392 return; 414 return;
393 415
394 out_kill: 416 out_kill:
395 os_kill_process(write_sigio_pid, 1); 417 l_write_sigio_pid = write_sigio_pid;
396 write_sigio_pid = -1; 418 write_sigio_pid = -1;
419 sigio_unlock();
420 /* Going to call waitpid, avoid holding the lock. */
421 os_kill_process(l_write_sigio_pid, 1);
422 goto out_free;
423
424 out_clear:
425 write_sigio_pid = -1;
426 out_unlock:
427 sigio_unlock();
428 out_free:
429 kfree(p);
397 out_close2: 430 out_close2:
398 os_close_file(sigio_private[0]); 431 os_close_file(l_sigio_private[0]);
399 os_close_file(sigio_private[1]); 432 os_close_file(l_sigio_private[1]);
400 out_close1: 433 out_close1:
401 os_close_file(write_sigio_fds[0]); 434 os_close_file(l_write_sigio_fds[0]);
402 os_close_file(write_sigio_fds[1]); 435 os_close_file(l_write_sigio_fds[1]);
403 sigio_unlock(); 436 return;
404} 437}
405 438
406int read_sigio_fd(int fd) 439int read_sigio_fd(int fd)
diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c
index 7b0e0e81c161..da17b7541e08 100644
--- a/arch/um/kernel/signal_kern.c
+++ b/arch/um/kernel/signal_kern.c
@@ -99,31 +99,46 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
99 return err; 99 return err;
100} 100}
101 101
102static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset) 102static int kern_do_signal(struct pt_regs *regs)
103{ 103{
104 struct k_sigaction ka_copy; 104 struct k_sigaction ka_copy;
105 siginfo_t info; 105 siginfo_t info;
106 sigset_t *oldset;
106 int sig, handled_sig = 0; 107 int sig, handled_sig = 0;
107 108
109 if (test_thread_flag(TIF_RESTORE_SIGMASK))
110 oldset = &current->saved_sigmask;
111 else
112 oldset = &current->blocked;
113
108 while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){ 114 while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){
109 handled_sig = 1; 115 handled_sig = 1;
110 /* Whee! Actually deliver the signal. */ 116 /* Whee! Actually deliver the signal. */
111 if(!handle_signal(regs, sig, &ka_copy, &info, oldset)) 117 if(!handle_signal(regs, sig, &ka_copy, &info, oldset)){
118 /* a signal was successfully delivered; the saved
119 * sigmask will have been stored in the signal frame,
120 * and will be restored by sigreturn, so we can simply
121 * clear the TIF_RESTORE_SIGMASK flag */
122 if (test_thread_flag(TIF_RESTORE_SIGMASK))
123 clear_thread_flag(TIF_RESTORE_SIGMASK);
112 break; 124 break;
125 }
113 } 126 }
114 127
115 /* Did we come from a system call? */ 128 /* Did we come from a system call? */
116 if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){ 129 if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){
117 /* Restart the system call - no handlers present */ 130 /* Restart the system call - no handlers present */
118 if(PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOHAND || 131 switch(PT_REGS_SYSCALL_RET(regs)){
119 PT_REGS_SYSCALL_RET(regs) == -ERESTARTSYS || 132 case -ERESTARTNOHAND:
120 PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOINTR){ 133 case -ERESTARTSYS:
134 case -ERESTARTNOINTR:
121 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); 135 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
122 PT_REGS_RESTART_SYSCALL(regs); 136 PT_REGS_RESTART_SYSCALL(regs);
123 } 137 break;
124 else if(PT_REGS_SYSCALL_RET(regs) == -ERESTART_RESTARTBLOCK){ 138 case -ERESTART_RESTARTBLOCK:
125 PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall; 139 PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall;
126 PT_REGS_RESTART_SYSCALL(regs); 140 PT_REGS_RESTART_SYSCALL(regs);
141 break;
127 } 142 }
128 } 143 }
129 144
@@ -137,12 +152,19 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset)
137 if(current->ptrace & PT_DTRACE) 152 if(current->ptrace & PT_DTRACE)
138 current->thread.singlestep_syscall = 153 current->thread.singlestep_syscall =
139 is_syscall(PT_REGS_IP(&current->thread.regs)); 154 is_syscall(PT_REGS_IP(&current->thread.regs));
155
156 /* if there's no signal to deliver, we just put the saved sigmask
157 * back */
158 if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) {
159 clear_thread_flag(TIF_RESTORE_SIGMASK);
160 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
161 }
140 return(handled_sig); 162 return(handled_sig);
141} 163}
142 164
143int do_signal(void) 165int do_signal(void)
144{ 166{
145 return(kern_do_signal(&current->thread.regs, &current->blocked)); 167 return(kern_do_signal(&current->thread.regs));
146} 168}
147 169
148/* 170/*
@@ -150,63 +172,20 @@ int do_signal(void)
150 */ 172 */
151long sys_sigsuspend(int history0, int history1, old_sigset_t mask) 173long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
152{ 174{
153 sigset_t saveset;
154
155 mask &= _BLOCKABLE; 175 mask &= _BLOCKABLE;
156 spin_lock_irq(&current->sighand->siglock); 176 spin_lock_irq(&current->sighand->siglock);
157 saveset = current->blocked; 177 current->saved_sigmask = current->blocked;
158 siginitset(&current->blocked, mask); 178 siginitset(&current->blocked, mask);
159 recalc_sigpending(); 179 recalc_sigpending();
160 spin_unlock_irq(&current->sighand->siglock); 180 spin_unlock_irq(&current->sighand->siglock);
161 181
162 PT_REGS_SYSCALL_RET(&current->thread.regs) = -EINTR; 182 current->state = TASK_INTERRUPTIBLE;
163 while (1) { 183 schedule();
164 current->state = TASK_INTERRUPTIBLE; 184 set_thread_flag(TIF_RESTORE_SIGMASK);
165 schedule(); 185 return -ERESTARTNOHAND;
166 if(kern_do_signal(&current->thread.regs, &saveset))
167 return(-EINTR);
168 }
169}
170
171long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
172{
173 sigset_t saveset, newset;
174
175 /* XXX: Don't preclude handling different sized sigset_t's. */
176 if (sigsetsize != sizeof(sigset_t))
177 return -EINVAL;
178
179 if (copy_from_user(&newset, unewset, sizeof(newset)))
180 return -EFAULT;
181 sigdelsetmask(&newset, ~_BLOCKABLE);
182
183 spin_lock_irq(&current->sighand->siglock);
184 saveset = current->blocked;
185 current->blocked = newset;
186 recalc_sigpending();
187 spin_unlock_irq(&current->sighand->siglock);
188
189 PT_REGS_SYSCALL_RET(&current->thread.regs) = -EINTR;
190 while (1) {
191 current->state = TASK_INTERRUPTIBLE;
192 schedule();
193 if (kern_do_signal(&current->thread.regs, &saveset))
194 return(-EINTR);
195 }
196} 186}
197 187
198long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) 188long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
199{ 189{
200 return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs))); 190 return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
201} 191}
202
203/*
204 * Overrides for Emacs so that we follow Linus's tabbing style.
205 * Emacs will notice this stuff at the end of the file and automatically
206 * adjust the settings for this buffer only. This must remain at the end
207 * of the file.
208 * ---------------------------------------------------------------------------
209 * Local variables:
210 * c-file-style: "linux"
211 * End:
212 */
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index 7a9fc16d71d4..57181a920d48 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -1,12 +1,12 @@
1# 1#
2# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com) 2# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
3# Licensed under the GPL 3# Licensed under the GPL
4# 4#
5 5
6obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \ 6obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \
7 syscall.o tlb.o uaccess.o 7 syscall.o tlb.o uaccess.o
8 8
9USER_OBJS := process.o clone.o 9USER_OBJS := clone.o
10 10
11include arch/um/scripts/Makefile.rules 11include arch/um/scripts/Makefile.rules
12 12
diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h
deleted file mode 100644
index 44110c521e49..000000000000
--- a/arch/um/kernel/skas/include/mmu-skas.h
+++ /dev/null
@@ -1,35 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SKAS_MMU_H
7#define __SKAS_MMU_H
8
9#include "linux/config.h"
10#include "mm_id.h"
11#include "asm/ldt.h"
12
13struct mmu_context_skas {
14 struct mm_id id;
15 unsigned long last_page_table;
16#ifdef CONFIG_3_LEVEL_PGTABLES
17 unsigned long last_pmd;
18#endif
19 uml_ldt_t ldt;
20};
21
22extern void switch_mm_skas(struct mm_id * mm_idp);
23
24#endif
25
26/*
27 * Overrides for Emacs so that we follow Linus's tabbing style.
28 * Emacs will notice this stuff at the end of the file and automatically
29 * adjust the settings for this buffer only. This must remain at the end
30 * of the file.
31 * ---------------------------------------------------------------------------
32 * Local variables:
33 * c-file-style: "linux"
34 * End:
35 */
diff --git a/arch/um/kernel/skas/include/mode-skas.h b/arch/um/kernel/skas/include/mode-skas.h
deleted file mode 100644
index bcd26a6a3888..000000000000
--- a/arch/um/kernel/skas/include/mode-skas.h
+++ /dev/null
@@ -1,33 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __MODE_SKAS_H__
7#define __MODE_SKAS_H__
8
9#include <sysdep/ptrace.h>
10
11extern unsigned long exec_regs[];
12extern unsigned long exec_fp_regs[];
13extern unsigned long exec_fpx_regs[];
14extern int have_fpx_regs;
15
16extern void sig_handler_common_skas(int sig, void *sc_ptr);
17extern void halt_skas(void);
18extern void reboot_skas(void);
19extern void kill_off_processes_skas(void);
20extern int is_skas_winch(int pid, int fd, void *data);
21
22#endif
23
24/*
25 * Overrides for Emacs so that we follow Linus's tabbing style.
26 * Emacs will notice this stuff at the end of the file and automatically
27 * adjust the settings for this buffer only. This must remain at the end
28 * of the file.
29 * ---------------------------------------------------------------------------
30 * Local variables:
31 * c-file-style: "linux"
32 * End:
33 */
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
deleted file mode 100644
index 01d489de3986..000000000000
--- a/arch/um/kernel/skas/include/skas.h
+++ /dev/null
@@ -1,49 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SKAS_H
7#define __SKAS_H
8
9#include "mm_id.h"
10#include "sysdep/ptrace.h"
11
12extern int userspace_pid[];
13extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
14extern int skas_needs_stub;
15
16extern void switch_threads(void *me, void *next);
17extern void thread_wait(void *sw, void *fb);
18extern void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
19 void (*handler)(int));
20extern int start_idle_thread(void *stack, void *switch_buf_ptr,
21 void **fork_buf_ptr);
22extern int user_thread(unsigned long stack, int flags);
23extern void userspace(union uml_pt_regs *regs);
24extern void new_thread_proc(void *stack, void (*handler)(int sig));
25extern void new_thread_handler(int sig);
26extern void handle_syscall(union uml_pt_regs *regs);
27extern int map(struct mm_id * mm_idp, unsigned long virt,
28 unsigned long len, int r, int w, int x, int phys_fd,
29 unsigned long long offset, int done, void **data);
30extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len,
31 int done, void **data);
32extern int protect(struct mm_id * mm_idp, unsigned long addr,
33 unsigned long len, int r, int w, int x, int done,
34 void **data);
35extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
36extern int new_mm(int from, unsigned long stack);
37extern int start_userspace(unsigned long stub_stack);
38extern int copy_context_skas0(unsigned long stack, int pid);
39extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
40extern long execute_syscall_skas(void *r);
41extern unsigned long current_stub_stack(void);
42extern long run_syscall_stub(struct mm_id * mm_idp,
43 int syscall, unsigned long *args, long expected,
44 void **addr, int done);
45extern long syscall_stub_data(struct mm_id * mm_idp,
46 unsigned long *data, int data_count,
47 void **addr, void **stub_addr);
48
49#endif
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 677871f1b37c..c5c9885a8297 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -78,7 +78,7 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
78 struct mmu_context_skas *from_mm = NULL; 78 struct mmu_context_skas *from_mm = NULL;
79 struct mmu_context_skas *to_mm = &mm->context.skas; 79 struct mmu_context_skas *to_mm = &mm->context.skas;
80 unsigned long stack = 0; 80 unsigned long stack = 0;
81 int from_fd, ret = -ENOMEM; 81 int ret = -ENOMEM;
82 82
83 if(skas_needs_stub){ 83 if(skas_needs_stub){
84 stack = get_zeroed_page(GFP_KERNEL); 84 stack = get_zeroed_page(GFP_KERNEL);
@@ -108,11 +108,7 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
108 from_mm = &current->mm->context.skas; 108 from_mm = &current->mm->context.skas;
109 109
110 if(proc_mm){ 110 if(proc_mm){
111 if(from_mm) 111 ret = new_mm(stack);
112 from_fd = from_mm->id.u.mm_fd;
113 else from_fd = -1;
114
115 ret = new_mm(from_fd, stack);
116 if(ret < 0){ 112 if(ret < 0){
117 printk("init_new_context_skas - new_mm failed, " 113 printk("init_new_context_skas - new_mm failed, "
118 "errno = %d\n", ret); 114 "errno = %d\n", ret);
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 3b3955d84407..eea1c9c4bb0f 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -18,7 +18,6 @@
18#include <asm/types.h> 18#include <asm/types.h>
19#include "user.h" 19#include "user.h"
20#include "ptrace_user.h" 20#include "ptrace_user.h"
21#include "time_user.h"
22#include "sysdep/ptrace.h" 21#include "sysdep/ptrace.h"
23#include "user_util.h" 22#include "user_util.h"
24#include "kern_util.h" 23#include "kern_util.h"
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index dc41c6dc2f34..3f70a2e12f06 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -13,14 +13,12 @@
13#include "asm/uaccess.h" 13#include "asm/uaccess.h"
14#include "asm/atomic.h" 14#include "asm/atomic.h"
15#include "kern_util.h" 15#include "kern_util.h"
16#include "time_user.h"
17#include "skas.h" 16#include "skas.h"
18#include "os.h" 17#include "os.h"
19#include "user_util.h" 18#include "user_util.h"
20#include "tlb.h" 19#include "tlb.h"
21#include "kern.h" 20#include "kern.h"
22#include "mode.h" 21#include "mode.h"
23#include "proc_mm.h"
24#include "registers.h" 22#include "registers.h"
25 23
26void switch_to_skas(void *prev, void *next) 24void switch_to_skas(void *prev, void *next)
@@ -34,7 +32,7 @@ void switch_to_skas(void *prev, void *next)
34 if(current->pid == 0) 32 if(current->pid == 0)
35 switch_timers(0); 33 switch_timers(0);
36 34
37 switch_threads(&from->thread.mode.skas.switch_buf, 35 switch_threads(&from->thread.mode.skas.switch_buf,
38 to->thread.mode.skas.switch_buf); 36 to->thread.mode.skas.switch_buf);
39 37
40 if(current->pid == 0) 38 if(current->pid == 0)
@@ -50,8 +48,8 @@ void new_thread_handler(int sig)
50 48
51 fn = current->thread.request.u.thread.proc; 49 fn = current->thread.request.u.thread.proc;
52 arg = current->thread.request.u.thread.arg; 50 arg = current->thread.request.u.thread.arg;
53 change_sig(SIGUSR1, 1); 51 os_usr1_signal(1);
54 thread_wait(&current->thread.mode.skas.switch_buf, 52 thread_wait(&current->thread.mode.skas.switch_buf,
55 current->thread.mode.skas.fork_buf); 53 current->thread.mode.skas.fork_buf);
56 54
57 if(current->thread.prev_sched != NULL) 55 if(current->thread.prev_sched != NULL)
@@ -82,8 +80,8 @@ void release_thread_skas(struct task_struct *task)
82 80
83void fork_handler(int sig) 81void fork_handler(int sig)
84{ 82{
85 change_sig(SIGUSR1, 1); 83 os_usr1_signal(1);
86 thread_wait(&current->thread.mode.skas.switch_buf, 84 thread_wait(&current->thread.mode.skas.switch_buf,
87 current->thread.mode.skas.fork_buf); 85 current->thread.mode.skas.fork_buf);
88 86
89 force_flush_all(); 87 force_flush_all();
@@ -93,13 +91,13 @@ void fork_handler(int sig)
93 schedule_tail(current->thread.prev_sched); 91 schedule_tail(current->thread.prev_sched);
94 current->thread.prev_sched = NULL; 92 current->thread.prev_sched = NULL;
95 93
96 /* Handle any immediate reschedules or signals */ 94/* Handle any immediate reschedules or signals */
97 interrupt_end(); 95 interrupt_end();
98 userspace(&current->thread.regs.regs); 96 userspace(&current->thread.regs.regs);
99} 97}
100 98
101int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, 99int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
102 unsigned long stack_top, struct task_struct * p, 100 unsigned long stack_top, struct task_struct * p,
103 struct pt_regs *regs) 101 struct pt_regs *regs)
104{ 102{
105 void (*handler)(int); 103 void (*handler)(int);
@@ -123,27 +121,14 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
123 return(0); 121 return(0);
124} 122}
125 123
126extern void map_stub_pages(int fd, unsigned long code, 124int new_mm(unsigned long stack)
127 unsigned long data, unsigned long stack);
128int new_mm(int from, unsigned long stack)
129{ 125{
130 struct proc_mm_op copy; 126 int fd;
131 int n, fd;
132 127
133 fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); 128 fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
134 if(fd < 0) 129 if(fd < 0)
135 return(fd); 130 return(fd);
136 131
137 if(from != -1){
138 copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS,
139 .u =
140 { .copy_segments = from } } );
141 n = os_write_file(fd, &copy, sizeof(copy));
142 if(n != sizeof(copy))
143 printk("new_mm : /proc/mm copy_segments failed, "
144 "err = %d\n", -n);
145 }
146
147 if(skas_needs_stub) 132 if(skas_needs_stub)
148 map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); 133 map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
149 134
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index a5a47528dec7..5992c3257167 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -13,7 +13,7 @@
13#include "asm/pgtable.h" 13#include "asm/pgtable.h"
14#include "asm/uaccess.h" 14#include "asm/uaccess.h"
15#include "kern_util.h" 15#include "kern_util.h"
16#include "user_util.h" 16#include "os.h"
17 17
18extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr, 18extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
19 pte_t *pte_out); 19 pte_t *pte_out);
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index 1429c131879d..1731d90e6850 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -25,12 +25,12 @@ int record_syscall_start(int syscall)
25 syscall_record[index].syscall = syscall; 25 syscall_record[index].syscall = syscall;
26 syscall_record[index].pid = current_pid(); 26 syscall_record[index].pid = current_pid();
27 syscall_record[index].result = 0xdeadbeef; 27 syscall_record[index].result = 0xdeadbeef;
28 syscall_record[index].start = os_usecs(); 28 syscall_record[index].start = os_nsecs();
29 return(index); 29 return(index);
30} 30}
31 31
32void record_syscall_end(int index, long result) 32void record_syscall_end(int index, long result)
33{ 33{
34 syscall_record[index].result = result; 34 syscall_record[index].result = result;
35 syscall_record[index].end = os_usecs(); 35 syscall_record[index].end = os_nsecs();
36} 36}
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 020ca79b8d33..3c7626cdba4b 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -13,12 +13,12 @@
13#include "linux/interrupt.h" 13#include "linux/interrupt.h"
14#include "linux/init.h" 14#include "linux/init.h"
15#include "linux/delay.h" 15#include "linux/delay.h"
16#include "linux/hrtimer.h"
16#include "asm/irq.h" 17#include "asm/irq.h"
17#include "asm/param.h" 18#include "asm/param.h"
18#include "asm/current.h" 19#include "asm/current.h"
19#include "kern_util.h" 20#include "kern_util.h"
20#include "user_util.h" 21#include "user_util.h"
21#include "time_user.h"
22#include "mode.h" 22#include "mode.h"
23#include "os.h" 23#include "os.h"
24 24
@@ -39,7 +39,7 @@ unsigned long long sched_clock(void)
39int timer_irq_inited = 0; 39int timer_irq_inited = 0;
40 40
41static int first_tick; 41static int first_tick;
42static unsigned long long prev_usecs; 42static unsigned long long prev_nsecs;
43#ifdef CONFIG_UML_REAL_TIME_CLOCK 43#ifdef CONFIG_UML_REAL_TIME_CLOCK
44static long long delta; /* Deviation per interval */ 44static long long delta; /* Deviation per interval */
45#endif 45#endif
@@ -58,23 +58,23 @@ void timer_irq(union uml_pt_regs *regs)
58 if(first_tick){ 58 if(first_tick){
59#ifdef CONFIG_UML_REAL_TIME_CLOCK 59#ifdef CONFIG_UML_REAL_TIME_CLOCK
60 /* We've had 1 tick */ 60 /* We've had 1 tick */
61 unsigned long long usecs = os_usecs(); 61 unsigned long long nsecs = os_nsecs();
62 62
63 delta += usecs - prev_usecs; 63 delta += nsecs - prev_nsecs;
64 prev_usecs = usecs; 64 prev_nsecs = nsecs;
65 65
66 /* Protect against the host clock being set backwards */ 66 /* Protect against the host clock being set backwards */
67 if(delta < 0) 67 if(delta < 0)
68 delta = 0; 68 delta = 0;
69 69
70 ticks += (delta * HZ) / MILLION; 70 ticks += (delta * HZ) / BILLION;
71 delta -= (ticks * MILLION) / HZ; 71 delta -= (ticks * BILLION) / HZ;
72#else 72#else
73 ticks = 1; 73 ticks = 1;
74#endif 74#endif
75 } 75 }
76 else { 76 else {
77 prev_usecs = os_usecs(); 77 prev_nsecs = os_nsecs();
78 first_tick = 1; 78 first_tick = 1;
79 } 79 }
80 80
@@ -84,49 +84,102 @@ void timer_irq(union uml_pt_regs *regs)
84 } 84 }
85} 85}
86 86
87void boot_timer_handler(int sig) 87void do_boot_timer_handler(struct sigcontext * sc)
88{ 88{
89 struct pt_regs regs; 89 struct pt_regs regs;
90 90
91 CHOOSE_MODE((void) 91 CHOOSE_MODE((void) (UPT_SC(&regs.regs) = sc),
92 (UPT_SC(&regs.regs) = (struct sigcontext *) (&sig + 1)),
93 (void) (regs.regs.skas.is_user = 0)); 92 (void) (regs.regs.skas.is_user = 0));
94 do_timer(&regs); 93 do_timer(&regs);
95} 94}
96 95
96static DEFINE_SPINLOCK(timer_spinlock);
97
98static unsigned long long local_offset = 0;
99
100static inline unsigned long long get_time(void)
101{
102 unsigned long long nsecs;
103 unsigned long flags;
104
105 spin_lock_irqsave(&timer_spinlock, flags);
106 nsecs = os_nsecs();
107 nsecs += local_offset;
108 spin_unlock_irqrestore(&timer_spinlock, flags);
109
110 return nsecs;
111}
112
97irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs) 113irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
98{ 114{
115 unsigned long long nsecs;
99 unsigned long flags; 116 unsigned long flags;
100 117
101 do_timer(regs); 118 do_timer(regs);
119
102 write_seqlock_irqsave(&xtime_lock, flags); 120 write_seqlock_irqsave(&xtime_lock, flags);
103 timer(); 121 nsecs = get_time() + local_offset;
122 xtime.tv_sec = nsecs / NSEC_PER_SEC;
123 xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC;
104 write_sequnlock_irqrestore(&xtime_lock, flags); 124 write_sequnlock_irqrestore(&xtime_lock, flags);
125
105 return(IRQ_HANDLED); 126 return(IRQ_HANDLED);
106} 127}
107 128
108long um_time(int __user *tloc) 129long um_time(int __user *tloc)
109{ 130{
110 struct timeval now; 131 long ret = get_time() / NSEC_PER_SEC;
111 132
112 do_gettimeofday(&now); 133 if((tloc != NULL) && put_user(ret, tloc))
113 if (tloc) { 134 return -EFAULT;
114 if (put_user(now.tv_sec, tloc)) 135
115 now.tv_sec = -EFAULT; 136 return ret;
116 } 137}
117 return now.tv_sec; 138
139void do_gettimeofday(struct timeval *tv)
140{
141 unsigned long long nsecs = get_time();
142
143 tv->tv_sec = nsecs / NSEC_PER_SEC;
144 /* Careful about calculations here - this was originally done as
145 * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC
146 * which gave bogus (> 1000000) values. Dunno why, suspect gcc
147 * (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion
148 * problem that I missed.
149 */
150 nsecs -= tv->tv_sec * NSEC_PER_SEC;
151 tv->tv_usec = (unsigned long) nsecs / NSEC_PER_USEC;
152}
153
154static inline void set_time(unsigned long long nsecs)
155{
156 unsigned long long now;
157 unsigned long flags;
158
159 spin_lock_irqsave(&timer_spinlock, flags);
160 now = os_nsecs();
161 local_offset = nsecs - now;
162 spin_unlock_irqrestore(&timer_spinlock, flags);
163
164 clock_was_set();
118} 165}
119 166
120long um_stime(int __user *tptr) 167long um_stime(int __user *tptr)
121{ 168{
122 int value; 169 int value;
123 struct timespec new;
124 170
125 if (get_user(value, tptr)) 171 if (get_user(value, tptr))
126 return -EFAULT; 172 return -EFAULT;
127 new.tv_sec = value; 173
128 new.tv_nsec = 0; 174 set_time((unsigned long long) value * NSEC_PER_SEC);
129 do_settimeofday(&new); 175
176 return 0;
177}
178
179int do_settimeofday(struct timespec *tv)
180{
181 set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec);
182
130 return 0; 183 return 0;
131} 184}
132 185
@@ -134,29 +187,15 @@ void timer_handler(int sig, union uml_pt_regs *regs)
134{ 187{
135 local_irq_disable(); 188 local_irq_disable();
136 irq_enter(); 189 irq_enter();
137 update_process_times(CHOOSE_MODE(user_context(UPT_SP(regs)), 190 update_process_times(CHOOSE_MODE(
138 (regs)->skas.is_user)); 191 (UPT_SC(regs) && user_context(UPT_SP(regs))),
192 (regs)->skas.is_user));
139 irq_exit(); 193 irq_exit();
140 local_irq_enable(); 194 local_irq_enable();
141 if(current_thread->cpu == 0) 195 if(current_thread->cpu == 0)
142 timer_irq(regs); 196 timer_irq(regs);
143} 197}
144 198
145static DEFINE_SPINLOCK(timer_spinlock);
146
147unsigned long time_lock(void)
148{
149 unsigned long flags;
150
151 spin_lock_irqsave(&timer_spinlock, flags);
152 return(flags);
153}
154
155void time_unlock(unsigned long flags)
156{
157 spin_unlock_irqrestore(&timer_spinlock, flags);
158}
159
160int __init timer_init(void) 199int __init timer_init(void)
161{ 200{
162 int err; 201 int err;
@@ -171,14 +210,3 @@ int __init timer_init(void)
171} 210}
172 211
173__initcall(timer_init); 212__initcall(timer_init);
174
175/*
176 * Overrides for Emacs so that we follow Linus's tabbing style.
177 * Emacs will notice this stuff at the end of the file and automatically
178 * adjust the settings for this buffer only. This must remain at the end
179 * of the file.
180 * ---------------------------------------------------------------------------
181 * Local variables:
182 * c-file-style: "linux"
183 * End:
184 */
diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c
index 8f40e4838736..5c1e4cc1c049 100644
--- a/arch/um/kernel/tt/exec_kern.c
+++ b/arch/um/kernel/tt/exec_kern.c
@@ -13,7 +13,6 @@
13#include "user_util.h" 13#include "user_util.h"
14#include "kern_util.h" 14#include "kern_util.h"
15#include "irq_user.h" 15#include "irq_user.h"
16#include "time_user.h"
17#include "mem_user.h" 16#include "mem_user.h"
18#include "os.h" 17#include "os.h"
19#include "tlb.h" 18#include "tlb.h"
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c
index 37e22d71a0d9..786e4edd86c5 100644
--- a/arch/um/kernel/tt/gdb.c
+++ b/arch/um/kernel/tt/gdb.c
@@ -20,6 +20,7 @@
20#include "user_util.h" 20#include "user_util.h"
21#include "tt.h" 21#include "tt.h"
22#include "sysdep/thread.h" 22#include "sysdep/thread.h"
23#include "os.h"
23 24
24extern int debugger_pid; 25extern int debugger_pid;
25extern int debugger_fd; 26extern int debugger_fd;
diff --git a/arch/um/kernel/tt/include/mmu-tt.h b/arch/um/kernel/tt/include/mmu-tt.h
deleted file mode 100644
index 0440510ab3fe..000000000000
--- a/arch/um/kernel/tt/include/mmu-tt.h
+++ /dev/null
@@ -1,23 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __TT_MMU_H
7#define __TT_MMU_H
8
9struct mmu_context_tt {
10};
11
12#endif
13
14/*
15 * Overrides for Emacs so that we follow Linus's tabbing style.
16 * Emacs will notice this stuff at the end of the file and automatically
17 * adjust the settings for this buffer only. This must remain at the end
18 * of the file.
19 * ---------------------------------------------------------------------------
20 * Local variables:
21 * c-file-style: "linux"
22 * End:
23 */
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index 62535303aa27..295c1ac817b3 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -18,7 +18,6 @@
18#include "os.h" 18#include "os.h"
19#include "kern.h" 19#include "kern.h"
20#include "sigcontext.h" 20#include "sigcontext.h"
21#include "time_user.h"
22#include "mem_user.h" 21#include "mem_user.h"
23#include "tlb.h" 22#include "tlb.h"
24#include "mode.h" 23#include "mode.h"
diff --git a/arch/um/kernel/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c
index 528a5fc8d887..03774427d468 100644
--- a/arch/um/kernel/tt/ptproxy/ptrace.c
+++ b/arch/um/kernel/tt/ptproxy/ptrace.c
@@ -20,6 +20,7 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml
20#include "kern_util.h" 20#include "kern_util.h"
21#include "ptrace_user.h" 21#include "ptrace_user.h"
22#include "tt.h" 22#include "tt.h"
23#include "os.h"
23 24
24long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2, 25long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2,
25 long arg3, long arg4, pid_t child, int *ret) 26 long arg3, long arg4, pid_t child, int *ret)
diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c
index a5f0e01e214e..99f178319d03 100644
--- a/arch/um/kernel/tt/ptproxy/sysdep.c
+++ b/arch/um/kernel/tt/ptproxy/sysdep.c
@@ -15,6 +15,7 @@ terms and conditions.
15#include "ptrace_user.h" 15#include "ptrace_user.h"
16#include "user_util.h" 16#include "user_util.h"
17#include "user.h" 17#include "user.h"
18#include "os.h"
18 19
19int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4, 20int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4,
20 long *arg5) 21 long *arg5)
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c
index a414c529fbcd..b5d9d64d91e4 100644
--- a/arch/um/kernel/tt/trap_user.c
+++ b/arch/um/kernel/tt/trap_user.c
@@ -18,7 +18,7 @@ void sig_handler_common_tt(int sig, void *sc_ptr)
18{ 18{
19 struct sigcontext *sc = sc_ptr; 19 struct sigcontext *sc = sc_ptr;
20 struct tt_regs save_regs, *r; 20 struct tt_regs save_regs, *r;
21 int save_errno = errno, is_user; 21 int save_errno = errno, is_user = 0;
22 void (*handler)(int, union uml_pt_regs *); 22 void (*handler)(int, union uml_pt_regs *);
23 23
24 /* This is done because to allow SIGSEGV to be delivered inside a SEGV 24 /* This is done because to allow SIGSEGV to be delivered inside a SEGV
@@ -35,7 +35,8 @@ void sig_handler_common_tt(int sig, void *sc_ptr)
35 GET_FAULTINFO_FROM_SC(r->faultinfo, sc); 35 GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
36 } 36 }
37 save_regs = *r; 37 save_regs = *r;
38 is_user = user_context(SC_SP(sc)); 38 if (sc)
39 is_user = user_context(SC_SP(sc));
39 r->sc = sc; 40 r->sc = sc;
40 if(sig != SIGUSR2) 41 if(sig != SIGUSR2)
41 r->syscall = -1; 42 r->syscall = -1;
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 40c7d6b1df68..08a4e628b24c 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -5,12 +5,12 @@
5 5
6obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ 6obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
7 start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o user_syms.o \ 7 start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o user_syms.o \
8 drivers/ sys-$(SUBARCH)/ 8 util.o drivers/ sys-$(SUBARCH)/
9 9
10obj-$(CONFIG_MODE_SKAS) += skas/ 10obj-$(CONFIG_MODE_SKAS) += skas/
11 11
12USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ 12USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
13 start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o 13 start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o util.o
14 14
15elf_aux.o: $(ARCH_DIR)/kernel-offsets.h 15elf_aux.o: $(ARCH_DIR)/kernel-offsets.h
16CFLAGS_elf_aux.o += -I$(objtree)/arch/um 16CFLAGS_elf_aux.o += -I$(objtree)/arch/um
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 36cc8475bcda..6490a4ff40ac 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -60,7 +60,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
60 60
61 if((stack_out != NULL) && (*stack_out != 0)) 61 if((stack_out != NULL) && (*stack_out != 0))
62 stack = *stack_out; 62 stack = *stack_out;
63 else stack = alloc_stack(0, um_in_interrupt()); 63 else stack = alloc_stack(0, __cant_sleep());
64 if(stack == 0) 64 if(stack == 0)
65 return(-ENOMEM); 65 return(-ENOMEM);
66 66
@@ -124,7 +124,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
124 unsigned long stack, sp; 124 unsigned long stack, sp;
125 int pid, status, err; 125 int pid, status, err;
126 126
127 stack = alloc_stack(stack_order, um_in_interrupt()); 127 stack = alloc_stack(stack_order, __cant_sleep());
128 if(stack == 0) return(-ENOMEM); 128 if(stack == 0) return(-ENOMEM);
129 129
130 sp = stack + (page_size() << stack_order) - sizeof(void *); 130 sp = stack + (page_size() << stack_order) - sizeof(void *);
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 172c8474453c..2878e89a674f 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -16,7 +16,6 @@
16#include "user_util.h" 16#include "user_util.h"
17#include "kern_util.h" 17#include "kern_util.h"
18#include "mem_user.h" 18#include "mem_user.h"
19#include "time_user.h"
20#include "irq_user.h" 19#include "irq_user.h"
21#include "user.h" 20#include "user.h"
22#include "init.h" 21#include "init.h"
@@ -82,20 +81,8 @@ extern void scan_elf_aux( char **envp);
82int main(int argc, char **argv, char **envp) 81int main(int argc, char **argv, char **envp)
83{ 82{
84 char **new_argv; 83 char **new_argv;
85 sigset_t mask;
86 int ret, i, err; 84 int ret, i, err;
87 85
88 /* Enable all signals except SIGIO - in some environments, we can
89 * enter with some signals blocked
90 */
91
92 sigemptyset(&mask);
93 sigaddset(&mask, SIGIO);
94 if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){
95 perror("sigprocmask");
96 exit(1);
97 }
98
99#ifdef UML_CONFIG_CMDLINE_ON_HOST 86#ifdef UML_CONFIG_CMDLINE_ON_HOST
100 /* Allocate memory for thread command lines */ 87 /* Allocate memory for thread command lines */
101 if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){ 88 if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 39815c6b5e45..7f5e2dac2a35 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -18,6 +18,7 @@
18#include "process.h" 18#include "process.h"
19#include "irq_user.h" 19#include "irq_user.h"
20#include "kern_util.h" 20#include "kern_util.h"
21#include "longjmp.h"
21 22
22#define ARBITRARY_ADDR -1 23#define ARBITRARY_ADDR -1
23#define FAILURE_PID -1 24#define FAILURE_PID -1
@@ -205,24 +206,13 @@ void init_new_thread_signals(int altstack)
205 206
206int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) 207int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
207{ 208{
208 sigjmp_buf buf; 209 sigjmp_buf buf;
209 int n; 210 int n, enable;
210 211
211 *jmp_ptr = &buf; 212 *jmp_ptr = &buf;
212 n = sigsetjmp(buf, 1); 213 n = UML_SIGSETJMP(&buf, enable);
213 if(n != 0) 214 if(n != 0)
214 return(n); 215 return(n);
215 (*fn)(arg); 216 (*fn)(arg);
216 return(0); 217 return(0);
217} 218}
218
219/*
220 * Overrides for Emacs so that we follow Linus's tabbing style.
221 * Emacs will notice this stuff at the end of the file and automatically
222 * adjust the settings for this buffer only. This must remain at the end
223 * of the file.
224 * ---------------------------------------------------------------------------
225 * Local variables:
226 * c-file-style: "linux"
227 * End:
228 */
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index c1f46a0fef13..f11b3124a0c8 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -12,32 +12,66 @@
12#include <string.h> 12#include <string.h>
13#include <sys/mman.h> 13#include <sys/mman.h>
14#include "user_util.h" 14#include "user_util.h"
15#include "kern_util.h"
16#include "user.h" 15#include "user.h"
17#include "signal_kern.h" 16#include "signal_kern.h"
18#include "sysdep/sigcontext.h" 17#include "sysdep/sigcontext.h"
19#include "sysdep/signal.h" 18#include "sysdep/signal.h"
20#include "sigcontext.h" 19#include "sigcontext.h"
21#include "time_user.h"
22#include "mode.h" 20#include "mode.h"
21#include "os.h"
22
23/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled
24 * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to
25 * be able to profile all of UML, not just the non-critical sections. If
26 * profiling is not thread-safe, then that is not my problem. We can disable
27 * profiling when SMP is enabled in that case.
28 */
29#define SIGIO_BIT 0
30#define SIGIO_MASK (1 << SIGIO_BIT)
31
32#define SIGVTALRM_BIT 1
33#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)
34
35#define SIGALRM_BIT 2
36#define SIGALRM_MASK (1 << SIGALRM_BIT)
37
38static int signals_enabled = 1;
39static int pending = 0;
23 40
24void sig_handler(ARCH_SIGHDLR_PARAM) 41void sig_handler(ARCH_SIGHDLR_PARAM)
25{ 42{
26 struct sigcontext *sc; 43 struct sigcontext *sc;
44 int enabled;
45
46 /* Must be the first thing that this handler does - x86_64 stores
47 * the sigcontext in %rdx, and we need to save it before it has a
48 * chance to get trashed.
49 */
27 50
28 ARCH_GET_SIGCONTEXT(sc, sig); 51 ARCH_GET_SIGCONTEXT(sc, sig);
52
53 enabled = signals_enabled;
54 if(!enabled && (sig == SIGIO)){
55 pending |= SIGIO_MASK;
56 return;
57 }
58
59 block_signals();
60
29 CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, 61 CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
30 sig, sc); 62 sig, sc);
63
64 set_signals(enabled);
31} 65}
32 66
33extern int timer_irq_inited; 67extern int timer_irq_inited;
34 68
35void alarm_handler(ARCH_SIGHDLR_PARAM) 69static void real_alarm_handler(int sig, struct sigcontext *sc)
36{ 70{
37 struct sigcontext *sc; 71 if(!timer_irq_inited){
38 72 signals_enabled = 1;
39 ARCH_GET_SIGCONTEXT(sc, sig); 73 return;
40 if(!timer_irq_inited) return; 74 }
41 75
42 if(sig == SIGALRM) 76 if(sig == SIGALRM)
43 switch_timers(0); 77 switch_timers(0);
@@ -47,6 +81,52 @@ void alarm_handler(ARCH_SIGHDLR_PARAM)
47 81
48 if(sig == SIGALRM) 82 if(sig == SIGALRM)
49 switch_timers(1); 83 switch_timers(1);
84
85}
86
87void alarm_handler(ARCH_SIGHDLR_PARAM)
88{
89 struct sigcontext *sc;
90 int enabled;
91
92 ARCH_GET_SIGCONTEXT(sc, sig);
93
94 enabled = signals_enabled;
95 if(!signals_enabled){
96 if(sig == SIGVTALRM)
97 pending |= SIGVTALRM_MASK;
98 else pending |= SIGALRM_MASK;
99
100 return;
101 }
102
103 block_signals();
104
105 real_alarm_handler(sig, sc);
106 set_signals(enabled);
107}
108
109extern void do_boot_timer_handler(struct sigcontext * sc);
110
111void boot_timer_handler(ARCH_SIGHDLR_PARAM)
112{
113 struct sigcontext *sc;
114 int enabled;
115
116 ARCH_GET_SIGCONTEXT(sc, sig);
117
118 enabled = signals_enabled;
119 if(!enabled){
120 if(sig == SIGVTALRM)
121 pending |= SIGVTALRM_MASK;
122 else pending |= SIGALRM_MASK;
123 return;
124 }
125
126 block_signals();
127
128 do_boot_timer_handler(sc);
129 set_signals(enabled);
50} 130}
51 131
52void set_sigstack(void *sig_stack, int size) 132void set_sigstack(void *sig_stack, int size)
@@ -73,6 +153,7 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
73{ 153{
74 struct sigaction action; 154 struct sigaction action;
75 va_list ap; 155 va_list ap;
156 sigset_t sig_mask;
76 int mask; 157 int mask;
77 158
78 va_start(ap, flags); 159 va_start(ap, flags);
@@ -85,7 +166,12 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
85 action.sa_flags = flags; 166 action.sa_flags = flags;
86 action.sa_restorer = NULL; 167 action.sa_restorer = NULL;
87 if(sigaction(sig, &action, NULL) < 0) 168 if(sigaction(sig, &action, NULL) < 0)
88 panic("sigaction failed"); 169 panic("sigaction failed - errno = %d\n", errno);
170
171 sigemptyset(&sig_mask);
172 sigaddset(&sig_mask, sig);
173 if(sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0)
174 panic("sigprocmask failed - errno = %d\n", errno);
89} 175}
90 176
91int change_sig(int signal, int on) 177int change_sig(int signal, int on)
@@ -98,89 +184,77 @@ int change_sig(int signal, int on)
98 return(!sigismember(&old, signal)); 184 return(!sigismember(&old, signal));
99} 185}
100 186
101/* Both here and in set/get_signal we don't touch SIGPROF, because we must not
102 * disable profiling; it's safe because the profiling code does not interact
103 * with the kernel code at all.*/
104
105static void change_signals(int type)
106{
107 sigset_t mask;
108
109 sigemptyset(&mask);
110 sigaddset(&mask, SIGVTALRM);
111 sigaddset(&mask, SIGALRM);
112 sigaddset(&mask, SIGIO);
113 if(sigprocmask(type, &mask, NULL) < 0)
114 panic("Failed to change signal mask - errno = %d", errno);
115}
116
117void block_signals(void) 187void block_signals(void)
118{ 188{
119 change_signals(SIG_BLOCK); 189 signals_enabled = 0;
120} 190}
121 191
122void unblock_signals(void) 192void unblock_signals(void)
123{ 193{
124 change_signals(SIG_UNBLOCK); 194 int save_pending;
125}
126 195
127/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled 196 if(signals_enabled == 1)
128 * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to 197 return;
129 * be able to profile all of UML, not just the non-critical sections. If
130 * profiling is not thread-safe, then that is not my problem. We can disable
131 * profiling when SMP is enabled in that case.
132 */
133#define SIGIO_BIT 0
134#define SIGVTALRM_BIT 1
135 198
136static int enable_mask(sigset_t *mask) 199 /* We loop because the IRQ handler returns with interrupts off. So,
137{ 200 * interrupts may have arrived and we need to re-enable them and
138 int sigs; 201 * recheck pending.
202 */
203 while(1){
204 /* Save and reset save_pending after enabling signals. This
205 * way, pending won't be changed while we're reading it.
206 */
207 signals_enabled = 1;
208
209 save_pending = pending;
210 if(save_pending == 0)
211 return;
212
213 pending = 0;
214
215 /* We have pending interrupts, so disable signals, as the
216 * handlers expect them off when they are called. They will
217 * be enabled again above.
218 */
219
220 signals_enabled = 0;
139 221
140 sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT; 222 /* Deal with SIGIO first because the alarm handler might
141 sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT; 223 * schedule, leaving the pending SIGIO stranded until we come
142 sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT; 224 * back here.
143 return(sigs); 225 */
226 if(save_pending & SIGIO_MASK)
227 CHOOSE_MODE_PROC(sig_handler_common_tt,
228 sig_handler_common_skas, SIGIO, NULL);
229
230 if(save_pending & SIGALRM_MASK)
231 real_alarm_handler(SIGALRM, NULL);
232
233 if(save_pending & SIGVTALRM_MASK)
234 real_alarm_handler(SIGVTALRM, NULL);
235 }
144} 236}
145 237
146int get_signals(void) 238int get_signals(void)
147{ 239{
148 sigset_t mask; 240 return signals_enabled;
149
150 if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0)
151 panic("Failed to get signal mask");
152 return(enable_mask(&mask));
153} 241}
154 242
155int set_signals(int enable) 243int set_signals(int enable)
156{ 244{
157 sigset_t mask;
158 int ret; 245 int ret;
246 if(signals_enabled == enable)
247 return enable;
159 248
160 sigemptyset(&mask); 249 ret = signals_enabled;
161 if(enable & (1 << SIGIO_BIT)) 250 if(enable)
162 sigaddset(&mask, SIGIO); 251 unblock_signals();
163 if(enable & (1 << SIGVTALRM_BIT)){ 252 else block_signals();
164 sigaddset(&mask, SIGVTALRM);
165 sigaddset(&mask, SIGALRM);
166 }
167 253
168 /* This is safe - sigprocmask is guaranteed to copy locally the 254 return ret;
169 * value of new_set, do his work and then, at the end, write to 255}
170 * old_set.
171 */
172 if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
173 panic("Failed to enable signals");
174 ret = enable_mask(&mask);
175 sigemptyset(&mask);
176 if((enable & (1 << SIGIO_BIT)) == 0)
177 sigaddset(&mask, SIGIO);
178 if((enable & (1 << SIGVTALRM_BIT)) == 0){
179 sigaddset(&mask, SIGVTALRM);
180 sigaddset(&mask, SIGALRM);
181 }
182 if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0)
183 panic("Failed to block signals");
184 256
185 return(ret); 257void os_usr1_signal(int on)
258{
259 change_sig(SIGUSR1, on);
186} 260}
diff --git a/arch/um/os-Linux/skas/Makefile b/arch/um/os-Linux/skas/Makefile
index eab5386d60a7..5fd8d4dad66a 100644
--- a/arch/um/os-Linux/skas/Makefile
+++ b/arch/um/os-Linux/skas/Makefile
@@ -3,8 +3,8 @@
3# Licensed under the GPL 3# Licensed under the GPL
4# 4#
5 5
6obj-y := trap.o 6obj-y := mem.o process.o trap.o
7 7
8USER_OBJS := trap.o 8USER_OBJS := mem.o process.o trap.o
9 9
10include arch/um/scripts/Makefile.rules 10include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/skas/mem_user.c b/arch/um/os-Linux/skas/mem.c
index 1d89640bd502..9890e9090f58 100644
--- a/arch/um/kernel/skas/mem_user.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -32,7 +32,7 @@ extern void wait_stub_done(int pid, int sig, char * fname);
32static inline unsigned long *check_init_stack(struct mm_id * mm_idp, 32static inline unsigned long *check_init_stack(struct mm_id * mm_idp,
33 unsigned long *stack) 33 unsigned long *stack)
34{ 34{
35 if(stack == NULL){ 35 if(stack == NULL) {
36 stack = (unsigned long *) mm_idp->stack + 2; 36 stack = (unsigned long *) mm_idp->stack + 2;
37 *stack = 0; 37 *stack = 0;
38 } 38 }
@@ -45,13 +45,14 @@ int single_count = 0;
45int multi_count = 0; 45int multi_count = 0;
46int multi_op_count = 0; 46int multi_op_count = 0;
47 47
48static long do_syscall_stub(struct mm_id *mm_idp, void **addr) 48static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
49{ 49{
50 unsigned long regs[MAX_REG_NR]; 50 unsigned long regs[MAX_REG_NR];
51 unsigned long *data; 51 int n;
52 unsigned long *syscall;
53 long ret, offset; 52 long ret, offset;
54 int n, pid = mm_idp->u.pid; 53 unsigned long * data;
54 unsigned long * syscall;
55 int pid = mm_idp->u.pid;
55 56
56 if(proc_mm) 57 if(proc_mm)
57#warning Need to look up userspace_pid by cpu 58#warning Need to look up userspace_pid by cpu
@@ -59,10 +60,11 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr)
59 60
60 multi_count++; 61 multi_count++;
61 62
62 get_safe_registers(regs); 63 get_safe_registers(regs);
63 regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + 64 regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
64 ((unsigned long) &batch_syscall_stub - 65 ((unsigned long) &batch_syscall_stub -
65 (unsigned long) &__syscall_stub_start); 66 (unsigned long) &__syscall_stub_start);
67
66 n = ptrace_setregs(pid, regs); 68 n = ptrace_setregs(pid, regs);
67 if(n < 0) 69 if(n < 0)
68 panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", 70 panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n",
@@ -80,6 +82,8 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr)
80 if (offset) { 82 if (offset) {
81 data = (unsigned long *)(mm_idp->stack + 83 data = (unsigned long *)(mm_idp->stack +
82 offset - UML_CONFIG_STUB_DATA); 84 offset - UML_CONFIG_STUB_DATA);
85 printk("do_syscall_stub : ret = %d, offset = %d, "
86 "data = 0x%x\n", ret, offset, data);
83 syscall = (unsigned long *)((unsigned long)data + data[0]); 87 syscall = (unsigned long *)((unsigned long)data + data[0]);
84 printk("do_syscall_stub: syscall %ld failed, return value = " 88 printk("do_syscall_stub: syscall %ld failed, return value = "
85 "0x%lx, expected return value = 0x%lx\n", 89 "0x%lx, expected return value = 0x%lx\n",
@@ -107,32 +111,32 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr)
107 111
108long run_syscall_stub(struct mm_id * mm_idp, int syscall, 112long run_syscall_stub(struct mm_id * mm_idp, int syscall,
109 unsigned long *args, long expected, void **addr, 113 unsigned long *args, long expected, void **addr,
110 int done) 114 int done)
111{ 115{
112 unsigned long *stack = check_init_stack(mm_idp, *addr); 116 unsigned long *stack = check_init_stack(mm_idp, *addr);
113 117
114 if(done && *addr == NULL) 118 if(done && *addr == NULL)
115 single_count++; 119 single_count++;
116 120
117 *stack += sizeof(long); 121 *stack += sizeof(long);
118 stack += *stack / sizeof(long); 122 stack += *stack / sizeof(long);
119 123
120 *stack++ = syscall; 124 *stack++ = syscall;
121 *stack++ = args[0]; 125 *stack++ = args[0];
122 *stack++ = args[1]; 126 *stack++ = args[1];
123 *stack++ = args[2]; 127 *stack++ = args[2];
124 *stack++ = args[3]; 128 *stack++ = args[3];
125 *stack++ = args[4]; 129 *stack++ = args[4];
126 *stack++ = args[5]; 130 *stack++ = args[5];
127 *stack++ = expected; 131 *stack++ = expected;
128 *stack = 0; 132 *stack = 0;
129 multi_op_count++; 133 multi_op_count++;
130 134
131 if(!done && ((((unsigned long) stack) & ~PAGE_MASK) < 135 if(!done && ((((unsigned long) stack) & ~PAGE_MASK) <
132 PAGE_SIZE - 10 * sizeof(long))){ 136 PAGE_SIZE - 10 * sizeof(long))){
133 *addr = stack; 137 *addr = stack;
134 return 0; 138 return 0;
135 } 139 }
136 140
137 return do_syscall_stub(mm_idp, addr); 141 return do_syscall_stub(mm_idp, addr);
138} 142}
@@ -150,7 +154,7 @@ long syscall_stub_data(struct mm_id * mm_idp,
150 if((((unsigned long) *addr) & ~PAGE_MASK) >= 154 if((((unsigned long) *addr) & ~PAGE_MASK) >=
151 PAGE_SIZE - (10 + data_count) * sizeof(long)) { 155 PAGE_SIZE - (10 + data_count) * sizeof(long)) {
152 ret = do_syscall_stub(mm_idp, addr); 156 ret = do_syscall_stub(mm_idp, addr);
153 /* in case of error, don't overwrite data on stack */ 157 /* in case of error, don't overwrite data on stack */
154 if(ret) 158 if(ret)
155 return ret; 159 return ret;
156 } 160 }
@@ -172,39 +176,39 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len,
172 int r, int w, int x, int phys_fd, unsigned long long offset, 176 int r, int w, int x, int phys_fd, unsigned long long offset,
173 int done, void **data) 177 int done, void **data)
174{ 178{
175 int prot, ret; 179 int prot, ret;
176 180
177 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 181 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
178 (x ? PROT_EXEC : 0); 182 (x ? PROT_EXEC : 0);
179 183
180 if(proc_mm){ 184 if(proc_mm){
181 struct proc_mm_op map; 185 struct proc_mm_op map;
182 int fd = mm_idp->u.mm_fd; 186 int fd = mm_idp->u.mm_fd;
183 187
184 map = ((struct proc_mm_op) { .op = MM_MMAP, 188 map = ((struct proc_mm_op) { .op = MM_MMAP,
185 .u = 189 .u =
186 { .mmap = 190 { .mmap =
187 { .addr = virt, 191 { .addr = virt,
188 .len = len, 192 .len = len,
189 .prot = prot, 193 .prot = prot,
190 .flags = MAP_SHARED | 194 .flags = MAP_SHARED |
191 MAP_FIXED, 195 MAP_FIXED,
192 .fd = phys_fd, 196 .fd = phys_fd,
193 .offset= offset 197 .offset= offset
194 } } } ); 198 } } } );
195 ret = os_write_file(fd, &map, sizeof(map)); 199 ret = os_write_file(fd, &map, sizeof(map));
196 if(ret != sizeof(map)) 200 if(ret != sizeof(map))
197 printk("map : /proc/mm map failed, err = %d\n", -ret); 201 printk("map : /proc/mm map failed, err = %d\n", -ret);
198 else ret = 0; 202 else ret = 0;
199 } 203 }
200 else { 204 else {
201 unsigned long args[] = { virt, len, prot, 205 unsigned long args[] = { virt, len, prot,
202 MAP_SHARED | MAP_FIXED, phys_fd, 206 MAP_SHARED | MAP_FIXED, phys_fd,
203 MMAP_OFFSET(offset) }; 207 MMAP_OFFSET(offset) };
204 208
205 ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt, 209 ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt,
206 data, done); 210 data, done);
207 } 211 }
208 212
209 return ret; 213 return ret;
210} 214}
@@ -212,68 +216,66 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len,
212int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done, 216int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done,
213 void **data) 217 void **data)
214{ 218{
215 int ret; 219 int ret;
216 220
217 if(proc_mm){ 221 if(proc_mm){
218 struct proc_mm_op unmap; 222 struct proc_mm_op unmap;
219 int fd = mm_idp->u.mm_fd; 223 int fd = mm_idp->u.mm_fd;
220 224
221 unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, 225 unmap = ((struct proc_mm_op) { .op = MM_MUNMAP,
222 .u = 226 .u =
223 { .munmap = 227 { .munmap =
224 { .addr = 228 { .addr =
225 (unsigned long) addr, 229 (unsigned long) addr,
226 .len = len } } } ); 230 .len = len } } } );
227 ret = os_write_file(fd, &unmap, sizeof(unmap)); 231 ret = os_write_file(fd, &unmap, sizeof(unmap));
228 if(ret != sizeof(unmap)) 232 if(ret != sizeof(unmap))
229 printk("unmap - proc_mm write returned %d\n", ret); 233 printk("unmap - proc_mm write returned %d\n", ret);
230 else ret = 0; 234 else ret = 0;
231 } 235 }
232 else { 236 else {
233 unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0, 237 unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0,
234 0 }; 238 0 };
235 239
236 ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0, 240 ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0,
237 data, done); 241 data, done);
238 if(ret < 0) 242 }
239 printk("munmap stub failed, errno = %d\n", ret);
240 }
241 243
242 return ret; 244 return ret;
243} 245}
244 246
245int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, 247int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
246 int r, int w, int x, int done, void **data) 248 int r, int w, int x, int done, void **data)
247{ 249{
248 struct proc_mm_op protect; 250 struct proc_mm_op protect;
249 int prot, ret; 251 int prot, ret;
250 252
251 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 253 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
252 (x ? PROT_EXEC : 0); 254 (x ? PROT_EXEC : 0);
253 255 if(proc_mm){
254 if(proc_mm){ 256 int fd = mm_idp->u.mm_fd;
255 int fd = mm_idp->u.mm_fd; 257
256 protect = ((struct proc_mm_op) { .op = MM_MPROTECT, 258 protect = ((struct proc_mm_op) { .op = MM_MPROTECT,
257 .u = 259 .u =
258 { .mprotect = 260 { .mprotect =
259 { .addr = 261 { .addr =
260 (unsigned long) addr, 262 (unsigned long) addr,
261 .len = len, 263 .len = len,
262 .prot = prot } } } ); 264 .prot = prot } } } );
263 265
264 ret = os_write_file(fd, &protect, sizeof(protect)); 266 ret = os_write_file(fd, &protect, sizeof(protect));
265 if(ret != sizeof(protect)) 267 if(ret != sizeof(protect))
266 printk("protect failed, err = %d", -ret); 268 printk("protect failed, err = %d", -ret);
267 else ret = 0; 269 else ret = 0;
268 } 270 }
269 else { 271 else {
270 unsigned long args[] = { addr, len, prot, 0, 0, 0 }; 272 unsigned long args[] = { addr, len, prot, 0, 0, 0 };
271 273
272 ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0, 274 ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0,
273 data, done); 275 data, done);
274 } 276 }
275 277
276 return ret; 278 return ret;
277} 279}
278 280
279void before_mem_skas(unsigned long unused) 281void before_mem_skas(unsigned long unused)
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
new file mode 100644
index 000000000000..120a21c5883f
--- /dev/null
+++ b/arch/um/os-Linux/skas/process.c
@@ -0,0 +1,566 @@
1/*
2 * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com)
3 * Licensed under the GPL
4 */
5
6#include <stdlib.h>
7#include <string.h>
8#include <unistd.h>
9#include <errno.h>
10#include <signal.h>
11#include <setjmp.h>
12#include <sched.h>
13#include "ptrace_user.h"
14#include <sys/wait.h>
15#include <sys/mman.h>
16#include <sys/user.h>
17#include <sys/time.h>
18#include <asm/unistd.h>
19#include <asm/types.h>
20#include "user.h"
21#include "sysdep/ptrace.h"
22#include "user_util.h"
23#include "kern_util.h"
24#include "skas.h"
25#include "stub-data.h"
26#include "mm_id.h"
27#include "sysdep/sigcontext.h"
28#include "sysdep/stub.h"
29#include "os.h"
30#include "proc_mm.h"
31#include "skas_ptrace.h"
32#include "chan_user.h"
33#include "registers.h"
34#include "mem.h"
35#include "uml-config.h"
36#include "process.h"
37#include "longjmp.h"
38
39int is_skas_winch(int pid, int fd, void *data)
40{
41 if(pid != os_getpgrp())
42 return(0);
43
44 register_winch_irq(-1, fd, -1, data);
45 return(1);
46}
47
48void wait_stub_done(int pid, int sig, char * fname)
49{
50 int n, status, err;
51
52 do {
53 if ( sig != -1 ) {
54 err = ptrace(PTRACE_CONT, pid, 0, sig);
55 if(err)
56 panic("%s : continue failed, errno = %d\n",
57 fname, errno);
58 }
59 sig = 0;
60
61 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
62 } while((n >= 0) && WIFSTOPPED(status) &&
63 ((WSTOPSIG(status) == SIGVTALRM) ||
64 /* running UML inside a detached screen can cause
65 * SIGWINCHes
66 */
67 (WSTOPSIG(status) == SIGWINCH)));
68
69 if((n < 0) || !WIFSTOPPED(status) ||
70 (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){
71 unsigned long regs[HOST_FRAME_SIZE];
72
73 if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
74 printk("Failed to get registers from stub, "
75 "errno = %d\n", errno);
76 else {
77 int i;
78
79 printk("Stub registers -\n");
80 for(i = 0; i < HOST_FRAME_SIZE; i++)
81 printk("\t%d - %lx\n", i, regs[i]);
82 }
83 panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
84 "pid = %d, n = %d, errno = %d, status = 0x%x\n",
85 fname, pid, n, errno, status);
86 }
87}
88
89extern unsigned long current_stub_stack(void);
90
91void get_skas_faultinfo(int pid, struct faultinfo * fi)
92{
93 int err;
94
95 if(ptrace_faultinfo){
96 err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
97 if(err)
98 panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "
99 "errno = %d\n", errno);
100
101 /* Special handling for i386, which has different structs */
102 if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
103 memset((char *)fi + sizeof(struct ptrace_faultinfo), 0,
104 sizeof(struct faultinfo) -
105 sizeof(struct ptrace_faultinfo));
106 }
107 else {
108 wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo");
109
110 /* faultinfo is prepared by the stub-segv-handler at start of
111 * the stub stack page. We just have to copy it.
112 */
113 memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
114 }
115}
116
117static void handle_segv(int pid, union uml_pt_regs * regs)
118{
119 get_skas_faultinfo(pid, &regs->skas.faultinfo);
120 segv(regs->skas.faultinfo, 0, 1, NULL);
121}
122
123/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
124static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu)
125{
126 int err, status;
127
128 /* Mark this as a syscall */
129 UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs);
130
131 if (!local_using_sysemu)
132 {
133 err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
134 __NR_getpid);
135 if(err < 0)
136 panic("handle_trap - nullifying syscall failed errno = %d\n",
137 errno);
138
139 err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
140 if(err < 0)
141 panic("handle_trap - continuing to end of syscall failed, "
142 "errno = %d\n", errno);
143
144 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
145 if((err < 0) || !WIFSTOPPED(status) ||
146 (WSTOPSIG(status) != SIGTRAP + 0x80))
147 panic("handle_trap - failed to wait at end of syscall, "
148 "errno = %d, status = %d\n", errno, status);
149 }
150
151 handle_syscall(regs);
152}
153
154extern int __syscall_stub_start;
155
156static int userspace_tramp(void *stack)
157{
158 void *addr;
159
160 ptrace(PTRACE_TRACEME, 0, 0, 0);
161
162 init_new_thread_signals(1);
163 enable_timer();
164
165 if(!proc_mm){
166 /* This has a pte, but it can't be mapped in with the usual
167 * tlb_flush mechanism because this is part of that mechanism
168 */
169 int fd;
170 __u64 offset;
171 fd = phys_mapping(to_phys(&__syscall_stub_start), &offset);
172 addr = mmap64((void *) UML_CONFIG_STUB_CODE, page_size(),
173 PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
174 if(addr == MAP_FAILED){
175 printk("mapping mmap stub failed, errno = %d\n",
176 errno);
177 exit(1);
178 }
179
180 if(stack != NULL){
181 fd = phys_mapping(to_phys(stack), &offset);
182 addr = mmap((void *) UML_CONFIG_STUB_DATA, page_size(),
183 PROT_READ | PROT_WRITE,
184 MAP_FIXED | MAP_SHARED, fd, offset);
185 if(addr == MAP_FAILED){
186 printk("mapping segfault stack failed, "
187 "errno = %d\n", errno);
188 exit(1);
189 }
190 }
191 }
192 if(!ptrace_faultinfo && (stack != NULL)){
193 unsigned long v = UML_CONFIG_STUB_CODE +
194 (unsigned long) stub_segv_handler -
195 (unsigned long) &__syscall_stub_start;
196
197 set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size());
198 set_handler(SIGSEGV, (void *) v, SA_ONSTACK,
199 SIGIO, SIGWINCH, SIGALRM, SIGVTALRM,
200 SIGUSR1, -1);
201 }
202
203 os_stop_process(os_getpid());
204 return(0);
205}
206
207/* Each element set once, and only accessed by a single processor anyway */
208#undef NR_CPUS
209#define NR_CPUS 1
210int userspace_pid[NR_CPUS];
211
212int start_userspace(unsigned long stub_stack)
213{
214 void *stack;
215 unsigned long sp;
216 int pid, status, n, flags;
217
218 stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
219 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
220 if(stack == MAP_FAILED)
221 panic("start_userspace : mmap failed, errno = %d", errno);
222 sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
223
224 flags = CLONE_FILES | SIGCHLD;
225 if(proc_mm) flags |= CLONE_VM;
226 pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
227 if(pid < 0)
228 panic("start_userspace : clone failed, errno = %d", errno);
229
230 do {
231 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
232 if(n < 0)
233 panic("start_userspace : wait failed, errno = %d",
234 errno);
235 } while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM));
236
237 if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
238 panic("start_userspace : expected SIGSTOP, got status = %d",
239 status);
240
241 if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0)
242 panic("start_userspace : PTRACE_OLDSETOPTIONS failed, errno=%d\n",
243 errno);
244
245 if(munmap(stack, PAGE_SIZE) < 0)
246 panic("start_userspace : munmap failed, errno = %d\n", errno);
247
248 return(pid);
249}
250
251void userspace(union uml_pt_regs *regs)
252{
253 int err, status, op, pid = userspace_pid[0];
254 int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/
255
256 while(1){
257 restore_registers(pid, regs);
258
259 /* Now we set local_using_sysemu to be used for one loop */
260 local_using_sysemu = get_using_sysemu();
261
262 op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL));
263
264 err = ptrace(op, pid, 0, 0);
265 if(err)
266 panic("userspace - could not resume userspace process, "
267 "pid=%d, ptrace operation = %d, errno = %d\n",
268 op, errno);
269
270 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
271 if(err < 0)
272 panic("userspace - waitpid failed, errno = %d\n",
273 errno);
274
275 regs->skas.is_user = 1;
276 save_registers(pid, regs);
277 UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
278
279 if(WIFSTOPPED(status)){
280 switch(WSTOPSIG(status)){
281 case SIGSEGV:
282 if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo)
283 user_signal(SIGSEGV, regs, pid);
284 else handle_segv(pid, regs);
285 break;
286 case SIGTRAP + 0x80:
287 handle_trap(pid, regs, local_using_sysemu);
288 break;
289 case SIGTRAP:
290 relay_signal(SIGTRAP, regs);
291 break;
292 case SIGIO:
293 case SIGVTALRM:
294 case SIGILL:
295 case SIGBUS:
296 case SIGFPE:
297 case SIGWINCH:
298 user_signal(WSTOPSIG(status), regs, pid);
299 break;
300 default:
301 printk("userspace - child stopped with signal "
302 "%d\n", WSTOPSIG(status));
303 }
304 pid = userspace_pid[0];
305 interrupt_end();
306
307 /* Avoid -ERESTARTSYS handling in host */
308 if(PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET)
309 PT_SYSCALL_NR(regs->skas.regs) = -1;
310 }
311 }
312}
313#define INIT_JMP_NEW_THREAD 0
314#define INIT_JMP_REMOVE_SIGSTACK 1
315#define INIT_JMP_CALLBACK 2
316#define INIT_JMP_HALT 3
317#define INIT_JMP_REBOOT 4
318
319int copy_context_skas0(unsigned long new_stack, int pid)
320{
321 int err;
322 unsigned long regs[MAX_REG_NR];
323 unsigned long current_stack = current_stub_stack();
324 struct stub_data *data = (struct stub_data *) current_stack;
325 struct stub_data *child_data = (struct stub_data *) new_stack;
326 __u64 new_offset;
327 int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset);
328
329 /* prepare offset and fd of child's stack as argument for parent's
330 * and child's mmap2 calls
331 */
332 *data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset),
333 .fd = new_fd,
334 .timer = ((struct itimerval)
335 { { 0, 1000000 / hz() },
336 { 0, 1000000 / hz() }})});
337 get_safe_registers(regs);
338
339 /* Set parent's instruction pointer to start of clone-stub */
340 regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
341 (unsigned long) stub_clone_handler -
342 (unsigned long) &__syscall_stub_start;
343 regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE -
344 sizeof(void *);
345#ifdef __SIGNAL_FRAMESIZE
346 regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
347#endif
348 err = ptrace_setregs(pid, regs);
349 if(err < 0)
350 panic("copy_context_skas0 : PTRACE_SETREGS failed, "
351 "pid = %d, errno = %d\n", pid, errno);
352
353 /* set a well known return code for detection of child write failure */
354 child_data->err = 12345678;
355
356 /* Wait, until parent has finished its work: read child's pid from
357 * parent's stack, and check, if bad result.
358 */
359 wait_stub_done(pid, 0, "copy_context_skas0");
360
361 pid = data->err;
362 if(pid < 0)
363 panic("copy_context_skas0 - stub-parent reports error %d\n",
364 pid);
365
366 /* Wait, until child has finished too: read child's result from
367 * child's stack and check it.
368 */
369 wait_stub_done(pid, -1, "copy_context_skas0");
370 if (child_data->err != UML_CONFIG_STUB_DATA)
371 panic("copy_context_skas0 - stub-child reports error %d\n",
372 child_data->err);
373
374 if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
375 (void *)PTRACE_O_TRACESYSGOOD) < 0)
376 panic("copy_context_skas0 : PTRACE_OLDSETOPTIONS failed, "
377 "errno = %d\n", errno);
378
379 return pid;
380}
381
382/*
383 * This is used only, if stub pages are needed, while proc_mm is
384 * availabl. Opening /proc/mm creates a new mm_context, which lacks
385 * the stub-pages. Thus, we map them using /proc/mm-fd
386 */
387void map_stub_pages(int fd, unsigned long code,
388 unsigned long data, unsigned long stack)
389{
390 struct proc_mm_op mmop;
391 int n;
392 __u64 code_offset;
393 int code_fd = phys_mapping(to_phys((void *) &__syscall_stub_start),
394 &code_offset);
395
396 mmop = ((struct proc_mm_op) { .op = MM_MMAP,
397 .u =
398 { .mmap =
399 { .addr = code,
400 .len = PAGE_SIZE,
401 .prot = PROT_EXEC,
402 .flags = MAP_FIXED | MAP_PRIVATE,
403 .fd = code_fd,
404 .offset = code_offset
405 } } });
406 n = os_write_file(fd, &mmop, sizeof(mmop));
407 if(n != sizeof(mmop))
408 panic("map_stub_pages : /proc/mm map for code failed, "
409 "err = %d\n", -n);
410
411 if ( stack ) {
412 __u64 map_offset;
413 int map_fd = phys_mapping(to_phys((void *)stack), &map_offset);
414 mmop = ((struct proc_mm_op)
415 { .op = MM_MMAP,
416 .u =
417 { .mmap =
418 { .addr = data,
419 .len = PAGE_SIZE,
420 .prot = PROT_READ | PROT_WRITE,
421 .flags = MAP_FIXED | MAP_SHARED,
422 .fd = map_fd,
423 .offset = map_offset
424 } } });
425 n = os_write_file(fd, &mmop, sizeof(mmop));
426 if(n != sizeof(mmop))
427 panic("map_stub_pages : /proc/mm map for data failed, "
428 "err = %d\n", -n);
429 }
430}
431
432void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
433 void (*handler)(int))
434{
435 unsigned long flags;
436 sigjmp_buf switch_buf, fork_buf;
437 int enable;
438
439 *switch_buf_ptr = &switch_buf;
440 *fork_buf_ptr = &fork_buf;
441
442 /* Somewhat subtle - siglongjmp restores the signal mask before doing
443 * the longjmp. This means that when jumping from one stack to another
444 * when the target stack has interrupts enabled, an interrupt may occur
445 * on the source stack. This is bad when starting up a process because
446 * it's not supposed to get timer ticks until it has been scheduled.
447 * So, we disable interrupts around the sigsetjmp to ensure that
448 * they can't happen until we get back here where they are safe.
449 */
450 flags = get_signals();
451 block_signals();
452 if(UML_SIGSETJMP(&fork_buf, enable) == 0)
453 new_thread_proc(stack, handler);
454
455 remove_sigstack();
456
457 set_signals(flags);
458}
459
460void thread_wait(void *sw, void *fb)
461{
462 sigjmp_buf buf, **switch_buf = sw, *fork_buf;
463 int enable;
464
465 *switch_buf = &buf;
466 fork_buf = fb;
467 if(UML_SIGSETJMP(&buf, enable) == 0)
468 siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
469}
470
471void switch_threads(void *me, void *next)
472{
473 sigjmp_buf my_buf, **me_ptr = me, *next_buf = next;
474 int enable;
475
476 *me_ptr = &my_buf;
477 if(UML_SIGSETJMP(&my_buf, enable) == 0)
478 UML_SIGLONGJMP(next_buf, 1);
479}
480
481static sigjmp_buf initial_jmpbuf;
482
483/* XXX Make these percpu */
484static void (*cb_proc)(void *arg);
485static void *cb_arg;
486static sigjmp_buf *cb_back;
487
488int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
489{
490 sigjmp_buf **switch_buf = switch_buf_ptr;
491 int n, enable;
492
493 set_handler(SIGWINCH, (__sighandler_t) sig_handler,
494 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
495 SIGVTALRM, -1);
496
497 *fork_buf_ptr = &initial_jmpbuf;
498 n = UML_SIGSETJMP(&initial_jmpbuf, enable);
499 switch(n){
500 case INIT_JMP_NEW_THREAD:
501 new_thread_proc((void *) stack, new_thread_handler);
502 break;
503 case INIT_JMP_REMOVE_SIGSTACK:
504 remove_sigstack();
505 break;
506 case INIT_JMP_CALLBACK:
507 (*cb_proc)(cb_arg);
508 UML_SIGLONGJMP(cb_back, 1);
509 break;
510 case INIT_JMP_HALT:
511 kmalloc_ok = 0;
512 return(0);
513 case INIT_JMP_REBOOT:
514 kmalloc_ok = 0;
515 return(1);
516 default:
517 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
518 }
519 UML_SIGLONGJMP(*switch_buf, 1);
520}
521
522void initial_thread_cb_skas(void (*proc)(void *), void *arg)
523{
524 sigjmp_buf here;
525 int enable;
526
527 cb_proc = proc;
528 cb_arg = arg;
529 cb_back = &here;
530
531 block_signals();
532 if(UML_SIGSETJMP(&here, enable) == 0)
533 UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
534 unblock_signals();
535
536 cb_proc = NULL;
537 cb_arg = NULL;
538 cb_back = NULL;
539}
540
541void halt_skas(void)
542{
543 block_signals();
544 UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
545}
546
547void reboot_skas(void)
548{
549 block_signals();
550 UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
551}
552
553void switch_mm_skas(struct mm_id *mm_idp)
554{
555 int err;
556
557#warning need cpu pid in switch_mm_skas
558 if(proc_mm){
559 err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
560 mm_idp->u.mm_fd);
561 if(err)
562 panic("switch_mm_skas - PTRACE_SWITCH_MM failed, "
563 "errno = %d\n", errno);
564 }
565 else userspace_pid[0] = mm_idp->u.pid;
566}
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index b47e5e71d1a5..6c5b17ed59e1 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -29,7 +29,6 @@
29#include "irq_user.h" 29#include "irq_user.h"
30#include "ptrace_user.h" 30#include "ptrace_user.h"
31#include "mem_user.h" 31#include "mem_user.h"
32#include "time_user.h"
33#include "init.h" 32#include "init.h"
34#include "os.h" 33#include "os.h"
35#include "uml-config.h" 34#include "uml-config.h"
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index cf30a39bc484..6f7626775acb 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -1,21 +1,128 @@
1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <stdio.h>
1#include <stdlib.h> 7#include <stdlib.h>
8#include <unistd.h>
9#include <time.h>
2#include <sys/time.h> 10#include <sys/time.h>
11#include <signal.h>
12#include <errno.h>
13#include "user_util.h"
14#include "kern_util.h"
15#include "user.h"
16#include "process.h"
17#include "kern_constants.h"
18#include "os.h"
19
20/* XXX This really needs to be declared and initialized in a kernel file since
21 * it's in <linux/time.h>
22 */
23extern struct timespec wall_to_monotonic;
24
25static void set_interval(int timer_type)
26{
27 int usec = 1000000/hz();
28 struct itimerval interval = ((struct itimerval) { { 0, usec },
29 { 0, usec } });
30
31 if(setitimer(timer_type, &interval, NULL) == -1)
32 panic("setitimer failed - errno = %d\n", errno);
33}
34
35void enable_timer(void)
36{
37 set_interval(ITIMER_VIRTUAL);
38}
39
40void disable_timer(void)
41{
42 struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
43 if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) ||
44 (setitimer(ITIMER_REAL, &disable, NULL) < 0))
45 printk("disnable_timer - setitimer failed, errno = %d\n",
46 errno);
47 /* If there are signals already queued, after unblocking ignore them */
48 set_handler(SIGALRM, SIG_IGN, 0, -1);
49 set_handler(SIGVTALRM, SIG_IGN, 0, -1);
50}
51
52void switch_timers(int to_real)
53{
54 struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
55 struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() },
56 { 0, 1000000/hz() }});
57 int old, new;
58
59 if(to_real){
60 old = ITIMER_VIRTUAL;
61 new = ITIMER_REAL;
62 }
63 else {
64 old = ITIMER_REAL;
65 new = ITIMER_VIRTUAL;
66 }
67
68 if((setitimer(old, &disable, NULL) < 0) ||
69 (setitimer(new, &enable, NULL)))
70 printk("switch_timers - setitimer failed, errno = %d\n",
71 errno);
72}
3 73
4unsigned long long os_usecs(void) 74void uml_idle_timer(void)
75{
76 if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
77 panic("Couldn't unset SIGVTALRM handler");
78
79 set_handler(SIGALRM, (__sighandler_t) alarm_handler,
80 SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
81 set_interval(ITIMER_REAL);
82}
83
84extern void ktime_get_ts(struct timespec *ts);
85#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
86
87void time_init(void)
88{
89 struct timespec now;
90
91 if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR)
92 panic("Couldn't set SIGVTALRM handler");
93 set_interval(ITIMER_VIRTUAL);
94
95 do_posix_clock_monotonic_gettime(&now);
96 wall_to_monotonic.tv_sec = -now.tv_sec;
97 wall_to_monotonic.tv_nsec = -now.tv_nsec;
98}
99
100unsigned long long os_nsecs(void)
5{ 101{
6 struct timeval tv; 102 struct timeval tv;
7 103
8 gettimeofday(&tv, NULL); 104 gettimeofday(&tv, NULL);
9 return((unsigned long long) tv.tv_sec * 1000000 + tv.tv_usec); 105 return((unsigned long long) tv.tv_sec * BILLION + tv.tv_usec * 1000);
10} 106}
11 107
12/* 108void idle_sleep(int secs)
13 * Overrides for Emacs so that we follow Linus's tabbing style. 109{
14 * Emacs will notice this stuff at the end of the file and automatically 110 struct timespec ts;
15 * adjust the settings for this buffer only. This must remain at the end 111
16 * of the file. 112 ts.tv_sec = secs;
17 * --------------------------------------------------------------------------- 113 ts.tv_nsec = 0;
18 * Local variables: 114 nanosleep(&ts, NULL);
19 * c-file-style: "linux" 115}
20 * End: 116
21 */ 117/* XXX This partly duplicates init_irq_signals */
118
119void user_time_init(void)
120{
121 set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
122 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
123 SIGALRM, SIGUSR2, -1);
124 set_handler(SIGALRM, (__sighandler_t) alarm_handler,
125 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
126 SIGVTALRM, SIGUSR2, -1);
127 set_interval(ITIMER_VIRTUAL);
128}
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
index 321e1c8e227d..a9f6b26f9828 100644
--- a/arch/um/os-Linux/trap.c
+++ b/arch/um/os-Linux/trap.c
@@ -10,6 +10,7 @@
10#include "user_util.h" 10#include "user_util.h"
11#include "os.h" 11#include "os.h"
12#include "mode.h" 12#include "mode.h"
13#include "longjmp.h"
13 14
14void usr2_handler(int sig, union uml_pt_regs *regs) 15void usr2_handler(int sig, union uml_pt_regs *regs)
15{ 16{
@@ -36,5 +37,5 @@ void do_longjmp(void *b, int val)
36{ 37{
37 sigjmp_buf *buf = b; 38 sigjmp_buf *buf = b;
38 39
39 siglongjmp(*buf, val); 40 UML_SIGLONGJMP(buf, val);
40} 41}
diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c
index cb2648b79d0f..919d19f11537 100644
--- a/arch/um/os-Linux/tt.c
+++ b/arch/um/os-Linux/tt.c
@@ -27,7 +27,6 @@
27#include "sysdep/sigcontext.h" 27#include "sysdep/sigcontext.h"
28#include "irq_user.h" 28#include "irq_user.h"
29#include "ptrace_user.h" 29#include "ptrace_user.h"
30#include "time_user.h"
31#include "init.h" 30#include "init.h"
32#include "os.h" 31#include "os.h"
33#include "uml-config.h" 32#include "uml-config.h"
@@ -63,6 +62,54 @@ void kill_child_dead(int pid)
63 } while(1); 62 } while(1);
64} 63}
65 64
65void stop(void)
66{
67 while(1) sleep(1000000);
68}
69
70int wait_for_stop(int pid, int sig, int cont_type, void *relay)
71{
72 sigset_t *relay_signals = relay;
73 int status, ret;
74
75 while(1){
76 CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED));
77 if((ret < 0) ||
78 !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){
79 if(ret < 0){
80 printk("wait failed, errno = %d\n",
81 errno);
82 }
83 else if(WIFEXITED(status))
84 printk("process %d exited with status %d\n",
85 pid, WEXITSTATUS(status));
86 else if(WIFSIGNALED(status))
87 printk("process %d exited with signal %d\n",
88 pid, WTERMSIG(status));
89 else if((WSTOPSIG(status) == SIGVTALRM) ||
90 (WSTOPSIG(status) == SIGALRM) ||
91 (WSTOPSIG(status) == SIGIO) ||
92 (WSTOPSIG(status) == SIGPROF) ||
93 (WSTOPSIG(status) == SIGCHLD) ||
94 (WSTOPSIG(status) == SIGWINCH) ||
95 (WSTOPSIG(status) == SIGINT)){
96 ptrace(cont_type, pid, 0, WSTOPSIG(status));
97 continue;
98 }
99 else if((relay_signals != NULL) &&
100 sigismember(relay_signals, WSTOPSIG(status))){
101 ptrace(cont_type, pid, 0, WSTOPSIG(status));
102 continue;
103 }
104 else printk("process %d stopped with signal %d\n",
105 pid, WSTOPSIG(status));
106 panic("wait_for_stop failed to wait for %d to stop "
107 "with %d\n", pid, sig);
108 }
109 return(status);
110 }
111}
112
66/* 113/*
67 *------------------------- 114 *-------------------------
68 * only for tt mode (will be deleted in future...) 115 * only for tt mode (will be deleted in future...)
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
index 38d710158c3d..166fb66995df 100644
--- a/arch/um/os-Linux/uaccess.c
+++ b/arch/um/os-Linux/uaccess.c
@@ -6,6 +6,7 @@
6 6
7#include <setjmp.h> 7#include <setjmp.h>
8#include <string.h> 8#include <string.h>
9#include "longjmp.h"
9 10
10unsigned long __do_user_copy(void *to, const void *from, int n, 11unsigned long __do_user_copy(void *to, const void *from, int n,
11 void **fault_addr, void **fault_catcher, 12 void **fault_addr, void **fault_catcher,
@@ -13,10 +14,11 @@ unsigned long __do_user_copy(void *to, const void *from, int n,
13 int n), int *faulted_out) 14 int n), int *faulted_out)
14{ 15{
15 unsigned long *faddrp = (unsigned long *) fault_addr, ret; 16 unsigned long *faddrp = (unsigned long *) fault_addr, ret;
17 int enable;
16 18
17 sigjmp_buf jbuf; 19 sigjmp_buf jbuf;
18 *fault_catcher = &jbuf; 20 *fault_catcher = &jbuf;
19 if(sigsetjmp(jbuf, 1) == 0){ 21 if(UML_SIGSETJMP(&jbuf, enable) == 0){
20 (*op)(to, from, n); 22 (*op)(to, from, n);
21 ret = 0; 23 ret = 0;
22 *faulted_out = 0; 24 *faulted_out = 0;
diff --git a/arch/um/kernel/user_util.c b/arch/um/os-Linux/util.c
index 4c231161f257..e32065e2fdc8 100644
--- a/arch/um/kernel/user_util.c
+++ b/arch/um/os-Linux/util.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -29,17 +29,14 @@
29#include "init.h" 29#include "init.h"
30#include "ptrace_user.h" 30#include "ptrace_user.h"
31#include "uml-config.h" 31#include "uml-config.h"
32 32#include "os.h"
33void stop(void) 33#include "longjmp.h"
34{
35 while(1) sleep(1000000);
36}
37 34
38void stack_protections(unsigned long address) 35void stack_protections(unsigned long address)
39{ 36{
40 int prot = PROT_READ | PROT_WRITE | PROT_EXEC; 37 int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
41 38
42 if(mprotect((void *) address, page_size(), prot) < 0) 39 if(mprotect((void *) address, page_size(), prot) < 0)
43 panic("protecting stack failed, errno = %d", errno); 40 panic("protecting stack failed, errno = %d", errno);
44} 41}
45 42
@@ -59,49 +56,6 @@ void task_protections(unsigned long address)
59 panic("protecting stack failed, errno = %d", errno); 56 panic("protecting stack failed, errno = %d", errno);
60} 57}
61 58
62int wait_for_stop(int pid, int sig, int cont_type, void *relay)
63{
64 sigset_t *relay_signals = relay;
65 int status, ret;
66
67 while(1){
68 CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED));
69 if((ret < 0) ||
70 !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){
71 if(ret < 0){
72 printk("wait failed, errno = %d\n",
73 errno);
74 }
75 else if(WIFEXITED(status))
76 printk("process %d exited with status %d\n",
77 pid, WEXITSTATUS(status));
78 else if(WIFSIGNALED(status))
79 printk("process %d exited with signal %d\n",
80 pid, WTERMSIG(status));
81 else if((WSTOPSIG(status) == SIGVTALRM) ||
82 (WSTOPSIG(status) == SIGALRM) ||
83 (WSTOPSIG(status) == SIGIO) ||
84 (WSTOPSIG(status) == SIGPROF) ||
85 (WSTOPSIG(status) == SIGCHLD) ||
86 (WSTOPSIG(status) == SIGWINCH) ||
87 (WSTOPSIG(status) == SIGINT)){
88 ptrace(cont_type, pid, 0, WSTOPSIG(status));
89 continue;
90 }
91 else if((relay_signals != NULL) &&
92 sigismember(relay_signals, WSTOPSIG(status))){
93 ptrace(cont_type, pid, 0, WSTOPSIG(status));
94 continue;
95 }
96 else printk("process %d stopped with signal %d\n",
97 pid, WSTOPSIG(status));
98 panic("wait_for_stop failed to wait for %d to stop "
99 "with %d\n", pid, sig);
100 }
101 return(status);
102 }
103}
104
105int raw(int fd) 59int raw(int fd)
106{ 60{
107 struct termios tt; 61 struct termios tt;
@@ -113,7 +67,7 @@ int raw(int fd)
113 67
114 cfmakeraw(&tt); 68 cfmakeraw(&tt);
115 69
116 CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt)); 70 CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt));
117 if(err < 0) 71 if(err < 0)
118 return -errno; 72 return -errno;
119 73
@@ -149,7 +103,7 @@ void setup_hostinfo(void)
149 103
150int setjmp_wrapper(void (*proc)(void *, void *), ...) 104int setjmp_wrapper(void (*proc)(void *, void *), ...)
151{ 105{
152 va_list args; 106 va_list args;
153 sigjmp_buf buf; 107 sigjmp_buf buf;
154 int n; 108 int n;
155 109
@@ -161,14 +115,3 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...)
161 va_end(args); 115 va_end(args);
162 return(n); 116 return(n);
163} 117}
164
165/*
166 * Overrides for Emacs so that we follow Linus's tabbing style.
167 * Emacs will notice this stuff at the end of the file and automatically
168 * adjust the settings for this buffer only. This must remain at the end
169 * of the file.
170 * ---------------------------------------------------------------------------
171 * Local variables:
172 * c-file-style: "linux"
173 * End:
174 */
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index 17746b4c08ff..0cdfd4481d5e 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -16,6 +16,8 @@
16#include "choose-mode.h" 16#include "choose-mode.h"
17#include "kern.h" 17#include "kern.h"
18#include "mode_kern.h" 18#include "mode_kern.h"
19#include "proc_mm.h"
20#include "os.h"
19 21
20extern int modify_ldt(int func, void *ptr, unsigned long bytecount); 22extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
21 23
@@ -456,13 +458,14 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
456 int i; 458 int i;
457 long page, err=0; 459 long page, err=0;
458 void *addr = NULL; 460 void *addr = NULL;
461 struct proc_mm_op copy;
459 462
460 memset(&desc, 0, sizeof(desc));
461 463
462 if(!ptrace_ldt) 464 if(!ptrace_ldt)
463 init_MUTEX(&new_mm->ldt.semaphore); 465 init_MUTEX(&new_mm->ldt.semaphore);
464 466
465 if(!from_mm){ 467 if(!from_mm){
468 memset(&desc, 0, sizeof(desc));
466 /* 469 /*
467 * We have to initialize a clean ldt. 470 * We have to initialize a clean ldt.
468 */ 471 */
@@ -494,8 +497,26 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
494 } 497 }
495 } 498 }
496 new_mm->ldt.entry_count = 0; 499 new_mm->ldt.entry_count = 0;
500
501 goto out;
497 } 502 }
498 else if (!ptrace_ldt) { 503
504 if(proc_mm){
505 /* We have a valid from_mm, so we now have to copy the LDT of
506 * from_mm to new_mm, because using proc_mm an new mm with
507 * an empty/default LDT was created in new_mm()
508 */
509 copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS,
510 .u =
511 { .copy_segments =
512 from_mm->id.u.mm_fd } } );
513 i = os_write_file(new_mm->id.u.mm_fd, &copy, sizeof(copy));
514 if(i != sizeof(copy))
515 printk("new_mm : /proc/mm copy_segments failed, "
516 "err = %d\n", -i);
517 }
518
519 if(!ptrace_ldt) {
499 /* Our local LDT is used to supply the data for 520 /* Our local LDT is used to supply the data for
500 * modify_ldt(READLDT), if PTRACE_LDT isn't available, 521 * modify_ldt(READLDT), if PTRACE_LDT isn't available,
501 * i.e., we have to use the stub for modify_ldt, which 522 * i.e., we have to use the stub for modify_ldt, which
@@ -524,6 +545,7 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
524 up(&from_mm->ldt.semaphore); 545 up(&from_mm->ldt.semaphore);
525 } 546 }
526 547
548 out:
527 return err; 549 return err;
528} 550}
529 551