diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/um/os-Linux |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/um/os-Linux')
-rw-r--r-- | arch/um/os-Linux/Makefile | 13 | ||||
-rw-r--r-- | arch/um/os-Linux/drivers/Makefile | 13 | ||||
-rw-r--r-- | arch/um/os-Linux/drivers/etap.h | 27 | ||||
-rw-r--r-- | arch/um/os-Linux/drivers/ethertap_kern.c | 119 | ||||
-rw-r--r-- | arch/um/os-Linux/drivers/ethertap_user.c | 240 | ||||
-rw-r--r-- | arch/um/os-Linux/drivers/tuntap.h | 32 | ||||
-rw-r--r-- | arch/um/os-Linux/drivers/tuntap_kern.c | 104 | ||||
-rw-r--r-- | arch/um/os-Linux/drivers/tuntap_user.c | 225 | ||||
-rw-r--r-- | arch/um/os-Linux/elf_aux.c | 66 | ||||
-rw-r--r-- | arch/um/os-Linux/file.c | 680 | ||||
-rw-r--r-- | arch/um/os-Linux/include/file.h | 22 | ||||
-rw-r--r-- | arch/um/os-Linux/process.c | 171 | ||||
-rw-r--r-- | arch/um/os-Linux/signal.c | 48 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-i386/Makefile | 10 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-i386/registers.c | 132 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-x86_64/Makefile | 10 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-x86_64/registers.c | 81 | ||||
-rw-r--r-- | arch/um/os-Linux/time.c | 21 | ||||
-rw-r--r-- | arch/um/os-Linux/tty.c | 61 | ||||
-rw-r--r-- | arch/um/os-Linux/user_syms.c | 95 | ||||
-rw-r--r-- | arch/um/os-Linux/util/Makefile | 4 | ||||
-rw-r--r-- | arch/um/os-Linux/util/mk_user_constants.c | 29 |
22 files changed, 2203 insertions, 0 deletions
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile new file mode 100644 index 000000000000..4ddf540284ce --- /dev/null +++ b/arch/um/os-Linux/Makefile | |||
@@ -0,0 +1,13 @@ | |||
1 | # | ||
2 | # Copyright (C) 2000 Jeff Dike (jdike@karaya.com) | ||
3 | # Licensed under the GPL | ||
4 | # | ||
5 | |||
6 | obj-y = elf_aux.o file.o process.o signal.o time.o tty.o user_syms.o drivers/ \ | ||
7 | sys-$(SUBARCH)/ | ||
8 | |||
9 | USER_OBJS := elf_aux.o file.o process.o signal.o time.o tty.o | ||
10 | |||
11 | CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) | ||
12 | |||
13 | include arch/um/scripts/Makefile.rules | ||
diff --git a/arch/um/os-Linux/drivers/Makefile b/arch/um/os-Linux/drivers/Makefile new file mode 100644 index 000000000000..6c546dc9222b --- /dev/null +++ b/arch/um/os-Linux/drivers/Makefile | |||
@@ -0,0 +1,13 @@ | |||
1 | # | ||
2 | # Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) | ||
3 | # Licensed under the GPL | ||
4 | # | ||
5 | |||
6 | ethertap-objs := ethertap_kern.o ethertap_user.o | ||
7 | tuntap-objs := tuntap_kern.o tuntap_user.o | ||
8 | |||
9 | obj-y = | ||
10 | obj-$(CONFIG_UML_NET_ETHERTAP) += ethertap.o | ||
11 | obj-$(CONFIG_UML_NET_TUNTAP) += tuntap.o | ||
12 | |||
13 | include arch/um/scripts/Makefile.rules | ||
diff --git a/arch/um/os-Linux/drivers/etap.h b/arch/um/os-Linux/drivers/etap.h new file mode 100644 index 000000000000..b84f6c4740f7 --- /dev/null +++ b/arch/um/os-Linux/drivers/etap.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "net_user.h" | ||
7 | |||
8 | struct ethertap_data { | ||
9 | char *dev_name; | ||
10 | char *gate_addr; | ||
11 | int data_fd; | ||
12 | int control_fd; | ||
13 | void *dev; | ||
14 | }; | ||
15 | |||
16 | extern struct net_user_info ethertap_user_info; | ||
17 | |||
18 | /* | ||
19 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
20 | * Emacs will notice this stuff at the end of the file and automatically | ||
21 | * adjust the settings for this buffer only. This must remain at the end | ||
22 | * of the file. | ||
23 | * --------------------------------------------------------------------------- | ||
24 | * Local variables: | ||
25 | * c-file-style: "linux" | ||
26 | * End: | ||
27 | */ | ||
diff --git a/arch/um/os-Linux/drivers/ethertap_kern.c b/arch/um/os-Linux/drivers/ethertap_kern.c new file mode 100644 index 000000000000..6ae4b19d9f50 --- /dev/null +++ b/arch/um/os-Linux/drivers/ethertap_kern.c | |||
@@ -0,0 +1,119 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and | ||
3 | * James Leu (jleu@mindspring.net). | ||
4 | * Copyright (C) 2001 by various other people who didn't put their name here. | ||
5 | * Licensed under the GPL. | ||
6 | */ | ||
7 | |||
8 | #include "linux/init.h" | ||
9 | #include "linux/netdevice.h" | ||
10 | #include "linux/etherdevice.h" | ||
11 | #include "net_kern.h" | ||
12 | #include "net_user.h" | ||
13 | #include "etap.h" | ||
14 | |||
15 | struct ethertap_init { | ||
16 | char *dev_name; | ||
17 | char *gate_addr; | ||
18 | }; | ||
19 | |||
20 | static void etap_init(struct net_device *dev, void *data) | ||
21 | { | ||
22 | struct uml_net_private *pri; | ||
23 | struct ethertap_data *epri; | ||
24 | struct ethertap_init *init = data; | ||
25 | |||
26 | pri = dev->priv; | ||
27 | epri = (struct ethertap_data *) pri->user; | ||
28 | epri->dev_name = init->dev_name; | ||
29 | epri->gate_addr = init->gate_addr; | ||
30 | epri->data_fd = -1; | ||
31 | epri->control_fd = -1; | ||
32 | epri->dev = dev; | ||
33 | |||
34 | printk("ethertap backend - %s", epri->dev_name); | ||
35 | if (epri->gate_addr != NULL) | ||
36 | printk(", IP = %s", epri->gate_addr); | ||
37 | printk("\n"); | ||
38 | } | ||
39 | |||
40 | static int etap_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) | ||
41 | { | ||
42 | int len; | ||
43 | |||
44 | *skb = ether_adjust_skb(*skb, ETH_HEADER_ETHERTAP); | ||
45 | if(*skb == NULL) return(-ENOMEM); | ||
46 | len = net_recvfrom(fd, (*skb)->mac.raw, | ||
47 | (*skb)->dev->mtu + 2 * ETH_HEADER_ETHERTAP); | ||
48 | if(len <= 0) return(len); | ||
49 | skb_pull(*skb, 2); | ||
50 | len -= 2; | ||
51 | return(len); | ||
52 | } | ||
53 | |||
54 | static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) | ||
55 | { | ||
56 | if(skb_headroom(*skb) < 2){ | ||
57 | struct sk_buff *skb2; | ||
58 | |||
59 | skb2 = skb_realloc_headroom(*skb, 2); | ||
60 | dev_kfree_skb(*skb); | ||
61 | if (skb2 == NULL) return(-ENOMEM); | ||
62 | *skb = skb2; | ||
63 | } | ||
64 | skb_push(*skb, 2); | ||
65 | return(net_send(fd, (*skb)->data, (*skb)->len)); | ||
66 | } | ||
67 | |||
68 | struct net_kern_info ethertap_kern_info = { | ||
69 | .init = etap_init, | ||
70 | .protocol = eth_protocol, | ||
71 | .read = etap_read, | ||
72 | .write = etap_write, | ||
73 | }; | ||
74 | |||
75 | int ethertap_setup(char *str, char **mac_out, void *data) | ||
76 | { | ||
77 | struct ethertap_init *init = data; | ||
78 | |||
79 | *init = ((struct ethertap_init) | ||
80 | { .dev_name = NULL, | ||
81 | .gate_addr = NULL }); | ||
82 | if(tap_setup_common(str, "ethertap", &init->dev_name, mac_out, | ||
83 | &init->gate_addr)) | ||
84 | return(0); | ||
85 | if(init->dev_name == NULL){ | ||
86 | printk("ethertap_setup : Missing tap device name\n"); | ||
87 | return(0); | ||
88 | } | ||
89 | |||
90 | return(1); | ||
91 | } | ||
92 | |||
93 | static struct transport ethertap_transport = { | ||
94 | .list = LIST_HEAD_INIT(ethertap_transport.list), | ||
95 | .name = "ethertap", | ||
96 | .setup = ethertap_setup, | ||
97 | .user = ðertap_user_info, | ||
98 | .kern = ðertap_kern_info, | ||
99 | .private_size = sizeof(struct ethertap_data), | ||
100 | }; | ||
101 | |||
102 | static int register_ethertap(void) | ||
103 | { | ||
104 | register_transport(ðertap_transport); | ||
105 | return(1); | ||
106 | } | ||
107 | |||
108 | __initcall(register_ethertap); | ||
109 | |||
110 | /* | ||
111 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
112 | * Emacs will notice this stuff at the end of the file and automatically | ||
113 | * adjust the settings for this buffer only. This must remain at the end | ||
114 | * of the file. | ||
115 | * --------------------------------------------------------------------------- | ||
116 | * Local variables: | ||
117 | * c-file-style: "linux" | ||
118 | * End: | ||
119 | */ | ||
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c new file mode 100644 index 000000000000..cd4d6544da71 --- /dev/null +++ b/arch/um/os-Linux/drivers/ethertap_user.c | |||
@@ -0,0 +1,240 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and | ||
3 | * James Leu (jleu@mindspring.net). | ||
4 | * Copyright (C) 2001 by various other people who didn't put their name here. | ||
5 | * Licensed under the GPL. | ||
6 | */ | ||
7 | |||
8 | #include <stdio.h> | ||
9 | #include <unistd.h> | ||
10 | #include <stddef.h> | ||
11 | #include <stdlib.h> | ||
12 | #include <sys/errno.h> | ||
13 | #include <sys/socket.h> | ||
14 | #include <sys/wait.h> | ||
15 | #include <sys/un.h> | ||
16 | #include <net/if.h> | ||
17 | #include "user.h" | ||
18 | #include "kern_util.h" | ||
19 | #include "user_util.h" | ||
20 | #include "net_user.h" | ||
21 | #include "etap.h" | ||
22 | #include "helper.h" | ||
23 | #include "os.h" | ||
24 | |||
25 | #define MAX_PACKET ETH_MAX_PACKET | ||
26 | |||
27 | void etap_user_init(void *data, void *dev) | ||
28 | { | ||
29 | struct ethertap_data *pri = data; | ||
30 | |||
31 | pri->dev = dev; | ||
32 | } | ||
33 | |||
34 | struct addr_change { | ||
35 | enum { ADD_ADDR, DEL_ADDR } what; | ||
36 | unsigned char addr[4]; | ||
37 | unsigned char netmask[4]; | ||
38 | }; | ||
39 | |||
40 | static void etap_change(int op, unsigned char *addr, unsigned char *netmask, | ||
41 | int fd) | ||
42 | { | ||
43 | struct addr_change change; | ||
44 | void *output; | ||
45 | int n; | ||
46 | |||
47 | change.what = op; | ||
48 | memcpy(change.addr, addr, sizeof(change.addr)); | ||
49 | memcpy(change.netmask, netmask, sizeof(change.netmask)); | ||
50 | n = os_write_file(fd, &change, sizeof(change)); | ||
51 | if(n != sizeof(change)) | ||
52 | printk("etap_change - request failed, err = %d\n", -n); | ||
53 | output = um_kmalloc(page_size()); | ||
54 | if(output == NULL) | ||
55 | printk("etap_change : Failed to allocate output buffer\n"); | ||
56 | read_output(fd, output, page_size()); | ||
57 | if(output != NULL){ | ||
58 | printk("%s", output); | ||
59 | kfree(output); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | static void etap_open_addr(unsigned char *addr, unsigned char *netmask, | ||
64 | void *arg) | ||
65 | { | ||
66 | etap_change(ADD_ADDR, addr, netmask, *((int *) arg)); | ||
67 | } | ||
68 | |||
69 | static void etap_close_addr(unsigned char *addr, unsigned char *netmask, | ||
70 | void *arg) | ||
71 | { | ||
72 | etap_change(DEL_ADDR, addr, netmask, *((int *) arg)); | ||
73 | } | ||
74 | |||
75 | struct etap_pre_exec_data { | ||
76 | int control_remote; | ||
77 | int control_me; | ||
78 | int data_me; | ||
79 | }; | ||
80 | |||
81 | static void etap_pre_exec(void *arg) | ||
82 | { | ||
83 | struct etap_pre_exec_data *data = arg; | ||
84 | |||
85 | dup2(data->control_remote, 1); | ||
86 | os_close_file(data->data_me); | ||
87 | os_close_file(data->control_me); | ||
88 | } | ||
89 | |||
90 | static int etap_tramp(char *dev, char *gate, int control_me, | ||
91 | int control_remote, int data_me, int data_remote) | ||
92 | { | ||
93 | struct etap_pre_exec_data pe_data; | ||
94 | int pid, status, err, n; | ||
95 | char version_buf[sizeof("nnnnn\0")]; | ||
96 | char data_fd_buf[sizeof("nnnnnn\0")]; | ||
97 | char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; | ||
98 | char *setup_args[] = { "uml_net", version_buf, "ethertap", dev, | ||
99 | data_fd_buf, gate_buf, NULL }; | ||
100 | char *nosetup_args[] = { "uml_net", version_buf, "ethertap", | ||
101 | dev, data_fd_buf, NULL }; | ||
102 | char **args, c; | ||
103 | |||
104 | sprintf(data_fd_buf, "%d", data_remote); | ||
105 | sprintf(version_buf, "%d", UML_NET_VERSION); | ||
106 | if(gate != NULL){ | ||
107 | strcpy(gate_buf, gate); | ||
108 | args = setup_args; | ||
109 | } | ||
110 | else args = nosetup_args; | ||
111 | |||
112 | err = 0; | ||
113 | pe_data.control_remote = control_remote; | ||
114 | pe_data.control_me = control_me; | ||
115 | pe_data.data_me = data_me; | ||
116 | pid = run_helper(etap_pre_exec, &pe_data, args, NULL); | ||
117 | |||
118 | if(pid < 0) err = pid; | ||
119 | os_close_file(data_remote); | ||
120 | os_close_file(control_remote); | ||
121 | n = os_read_file(control_me, &c, sizeof(c)); | ||
122 | if(n != sizeof(c)){ | ||
123 | printk("etap_tramp : read of status failed, err = %d\n", -n); | ||
124 | return(-EINVAL); | ||
125 | } | ||
126 | if(c != 1){ | ||
127 | printk("etap_tramp : uml_net failed\n"); | ||
128 | err = -EINVAL; | ||
129 | CATCH_EINTR(n = waitpid(pid, &status, 0)); | ||
130 | if(n < 0) | ||
131 | err = -errno; | ||
132 | else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)) | ||
133 | printk("uml_net didn't exit with status 1\n"); | ||
134 | } | ||
135 | return(err); | ||
136 | } | ||
137 | |||
138 | static int etap_open(void *data) | ||
139 | { | ||
140 | struct ethertap_data *pri = data; | ||
141 | char *output; | ||
142 | int data_fds[2], control_fds[2], err, output_len; | ||
143 | |||
144 | err = tap_open_common(pri->dev, pri->gate_addr); | ||
145 | if(err) return(err); | ||
146 | |||
147 | err = os_pipe(data_fds, 0, 0); | ||
148 | if(err < 0){ | ||
149 | printk("data os_pipe failed - err = %d\n", -err); | ||
150 | return(err); | ||
151 | } | ||
152 | |||
153 | err = os_pipe(control_fds, 1, 0); | ||
154 | if(err < 0){ | ||
155 | printk("control os_pipe failed - err = %d\n", -err); | ||
156 | return(err); | ||
157 | } | ||
158 | |||
159 | err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], | ||
160 | control_fds[1], data_fds[0], data_fds[1]); | ||
161 | output_len = page_size(); | ||
162 | output = um_kmalloc(output_len); | ||
163 | read_output(control_fds[0], output, output_len); | ||
164 | |||
165 | if(output == NULL) | ||
166 | printk("etap_open : failed to allocate output buffer\n"); | ||
167 | else { | ||
168 | printk("%s", output); | ||
169 | kfree(output); | ||
170 | } | ||
171 | |||
172 | if(err < 0){ | ||
173 | printk("etap_tramp failed - err = %d\n", -err); | ||
174 | return(err); | ||
175 | } | ||
176 | |||
177 | pri->data_fd = data_fds[0]; | ||
178 | pri->control_fd = control_fds[0]; | ||
179 | iter_addresses(pri->dev, etap_open_addr, &pri->control_fd); | ||
180 | return(data_fds[0]); | ||
181 | } | ||
182 | |||
183 | static void etap_close(int fd, void *data) | ||
184 | { | ||
185 | struct ethertap_data *pri = data; | ||
186 | |||
187 | iter_addresses(pri->dev, etap_close_addr, &pri->control_fd); | ||
188 | os_close_file(fd); | ||
189 | os_shutdown_socket(pri->data_fd, 1, 1); | ||
190 | os_close_file(pri->data_fd); | ||
191 | pri->data_fd = -1; | ||
192 | os_close_file(pri->control_fd); | ||
193 | pri->control_fd = -1; | ||
194 | } | ||
195 | |||
196 | static int etap_set_mtu(int mtu, void *data) | ||
197 | { | ||
198 | return(mtu); | ||
199 | } | ||
200 | |||
201 | static void etap_add_addr(unsigned char *addr, unsigned char *netmask, | ||
202 | void *data) | ||
203 | { | ||
204 | struct ethertap_data *pri = data; | ||
205 | |||
206 | tap_check_ips(pri->gate_addr, addr); | ||
207 | if(pri->control_fd == -1) return; | ||
208 | etap_open_addr(addr, netmask, &pri->control_fd); | ||
209 | } | ||
210 | |||
211 | static void etap_del_addr(unsigned char *addr, unsigned char *netmask, | ||
212 | void *data) | ||
213 | { | ||
214 | struct ethertap_data *pri = data; | ||
215 | |||
216 | if(pri->control_fd == -1) return; | ||
217 | etap_close_addr(addr, netmask, &pri->control_fd); | ||
218 | } | ||
219 | |||
220 | struct net_user_info ethertap_user_info = { | ||
221 | .init = etap_user_init, | ||
222 | .open = etap_open, | ||
223 | .close = etap_close, | ||
224 | .remove = NULL, | ||
225 | .set_mtu = etap_set_mtu, | ||
226 | .add_address = etap_add_addr, | ||
227 | .delete_address = etap_del_addr, | ||
228 | .max_packet = MAX_PACKET - ETH_HEADER_ETHERTAP | ||
229 | }; | ||
230 | |||
231 | /* | ||
232 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
233 | * Emacs will notice this stuff at the end of the file and automatically | ||
234 | * adjust the settings for this buffer only. This must remain at the end | ||
235 | * of the file. | ||
236 | * --------------------------------------------------------------------------- | ||
237 | * Local variables: | ||
238 | * c-file-style: "linux" | ||
239 | * End: | ||
240 | */ | ||
diff --git a/arch/um/os-Linux/drivers/tuntap.h b/arch/um/os-Linux/drivers/tuntap.h new file mode 100644 index 000000000000..25d4a2868814 --- /dev/null +++ b/arch/um/os-Linux/drivers/tuntap.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __UM_TUNTAP_H | ||
7 | #define __UM_TUNTAP_H | ||
8 | |||
9 | #include "net_user.h" | ||
10 | |||
11 | struct tuntap_data { | ||
12 | char *dev_name; | ||
13 | int fixed_config; | ||
14 | char *gate_addr; | ||
15 | int fd; | ||
16 | void *dev; | ||
17 | }; | ||
18 | |||
19 | extern struct net_user_info tuntap_user_info; | ||
20 | |||
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/os-Linux/drivers/tuntap_kern.c b/arch/um/os-Linux/drivers/tuntap_kern.c new file mode 100644 index 000000000000..4202b9ebad4c --- /dev/null +++ b/arch/um/os-Linux/drivers/tuntap_kern.c | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/stddef.h" | ||
7 | #include "linux/netdevice.h" | ||
8 | #include "linux/etherdevice.h" | ||
9 | #include "linux/skbuff.h" | ||
10 | #include "linux/init.h" | ||
11 | #include "asm/errno.h" | ||
12 | #include "net_kern.h" | ||
13 | #include "net_user.h" | ||
14 | #include "tuntap.h" | ||
15 | |||
16 | struct tuntap_init { | ||
17 | char *dev_name; | ||
18 | char *gate_addr; | ||
19 | }; | ||
20 | |||
21 | static void tuntap_init(struct net_device *dev, void *data) | ||
22 | { | ||
23 | struct uml_net_private *pri; | ||
24 | struct tuntap_data *tpri; | ||
25 | struct tuntap_init *init = data; | ||
26 | |||
27 | pri = dev->priv; | ||
28 | tpri = (struct tuntap_data *) pri->user; | ||
29 | tpri->dev_name = init->dev_name; | ||
30 | tpri->fixed_config = (init->dev_name != NULL); | ||
31 | tpri->gate_addr = init->gate_addr; | ||
32 | tpri->fd = -1; | ||
33 | tpri->dev = dev; | ||
34 | |||
35 | printk("TUN/TAP backend - "); | ||
36 | if (tpri->gate_addr != NULL) | ||
37 | printk("IP = %s", tpri->gate_addr); | ||
38 | printk("\n"); | ||
39 | } | ||
40 | |||
41 | static int tuntap_read(int fd, struct sk_buff **skb, | ||
42 | struct uml_net_private *lp) | ||
43 | { | ||
44 | *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); | ||
45 | if(*skb == NULL) return(-ENOMEM); | ||
46 | return(net_read(fd, (*skb)->mac.raw, | ||
47 | (*skb)->dev->mtu + ETH_HEADER_OTHER)); | ||
48 | } | ||
49 | |||
50 | static int tuntap_write(int fd, struct sk_buff **skb, | ||
51 | struct uml_net_private *lp) | ||
52 | { | ||
53 | return(net_write(fd, (*skb)->data, (*skb)->len)); | ||
54 | } | ||
55 | |||
56 | struct net_kern_info tuntap_kern_info = { | ||
57 | .init = tuntap_init, | ||
58 | .protocol = eth_protocol, | ||
59 | .read = tuntap_read, | ||
60 | .write = tuntap_write, | ||
61 | }; | ||
62 | |||
63 | int tuntap_setup(char *str, char **mac_out, void *data) | ||
64 | { | ||
65 | struct tuntap_init *init = data; | ||
66 | |||
67 | *init = ((struct tuntap_init) | ||
68 | { .dev_name = NULL, | ||
69 | .gate_addr = NULL }); | ||
70 | if(tap_setup_common(str, "tuntap", &init->dev_name, mac_out, | ||
71 | &init->gate_addr)) | ||
72 | return(0); | ||
73 | |||
74 | return(1); | ||
75 | } | ||
76 | |||
77 | static struct transport tuntap_transport = { | ||
78 | .list = LIST_HEAD_INIT(tuntap_transport.list), | ||
79 | .name = "tuntap", | ||
80 | .setup = tuntap_setup, | ||
81 | .user = &tuntap_user_info, | ||
82 | .kern = &tuntap_kern_info, | ||
83 | .private_size = sizeof(struct tuntap_data), | ||
84 | .setup_size = sizeof(struct tuntap_init), | ||
85 | }; | ||
86 | |||
87 | static int register_tuntap(void) | ||
88 | { | ||
89 | register_transport(&tuntap_transport); | ||
90 | return(1); | ||
91 | } | ||
92 | |||
93 | __initcall(register_tuntap); | ||
94 | |||
95 | /* | ||
96 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
97 | * Emacs will notice this stuff at the end of the file and automatically | ||
98 | * adjust the settings for this buffer only. This must remain at the end | ||
99 | * of the file. | ||
100 | * --------------------------------------------------------------------------- | ||
101 | * Local variables: | ||
102 | * c-file-style: "linux" | ||
103 | * End: | ||
104 | */ | ||
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c new file mode 100644 index 000000000000..4b83c6c3f48d --- /dev/null +++ b/arch/um/os-Linux/drivers/tuntap_user.c | |||
@@ -0,0 +1,225 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stdio.h> | ||
7 | #include <stddef.h> | ||
8 | #include <stdlib.h> | ||
9 | #include <unistd.h> | ||
10 | #include <errno.h> | ||
11 | #include <sys/wait.h> | ||
12 | #include <sys/socket.h> | ||
13 | #include <sys/un.h> | ||
14 | #include <sys/uio.h> | ||
15 | #include <sys/ioctl.h> | ||
16 | #include <net/if.h> | ||
17 | #include <linux/if_tun.h> | ||
18 | #include "net_user.h" | ||
19 | #include "tuntap.h" | ||
20 | #include "kern_util.h" | ||
21 | #include "user_util.h" | ||
22 | #include "user.h" | ||
23 | #include "helper.h" | ||
24 | #include "os.h" | ||
25 | |||
26 | #define MAX_PACKET ETH_MAX_PACKET | ||
27 | |||
28 | void tuntap_user_init(void *data, void *dev) | ||
29 | { | ||
30 | struct tuntap_data *pri = data; | ||
31 | |||
32 | pri->dev = dev; | ||
33 | } | ||
34 | |||
35 | static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask, | ||
36 | void *data) | ||
37 | { | ||
38 | struct tuntap_data *pri = data; | ||
39 | |||
40 | tap_check_ips(pri->gate_addr, addr); | ||
41 | if((pri->fd == -1) || pri->fixed_config) return; | ||
42 | open_addr(addr, netmask, pri->dev_name); | ||
43 | } | ||
44 | |||
45 | static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask, | ||
46 | void *data) | ||
47 | { | ||
48 | struct tuntap_data *pri = data; | ||
49 | |||
50 | if((pri->fd == -1) || pri->fixed_config) return; | ||
51 | close_addr(addr, netmask, pri->dev_name); | ||
52 | } | ||
53 | |||
54 | struct tuntap_pre_exec_data { | ||
55 | int stdout; | ||
56 | int close_me; | ||
57 | }; | ||
58 | |||
59 | static void tuntap_pre_exec(void *arg) | ||
60 | { | ||
61 | struct tuntap_pre_exec_data *data = arg; | ||
62 | |||
63 | dup2(data->stdout, 1); | ||
64 | os_close_file(data->close_me); | ||
65 | } | ||
66 | |||
67 | static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, | ||
68 | char *buffer, int buffer_len, int *used_out) | ||
69 | { | ||
70 | struct tuntap_pre_exec_data data; | ||
71 | char version_buf[sizeof("nnnnn\0")]; | ||
72 | char *argv[] = { "uml_net", version_buf, "tuntap", "up", gate, | ||
73 | NULL }; | ||
74 | char buf[CMSG_SPACE(sizeof(*fd_out))]; | ||
75 | struct msghdr msg; | ||
76 | struct cmsghdr *cmsg; | ||
77 | struct iovec iov; | ||
78 | int pid, n; | ||
79 | |||
80 | sprintf(version_buf, "%d", UML_NET_VERSION); | ||
81 | |||
82 | data.stdout = remote; | ||
83 | data.close_me = me; | ||
84 | |||
85 | pid = run_helper(tuntap_pre_exec, &data, argv, NULL); | ||
86 | |||
87 | if(pid < 0) return(-pid); | ||
88 | |||
89 | os_close_file(remote); | ||
90 | |||
91 | msg.msg_name = NULL; | ||
92 | msg.msg_namelen = 0; | ||
93 | if(buffer != NULL){ | ||
94 | iov = ((struct iovec) { buffer, buffer_len }); | ||
95 | msg.msg_iov = &iov; | ||
96 | msg.msg_iovlen = 1; | ||
97 | } | ||
98 | else { | ||
99 | msg.msg_iov = NULL; | ||
100 | msg.msg_iovlen = 0; | ||
101 | } | ||
102 | msg.msg_control = buf; | ||
103 | msg.msg_controllen = sizeof(buf); | ||
104 | msg.msg_flags = 0; | ||
105 | n = recvmsg(me, &msg, 0); | ||
106 | *used_out = n; | ||
107 | if(n < 0){ | ||
108 | printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", | ||
109 | errno); | ||
110 | return(-errno); | ||
111 | } | ||
112 | CATCH_EINTR(waitpid(pid, NULL, 0)); | ||
113 | |||
114 | cmsg = CMSG_FIRSTHDR(&msg); | ||
115 | if(cmsg == NULL){ | ||
116 | printk("tuntap_open_tramp : didn't receive a message\n"); | ||
117 | return(-EINVAL); | ||
118 | } | ||
119 | if((cmsg->cmsg_level != SOL_SOCKET) || | ||
120 | (cmsg->cmsg_type != SCM_RIGHTS)){ | ||
121 | printk("tuntap_open_tramp : didn't receive a descriptor\n"); | ||
122 | return(-EINVAL); | ||
123 | } | ||
124 | *fd_out = ((int *) CMSG_DATA(cmsg))[0]; | ||
125 | return(0); | ||
126 | } | ||
127 | |||
128 | static int tuntap_open(void *data) | ||
129 | { | ||
130 | struct ifreq ifr; | ||
131 | struct tuntap_data *pri = data; | ||
132 | char *output, *buffer; | ||
133 | int err, fds[2], len, used; | ||
134 | |||
135 | err = tap_open_common(pri->dev, pri->gate_addr); | ||
136 | if(err < 0) | ||
137 | return(err); | ||
138 | |||
139 | if(pri->fixed_config){ | ||
140 | pri->fd = os_open_file("/dev/net/tun", of_rdwr(OPENFLAGS()), 0); | ||
141 | if(pri->fd < 0){ | ||
142 | printk("Failed to open /dev/net/tun, err = %d\n", | ||
143 | -pri->fd); | ||
144 | return(pri->fd); | ||
145 | } | ||
146 | memset(&ifr, 0, sizeof(ifr)); | ||
147 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI; | ||
148 | strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); | ||
149 | if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){ | ||
150 | printk("TUNSETIFF failed, errno = %d\n", errno); | ||
151 | os_close_file(pri->fd); | ||
152 | return(-errno); | ||
153 | } | ||
154 | } | ||
155 | else { | ||
156 | err = os_pipe(fds, 0, 0); | ||
157 | if(err < 0){ | ||
158 | printk("tuntap_open : os_pipe failed - err = %d\n", | ||
159 | -err); | ||
160 | return(err); | ||
161 | } | ||
162 | |||
163 | buffer = get_output_buffer(&len); | ||
164 | if(buffer != NULL) len--; | ||
165 | used = 0; | ||
166 | |||
167 | err = tuntap_open_tramp(pri->gate_addr, &pri->fd, fds[0], | ||
168 | fds[1], buffer, len, &used); | ||
169 | |||
170 | output = buffer; | ||
171 | if(err < 0) { | ||
172 | printk("%s", output); | ||
173 | free_output_buffer(buffer); | ||
174 | printk("tuntap_open_tramp failed - err = %d\n", -err); | ||
175 | return(err); | ||
176 | } | ||
177 | |||
178 | pri->dev_name = uml_strdup(buffer); | ||
179 | output += IFNAMSIZ; | ||
180 | printk("%s", output); | ||
181 | free_output_buffer(buffer); | ||
182 | |||
183 | os_close_file(fds[0]); | ||
184 | iter_addresses(pri->dev, open_addr, pri->dev_name); | ||
185 | } | ||
186 | |||
187 | return(pri->fd); | ||
188 | } | ||
189 | |||
190 | static void tuntap_close(int fd, void *data) | ||
191 | { | ||
192 | struct tuntap_data *pri = data; | ||
193 | |||
194 | if(!pri->fixed_config) | ||
195 | iter_addresses(pri->dev, close_addr, pri->dev_name); | ||
196 | os_close_file(fd); | ||
197 | pri->fd = -1; | ||
198 | } | ||
199 | |||
200 | static int tuntap_set_mtu(int mtu, void *data) | ||
201 | { | ||
202 | return(mtu); | ||
203 | } | ||
204 | |||
205 | struct net_user_info tuntap_user_info = { | ||
206 | .init = tuntap_user_init, | ||
207 | .open = tuntap_open, | ||
208 | .close = tuntap_close, | ||
209 | .remove = NULL, | ||
210 | .set_mtu = tuntap_set_mtu, | ||
211 | .add_address = tuntap_add_addr, | ||
212 | .delete_address = tuntap_del_addr, | ||
213 | .max_packet = MAX_PACKET | ||
214 | }; | ||
215 | |||
216 | /* | ||
217 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
218 | * Emacs will notice this stuff at the end of the file and automatically | ||
219 | * adjust the settings for this buffer only. This must remain at the end | ||
220 | * of the file. | ||
221 | * --------------------------------------------------------------------------- | ||
222 | * Local variables: | ||
223 | * c-file-style: "linux" | ||
224 | * End: | ||
225 | */ | ||
diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c new file mode 100644 index 000000000000..9aee0b62ebca --- /dev/null +++ b/arch/um/os-Linux/elf_aux.c | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * arch/um/kernel/elf_aux.c | ||
3 | * | ||
4 | * Scan the Elf auxiliary vector provided by the host to extract | ||
5 | * information about vsyscall-page, etc. | ||
6 | * | ||
7 | * Copyright (C) 2004 Fujitsu Siemens Computers GmbH | ||
8 | * Author: Bodo Stroesser (bodo.stroesser@fujitsu-siemens.com) | ||
9 | */ | ||
10 | #include <elf.h> | ||
11 | #include <stddef.h> | ||
12 | #include "init.h" | ||
13 | #include "elf_user.h" | ||
14 | |||
15 | #if ELF_CLASS == ELFCLASS32 | ||
16 | typedef Elf32_auxv_t elf_auxv_t; | ||
17 | #else | ||
18 | typedef Elf64_auxv_t elf_auxv_t; | ||
19 | #endif | ||
20 | |||
21 | char * elf_aux_platform; | ||
22 | long elf_aux_hwcap; | ||
23 | |||
24 | unsigned long vsyscall_ehdr; | ||
25 | unsigned long vsyscall_end; | ||
26 | |||
27 | unsigned long __kernel_vsyscall; | ||
28 | |||
29 | __init void scan_elf_aux( char **envp) | ||
30 | { | ||
31 | long page_size = 0; | ||
32 | elf_auxv_t * auxv; | ||
33 | |||
34 | while ( *envp++ != NULL) ; | ||
35 | |||
36 | for ( auxv = (elf_auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) { | ||
37 | switch ( auxv->a_type ) { | ||
38 | case AT_SYSINFO: | ||
39 | __kernel_vsyscall = auxv->a_un.a_val; | ||
40 | break; | ||
41 | case AT_SYSINFO_EHDR: | ||
42 | vsyscall_ehdr = auxv->a_un.a_val; | ||
43 | break; | ||
44 | case AT_HWCAP: | ||
45 | elf_aux_hwcap = auxv->a_un.a_val; | ||
46 | break; | ||
47 | case AT_PLATFORM: | ||
48 | elf_aux_platform = auxv->a_un.a_ptr; | ||
49 | break; | ||
50 | case AT_PAGESZ: | ||
51 | page_size = auxv->a_un.a_val; | ||
52 | break; | ||
53 | } | ||
54 | } | ||
55 | if ( ! __kernel_vsyscall || ! vsyscall_ehdr || | ||
56 | ! elf_aux_hwcap || ! elf_aux_platform || | ||
57 | ! page_size || (vsyscall_ehdr % page_size) ) { | ||
58 | __kernel_vsyscall = 0; | ||
59 | vsyscall_ehdr = 0; | ||
60 | elf_aux_hwcap = 0; | ||
61 | elf_aux_platform = "i586"; | ||
62 | } | ||
63 | else { | ||
64 | vsyscall_end = vsyscall_ehdr + page_size; | ||
65 | } | ||
66 | } | ||
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c new file mode 100644 index 000000000000..77d4066d1af8 --- /dev/null +++ b/arch/um/os-Linux/file.c | |||
@@ -0,0 +1,680 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stdio.h> | ||
7 | #include <unistd.h> | ||
8 | #include <errno.h> | ||
9 | #include <fcntl.h> | ||
10 | #include <signal.h> | ||
11 | #include <sys/types.h> | ||
12 | #include <sys/stat.h> | ||
13 | #include <sys/socket.h> | ||
14 | #include <sys/un.h> | ||
15 | #include <sys/ioctl.h> | ||
16 | #include <sys/mount.h> | ||
17 | #include <sys/uio.h> | ||
18 | #include "os.h" | ||
19 | #include "user.h" | ||
20 | #include "kern_util.h" | ||
21 | |||
22 | static void copy_stat(struct uml_stat *dst, struct stat64 *src) | ||
23 | { | ||
24 | *dst = ((struct uml_stat) { | ||
25 | .ust_dev = src->st_dev, /* device */ | ||
26 | .ust_ino = src->st_ino, /* inode */ | ||
27 | .ust_mode = src->st_mode, /* protection */ | ||
28 | .ust_nlink = src->st_nlink, /* number of hard links */ | ||
29 | .ust_uid = src->st_uid, /* user ID of owner */ | ||
30 | .ust_gid = src->st_gid, /* group ID of owner */ | ||
31 | .ust_size = src->st_size, /* total size, in bytes */ | ||
32 | .ust_blksize = src->st_blksize, /* blocksize for filesys I/O */ | ||
33 | .ust_blocks = src->st_blocks, /* number of blocks allocated */ | ||
34 | .ust_atime = src->st_atime, /* time of last access */ | ||
35 | .ust_mtime = src->st_mtime, /* time of last modification */ | ||
36 | .ust_ctime = src->st_ctime, /* time of last change */ | ||
37 | }); | ||
38 | } | ||
39 | |||
40 | int os_stat_fd(const int fd, struct uml_stat *ubuf) | ||
41 | { | ||
42 | struct stat64 sbuf; | ||
43 | int err; | ||
44 | |||
45 | do { | ||
46 | err = fstat64(fd, &sbuf); | ||
47 | } while((err < 0) && (errno == EINTR)) ; | ||
48 | |||
49 | if(err < 0) | ||
50 | return(-errno); | ||
51 | |||
52 | if(ubuf != NULL) | ||
53 | copy_stat(ubuf, &sbuf); | ||
54 | return(err); | ||
55 | } | ||
56 | |||
57 | int os_stat_file(const char *file_name, struct uml_stat *ubuf) | ||
58 | { | ||
59 | struct stat64 sbuf; | ||
60 | int err; | ||
61 | |||
62 | do { | ||
63 | err = stat64(file_name, &sbuf); | ||
64 | } while((err < 0) && (errno == EINTR)) ; | ||
65 | |||
66 | if(err < 0) | ||
67 | return(-errno); | ||
68 | |||
69 | if(ubuf != NULL) | ||
70 | copy_stat(ubuf, &sbuf); | ||
71 | return(err); | ||
72 | } | ||
73 | |||
74 | int os_access(const char* file, int mode) | ||
75 | { | ||
76 | int amode, err; | ||
77 | |||
78 | amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) | | ||
79 | (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ; | ||
80 | |||
81 | err = access(file, amode); | ||
82 | if(err < 0) | ||
83 | return(-errno); | ||
84 | |||
85 | return(0); | ||
86 | } | ||
87 | |||
88 | void os_print_error(int error, const char* str) | ||
89 | { | ||
90 | errno = error < 0 ? -error : error; | ||
91 | |||
92 | perror(str); | ||
93 | } | ||
94 | |||
95 | /* FIXME? required only by hostaudio (because it passes ioctls verbatim) */ | ||
96 | int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg) | ||
97 | { | ||
98 | int err; | ||
99 | |||
100 | err = ioctl(fd, cmd, arg); | ||
101 | if(err < 0) | ||
102 | return(-errno); | ||
103 | |||
104 | return(err); | ||
105 | } | ||
106 | |||
107 | int os_window_size(int fd, int *rows, int *cols) | ||
108 | { | ||
109 | struct winsize size; | ||
110 | |||
111 | if(ioctl(fd, TIOCGWINSZ, &size) < 0) | ||
112 | return(-errno); | ||
113 | |||
114 | *rows = size.ws_row; | ||
115 | *cols = size.ws_col; | ||
116 | |||
117 | return(0); | ||
118 | } | ||
119 | |||
120 | int os_new_tty_pgrp(int fd, int pid) | ||
121 | { | ||
122 | if(ioctl(fd, TIOCSCTTY, 0) < 0){ | ||
123 | printk("TIOCSCTTY failed, errno = %d\n", errno); | ||
124 | return(-errno); | ||
125 | } | ||
126 | |||
127 | if(tcsetpgrp(fd, pid) < 0){ | ||
128 | printk("tcsetpgrp failed, errno = %d\n", errno); | ||
129 | return(-errno); | ||
130 | } | ||
131 | |||
132 | return(0); | ||
133 | } | ||
134 | |||
135 | /* FIXME: ensure namebuf in os_get_if_name is big enough */ | ||
136 | int os_get_ifname(int fd, char* namebuf) | ||
137 | { | ||
138 | if(ioctl(fd, SIOCGIFNAME, namebuf) < 0) | ||
139 | return(-errno); | ||
140 | |||
141 | return(0); | ||
142 | } | ||
143 | |||
144 | int os_set_slip(int fd) | ||
145 | { | ||
146 | int disc, sencap; | ||
147 | |||
148 | disc = N_SLIP; | ||
149 | if(ioctl(fd, TIOCSETD, &disc) < 0){ | ||
150 | printk("Failed to set slip line discipline - " | ||
151 | "errno = %d\n", errno); | ||
152 | return(-errno); | ||
153 | } | ||
154 | |||
155 | sencap = 0; | ||
156 | if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){ | ||
157 | printk("Failed to set slip encapsulation - " | ||
158 | "errno = %d\n", errno); | ||
159 | return(-errno); | ||
160 | } | ||
161 | |||
162 | return(0); | ||
163 | } | ||
164 | |||
165 | int os_set_owner(int fd, int pid) | ||
166 | { | ||
167 | if(fcntl(fd, F_SETOWN, pid) < 0){ | ||
168 | int save_errno = errno; | ||
169 | |||
170 | if(fcntl(fd, F_GETOWN, 0) != pid) | ||
171 | return(-save_errno); | ||
172 | } | ||
173 | |||
174 | return(0); | ||
175 | } | ||
176 | |||
177 | /* FIXME? moved wholesale from sigio_user.c to get fcntls out of that file */ | ||
178 | int os_sigio_async(int master, int slave) | ||
179 | { | ||
180 | int flags; | ||
181 | |||
182 | flags = fcntl(master, F_GETFL); | ||
183 | if(flags < 0) { | ||
184 | printk("fcntl F_GETFL failed, errno = %d\n", errno); | ||
185 | return(-errno); | ||
186 | } | ||
187 | |||
188 | if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || | ||
189 | (fcntl(master, F_SETOWN, os_getpid()) < 0)){ | ||
190 | printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n", | ||
191 | errno); | ||
192 | return(-errno); | ||
193 | } | ||
194 | |||
195 | if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){ | ||
196 | printk("fcntl F_SETFL failed, errno = %d\n", errno); | ||
197 | return(-errno); | ||
198 | } | ||
199 | |||
200 | return(0); | ||
201 | } | ||
202 | |||
203 | int os_mode_fd(int fd, int mode) | ||
204 | { | ||
205 | int err; | ||
206 | |||
207 | do { | ||
208 | err = fchmod(fd, mode); | ||
209 | } while((err < 0) && (errno==EINTR)) ; | ||
210 | |||
211 | if(err < 0) | ||
212 | return(-errno); | ||
213 | |||
214 | return(0); | ||
215 | } | ||
216 | |||
217 | int os_file_type(char *file) | ||
218 | { | ||
219 | struct uml_stat buf; | ||
220 | int err; | ||
221 | |||
222 | err = os_stat_file(file, &buf); | ||
223 | if(err < 0) | ||
224 | return(err); | ||
225 | |||
226 | if(S_ISDIR(buf.ust_mode)) return(OS_TYPE_DIR); | ||
227 | else if(S_ISLNK(buf.ust_mode)) return(OS_TYPE_SYMLINK); | ||
228 | else if(S_ISCHR(buf.ust_mode)) return(OS_TYPE_CHARDEV); | ||
229 | else if(S_ISBLK(buf.ust_mode)) return(OS_TYPE_BLOCKDEV); | ||
230 | else if(S_ISFIFO(buf.ust_mode)) return(OS_TYPE_FIFO); | ||
231 | else if(S_ISSOCK(buf.ust_mode)) return(OS_TYPE_SOCK); | ||
232 | else return(OS_TYPE_FILE); | ||
233 | } | ||
234 | |||
235 | int os_file_mode(char *file, struct openflags *mode_out) | ||
236 | { | ||
237 | int err; | ||
238 | |||
239 | *mode_out = OPENFLAGS(); | ||
240 | |||
241 | err = os_access(file, OS_ACC_W_OK); | ||
242 | if((err < 0) && (err != -EACCES)) | ||
243 | return(err); | ||
244 | |||
245 | *mode_out = of_write(*mode_out); | ||
246 | |||
247 | err = os_access(file, OS_ACC_R_OK); | ||
248 | if((err < 0) && (err != -EACCES)) | ||
249 | return(err); | ||
250 | |||
251 | *mode_out = of_read(*mode_out); | ||
252 | |||
253 | return(0); | ||
254 | } | ||
255 | |||
256 | int os_open_file(char *file, struct openflags flags, int mode) | ||
257 | { | ||
258 | int fd, f = 0; | ||
259 | |||
260 | if(flags.r && flags.w) f = O_RDWR; | ||
261 | else if(flags.r) f = O_RDONLY; | ||
262 | else if(flags.w) f = O_WRONLY; | ||
263 | else f = 0; | ||
264 | |||
265 | if(flags.s) f |= O_SYNC; | ||
266 | if(flags.c) f |= O_CREAT; | ||
267 | if(flags.t) f |= O_TRUNC; | ||
268 | if(flags.e) f |= O_EXCL; | ||
269 | |||
270 | fd = open64(file, f, mode); | ||
271 | if(fd < 0) | ||
272 | return(-errno); | ||
273 | |||
274 | if(flags.cl && fcntl(fd, F_SETFD, 1)){ | ||
275 | os_close_file(fd); | ||
276 | return(-errno); | ||
277 | } | ||
278 | |||
279 | return(fd); | ||
280 | } | ||
281 | |||
282 | int os_connect_socket(char *name) | ||
283 | { | ||
284 | struct sockaddr_un sock; | ||
285 | int fd, err; | ||
286 | |||
287 | sock.sun_family = AF_UNIX; | ||
288 | snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name); | ||
289 | |||
290 | fd = socket(AF_UNIX, SOCK_STREAM, 0); | ||
291 | if(fd < 0) | ||
292 | return(fd); | ||
293 | |||
294 | err = connect(fd, (struct sockaddr *) &sock, sizeof(sock)); | ||
295 | if(err) | ||
296 | return(-errno); | ||
297 | |||
298 | return(fd); | ||
299 | } | ||
300 | |||
301 | void os_close_file(int fd) | ||
302 | { | ||
303 | close(fd); | ||
304 | } | ||
305 | |||
306 | int os_seek_file(int fd, __u64 offset) | ||
307 | { | ||
308 | __u64 actual; | ||
309 | |||
310 | actual = lseek64(fd, offset, SEEK_SET); | ||
311 | if(actual != offset) | ||
312 | return(-errno); | ||
313 | return(0); | ||
314 | } | ||
315 | |||
316 | static int fault_buffer(void *start, int len, | ||
317 | int (*copy_proc)(void *addr, void *buf, int len)) | ||
318 | { | ||
319 | int page = getpagesize(), i; | ||
320 | char c; | ||
321 | |||
322 | for(i = 0; i < len; i += page){ | ||
323 | if((*copy_proc)(start + i, &c, sizeof(c))) | ||
324 | return(-EFAULT); | ||
325 | } | ||
326 | if((len % page) != 0){ | ||
327 | if((*copy_proc)(start + len - 1, &c, sizeof(c))) | ||
328 | return(-EFAULT); | ||
329 | } | ||
330 | return(0); | ||
331 | } | ||
332 | |||
333 | static int file_io(int fd, void *buf, int len, | ||
334 | int (*io_proc)(int fd, void *buf, int len), | ||
335 | int (*copy_user_proc)(void *addr, void *buf, int len)) | ||
336 | { | ||
337 | int n, err; | ||
338 | |||
339 | do { | ||
340 | n = (*io_proc)(fd, buf, len); | ||
341 | if((n < 0) && (errno == EFAULT)){ | ||
342 | err = fault_buffer(buf, len, copy_user_proc); | ||
343 | if(err) | ||
344 | return(err); | ||
345 | n = (*io_proc)(fd, buf, len); | ||
346 | } | ||
347 | } while((n < 0) && (errno == EINTR)); | ||
348 | |||
349 | if(n < 0) | ||
350 | return(-errno); | ||
351 | return(n); | ||
352 | } | ||
353 | |||
354 | int os_read_file(int fd, void *buf, int len) | ||
355 | { | ||
356 | return(file_io(fd, buf, len, (int (*)(int, void *, int)) read, | ||
357 | copy_from_user_proc)); | ||
358 | } | ||
359 | |||
360 | int os_write_file(int fd, const void *buf, int len) | ||
361 | { | ||
362 | return(file_io(fd, (void *) buf, len, | ||
363 | (int (*)(int, void *, int)) write, copy_to_user_proc)); | ||
364 | } | ||
365 | |||
366 | int os_file_size(char *file, long long *size_out) | ||
367 | { | ||
368 | struct uml_stat buf; | ||
369 | int err; | ||
370 | |||
371 | err = os_stat_file(file, &buf); | ||
372 | if(err < 0){ | ||
373 | printk("Couldn't stat \"%s\" : err = %d\n", file, -err); | ||
374 | return(err); | ||
375 | } | ||
376 | |||
377 | if(S_ISBLK(buf.ust_mode)){ | ||
378 | int fd, blocks; | ||
379 | |||
380 | fd = os_open_file(file, of_read(OPENFLAGS()), 0); | ||
381 | if(fd < 0){ | ||
382 | printk("Couldn't open \"%s\", errno = %d\n", file, -fd); | ||
383 | return(fd); | ||
384 | } | ||
385 | if(ioctl(fd, BLKGETSIZE, &blocks) < 0){ | ||
386 | printk("Couldn't get the block size of \"%s\", " | ||
387 | "errno = %d\n", file, errno); | ||
388 | err = -errno; | ||
389 | os_close_file(fd); | ||
390 | return(err); | ||
391 | } | ||
392 | *size_out = ((long long) blocks) * 512; | ||
393 | os_close_file(fd); | ||
394 | return(0); | ||
395 | } | ||
396 | *size_out = buf.ust_size; | ||
397 | return(0); | ||
398 | } | ||
399 | |||
400 | int os_file_modtime(char *file, unsigned long *modtime) | ||
401 | { | ||
402 | struct uml_stat buf; | ||
403 | int err; | ||
404 | |||
405 | err = os_stat_file(file, &buf); | ||
406 | if(err < 0){ | ||
407 | printk("Couldn't stat \"%s\" : err = %d\n", file, -err); | ||
408 | return(err); | ||
409 | } | ||
410 | |||
411 | *modtime = buf.ust_mtime; | ||
412 | return(0); | ||
413 | } | ||
414 | |||
415 | int os_get_exec_close(int fd, int* close_on_exec) | ||
416 | { | ||
417 | int ret; | ||
418 | |||
419 | do { | ||
420 | ret = fcntl(fd, F_GETFD); | ||
421 | } while((ret < 0) && (errno == EINTR)) ; | ||
422 | |||
423 | if(ret < 0) | ||
424 | return(-errno); | ||
425 | |||
426 | *close_on_exec = (ret&FD_CLOEXEC) ? 1 : 0; | ||
427 | return(ret); | ||
428 | } | ||
429 | |||
430 | int os_set_exec_close(int fd, int close_on_exec) | ||
431 | { | ||
432 | int flag, err; | ||
433 | |||
434 | if(close_on_exec) flag = FD_CLOEXEC; | ||
435 | else flag = 0; | ||
436 | |||
437 | do { | ||
438 | err = fcntl(fd, F_SETFD, flag); | ||
439 | } while((err < 0) && (errno == EINTR)) ; | ||
440 | |||
441 | if(err < 0) | ||
442 | return(-errno); | ||
443 | return(err); | ||
444 | } | ||
445 | |||
446 | int os_pipe(int *fds, int stream, int close_on_exec) | ||
447 | { | ||
448 | int err, type = stream ? SOCK_STREAM : SOCK_DGRAM; | ||
449 | |||
450 | err = socketpair(AF_UNIX, type, 0, fds); | ||
451 | if(err < 0) | ||
452 | return(-errno); | ||
453 | |||
454 | if(!close_on_exec) | ||
455 | return(0); | ||
456 | |||
457 | err = os_set_exec_close(fds[0], 1); | ||
458 | if(err < 0) | ||
459 | goto error; | ||
460 | |||
461 | err = os_set_exec_close(fds[1], 1); | ||
462 | if(err < 0) | ||
463 | goto error; | ||
464 | |||
465 | return(0); | ||
466 | |||
467 | error: | ||
468 | printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err); | ||
469 | os_close_file(fds[1]); | ||
470 | os_close_file(fds[0]); | ||
471 | return(err); | ||
472 | } | ||
473 | |||
474 | int os_set_fd_async(int fd, int owner) | ||
475 | { | ||
476 | /* XXX This should do F_GETFL first */ | ||
477 | if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){ | ||
478 | printk("os_set_fd_async : failed to set O_ASYNC and " | ||
479 | "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno); | ||
480 | return(-errno); | ||
481 | } | ||
482 | #ifdef notdef | ||
483 | if(fcntl(fd, F_SETFD, 1) < 0){ | ||
484 | printk("os_set_fd_async : Setting FD_CLOEXEC failed, " | ||
485 | "errno = %d\n", errno); | ||
486 | } | ||
487 | #endif | ||
488 | |||
489 | if((fcntl(fd, F_SETSIG, SIGIO) < 0) || | ||
490 | (fcntl(fd, F_SETOWN, owner) < 0)){ | ||
491 | printk("os_set_fd_async : Failed to fcntl F_SETOWN " | ||
492 | "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd, | ||
493 | owner, errno); | ||
494 | return(-errno); | ||
495 | } | ||
496 | |||
497 | return(0); | ||
498 | } | ||
499 | |||
500 | int os_clear_fd_async(int fd) | ||
501 | { | ||
502 | int flags = fcntl(fd, F_GETFL); | ||
503 | |||
504 | flags &= ~(O_ASYNC | O_NONBLOCK); | ||
505 | if(fcntl(fd, F_SETFL, flags) < 0) | ||
506 | return(-errno); | ||
507 | return(0); | ||
508 | } | ||
509 | |||
510 | int os_set_fd_block(int fd, int blocking) | ||
511 | { | ||
512 | int flags; | ||
513 | |||
514 | flags = fcntl(fd, F_GETFL); | ||
515 | |||
516 | if(blocking) flags &= ~O_NONBLOCK; | ||
517 | else flags |= O_NONBLOCK; | ||
518 | |||
519 | if(fcntl(fd, F_SETFL, flags) < 0){ | ||
520 | printk("Failed to change blocking on fd # %d, errno = %d\n", | ||
521 | fd, errno); | ||
522 | return(-errno); | ||
523 | } | ||
524 | return(0); | ||
525 | } | ||
526 | |||
527 | int os_accept_connection(int fd) | ||
528 | { | ||
529 | int new; | ||
530 | |||
531 | new = accept(fd, NULL, 0); | ||
532 | if(new < 0) | ||
533 | return(-errno); | ||
534 | return(new); | ||
535 | } | ||
536 | |||
537 | #ifndef SHUT_RD | ||
538 | #define SHUT_RD 0 | ||
539 | #endif | ||
540 | |||
541 | #ifndef SHUT_WR | ||
542 | #define SHUT_WR 1 | ||
543 | #endif | ||
544 | |||
545 | #ifndef SHUT_RDWR | ||
546 | #define SHUT_RDWR 2 | ||
547 | #endif | ||
548 | |||
549 | int os_shutdown_socket(int fd, int r, int w) | ||
550 | { | ||
551 | int what, err; | ||
552 | |||
553 | if(r && w) what = SHUT_RDWR; | ||
554 | else if(r) what = SHUT_RD; | ||
555 | else if(w) what = SHUT_WR; | ||
556 | else { | ||
557 | printk("os_shutdown_socket : neither r or w was set\n"); | ||
558 | return(-EINVAL); | ||
559 | } | ||
560 | err = shutdown(fd, what); | ||
561 | if(err < 0) | ||
562 | return(-errno); | ||
563 | return(0); | ||
564 | } | ||
565 | |||
566 | int os_rcv_fd(int fd, int *helper_pid_out) | ||
567 | { | ||
568 | int new, n; | ||
569 | char buf[CMSG_SPACE(sizeof(new))]; | ||
570 | struct msghdr msg; | ||
571 | struct cmsghdr *cmsg; | ||
572 | struct iovec iov; | ||
573 | |||
574 | msg.msg_name = NULL; | ||
575 | msg.msg_namelen = 0; | ||
576 | iov = ((struct iovec) { .iov_base = helper_pid_out, | ||
577 | .iov_len = sizeof(*helper_pid_out) }); | ||
578 | msg.msg_iov = &iov; | ||
579 | msg.msg_iovlen = 1; | ||
580 | msg.msg_control = buf; | ||
581 | msg.msg_controllen = sizeof(buf); | ||
582 | msg.msg_flags = 0; | ||
583 | |||
584 | n = recvmsg(fd, &msg, 0); | ||
585 | if(n < 0) | ||
586 | return(-errno); | ||
587 | |||
588 | else if(n != sizeof(iov.iov_len)) | ||
589 | *helper_pid_out = -1; | ||
590 | |||
591 | cmsg = CMSG_FIRSTHDR(&msg); | ||
592 | if(cmsg == NULL){ | ||
593 | printk("rcv_fd didn't receive anything, error = %d\n", errno); | ||
594 | return(-1); | ||
595 | } | ||
596 | if((cmsg->cmsg_level != SOL_SOCKET) || | ||
597 | (cmsg->cmsg_type != SCM_RIGHTS)){ | ||
598 | printk("rcv_fd didn't receive a descriptor\n"); | ||
599 | return(-1); | ||
600 | } | ||
601 | |||
602 | new = ((int *) CMSG_DATA(cmsg))[0]; | ||
603 | return(new); | ||
604 | } | ||
605 | |||
606 | int os_create_unix_socket(char *file, int len, int close_on_exec) | ||
607 | { | ||
608 | struct sockaddr_un addr; | ||
609 | int sock, err; | ||
610 | |||
611 | sock = socket(PF_UNIX, SOCK_DGRAM, 0); | ||
612 | if (sock < 0){ | ||
613 | printk("create_unix_socket - socket failed, errno = %d\n", | ||
614 | errno); | ||
615 | return(-errno); | ||
616 | } | ||
617 | |||
618 | if(close_on_exec) { | ||
619 | err = os_set_exec_close(sock, 1); | ||
620 | if(err < 0) | ||
621 | printk("create_unix_socket : close_on_exec failed, " | ||
622 | "err = %d", -err); | ||
623 | } | ||
624 | |||
625 | addr.sun_family = AF_UNIX; | ||
626 | |||
627 | /* XXX Be more careful about overflow */ | ||
628 | snprintf(addr.sun_path, len, "%s", file); | ||
629 | |||
630 | err = bind(sock, (struct sockaddr *) &addr, sizeof(addr)); | ||
631 | if (err < 0){ | ||
632 | printk("create_listening_socket at '%s' - bind failed, " | ||
633 | "errno = %d\n", file, errno); | ||
634 | return(-errno); | ||
635 | } | ||
636 | |||
637 | return(sock); | ||
638 | } | ||
639 | |||
640 | void os_flush_stdout(void) | ||
641 | { | ||
642 | fflush(stdout); | ||
643 | } | ||
644 | |||
645 | int os_lock_file(int fd, int excl) | ||
646 | { | ||
647 | int type = excl ? F_WRLCK : F_RDLCK; | ||
648 | struct flock lock = ((struct flock) { .l_type = type, | ||
649 | .l_whence = SEEK_SET, | ||
650 | .l_start = 0, | ||
651 | .l_len = 0 } ); | ||
652 | int err, save; | ||
653 | |||
654 | err = fcntl(fd, F_SETLK, &lock); | ||
655 | if(!err) | ||
656 | goto out; | ||
657 | |||
658 | save = -errno; | ||
659 | err = fcntl(fd, F_GETLK, &lock); | ||
660 | if(err){ | ||
661 | err = -errno; | ||
662 | goto out; | ||
663 | } | ||
664 | |||
665 | printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid); | ||
666 | err = save; | ||
667 | out: | ||
668 | return(err); | ||
669 | } | ||
670 | |||
671 | /* | ||
672 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
673 | * Emacs will notice this stuff at the end of the file and automatically | ||
674 | * adjust the settings for this buffer only. This must remain at the end | ||
675 | * of the file. | ||
676 | * --------------------------------------------------------------------------- | ||
677 | * Local variables: | ||
678 | * c-file-style: "linux" | ||
679 | * End: | ||
680 | */ | ||
diff --git a/arch/um/os-Linux/include/file.h b/arch/um/os-Linux/include/file.h new file mode 100644 index 000000000000..d82711efacfa --- /dev/null +++ b/arch/um/os-Linux/include/file.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __OS_FILE_H__ | ||
7 | #define __OS_FILE_H__ | ||
8 | |||
9 | #define DEV_NULL "/dev/null" | ||
10 | |||
11 | #endif | ||
12 | |||
13 | /* | ||
14 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
15 | * Emacs will notice this stuff at the end of the file and automatically | ||
16 | * adjust the settings for this buffer only. This must remain at the end | ||
17 | * of the file. | ||
18 | * --------------------------------------------------------------------------- | ||
19 | * Local variables: | ||
20 | * c-file-style: "linux" | ||
21 | * End: | ||
22 | */ | ||
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c new file mode 100644 index 000000000000..ba9ca1cc790a --- /dev/null +++ b/arch/um/os-Linux/process.c | |||
@@ -0,0 +1,171 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@addtoit.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <unistd.h> | ||
7 | #include <stdio.h> | ||
8 | #include <errno.h> | ||
9 | #include <signal.h> | ||
10 | #include <linux/unistd.h> | ||
11 | #include <sys/mman.h> | ||
12 | #include <sys/wait.h> | ||
13 | #include "ptrace_user.h" | ||
14 | #include "os.h" | ||
15 | #include "user.h" | ||
16 | #include "user_util.h" | ||
17 | |||
18 | #define ARBITRARY_ADDR -1 | ||
19 | #define FAILURE_PID -1 | ||
20 | |||
21 | #define STAT_PATH_LEN sizeof("/proc/#######/stat\0") | ||
22 | #define COMM_SCANF "%*[^)])" | ||
23 | |||
24 | unsigned long os_process_pc(int pid) | ||
25 | { | ||
26 | char proc_stat[STAT_PATH_LEN], buf[256]; | ||
27 | unsigned long pc; | ||
28 | int fd, err; | ||
29 | |||
30 | sprintf(proc_stat, "/proc/%d/stat", pid); | ||
31 | fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0); | ||
32 | if(fd < 0){ | ||
33 | printk("os_process_pc - couldn't open '%s', err = %d\n", | ||
34 | proc_stat, -fd); | ||
35 | return(ARBITRARY_ADDR); | ||
36 | } | ||
37 | err = os_read_file(fd, buf, sizeof(buf)); | ||
38 | if(err < 0){ | ||
39 | printk("os_process_pc - couldn't read '%s', err = %d\n", | ||
40 | proc_stat, -err); | ||
41 | os_close_file(fd); | ||
42 | return(ARBITRARY_ADDR); | ||
43 | } | ||
44 | os_close_file(fd); | ||
45 | pc = ARBITRARY_ADDR; | ||
46 | if(sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d " | ||
47 | "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d " | ||
48 | "%*d %*d %*d %*d %*d %lu", &pc) != 1){ | ||
49 | printk("os_process_pc - couldn't find pc in '%s'\n", buf); | ||
50 | } | ||
51 | return(pc); | ||
52 | } | ||
53 | |||
54 | int os_process_parent(int pid) | ||
55 | { | ||
56 | char stat[STAT_PATH_LEN]; | ||
57 | char data[256]; | ||
58 | int parent, n, fd; | ||
59 | |||
60 | if(pid == -1) return(-1); | ||
61 | |||
62 | snprintf(stat, sizeof(stat), "/proc/%d/stat", pid); | ||
63 | fd = os_open_file(stat, of_read(OPENFLAGS()), 0); | ||
64 | if(fd < 0){ | ||
65 | printk("Couldn't open '%s', err = %d\n", stat, -fd); | ||
66 | return(FAILURE_PID); | ||
67 | } | ||
68 | |||
69 | n = os_read_file(fd, data, sizeof(data)); | ||
70 | os_close_file(fd); | ||
71 | |||
72 | if(n < 0){ | ||
73 | printk("Couldn't read '%s', err = %d\n", stat, -n); | ||
74 | return(FAILURE_PID); | ||
75 | } | ||
76 | |||
77 | parent = FAILURE_PID; | ||
78 | n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent); | ||
79 | if(n != 1) | ||
80 | printk("Failed to scan '%s'\n", data); | ||
81 | |||
82 | return(parent); | ||
83 | } | ||
84 | |||
85 | void os_stop_process(int pid) | ||
86 | { | ||
87 | kill(pid, SIGSTOP); | ||
88 | } | ||
89 | |||
90 | void os_kill_process(int pid, int reap_child) | ||
91 | { | ||
92 | kill(pid, SIGKILL); | ||
93 | if(reap_child) | ||
94 | CATCH_EINTR(waitpid(pid, NULL, 0)); | ||
95 | |||
96 | } | ||
97 | |||
98 | /* Kill off a ptraced child by all means available. kill it normally first, | ||
99 | * then PTRACE_KILL it, then PTRACE_CONT it in case it's in a run state from | ||
100 | * which it can't exit directly. | ||
101 | */ | ||
102 | |||
103 | void os_kill_ptraced_process(int pid, int reap_child) | ||
104 | { | ||
105 | kill(pid, SIGKILL); | ||
106 | ptrace(PTRACE_KILL, pid); | ||
107 | ptrace(PTRACE_CONT, pid); | ||
108 | if(reap_child) | ||
109 | CATCH_EINTR(waitpid(pid, NULL, 0)); | ||
110 | } | ||
111 | |||
112 | void os_usr1_process(int pid) | ||
113 | { | ||
114 | kill(pid, SIGUSR1); | ||
115 | } | ||
116 | |||
117 | /*Don't use the glibc version, which caches the result in TLS. It misses some | ||
118 | * syscalls, and also breaks with clone(), which does not unshare the TLS.*/ | ||
119 | inline _syscall0(pid_t, getpid) | ||
120 | |||
121 | int os_getpid(void) | ||
122 | { | ||
123 | return(getpid()); | ||
124 | } | ||
125 | |||
126 | int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, | ||
127 | int r, int w, int x) | ||
128 | { | ||
129 | void *loc; | ||
130 | int prot; | ||
131 | |||
132 | prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | | ||
133 | (x ? PROT_EXEC : 0); | ||
134 | |||
135 | loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, | ||
136 | fd, off); | ||
137 | if(loc == MAP_FAILED) | ||
138 | return(-errno); | ||
139 | return(0); | ||
140 | } | ||
141 | |||
142 | int os_protect_memory(void *addr, unsigned long len, int r, int w, int x) | ||
143 | { | ||
144 | int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | | ||
145 | (x ? PROT_EXEC : 0)); | ||
146 | |||
147 | if(mprotect(addr, len, prot) < 0) | ||
148 | return(-errno); | ||
149 | return(0); | ||
150 | } | ||
151 | |||
152 | int os_unmap_memory(void *addr, int len) | ||
153 | { | ||
154 | int err; | ||
155 | |||
156 | err = munmap(addr, len); | ||
157 | if(err < 0) | ||
158 | return(-errno); | ||
159 | return(0); | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
164 | * Emacs will notice this stuff at the end of the file and automatically | ||
165 | * adjust the settings for this buffer only. This must remain at the end | ||
166 | * of the file. | ||
167 | * --------------------------------------------------------------------------- | ||
168 | * Local variables: | ||
169 | * c-file-style: "linux" | ||
170 | * End: | ||
171 | */ | ||
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c new file mode 100644 index 000000000000..7eac1baf5975 --- /dev/null +++ b/arch/um/os-Linux/signal.c | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004 PathScale, Inc | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <signal.h> | ||
7 | #include "time_user.h" | ||
8 | #include "mode.h" | ||
9 | #include "sysdep/signal.h" | ||
10 | |||
11 | void sig_handler(int sig) | ||
12 | { | ||
13 | struct sigcontext *sc; | ||
14 | |||
15 | ARCH_GET_SIGCONTEXT(sc, sig); | ||
16 | CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, | ||
17 | sig, sc); | ||
18 | } | ||
19 | |||
20 | extern int timer_irq_inited; | ||
21 | |||
22 | void alarm_handler(int sig) | ||
23 | { | ||
24 | struct sigcontext *sc; | ||
25 | |||
26 | ARCH_GET_SIGCONTEXT(sc, sig); | ||
27 | if(!timer_irq_inited) return; | ||
28 | |||
29 | if(sig == SIGALRM) | ||
30 | switch_timers(0); | ||
31 | |||
32 | CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, | ||
33 | sig, sc); | ||
34 | |||
35 | if(sig == SIGALRM) | ||
36 | switch_timers(1); | ||
37 | } | ||
38 | |||
39 | /* | ||
40 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
41 | * Emacs will notice this stuff at the end of the file and automatically | ||
42 | * adjust the settings for this buffer only. This must remain at the end | ||
43 | * of the file. | ||
44 | * --------------------------------------------------------------------------- | ||
45 | * Local variables: | ||
46 | * c-file-style: "linux" | ||
47 | * End: | ||
48 | */ | ||
diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile new file mode 100644 index 000000000000..340ef26f5944 --- /dev/null +++ b/arch/um/os-Linux/sys-i386/Makefile | |||
@@ -0,0 +1,10 @@ | |||
1 | # | ||
2 | # Copyright (C) 2000 Jeff Dike (jdike@karaya.com) | ||
3 | # Licensed under the GPL | ||
4 | # | ||
5 | |||
6 | obj-$(CONFIG_MODE_SKAS) = registers.o | ||
7 | |||
8 | USER_OBJS := $(obj-y) | ||
9 | |||
10 | include arch/um/scripts/Makefile.rules | ||
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c new file mode 100644 index 000000000000..148645b14480 --- /dev/null +++ b/arch/um/os-Linux/sys-i386/registers.c | |||
@@ -0,0 +1,132 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004 PathScale, Inc | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <errno.h> | ||
7 | #include <string.h> | ||
8 | #include "sysdep/ptrace_user.h" | ||
9 | #include "sysdep/ptrace.h" | ||
10 | #include "uml-config.h" | ||
11 | #include "skas_ptregs.h" | ||
12 | #include "registers.h" | ||
13 | #include "user.h" | ||
14 | |||
15 | /* These are set once at boot time and not changed thereafter */ | ||
16 | |||
17 | static unsigned long exec_regs[HOST_FRAME_SIZE]; | ||
18 | static unsigned long exec_fp_regs[HOST_FP_SIZE]; | ||
19 | static unsigned long exec_fpx_regs[HOST_XFP_SIZE]; | ||
20 | static int have_fpx_regs = 1; | ||
21 | |||
22 | void init_thread_registers(union uml_pt_regs *to) | ||
23 | { | ||
24 | memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs)); | ||
25 | memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp)); | ||
26 | if(have_fpx_regs) | ||
27 | memcpy(to->skas.xfp, exec_fpx_regs, sizeof(to->skas.xfp)); | ||
28 | } | ||
29 | |||
30 | /* XXX These need to use [GS]ETFPXREGS and copy_sc_{to,from}_user_skas needs | ||
31 | * to pass in a sufficiently large buffer | ||
32 | */ | ||
33 | int save_fp_registers(int pid, unsigned long *fp_regs) | ||
34 | { | ||
35 | if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) | ||
36 | return(-errno); | ||
37 | return(0); | ||
38 | } | ||
39 | |||
40 | int restore_fp_registers(int pid, unsigned long *fp_regs) | ||
41 | { | ||
42 | if(ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) | ||
43 | return(-errno); | ||
44 | return(0); | ||
45 | } | ||
46 | |||
47 | static int move_registers(int pid, int int_op, union uml_pt_regs *regs, | ||
48 | int fp_op, unsigned long *fp_regs) | ||
49 | { | ||
50 | if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) | ||
51 | return(-errno); | ||
52 | |||
53 | if(ptrace(fp_op, pid, 0, fp_regs) < 0) | ||
54 | return(-errno); | ||
55 | |||
56 | return(0); | ||
57 | } | ||
58 | |||
59 | void save_registers(int pid, union uml_pt_regs *regs) | ||
60 | { | ||
61 | unsigned long *fp_regs; | ||
62 | int err, fp_op; | ||
63 | |||
64 | if(have_fpx_regs){ | ||
65 | fp_op = PTRACE_GETFPXREGS; | ||
66 | fp_regs = regs->skas.xfp; | ||
67 | } | ||
68 | else { | ||
69 | fp_op = PTRACE_GETFPREGS; | ||
70 | fp_regs = regs->skas.fp; | ||
71 | } | ||
72 | |||
73 | err = move_registers(pid, PTRACE_GETREGS, regs, fp_op, fp_regs); | ||
74 | if(err) | ||
75 | panic("save_registers - saving registers failed, errno = %d\n", | ||
76 | -err); | ||
77 | } | ||
78 | |||
79 | void restore_registers(int pid, union uml_pt_regs *regs) | ||
80 | { | ||
81 | unsigned long *fp_regs; | ||
82 | int err, fp_op; | ||
83 | |||
84 | if(have_fpx_regs){ | ||
85 | fp_op = PTRACE_SETFPXREGS; | ||
86 | fp_regs = regs->skas.xfp; | ||
87 | } | ||
88 | else { | ||
89 | fp_op = PTRACE_SETFPREGS; | ||
90 | fp_regs = regs->skas.fp; | ||
91 | } | ||
92 | |||
93 | err = move_registers(pid, PTRACE_SETREGS, regs, fp_op, fp_regs); | ||
94 | if(err) | ||
95 | panic("restore_registers - saving registers failed, " | ||
96 | "errno = %d\n", -err); | ||
97 | } | ||
98 | |||
99 | void init_registers(int pid) | ||
100 | { | ||
101 | int err; | ||
102 | |||
103 | err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); | ||
104 | if(err) | ||
105 | panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", | ||
106 | err); | ||
107 | |||
108 | err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs); | ||
109 | if(!err) | ||
110 | return; | ||
111 | |||
112 | have_fpx_regs = 0; | ||
113 | if(err != EIO) | ||
114 | panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", | ||
115 | err); | ||
116 | |||
117 | err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs); | ||
118 | if(err) | ||
119 | panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", | ||
120 | err); | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
125 | * Emacs will notice this stuff at the end of the file and automatically | ||
126 | * adjust the settings for this buffer only. This must remain at the end | ||
127 | * of the file. | ||
128 | * --------------------------------------------------------------------------- | ||
129 | * Local variables: | ||
130 | * c-file-style: "linux" | ||
131 | * End: | ||
132 | */ | ||
diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile new file mode 100644 index 000000000000..340ef26f5944 --- /dev/null +++ b/arch/um/os-Linux/sys-x86_64/Makefile | |||
@@ -0,0 +1,10 @@ | |||
1 | # | ||
2 | # Copyright (C) 2000 Jeff Dike (jdike@karaya.com) | ||
3 | # Licensed under the GPL | ||
4 | # | ||
5 | |||
6 | obj-$(CONFIG_MODE_SKAS) = registers.o | ||
7 | |||
8 | USER_OBJS := $(obj-y) | ||
9 | |||
10 | include arch/um/scripts/Makefile.rules | ||
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c new file mode 100644 index 000000000000..6286c974bbeb --- /dev/null +++ b/arch/um/os-Linux/sys-x86_64/registers.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004 PathScale, Inc | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <errno.h> | ||
7 | #include <string.h> | ||
8 | #include "ptrace_user.h" | ||
9 | #include "uml-config.h" | ||
10 | #include "skas_ptregs.h" | ||
11 | #include "registers.h" | ||
12 | #include "user.h" | ||
13 | |||
14 | /* These are set once at boot time and not changed thereafter */ | ||
15 | |||
16 | static unsigned long exec_regs[HOST_FRAME_SIZE]; | ||
17 | static unsigned long exec_fp_regs[HOST_FP_SIZE]; | ||
18 | |||
19 | void init_thread_registers(union uml_pt_regs *to) | ||
20 | { | ||
21 | memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs)); | ||
22 | memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp)); | ||
23 | } | ||
24 | |||
25 | static int move_registers(int pid, int int_op, int fp_op, | ||
26 | union uml_pt_regs *regs) | ||
27 | { | ||
28 | if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) | ||
29 | return(-errno); | ||
30 | |||
31 | if(ptrace(fp_op, pid, 0, regs->skas.fp) < 0) | ||
32 | return(-errno); | ||
33 | |||
34 | return(0); | ||
35 | } | ||
36 | |||
37 | void save_registers(int pid, union uml_pt_regs *regs) | ||
38 | { | ||
39 | int err; | ||
40 | |||
41 | err = move_registers(pid, PTRACE_GETREGS, PTRACE_GETFPREGS, regs); | ||
42 | if(err) | ||
43 | panic("save_registers - saving registers failed, errno = %d\n", | ||
44 | -err); | ||
45 | } | ||
46 | |||
47 | void restore_registers(int pid, union uml_pt_regs *regs) | ||
48 | { | ||
49 | int err; | ||
50 | |||
51 | err = move_registers(pid, PTRACE_SETREGS, PTRACE_SETFPREGS, regs); | ||
52 | if(err) | ||
53 | panic("restore_registers - saving registers failed, " | ||
54 | "errno = %d\n", -err); | ||
55 | } | ||
56 | |||
57 | void init_registers(int pid) | ||
58 | { | ||
59 | int err; | ||
60 | |||
61 | err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); | ||
62 | if(err) | ||
63 | panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", | ||
64 | err); | ||
65 | |||
66 | err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs); | ||
67 | if(err) | ||
68 | panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", | ||
69 | err); | ||
70 | } | ||
71 | |||
72 | /* | ||
73 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
74 | * Emacs will notice this stuff at the end of the file and automatically | ||
75 | * adjust the settings for this buffer only. This must remain at the end | ||
76 | * of the file. | ||
77 | * --------------------------------------------------------------------------- | ||
78 | * Local variables: | ||
79 | * c-file-style: "linux" | ||
80 | * End: | ||
81 | */ | ||
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c new file mode 100644 index 000000000000..cf30a39bc484 --- /dev/null +++ b/arch/um/os-Linux/time.c | |||
@@ -0,0 +1,21 @@ | |||
1 | #include <stdlib.h> | ||
2 | #include <sys/time.h> | ||
3 | |||
4 | unsigned long long os_usecs(void) | ||
5 | { | ||
6 | struct timeval tv; | ||
7 | |||
8 | gettimeofday(&tv, NULL); | ||
9 | return((unsigned long long) tv.tv_sec * 1000000 + tv.tv_usec); | ||
10 | } | ||
11 | |||
12 | /* | ||
13 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
14 | * Emacs will notice this stuff at the end of the file and automatically | ||
15 | * adjust the settings for this buffer only. This must remain at the end | ||
16 | * of the file. | ||
17 | * --------------------------------------------------------------------------- | ||
18 | * Local variables: | ||
19 | * c-file-style: "linux" | ||
20 | * End: | ||
21 | */ | ||
diff --git a/arch/um/os-Linux/tty.c b/arch/um/os-Linux/tty.c new file mode 100644 index 000000000000..4cfdd18ea1ef --- /dev/null +++ b/arch/um/os-Linux/tty.c | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stdlib.h> | ||
7 | #include <errno.h> | ||
8 | #include "os.h" | ||
9 | #include "user.h" | ||
10 | #include "kern_util.h" | ||
11 | |||
12 | struct grantpt_info { | ||
13 | int fd; | ||
14 | int res; | ||
15 | int err; | ||
16 | }; | ||
17 | |||
18 | static void grantpt_cb(void *arg) | ||
19 | { | ||
20 | struct grantpt_info *info = arg; | ||
21 | |||
22 | info->res = grantpt(info->fd); | ||
23 | info->err = errno; | ||
24 | } | ||
25 | |||
26 | int get_pty(void) | ||
27 | { | ||
28 | struct grantpt_info info; | ||
29 | int fd; | ||
30 | |||
31 | fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0); | ||
32 | if(fd < 0){ | ||
33 | printk("get_pty : Couldn't open /dev/ptmx - err = %d\n", -fd); | ||
34 | return(fd); | ||
35 | } | ||
36 | |||
37 | info.fd = fd; | ||
38 | initial_thread_cb(grantpt_cb, &info); | ||
39 | |||
40 | if(info.res < 0){ | ||
41 | printk("get_pty : Couldn't grant pty - errno = %d\n", | ||
42 | -info.err); | ||
43 | return(-1); | ||
44 | } | ||
45 | if(unlockpt(fd) < 0){ | ||
46 | printk("get_pty : Couldn't unlock pty - errno = %d\n", errno); | ||
47 | return(-1); | ||
48 | } | ||
49 | return(fd); | ||
50 | } | ||
51 | |||
52 | /* | ||
53 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
54 | * Emacs will notice this stuff at the end of the file and automatically | ||
55 | * adjust the settings for this buffer only. This must remain at the end | ||
56 | * of the file. | ||
57 | * --------------------------------------------------------------------------- | ||
58 | * Local variables: | ||
59 | * c-file-style: "linux" | ||
60 | * End: | ||
61 | */ | ||
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c new file mode 100644 index 000000000000..75d7af9ae1d2 --- /dev/null +++ b/arch/um/os-Linux/user_syms.c | |||
@@ -0,0 +1,95 @@ | |||
1 | #include "linux/types.h" | ||
2 | #include "linux/module.h" | ||
3 | |||
4 | /* Some of this are builtin function (some are not but could in the future), | ||
5 | * so I *must* declare good prototypes for them and then EXPORT them. | ||
6 | * The kernel code uses the macro defined by include/linux/string.h, | ||
7 | * so I undef macros; the userspace code does not include that and I | ||
8 | * add an EXPORT for the glibc one.*/ | ||
9 | |||
10 | #undef strlen | ||
11 | #undef strstr | ||
12 | #undef memcpy | ||
13 | #undef memset | ||
14 | |||
15 | extern size_t strlen(const char *); | ||
16 | extern void *memcpy(void *, const void *, size_t); | ||
17 | extern void *memmove(void *, const void *, size_t); | ||
18 | extern void *memset(void *, int, size_t); | ||
19 | extern int printf(const char *, ...); | ||
20 | |||
21 | EXPORT_SYMBOL(strlen); | ||
22 | EXPORT_SYMBOL(memcpy); | ||
23 | EXPORT_SYMBOL(memmove); | ||
24 | EXPORT_SYMBOL(memset); | ||
25 | EXPORT_SYMBOL(printf); | ||
26 | |||
27 | EXPORT_SYMBOL(strstr); | ||
28 | |||
29 | /* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms. | ||
30 | * However, the modules will use the CRC defined *here*, no matter if it is | ||
31 | * good; so the versions of these symbols will always match | ||
32 | */ | ||
33 | #define EXPORT_SYMBOL_PROTO(sym) \ | ||
34 | int sym(void); \ | ||
35 | EXPORT_SYMBOL(sym); | ||
36 | |||
37 | #ifdef SUBARCH_i386 | ||
38 | EXPORT_SYMBOL(vsyscall_ehdr); | ||
39 | EXPORT_SYMBOL(vsyscall_end); | ||
40 | #endif | ||
41 | |||
42 | EXPORT_SYMBOL_PROTO(__errno_location); | ||
43 | |||
44 | EXPORT_SYMBOL_PROTO(access); | ||
45 | EXPORT_SYMBOL_PROTO(open); | ||
46 | EXPORT_SYMBOL_PROTO(open64); | ||
47 | EXPORT_SYMBOL_PROTO(close); | ||
48 | EXPORT_SYMBOL_PROTO(read); | ||
49 | EXPORT_SYMBOL_PROTO(write); | ||
50 | EXPORT_SYMBOL_PROTO(dup2); | ||
51 | EXPORT_SYMBOL_PROTO(__xstat); | ||
52 | EXPORT_SYMBOL_PROTO(__lxstat); | ||
53 | EXPORT_SYMBOL_PROTO(__lxstat64); | ||
54 | EXPORT_SYMBOL_PROTO(lseek); | ||
55 | EXPORT_SYMBOL_PROTO(lseek64); | ||
56 | EXPORT_SYMBOL_PROTO(chown); | ||
57 | EXPORT_SYMBOL_PROTO(truncate); | ||
58 | EXPORT_SYMBOL_PROTO(utime); | ||
59 | EXPORT_SYMBOL_PROTO(chmod); | ||
60 | EXPORT_SYMBOL_PROTO(rename); | ||
61 | EXPORT_SYMBOL_PROTO(__xmknod); | ||
62 | |||
63 | EXPORT_SYMBOL_PROTO(symlink); | ||
64 | EXPORT_SYMBOL_PROTO(link); | ||
65 | EXPORT_SYMBOL_PROTO(unlink); | ||
66 | EXPORT_SYMBOL_PROTO(readlink); | ||
67 | |||
68 | EXPORT_SYMBOL_PROTO(mkdir); | ||
69 | EXPORT_SYMBOL_PROTO(rmdir); | ||
70 | EXPORT_SYMBOL_PROTO(opendir); | ||
71 | EXPORT_SYMBOL_PROTO(readdir); | ||
72 | EXPORT_SYMBOL_PROTO(closedir); | ||
73 | EXPORT_SYMBOL_PROTO(seekdir); | ||
74 | EXPORT_SYMBOL_PROTO(telldir); | ||
75 | |||
76 | EXPORT_SYMBOL_PROTO(ioctl); | ||
77 | |||
78 | EXPORT_SYMBOL_PROTO(pread64); | ||
79 | EXPORT_SYMBOL_PROTO(pwrite64); | ||
80 | |||
81 | EXPORT_SYMBOL_PROTO(statfs); | ||
82 | EXPORT_SYMBOL_PROTO(statfs64); | ||
83 | |||
84 | EXPORT_SYMBOL_PROTO(getuid); | ||
85 | |||
86 | /* | ||
87 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
88 | * Emacs will notice this stuff at the end of the file and automatically | ||
89 | * adjust the settings for this buffer only. This must remain at the end | ||
90 | * of the file. | ||
91 | * --------------------------------------------------------------------------- | ||
92 | * Local variables: | ||
93 | * c-file-style: "linux" | ||
94 | * End: | ||
95 | */ | ||
diff --git a/arch/um/os-Linux/util/Makefile b/arch/um/os-Linux/util/Makefile new file mode 100644 index 000000000000..fb00ddf969bd --- /dev/null +++ b/arch/um/os-Linux/util/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | hostprogs-y := mk_user_constants | ||
2 | always := $(hostprogs-y) | ||
3 | |||
4 | mk_user_constants-objs := mk_user_constants.o | ||
diff --git a/arch/um/os-Linux/util/mk_user_constants.c b/arch/um/os-Linux/util/mk_user_constants.c new file mode 100644 index 000000000000..0933518aa8bd --- /dev/null +++ b/arch/um/os-Linux/util/mk_user_constants.c | |||
@@ -0,0 +1,29 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <asm/types.h> | ||
3 | /* For some reason, x86_64 nowhere defines u64 and u32, even though they're | ||
4 | * used throughout the headers. | ||
5 | */ | ||
6 | typedef __u64 u64; | ||
7 | typedef __u32 u32; | ||
8 | #include <asm/user.h> | ||
9 | |||
10 | int main(int argc, char **argv) | ||
11 | { | ||
12 | printf("/*\n"); | ||
13 | printf(" * Generated by mk_user_constants\n"); | ||
14 | printf(" */\n"); | ||
15 | printf("\n"); | ||
16 | printf("#ifndef __UM_USER_CONSTANTS_H\n"); | ||
17 | printf("#define __UM_USER_CONSTANTS_H\n"); | ||
18 | printf("\n"); | ||
19 | /* I'd like to use FRAME_SIZE from ptrace.h here, but that's wrong on | ||
20 | * x86_64 (216 vs 168 bytes). user_regs_struct is the correct size on | ||
21 | * both x86_64 and i386. | ||
22 | */ | ||
23 | printf("#define UM_FRAME_SIZE %d\n", (int) sizeof(struct user_regs_struct)); | ||
24 | |||
25 | printf("\n"); | ||
26 | printf("#endif\n"); | ||
27 | |||
28 | return(0); | ||
29 | } | ||