aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/Kconfig_x86_644
-rw-r--r--arch/um/drivers/chan_kern.c22
-rw-r--r--arch/um/drivers/mcast_kern.c4
-rw-r--r--arch/um/drivers/mcast_user.c47
-rw-r--r--arch/um/drivers/ubd_kern.c296
-rw-r--r--arch/um/include/sysdep-i386/ptrace.h2
-rw-r--r--arch/um/include/sysdep-x86_64/checksum.h26
-rw-r--r--arch/um/include/sysdep-x86_64/ptrace.h62
-rw-r--r--arch/um/kernel/Makefile2
-rw-r--r--arch/um/kernel/checksum.c0
-rw-r--r--arch/um/kernel/initrd.c78
-rw-r--r--arch/um/kernel/irq_user.c10
-rw-r--r--arch/um/kernel/ksyms.c1
-rw-r--r--arch/um/kernel/mem.c40
-rw-r--r--arch/um/kernel/ptrace.c6
-rw-r--r--arch/um/kernel/trap_kern.c36
-rw-r--r--arch/um/kernel/tt/ksyms.c1
-rw-r--r--arch/um/kernel/uml.lds.S2
-rw-r--r--arch/um/sys-i386/Makefile4
-rw-r--r--arch/um/sys-i386/delay.c16
-rw-r--r--arch/um/sys-x86_64/Makefile6
-rw-r--r--arch/um/sys-x86_64/delay.c33
-rw-r--r--arch/um/sys-x86_64/ksyms.c3
-rw-r--r--arch/um/sys-x86_64/ptrace.c9
-rw-r--r--arch/um/sys-x86_64/syscalls.c1
-rw-r--r--arch/um/sys-x86_64/user-offsets.c8
26 files changed, 250 insertions, 469 deletions
diff --git a/arch/um/Kconfig_x86_64 b/arch/um/Kconfig_x86_64
index fd8d7e8982b1..f162f50f0b17 100644
--- a/arch/um/Kconfig_x86_64
+++ b/arch/um/Kconfig_x86_64
@@ -6,6 +6,10 @@ config 64BIT
6 bool 6 bool
7 default y 7 default y
8 8
9config TOP_ADDR
10 hex
11 default 0x80000000
12
9config 3_LEVEL_PGTABLES 13config 3_LEVEL_PGTABLES
10 bool 14 bool
11 default y 15 default y
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 0150038af795..14a12d6b3df6 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -20,9 +20,17 @@
20#include "os.h" 20#include "os.h"
21 21
22#ifdef CONFIG_NOCONFIG_CHAN 22#ifdef CONFIG_NOCONFIG_CHAN
23
24/* The printk's here are wrong because we are complaining that there is no
25 * output device, but printk is printing to that output device. The user will
26 * never see the error. printf would be better, except it can't run on a
27 * kernel stack because it will overflow it.
28 * Use printk for now since that will avoid crashing.
29 */
30
23static void *not_configged_init(char *str, int device, struct chan_opts *opts) 31static void *not_configged_init(char *str, int device, struct chan_opts *opts)
24{ 32{
25 printf(KERN_ERR "Using a channel type which is configured out of " 33 printk(KERN_ERR "Using a channel type which is configured out of "
26 "UML\n"); 34 "UML\n");
27 return(NULL); 35 return(NULL);
28} 36}
@@ -30,27 +38,27 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts)
30static int not_configged_open(int input, int output, int primary, void *data, 38static int not_configged_open(int input, int output, int primary, void *data,
31 char **dev_out) 39 char **dev_out)
32{ 40{
33 printf(KERN_ERR "Using a channel type which is configured out of " 41 printk(KERN_ERR "Using a channel type which is configured out of "
34 "UML\n"); 42 "UML\n");
35 return(-ENODEV); 43 return(-ENODEV);
36} 44}
37 45
38static void not_configged_close(int fd, void *data) 46static void not_configged_close(int fd, void *data)
39{ 47{
40 printf(KERN_ERR "Using a channel type which is configured out of " 48 printk(KERN_ERR "Using a channel type which is configured out of "
41 "UML\n"); 49 "UML\n");
42} 50}
43 51
44static int not_configged_read(int fd, char *c_out, void *data) 52static int not_configged_read(int fd, char *c_out, void *data)
45{ 53{
46 printf(KERN_ERR "Using a channel type which is configured out of " 54 printk(KERN_ERR "Using a channel type which is configured out of "
47 "UML\n"); 55 "UML\n");
48 return(-EIO); 56 return(-EIO);
49} 57}
50 58
51static int not_configged_write(int fd, const char *buf, int len, void *data) 59static int not_configged_write(int fd, const char *buf, int len, void *data)
52{ 60{
53 printf(KERN_ERR "Using a channel type which is configured out of " 61 printk(KERN_ERR "Using a channel type which is configured out of "
54 "UML\n"); 62 "UML\n");
55 return(-EIO); 63 return(-EIO);
56} 64}
@@ -58,7 +66,7 @@ static int not_configged_write(int fd, const char *buf, int len, void *data)
58static int not_configged_console_write(int fd, const char *buf, int len, 66static int not_configged_console_write(int fd, const char *buf, int len,
59 void *data) 67 void *data)
60{ 68{
61 printf(KERN_ERR "Using a channel type which is configured out of " 69 printk(KERN_ERR "Using a channel type which is configured out of "
62 "UML\n"); 70 "UML\n");
63 return(-EIO); 71 return(-EIO);
64} 72}
@@ -66,7 +74,7 @@ static int not_configged_console_write(int fd, const char *buf, int len,
66static int not_configged_window_size(int fd, void *data, unsigned short *rows, 74static int not_configged_window_size(int fd, void *data, unsigned short *rows,
67 unsigned short *cols) 75 unsigned short *cols)
68{ 76{
69 printf(KERN_ERR "Using a channel type which is configured out of " 77 printk(KERN_ERR "Using a channel type which is configured out of "
70 "UML\n"); 78 "UML\n");
71 return(-ENODEV); 79 return(-ENODEV);
72} 80}
diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c
index faf714e87b5b..217438cdef33 100644
--- a/arch/um/drivers/mcast_kern.c
+++ b/arch/um/drivers/mcast_kern.c
@@ -73,7 +73,6 @@ int mcast_setup(char *str, char **mac_out, void *data)
73 struct mcast_init *init = data; 73 struct mcast_init *init = data;
74 char *port_str = NULL, *ttl_str = NULL, *remain; 74 char *port_str = NULL, *ttl_str = NULL, *remain;
75 char *last; 75 char *last;
76 int n;
77 76
78 *init = ((struct mcast_init) 77 *init = ((struct mcast_init)
79 { .addr = "239.192.168.1", 78 { .addr = "239.192.168.1",
@@ -89,13 +88,12 @@ int mcast_setup(char *str, char **mac_out, void *data)
89 } 88 }
90 89
91 if(port_str != NULL){ 90 if(port_str != NULL){
92 n = simple_strtoul(port_str, &last, 10); 91 init->port = simple_strtoul(port_str, &last, 10);
93 if((*last != '\0') || (last == port_str)){ 92 if((*last != '\0') || (last == port_str)){
94 printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", 93 printk(KERN_ERR "mcast_setup - Bad port : '%s'\n",
95 port_str); 94 port_str);
96 return(0); 95 return(0);
97 } 96 }
98 init->port = htons(n);
99 } 97 }
100 98
101 if(ttl_str != NULL){ 99 if(ttl_str != NULL){
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
index 0fe1d9fa9139..7a0d115b29d0 100644
--- a/arch/um/drivers/mcast_user.c
+++ b/arch/um/drivers/mcast_user.c
@@ -38,7 +38,7 @@ static struct sockaddr_in *new_addr(char *addr, unsigned short port)
38 } 38 }
39 sin->sin_family = AF_INET; 39 sin->sin_family = AF_INET;
40 sin->sin_addr.s_addr = in_aton(addr); 40 sin->sin_addr.s_addr = in_aton(addr);
41 sin->sin_port = port; 41 sin->sin_port = htons(port);
42 return(sin); 42 return(sin);
43} 43}
44 44
@@ -55,28 +55,25 @@ static int mcast_open(void *data)
55 struct mcast_data *pri = data; 55 struct mcast_data *pri = data;
56 struct sockaddr_in *sin = pri->mcast_addr; 56 struct sockaddr_in *sin = pri->mcast_addr;
57 struct ip_mreq mreq; 57 struct ip_mreq mreq;
58 int fd, yes = 1; 58 int fd = -EINVAL, yes = 1, err = -EINVAL;;
59 59
60 60
61 if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) { 61 if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0))
62 fd = -EINVAL;
63 goto out; 62 goto out;
64 }
65 63
66 fd = socket(AF_INET, SOCK_DGRAM, 0); 64 fd = socket(AF_INET, SOCK_DGRAM, 0);
65
67 if (fd < 0){ 66 if (fd < 0){
68 printk("mcast_open : data socket failed, errno = %d\n", 67 printk("mcast_open : data socket failed, errno = %d\n",
69 errno); 68 errno);
70 fd = -ENOMEM; 69 fd = -errno;
71 goto out; 70 goto out;
72 } 71 }
73 72
74 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { 73 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
75 printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", 74 printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
76 errno); 75 errno);
77 os_close_file(fd); 76 goto out_close;
78 fd = -EINVAL;
79 goto out;
80 } 77 }
81 78
82 /* set ttl according to config */ 79 /* set ttl according to config */
@@ -84,26 +81,20 @@ static int mcast_open(void *data)
84 sizeof(pri->ttl)) < 0) { 81 sizeof(pri->ttl)) < 0) {
85 printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", 82 printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
86 errno); 83 errno);
87 os_close_file(fd); 84 goto out_close;
88 fd = -EINVAL;
89 goto out;
90 } 85 }
91 86
92 /* set LOOP, so data does get fed back to local sockets */ 87 /* set LOOP, so data does get fed back to local sockets */
93 if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { 88 if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
94 printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", 89 printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
95 errno); 90 errno);
96 os_close_file(fd); 91 goto out_close;
97 fd = -EINVAL;
98 goto out;
99 } 92 }
100 93
101 /* bind socket to mcast address */ 94 /* bind socket to mcast address */
102 if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { 95 if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
103 printk("mcast_open : data bind failed, errno = %d\n", errno); 96 printk("mcast_open : data bind failed, errno = %d\n", errno);
104 os_close_file(fd); 97 goto out_close;
105 fd = -EINVAL;
106 goto out;
107 } 98 }
108 99
109 /* subscribe to the multicast group */ 100 /* subscribe to the multicast group */
@@ -117,12 +108,15 @@ static int mcast_open(void *data)
117 "interface on the host.\n"); 108 "interface on the host.\n");
118 printk("eth0 should be configured in order to use the " 109 printk("eth0 should be configured in order to use the "
119 "multicast transport.\n"); 110 "multicast transport.\n");
120 os_close_file(fd); 111 goto out_close;
121 fd = -EINVAL;
122 } 112 }
123 113
124 out: 114 out:
125 return(fd); 115 return fd;
116
117 out_close:
118 os_close_file(fd);
119 return err;
126} 120}
127 121
128static void mcast_close(int fd, void *data) 122static void mcast_close(int fd, void *data)
@@ -164,14 +158,3 @@ struct net_user_info mcast_user_info = {
164 .delete_address = NULL, 158 .delete_address = NULL,
165 .max_packet = MAX_PACKET - ETH_HEADER_OTHER 159 .max_packet = MAX_PACKET - ETH_HEADER_OTHER
166}; 160};
167
168/*
169 * Overrides for Emacs so that we follow Linus's tabbing style.
170 * Emacs will notice this stuff at the end of the file and automatically
171 * adjust the settings for this buffer only. This must remain at the end
172 * of the file.
173 * ---------------------------------------------------------------------------
174 * Local variables:
175 * c-file-style: "linux"
176 * End:
177 */
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 9a56ff94308d..88f956c34fed 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -55,7 +55,7 @@
55#include "mem_kern.h" 55#include "mem_kern.h"
56#include "cow.h" 56#include "cow.h"
57 57
58enum ubd_req { UBD_READ, UBD_WRITE, UBD_MMAP }; 58enum ubd_req { UBD_READ, UBD_WRITE };
59 59
60struct io_thread_req { 60struct io_thread_req {
61 enum ubd_req op; 61 enum ubd_req op;
@@ -68,8 +68,6 @@ struct io_thread_req {
68 unsigned long sector_mask; 68 unsigned long sector_mask;
69 unsigned long long cow_offset; 69 unsigned long long cow_offset;
70 unsigned long bitmap_words[2]; 70 unsigned long bitmap_words[2];
71 int map_fd;
72 unsigned long long map_offset;
73 int error; 71 int error;
74}; 72};
75 73
@@ -122,10 +120,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
122 120
123#define MAX_DEV (8) 121#define MAX_DEV (8)
124 122
125/* Changed in early boot */
126static int ubd_do_mmap = 0;
127#define UBD_MMAP_BLOCK_SIZE PAGE_SIZE
128
129static struct block_device_operations ubd_blops = { 123static struct block_device_operations ubd_blops = {
130 .owner = THIS_MODULE, 124 .owner = THIS_MODULE,
131 .open = ubd_open, 125 .open = ubd_open,
@@ -175,12 +169,6 @@ struct ubd {
175 int no_cow; 169 int no_cow;
176 struct cow cow; 170 struct cow cow;
177 struct platform_device pdev; 171 struct platform_device pdev;
178
179 int map_writes;
180 int map_reads;
181 int nomap_writes;
182 int nomap_reads;
183 int write_maps;
184}; 172};
185 173
186#define DEFAULT_COW { \ 174#define DEFAULT_COW { \
@@ -200,11 +188,6 @@ struct ubd {
200 .openflags = OPEN_FLAGS, \ 188 .openflags = OPEN_FLAGS, \
201 .no_cow = 0, \ 189 .no_cow = 0, \
202 .cow = DEFAULT_COW, \ 190 .cow = DEFAULT_COW, \
203 .map_writes = 0, \
204 .map_reads = 0, \
205 .nomap_writes = 0, \
206 .nomap_reads = 0, \
207 .write_maps = 0, \
208} 191}
209 192
210struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; 193struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };
@@ -314,13 +297,6 @@ static int ubd_setup_common(char *str, int *index_out)
314 int major; 297 int major;
315 298
316 str++; 299 str++;
317 if(!strcmp(str, "mmap")){
318 CHOOSE_MODE(printk("mmap not supported by the ubd "
319 "driver in tt mode\n"),
320 ubd_do_mmap = 1);
321 return(0);
322 }
323
324 if(!strcmp(str, "sync")){ 300 if(!strcmp(str, "sync")){
325 global_openflags = of_sync(global_openflags); 301 global_openflags = of_sync(global_openflags);
326 return(0); 302 return(0);
@@ -524,7 +500,7 @@ static void ubd_handler(void)
524{ 500{
525 struct io_thread_req req; 501 struct io_thread_req req;
526 struct request *rq = elv_next_request(ubd_queue); 502 struct request *rq = elv_next_request(ubd_queue);
527 int n, err; 503 int n;
528 504
529 do_ubd = NULL; 505 do_ubd = NULL;
530 intr_count++; 506 intr_count++;
@@ -538,19 +514,6 @@ static void ubd_handler(void)
538 return; 514 return;
539 } 515 }
540 516
541 if((req.op != UBD_MMAP) &&
542 ((req.offset != ((__u64) (rq->sector)) << 9) ||
543 (req.length != (rq->current_nr_sectors) << 9)))
544 panic("I/O op mismatch");
545
546 if(req.map_fd != -1){
547 err = physmem_subst_mapping(req.buffer, req.map_fd,
548 req.map_offset, 1);
549 if(err)
550 printk("ubd_handler - physmem_subst_mapping failed, "
551 "err = %d\n", -err);
552 }
553
554 ubd_finish(rq, req.error); 517 ubd_finish(rq, req.error);
555 reactivate_fd(thread_fd, UBD_IRQ); 518 reactivate_fd(thread_fd, UBD_IRQ);
556 do_ubd_request(ubd_queue); 519 do_ubd_request(ubd_queue);
@@ -583,14 +546,10 @@ static int ubd_file_size(struct ubd *dev, __u64 *size_out)
583 546
584static void ubd_close(struct ubd *dev) 547static void ubd_close(struct ubd *dev)
585{ 548{
586 if(ubd_do_mmap)
587 physmem_forget_descriptor(dev->fd);
588 os_close_file(dev->fd); 549 os_close_file(dev->fd);
589 if(dev->cow.file == NULL) 550 if(dev->cow.file == NULL)
590 return; 551 return;
591 552
592 if(ubd_do_mmap)
593 physmem_forget_descriptor(dev->cow.fd);
594 os_close_file(dev->cow.fd); 553 os_close_file(dev->cow.fd);
595 vfree(dev->cow.bitmap); 554 vfree(dev->cow.bitmap);
596 dev->cow.bitmap = NULL; 555 dev->cow.bitmap = NULL;
@@ -1010,94 +969,13 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
1010 req->bitmap_words, bitmap_len); 969 req->bitmap_words, bitmap_len);
1011} 970}
1012 971
1013static int mmap_fd(struct request *req, struct ubd *dev, __u64 offset)
1014{
1015 __u64 sector;
1016 unsigned char *bitmap;
1017 int bit, i;
1018
1019 /* mmap must have been requested on the command line */
1020 if(!ubd_do_mmap)
1021 return(-1);
1022
1023 /* The buffer must be page aligned */
1024 if(((unsigned long) req->buffer % UBD_MMAP_BLOCK_SIZE) != 0)
1025 return(-1);
1026
1027 /* The request must be a page long */
1028 if((req->current_nr_sectors << 9) != PAGE_SIZE)
1029 return(-1);
1030
1031 if(dev->cow.file == NULL)
1032 return(dev->fd);
1033
1034 sector = offset >> 9;
1035 bitmap = (unsigned char *) dev->cow.bitmap;
1036 bit = ubd_test_bit(sector, bitmap);
1037
1038 for(i = 1; i < req->current_nr_sectors; i++){
1039 if(ubd_test_bit(sector + i, bitmap) != bit)
1040 return(-1);
1041 }
1042
1043 if(bit || (rq_data_dir(req) == WRITE))
1044 offset += dev->cow.data_offset;
1045
1046 /* The data on disk must be page aligned */
1047 if((offset % UBD_MMAP_BLOCK_SIZE) != 0)
1048 return(-1);
1049
1050 return(bit ? dev->fd : dev->cow.fd);
1051}
1052
1053static int prepare_mmap_request(struct ubd *dev, int fd, __u64 offset,
1054 struct request *req,
1055 struct io_thread_req *io_req)
1056{
1057 int err;
1058
1059 if(rq_data_dir(req) == WRITE){
1060 /* Writes are almost no-ops since the new data is already in the
1061 * host page cache
1062 */
1063 dev->map_writes++;
1064 if(dev->cow.file != NULL)
1065 cowify_bitmap(io_req->offset, io_req->length,
1066 &io_req->sector_mask, &io_req->cow_offset,
1067 dev->cow.bitmap, dev->cow.bitmap_offset,
1068 io_req->bitmap_words,
1069 dev->cow.bitmap_len);
1070 }
1071 else {
1072 int w;
1073
1074 if((dev->cow.file != NULL) && (fd == dev->cow.fd))
1075 w = 0;
1076 else w = dev->openflags.w;
1077
1078 if((dev->cow.file != NULL) && (fd == dev->fd))
1079 offset += dev->cow.data_offset;
1080
1081 err = physmem_subst_mapping(req->buffer, fd, offset, w);
1082 if(err){
1083 printk("physmem_subst_mapping failed, err = %d\n",
1084 -err);
1085 return(1);
1086 }
1087 dev->map_reads++;
1088 }
1089 io_req->op = UBD_MMAP;
1090 io_req->buffer = req->buffer;
1091 return(0);
1092}
1093
1094/* Called with ubd_io_lock held */ 972/* Called with ubd_io_lock held */
1095static int prepare_request(struct request *req, struct io_thread_req *io_req) 973static int prepare_request(struct request *req, struct io_thread_req *io_req)
1096{ 974{
1097 struct gendisk *disk = req->rq_disk; 975 struct gendisk *disk = req->rq_disk;
1098 struct ubd *dev = disk->private_data; 976 struct ubd *dev = disk->private_data;
1099 __u64 offset; 977 __u64 offset;
1100 int len, fd; 978 int len;
1101 979
1102 if(req->rq_status == RQ_INACTIVE) return(1); 980 if(req->rq_status == RQ_INACTIVE) return(1);
1103 981
@@ -1114,34 +992,12 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
1114 992
1115 io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd; 993 io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
1116 io_req->fds[1] = dev->fd; 994 io_req->fds[1] = dev->fd;
1117 io_req->map_fd = -1;
1118 io_req->cow_offset = -1; 995 io_req->cow_offset = -1;
1119 io_req->offset = offset; 996 io_req->offset = offset;
1120 io_req->length = len; 997 io_req->length = len;
1121 io_req->error = 0; 998 io_req->error = 0;
1122 io_req->sector_mask = 0; 999 io_req->sector_mask = 0;
1123 1000
1124 fd = mmap_fd(req, dev, io_req->offset);
1125 if(fd > 0){
1126 /* If mmapping is otherwise OK, but the first access to the
1127 * page is a write, then it's not mapped in yet. So we have
1128 * to write the data to disk first, then we can map the disk
1129 * page in and continue normally from there.
1130 */
1131 if((rq_data_dir(req) == WRITE) && !is_remapped(req->buffer)){
1132 io_req->map_fd = dev->fd;
1133 io_req->map_offset = io_req->offset +
1134 dev->cow.data_offset;
1135 dev->write_maps++;
1136 }
1137 else return(prepare_mmap_request(dev, fd, io_req->offset, req,
1138 io_req));
1139 }
1140
1141 if(rq_data_dir(req) == READ)
1142 dev->nomap_reads++;
1143 else dev->nomap_writes++;
1144
1145 io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE; 1001 io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
1146 io_req->offsets[0] = 0; 1002 io_req->offsets[0] = 0;
1147 io_req->offsets[1] = dev->cow.data_offset; 1003 io_req->offsets[1] = dev->cow.data_offset;
@@ -1229,143 +1085,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
1229 return(-EINVAL); 1085 return(-EINVAL);
1230} 1086}
1231 1087
1232static int ubd_check_remapped(int fd, unsigned long address, int is_write,
1233 __u64 offset)
1234{
1235 __u64 bitmap_offset;
1236 unsigned long new_bitmap[2];
1237 int i, err, n;
1238
1239 /* If it's not a write access, we can't do anything about it */
1240 if(!is_write)
1241 return(0);
1242
1243 /* We have a write */
1244 for(i = 0; i < sizeof(ubd_dev) / sizeof(ubd_dev[0]); i++){
1245 struct ubd *dev = &ubd_dev[i];
1246
1247 if((dev->fd != fd) && (dev->cow.fd != fd))
1248 continue;
1249
1250 /* It's a write to a ubd device */
1251
1252 /* This should be impossible now */
1253 if(!dev->openflags.w){
1254 /* It's a write access on a read-only device - probably
1255 * shouldn't happen. If the kernel is trying to change
1256 * something with no intention of writing it back out,
1257 * then this message will clue us in that this needs
1258 * fixing
1259 */
1260 printk("Write access to mapped page from readonly ubd "
1261 "device %d\n", i);
1262 return(0);
1263 }
1264
1265 /* It's a write to a writeable ubd device - it must be COWed
1266 * because, otherwise, the page would have been mapped in
1267 * writeable
1268 */
1269
1270 if(!dev->cow.file)
1271 panic("Write fault on writeable non-COW ubd device %d",
1272 i);
1273
1274 /* It should also be an access to the backing file since the
1275 * COW pages should be mapped in read-write
1276 */
1277
1278 if(fd == dev->fd)
1279 panic("Write fault on a backing page of ubd "
1280 "device %d\n", i);
1281
1282 /* So, we do the write, copying the backing data to the COW
1283 * file...
1284 */
1285
1286 err = os_seek_file(dev->fd, offset + dev->cow.data_offset);
1287 if(err < 0)
1288 panic("Couldn't seek to %lld in COW file of ubd "
1289 "device %d, err = %d",
1290 offset + dev->cow.data_offset, i, -err);
1291
1292 n = os_write_file(dev->fd, (void *) address, PAGE_SIZE);
1293 if(n != PAGE_SIZE)
1294 panic("Couldn't copy data to COW file of ubd "
1295 "device %d, err = %d", i, -n);
1296
1297 /* ... updating the COW bitmap... */
1298
1299 cowify_bitmap(offset, PAGE_SIZE, NULL, &bitmap_offset,
1300 dev->cow.bitmap, dev->cow.bitmap_offset,
1301 new_bitmap, dev->cow.bitmap_len);
1302
1303 err = os_seek_file(dev->fd, bitmap_offset);
1304 if(err < 0)
1305 panic("Couldn't seek to %lld in COW file of ubd "
1306 "device %d, err = %d", bitmap_offset, i, -err);
1307
1308 n = os_write_file(dev->fd, new_bitmap, sizeof(new_bitmap));
1309 if(n != sizeof(new_bitmap))
1310 panic("Couldn't update bitmap of ubd device %d, "
1311 "err = %d", i, -n);
1312
1313 /* Maybe we can map the COW page in, and maybe we can't. If
1314 * it is a pre-V3 COW file, we can't, since the alignment will
1315 * be wrong. If it is a V3 or later COW file which has been
1316 * moved to a system with a larger page size, then maybe we
1317 * can't, depending on the exact location of the page.
1318 */
1319
1320 offset += dev->cow.data_offset;
1321
1322 /* Remove the remapping, putting the original anonymous page
1323 * back. If the COW file can be mapped in, that is done.
1324 * Otherwise, the COW page is read in.
1325 */
1326
1327 if(!physmem_remove_mapping((void *) address))
1328 panic("Address 0x%lx not remapped by ubd device %d",
1329 address, i);
1330 if((offset % UBD_MMAP_BLOCK_SIZE) == 0)
1331 physmem_subst_mapping((void *) address, dev->fd,
1332 offset, 1);
1333 else {
1334 err = os_seek_file(dev->fd, offset);
1335 if(err < 0)
1336 panic("Couldn't seek to %lld in COW file of "
1337 "ubd device %d, err = %d", offset, i,
1338 -err);
1339
1340 n = os_read_file(dev->fd, (void *) address, PAGE_SIZE);
1341 if(n != PAGE_SIZE)
1342 panic("Failed to read page from offset %llx of "
1343 "COW file of ubd device %d, err = %d",
1344 offset, i, -n);
1345 }
1346
1347 return(1);
1348 }
1349
1350 /* It's not a write on a ubd device */
1351 return(0);
1352}
1353
1354static struct remapper ubd_remapper = {
1355 .list = LIST_HEAD_INIT(ubd_remapper.list),
1356 .proc = ubd_check_remapped,
1357};
1358
1359static int ubd_remapper_setup(void)
1360{
1361 if(ubd_do_mmap)
1362 register_remapper(&ubd_remapper);
1363
1364 return(0);
1365}
1366
1367__initcall(ubd_remapper_setup);
1368
1369static int same_backing_files(char *from_cmdline, char *from_cow, char *cow) 1088static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
1370{ 1089{
1371 struct uml_stat buf1, buf2; 1090 struct uml_stat buf1, buf2;
@@ -1568,15 +1287,6 @@ void do_io(struct io_thread_req *req)
1568 int err; 1287 int err;
1569 __u64 off; 1288 __u64 off;
1570 1289
1571 if(req->op == UBD_MMAP){
1572 /* Touch the page to force the host to do any necessary IO to
1573 * get it into memory
1574 */
1575 n = *((volatile int *) req->buffer);
1576 req->error = update_bitmap(req);
1577 return;
1578 }
1579
1580 nsectors = req->length / req->sectorsize; 1290 nsectors = req->length / req->sectorsize;
1581 start = 0; 1291 start = 0;
1582 do { 1292 do {
diff --git a/arch/um/include/sysdep-i386/ptrace.h b/arch/um/include/sysdep-i386/ptrace.h
index 84ec7ff5cf8c..6eaeb9919983 100644
--- a/arch/um/include/sysdep-i386/ptrace.h
+++ b/arch/um/include/sysdep-i386/ptrace.h
@@ -31,7 +31,6 @@ extern int sysemu_supported;
31#ifdef UML_CONFIG_MODE_SKAS 31#ifdef UML_CONFIG_MODE_SKAS
32 32
33#include "skas_ptregs.h" 33#include "skas_ptregs.h"
34#include "sysdep/faultinfo.h"
35 34
36#define REGS_IP(r) ((r)[HOST_IP]) 35#define REGS_IP(r) ((r)[HOST_IP])
37#define REGS_SP(r) ((r)[HOST_SP]) 36#define REGS_SP(r) ((r)[HOST_SP])
@@ -59,6 +58,7 @@ extern int sysemu_supported;
59#define PTRACE_SYSEMU_SINGLESTEP 32 58#define PTRACE_SYSEMU_SINGLESTEP 32
60#endif 59#endif
61 60
61#include "sysdep/faultinfo.h"
62#include "choose-mode.h" 62#include "choose-mode.h"
63 63
64union uml_pt_regs { 64union uml_pt_regs {
diff --git a/arch/um/include/sysdep-x86_64/checksum.h b/arch/um/include/sysdep-x86_64/checksum.h
index 572c6c19be33..ea97005af694 100644
--- a/arch/um/include/sysdep-x86_64/checksum.h
+++ b/arch/um/include/sysdep-x86_64/checksum.h
@@ -9,8 +9,6 @@
9#include "linux/in6.h" 9#include "linux/in6.h"
10#include "asm/uaccess.h" 10#include "asm/uaccess.h"
11 11
12extern unsigned int csum_partial_copy_from(const unsigned char *src, unsigned char *dst, int len,
13 int sum, int *err_ptr);
14extern unsigned csum_partial(const unsigned char *buff, unsigned len, 12extern unsigned csum_partial(const unsigned char *buff, unsigned len,
15 unsigned sum); 13 unsigned sum);
16 14
@@ -31,10 +29,15 @@ unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *
31} 29}
32 30
33static __inline__ 31static __inline__
34unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst, 32unsigned int csum_partial_copy_from_user(const unsigned char *src,
35 int len, int sum, int *err_ptr) 33 unsigned char *dst, int len, int sum,
34 int *err_ptr)
36{ 35{
37 return csum_partial_copy_from(src, dst, len, sum, err_ptr); 36 if(copy_from_user(dst, src, len)){
37 *err_ptr = -EFAULT;
38 return(-1);
39 }
40 return csum_partial(dst, len, sum);
38} 41}
39 42
40/** 43/**
@@ -137,15 +140,6 @@ static inline unsigned add32_with_carry(unsigned a, unsigned b)
137 return a; 140 return a;
138} 141}
139 142
140#endif 143extern unsigned short ip_compute_csum(unsigned char * buff, int len);
141 144
142/* 145#endif
143 * Overrides for Emacs so that we follow Linus's tabbing style.
144 * Emacs will notice this stuff at the end of the file and automatically
145 * adjust the settings for this buffer only. This must remain at the end
146 * of the file.
147 * ---------------------------------------------------------------------------
148 * Local variables:
149 * c-file-style: "linux"
150 * End:
151 */
diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h
index 348e8fcd513f..be8acd5efd97 100644
--- a/arch/um/include/sysdep-x86_64/ptrace.h
+++ b/arch/um/include/sysdep-x86_64/ptrace.h
@@ -135,6 +135,7 @@ extern int mode_tt;
135 __CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs)) 135 __CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs))
136#define UPT_SC(r) ((r)->tt.sc) 136#define UPT_SC(r) ((r)->tt.sc)
137#define UPT_SYSCALL_NR(r) __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall) 137#define UPT_SYSCALL_NR(r) __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall)
138#define UPT_SYSCALL_RET(r) UPT_RAX(r)
138 139
139extern int user_context(unsigned long sp); 140extern int user_context(unsigned long sp);
140 141
@@ -196,32 +197,32 @@ struct syscall_args {
196 197
197 198
198#define UPT_SET(regs, reg, val) \ 199#define UPT_SET(regs, reg, val) \
199 ({ unsigned long val; \ 200 ({ unsigned long __upt_val = val; \
200 switch(reg){ \ 201 switch(reg){ \
201 case R8: UPT_R8(regs) = val; break; \ 202 case R8: UPT_R8(regs) = __upt_val; break; \
202 case R9: UPT_R9(regs) = val; break; \ 203 case R9: UPT_R9(regs) = __upt_val; break; \
203 case R10: UPT_R10(regs) = val; break; \ 204 case R10: UPT_R10(regs) = __upt_val; break; \
204 case R11: UPT_R11(regs) = val; break; \ 205 case R11: UPT_R11(regs) = __upt_val; break; \
205 case R12: UPT_R12(regs) = val; break; \ 206 case R12: UPT_R12(regs) = __upt_val; break; \
206 case R13: UPT_R13(regs) = val; break; \ 207 case R13: UPT_R13(regs) = __upt_val; break; \
207 case R14: UPT_R14(regs) = val; break; \ 208 case R14: UPT_R14(regs) = __upt_val; break; \
208 case R15: UPT_R15(regs) = val; break; \ 209 case R15: UPT_R15(regs) = __upt_val; break; \
209 case RIP: UPT_IP(regs) = val; break; \ 210 case RIP: UPT_IP(regs) = __upt_val; break; \
210 case RSP: UPT_SP(regs) = val; break; \ 211 case RSP: UPT_SP(regs) = __upt_val; break; \
211 case RAX: UPT_RAX(regs) = val; break; \ 212 case RAX: UPT_RAX(regs) = __upt_val; break; \
212 case RBX: UPT_RBX(regs) = val; break; \ 213 case RBX: UPT_RBX(regs) = __upt_val; break; \
213 case RCX: UPT_RCX(regs) = val; break; \ 214 case RCX: UPT_RCX(regs) = __upt_val; break; \
214 case RDX: UPT_RDX(regs) = val; break; \ 215 case RDX: UPT_RDX(regs) = __upt_val; break; \
215 case RSI: UPT_RSI(regs) = val; break; \ 216 case RSI: UPT_RSI(regs) = __upt_val; break; \
216 case RDI: UPT_RDI(regs) = val; break; \ 217 case RDI: UPT_RDI(regs) = __upt_val; break; \
217 case RBP: UPT_RBP(regs) = val; break; \ 218 case RBP: UPT_RBP(regs) = __upt_val; break; \
218 case ORIG_RAX: UPT_ORIG_RAX(regs) = val; break; \ 219 case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \
219 case CS: UPT_CS(regs) = val; break; \ 220 case CS: UPT_CS(regs) = __upt_val; break; \
220 case DS: UPT_DS(regs) = val; break; \ 221 case DS: UPT_DS(regs) = __upt_val; break; \
221 case ES: UPT_ES(regs) = val; break; \ 222 case ES: UPT_ES(regs) = __upt_val; break; \
222 case FS: UPT_FS(regs) = val; break; \ 223 case FS: UPT_FS(regs) = __upt_val; break; \
223 case GS: UPT_GS(regs) = val; break; \ 224 case GS: UPT_GS(regs) = __upt_val; break; \
224 case EFLAGS: UPT_EFLAGS(regs) = val; break; \ 225 case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \
225 default : \ 226 default : \
226 panic("Bad register in UPT_SET : %d\n", reg); \ 227 panic("Bad register in UPT_SET : %d\n", reg); \
227 break; \ 228 break; \
@@ -245,14 +246,3 @@ struct syscall_args {
245 CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo)) 246 CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo))
246 247
247#endif 248#endif
248
249/*
250 * Overrides for Emacs so that we follow Linus's tabbing style.
251 * Emacs will notice this stuff at the end of the file and automatically
252 * adjust the settings for this buffer only. This must remain at the end
253 * of the file.
254 * ---------------------------------------------------------------------------
255 * Local variables:
256 * c-file-style: "linux"
257 * End:
258 */
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 9736ca27c5f0..a8918e80df96 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -14,7 +14,7 @@ obj-y = config.o exec_kern.o exitcode.o \
14 tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o umid.o \ 14 tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o umid.o \
15 user_util.o 15 user_util.o
16 16
17obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o 17obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
18obj-$(CONFIG_GPROF) += gprof_syms.o 18obj-$(CONFIG_GPROF) += gprof_syms.o
19obj-$(CONFIG_GCOV) += gmon_syms.o 19obj-$(CONFIG_GCOV) += gmon_syms.o
20obj-$(CONFIG_TTY_LOG) += tty_log.o 20obj-$(CONFIG_TTY_LOG) += tty_log.o
diff --git a/arch/um/kernel/checksum.c b/arch/um/kernel/checksum.c
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/arch/um/kernel/checksum.c
+++ /dev/null
diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c
new file mode 100644
index 000000000000..82ecf904b09c
--- /dev/null
+++ b/arch/um/kernel/initrd.c
@@ -0,0 +1,78 @@
1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include "linux/init.h"
7#include "linux/bootmem.h"
8#include "linux/initrd.h"
9#include "asm/types.h"
10#include "user_util.h"
11#include "kern_util.h"
12#include "initrd.h"
13#include "init.h"
14#include "os.h"
15
16/* Changed by uml_initrd_setup, which is a setup */
17static char *initrd __initdata = NULL;
18
19static int __init read_initrd(void)
20{
21 void *area;
22 long long size;
23 int err;
24
25 if(initrd == NULL) return 0;
26 err = os_file_size(initrd, &size);
27 if(err) return 0;
28 area = alloc_bootmem(size);
29 if(area == NULL) return 0;
30 if(load_initrd(initrd, area, size) == -1) return 0;
31 initrd_start = (unsigned long) area;
32 initrd_end = initrd_start + size;
33 return 0;
34}
35
36__uml_postsetup(read_initrd);
37
38static int __init uml_initrd_setup(char *line, int *add)
39{
40 initrd = line;
41 return 0;
42}
43
44__uml_setup("initrd=", uml_initrd_setup,
45"initrd=<initrd image>\n"
46" This is used to boot UML from an initrd image. The argument is the\n"
47" name of the file containing the image.\n\n"
48);
49
50int load_initrd(char *filename, void *buf, int size)
51{
52 int fd, n;
53
54 fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
55 if(fd < 0){
56 printk("Opening '%s' failed - err = %d\n", filename, -fd);
57 return(-1);
58 }
59 n = os_read_file(fd, buf, size);
60 if(n != size){
61 printk("Read of %d bytes from '%s' failed, err = %d\n", size,
62 filename, -n);
63 return(-1);
64 }
65
66 os_close_file(fd);
67 return(0);
68}
69/*
70 * Overrides for Emacs so that we follow Linus's tabbing style.
71 * Emacs will notice this stuff at the end of the file and automatically
72 * adjust the settings for this buffer only. This must remain at the end
73 * of the file.
74 * ---------------------------------------------------------------------------
75 * Local variables:
76 * c-file-style: "linux"
77 * End:
78 */
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
index 6d6f9484b884..b3074cbaa479 100644
--- a/arch/um/kernel/irq_user.c
+++ b/arch/um/kernel/irq_user.c
@@ -236,9 +236,15 @@ static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
236 (*prev)->fd, pollfds[i].fd); 236 (*prev)->fd, pollfds[i].fd);
237 goto out; 237 goto out;
238 } 238 }
239 memcpy(&pollfds[i], &pollfds[i + 1], 239
240 (pollfds_num - i - 1) * sizeof(pollfds[0]));
241 pollfds_num--; 240 pollfds_num--;
241
242 /* This moves the *whole* array after pollfds[i] (though
243 * it doesn't spot as such)! */
244
245 memmove(&pollfds[i], &pollfds[i + 1],
246 (pollfds_num - i) * sizeof(pollfds[0]));
247
242 if(last_irq_ptr == &old_fd->next) 248 if(last_irq_ptr == &old_fd->next)
243 last_irq_ptr = prev; 249 last_irq_ptr = prev;
244 *prev = (*prev)->next; 250 *prev = (*prev)->next;
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 78d69dc74b26..99439fa15ef4 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -57,6 +57,7 @@ EXPORT_SYMBOL(copy_to_user_tt);
57EXPORT_SYMBOL(strncpy_from_user_skas); 57EXPORT_SYMBOL(strncpy_from_user_skas);
58EXPORT_SYMBOL(copy_to_user_skas); 58EXPORT_SYMBOL(copy_to_user_skas);
59EXPORT_SYMBOL(copy_from_user_skas); 59EXPORT_SYMBOL(copy_from_user_skas);
60EXPORT_SYMBOL(clear_user_skas);
60#endif 61#endif
61EXPORT_SYMBOL(uml_strdup); 62EXPORT_SYMBOL(uml_strdup);
62 63
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index f156661781cb..c22825f13e40 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -100,12 +100,37 @@ void mem_init(void)
100#endif 100#endif
101} 101}
102 102
103/*
104 * Create a page table and place a pointer to it in a middle page
105 * directory entry.
106 */
107static void __init one_page_table_init(pmd_t *pmd)
108{
109 if (pmd_none(*pmd)) {
110 pte_t *pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
111 set_pmd(pmd, __pmd(_KERNPG_TABLE +
112 (unsigned long) __pa(pte)));
113 if (pte != pte_offset_kernel(pmd, 0))
114 BUG();
115 }
116}
117
118static void __init one_md_table_init(pud_t *pud)
119{
120#ifdef CONFIG_3_LEVEL_PGTABLES
121 pmd_t *pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
122 set_pud(pud, __pud(_KERNPG_TABLE + (unsigned long) __pa(pmd_table)));
123 if (pmd_table != pmd_offset(pud, 0))
124 BUG();
125#endif
126}
127
103static void __init fixrange_init(unsigned long start, unsigned long end, 128static void __init fixrange_init(unsigned long start, unsigned long end,
104 pgd_t *pgd_base) 129 pgd_t *pgd_base)
105{ 130{
106 pgd_t *pgd; 131 pgd_t *pgd;
132 pud_t *pud;
107 pmd_t *pmd; 133 pmd_t *pmd;
108 pte_t *pte;
109 int i, j; 134 int i, j;
110 unsigned long vaddr; 135 unsigned long vaddr;
111 136
@@ -115,15 +140,12 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
115 pgd = pgd_base + i; 140 pgd = pgd_base + i;
116 141
117 for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) { 142 for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) {
118 pmd = (pmd_t *)pgd; 143 pud = pud_offset(pgd, vaddr);
144 if (pud_none(*pud))
145 one_md_table_init(pud);
146 pmd = pmd_offset(pud, vaddr);
119 for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) { 147 for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
120 if (pmd_none(*pmd)) { 148 one_page_table_init(pmd);
121 pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
122 set_pmd(pmd, __pmd(_KERNPG_TABLE +
123 (unsigned long) __pa(pte)));
124 if (pte != pte_offset_kernel(pmd, 0))
125 BUG();
126 }
127 vaddr += PMD_SIZE; 149 vaddr += PMD_SIZE;
128 } 150 }
129 j = 0; 151 j = 0;
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 2b75d8d9ba73..2925e15324de 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -28,9 +28,9 @@ static inline void set_singlestepping(struct task_struct *child, int on)
28 child->thread.singlestep_syscall = 0; 28 child->thread.singlestep_syscall = 0;
29 29
30#ifdef SUBARCH_SET_SINGLESTEPPING 30#ifdef SUBARCH_SET_SINGLESTEPPING
31 SUBARCH_SET_SINGLESTEPPING(child, on) 31 SUBARCH_SET_SINGLESTEPPING(child, on);
32#endif 32#endif
33 } 33}
34 34
35/* 35/*
36 * Called by kernel/ptrace.c when detaching.. 36 * Called by kernel/ptrace.c when detaching..
@@ -83,7 +83,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
83 } 83 }
84 84
85#ifdef SUBACH_PTRACE_SPECIAL 85#ifdef SUBACH_PTRACE_SPECIAL
86 SUBARCH_PTRACE_SPECIAL(child,request,addr,data) 86 SUBARCH_PTRACE_SPECIAL(child,request,addr,data);
87#endif 87#endif
88 88
89 ret = ptrace_check_attach(child, request == PTRACE_KILL); 89 ret = ptrace_check_attach(child, request == PTRACE_KILL);
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
index 5fca2c61eb98..1de22d8a313a 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -57,10 +57,11 @@ int handle_page_fault(unsigned long address, unsigned long ip,
57 *code_out = SEGV_ACCERR; 57 *code_out = SEGV_ACCERR;
58 if(is_write && !(vma->vm_flags & VM_WRITE)) 58 if(is_write && !(vma->vm_flags & VM_WRITE))
59 goto out; 59 goto out;
60
61 if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
62 goto out;
63
60 page = address & PAGE_MASK; 64 page = address & PAGE_MASK;
61 pgd = pgd_offset(mm, page);
62 pud = pud_offset(pgd, page);
63 pmd = pmd_offset(pud, page);
64 do { 65 do {
65 survive: 66 survive:
66 switch (handle_mm_fault(mm, vma, address, is_write)){ 67 switch (handle_mm_fault(mm, vma, address, is_write)){
@@ -106,33 +107,6 @@ out_of_memory:
106 goto out; 107 goto out;
107} 108}
108 109
109LIST_HEAD(physmem_remappers);
110
111void register_remapper(struct remapper *info)
112{
113 list_add(&info->list, &physmem_remappers);
114}
115
116static int check_remapped_addr(unsigned long address, int is_write)
117{
118 struct remapper *remapper;
119 struct list_head *ele;
120 __u64 offset;
121 int fd;
122
123 fd = phys_mapping(__pa(address), &offset);
124 if(fd == -1)
125 return(0);
126
127 list_for_each(ele, &physmem_remappers){
128 remapper = list_entry(ele, struct remapper, list);
129 if((*remapper->proc)(fd, address, is_write, offset))
130 return(1);
131 }
132
133 return(0);
134}
135
136/* 110/*
137 * We give a *copy* of the faultinfo in the regs to segv. 111 * We give a *copy* of the faultinfo in the regs to segv.
138 * This must be done, since nesting SEGVs could overwrite 112 * This must be done, since nesting SEGVs could overwrite
@@ -151,8 +125,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
151 flush_tlb_kernel_vm(); 125 flush_tlb_kernel_vm();
152 return(0); 126 return(0);
153 } 127 }
154 else if(check_remapped_addr(address & PAGE_MASK, is_write))
155 return(0);
156 else if(current->mm == NULL) 128 else if(current->mm == NULL)
157 panic("Segfault with no mm"); 129 panic("Segfault with no mm");
158 err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); 130 err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
diff --git a/arch/um/kernel/tt/ksyms.c b/arch/um/kernel/tt/ksyms.c
index 92ec85d67c7c..84a9385a8fef 100644
--- a/arch/um/kernel/tt/ksyms.c
+++ b/arch/um/kernel/tt/ksyms.c
@@ -12,6 +12,7 @@ EXPORT_SYMBOL(__do_copy_to_user);
12EXPORT_SYMBOL(__do_strncpy_from_user); 12EXPORT_SYMBOL(__do_strncpy_from_user);
13EXPORT_SYMBOL(__do_strnlen_user); 13EXPORT_SYMBOL(__do_strnlen_user);
14EXPORT_SYMBOL(__do_clear_user); 14EXPORT_SYMBOL(__do_clear_user);
15EXPORT_SYMBOL(clear_user_tt);
15 16
16EXPORT_SYMBOL(tracing_pid); 17EXPORT_SYMBOL(tracing_pid);
17EXPORT_SYMBOL(honeypot); 18EXPORT_SYMBOL(honeypot);
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index 76eadb309189..dd5355500bdc 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -73,6 +73,8 @@ SECTIONS
73 73
74 .got : { *(.got.plt) *(.got) } 74 .got : { *(.got.plt) *(.got) }
75 .dynamic : { *(.dynamic) } 75 .dynamic : { *(.dynamic) }
76 .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
77 .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
76 /* We want the small data sections together, so single-instruction offsets 78 /* We want the small data sections together, so single-instruction offsets
77 can access them all, and initialized data all before uninitialized, so 79 can access them all, and initialized data all before uninitialized, so
78 we can shorten the on-disk segment size. */ 80 we can shorten the on-disk segment size. */
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index fcd67c3414e4..4351e5605506 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -9,11 +9,11 @@ USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
9 9
10SYMLINKS = bitops.c semaphore.c highmem.c module.c 10SYMLINKS = bitops.c semaphore.c highmem.c module.c
11 11
12include arch/um/scripts/Makefile.rules
13
12bitops.c-dir = lib 14bitops.c-dir = lib
13semaphore.c-dir = kernel 15semaphore.c-dir = kernel
14highmem.c-dir = mm 16highmem.c-dir = mm
15module.c-dir = kernel 17module.c-dir = kernel
16 18
17subdir- := util 19subdir- := util
18
19include arch/um/scripts/Makefile.rules
diff --git a/arch/um/sys-i386/delay.c b/arch/um/sys-i386/delay.c
index e9892eef51ce..2c11b9770e8b 100644
--- a/arch/um/sys-i386/delay.c
+++ b/arch/um/sys-i386/delay.c
@@ -1,5 +1,7 @@
1#include "linux/delay.h" 1#include <linux/module.h>
2#include "asm/param.h" 2#include <linux/kernel.h>
3#include <linux/delay.h>
4#include <asm/param.h>
3 5
4void __delay(unsigned long time) 6void __delay(unsigned long time)
5{ 7{
@@ -20,13 +22,19 @@ void __udelay(unsigned long usecs)
20 int i, n; 22 int i, n;
21 23
22 n = (loops_per_jiffy * HZ * usecs) / MILLION; 24 n = (loops_per_jiffy * HZ * usecs) / MILLION;
23 for(i=0;i<n;i++) ; 25 for(i=0;i<n;i++)
26 cpu_relax();
24} 27}
25 28
29EXPORT_SYMBOL(__udelay);
30
26void __const_udelay(unsigned long usecs) 31void __const_udelay(unsigned long usecs)
27{ 32{
28 int i, n; 33 int i, n;
29 34
30 n = (loops_per_jiffy * HZ * usecs) / MILLION; 35 n = (loops_per_jiffy * HZ * usecs) / MILLION;
31 for(i=0;i<n;i++) ; 36 for(i=0;i<n;i++)
37 cpu_relax();
32} 38}
39
40EXPORT_SYMBOL(__const_udelay);
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index 3d7da911cc8c..608466ad6b22 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -14,11 +14,11 @@ obj-$(CONFIG_MODULES) += module.o um_module.o
14 14
15USER_OBJS := ptrace_user.o sigcontext.o 15USER_OBJS := ptrace_user.o sigcontext.o
16 16
17include arch/um/scripts/Makefile.rules
18
19SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \ 17SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \
20 semaphore.c thunk.S module.c 18 semaphore.c thunk.S module.c
21 19
20include arch/um/scripts/Makefile.rules
21
22bitops.c-dir = lib 22bitops.c-dir = lib
23csum-copy.S-dir = lib 23csum-copy.S-dir = lib
24csum-partial.c-dir = lib 24csum-partial.c-dir = lib
@@ -28,6 +28,4 @@ semaphore.c-dir = kernel
28thunk.S-dir = lib 28thunk.S-dir = lib
29module.c-dir = kernel 29module.c-dir = kernel
30 30
31CFLAGS_csum-partial.o := -Dcsum_partial=arch_csum_partial
32
33subdir- := util 31subdir- := util
diff --git a/arch/um/sys-x86_64/delay.c b/arch/um/sys-x86_64/delay.c
index 651332aeec22..137f4446b439 100644
--- a/arch/um/sys-x86_64/delay.c
+++ b/arch/um/sys-x86_64/delay.c
@@ -5,40 +5,37 @@
5 * Licensed under the GPL 5 * Licensed under the GPL
6 */ 6 */
7 7
8#include "linux/delay.h" 8#include <linux/module.h>
9#include "asm/processor.h" 9#include <linux/delay.h>
10#include "asm/param.h" 10#include <asm/processor.h>
11#include <asm/param.h>
11 12
12void __delay(unsigned long loops) 13void __delay(unsigned long loops)
13{ 14{
14 unsigned long i; 15 unsigned long i;
15 16
16 for(i = 0; i < loops; i++) ; 17 for(i = 0; i < loops; i++)
18 cpu_relax();
17} 19}
18 20
19void __udelay(unsigned long usecs) 21void __udelay(unsigned long usecs)
20{ 22{
21 int i, n; 23 unsigned long i, n;
22 24
23 n = (loops_per_jiffy * HZ * usecs) / MILLION; 25 n = (loops_per_jiffy * HZ * usecs) / MILLION;
24 for(i=0;i<n;i++) ; 26 for(i=0;i<n;i++)
27 cpu_relax();
25} 28}
26 29
30EXPORT_SYMBOL(__udelay);
31
27void __const_udelay(unsigned long usecs) 32void __const_udelay(unsigned long usecs)
28{ 33{
29 int i, n; 34 unsigned long i, n;
30 35
31 n = (loops_per_jiffy * HZ * usecs) / MILLION; 36 n = (loops_per_jiffy * HZ * usecs) / MILLION;
32 for(i=0;i<n;i++) ; 37 for(i=0;i<n;i++)
38 cpu_relax();
33} 39}
34 40
35/* 41EXPORT_SYMBOL(__const_udelay);
36 * Overrides for Emacs so that we follow Linus's tabbing style.
37 * Emacs will notice this stuff at the end of the file and automatically
38 * adjust the settings for this buffer only. This must remain at the end
39 * of the file.
40 * ---------------------------------------------------------------------------
41 * Local variables:
42 * c-file-style: "linux"
43 * End:
44 */
diff --git a/arch/um/sys-x86_64/ksyms.c b/arch/um/sys-x86_64/ksyms.c
index a27f0ee6a4f6..859273808203 100644
--- a/arch/um/sys-x86_64/ksyms.c
+++ b/arch/um/sys-x86_64/ksyms.c
@@ -16,5 +16,4 @@ EXPORT_SYMBOL(__up_wakeup);
16EXPORT_SYMBOL(__memcpy); 16EXPORT_SYMBOL(__memcpy);
17 17
18/* Networking helper routines. */ 18/* Networking helper routines. */
19/*EXPORT_SYMBOL(csum_partial_copy_from); 19EXPORT_SYMBOL(ip_compute_csum);
20EXPORT_SYMBOL(csum_partial_copy_to);*/
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
index b593bb256f2c..74eee5c7c6dd 100644
--- a/arch/um/sys-x86_64/ptrace.c
+++ b/arch/um/sys-x86_64/ptrace.c
@@ -5,10 +5,11 @@
5 */ 5 */
6 6
7#define __FRAME_OFFSETS 7#define __FRAME_OFFSETS
8#include "asm/ptrace.h" 8#include <asm/ptrace.h>
9#include "linux/sched.h" 9#include <linux/sched.h>
10#include "linux/errno.h" 10#include <linux/errno.h>
11#include "asm/elf.h" 11#include <asm/uaccess.h>
12#include <asm/elf.h>
12 13
13/* XXX x86_64 */ 14/* XXX x86_64 */
14unsigned long not_ss; 15unsigned long not_ss;
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index dd9914642b8e..d4a59657fb99 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -15,6 +15,7 @@
15#include "asm/unistd.h" 15#include "asm/unistd.h"
16#include "asm/prctl.h" /* XXX This should get the constants from libc */ 16#include "asm/prctl.h" /* XXX This should get the constants from libc */
17#include "choose-mode.h" 17#include "choose-mode.h"
18#include "kern.h"
18 19
19asmlinkage long sys_uname64(struct new_utsname __user * name) 20asmlinkage long sys_uname64(struct new_utsname __user * name)
20{ 21{
diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c
index 5e14792e4838..513d17ceafd4 100644
--- a/arch/um/sys-x86_64/user-offsets.c
+++ b/arch/um/sys-x86_64/user-offsets.c
@@ -3,6 +3,14 @@
3#include <signal.h> 3#include <signal.h>
4#define __FRAME_OFFSETS 4#define __FRAME_OFFSETS
5#include <asm/ptrace.h> 5#include <asm/ptrace.h>
6#include <asm/types.h>
7/* For some reason, x86_64 defines u64 and u32 only in <pci/types.h>, which I
8 * refuse to include here, even though they're used throughout the headers.
9 * These are used in asm/user.h, and that include can't be avoided because of
10 * the sizeof(struct user_regs_struct) below.
11 */
12typedef __u64 u64;
13typedef __u32 u32;
6#include <asm/user.h> 14#include <asm/user.h>
7 15
8#define DEFINE(sym, val) \ 16#define DEFINE(sym, val) \