diff options
Diffstat (limited to 'arch/um')
196 files changed, 5130 insertions, 10047 deletions
diff --git a/arch/um/Kconfig b/arch/um/Kconfig index e6ff30266542..740d8a922e48 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig | |||
@@ -55,6 +55,14 @@ config GENERIC_BUG | |||
55 | default y | 55 | default y |
56 | depends on BUG | 56 | depends on BUG |
57 | 57 | ||
58 | config GENERIC_TIME | ||
59 | bool | ||
60 | default y | ||
61 | |||
62 | config GENERIC_CLOCKEVENTS | ||
63 | bool | ||
64 | default y | ||
65 | |||
58 | # Used in kernel/irq/manage.c and include/linux/irq.h | 66 | # Used in kernel/irq/manage.c and include/linux/irq.h |
59 | config IRQ_RELEASE_METHOD | 67 | config IRQ_RELEASE_METHOD |
60 | bool | 68 | bool |
@@ -62,63 +70,25 @@ config IRQ_RELEASE_METHOD | |||
62 | 70 | ||
63 | menu "UML-specific options" | 71 | menu "UML-specific options" |
64 | 72 | ||
65 | config MODE_TT | ||
66 | bool "Tracing thread support (DEPRECATED)" | ||
67 | default n | ||
68 | depends on BROKEN | ||
69 | help | ||
70 | This option controls whether tracing thread support is compiled | ||
71 | into UML. This option is largely obsolete, given that skas0 provides | ||
72 | skas security and performance without needing to patch the host. | ||
73 | It is safe to say 'N' here; saying 'Y' may cause additional problems | ||
74 | with the resulting binary even if you run UML in SKAS mode, and running | ||
75 | in TT mode is strongly *NOT RECOMMENDED*. | ||
76 | |||
77 | config STATIC_LINK | 73 | config STATIC_LINK |
78 | bool "Force a static link" | 74 | bool "Force a static link" |
79 | default n | 75 | default n |
80 | depends on !MODE_TT | ||
81 | help | 76 | help |
82 | If CONFIG_MODE_TT is disabled, then this option gives you the ability | 77 | This option gives you the ability to force a static link of UML. |
83 | to force a static link of UML. Normally, if only skas mode is built | 78 | Normally, UML is linked as a shared binary. This is inconvenient for |
84 | in to UML, it will be linked as a shared binary. This is inconvenient | 79 | use in a chroot jail. So, if you intend to run UML inside a chroot, |
85 | for use in a chroot jail. So, if you intend to run UML inside a | 80 | you probably want to say Y here. |
86 | chroot, and you disable CONFIG_MODE_TT, you probably want to say Y | 81 | Additionally, this option enables using higher memory spaces (up to |
87 | here. | 82 | 2.75G) for UML. |
88 | Additionally, this option enables using higher memory spaces (up to | ||
89 | 2.75G) for UML - disabling CONFIG_MODE_TT and enabling this option leads | ||
90 | to best results for this. | ||
91 | |||
92 | config KERNEL_HALF_GIGS | ||
93 | int "Kernel address space size (in .5G units)" | ||
94 | default "1" | ||
95 | depends on MODE_TT | ||
96 | help | ||
97 | This determines the amount of address space that UML will allocate for | ||
98 | its own, measured in half Gigabyte units. The default is 1. | ||
99 | Change this only if you need to boot UML with an unusually large amount | ||
100 | of physical memory. | ||
101 | |||
102 | config MODE_SKAS | ||
103 | bool "Separate Kernel Address Space support" if MODE_TT | ||
104 | default y | ||
105 | help | ||
106 | This option controls whether skas (separate kernel address space) | ||
107 | support is compiled in. | ||
108 | Unless you have specific needs to use TT mode (which applies almost only | ||
109 | to developers), you should say Y here. | ||
110 | SKAS mode will make use of the SKAS3 patch if it is applied on the host | ||
111 | (and your UML will run in SKAS3 mode), but if no SKAS patch is applied | ||
112 | on the host it will run in SKAS0 mode, which is anyway faster than TT | ||
113 | mode. | ||
114 | 83 | ||
115 | source "arch/um/Kconfig.arch" | 84 | source "arch/um/Kconfig.arch" |
116 | source "mm/Kconfig" | 85 | source "mm/Kconfig" |
86 | source "kernel/time/Kconfig" | ||
117 | 87 | ||
118 | config LD_SCRIPT_STATIC | 88 | config LD_SCRIPT_STATIC |
119 | bool | 89 | bool |
120 | default y | 90 | default y |
121 | depends on MODE_TT || STATIC_LINK | 91 | depends on STATIC_LINK |
122 | 92 | ||
123 | config LD_SCRIPT_DYN | 93 | config LD_SCRIPT_DYN |
124 | bool | 94 | bool |
@@ -128,18 +98,18 @@ config LD_SCRIPT_DYN | |||
128 | config NET | 98 | config NET |
129 | bool "Networking support" | 99 | bool "Networking support" |
130 | help | 100 | help |
131 | Unless you really know what you are doing, you should say Y here. | 101 | Unless you really know what you are doing, you should say Y here. |
132 | The reason is that some programs need kernel networking support even | 102 | The reason is that some programs need kernel networking support even |
133 | when running on a stand-alone machine that isn't connected to any | 103 | when running on a stand-alone machine that isn't connected to any |
134 | other computer. If you are upgrading from an older kernel, you | 104 | other computer. If you are upgrading from an older kernel, you |
135 | should consider updating your networking tools too because changes | 105 | should consider updating your networking tools too because changes |
136 | in the kernel and the tools often go hand in hand. The tools are | 106 | in the kernel and the tools often go hand in hand. The tools are |
137 | contained in the package net-tools, the location and version number | 107 | contained in the package net-tools, the location and version number |
138 | of which are given in <file:Documentation/Changes>. | 108 | of which are given in <file:Documentation/Changes>. |
139 | 109 | ||
140 | For a general introduction to Linux networking, it is highly | 110 | For a general introduction to Linux networking, it is highly |
141 | recommended to read the NET-HOWTO, available from | 111 | recommended to read the NET-HOWTO, available from |
142 | <http://www.tldp.org/docs.html#howto>. | 112 | <http://www.tldp.org/docs.html#howto>. |
143 | 113 | ||
144 | 114 | ||
145 | source "fs/Kconfig.binfmt" | 115 | source "fs/Kconfig.binfmt" |
@@ -147,99 +117,99 @@ source "fs/Kconfig.binfmt" | |||
147 | config HOSTFS | 117 | config HOSTFS |
148 | tristate "Host filesystem" | 118 | tristate "Host filesystem" |
149 | help | 119 | help |
150 | While the User-Mode Linux port uses its own root file system for | 120 | While the User-Mode Linux port uses its own root file system for |
151 | booting and normal file access, this module lets the UML user | 121 | booting and normal file access, this module lets the UML user |
152 | access files stored on the host. It does not require any | 122 | access files stored on the host. It does not require any |
153 | network connection between the Host and UML. An example use of | 123 | network connection between the Host and UML. An example use of |
154 | this might be: | 124 | this might be: |
155 | 125 | ||
156 | mount none /tmp/fromhost -t hostfs -o /tmp/umlshare | 126 | mount none /tmp/fromhost -t hostfs -o /tmp/umlshare |
157 | 127 | ||
158 | where /tmp/fromhost is an empty directory inside UML and | 128 | where /tmp/fromhost is an empty directory inside UML and |
159 | /tmp/umlshare is a directory on the host with files the UML user | 129 | /tmp/umlshare is a directory on the host with files the UML user |
160 | wishes to access. | 130 | wishes to access. |
161 | 131 | ||
162 | For more information, see | 132 | For more information, see |
163 | <http://user-mode-linux.sourceforge.net/hostfs.html>. | 133 | <http://user-mode-linux.sourceforge.net/hostfs.html>. |
164 | 134 | ||
165 | If you'd like to be able to work with files stored on the host, | 135 | If you'd like to be able to work with files stored on the host, |
166 | say Y or M here; otherwise say N. | 136 | say Y or M here; otherwise say N. |
167 | 137 | ||
168 | config HPPFS | 138 | config HPPFS |
169 | tristate "HoneyPot ProcFS (EXPERIMENTAL)" | 139 | tristate "HoneyPot ProcFS (EXPERIMENTAL)" |
170 | depends on EXPERIMENTAL | 140 | depends on EXPERIMENTAL |
171 | help | 141 | help |
172 | hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc | 142 | hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc |
173 | entries to be overridden, removed, or fabricated from the host. | 143 | entries to be overridden, removed, or fabricated from the host. |
174 | Its purpose is to allow a UML to appear to be a physical machine | 144 | Its purpose is to allow a UML to appear to be a physical machine |
175 | by removing or changing anything in /proc which gives away the | 145 | by removing or changing anything in /proc which gives away the |
176 | identity of a UML. | 146 | identity of a UML. |
177 | 147 | ||
178 | See <http://user-mode-linux.sf.net/hppfs.html> for more information. | 148 | See <http://user-mode-linux.sf.net/hppfs.html> for more information. |
179 | 149 | ||
180 | You only need this if you are setting up a UML honeypot. Otherwise, | 150 | You only need this if you are setting up a UML honeypot. Otherwise, |
181 | it is safe to say 'N' here. | 151 | it is safe to say 'N' here. |
182 | 152 | ||
183 | config MCONSOLE | 153 | config MCONSOLE |
184 | bool "Management console" | 154 | bool "Management console" |
185 | default y | 155 | default y |
186 | help | 156 | help |
187 | The user mode linux management console is a low-level interface to | 157 | The user mode linux management console is a low-level interface to |
188 | the kernel, somewhat like the i386 SysRq interface. Since there is | 158 | the kernel, somewhat like the i386 SysRq interface. Since there is |
189 | a full-blown operating system running under every user mode linux | 159 | a full-blown operating system running under every user mode linux |
190 | instance, there is much greater flexibility possible than with the | 160 | instance, there is much greater flexibility possible than with the |
191 | SysRq mechanism. | 161 | SysRq mechanism. |
192 | 162 | ||
193 | If you answer 'Y' to this option, to use this feature, you need the | 163 | If you answer 'Y' to this option, to use this feature, you need the |
194 | mconsole client (called uml_mconsole) which is present in CVS in | 164 | mconsole client (called uml_mconsole) which is present in CVS in |
195 | 2.4.5-9um and later (path /tools/mconsole), and is also in the | 165 | 2.4.5-9um and later (path /tools/mconsole), and is also in the |
196 | distribution RPM package in 2.4.6 and later. | 166 | distribution RPM package in 2.4.6 and later. |
197 | 167 | ||
198 | It is safe to say 'Y' here. | 168 | It is safe to say 'Y' here. |
199 | 169 | ||
200 | config MAGIC_SYSRQ | 170 | config MAGIC_SYSRQ |
201 | bool "Magic SysRq key" | 171 | bool "Magic SysRq key" |
202 | depends on MCONSOLE | 172 | depends on MCONSOLE |
203 | ---help--- | 173 | help |
204 | If you say Y here, you will have some control over the system even | 174 | If you say Y here, you will have some control over the system even |
205 | if the system crashes for example during kernel debugging (e.g., you | 175 | if the system crashes for example during kernel debugging (e.g., you |
206 | will be able to flush the buffer cache to disk, reboot the system | 176 | will be able to flush the buffer cache to disk, reboot the system |
207 | immediately or dump some status information). A key for each of the | 177 | immediately or dump some status information). A key for each of the |
208 | possible requests is provided. | 178 | possible requests is provided. |
209 | 179 | ||
210 | This is the feature normally accomplished by pressing a key | 180 | This is the feature normally accomplished by pressing a key |
211 | while holding SysRq (Alt+PrintScreen). | 181 | while holding SysRq (Alt+PrintScreen). |
212 | 182 | ||
213 | On UML, this is accomplished by sending a "sysrq" command with | 183 | On UML, this is accomplished by sending a "sysrq" command with |
214 | mconsole, followed by the letter for the requested command. | 184 | mconsole, followed by the letter for the requested command. |
215 | 185 | ||
216 | The keys are documented in <file:Documentation/sysrq.txt>. Don't say Y | 186 | The keys are documented in <file:Documentation/sysrq.txt>. Don't say Y |
217 | unless you really know what this hack does. | 187 | unless you really know what this hack does. |
218 | 188 | ||
219 | config SMP | 189 | config SMP |
220 | bool "Symmetric multi-processing support (EXPERIMENTAL)" | 190 | bool "Symmetric multi-processing support (EXPERIMENTAL)" |
221 | default n | 191 | default n |
222 | #SMP_BROKEN is for x86_64. | 192 | #SMP_BROKEN is for x86_64. |
223 | depends on MODE_TT && EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN)) | 193 | depends on EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN)) |
224 | help | 194 | help |
225 | This option enables UML SMP support. | 195 | This option enables UML SMP support. |
226 | It is NOT related to having a real SMP box. Not directly, at least. | 196 | It is NOT related to having a real SMP box. Not directly, at least. |
227 | 197 | ||
228 | UML implements virtual SMP by allowing as many processes to run | 198 | UML implements virtual SMP by allowing as many processes to run |
229 | simultaneously on the host as there are virtual processors configured. | 199 | simultaneously on the host as there are virtual processors configured. |
230 | 200 | ||
231 | Obviously, if the host is a uniprocessor, those processes will | 201 | Obviously, if the host is a uniprocessor, those processes will |
232 | timeshare, but, inside UML, will appear to be running simultaneously. | 202 | timeshare, but, inside UML, will appear to be running simultaneously. |
233 | If the host is a multiprocessor, then UML processes may run | 203 | If the host is a multiprocessor, then UML processes may run |
234 | simultaneously, depending on the host scheduler. | 204 | simultaneously, depending on the host scheduler. |
235 | 205 | ||
236 | This, however, is supported only in TT mode. So, if you use the SKAS | 206 | This, however, is supported only in TT mode. So, if you use the SKAS |
237 | patch on your host, switching to TT mode and enabling SMP usually gives | 207 | patch on your host, switching to TT mode and enabling SMP usually |
238 | you worse performances. | 208 | gives you worse performances. |
239 | Also, since the support for SMP has been under-developed, there could | 209 | Also, since the support for SMP has been under-developed, there could |
240 | be some bugs being exposed by enabling SMP. | 210 | be some bugs being exposed by enabling SMP. |
241 | 211 | ||
242 | If you don't know what to do, say N. | 212 | If you don't know what to do, say N. |
243 | 213 | ||
244 | config NR_CPUS | 214 | config NR_CPUS |
245 | int "Maximum number of CPUs (2-32)" | 215 | int "Maximum number of CPUs (2-32)" |
@@ -251,29 +221,24 @@ config NEST_LEVEL | |||
251 | int "Nesting level" | 221 | int "Nesting level" |
252 | default "0" | 222 | default "0" |
253 | help | 223 | help |
254 | This is set to the number of layers of UMLs that this UML will be run | 224 | This is set to the number of layers of UMLs that this UML will be run |
255 | in. Normally, this is zero, meaning that it will run directly on the | 225 | in. Normally, this is zero, meaning that it will run directly on the |
256 | host. Setting it to one will build a UML that can run inside a UML | 226 | host. Setting it to one will build a UML that can run inside a UML |
257 | that is running on the host. Generally, if you intend this UML to run | 227 | that is running on the host. Generally, if you intend this UML to run |
258 | inside another UML, set CONFIG_NEST_LEVEL to one more than the host | 228 | inside another UML, set CONFIG_NEST_LEVEL to one more than the host |
259 | UML. | 229 | UML. |
260 | |||
261 | Note that if the hosting UML has its CONFIG_KERNEL_HALF_GIGS set to | ||
262 | greater than one, then the guest UML should have its CONFIG_NEST_LEVEL | ||
263 | set to the host's CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS. | ||
264 | Only change this if you are running nested UMLs. | ||
265 | 230 | ||
266 | config HIGHMEM | 231 | config HIGHMEM |
267 | bool "Highmem support (EXPERIMENTAL)" | 232 | bool "Highmem support (EXPERIMENTAL)" |
268 | depends on !64BIT && EXPERIMENTAL | 233 | depends on !64BIT && EXPERIMENTAL |
269 | default n | 234 | default n |
270 | help | 235 | help |
271 | This was used to allow UML to run with big amounts of memory. | 236 | This was used to allow UML to run with big amounts of memory. |
272 | Currently it is unstable, so if unsure say N. | 237 | Currently it is unstable, so if unsure say N. |
273 | 238 | ||
274 | To use big amounts of memory, it is recommended to disable TT mode (i.e. | 239 | To use big amounts of memory, it is recommended enable static |
275 | CONFIG_MODE_TT) and enable static linking (i.e. CONFIG_STATIC_LINK) - | 240 | linking (i.e. CONFIG_STATIC_LINK) - this should allow the |
276 | this should allow the guest to use up to 2.75G of memory. | 241 | guest to use up to 2.75G of memory. |
277 | 242 | ||
278 | config KERNEL_STACK_ORDER | 243 | config KERNEL_STACK_ORDER |
279 | int "Kernel stack size order" | 244 | int "Kernel stack size order" |
@@ -281,20 +246,9 @@ config KERNEL_STACK_ORDER | |||
281 | range 1 10 if 64BIT | 246 | range 1 10 if 64BIT |
282 | default 0 if !64BIT | 247 | default 0 if !64BIT |
283 | help | 248 | help |
284 | This option determines the size of UML kernel stacks. They will | 249 | This option determines the size of UML kernel stacks. They will |
285 | be 1 << order pages. The default is OK unless you're running Valgrind | 250 | be 1 << order pages. The default is OK unless you're running Valgrind |
286 | on UML, in which case, set this to 3. | 251 | on UML, in which case, set this to 3. |
287 | |||
288 | config UML_REAL_TIME_CLOCK | ||
289 | bool "Real-time Clock" | ||
290 | default y | ||
291 | help | ||
292 | This option makes UML time deltas match wall clock deltas. This should | ||
293 | normally be enabled. The exception would be if you are debugging with | ||
294 | UML and spend long times with UML stopped at a breakpoint. In this | ||
295 | case, when UML is restarted, it will call the timer enough times to make | ||
296 | up for the time spent at the breakpoint. This could result in a | ||
297 | noticeable lag. If this is a problem, then disable this option. | ||
298 | 252 | ||
299 | endmenu | 253 | endmenu |
300 | 254 | ||
diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char index a5b079d5e865..9a78d354f0b4 100644 --- a/arch/um/Kconfig.char +++ b/arch/um/Kconfig.char | |||
@@ -5,7 +5,7 @@ config STDERR_CONSOLE | |||
5 | bool "stderr console" | 5 | bool "stderr console" |
6 | default y | 6 | default y |
7 | help | 7 | help |
8 | console driver which dumps all printk messages to stderr. | 8 | console driver which dumps all printk messages to stderr. |
9 | 9 | ||
10 | config STDIO_CONSOLE | 10 | config STDIO_CONSOLE |
11 | bool | 11 | bool |
@@ -14,60 +14,58 @@ config STDIO_CONSOLE | |||
14 | config SSL | 14 | config SSL |
15 | bool "Virtual serial line" | 15 | bool "Virtual serial line" |
16 | help | 16 | help |
17 | The User-Mode Linux environment allows you to create virtual serial | 17 | The User-Mode Linux environment allows you to create virtual serial |
18 | lines on the UML that are usually made to show up on the host as | 18 | lines on the UML that are usually made to show up on the host as |
19 | ttys or ptys. | 19 | ttys or ptys. |
20 | 20 | ||
21 | See <http://user-mode-linux.sourceforge.net/input.html> for more | 21 | See <http://user-mode-linux.sourceforge.net/input.html> for more |
22 | information and command line examples of how to use this facility. | 22 | information and command line examples of how to use this facility. |
23 | 23 | ||
24 | Unless you have a specific reason for disabling this, say Y. | 24 | Unless you have a specific reason for disabling this, say Y. |
25 | 25 | ||
26 | config NULL_CHAN | 26 | config NULL_CHAN |
27 | bool "null channel support" | 27 | bool "null channel support" |
28 | help | 28 | help |
29 | This option enables support for attaching UML consoles and serial | 29 | This option enables support for attaching UML consoles and serial |
30 | lines to a device similar to /dev/null. Data written to it disappears | 30 | lines to a device similar to /dev/null. Data written to it disappears |
31 | and there is never any data to be read. | 31 | and there is never any data to be read. |
32 | 32 | ||
33 | config PORT_CHAN | 33 | config PORT_CHAN |
34 | bool "port channel support" | 34 | bool "port channel support" |
35 | help | 35 | help |
36 | This option enables support for attaching UML consoles and serial | 36 | This option enables support for attaching UML consoles and serial |
37 | lines to host portals. They may be accessed with 'telnet <host> | 37 | lines to host portals. They may be accessed with 'telnet <host> |
38 | <port number>'. Any number of consoles and serial lines may be | 38 | <port number>'. Any number of consoles and serial lines may be |
39 | attached to a single portal, although what UML device you get when | 39 | attached to a single portal, although what UML device you get when |
40 | you telnet to that portal will be unpredictable. | 40 | you telnet to that portal will be unpredictable. |
41 | It is safe to say 'Y' here. | 41 | It is safe to say 'Y' here. |
42 | 42 | ||
43 | config PTY_CHAN | 43 | config PTY_CHAN |
44 | bool "pty channel support" | 44 | bool "pty channel support" |
45 | help | 45 | help |
46 | This option enables support for attaching UML consoles and serial | 46 | This option enables support for attaching UML consoles and serial |
47 | lines to host pseudo-terminals. Access to both traditional | 47 | lines to host pseudo-terminals. Access to both traditional |
48 | pseudo-terminals (/dev/pty*) and pts pseudo-terminals are controlled | 48 | pseudo-terminals (/dev/pty*) and pts pseudo-terminals are controlled |
49 | with this option. The assignment of UML devices to host devices | 49 | with this option. The assignment of UML devices to host devices |
50 | will be announced in the kernel message log. | 50 | will be announced in the kernel message log. |
51 | It is safe to say 'Y' here. | 51 | It is safe to say 'Y' here. |
52 | 52 | ||
53 | config TTY_CHAN | 53 | config TTY_CHAN |
54 | bool "tty channel support" | 54 | bool "tty channel support" |
55 | help | 55 | help |
56 | This option enables support for attaching UML consoles and serial | 56 | This option enables support for attaching UML consoles and serial |
57 | lines to host terminals. Access to both virtual consoles | 57 | lines to host terminals. Access to both virtual consoles |
58 | (/dev/tty*) and the slave side of pseudo-terminals (/dev/ttyp* and | 58 | (/dev/tty*) and the slave side of pseudo-terminals (/dev/ttyp* and |
59 | /dev/pts/*) are controlled by this option. | 59 | /dev/pts/*) are controlled by this option. |
60 | It is safe to say 'Y' here. | 60 | It is safe to say 'Y' here. |
61 | 61 | ||
62 | config XTERM_CHAN | 62 | config XTERM_CHAN |
63 | bool "xterm channel support" | 63 | bool "xterm channel support" |
64 | help | 64 | help |
65 | This option enables support for attaching UML consoles and serial | 65 | This option enables support for attaching UML consoles and serial |
66 | lines to xterms. Each UML device so assigned will be brought up in | 66 | lines to xterms. Each UML device so assigned will be brought up in |
67 | its own xterm. | 67 | its own xterm. |
68 | If you disable this option, then CONFIG_PT_PROXY will be disabled as | 68 | It is safe to say 'Y' here. |
69 | well, since UML's gdb currently requires an xterm. | ||
70 | It is safe to say 'Y' here. | ||
71 | 69 | ||
72 | config NOCONFIG_CHAN | 70 | config NOCONFIG_CHAN |
73 | bool | 71 | bool |
@@ -77,39 +75,39 @@ config CON_ZERO_CHAN | |||
77 | string "Default main console channel initialization" | 75 | string "Default main console channel initialization" |
78 | default "fd:0,fd:1" | 76 | default "fd:0,fd:1" |
79 | help | 77 | help |
80 | This is the string describing the channel to which the main console | 78 | This is the string describing the channel to which the main console |
81 | will be attached by default. This value can be overridden from the | 79 | will be attached by default. This value can be overridden from the |
82 | command line. The default value is "fd:0,fd:1", which attaches the | 80 | command line. The default value is "fd:0,fd:1", which attaches the |
83 | main console to stdin and stdout. | 81 | main console to stdin and stdout. |
84 | It is safe to leave this unchanged. | 82 | It is safe to leave this unchanged. |
85 | 83 | ||
86 | config CON_CHAN | 84 | config CON_CHAN |
87 | string "Default console channel initialization" | 85 | string "Default console channel initialization" |
88 | default "xterm" | 86 | default "xterm" |
89 | help | 87 | help |
90 | This is the string describing the channel to which all consoles | 88 | This is the string describing the channel to which all consoles |
91 | except the main console will be attached by default. This value can | 89 | except the main console will be attached by default. This value can |
92 | be overridden from the command line. The default value is "xterm", | 90 | be overridden from the command line. The default value is "xterm", |
93 | which brings them up in xterms. | 91 | which brings them up in xterms. |
94 | It is safe to leave this unchanged, although you may wish to change | 92 | It is safe to leave this unchanged, although you may wish to change |
95 | this if you expect the UML that you build to be run in environments | 93 | this if you expect the UML that you build to be run in environments |
96 | which don't have X or xterm available. | 94 | which don't have X or xterm available. |
97 | 95 | ||
98 | config SSL_CHAN | 96 | config SSL_CHAN |
99 | string "Default serial line channel initialization" | 97 | string "Default serial line channel initialization" |
100 | default "pty" | 98 | default "pty" |
101 | help | 99 | help |
102 | This is the string describing the channel to which the serial lines | 100 | This is the string describing the channel to which the serial lines |
103 | will be attached by default. This value can be overridden from the | 101 | will be attached by default. This value can be overridden from the |
104 | command line. The default value is "pty", which attaches them to | 102 | command line. The default value is "pty", which attaches them to |
105 | traditional pseudo-terminals. | 103 | traditional pseudo-terminals. |
106 | It is safe to leave this unchanged, although you may wish to change | 104 | It is safe to leave this unchanged, although you may wish to change |
107 | this if you expect the UML that you build to be run in environments | 105 | this if you expect the UML that you build to be run in environments |
108 | which don't have a set of /dev/pty* devices. | 106 | which don't have a set of /dev/pty* devices. |
109 | 107 | ||
110 | config UNIX98_PTYS | 108 | config UNIX98_PTYS |
111 | bool "Unix98 PTY support" | 109 | bool "Unix98 PTY support" |
112 | ---help--- | 110 | help |
113 | A pseudo terminal (PTY) is a software device consisting of two | 111 | A pseudo terminal (PTY) is a software device consisting of two |
114 | halves: a master and a slave. The slave device behaves identical to | 112 | halves: a master and a slave. The slave device behaves identical to |
115 | a physical terminal; the master device is used by a process to | 113 | a physical terminal; the master device is used by a process to |
@@ -132,7 +130,7 @@ config UNIX98_PTYS | |||
132 | config LEGACY_PTYS | 130 | config LEGACY_PTYS |
133 | bool "Legacy (BSD) PTY support" | 131 | bool "Legacy (BSD) PTY support" |
134 | default y | 132 | default y |
135 | ---help--- | 133 | help |
136 | A pseudo terminal (PTY) is a software device consisting of two | 134 | A pseudo terminal (PTY) is a software device consisting of two |
137 | halves: a master and a slave. The slave device behaves identical to | 135 | halves: a master and a slave. The slave device behaves identical to |
138 | a physical terminal; the master device is used by a process to | 136 | a physical terminal; the master device is used by a process to |
@@ -170,7 +168,7 @@ config LEGACY_PTY_COUNT | |||
170 | int "Maximum number of legacy PTY in use" | 168 | int "Maximum number of legacy PTY in use" |
171 | depends on LEGACY_PTYS | 169 | depends on LEGACY_PTYS |
172 | default "256" | 170 | default "256" |
173 | ---help--- | 171 | help |
174 | The maximum number of legacy PTYs that can be used at any one time. | 172 | The maximum number of legacy PTYs that can be used at any one time. |
175 | The default is 256, and should be more than enough. Embedded | 173 | The default is 256, and should be more than enough. Embedded |
176 | systems may want to reduce this to save memory. | 174 | systems may want to reduce this to save memory. |
@@ -196,10 +194,10 @@ config UML_WATCHDOG | |||
196 | config UML_SOUND | 194 | config UML_SOUND |
197 | tristate "Sound support" | 195 | tristate "Sound support" |
198 | help | 196 | help |
199 | This option enables UML sound support. If enabled, it will pull in | 197 | This option enables UML sound support. If enabled, it will pull in |
200 | soundcore and the UML hostaudio relay, which acts as a intermediary | 198 | soundcore and the UML hostaudio relay, which acts as a intermediary |
201 | between the host's dsp and mixer devices and the UML sound system. | 199 | between the host's dsp and mixer devices and the UML sound system. |
202 | It is safe to say 'Y' here. | 200 | It is safe to say 'Y' here. |
203 | 201 | ||
204 | config SOUND | 202 | config SOUND |
205 | tristate | 203 | tristate |
@@ -217,22 +215,21 @@ config HW_RANDOM | |||
217 | config UML_RANDOM | 215 | config UML_RANDOM |
218 | tristate "Hardware random number generator" | 216 | tristate "Hardware random number generator" |
219 | help | 217 | help |
220 | This option enables UML's "hardware" random number generator. It | 218 | This option enables UML's "hardware" random number generator. It |
221 | attaches itself to the host's /dev/random, supplying as much entropy | 219 | attaches itself to the host's /dev/random, supplying as much entropy |
222 | as the host has, rather than the small amount the UML gets from its | 220 | as the host has, rather than the small amount the UML gets from its |
223 | own drivers. It registers itself as a standard hardware random number | 221 | own drivers. It registers itself as a standard hardware random number |
224 | generator, major 10, minor 183, and the canonical device name is | 222 | generator, major 10, minor 183, and the canonical device name is |
225 | /dev/hwrng. | 223 | /dev/hwrng. |
226 | The way to make use of this is to install the rng-tools package | 224 | The way to make use of this is to install the rng-tools package |
227 | (check your distro, or download from | 225 | (check your distro, or download from |
228 | http://sourceforge.net/projects/gkernel/). rngd periodically reads | 226 | http://sourceforge.net/projects/gkernel/). rngd periodically reads |
229 | /dev/hwrng and injects the entropy into /dev/random. | 227 | /dev/hwrng and injects the entropy into /dev/random. |
230 | 228 | ||
231 | config MMAPPER | 229 | config MMAPPER |
232 | tristate "iomem emulation driver" | 230 | tristate "iomem emulation driver" |
233 | help | 231 | help |
234 | This driver allows a host file to be used as emulated IO memory inside | 232 | This driver allows a host file to be used as emulated IO memory inside |
235 | UML. | 233 | UML. |
236 | 234 | ||
237 | endmenu | 235 | endmenu |
238 | |||
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug index c86f5eb29fd5..1f6462ffd3e8 100644 --- a/arch/um/Kconfig.debug +++ b/arch/um/Kconfig.debug | |||
@@ -2,50 +2,31 @@ menu "Kernel hacking" | |||
2 | 2 | ||
3 | source "lib/Kconfig.debug" | 3 | source "lib/Kconfig.debug" |
4 | 4 | ||
5 | config CMDLINE_ON_HOST | ||
6 | bool "Show command line arguments on the host in TT mode" | ||
7 | depends on MODE_TT | ||
8 | default !DEBUG_INFO | ||
9 | help | ||
10 | This controls whether arguments in guest processes should be shown on | ||
11 | the host's ps output. | ||
12 | Enabling this option hinders debugging on some recent GDB versions | ||
13 | (because GDB gets "confused" when we do an execvp()). So probably you | ||
14 | should disable it. | ||
15 | |||
16 | config PT_PROXY | ||
17 | bool "Enable ptrace proxy" | ||
18 | depends on XTERM_CHAN && DEBUG_INFO && MODE_TT | ||
19 | help | ||
20 | This option enables a debugging interface which allows gdb to debug | ||
21 | the kernel without needing to actually attach to kernel threads. | ||
22 | If you want to do kernel debugging, say Y here; otherwise say N. | ||
23 | |||
24 | config GPROF | 5 | config GPROF |
25 | bool "Enable gprof support" | 6 | bool "Enable gprof support" |
26 | depends on DEBUG_INFO && MODE_SKAS && !MODE_TT | 7 | depends on DEBUG_INFO |
27 | help | 8 | help |
28 | This allows profiling of a User-Mode Linux kernel with the gprof | 9 | This allows profiling of a User-Mode Linux kernel with the gprof |
29 | utility. | 10 | utility. |
30 | 11 | ||
31 | See <http://user-mode-linux.sourceforge.net/gprof.html> for more | 12 | See <http://user-mode-linux.sourceforge.net/gprof.html> for more |
32 | details. | 13 | details. |
33 | 14 | ||
34 | If you're involved in UML kernel development and want to use gprof, | 15 | If you're involved in UML kernel development and want to use gprof, |
35 | say Y. If you're unsure, say N. | 16 | say Y. If you're unsure, say N. |
36 | 17 | ||
37 | config GCOV | 18 | config GCOV |
38 | bool "Enable gcov support" | 19 | bool "Enable gcov support" |
39 | depends on DEBUG_INFO && MODE_SKAS | 20 | depends on DEBUG_INFO |
40 | help | 21 | help |
41 | This option allows developers to retrieve coverage data from a UML | 22 | This option allows developers to retrieve coverage data from a UML |
42 | session. | 23 | session. |
43 | 24 | ||
44 | See <http://user-mode-linux.sourceforge.net/gprof.html> for more | 25 | See <http://user-mode-linux.sourceforge.net/gprof.html> for more |
45 | details. | 26 | details. |
46 | 27 | ||
47 | If you're involved in UML kernel development and want to use gcov, | 28 | If you're involved in UML kernel development and want to use gcov, |
48 | say Y. If you're unsure, say N. | 29 | say Y. If you're unsure, say N. |
49 | 30 | ||
50 | config DEBUG_STACK_USAGE | 31 | config DEBUG_STACK_USAGE |
51 | bool "Stack utilization instrumentation" | 32 | bool "Stack utilization instrumentation" |
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386 index d6cffb27fff8..9876d80d85dd 100644 --- a/arch/um/Kconfig.i386 +++ b/arch/um/Kconfig.i386 | |||
@@ -65,20 +65,6 @@ config 3_LEVEL_PGTABLES | |||
65 | However, this it experimental on 32-bit architectures, so if unsure say | 65 | However, this it experimental on 32-bit architectures, so if unsure say |
66 | N (on x86-64 it's automatically enabled, instead, as it's safe there). | 66 | N (on x86-64 it's automatically enabled, instead, as it's safe there). |
67 | 67 | ||
68 | config STUB_CODE | ||
69 | hex | ||
70 | default 0xbfffe000 if !HOST_VMSPLIT_2G | ||
71 | default 0x7fffe000 if HOST_VMSPLIT_2G | ||
72 | |||
73 | config STUB_DATA | ||
74 | hex | ||
75 | default 0xbffff000 if !HOST_VMSPLIT_2G | ||
76 | default 0x7ffff000 if HOST_VMSPLIT_2G | ||
77 | |||
78 | config STUB_START | ||
79 | hex | ||
80 | default STUB_CODE | ||
81 | |||
82 | config ARCH_HAS_SC_SIGNALS | 68 | config ARCH_HAS_SC_SIGNALS |
83 | bool | 69 | bool |
84 | default y | 70 | default y |
diff --git a/arch/um/Kconfig.net b/arch/um/Kconfig.net index 14a04ebdeae9..66e50026ade9 100644 --- a/arch/um/Kconfig.net +++ b/arch/um/Kconfig.net | |||
@@ -108,6 +108,28 @@ config UML_NET_DAEMON | |||
108 | more than one without conflict. If you don't need UML networking, | 108 | more than one without conflict. If you don't need UML networking, |
109 | say N. | 109 | say N. |
110 | 110 | ||
111 | config UML_NET_VDE | ||
112 | bool "VDE transport" | ||
113 | depends on UML_NET | ||
114 | help | ||
115 | This User-Mode Linux network transport allows one or more running | ||
116 | UMLs on a single host to communicate with each other and also | ||
117 | with the rest of the world using Virtual Distributed Ethernet, | ||
118 | an improved fork of uml_switch. | ||
119 | |||
120 | You must have libvdeplug installed in order to build the vde | ||
121 | transport into UML. | ||
122 | |||
123 | To use this form of networking, you will need to run vde_switch | ||
124 | on the host. | ||
125 | |||
126 | For more information, see <http://wiki.virtualsquare.org/> | ||
127 | That site has a good overview of what VDE is and also examples | ||
128 | of the UML command line to use to enable VDE networking. | ||
129 | |||
130 | If you need UML networking with VDE, | ||
131 | say Y. | ||
132 | |||
111 | config UML_NET_MCAST | 133 | config UML_NET_MCAST |
112 | bool "Multicast transport" | 134 | bool "Multicast transport" |
113 | depends on UML_NET | 135 | depends on UML_NET |
diff --git a/arch/um/Kconfig.x86_64 b/arch/um/Kconfig.x86_64 index f60e9e506424..d632e9a89cc3 100644 --- a/arch/um/Kconfig.x86_64 +++ b/arch/um/Kconfig.x86_64 | |||
@@ -17,24 +17,12 @@ config SEMAPHORE_SLEEPERS | |||
17 | 17 | ||
18 | config TOP_ADDR | 18 | config TOP_ADDR |
19 | hex | 19 | hex |
20 | default 0x80000000 | 20 | default 0x7fc0000000 |
21 | 21 | ||
22 | config 3_LEVEL_PGTABLES | 22 | config 3_LEVEL_PGTABLES |
23 | bool | 23 | bool |
24 | default y | 24 | default y |
25 | 25 | ||
26 | config STUB_CODE | ||
27 | hex | ||
28 | default 0x7fbfffe000 | ||
29 | |||
30 | config STUB_DATA | ||
31 | hex | ||
32 | default 0x7fbffff000 | ||
33 | |||
34 | config STUB_START | ||
35 | hex | ||
36 | default STUB_CODE | ||
37 | |||
38 | config ARCH_HAS_SC_SIGNALS | 26 | config ARCH_HAS_SC_SIGNALS |
39 | bool | 27 | bool |
40 | default n | 28 | default n |
diff --git a/arch/um/Makefile b/arch/um/Makefile index 0666729eb976..ab22fdeedf29 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # This file is included by the global makefile so that you can add your own | 2 | # This file is included by the global makefile so that you can add your own |
3 | # architecture-specific flags and dependencies. | 3 | # architecture-specific flags and dependencies. |
4 | # | 4 | # |
5 | # Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 5 | # Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
6 | # Licensed under the GPL | 6 | # Licensed under the GPL |
7 | # | 7 | # |
8 | 8 | ||
@@ -31,18 +31,9 @@ SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header)) | |||
31 | ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \ | 31 | ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \ |
32 | $(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h | 32 | $(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h |
33 | 33 | ||
34 | um-modes-$(CONFIG_MODE_TT) += tt | 34 | MODE_INCLUDE += -I$(srctree)/$(ARCH_DIR)/include/skas |
35 | um-modes-$(CONFIG_MODE_SKAS) += skas | ||
36 | 35 | ||
37 | MODE_INCLUDE += $(foreach mode,$(um-modes-y),\ | 36 | include $(srctree)/$(ARCH_DIR)/Makefile-skas |
38 | -I$(srctree)/$(ARCH_DIR)/include/$(mode)) | ||
39 | |||
40 | MAKEFILES-INCL += $(foreach mode,$(um-modes-y),\ | ||
41 | $(srctree)/$(ARCH_DIR)/Makefile-$(mode)) | ||
42 | |||
43 | ifneq ($(MAKEFILES-INCL),) | ||
44 | include $(MAKEFILES-INCL) | ||
45 | endif | ||
46 | 37 | ||
47 | ARCH_INCLUDE := -I$(ARCH_DIR)/include | 38 | ARCH_INCLUDE := -I$(ARCH_DIR)/include |
48 | ifneq ($(KBUILD_SRC),) | 39 | ifneq ($(KBUILD_SRC),) |
@@ -60,7 +51,8 @@ SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH) | |||
60 | 51 | ||
61 | CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ | 52 | CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ |
62 | $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \ | 53 | $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \ |
63 | -Din6addr_loopback=kernel_in6addr_loopback | 54 | -Din6addr_loopback=kernel_in6addr_loopback \ |
55 | -Din6addr_any=kernel_in6addr_any | ||
64 | 56 | ||
65 | AFLAGS += $(ARCH_INCLUDE) | 57 | AFLAGS += $(ARCH_INCLUDE) |
66 | 58 | ||
@@ -88,9 +80,8 @@ CFLAGS += $(call cc-option,-fno-unit-at-a-time,) | |||
88 | # included; the values here are meaningless | 80 | # included; the values here are meaningless |
89 | 81 | ||
90 | CONFIG_NEST_LEVEL ?= 0 | 82 | CONFIG_NEST_LEVEL ?= 0 |
91 | CONFIG_KERNEL_HALF_GIGS ?= 0 | ||
92 | 83 | ||
93 | SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000) | 84 | SIZE = ($(CONFIG_NEST_LEVEL) * 0x20000000) |
94 | 85 | ||
95 | PHONY += linux | 86 | PHONY += linux |
96 | 87 | ||
@@ -123,7 +114,6 @@ CFLAGS_NO_HARDENING := $(call cc-option, -fno-PIC,) $(call cc-option, -fno-pic,) | |||
123 | $(call cc-option, -fno-stack-protector,) \ | 114 | $(call cc-option, -fno-stack-protector,) \ |
124 | $(call cc-option, -fno-stack-protector-all,) | 115 | $(call cc-option, -fno-stack-protector-all,) |
125 | 116 | ||
126 | CPP_MODE-$(CONFIG_MODE_TT) := -DMODE_TT | ||
127 | CONFIG_KERNEL_STACK_ORDER ?= 2 | 117 | CONFIG_KERNEL_STACK_ORDER ?= 2 |
128 | STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] ) | 118 | STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] ) |
129 | 119 | ||
@@ -131,13 +121,10 @@ ifndef START | |||
131 | START = $(shell echo $$[ $(TOP_ADDR) - $(SIZE) ] ) | 121 | START = $(shell echo $$[ $(TOP_ADDR) - $(SIZE) ] ) |
132 | endif | 122 | endif |
133 | 123 | ||
134 | CPPFLAGS_vmlinux.lds = -U$(SUBARCH) \ | 124 | CPPFLAGS_vmlinux.lds = -U$(SUBARCH) -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \ |
135 | -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \ | 125 | -DELF_FORMAT="$(ELF_FORMAT)" -DKERNEL_STACK_SIZE=$(STACK_SIZE) |
136 | -DELF_FORMAT="$(ELF_FORMAT)" $(CPP_MODE-y) \ | ||
137 | -DKERNEL_STACK_SIZE=$(STACK_SIZE) \ | ||
138 | -DUNMAP_PATH=arch/um/sys-$(SUBARCH)/unmap.o | ||
139 | 126 | ||
140 | #The wrappers will select whether using "malloc" or the kernel allocator. | 127 | # The wrappers will select whether using "malloc" or the kernel allocator. |
141 | LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc | 128 | LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc |
142 | 129 | ||
143 | CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) | 130 | CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) |
@@ -150,8 +137,8 @@ define cmd_vmlinux__ | |||
150 | FORCE ,$^) ; rm -f linux | 137 | FORCE ,$^) ; rm -f linux |
151 | endef | 138 | endef |
152 | 139 | ||
153 | #When cleaning we don't include .config, so we don't include | 140 | # When cleaning we don't include .config, so we don't include |
154 | #TT or skas makefiles and don't clean skas_ptregs.h. | 141 | # TT or skas makefiles and don't clean skas_ptregs.h. |
155 | CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/include/uml-config.h \ | 142 | CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/include/uml-config.h \ |
156 | $(ARCH_DIR)/include/user_constants.h \ | 143 | $(ARCH_DIR)/include/user_constants.h \ |
157 | $(ARCH_DIR)/include/kern_constants.h $(ARCH_DIR)/Kconfig.arch | 144 | $(ARCH_DIR)/include/kern_constants.h $(ARCH_DIR)/Kconfig.arch |
diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index 60107ed4905b..ae61e3c271e2 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 | |||
@@ -2,11 +2,7 @@ core-y += arch/um/sys-i386/ arch/x86/crypto/ | |||
2 | 2 | ||
3 | TOP_ADDR := $(CONFIG_TOP_ADDR) | 3 | TOP_ADDR := $(CONFIG_TOP_ADDR) |
4 | 4 | ||
5 | ifeq ($(CONFIG_MODE_SKAS),y) | 5 | START := 0x8048000 |
6 | ifneq ($(CONFIG_MODE_TT),y) | ||
7 | START := 0x8048000 | ||
8 | endif | ||
9 | endif | ||
10 | 6 | ||
11 | LDFLAGS += -m elf_i386 | 7 | LDFLAGS += -m elf_i386 |
12 | ELF_ARCH := $(SUBARCH) | 8 | ELF_ARCH := $(SUBARCH) |
diff --git a/arch/um/defconfig b/arch/um/defconfig index 1e0f677c2f46..f609edede065 100644 --- a/arch/um/defconfig +++ b/arch/um/defconfig | |||
@@ -12,9 +12,7 @@ CONFIG_IRQ_RELEASE_METHOD=y | |||
12 | # | 12 | # |
13 | # UML-specific options | 13 | # UML-specific options |
14 | # | 14 | # |
15 | # CONFIG_MODE_TT is not set | ||
16 | # CONFIG_STATIC_LINK is not set | 15 | # CONFIG_STATIC_LINK is not set |
17 | CONFIG_MODE_SKAS=y | ||
18 | 16 | ||
19 | # | 17 | # |
20 | # Host processor type and features | 18 | # Host processor type and features |
@@ -61,9 +59,6 @@ CONFIG_SEMAPHORE_SLEEPERS=y | |||
61 | # CONFIG_HOST_2G_2G is not set | 59 | # CONFIG_HOST_2G_2G is not set |
62 | CONFIG_TOP_ADDR=0xc0000000 | 60 | CONFIG_TOP_ADDR=0xc0000000 |
63 | # CONFIG_3_LEVEL_PGTABLES is not set | 61 | # CONFIG_3_LEVEL_PGTABLES is not set |
64 | CONFIG_STUB_CODE=0xbfffe000 | ||
65 | CONFIG_STUB_DATA=0xbffff000 | ||
66 | CONFIG_STUB_START=0xbfffe000 | ||
67 | CONFIG_ARCH_HAS_SC_SIGNALS=y | 62 | CONFIG_ARCH_HAS_SC_SIGNALS=y |
68 | CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y | 63 | CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y |
69 | CONFIG_GENERIC_HWEIGHT=y | 64 | CONFIG_GENERIC_HWEIGHT=y |
@@ -75,6 +70,9 @@ CONFIG_FLATMEM=y | |||
75 | CONFIG_FLAT_NODE_MEM_MAP=y | 70 | CONFIG_FLAT_NODE_MEM_MAP=y |
76 | # CONFIG_SPARSEMEM_STATIC is not set | 71 | # CONFIG_SPARSEMEM_STATIC is not set |
77 | CONFIG_SPLIT_PTLOCK_CPUS=4 | 72 | CONFIG_SPLIT_PTLOCK_CPUS=4 |
73 | CONFIG_TICK_ONESHOT=y | ||
74 | CONFIG_NO_HZ=y | ||
75 | CONFIG_HIGH_RES_TIMERS=y | ||
78 | CONFIG_LD_SCRIPT_DYN=y | 76 | CONFIG_LD_SCRIPT_DYN=y |
79 | CONFIG_NET=y | 77 | CONFIG_NET=y |
80 | CONFIG_BINFMT_ELF=y | 78 | CONFIG_BINFMT_ELF=y |
@@ -82,11 +80,10 @@ CONFIG_BINFMT_MISC=m | |||
82 | # CONFIG_HOSTFS is not set | 80 | # CONFIG_HOSTFS is not set |
83 | # CONFIG_HPPFS is not set | 81 | # CONFIG_HPPFS is not set |
84 | CONFIG_MCONSOLE=y | 82 | CONFIG_MCONSOLE=y |
85 | # CONFIG_MAGIC_SYSRQ is not set | 83 | CONFIG_MAGIC_SYSRQ=y |
86 | CONFIG_NEST_LEVEL=0 | 84 | CONFIG_NEST_LEVEL=0 |
87 | # CONFIG_HIGHMEM is not set | 85 | # CONFIG_HIGHMEM is not set |
88 | CONFIG_KERNEL_STACK_ORDER=0 | 86 | CONFIG_KERNEL_STACK_ORDER=0 |
89 | CONFIG_UML_REAL_TIME_CLOCK=y | ||
90 | 87 | ||
91 | # | 88 | # |
92 | # Code maturity level options | 89 | # Code maturity level options |
diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile index de17d4c6e02d..634968150bd6 100644 --- a/arch/um/drivers/Makefile +++ b/arch/um/drivers/Makefile | |||
@@ -19,10 +19,16 @@ harddog-objs := harddog_kern.o harddog_user.o | |||
19 | 19 | ||
20 | LDFLAGS_pcap.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libpcap.a) | 20 | LDFLAGS_pcap.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libpcap.a) |
21 | 21 | ||
22 | targets := pcap_kern.o pcap_user.o | 22 | LDFLAGS_vde.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libvdeplug.a) |
23 | |||
24 | targets := pcap_kern.o pcap_user.o vde_kern.o vde_user.o | ||
23 | 25 | ||
24 | $(obj)/pcap.o: $(obj)/pcap_kern.o $(obj)/pcap_user.o | 26 | $(obj)/pcap.o: $(obj)/pcap_kern.o $(obj)/pcap_user.o |
25 | $(LD) -r -dp -o $@ $^ $(LDFLAGS) $(LDFLAGS_pcap.o) | 27 | $(LD) -r -dp -o $@ $^ $(LDFLAGS) $(LDFLAGS_pcap.o) |
28 | |||
29 | $(obj)/vde.o: $(obj)/vde_kern.o $(obj)/vde_user.o | ||
30 | $(LD) -r -dp -o $@ $^ $(LDFLAGS) $(LDFLAGS_vde.o) | ||
31 | |||
26 | #XXX: The call below does not work because the flags are added before the | 32 | #XXX: The call below does not work because the flags are added before the |
27 | # object name, so nothing from the library gets linked. | 33 | # object name, so nothing from the library gets linked. |
28 | #$(call if_changed,ld) | 34 | #$(call if_changed,ld) |
@@ -37,6 +43,7 @@ obj-$(CONFIG_STDERR_CONSOLE) += stderr_console.o | |||
37 | obj-$(CONFIG_UML_NET_SLIP) += slip.o slip_common.o | 43 | obj-$(CONFIG_UML_NET_SLIP) += slip.o slip_common.o |
38 | obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o | 44 | obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o |
39 | obj-$(CONFIG_UML_NET_DAEMON) += daemon.o | 45 | obj-$(CONFIG_UML_NET_DAEMON) += daemon.o |
46 | obj-$(CONFIG_UML_NET_VDE) += vde.o | ||
40 | obj-$(CONFIG_UML_NET_MCAST) += mcast.o | 47 | obj-$(CONFIG_UML_NET_MCAST) += mcast.o |
41 | obj-$(CONFIG_UML_NET_PCAP) += pcap.o | 48 | obj-$(CONFIG_UML_NET_PCAP) += pcap.o |
42 | obj-$(CONFIG_UML_NET) += net.o | 49 | obj-$(CONFIG_UML_NET) += net.o |
@@ -54,6 +61,6 @@ obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o | |||
54 | obj-$(CONFIG_UML_RANDOM) += random.o | 61 | obj-$(CONFIG_UML_RANDOM) += random.o |
55 | 62 | ||
56 | # pcap_user.o must be added explicitly. | 63 | # pcap_user.o must be added explicitly. |
57 | USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o pcap_user.o | 64 | USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o pcap_user.o vde_user.o |
58 | 65 | ||
59 | include arch/um/scripts/Makefile.rules | 66 | include arch/um/scripts/Makefile.rules |
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 629b00e3b0b0..db3082b4da46 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c | |||
@@ -1,28 +1,19 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/stddef.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/list.h> | ||
9 | #include <linux/slab.h> | 6 | #include <linux/slab.h> |
10 | #include <linux/tty.h> | 7 | #include <linux/tty.h> |
11 | #include <linux/string.h> | ||
12 | #include <linux/tty_flip.h> | 8 | #include <linux/tty_flip.h> |
13 | #include <asm/irq.h> | ||
14 | #include "chan_kern.h" | 9 | #include "chan_kern.h" |
15 | #include "kern.h" | ||
16 | #include "irq_user.h" | ||
17 | #include "sigio.h" | ||
18 | #include "line.h" | ||
19 | #include "os.h" | 10 | #include "os.h" |
20 | 11 | ||
21 | #ifdef CONFIG_NOCONFIG_CHAN | 12 | #ifdef CONFIG_NOCONFIG_CHAN |
22 | static void *not_configged_init(char *str, int device, | 13 | static void *not_configged_init(char *str, int device, |
23 | const struct chan_opts *opts) | 14 | const struct chan_opts *opts) |
24 | { | 15 | { |
25 | printk("Using a channel type which is configured out of " | 16 | printk(KERN_ERR "Using a channel type which is configured out of " |
26 | "UML\n"); | 17 | "UML\n"); |
27 | return NULL; | 18 | return NULL; |
28 | } | 19 | } |
@@ -30,34 +21,34 @@ static void *not_configged_init(char *str, int device, | |||
30 | static int not_configged_open(int input, int output, int primary, void *data, | 21 | static int not_configged_open(int input, int output, int primary, void *data, |
31 | char **dev_out) | 22 | char **dev_out) |
32 | { | 23 | { |
33 | printk("Using a channel type which is configured out of " | 24 | printk(KERN_ERR "Using a channel type which is configured out of " |
34 | "UML\n"); | 25 | "UML\n"); |
35 | return -ENODEV; | 26 | return -ENODEV; |
36 | } | 27 | } |
37 | 28 | ||
38 | static void not_configged_close(int fd, void *data) | 29 | static void not_configged_close(int fd, void *data) |
39 | { | 30 | { |
40 | printk("Using a channel type which is configured out of " | 31 | printk(KERN_ERR "Using a channel type which is configured out of " |
41 | "UML\n"); | 32 | "UML\n"); |
42 | } | 33 | } |
43 | 34 | ||
44 | static int not_configged_read(int fd, char *c_out, void *data) | 35 | static int not_configged_read(int fd, char *c_out, void *data) |
45 | { | 36 | { |
46 | printk("Using a channel type which is configured out of " | 37 | printk(KERN_ERR "Using a channel type which is configured out of " |
47 | "UML\n"); | 38 | "UML\n"); |
48 | return -EIO; | 39 | return -EIO; |
49 | } | 40 | } |
50 | 41 | ||
51 | static int not_configged_write(int fd, const char *buf, int len, void *data) | 42 | static int not_configged_write(int fd, const char *buf, int len, void *data) |
52 | { | 43 | { |
53 | printk("Using a channel type which is configured out of " | 44 | printk(KERN_ERR "Using a channel type which is configured out of " |
54 | "UML\n"); | 45 | "UML\n"); |
55 | return -EIO; | 46 | return -EIO; |
56 | } | 47 | } |
57 | 48 | ||
58 | static int not_configged_console_write(int fd, const char *buf, int len) | 49 | static int not_configged_console_write(int fd, const char *buf, int len) |
59 | { | 50 | { |
60 | printk("Using a channel type which is configured out of " | 51 | printk(KERN_ERR "Using a channel type which is configured out of " |
61 | "UML\n"); | 52 | "UML\n"); |
62 | return -EIO; | 53 | return -EIO; |
63 | } | 54 | } |
@@ -65,14 +56,14 @@ static int not_configged_console_write(int fd, const char *buf, int len) | |||
65 | static int not_configged_window_size(int fd, void *data, unsigned short *rows, | 56 | static int not_configged_window_size(int fd, void *data, unsigned short *rows, |
66 | unsigned short *cols) | 57 | unsigned short *cols) |
67 | { | 58 | { |
68 | printk("Using a channel type which is configured out of " | 59 | printk(KERN_ERR "Using a channel type which is configured out of " |
69 | "UML\n"); | 60 | "UML\n"); |
70 | return -ENODEV; | 61 | return -ENODEV; |
71 | } | 62 | } |
72 | 63 | ||
73 | static void not_configged_free(void *data) | 64 | static void not_configged_free(void *data) |
74 | { | 65 | { |
75 | printk("Using a channel type which is configured out of " | 66 | printk(KERN_ERR "Using a channel type which is configured out of " |
76 | "UML\n"); | 67 | "UML\n"); |
77 | } | 68 | } |
78 | 69 | ||
@@ -89,64 +80,17 @@ static const struct chan_ops not_configged_ops = { | |||
89 | }; | 80 | }; |
90 | #endif /* CONFIG_NOCONFIG_CHAN */ | 81 | #endif /* CONFIG_NOCONFIG_CHAN */ |
91 | 82 | ||
92 | void generic_close(int fd, void *unused) | ||
93 | { | ||
94 | os_close_file(fd); | ||
95 | } | ||
96 | |||
97 | int generic_read(int fd, char *c_out, void *unused) | ||
98 | { | ||
99 | int n; | ||
100 | |||
101 | n = os_read_file(fd, c_out, sizeof(*c_out)); | ||
102 | |||
103 | if(n == -EAGAIN) | ||
104 | return 0; | ||
105 | else if(n == 0) | ||
106 | return -EIO; | ||
107 | return n; | ||
108 | } | ||
109 | |||
110 | /* XXX Trivial wrapper around os_write_file */ | ||
111 | |||
112 | int generic_write(int fd, const char *buf, int n, void *unused) | ||
113 | { | ||
114 | return os_write_file(fd, buf, n); | ||
115 | } | ||
116 | |||
117 | int generic_window_size(int fd, void *unused, unsigned short *rows_out, | ||
118 | unsigned short *cols_out) | ||
119 | { | ||
120 | int rows, cols; | ||
121 | int ret; | ||
122 | |||
123 | ret = os_window_size(fd, &rows, &cols); | ||
124 | if(ret < 0) | ||
125 | return ret; | ||
126 | |||
127 | ret = ((*rows_out != rows) || (*cols_out != cols)); | ||
128 | |||
129 | *rows_out = rows; | ||
130 | *cols_out = cols; | ||
131 | |||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | void generic_free(void *data) | ||
136 | { | ||
137 | kfree(data); | ||
138 | } | ||
139 | |||
140 | static void tty_receive_char(struct tty_struct *tty, char ch) | 83 | static void tty_receive_char(struct tty_struct *tty, char ch) |
141 | { | 84 | { |
142 | if(tty == NULL) return; | 85 | if (tty == NULL) |
86 | return; | ||
143 | 87 | ||
144 | if(I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) { | 88 | if (I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) { |
145 | if(ch == STOP_CHAR(tty)){ | 89 | if (ch == STOP_CHAR(tty)) { |
146 | stop_tty(tty); | 90 | stop_tty(tty); |
147 | return; | 91 | return; |
148 | } | 92 | } |
149 | else if(ch == START_CHAR(tty)){ | 93 | else if (ch == START_CHAR(tty)) { |
150 | start_tty(tty); | 94 | start_tty(tty); |
151 | return; | 95 | return; |
152 | } | 96 | } |
@@ -159,14 +103,14 @@ static int open_one_chan(struct chan *chan) | |||
159 | { | 103 | { |
160 | int fd, err; | 104 | int fd, err; |
161 | 105 | ||
162 | if(chan->opened) | 106 | if (chan->opened) |
163 | return 0; | 107 | return 0; |
164 | 108 | ||
165 | if(chan->ops->open == NULL) | 109 | if (chan->ops->open == NULL) |
166 | fd = 0; | 110 | fd = 0; |
167 | else fd = (*chan->ops->open)(chan->input, chan->output, chan->primary, | 111 | else fd = (*chan->ops->open)(chan->input, chan->output, chan->primary, |
168 | chan->data, &chan->dev); | 112 | chan->data, &chan->dev); |
169 | if(fd < 0) | 113 | if (fd < 0) |
170 | return fd; | 114 | return fd; |
171 | 115 | ||
172 | err = os_set_fd_block(fd, 0); | 116 | err = os_set_fd_block(fd, 0); |
@@ -187,10 +131,10 @@ int open_chan(struct list_head *chans) | |||
187 | struct chan *chan; | 131 | struct chan *chan; |
188 | int ret, err = 0; | 132 | int ret, err = 0; |
189 | 133 | ||
190 | list_for_each(ele, chans){ | 134 | list_for_each(ele, chans) { |
191 | chan = list_entry(ele, struct chan, list); | 135 | chan = list_entry(ele, struct chan, list); |
192 | ret = open_one_chan(chan); | 136 | ret = open_one_chan(chan); |
193 | if(chan->primary) | 137 | if (chan->primary) |
194 | err = ret; | 138 | err = ret; |
195 | } | 139 | } |
196 | return err; | 140 | return err; |
@@ -201,9 +145,9 @@ void chan_enable_winch(struct list_head *chans, struct tty_struct *tty) | |||
201 | struct list_head *ele; | 145 | struct list_head *ele; |
202 | struct chan *chan; | 146 | struct chan *chan; |
203 | 147 | ||
204 | list_for_each(ele, chans){ | 148 | list_for_each(ele, chans) { |
205 | chan = list_entry(ele, struct chan, list); | 149 | chan = list_entry(ele, struct chan, list); |
206 | if(chan->primary && chan->output && chan->ops->winch){ | 150 | if (chan->primary && chan->output && chan->ops->winch) { |
207 | register_winch(chan->fd, tty); | 151 | register_winch(chan->fd, tty); |
208 | return; | 152 | return; |
209 | } | 153 | } |
@@ -216,7 +160,7 @@ int enable_chan(struct line *line) | |||
216 | struct chan *chan; | 160 | struct chan *chan; |
217 | int err; | 161 | int err; |
218 | 162 | ||
219 | list_for_each(ele, &line->chan_list){ | 163 | list_for_each(ele, &line->chan_list) { |
220 | chan = list_entry(ele, struct chan, list); | 164 | chan = list_entry(ele, struct chan, list); |
221 | err = open_one_chan(chan); | 165 | err = open_one_chan(chan); |
222 | if (err) { | 166 | if (err) { |
@@ -226,7 +170,7 @@ int enable_chan(struct line *line) | |||
226 | continue; | 170 | continue; |
227 | } | 171 | } |
228 | 172 | ||
229 | if(chan->enabled) | 173 | if (chan->enabled) |
230 | continue; | 174 | continue; |
231 | err = line_setup_irq(chan->fd, chan->input, chan->output, line, | 175 | err = line_setup_irq(chan->fd, chan->input, chan->output, line, |
232 | chan); | 176 | chan); |
@@ -263,12 +207,12 @@ void free_irqs(void) | |||
263 | list_splice_init(&irqs_to_free, &list); | 207 | list_splice_init(&irqs_to_free, &list); |
264 | spin_unlock_irqrestore(&irqs_to_free_lock, flags); | 208 | spin_unlock_irqrestore(&irqs_to_free_lock, flags); |
265 | 209 | ||
266 | list_for_each(ele, &list){ | 210 | list_for_each(ele, &list) { |
267 | chan = list_entry(ele, struct chan, free_list); | 211 | chan = list_entry(ele, struct chan, free_list); |
268 | 212 | ||
269 | if(chan->input) | 213 | if (chan->input) |
270 | free_irq(chan->line->driver->read_irq, chan); | 214 | free_irq(chan->line->driver->read_irq, chan); |
271 | if(chan->output) | 215 | if (chan->output) |
272 | free_irq(chan->line->driver->write_irq, chan); | 216 | free_irq(chan->line->driver->write_irq, chan); |
273 | chan->enabled = 0; | 217 | chan->enabled = 0; |
274 | } | 218 | } |
@@ -278,22 +222,22 @@ static void close_one_chan(struct chan *chan, int delay_free_irq) | |||
278 | { | 222 | { |
279 | unsigned long flags; | 223 | unsigned long flags; |
280 | 224 | ||
281 | if(!chan->opened) | 225 | if (!chan->opened) |
282 | return; | 226 | return; |
283 | 227 | ||
284 | if(delay_free_irq){ | 228 | if (delay_free_irq) { |
285 | spin_lock_irqsave(&irqs_to_free_lock, flags); | 229 | spin_lock_irqsave(&irqs_to_free_lock, flags); |
286 | list_add(&chan->free_list, &irqs_to_free); | 230 | list_add(&chan->free_list, &irqs_to_free); |
287 | spin_unlock_irqrestore(&irqs_to_free_lock, flags); | 231 | spin_unlock_irqrestore(&irqs_to_free_lock, flags); |
288 | } | 232 | } |
289 | else { | 233 | else { |
290 | if(chan->input) | 234 | if (chan->input) |
291 | free_irq(chan->line->driver->read_irq, chan); | 235 | free_irq(chan->line->driver->read_irq, chan); |
292 | if(chan->output) | 236 | if (chan->output) |
293 | free_irq(chan->line->driver->write_irq, chan); | 237 | free_irq(chan->line->driver->write_irq, chan); |
294 | chan->enabled = 0; | 238 | chan->enabled = 0; |
295 | } | 239 | } |
296 | if(chan->ops->close != NULL) | 240 | if (chan->ops->close != NULL) |
297 | (*chan->ops->close)(chan->fd, chan->data); | 241 | (*chan->ops->close)(chan->fd, chan->data); |
298 | 242 | ||
299 | chan->opened = 0; | 243 | chan->opened = 0; |
@@ -322,7 +266,7 @@ void deactivate_chan(struct list_head *chans, int irq) | |||
322 | list_for_each(ele, chans) { | 266 | list_for_each(ele, chans) { |
323 | chan = list_entry(ele, struct chan, list); | 267 | chan = list_entry(ele, struct chan, list); |
324 | 268 | ||
325 | if(chan->enabled && chan->input) | 269 | if (chan->enabled && chan->input) |
326 | deactivate_fd(chan->fd, irq); | 270 | deactivate_fd(chan->fd, irq); |
327 | } | 271 | } |
328 | } | 272 | } |
@@ -335,7 +279,7 @@ void reactivate_chan(struct list_head *chans, int irq) | |||
335 | list_for_each(ele, chans) { | 279 | list_for_each(ele, chans) { |
336 | chan = list_entry(ele, struct chan, list); | 280 | chan = list_entry(ele, struct chan, list); |
337 | 281 | ||
338 | if(chan->enabled && chan->input) | 282 | if (chan->enabled && chan->input) |
339 | reactivate_fd(chan->fd, irq); | 283 | reactivate_fd(chan->fd, irq); |
340 | } | 284 | } |
341 | } | 285 | } |
@@ -347,10 +291,14 @@ int write_chan(struct list_head *chans, const char *buf, int len, | |||
347 | struct chan *chan = NULL; | 291 | struct chan *chan = NULL; |
348 | int n, ret = 0; | 292 | int n, ret = 0; |
349 | 293 | ||
294 | if (len == 0) | ||
295 | return 0; | ||
296 | |||
350 | list_for_each(ele, chans) { | 297 | list_for_each(ele, chans) { |
351 | chan = list_entry(ele, struct chan, list); | 298 | chan = list_entry(ele, struct chan, list); |
352 | if (!chan->output || (chan->ops->write == NULL)) | 299 | if (!chan->output || (chan->ops->write == NULL)) |
353 | continue; | 300 | continue; |
301 | |||
354 | n = chan->ops->write(chan->fd, buf, len, chan->data); | 302 | n = chan->ops->write(chan->fd, buf, len, chan->data); |
355 | if (chan->primary) { | 303 | if (chan->primary) { |
356 | ret = n; | 304 | ret = n; |
@@ -367,12 +315,14 @@ int console_write_chan(struct list_head *chans, const char *buf, int len) | |||
367 | struct chan *chan; | 315 | struct chan *chan; |
368 | int n, ret = 0; | 316 | int n, ret = 0; |
369 | 317 | ||
370 | list_for_each(ele, chans){ | 318 | list_for_each(ele, chans) { |
371 | chan = list_entry(ele, struct chan, list); | 319 | chan = list_entry(ele, struct chan, list); |
372 | if(!chan->output || (chan->ops->console_write == NULL)) | 320 | if (!chan->output || (chan->ops->console_write == NULL)) |
373 | continue; | 321 | continue; |
322 | |||
374 | n = chan->ops->console_write(chan->fd, buf, len); | 323 | n = chan->ops->console_write(chan->fd, buf, len); |
375 | if(chan->primary) ret = n; | 324 | if (chan->primary) |
325 | ret = n; | ||
376 | } | 326 | } |
377 | return ret; | 327 | return ret; |
378 | } | 328 | } |
@@ -382,10 +332,11 @@ int console_open_chan(struct line *line, struct console *co) | |||
382 | int err; | 332 | int err; |
383 | 333 | ||
384 | err = open_chan(&line->chan_list); | 334 | err = open_chan(&line->chan_list); |
385 | if(err) | 335 | if (err) |
386 | return err; | 336 | return err; |
387 | 337 | ||
388 | printk("Console initialized on /dev/%s%d\n", co->name, co->index); | 338 | printk(KERN_INFO "Console initialized on /dev/%s%d\n", co->name, |
339 | co->index); | ||
389 | return 0; | 340 | return 0; |
390 | } | 341 | } |
391 | 342 | ||
@@ -395,10 +346,10 @@ int chan_window_size(struct list_head *chans, unsigned short *rows_out, | |||
395 | struct list_head *ele; | 346 | struct list_head *ele; |
396 | struct chan *chan; | 347 | struct chan *chan; |
397 | 348 | ||
398 | list_for_each(ele, chans){ | 349 | list_for_each(ele, chans) { |
399 | chan = list_entry(ele, struct chan, list); | 350 | chan = list_entry(ele, struct chan, list); |
400 | if(chan->primary){ | 351 | if (chan->primary) { |
401 | if(chan->ops->window_size == NULL) | 352 | if (chan->ops->window_size == NULL) |
402 | return 0; | 353 | return 0; |
403 | return chan->ops->window_size(chan->fd, chan->data, | 354 | return chan->ops->window_size(chan->fd, chan->data, |
404 | rows_out, cols_out); | 355 | rows_out, cols_out); |
@@ -413,10 +364,11 @@ static void free_one_chan(struct chan *chan, int delay_free_irq) | |||
413 | 364 | ||
414 | close_one_chan(chan, delay_free_irq); | 365 | close_one_chan(chan, delay_free_irq); |
415 | 366 | ||
416 | if(chan->ops->free != NULL) | 367 | if (chan->ops->free != NULL) |
417 | (*chan->ops->free)(chan->data); | 368 | (*chan->ops->free)(chan->data); |
418 | 369 | ||
419 | if(chan->primary && chan->output) ignore_sigio_fd(chan->fd); | 370 | if (chan->primary && chan->output) |
371 | ignore_sigio_fd(chan->fd); | ||
420 | kfree(chan); | 372 | kfree(chan); |
421 | } | 373 | } |
422 | 374 | ||
@@ -425,7 +377,7 @@ static void free_chan(struct list_head *chans, int delay_free_irq) | |||
425 | struct list_head *ele, *next; | 377 | struct list_head *ele, *next; |
426 | struct chan *chan; | 378 | struct chan *chan; |
427 | 379 | ||
428 | list_for_each_safe(ele, next, chans){ | 380 | list_for_each_safe(ele, next, chans) { |
429 | chan = list_entry(ele, struct chan, list); | 381 | chan = list_entry(ele, struct chan, list); |
430 | free_one_chan(chan, delay_free_irq); | 382 | free_one_chan(chan, delay_free_irq); |
431 | } | 383 | } |
@@ -436,14 +388,14 @@ static int one_chan_config_string(struct chan *chan, char *str, int size, | |||
436 | { | 388 | { |
437 | int n = 0; | 389 | int n = 0; |
438 | 390 | ||
439 | if(chan == NULL){ | 391 | if (chan == NULL) { |
440 | CONFIG_CHUNK(str, size, n, "none", 1); | 392 | CONFIG_CHUNK(str, size, n, "none", 1); |
441 | return n; | 393 | return n; |
442 | } | 394 | } |
443 | 395 | ||
444 | CONFIG_CHUNK(str, size, n, chan->ops->type, 0); | 396 | CONFIG_CHUNK(str, size, n, chan->ops->type, 0); |
445 | 397 | ||
446 | if(chan->dev == NULL){ | 398 | if (chan->dev == NULL) { |
447 | CONFIG_CHUNK(str, size, n, "", 1); | 399 | CONFIG_CHUNK(str, size, n, "", 1); |
448 | return n; | 400 | return n; |
449 | } | 401 | } |
@@ -463,7 +415,7 @@ static int chan_pair_config_string(struct chan *in, struct chan *out, | |||
463 | str += n; | 415 | str += n; |
464 | size -= n; | 416 | size -= n; |
465 | 417 | ||
466 | if(in == out){ | 418 | if (in == out) { |
467 | CONFIG_CHUNK(str, size, n, "", 1); | 419 | CONFIG_CHUNK(str, size, n, "", 1); |
468 | return n; | 420 | return n; |
469 | } | 421 | } |
@@ -483,13 +435,13 @@ int chan_config_string(struct list_head *chans, char *str, int size, | |||
483 | struct list_head *ele; | 435 | struct list_head *ele; |
484 | struct chan *chan, *in = NULL, *out = NULL; | 436 | struct chan *chan, *in = NULL, *out = NULL; |
485 | 437 | ||
486 | list_for_each(ele, chans){ | 438 | list_for_each(ele, chans) { |
487 | chan = list_entry(ele, struct chan, list); | 439 | chan = list_entry(ele, struct chan, list); |
488 | if(!chan->primary) | 440 | if (!chan->primary) |
489 | continue; | 441 | continue; |
490 | if(chan->input) | 442 | if (chan->input) |
491 | in = chan; | 443 | in = chan; |
492 | if(chan->output) | 444 | if (chan->output) |
493 | out = chan; | 445 | out = chan; |
494 | } | 446 | } |
495 | 447 | ||
@@ -548,27 +500,27 @@ static struct chan *parse_chan(struct line *line, char *str, int device, | |||
548 | 500 | ||
549 | ops = NULL; | 501 | ops = NULL; |
550 | data = NULL; | 502 | data = NULL; |
551 | for(i = 0; i < ARRAY_SIZE(chan_table); i++){ | 503 | for(i = 0; i < ARRAY_SIZE(chan_table); i++) { |
552 | entry = &chan_table[i]; | 504 | entry = &chan_table[i]; |
553 | if(!strncmp(str, entry->key, strlen(entry->key))){ | 505 | if (!strncmp(str, entry->key, strlen(entry->key))) { |
554 | ops = entry->ops; | 506 | ops = entry->ops; |
555 | str += strlen(entry->key); | 507 | str += strlen(entry->key); |
556 | break; | 508 | break; |
557 | } | 509 | } |
558 | } | 510 | } |
559 | if(ops == NULL){ | 511 | if (ops == NULL) { |
560 | *error_out = "No match for configured backends"; | 512 | *error_out = "No match for configured backends"; |
561 | return NULL; | 513 | return NULL; |
562 | } | 514 | } |
563 | 515 | ||
564 | data = (*ops->init)(str, device, opts); | 516 | data = (*ops->init)(str, device, opts); |
565 | if(data == NULL){ | 517 | if (data == NULL) { |
566 | *error_out = "Configuration failed"; | 518 | *error_out = "Configuration failed"; |
567 | return NULL; | 519 | return NULL; |
568 | } | 520 | } |
569 | 521 | ||
570 | chan = kmalloc(sizeof(*chan), GFP_ATOMIC); | 522 | chan = kmalloc(sizeof(*chan), GFP_ATOMIC); |
571 | if(chan == NULL){ | 523 | if (chan == NULL) { |
572 | *error_out = "Memory allocation failed"; | 524 | *error_out = "Memory allocation failed"; |
573 | return NULL; | 525 | return NULL; |
574 | } | 526 | } |
@@ -594,26 +546,26 @@ int parse_chan_pair(char *str, struct line *line, int device, | |||
594 | struct chan *new, *chan; | 546 | struct chan *new, *chan; |
595 | char *in, *out; | 547 | char *in, *out; |
596 | 548 | ||
597 | if(!list_empty(chans)){ | 549 | if (!list_empty(chans)) { |
598 | chan = list_entry(chans->next, struct chan, list); | 550 | chan = list_entry(chans->next, struct chan, list); |
599 | free_chan(chans, 0); | 551 | free_chan(chans, 0); |
600 | INIT_LIST_HEAD(chans); | 552 | INIT_LIST_HEAD(chans); |
601 | } | 553 | } |
602 | 554 | ||
603 | out = strchr(str, ','); | 555 | out = strchr(str, ','); |
604 | if(out != NULL){ | 556 | if (out != NULL) { |
605 | in = str; | 557 | in = str; |
606 | *out = '\0'; | 558 | *out = '\0'; |
607 | out++; | 559 | out++; |
608 | new = parse_chan(line, in, device, opts, error_out); | 560 | new = parse_chan(line, in, device, opts, error_out); |
609 | if(new == NULL) | 561 | if (new == NULL) |
610 | return -1; | 562 | return -1; |
611 | 563 | ||
612 | new->input = 1; | 564 | new->input = 1; |
613 | list_add(&new->list, chans); | 565 | list_add(&new->list, chans); |
614 | 566 | ||
615 | new = parse_chan(line, out, device, opts, error_out); | 567 | new = parse_chan(line, out, device, opts, error_out); |
616 | if(new == NULL) | 568 | if (new == NULL) |
617 | return -1; | 569 | return -1; |
618 | 570 | ||
619 | list_add(&new->list, chans); | 571 | list_add(&new->list, chans); |
@@ -621,7 +573,7 @@ int parse_chan_pair(char *str, struct line *line, int device, | |||
621 | } | 573 | } |
622 | else { | 574 | else { |
623 | new = parse_chan(line, str, device, opts, error_out); | 575 | new = parse_chan(line, str, device, opts, error_out); |
624 | if(new == NULL) | 576 | if (new == NULL) |
625 | return -1; | 577 | return -1; |
626 | 578 | ||
627 | list_add(&new->list, chans); | 579 | list_add(&new->list, chans); |
@@ -636,9 +588,9 @@ int chan_out_fd(struct list_head *chans) | |||
636 | struct list_head *ele; | 588 | struct list_head *ele; |
637 | struct chan *chan; | 589 | struct chan *chan; |
638 | 590 | ||
639 | list_for_each(ele, chans){ | 591 | list_for_each(ele, chans) { |
640 | chan = list_entry(ele, struct chan, list); | 592 | chan = list_entry(ele, struct chan, list); |
641 | if(chan->primary && chan->output) | 593 | if (chan->primary && chan->output) |
642 | return chan->fd; | 594 | return chan->fd; |
643 | } | 595 | } |
644 | return -1; | 596 | return -1; |
@@ -652,23 +604,25 @@ void chan_interrupt(struct list_head *chans, struct delayed_work *task, | |||
652 | int err; | 604 | int err; |
653 | char c; | 605 | char c; |
654 | 606 | ||
655 | list_for_each_safe(ele, next, chans){ | 607 | list_for_each_safe(ele, next, chans) { |
656 | chan = list_entry(ele, struct chan, list); | 608 | chan = list_entry(ele, struct chan, list); |
657 | if(!chan->input || (chan->ops->read == NULL)) continue; | 609 | if (!chan->input || (chan->ops->read == NULL)) |
610 | continue; | ||
658 | do { | 611 | do { |
659 | if (tty && !tty_buffer_request_room(tty, 1)) { | 612 | if (tty && !tty_buffer_request_room(tty, 1)) { |
660 | schedule_delayed_work(task, 1); | 613 | schedule_delayed_work(task, 1); |
661 | goto out; | 614 | goto out; |
662 | } | 615 | } |
663 | err = chan->ops->read(chan->fd, &c, chan->data); | 616 | err = chan->ops->read(chan->fd, &c, chan->data); |
664 | if(err > 0) | 617 | if (err > 0) |
665 | tty_receive_char(tty, c); | 618 | tty_receive_char(tty, c); |
666 | } while(err > 0); | 619 | } while (err > 0); |
667 | 620 | ||
668 | if(err == 0) reactivate_fd(chan->fd, irq); | 621 | if (err == 0) |
669 | if(err == -EIO){ | 622 | reactivate_fd(chan->fd, irq); |
670 | if(chan->primary){ | 623 | if (err == -EIO) { |
671 | if(tty != NULL) | 624 | if (chan->primary) { |
625 | if (tty != NULL) | ||
672 | tty_hangup(tty); | 626 | tty_hangup(tty); |
673 | close_chan(chans, 1); | 627 | close_chan(chans, 1); |
674 | return; | 628 | return; |
@@ -677,5 +631,6 @@ void chan_interrupt(struct list_head *chans, struct delayed_work *task, | |||
677 | } | 631 | } |
678 | } | 632 | } |
679 | out: | 633 | out: |
680 | if(tty) tty_flip_buffer_push(tty); | 634 | if (tty) |
635 | tty_flip_buffer_push(tty); | ||
681 | } | 636 | } |
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index 4d438f36ea2e..b88e93b3a39f 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c | |||
@@ -1,51 +1,107 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <unistd.h> | ||
7 | #include <stdlib.h> | 6 | #include <stdlib.h> |
7 | #include <unistd.h> | ||
8 | #include <errno.h> | 8 | #include <errno.h> |
9 | #include <termios.h> | ||
10 | #include <string.h> | ||
11 | #include <signal.h> | ||
12 | #include <sched.h> | 9 | #include <sched.h> |
13 | #include <sys/stat.h> | 10 | #include <signal.h> |
11 | #include <termios.h> | ||
14 | #include <sys/ioctl.h> | 12 | #include <sys/ioctl.h> |
15 | #include <sys/socket.h> | ||
16 | #include "kern_util.h" | ||
17 | #include "chan_user.h" | 13 | #include "chan_user.h" |
18 | #include "user.h" | ||
19 | #include "os.h" | 14 | #include "os.h" |
20 | #include "choose-mode.h" | 15 | #include "um_malloc.h" |
21 | #include "mode.h" | 16 | #include "user.h" |
17 | |||
18 | void generic_close(int fd, void *unused) | ||
19 | { | ||
20 | close(fd); | ||
21 | } | ||
22 | |||
23 | int generic_read(int fd, char *c_out, void *unused) | ||
24 | { | ||
25 | int n; | ||
26 | |||
27 | n = read(fd, c_out, sizeof(*c_out)); | ||
28 | if (n > 0) | ||
29 | return n; | ||
30 | else if (errno == EAGAIN) | ||
31 | return 0; | ||
32 | else if (n == 0) | ||
33 | return -EIO; | ||
34 | return -errno; | ||
35 | } | ||
36 | |||
37 | /* XXX Trivial wrapper around write */ | ||
38 | |||
39 | int generic_write(int fd, const char *buf, int n, void *unused) | ||
40 | { | ||
41 | int err; | ||
42 | |||
43 | err = write(fd, buf, n); | ||
44 | if (err > 0) | ||
45 | return err; | ||
46 | else if (errno == EAGAIN) | ||
47 | return 0; | ||
48 | else if (err == 0) | ||
49 | return -EIO; | ||
50 | return -errno; | ||
51 | } | ||
52 | |||
53 | int generic_window_size(int fd, void *unused, unsigned short *rows_out, | ||
54 | unsigned short *cols_out) | ||
55 | { | ||
56 | struct winsize size; | ||
57 | int ret; | ||
58 | |||
59 | if (ioctl(fd, TIOCGWINSZ, &size) < 0) | ||
60 | return -errno; | ||
61 | |||
62 | ret = ((*rows_out != size.ws_row) || (*cols_out != size.ws_col)); | ||
63 | |||
64 | *rows_out = size.ws_row; | ||
65 | *cols_out = size.ws_col; | ||
66 | |||
67 | return ret; | ||
68 | } | ||
69 | |||
70 | void generic_free(void *data) | ||
71 | { | ||
72 | kfree(data); | ||
73 | } | ||
22 | 74 | ||
23 | int generic_console_write(int fd, const char *buf, int n) | 75 | int generic_console_write(int fd, const char *buf, int n) |
24 | { | 76 | { |
25 | struct termios save, new; | 77 | struct termios save, new; |
26 | int err; | 78 | int err; |
27 | 79 | ||
28 | if(isatty(fd)){ | 80 | if (isatty(fd)) { |
29 | CATCH_EINTR(err = tcgetattr(fd, &save)); | 81 | CATCH_EINTR(err = tcgetattr(fd, &save)); |
30 | if (err) | 82 | if (err) |
31 | goto error; | 83 | goto error; |
32 | new = save; | 84 | new = save; |
33 | /* The terminal becomes a bit less raw, to handle \n also as | 85 | /* |
86 | * The terminal becomes a bit less raw, to handle \n also as | ||
34 | * "Carriage Return", not only as "New Line". Otherwise, the new | 87 | * "Carriage Return", not only as "New Line". Otherwise, the new |
35 | * line won't start at the first column.*/ | 88 | * line won't start at the first column. |
89 | */ | ||
36 | new.c_oflag |= OPOST; | 90 | new.c_oflag |= OPOST; |
37 | CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &new)); | 91 | CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &new)); |
38 | if (err) | 92 | if (err) |
39 | goto error; | 93 | goto error; |
40 | } | 94 | } |
41 | err = generic_write(fd, buf, n, NULL); | 95 | err = generic_write(fd, buf, n, NULL); |
42 | /* Restore raw mode, in any case; we *must* ignore any error apart | 96 | /* |
43 | * EINTR, except for debug.*/ | 97 | * Restore raw mode, in any case; we *must* ignore any error apart |
44 | if(isatty(fd)) | 98 | * EINTR, except for debug. |
99 | */ | ||
100 | if (isatty(fd)) | ||
45 | CATCH_EINTR(tcsetattr(fd, TCSAFLUSH, &save)); | 101 | CATCH_EINTR(tcsetattr(fd, TCSAFLUSH, &save)); |
46 | return(err); | 102 | return err; |
47 | error: | 103 | error: |
48 | return(-errno); | 104 | return -errno; |
49 | } | 105 | } |
50 | 106 | ||
51 | /* | 107 | /* |
@@ -82,62 +138,73 @@ static int winch_thread(void *arg) | |||
82 | struct winch_data *data = arg; | 138 | struct winch_data *data = arg; |
83 | sigset_t sigs; | 139 | sigset_t sigs; |
84 | int pty_fd, pipe_fd; | 140 | int pty_fd, pipe_fd; |
85 | int count, err; | 141 | int count; |
86 | char c = 1; | 142 | char c = 1; |
87 | 143 | ||
88 | pty_fd = data->pty_fd; | 144 | pty_fd = data->pty_fd; |
89 | pipe_fd = data->pipe_fd; | 145 | pipe_fd = data->pipe_fd; |
90 | count = os_write_file(pipe_fd, &c, sizeof(c)); | 146 | count = write(pipe_fd, &c, sizeof(c)); |
91 | if(count != sizeof(c)) | 147 | if (count != sizeof(c)) |
92 | printk("winch_thread : failed to write synchronization " | 148 | printk(UM_KERN_ERR "winch_thread : failed to write " |
93 | "byte, err = %d\n", -count); | 149 | "synchronization byte, err = %d\n", -count); |
94 | 150 | ||
95 | /* We are not using SIG_IGN on purpose, so don't fix it as I thought to | 151 | /* |
152 | * We are not using SIG_IGN on purpose, so don't fix it as I thought to | ||
96 | * do! If using SIG_IGN, the sigsuspend() call below would not stop on | 153 | * do! If using SIG_IGN, the sigsuspend() call below would not stop on |
97 | * SIGWINCH. */ | 154 | * SIGWINCH. |
155 | */ | ||
98 | 156 | ||
99 | signal(SIGWINCH, winch_handler); | 157 | signal(SIGWINCH, winch_handler); |
100 | sigfillset(&sigs); | 158 | sigfillset(&sigs); |
101 | /* Block all signals possible. */ | 159 | /* Block all signals possible. */ |
102 | if(sigprocmask(SIG_SETMASK, &sigs, NULL) < 0){ | 160 | if (sigprocmask(SIG_SETMASK, &sigs, NULL) < 0) { |
103 | printk("winch_thread : sigprocmask failed, errno = %d\n", | 161 | printk(UM_KERN_ERR "winch_thread : sigprocmask failed, " |
104 | errno); | 162 | "errno = %d\n", errno); |
105 | exit(1); | 163 | exit(1); |
106 | } | 164 | } |
107 | /* In sigsuspend(), block anything else than SIGWINCH. */ | 165 | /* In sigsuspend(), block anything else than SIGWINCH. */ |
108 | sigdelset(&sigs, SIGWINCH); | 166 | sigdelset(&sigs, SIGWINCH); |
109 | 167 | ||
110 | if(setsid() < 0){ | 168 | if (setsid() < 0) { |
111 | printk("winch_thread : setsid failed, errno = %d\n", errno); | 169 | printk(UM_KERN_ERR "winch_thread : setsid failed, errno = %d\n", |
170 | errno); | ||
171 | exit(1); | ||
172 | } | ||
173 | |||
174 | if (ioctl(pty_fd, TIOCSCTTY, 0) < 0) { | ||
175 | printk(UM_KERN_ERR "winch_thread : TIOCSCTTY failed on " | ||
176 | "fd %d err = %d\n", pty_fd, errno); | ||
112 | exit(1); | 177 | exit(1); |
113 | } | 178 | } |
114 | 179 | ||
115 | err = os_new_tty_pgrp(pty_fd, os_getpid()); | 180 | if (tcsetpgrp(pty_fd, os_getpid()) < 0) { |
116 | if(err < 0){ | 181 | printk(UM_KERN_ERR "winch_thread : tcsetpgrp failed on " |
117 | printk("winch_thread : new_tty_pgrp failed on fd %d, " | 182 | "fd %d err = %d\n", pty_fd, errno); |
118 | "err = %d\n", pty_fd, -err); | ||
119 | exit(1); | 183 | exit(1); |
120 | } | 184 | } |
121 | 185 | ||
122 | /* These are synchronization calls between various UML threads on the | 186 | /* |
187 | * These are synchronization calls between various UML threads on the | ||
123 | * host - since they are not different kernel threads, we cannot use | 188 | * host - since they are not different kernel threads, we cannot use |
124 | * kernel semaphores. We don't use SysV semaphores because they are | 189 | * kernel semaphores. We don't use SysV semaphores because they are |
125 | * persistent. */ | 190 | * persistent. |
126 | count = os_read_file(pipe_fd, &c, sizeof(c)); | 191 | */ |
127 | if(count != sizeof(c)) | 192 | count = read(pipe_fd, &c, sizeof(c)); |
128 | printk("winch_thread : failed to read synchronization byte, " | 193 | if (count != sizeof(c)) |
129 | "err = %d\n", -count); | 194 | printk(UM_KERN_ERR "winch_thread : failed to read " |
130 | 195 | "synchronization byte, err = %d\n", errno); | |
131 | while(1){ | 196 | |
132 | /* This will be interrupted by SIGWINCH only, since | 197 | while(1) { |
198 | /* | ||
199 | * This will be interrupted by SIGWINCH only, since | ||
133 | * other signals are blocked. | 200 | * other signals are blocked. |
134 | */ | 201 | */ |
135 | sigsuspend(&sigs); | 202 | sigsuspend(&sigs); |
136 | 203 | ||
137 | count = os_write_file(pipe_fd, &c, sizeof(c)); | 204 | count = write(pipe_fd, &c, sizeof(c)); |
138 | if(count != sizeof(c)) | 205 | if (count != sizeof(c)) |
139 | printk("winch_thread : write failed, err = %d\n", | 206 | printk(UM_KERN_ERR "winch_thread : write failed, " |
140 | -count); | 207 | "err = %d\n", errno); |
141 | } | 208 | } |
142 | } | 209 | } |
143 | 210 | ||
@@ -149,44 +216,49 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out, | |||
149 | char c; | 216 | char c; |
150 | 217 | ||
151 | err = os_pipe(fds, 1, 1); | 218 | err = os_pipe(fds, 1, 1); |
152 | if(err < 0){ | 219 | if (err < 0) { |
153 | printk("winch_tramp : os_pipe failed, err = %d\n", -err); | 220 | printk(UM_KERN_ERR "winch_tramp : os_pipe failed, err = %d\n", |
221 | -err); | ||
154 | goto out; | 222 | goto out; |
155 | } | 223 | } |
156 | 224 | ||
157 | data = ((struct winch_data) { .pty_fd = fd, | 225 | data = ((struct winch_data) { .pty_fd = fd, |
158 | .pipe_fd = fds[1] } ); | 226 | .pipe_fd = fds[1] } ); |
159 | /* CLONE_FILES so this thread doesn't hold open files which are open | 227 | /* |
228 | * CLONE_FILES so this thread doesn't hold open files which are open | ||
160 | * now, but later closed in a different thread. This is a | 229 | * now, but later closed in a different thread. This is a |
161 | * problem with /dev/net/tun, which if held open by this | 230 | * problem with /dev/net/tun, which if held open by this |
162 | * thread, prevents the TUN/TAP device from being reused. | 231 | * thread, prevents the TUN/TAP device from being reused. |
163 | */ | 232 | */ |
164 | err = run_helper_thread(winch_thread, &data, CLONE_FILES, stack_out); | 233 | err = run_helper_thread(winch_thread, &data, CLONE_FILES, stack_out); |
165 | if(err < 0){ | 234 | if (err < 0) { |
166 | printk("fork of winch_thread failed - errno = %d\n", -err); | 235 | printk(UM_KERN_ERR "fork of winch_thread failed - errno = %d\n", |
236 | -err); | ||
167 | goto out_close; | 237 | goto out_close; |
168 | } | 238 | } |
169 | 239 | ||
170 | *fd_out = fds[0]; | 240 | *fd_out = fds[0]; |
171 | n = os_read_file(fds[0], &c, sizeof(c)); | 241 | n = read(fds[0], &c, sizeof(c)); |
172 | if(n != sizeof(c)){ | 242 | if (n != sizeof(c)) { |
173 | printk("winch_tramp : failed to read synchronization byte\n"); | 243 | printk(UM_KERN_ERR "winch_tramp : failed to read " |
174 | printk("read failed, err = %d\n", -n); | 244 | "synchronization byte\n"); |
175 | printk("fd %d will not support SIGWINCH\n", fd); | 245 | printk(UM_KERN_ERR "read failed, err = %d\n", errno); |
176 | err = -EINVAL; | 246 | printk(UM_KERN_ERR "fd %d will not support SIGWINCH\n", fd); |
247 | err = -EINVAL; | ||
177 | goto out_close; | 248 | goto out_close; |
178 | } | 249 | } |
179 | 250 | ||
180 | if (os_set_fd_block(*fd_out, 0)) { | 251 | if (os_set_fd_block(*fd_out, 0)) { |
181 | printk("winch_tramp: failed to set thread_fd non-blocking.\n"); | 252 | printk(UM_KERN_ERR "winch_tramp: failed to set thread_fd " |
253 | "non-blocking.\n"); | ||
182 | goto out_close; | 254 | goto out_close; |
183 | } | 255 | } |
184 | 256 | ||
185 | return err; | 257 | return err; |
186 | 258 | ||
187 | out_close: | 259 | out_close: |
188 | os_close_file(fds[1]); | 260 | close(fds[1]); |
189 | os_close_file(fds[0]); | 261 | close(fds[0]); |
190 | out: | 262 | out: |
191 | return err; | 263 | return err; |
192 | } | 264 | } |
@@ -197,21 +269,20 @@ void register_winch(int fd, struct tty_struct *tty) | |||
197 | int pid, thread, count, thread_fd = -1; | 269 | int pid, thread, count, thread_fd = -1; |
198 | char c = 1; | 270 | char c = 1; |
199 | 271 | ||
200 | if(!isatty(fd)) | 272 | if (!isatty(fd)) |
201 | return; | 273 | return; |
202 | 274 | ||
203 | pid = tcgetpgrp(fd); | 275 | pid = tcgetpgrp(fd); |
204 | if (!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd, tty) && | 276 | if (!is_skas_winch(pid, fd, tty) && (pid == -1)) { |
205 | (pid == -1)) { | ||
206 | thread = winch_tramp(fd, tty, &thread_fd, &stack); | 277 | thread = winch_tramp(fd, tty, &thread_fd, &stack); |
207 | if (thread < 0) | 278 | if (thread < 0) |
208 | return; | 279 | return; |
209 | 280 | ||
210 | register_winch_irq(thread_fd, fd, thread, tty, stack); | 281 | register_winch_irq(thread_fd, fd, thread, tty, stack); |
211 | 282 | ||
212 | count = os_write_file(thread_fd, &c, sizeof(c)); | 283 | count = write(thread_fd, &c, sizeof(c)); |
213 | if(count != sizeof(c)) | 284 | if (count != sizeof(c)) |
214 | printk("register_winch : failed to write " | 285 | printk(UM_KERN_ERR "register_winch : failed to write " |
215 | "synchronization byte, err = %d\n", -count); | 286 | "synchronization byte, err = %d\n", errno); |
216 | } | 287 | } |
217 | } | 288 | } |
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c index 0ec4052db9c5..93f227a25ba4 100644 --- a/arch/um/drivers/cow_user.c +++ b/arch/um/drivers/cow_user.c | |||
@@ -1,17 +1,18 @@ | |||
1 | #include <stddef.h> | 1 | /* |
2 | #include <string.h> | 2 | * Copyright (C) 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) |
3 | #include <errno.h> | 3 | * Licensed under the GPL |
4 | /* _XOPEN_SOURCE is needed for pread, but we define _GNU_SOURCE, which defines | 4 | */ |
5 | |||
6 | /* | ||
7 | * _XOPEN_SOURCE is needed for pread, but we define _GNU_SOURCE, which defines | ||
5 | * that. | 8 | * that. |
6 | */ | 9 | */ |
7 | #include <unistd.h> | 10 | #include <unistd.h> |
8 | #include <byteswap.h> | 11 | #include <byteswap.h> |
9 | #include <sys/time.h> | 12 | #include <errno.h> |
10 | #include <sys/param.h> | 13 | #include <string.h> |
11 | #include <sys/user.h> | 14 | #include <arpa/inet.h> |
12 | 15 | #include <asm/types.h> | |
13 | #include "os.h" | ||
14 | |||
15 | #include "cow.h" | 16 | #include "cow.h" |
16 | #include "cow_sys.h" | 17 | #include "cow_sys.h" |
17 | 18 | ||
@@ -28,7 +29,8 @@ struct cow_header_v1 { | |||
28 | __s32 sectorsize; | 29 | __s32 sectorsize; |
29 | } __attribute__((packed)); | 30 | } __attribute__((packed)); |
30 | 31 | ||
31 | /* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in | 32 | /* |
33 | * Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in | ||
32 | * case other systems have different values for MAXPATHLEN. | 34 | * case other systems have different values for MAXPATHLEN. |
33 | * | 35 | * |
34 | * The same must hold for V2 - we want file format compatibility, not anything | 36 | * The same must hold for V2 - we want file format compatibility, not anything |
@@ -46,7 +48,8 @@ struct cow_header_v2 { | |||
46 | __s32 sectorsize; | 48 | __s32 sectorsize; |
47 | } __attribute__((packed)); | 49 | } __attribute__((packed)); |
48 | 50 | ||
49 | /* Changes from V2 - | 51 | /* |
52 | * Changes from V2 - | ||
50 | * PATH_LEN_V3 as described above | 53 | * PATH_LEN_V3 as described above |
51 | * Explicitly specify field bit lengths for systems with different | 54 | * Explicitly specify field bit lengths for systems with different |
52 | * lengths for the usual C types. Not sure whether char or | 55 | * lengths for the usual C types. Not sure whether char or |
@@ -70,7 +73,8 @@ struct cow_header_v2 { | |||
70 | * Fixed (finally!) the rounding bug | 73 | * Fixed (finally!) the rounding bug |
71 | */ | 74 | */ |
72 | 75 | ||
73 | /* Until Dec2005, __attribute__((packed)) was left out from the below | 76 | /* |
77 | * Until Dec2005, __attribute__((packed)) was left out from the below | ||
74 | * definition, leading on 64-bit systems to 4 bytes of padding after mtime, to | 78 | * definition, leading on 64-bit systems to 4 bytes of padding after mtime, to |
75 | * align size to 8-byte alignment. This shifted all fields above (no padding | 79 | * align size to 8-byte alignment. This shifted all fields above (no padding |
76 | * was present on 32-bit, no other padding was added). | 80 | * was present on 32-bit, no other padding was added). |
@@ -122,7 +126,7 @@ void cow_sizes(int version, __u64 size, int sectorsize, int align, | |||
122 | int bitmap_offset, unsigned long *bitmap_len_out, | 126 | int bitmap_offset, unsigned long *bitmap_len_out, |
123 | int *data_offset_out) | 127 | int *data_offset_out) |
124 | { | 128 | { |
125 | if(version < 3){ | 129 | if (version < 3) { |
126 | *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize); | 130 | *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize); |
127 | 131 | ||
128 | *data_offset_out = bitmap_offset + *bitmap_len_out; | 132 | *data_offset_out = bitmap_offset + *bitmap_len_out; |
@@ -144,46 +148,46 @@ static int absolutize(char *to, int size, char *from) | |||
144 | char save_cwd[256], *slash; | 148 | char save_cwd[256], *slash; |
145 | int remaining; | 149 | int remaining; |
146 | 150 | ||
147 | if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) { | 151 | if (getcwd(save_cwd, sizeof(save_cwd)) == NULL) { |
148 | cow_printf("absolutize : unable to get cwd - errno = %d\n", | 152 | cow_printf("absolutize : unable to get cwd - errno = %d\n", |
149 | errno); | 153 | errno); |
150 | return(-1); | 154 | return -1; |
151 | } | 155 | } |
152 | slash = strrchr(from, '/'); | 156 | slash = strrchr(from, '/'); |
153 | if(slash != NULL){ | 157 | if (slash != NULL) { |
154 | *slash = '\0'; | 158 | *slash = '\0'; |
155 | if(chdir(from)){ | 159 | if (chdir(from)) { |
156 | *slash = '/'; | 160 | *slash = '/'; |
157 | cow_printf("absolutize : Can't cd to '%s' - " | 161 | cow_printf("absolutize : Can't cd to '%s' - " |
158 | "errno = %d\n", from, errno); | 162 | "errno = %d\n", from, errno); |
159 | return(-1); | 163 | return -1; |
160 | } | 164 | } |
161 | *slash = '/'; | 165 | *slash = '/'; |
162 | if(getcwd(to, size) == NULL){ | 166 | if (getcwd(to, size) == NULL) { |
163 | cow_printf("absolutize : unable to get cwd of '%s' - " | 167 | cow_printf("absolutize : unable to get cwd of '%s' - " |
164 | "errno = %d\n", from, errno); | 168 | "errno = %d\n", from, errno); |
165 | return(-1); | 169 | return -1; |
166 | } | 170 | } |
167 | remaining = size - strlen(to); | 171 | remaining = size - strlen(to); |
168 | if(strlen(slash) + 1 > remaining){ | 172 | if (strlen(slash) + 1 > remaining) { |
169 | cow_printf("absolutize : unable to fit '%s' into %d " | 173 | cow_printf("absolutize : unable to fit '%s' into %d " |
170 | "chars\n", from, size); | 174 | "chars\n", from, size); |
171 | return(-1); | 175 | return -1; |
172 | } | 176 | } |
173 | strcat(to, slash); | 177 | strcat(to, slash); |
174 | } | 178 | } |
175 | else { | 179 | else { |
176 | if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){ | 180 | if (strlen(save_cwd) + 1 + strlen(from) + 1 > size) { |
177 | cow_printf("absolutize : unable to fit '%s' into %d " | 181 | cow_printf("absolutize : unable to fit '%s' into %d " |
178 | "chars\n", from, size); | 182 | "chars\n", from, size); |
179 | return(-1); | 183 | return -1; |
180 | } | 184 | } |
181 | strcpy(to, save_cwd); | 185 | strcpy(to, save_cwd); |
182 | strcat(to, "/"); | 186 | strcat(to, "/"); |
183 | strcat(to, from); | 187 | strcat(to, from); |
184 | } | 188 | } |
185 | chdir(save_cwd); | 189 | chdir(save_cwd); |
186 | return(0); | 190 | return 0; |
187 | } | 191 | } |
188 | 192 | ||
189 | int write_cow_header(char *cow_file, int fd, char *backing_file, | 193 | int write_cow_header(char *cow_file, int fd, char *backing_file, |
@@ -194,22 +198,23 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, | |||
194 | int err; | 198 | int err; |
195 | 199 | ||
196 | err = cow_seek_file(fd, 0); | 200 | err = cow_seek_file(fd, 0); |
197 | if(err < 0){ | 201 | if (err < 0) { |
198 | cow_printf("write_cow_header - lseek failed, err = %d\n", -err); | 202 | cow_printf("write_cow_header - lseek failed, err = %d\n", -err); |
199 | goto out; | 203 | goto out; |
200 | } | 204 | } |
201 | 205 | ||
202 | err = -ENOMEM; | 206 | err = -ENOMEM; |
203 | header = cow_malloc(sizeof(*header)); | 207 | header = cow_malloc(sizeof(*header)); |
204 | if(header == NULL){ | 208 | if (header == NULL) { |
205 | cow_printf("write_cow_header - failed to allocate COW V3 header\n"); | 209 | cow_printf("write_cow_header - failed to allocate COW V3 " |
210 | "header\n"); | ||
206 | goto out; | 211 | goto out; |
207 | } | 212 | } |
208 | header->magic = htonl(COW_MAGIC); | 213 | header->magic = htonl(COW_MAGIC); |
209 | header->version = htonl(COW_VERSION); | 214 | header->version = htonl(COW_VERSION); |
210 | 215 | ||
211 | err = -EINVAL; | 216 | err = -EINVAL; |
212 | if(strlen(backing_file) > sizeof(header->backing_file) - 1){ | 217 | if (strlen(backing_file) > sizeof(header->backing_file) - 1) { |
213 | /* Below, %zd is for a size_t value */ | 218 | /* Below, %zd is for a size_t value */ |
214 | cow_printf("Backing file name \"%s\" is too long - names are " | 219 | cow_printf("Backing file name \"%s\" is too long - names are " |
215 | "limited to %zd characters\n", backing_file, | 220 | "limited to %zd characters\n", backing_file, |
@@ -217,12 +222,12 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, | |||
217 | goto out_free; | 222 | goto out_free; |
218 | } | 223 | } |
219 | 224 | ||
220 | if(absolutize(header->backing_file, sizeof(header->backing_file), | 225 | if (absolutize(header->backing_file, sizeof(header->backing_file), |
221 | backing_file)) | 226 | backing_file)) |
222 | goto out_free; | 227 | goto out_free; |
223 | 228 | ||
224 | err = os_file_modtime(header->backing_file, &modtime); | 229 | err = os_file_modtime(header->backing_file, &modtime); |
225 | if(err < 0){ | 230 | if (err < 0) { |
226 | cow_printf("write_cow_header - backing file '%s' mtime " | 231 | cow_printf("write_cow_header - backing file '%s' mtime " |
227 | "request failed, err = %d\n", header->backing_file, | 232 | "request failed, err = %d\n", header->backing_file, |
228 | -err); | 233 | -err); |
@@ -230,7 +235,7 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, | |||
230 | } | 235 | } |
231 | 236 | ||
232 | err = cow_file_size(header->backing_file, size); | 237 | err = cow_file_size(header->backing_file, size); |
233 | if(err < 0){ | 238 | if (err < 0) { |
234 | cow_printf("write_cow_header - couldn't get size of " | 239 | cow_printf("write_cow_header - couldn't get size of " |
235 | "backing file '%s', err = %d\n", | 240 | "backing file '%s', err = %d\n", |
236 | header->backing_file, -err); | 241 | header->backing_file, -err); |
@@ -244,7 +249,7 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, | |||
244 | header->cow_format = COW_BITMAP; | 249 | header->cow_format = COW_BITMAP; |
245 | 250 | ||
246 | err = cow_write_file(fd, header, sizeof(*header)); | 251 | err = cow_write_file(fd, header, sizeof(*header)); |
247 | if(err != sizeof(*header)){ | 252 | if (err != sizeof(*header)) { |
248 | cow_printf("write_cow_header - write of header to " | 253 | cow_printf("write_cow_header - write of header to " |
249 | "new COW file '%s' failed, err = %d\n", cow_file, | 254 | "new COW file '%s' failed, err = %d\n", cow_file, |
250 | -err); | 255 | -err); |
@@ -254,14 +259,14 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, | |||
254 | out_free: | 259 | out_free: |
255 | cow_free(header); | 260 | cow_free(header); |
256 | out: | 261 | out: |
257 | return(err); | 262 | return err; |
258 | } | 263 | } |
259 | 264 | ||
260 | int file_reader(__u64 offset, char *buf, int len, void *arg) | 265 | int file_reader(__u64 offset, char *buf, int len, void *arg) |
261 | { | 266 | { |
262 | int fd = *((int *) arg); | 267 | int fd = *((int *) arg); |
263 | 268 | ||
264 | return(pread(fd, buf, len, offset)); | 269 | return pread(fd, buf, len, offset); |
265 | } | 270 | } |
266 | 271 | ||
267 | /* XXX Need to sanity-check the values read from the header */ | 272 | /* XXX Need to sanity-check the values read from the header */ |
@@ -278,31 +283,29 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, | |||
278 | unsigned long version, magic; | 283 | unsigned long version, magic; |
279 | 284 | ||
280 | header = cow_malloc(sizeof(*header)); | 285 | header = cow_malloc(sizeof(*header)); |
281 | if(header == NULL){ | 286 | if (header == NULL) { |
282 | cow_printf("read_cow_header - Failed to allocate header\n"); | 287 | cow_printf("read_cow_header - Failed to allocate header\n"); |
283 | return(-ENOMEM); | 288 | return -ENOMEM; |
284 | } | 289 | } |
285 | err = -EINVAL; | 290 | err = -EINVAL; |
286 | n = (*reader)(0, (char *) header, sizeof(*header), arg); | 291 | n = (*reader)(0, (char *) header, sizeof(*header), arg); |
287 | if(n < offsetof(typeof(header->v1), backing_file)){ | 292 | if (n < offsetof(typeof(header->v1), backing_file)) { |
288 | cow_printf("read_cow_header - short header\n"); | 293 | cow_printf("read_cow_header - short header\n"); |
289 | goto out; | 294 | goto out; |
290 | } | 295 | } |
291 | 296 | ||
292 | magic = header->v1.magic; | 297 | magic = header->v1.magic; |
293 | if(magic == COW_MAGIC) { | 298 | if (magic == COW_MAGIC) |
294 | version = header->v1.version; | 299 | version = header->v1.version; |
295 | } | 300 | else if (magic == ntohl(COW_MAGIC)) |
296 | else if(magic == ntohl(COW_MAGIC)){ | ||
297 | version = ntohl(header->v1.version); | 301 | version = ntohl(header->v1.version); |
298 | } | ||
299 | /* No error printed because the non-COW case comes through here */ | 302 | /* No error printed because the non-COW case comes through here */ |
300 | else goto out; | 303 | else goto out; |
301 | 304 | ||
302 | *version_out = version; | 305 | *version_out = version; |
303 | 306 | ||
304 | if(version == 1){ | 307 | if (version == 1) { |
305 | if(n < sizeof(header->v1)){ | 308 | if (n < sizeof(header->v1)) { |
306 | cow_printf("read_cow_header - failed to read V1 " | 309 | cow_printf("read_cow_header - failed to read V1 " |
307 | "header\n"); | 310 | "header\n"); |
308 | goto out; | 311 | goto out; |
@@ -314,8 +317,8 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, | |||
314 | *align_out = *sectorsize_out; | 317 | *align_out = *sectorsize_out; |
315 | file = header->v1.backing_file; | 318 | file = header->v1.backing_file; |
316 | } | 319 | } |
317 | else if(version == 2){ | 320 | else if (version == 2) { |
318 | if(n < sizeof(header->v2)){ | 321 | if (n < sizeof(header->v2)) { |
319 | cow_printf("read_cow_header - failed to read V2 " | 322 | cow_printf("read_cow_header - failed to read V2 " |
320 | "header\n"); | 323 | "header\n"); |
321 | goto out; | 324 | goto out; |
@@ -328,8 +331,8 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, | |||
328 | file = header->v2.backing_file; | 331 | file = header->v2.backing_file; |
329 | } | 332 | } |
330 | /* This is very subtle - see above at union cow_header definition */ | 333 | /* This is very subtle - see above at union cow_header definition */ |
331 | else if(version == 3 && (*((int*)header->v3.backing_file) != 0)){ | 334 | else if (version == 3 && (*((int*)header->v3.backing_file) != 0)) { |
332 | if(n < sizeof(header->v3)){ | 335 | if (n < sizeof(header->v3)) { |
333 | cow_printf("read_cow_header - failed to read V3 " | 336 | cow_printf("read_cow_header - failed to read V3 " |
334 | "header\n"); | 337 | "header\n"); |
335 | goto out; | 338 | goto out; |
@@ -345,17 +348,18 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, | |||
345 | *bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out); | 348 | *bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out); |
346 | file = header->v3.backing_file; | 349 | file = header->v3.backing_file; |
347 | } | 350 | } |
348 | else if(version == 3){ | 351 | else if (version == 3) { |
349 | cow_printf("read_cow_header - broken V3 file with" | 352 | cow_printf("read_cow_header - broken V3 file with" |
350 | " 64-bit layout - recovering content.\n"); | 353 | " 64-bit layout - recovering content.\n"); |
351 | 354 | ||
352 | if(n < sizeof(header->v3_b)){ | 355 | if (n < sizeof(header->v3_b)) { |
353 | cow_printf("read_cow_header - failed to read V3 " | 356 | cow_printf("read_cow_header - failed to read V3 " |
354 | "header\n"); | 357 | "header\n"); |
355 | goto out; | 358 | goto out; |
356 | } | 359 | } |
357 | 360 | ||
358 | /* this was used until Dec2005 - 64bits are needed to represent | 361 | /* |
362 | * this was used until Dec2005 - 64bits are needed to represent | ||
359 | * 2038+. I.e. we can safely do this truncating cast. | 363 | * 2038+. I.e. we can safely do this truncating cast. |
360 | * | 364 | * |
361 | * Additionally, we must use ntohl() instead of ntohll(), since | 365 | * Additionally, we must use ntohl() instead of ntohll(), since |
@@ -381,7 +385,7 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, | |||
381 | } | 385 | } |
382 | err = -ENOMEM; | 386 | err = -ENOMEM; |
383 | *backing_file_out = cow_strdup(file); | 387 | *backing_file_out = cow_strdup(file); |
384 | if(*backing_file_out == NULL){ | 388 | if (*backing_file_out == NULL) { |
385 | cow_printf("read_cow_header - failed to allocate backing " | 389 | cow_printf("read_cow_header - failed to allocate backing " |
386 | "file\n"); | 390 | "file\n"); |
387 | goto out; | 391 | goto out; |
@@ -389,7 +393,7 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, | |||
389 | err = 0; | 393 | err = 0; |
390 | out: | 394 | out: |
391 | cow_free(header); | 395 | cow_free(header); |
392 | return(err); | 396 | return err; |
393 | } | 397 | } |
394 | 398 | ||
395 | int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, | 399 | int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, |
@@ -402,7 +406,7 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, | |||
402 | 406 | ||
403 | err = write_cow_header(cow_file, fd, backing_file, sectorsize, | 407 | err = write_cow_header(cow_file, fd, backing_file, sectorsize, |
404 | alignment, &size); | 408 | alignment, &size); |
405 | if(err) | 409 | if (err) |
406 | goto out; | 410 | goto out; |
407 | 411 | ||
408 | *bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment); | 412 | *bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment); |
@@ -411,17 +415,18 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, | |||
411 | 415 | ||
412 | offset = *data_offset_out + size - sizeof(zero); | 416 | offset = *data_offset_out + size - sizeof(zero); |
413 | err = cow_seek_file(fd, offset); | 417 | err = cow_seek_file(fd, offset); |
414 | if(err < 0){ | 418 | if (err < 0) { |
415 | cow_printf("cow bitmap lseek failed : err = %d\n", -err); | 419 | cow_printf("cow bitmap lseek failed : err = %d\n", -err); |
416 | goto out; | 420 | goto out; |
417 | } | 421 | } |
418 | 422 | ||
419 | /* does not really matter how much we write it is just to set EOF | 423 | /* |
424 | * does not really matter how much we write it is just to set EOF | ||
420 | * this also sets the entire COW bitmap | 425 | * this also sets the entire COW bitmap |
421 | * to zero without having to allocate it | 426 | * to zero without having to allocate it |
422 | */ | 427 | */ |
423 | err = cow_write_file(fd, &zero, sizeof(zero)); | 428 | err = cow_write_file(fd, &zero, sizeof(zero)); |
424 | if(err != sizeof(zero)){ | 429 | if (err != sizeof(zero)) { |
425 | cow_printf("Write of bitmap to new COW file '%s' failed, " | 430 | cow_printf("Write of bitmap to new COW file '%s' failed, " |
426 | "err = %d\n", cow_file, -err); | 431 | "err = %d\n", cow_file, -err); |
427 | if (err >= 0) | 432 | if (err >= 0) |
@@ -429,15 +434,7 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, | |||
429 | goto out; | 434 | goto out; |
430 | } | 435 | } |
431 | 436 | ||
432 | return(0); | 437 | return 0; |
433 | |||
434 | out: | 438 | out: |
435 | return(err); | 439 | return err; |
436 | } | 440 | } |
437 | |||
438 | /* | ||
439 | * --------------------------------------------------------------------------- | ||
440 | * Local variables: | ||
441 | * c-file-style: "linux" | ||
442 | * End: | ||
443 | */ | ||
diff --git a/arch/um/drivers/daemon.h b/arch/um/drivers/daemon.h index 3bc3cf6b94aa..6e0e891f8a00 100644 --- a/arch/um/drivers/daemon.h +++ b/arch/um/drivers/daemon.h | |||
@@ -1,8 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #ifndef __DAEMON_H__ | ||
7 | #define __DAEMON_H__ | ||
8 | |||
6 | #include "net_user.h" | 9 | #include "net_user.h" |
7 | 10 | ||
8 | #define SWITCH_VERSION 3 | 11 | #define SWITCH_VERSION 3 |
@@ -20,16 +23,7 @@ struct daemon_data { | |||
20 | 23 | ||
21 | extern const struct net_user_info daemon_user_info; | 24 | extern const struct net_user_info daemon_user_info; |
22 | 25 | ||
23 | extern int daemon_user_write(int fd, void *buf, int len, | 26 | extern int daemon_user_write(int fd, void *buf, int len, |
24 | struct daemon_data *pri); | 27 | struct daemon_data *pri); |
25 | 28 | ||
26 | /* | 29 | #endif |
27 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
28 | * Emacs will notice this stuff at the end of the file and automatically | ||
29 | * adjust the settings for this buffer only. This must remain at the end | ||
30 | * of the file. | ||
31 | * --------------------------------------------------------------------------- | ||
32 | * Local variables: | ||
33 | * c-file-style: "linux" | ||
34 | * End: | ||
35 | */ | ||
diff --git a/arch/um/drivers/daemon_kern.c b/arch/um/drivers/daemon_kern.c index adeece11e596..d53ff52bb404 100644 --- a/arch/um/drivers/daemon_kern.c +++ b/arch/um/drivers/daemon_kern.c | |||
@@ -1,16 +1,14 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and | 2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and |
3 | * James Leu (jleu@mindspring.net). | 3 | * James Leu (jleu@mindspring.net). |
4 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
4 | * Copyright (C) 2001 by various other people who didn't put their name here. | 5 | * Copyright (C) 2001 by various other people who didn't put their name here. |
5 | * Licensed under the GPL. | 6 | * Licensed under the GPL. |
6 | */ | 7 | */ |
7 | 8 | ||
8 | #include "linux/kernel.h" | ||
9 | #include "linux/init.h" | 9 | #include "linux/init.h" |
10 | #include "linux/netdevice.h" | 10 | #include <linux/netdevice.h> |
11 | #include "linux/etherdevice.h" | ||
12 | #include "net_kern.h" | 11 | #include "net_kern.h" |
13 | #include "net_user.h" | ||
14 | #include "daemon.h" | 12 | #include "daemon.h" |
15 | 13 | ||
16 | struct daemon_init { | 14 | struct daemon_init { |
@@ -36,25 +34,21 @@ static void daemon_init(struct net_device *dev, void *data) | |||
36 | dpri->data_addr = NULL; | 34 | dpri->data_addr = NULL; |
37 | dpri->local_addr = NULL; | 35 | dpri->local_addr = NULL; |
38 | 36 | ||
39 | printk("daemon backend (uml_switch version %d) - %s:%s", | 37 | printk("daemon backend (uml_switch version %d) - %s:%s", |
40 | SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock); | 38 | SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock); |
41 | printk("\n"); | 39 | printk("\n"); |
42 | } | 40 | } |
43 | 41 | ||
44 | static int daemon_read(int fd, struct sk_buff **skb, | 42 | static int daemon_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) |
45 | struct uml_net_private *lp) | ||
46 | { | 43 | { |
47 | *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); | 44 | return net_recvfrom(fd, skb_mac_header(skb), |
48 | if(*skb == NULL) return(-ENOMEM); | 45 | skb->dev->mtu + ETH_HEADER_OTHER); |
49 | return(net_recvfrom(fd, skb_mac_header(*skb), | ||
50 | (*skb)->dev->mtu + ETH_HEADER_OTHER)); | ||
51 | } | 46 | } |
52 | 47 | ||
53 | static int daemon_write(int fd, struct sk_buff **skb, | 48 | static int daemon_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) |
54 | struct uml_net_private *lp) | ||
55 | { | 49 | { |
56 | return(daemon_user_write(fd, (*skb)->data, (*skb)->len, | 50 | return daemon_user_write(fd, skb->data, skb->len, |
57 | (struct daemon_data *) &lp->user)); | 51 | (struct daemon_data *) &lp->user); |
58 | } | 52 | } |
59 | 53 | ||
60 | static const struct net_kern_info daemon_kern_info = { | 54 | static const struct net_kern_info daemon_kern_info = { |
@@ -72,14 +66,14 @@ static int daemon_setup(char *str, char **mac_out, void *data) | |||
72 | *init = ((struct daemon_init) | 66 | *init = ((struct daemon_init) |
73 | { .sock_type = "unix", | 67 | { .sock_type = "unix", |
74 | .ctl_sock = "/tmp/uml.ctl" }); | 68 | .ctl_sock = "/tmp/uml.ctl" }); |
75 | 69 | ||
76 | remain = split_if_spec(str, mac_out, &init->sock_type, &init->ctl_sock, | 70 | remain = split_if_spec(str, mac_out, &init->sock_type, &init->ctl_sock, |
77 | NULL); | 71 | NULL); |
78 | if(remain != NULL) | 72 | if (remain != NULL) |
79 | printk(KERN_WARNING "daemon_setup : Ignoring data socket " | 73 | printk(KERN_WARNING "daemon_setup : Ignoring data socket " |
80 | "specification\n"); | 74 | "specification\n"); |
81 | 75 | ||
82 | return(1); | 76 | return 1; |
83 | } | 77 | } |
84 | 78 | ||
85 | static struct transport daemon_transport = { | 79 | static struct transport daemon_transport = { |
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c index 8d2008f06682..f23c109a055c 100644 --- a/arch/um/drivers/daemon_user.c +++ b/arch/um/drivers/daemon_user.c | |||
@@ -1,24 +1,23 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and | 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and | ||
3 | * James Leu (jleu@mindspring.net). | 4 | * James Leu (jleu@mindspring.net). |
4 | * Copyright (C) 2001 by various other people who didn't put their name here. | 5 | * Copyright (C) 2001 by various other people who didn't put their name here. |
5 | * Licensed under the GPL. | 6 | * Licensed under the GPL. |
6 | */ | 7 | */ |
7 | 8 | ||
8 | #include <errno.h> | ||
9 | #include <unistd.h> | ||
10 | #include <stdint.h> | 9 | #include <stdint.h> |
10 | #include <unistd.h> | ||
11 | #include <errno.h> | ||
12 | #include <sys/types.h> | ||
11 | #include <sys/socket.h> | 13 | #include <sys/socket.h> |
12 | #include <sys/un.h> | ||
13 | #include <sys/time.h> | 14 | #include <sys/time.h> |
14 | #include "net_user.h" | 15 | #include <sys/un.h> |
15 | #include "daemon.h" | 16 | #include "daemon.h" |
16 | #include "kern_util.h" | 17 | #include "net_user.h" |
17 | #include "user.h" | ||
18 | #include "os.h" | 18 | #include "os.h" |
19 | #include "um_malloc.h" | 19 | #include "um_malloc.h" |
20 | 20 | #include "user.h" | |
21 | #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) | ||
22 | 21 | ||
23 | enum request_type { REQ_NEW_CONTROL }; | 22 | enum request_type { REQ_NEW_CONTROL }; |
24 | 23 | ||
@@ -36,8 +35,9 @@ static struct sockaddr_un *new_addr(void *name, int len) | |||
36 | struct sockaddr_un *sun; | 35 | struct sockaddr_un *sun; |
37 | 36 | ||
38 | sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); | 37 | sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); |
39 | if(sun == NULL){ | 38 | if (sun == NULL) { |
40 | printk("new_addr: allocation of sockaddr_un failed\n"); | 39 | printk(UM_KERN_ERR "new_addr: allocation of sockaddr_un " |
40 | "failed\n"); | ||
41 | return NULL; | 41 | return NULL; |
42 | } | 42 | } |
43 | sun->sun_family = AF_UNIX; | 43 | sun->sun_family = AF_UNIX; |
@@ -54,38 +54,39 @@ static int connect_to_switch(struct daemon_data *pri) | |||
54 | int fd, n, err; | 54 | int fd, n, err; |
55 | 55 | ||
56 | pri->control = socket(AF_UNIX, SOCK_STREAM, 0); | 56 | pri->control = socket(AF_UNIX, SOCK_STREAM, 0); |
57 | if(pri->control < 0){ | 57 | if (pri->control < 0) { |
58 | err = -errno; | 58 | err = -errno; |
59 | printk("daemon_open : control socket failed, errno = %d\n", | 59 | printk(UM_KERN_ERR "daemon_open : control socket failed, " |
60 | -err); | 60 | "errno = %d\n", -err); |
61 | return err; | 61 | return err; |
62 | } | 62 | } |
63 | 63 | ||
64 | if(connect(pri->control, (struct sockaddr *) ctl_addr, | 64 | if (connect(pri->control, (struct sockaddr *) ctl_addr, |
65 | sizeof(*ctl_addr)) < 0){ | 65 | sizeof(*ctl_addr)) < 0) { |
66 | err = -errno; | 66 | err = -errno; |
67 | printk("daemon_open : control connect failed, errno = %d\n", | 67 | printk(UM_KERN_ERR "daemon_open : control connect failed, " |
68 | -err); | 68 | "errno = %d\n", -err); |
69 | goto out; | 69 | goto out; |
70 | } | 70 | } |
71 | 71 | ||
72 | fd = socket(AF_UNIX, SOCK_DGRAM, 0); | 72 | fd = socket(AF_UNIX, SOCK_DGRAM, 0); |
73 | if(fd < 0){ | 73 | if (fd < 0) { |
74 | err = -errno; | 74 | err = -errno; |
75 | printk("daemon_open : data socket failed, errno = %d\n", | 75 | printk(UM_KERN_ERR "daemon_open : data socket failed, " |
76 | -err); | 76 | "errno = %d\n", -err); |
77 | goto out; | 77 | goto out; |
78 | } | 78 | } |
79 | if(bind(fd, (struct sockaddr *) local_addr, sizeof(*local_addr)) < 0){ | 79 | if (bind(fd, (struct sockaddr *) local_addr, sizeof(*local_addr)) < 0) { |
80 | err = -errno; | 80 | err = -errno; |
81 | printk("daemon_open : data bind failed, errno = %d\n", | 81 | printk(UM_KERN_ERR "daemon_open : data bind failed, " |
82 | -err); | 82 | "errno = %d\n", -err); |
83 | goto out_close; | 83 | goto out_close; |
84 | } | 84 | } |
85 | 85 | ||
86 | sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); | 86 | sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); |
87 | if(sun == NULL){ | 87 | if (sun == NULL) { |
88 | printk("new_addr: allocation of sockaddr_un failed\n"); | 88 | printk(UM_KERN_ERR "new_addr: allocation of sockaddr_un " |
89 | "failed\n"); | ||
89 | err = -ENOMEM; | 90 | err = -ENOMEM; |
90 | goto out_close; | 91 | goto out_close; |
91 | } | 92 | } |
@@ -94,18 +95,18 @@ static int connect_to_switch(struct daemon_data *pri) | |||
94 | req.version = SWITCH_VERSION; | 95 | req.version = SWITCH_VERSION; |
95 | req.type = REQ_NEW_CONTROL; | 96 | req.type = REQ_NEW_CONTROL; |
96 | req.sock = *local_addr; | 97 | req.sock = *local_addr; |
97 | n = os_write_file(pri->control, &req, sizeof(req)); | 98 | n = write(pri->control, &req, sizeof(req)); |
98 | if(n != sizeof(req)){ | 99 | if (n != sizeof(req)) { |
99 | printk("daemon_open : control setup request failed, err = %d\n", | 100 | printk(UM_KERN_ERR "daemon_open : control setup request " |
100 | -n); | 101 | "failed, err = %d\n", -errno); |
101 | err = -ENOTCONN; | 102 | err = -ENOTCONN; |
102 | goto out_free; | 103 | goto out_free; |
103 | } | 104 | } |
104 | 105 | ||
105 | n = os_read_file(pri->control, sun, sizeof(*sun)); | 106 | n = read(pri->control, sun, sizeof(*sun)); |
106 | if(n != sizeof(*sun)){ | 107 | if (n != sizeof(*sun)) { |
107 | printk("daemon_open : read of data socket failed, err = %d\n", | 108 | printk(UM_KERN_ERR "daemon_open : read of data socket failed, " |
108 | -n); | 109 | "err = %d\n", -errno); |
109 | err = -ENOTCONN; | 110 | err = -ENOTCONN; |
110 | goto out_free; | 111 | goto out_free; |
111 | } | 112 | } |
@@ -116,9 +117,9 @@ static int connect_to_switch(struct daemon_data *pri) | |||
116 | out_free: | 117 | out_free: |
117 | kfree(sun); | 118 | kfree(sun); |
118 | out_close: | 119 | out_close: |
119 | os_close_file(fd); | 120 | close(fd); |
120 | out: | 121 | out: |
121 | os_close_file(pri->control); | 122 | close(pri->control); |
122 | return err; | 123 | return err; |
123 | } | 124 | } |
124 | 125 | ||
@@ -132,8 +133,8 @@ static int daemon_user_init(void *data, void *dev) | |||
132 | int usecs; | 133 | int usecs; |
133 | } name; | 134 | } name; |
134 | 135 | ||
135 | if(!strcmp(pri->sock_type, "unix")) | 136 | if (!strcmp(pri->sock_type, "unix")) |
136 | pri->ctl_addr = new_addr(pri->ctl_sock, | 137 | pri->ctl_addr = new_addr(pri->ctl_sock, |
137 | strlen(pri->ctl_sock) + 1); | 138 | strlen(pri->ctl_sock) + 1); |
138 | name.zero = 0; | 139 | name.zero = 0; |
139 | name.pid = os_getpid(); | 140 | name.pid = os_getpid(); |
@@ -142,7 +143,7 @@ static int daemon_user_init(void *data, void *dev) | |||
142 | pri->local_addr = new_addr(&name, sizeof(name)); | 143 | pri->local_addr = new_addr(&name, sizeof(name)); |
143 | pri->dev = dev; | 144 | pri->dev = dev; |
144 | pri->fd = connect_to_switch(pri); | 145 | pri->fd = connect_to_switch(pri); |
145 | if(pri->fd < 0){ | 146 | if (pri->fd < 0) { |
146 | kfree(pri->local_addr); | 147 | kfree(pri->local_addr); |
147 | pri->local_addr = NULL; | 148 | pri->local_addr = NULL; |
148 | return pri->fd; | 149 | return pri->fd; |
@@ -161,9 +162,9 @@ static void daemon_remove(void *data) | |||
161 | { | 162 | { |
162 | struct daemon_data *pri = data; | 163 | struct daemon_data *pri = data; |
163 | 164 | ||
164 | os_close_file(pri->fd); | 165 | close(pri->fd); |
165 | pri->fd = -1; | 166 | pri->fd = -1; |
166 | os_close_file(pri->control); | 167 | close(pri->control); |
167 | pri->control = -1; | 168 | pri->control = -1; |
168 | 169 | ||
169 | kfree(pri->data_addr); | 170 | kfree(pri->data_addr); |
@@ -181,18 +182,13 @@ int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri) | |||
181 | return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); | 182 | return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); |
182 | } | 183 | } |
183 | 184 | ||
184 | static int daemon_set_mtu(int mtu, void *data) | ||
185 | { | ||
186 | return mtu; | ||
187 | } | ||
188 | |||
189 | const struct net_user_info daemon_user_info = { | 185 | const struct net_user_info daemon_user_info = { |
190 | .init = daemon_user_init, | 186 | .init = daemon_user_init, |
191 | .open = daemon_open, | 187 | .open = daemon_open, |
192 | .close = NULL, | 188 | .close = NULL, |
193 | .remove = daemon_remove, | 189 | .remove = daemon_remove, |
194 | .set_mtu = daemon_set_mtu, | ||
195 | .add_address = NULL, | 190 | .add_address = NULL, |
196 | .delete_address = NULL, | 191 | .delete_address = NULL, |
197 | .max_packet = MAX_PACKET - ETH_HEADER_OTHER | 192 | .mtu = ETH_MAX_PACKET, |
193 | .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, | ||
198 | }; | 194 | }; |
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c index 39c01ffd45c9..0a2bb5b64b82 100644 --- a/arch/um/drivers/fd.c +++ b/arch/um/drivers/fd.c | |||
@@ -1,17 +1,18 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdio.h> | 6 | #include <stdio.h> |
7 | #include <stdlib.h> | 7 | #include <stdlib.h> |
8 | #include <unistd.h> | 8 | #include <unistd.h> |
9 | #include <termios.h> | ||
10 | #include <errno.h> | 9 | #include <errno.h> |
11 | #include "user.h" | 10 | #include <termios.h> |
12 | #include "chan_user.h" | 11 | #include "chan_user.h" |
12 | #include "kern_constants.h" | ||
13 | #include "os.h" | 13 | #include "os.h" |
14 | #include "um_malloc.h" | 14 | #include "um_malloc.h" |
15 | #include "user.h" | ||
15 | 16 | ||
16 | struct fd_chan { | 17 | struct fd_chan { |
17 | int fd; | 18 | int fd; |
@@ -26,22 +27,26 @@ static void *fd_init(char *str, int device, const struct chan_opts *opts) | |||
26 | char *end; | 27 | char *end; |
27 | int n; | 28 | int n; |
28 | 29 | ||
29 | if(*str != ':'){ | 30 | if (*str != ':') { |
30 | printk("fd_init : channel type 'fd' must specify a file " | 31 | printk(UM_KERN_ERR "fd_init : channel type 'fd' must specify a " |
31 | "descriptor\n"); | 32 | "file descriptor\n"); |
32 | return(NULL); | 33 | return NULL; |
33 | } | 34 | } |
34 | str++; | 35 | str++; |
35 | n = strtoul(str, &end, 0); | 36 | n = strtoul(str, &end, 0); |
36 | if((*end != '\0') || (end == str)){ | 37 | if ((*end != '\0') || (end == str)) { |
37 | printk("fd_init : couldn't parse file descriptor '%s'\n", str); | 38 | printk(UM_KERN_ERR "fd_init : couldn't parse file descriptor " |
38 | return(NULL); | 39 | "'%s'\n", str); |
40 | return NULL; | ||
39 | } | 41 | } |
42 | |||
40 | data = kmalloc(sizeof(*data), UM_GFP_KERNEL); | 43 | data = kmalloc(sizeof(*data), UM_GFP_KERNEL); |
41 | if(data == NULL) return(NULL); | 44 | if (data == NULL) |
45 | return NULL; | ||
46 | |||
42 | *data = ((struct fd_chan) { .fd = n, | 47 | *data = ((struct fd_chan) { .fd = n, |
43 | .raw = opts->raw }); | 48 | .raw = opts->raw }); |
44 | return(data); | 49 | return data; |
45 | } | 50 | } |
46 | 51 | ||
47 | static int fd_open(int input, int output, int primary, void *d, char **dev_out) | 52 | static int fd_open(int input, int output, int primary, void *d, char **dev_out) |
@@ -49,18 +54,18 @@ static int fd_open(int input, int output, int primary, void *d, char **dev_out) | |||
49 | struct fd_chan *data = d; | 54 | struct fd_chan *data = d; |
50 | int err; | 55 | int err; |
51 | 56 | ||
52 | if(data->raw && isatty(data->fd)){ | 57 | if (data->raw && isatty(data->fd)) { |
53 | CATCH_EINTR(err = tcgetattr(data->fd, &data->tt)); | 58 | CATCH_EINTR(err = tcgetattr(data->fd, &data->tt)); |
54 | if(err) | 59 | if (err) |
55 | return(err); | 60 | return err; |
56 | 61 | ||
57 | err = raw(data->fd); | 62 | err = raw(data->fd); |
58 | if(err) | 63 | if (err) |
59 | return(err); | 64 | return err; |
60 | } | 65 | } |
61 | sprintf(data->str, "%d", data->fd); | 66 | sprintf(data->str, "%d", data->fd); |
62 | *dev_out = data->str; | 67 | *dev_out = data->str; |
63 | return(data->fd); | 68 | return data->fd; |
64 | } | 69 | } |
65 | 70 | ||
66 | static void fd_close(int fd, void *d) | 71 | static void fd_close(int fd, void *d) |
@@ -68,13 +73,14 @@ static void fd_close(int fd, void *d) | |||
68 | struct fd_chan *data = d; | 73 | struct fd_chan *data = d; |
69 | int err; | 74 | int err; |
70 | 75 | ||
71 | if(data->raw && isatty(fd)){ | 76 | if (!data->raw || !isatty(fd)) |
72 | CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &data->tt)); | 77 | return; |
73 | if(err) | 78 | |
74 | printk("Failed to restore terminal state - " | 79 | CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &data->tt)); |
75 | "errno = %d\n", -err); | 80 | if (err) |
76 | data->raw = 0; | 81 | printk(UM_KERN_ERR "Failed to restore terminal state - " |
77 | } | 82 | "errno = %d\n", -err); |
83 | data->raw = 0; | ||
78 | } | 84 | } |
79 | 85 | ||
80 | const struct chan_ops fd_ops = { | 86 | const struct chan_ops fd_ops = { |
@@ -89,14 +95,3 @@ const struct chan_ops fd_ops = { | |||
89 | .free = generic_free, | 95 | .free = generic_free, |
90 | .winch = 1, | 96 | .winch = 1, |
91 | }; | 97 | }; |
92 | |||
93 | /* | ||
94 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
95 | * Emacs will notice this stuff at the end of the file and automatically | ||
96 | * adjust the settings for this buffer only. This must remain at the end | ||
97 | * of the file. | ||
98 | * --------------------------------------------------------------------------- | ||
99 | * Local variables: | ||
100 | * c-file-style: "linux" | ||
101 | * End: | ||
102 | */ | ||
diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c index 55601687b3bc..a9ad4bd6d953 100644 --- a/arch/um/drivers/harddog_kern.c +++ b/arch/um/drivers/harddog_kern.c | |||
@@ -69,7 +69,7 @@ static int harddog_open(struct inode *inode, struct file *file) | |||
69 | spin_lock(&lock); | 69 | spin_lock(&lock); |
70 | if(timer_alive) | 70 | if(timer_alive) |
71 | goto err; | 71 | goto err; |
72 | #ifdef CONFIG_HARDDOG_NOWAYOUT | 72 | #ifdef CONFIG_WATCHDOG_NOWAYOUT |
73 | __module_get(THIS_MODULE); | 73 | __module_get(THIS_MODULE); |
74 | #endif | 74 | #endif |
75 | 75 | ||
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c index 1171790f742c..b56f8e0196a9 100644 --- a/arch/um/drivers/harddog_user.c +++ b/arch/um/drivers/harddog_user.c | |||
@@ -1,16 +1,13 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdio.h> | 6 | #include <stdio.h> |
7 | #include <unistd.h> | 7 | #include <unistd.h> |
8 | #include <errno.h> | 8 | #include <errno.h> |
9 | #include "user.h" | ||
10 | #include "mconsole.h" | ||
11 | #include "os.h" | 9 | #include "os.h" |
12 | #include "choose-mode.h" | 10 | #include "user.h" |
13 | #include "mode.h" | ||
14 | 11 | ||
15 | struct dog_data { | 12 | struct dog_data { |
16 | int stdin; | 13 | int stdin; |
@@ -25,10 +22,10 @@ static void pre_exec(void *d) | |||
25 | dup2(data->stdin, 0); | 22 | dup2(data->stdin, 0); |
26 | dup2(data->stdout, 1); | 23 | dup2(data->stdout, 1); |
27 | dup2(data->stdout, 2); | 24 | dup2(data->stdout, 2); |
28 | os_close_file(data->stdin); | 25 | close(data->stdin); |
29 | os_close_file(data->stdout); | 26 | close(data->stdout); |
30 | os_close_file(data->close_me[0]); | 27 | close(data->close_me[0]); |
31 | os_close_file(data->close_me[1]); | 28 | close(data->close_me[1]); |
32 | } | 29 | } |
33 | 30 | ||
34 | int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) | 31 | int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) |
@@ -42,13 +39,13 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) | |||
42 | char **args = NULL; | 39 | char **args = NULL; |
43 | 40 | ||
44 | err = os_pipe(in_fds, 1, 0); | 41 | err = os_pipe(in_fds, 1, 0); |
45 | if(err < 0){ | 42 | if (err < 0) { |
46 | printk("harddog_open - os_pipe failed, err = %d\n", -err); | 43 | printk("harddog_open - os_pipe failed, err = %d\n", -err); |
47 | goto out; | 44 | goto out; |
48 | } | 45 | } |
49 | 46 | ||
50 | err = os_pipe(out_fds, 1, 0); | 47 | err = os_pipe(out_fds, 1, 0); |
51 | if(err < 0){ | 48 | if (err < 0) { |
52 | printk("harddog_open - os_pipe failed, err = %d\n", -err); | 49 | printk("harddog_open - os_pipe failed, err = %d\n", -err); |
53 | goto out_close_in; | 50 | goto out_close_in; |
54 | } | 51 | } |
@@ -58,37 +55,37 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) | |||
58 | data.close_me[0] = out_fds[1]; | 55 | data.close_me[0] = out_fds[1]; |
59 | data.close_me[1] = in_fds[0]; | 56 | data.close_me[1] = in_fds[0]; |
60 | 57 | ||
61 | if(sock != NULL){ | 58 | if (sock != NULL) { |
62 | mconsole_args[2] = sock; | 59 | mconsole_args[2] = sock; |
63 | args = mconsole_args; | 60 | args = mconsole_args; |
64 | } | 61 | } |
65 | else { | 62 | else { |
66 | /* XXX The os_getpid() is not SMP correct */ | 63 | /* XXX The os_getpid() is not SMP correct */ |
67 | sprintf(pid_buf, "%d", CHOOSE_MODE(tracing_pid, os_getpid())); | 64 | sprintf(pid_buf, "%d", os_getpid()); |
68 | args = pid_args; | 65 | args = pid_args; |
69 | } | 66 | } |
70 | 67 | ||
71 | pid = run_helper(pre_exec, &data, args); | 68 | pid = run_helper(pre_exec, &data, args); |
72 | 69 | ||
73 | os_close_file(out_fds[0]); | 70 | close(out_fds[0]); |
74 | os_close_file(in_fds[1]); | 71 | close(in_fds[1]); |
75 | 72 | ||
76 | if(pid < 0){ | 73 | if (pid < 0) { |
77 | err = -pid; | 74 | err = -pid; |
78 | printk("harddog_open - run_helper failed, errno = %d\n", -err); | 75 | printk("harddog_open - run_helper failed, errno = %d\n", -err); |
79 | goto out_close_out; | 76 | goto out_close_out; |
80 | } | 77 | } |
81 | 78 | ||
82 | n = os_read_file(in_fds[0], &c, sizeof(c)); | 79 | n = read(in_fds[0], &c, sizeof(c)); |
83 | if(n == 0){ | 80 | if (n == 0) { |
84 | printk("harddog_open - EOF on watchdog pipe\n"); | 81 | printk("harddog_open - EOF on watchdog pipe\n"); |
85 | helper_wait(pid); | 82 | helper_wait(pid); |
86 | err = -EIO; | 83 | err = -EIO; |
87 | goto out_close_out; | 84 | goto out_close_out; |
88 | } | 85 | } |
89 | else if(n < 0){ | 86 | else if (n < 0) { |
90 | printk("harddog_open - read of watchdog pipe failed, " | 87 | printk("harddog_open - read of watchdog pipe failed, " |
91 | "err = %d\n", -n); | 88 | "err = %d\n", errno); |
92 | helper_wait(pid); | 89 | helper_wait(pid); |
93 | err = n; | 90 | err = n; |
94 | goto out_close_out; | 91 | goto out_close_out; |
@@ -98,19 +95,19 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) | |||
98 | return 0; | 95 | return 0; |
99 | 96 | ||
100 | out_close_in: | 97 | out_close_in: |
101 | os_close_file(in_fds[0]); | 98 | close(in_fds[0]); |
102 | os_close_file(in_fds[1]); | 99 | close(in_fds[1]); |
103 | out_close_out: | 100 | out_close_out: |
104 | os_close_file(out_fds[0]); | 101 | close(out_fds[0]); |
105 | os_close_file(out_fds[1]); | 102 | close(out_fds[1]); |
106 | out: | 103 | out: |
107 | return err; | 104 | return err; |
108 | } | 105 | } |
109 | 106 | ||
110 | void stop_watchdog(int in_fd, int out_fd) | 107 | void stop_watchdog(int in_fd, int out_fd) |
111 | { | 108 | { |
112 | os_close_file(in_fd); | 109 | close(in_fd); |
113 | os_close_file(out_fd); | 110 | close(out_fd); |
114 | } | 111 | } |
115 | 112 | ||
116 | int ping_watchdog(int fd) | 113 | int ping_watchdog(int fd) |
@@ -118,10 +115,11 @@ int ping_watchdog(int fd) | |||
118 | int n; | 115 | int n; |
119 | char c = '\n'; | 116 | char c = '\n'; |
120 | 117 | ||
121 | n = os_write_file(fd, &c, sizeof(c)); | 118 | n = write(fd, &c, sizeof(c)); |
122 | if(n != sizeof(c)){ | 119 | if (n != sizeof(c)) { |
123 | printk("ping_watchdog - write failed, err = %d\n", -n); | 120 | printk("ping_watchdog - write failed, ret = %d, err = %d\n", |
124 | if(n < 0) | 121 | n, errno); |
122 | if (n < 0) | ||
125 | return n; | 123 | return n; |
126 | return -EIO; | 124 | return -EIO; |
127 | } | 125 | } |
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index 10e08a8c17c3..ff1b22b69e9c 100644 --- a/arch/um/drivers/hostaudio_kern.c +++ b/arch/um/drivers/hostaudio_kern.c | |||
@@ -1,16 +1,14 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Steve Schmidtke | 2 | * Copyright (C) 2002 Steve Schmidtke |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/fs.h" | ||
6 | #include "linux/module.h" | 7 | #include "linux/module.h" |
7 | #include "linux/init.h" | ||
8 | #include "linux/slab.h" | 8 | #include "linux/slab.h" |
9 | #include "linux/fs.h" | ||
10 | #include "linux/sound.h" | 9 | #include "linux/sound.h" |
11 | #include "linux/soundcard.h" | 10 | #include "linux/soundcard.h" |
12 | #include "asm/uaccess.h" | 11 | #include "asm/uaccess.h" |
13 | #include "kern_util.h" | ||
14 | #include "init.h" | 12 | #include "init.h" |
15 | #include "os.h" | 13 | #include "os.h" |
16 | 14 | ||
@@ -25,7 +23,8 @@ struct hostmixer_state { | |||
25 | #define HOSTAUDIO_DEV_DSP "/dev/sound/dsp" | 23 | #define HOSTAUDIO_DEV_DSP "/dev/sound/dsp" |
26 | #define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer" | 24 | #define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer" |
27 | 25 | ||
28 | /* Changed either at boot time or module load time. At boot, this is | 26 | /* |
27 | * Changed either at boot time or module load time. At boot, this is | ||
29 | * single-threaded; at module load, multiple modules would each have | 28 | * single-threaded; at module load, multiple modules would each have |
30 | * their own copy of these variables. | 29 | * their own copy of these variables. |
31 | */ | 30 | */ |
@@ -44,7 +43,7 @@ static char *mixer = HOSTAUDIO_DEV_MIXER; | |||
44 | static int set_dsp(char *name, int *add) | 43 | static int set_dsp(char *name, int *add) |
45 | { | 44 | { |
46 | dsp = name; | 45 | dsp = name; |
47 | return(0); | 46 | return 0; |
48 | } | 47 | } |
49 | 48 | ||
50 | __uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP); | 49 | __uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP); |
@@ -52,7 +51,7 @@ __uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP); | |||
52 | static int set_mixer(char *name, int *add) | 51 | static int set_mixer(char *name, int *add) |
53 | { | 52 | { |
54 | mixer = name; | 53 | mixer = name; |
55 | return(0); | 54 | return 0; |
56 | } | 55 | } |
57 | 56 | ||
58 | __uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP); | 57 | __uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP); |
@@ -77,23 +76,23 @@ static ssize_t hostaudio_read(struct file *file, char __user *buffer, | |||
77 | int err; | 76 | int err; |
78 | 77 | ||
79 | #ifdef DEBUG | 78 | #ifdef DEBUG |
80 | printk("hostaudio: read called, count = %d\n", count); | 79 | printk(KERN_DEBUG "hostaudio: read called, count = %d\n", count); |
81 | #endif | 80 | #endif |
82 | 81 | ||
83 | kbuf = kmalloc(count, GFP_KERNEL); | 82 | kbuf = kmalloc(count, GFP_KERNEL); |
84 | if(kbuf == NULL) | 83 | if (kbuf == NULL) |
85 | return(-ENOMEM); | 84 | return -ENOMEM; |
86 | 85 | ||
87 | err = os_read_file(state->fd, kbuf, count); | 86 | err = os_read_file(state->fd, kbuf, count); |
88 | if(err < 0) | 87 | if (err < 0) |
89 | goto out; | 88 | goto out; |
90 | 89 | ||
91 | if(copy_to_user(buffer, kbuf, err)) | 90 | if (copy_to_user(buffer, kbuf, err)) |
92 | err = -EFAULT; | 91 | err = -EFAULT; |
93 | 92 | ||
94 | out: | 93 | out: |
95 | kfree(kbuf); | 94 | kfree(kbuf); |
96 | return(err); | 95 | return err; |
97 | } | 96 | } |
98 | 97 | ||
99 | static ssize_t hostaudio_write(struct file *file, const char __user *buffer, | 98 | static ssize_t hostaudio_write(struct file *file, const char __user *buffer, |
@@ -104,40 +103,40 @@ static ssize_t hostaudio_write(struct file *file, const char __user *buffer, | |||
104 | int err; | 103 | int err; |
105 | 104 | ||
106 | #ifdef DEBUG | 105 | #ifdef DEBUG |
107 | printk("hostaudio: write called, count = %d\n", count); | 106 | printk(KERN_DEBUG "hostaudio: write called, count = %d\n", count); |
108 | #endif | 107 | #endif |
109 | 108 | ||
110 | kbuf = kmalloc(count, GFP_KERNEL); | 109 | kbuf = kmalloc(count, GFP_KERNEL); |
111 | if(kbuf == NULL) | 110 | if (kbuf == NULL) |
112 | return(-ENOMEM); | 111 | return -ENOMEM; |
113 | 112 | ||
114 | err = -EFAULT; | 113 | err = -EFAULT; |
115 | if(copy_from_user(kbuf, buffer, count)) | 114 | if (copy_from_user(kbuf, buffer, count)) |
116 | goto out; | 115 | goto out; |
117 | 116 | ||
118 | err = os_write_file(state->fd, kbuf, count); | 117 | err = os_write_file(state->fd, kbuf, count); |
119 | if(err < 0) | 118 | if (err < 0) |
120 | goto out; | 119 | goto out; |
121 | *ppos += err; | 120 | *ppos += err; |
122 | 121 | ||
123 | out: | 122 | out: |
124 | kfree(kbuf); | 123 | kfree(kbuf); |
125 | return(err); | 124 | return err; |
126 | } | 125 | } |
127 | 126 | ||
128 | static unsigned int hostaudio_poll(struct file *file, | 127 | static unsigned int hostaudio_poll(struct file *file, |
129 | struct poll_table_struct *wait) | 128 | struct poll_table_struct *wait) |
130 | { | 129 | { |
131 | unsigned int mask = 0; | 130 | unsigned int mask = 0; |
132 | 131 | ||
133 | #ifdef DEBUG | 132 | #ifdef DEBUG |
134 | printk("hostaudio: poll called (unimplemented)\n"); | 133 | printk(KERN_DEBUG "hostaudio: poll called (unimplemented)\n"); |
135 | #endif | 134 | #endif |
136 | 135 | ||
137 | return(mask); | 136 | return mask; |
138 | } | 137 | } |
139 | 138 | ||
140 | static int hostaudio_ioctl(struct inode *inode, struct file *file, | 139 | static int hostaudio_ioctl(struct inode *inode, struct file *file, |
141 | unsigned int cmd, unsigned long arg) | 140 | unsigned int cmd, unsigned long arg) |
142 | { | 141 | { |
143 | struct hostaudio_state *state = file->private_data; | 142 | struct hostaudio_state *state = file->private_data; |
@@ -145,7 +144,7 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file, | |||
145 | int err; | 144 | int err; |
146 | 145 | ||
147 | #ifdef DEBUG | 146 | #ifdef DEBUG |
148 | printk("hostaudio: ioctl called, cmd = %u\n", cmd); | 147 | printk(KERN_DEBUG "hostaudio: ioctl called, cmd = %u\n", cmd); |
149 | #endif | 148 | #endif |
150 | switch(cmd){ | 149 | switch(cmd){ |
151 | case SNDCTL_DSP_SPEED: | 150 | case SNDCTL_DSP_SPEED: |
@@ -154,8 +153,8 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file, | |||
154 | case SNDCTL_DSP_CHANNELS: | 153 | case SNDCTL_DSP_CHANNELS: |
155 | case SNDCTL_DSP_SUBDIVIDE: | 154 | case SNDCTL_DSP_SUBDIVIDE: |
156 | case SNDCTL_DSP_SETFRAGMENT: | 155 | case SNDCTL_DSP_SETFRAGMENT: |
157 | if(get_user(data, (int __user *) arg)) | 156 | if (get_user(data, (int __user *) arg)) |
158 | return(-EFAULT); | 157 | return EFAULT; |
159 | break; | 158 | break; |
160 | default: | 159 | default: |
161 | break; | 160 | break; |
@@ -170,14 +169,14 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file, | |||
170 | case SNDCTL_DSP_CHANNELS: | 169 | case SNDCTL_DSP_CHANNELS: |
171 | case SNDCTL_DSP_SUBDIVIDE: | 170 | case SNDCTL_DSP_SUBDIVIDE: |
172 | case SNDCTL_DSP_SETFRAGMENT: | 171 | case SNDCTL_DSP_SETFRAGMENT: |
173 | if(put_user(data, (int __user *) arg)) | 172 | if (put_user(data, (int __user *) arg)) |
174 | return(-EFAULT); | 173 | return -EFAULT; |
175 | break; | 174 | break; |
176 | default: | 175 | default: |
177 | break; | 176 | break; |
178 | } | 177 | } |
179 | 178 | ||
180 | return(err); | 179 | return err; |
181 | } | 180 | } |
182 | 181 | ||
183 | static int hostaudio_open(struct inode *inode, struct file *file) | 182 | static int hostaudio_open(struct inode *inode, struct file *file) |
@@ -187,24 +186,26 @@ static int hostaudio_open(struct inode *inode, struct file *file) | |||
187 | int ret; | 186 | int ret; |
188 | 187 | ||
189 | #ifdef DEBUG | 188 | #ifdef DEBUG |
190 | printk("hostaudio: open called (host: %s)\n", dsp); | 189 | printk(KERN_DEBUG "hostaudio: open called (host: %s)\n", dsp); |
191 | #endif | 190 | #endif |
192 | 191 | ||
193 | state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL); | 192 | state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL); |
194 | if(state == NULL) | 193 | if (state == NULL) |
195 | return(-ENOMEM); | 194 | return -ENOMEM; |
196 | 195 | ||
197 | if(file->f_mode & FMODE_READ) r = 1; | 196 | if (file->f_mode & FMODE_READ) |
198 | if(file->f_mode & FMODE_WRITE) w = 1; | 197 | r = 1; |
198 | if (file->f_mode & FMODE_WRITE) | ||
199 | w = 1; | ||
199 | 200 | ||
200 | ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); | 201 | ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); |
201 | if(ret < 0){ | 202 | if (ret < 0) { |
202 | kfree(state); | 203 | kfree(state); |
203 | return(ret); | 204 | return ret; |
204 | } | 205 | } |
205 | state->fd = ret; | 206 | state->fd = ret; |
206 | file->private_data = state; | 207 | file->private_data = state; |
207 | return(0); | 208 | return 0; |
208 | } | 209 | } |
209 | 210 | ||
210 | static int hostaudio_release(struct inode *inode, struct file *file) | 211 | static int hostaudio_release(struct inode *inode, struct file *file) |
@@ -212,26 +213,26 @@ static int hostaudio_release(struct inode *inode, struct file *file) | |||
212 | struct hostaudio_state *state = file->private_data; | 213 | struct hostaudio_state *state = file->private_data; |
213 | 214 | ||
214 | #ifdef DEBUG | 215 | #ifdef DEBUG |
215 | printk("hostaudio: release called\n"); | 216 | printk(KERN_DEBUG "hostaudio: release called\n"); |
216 | #endif | 217 | #endif |
217 | os_close_file(state->fd); | 218 | os_close_file(state->fd); |
218 | kfree(state); | 219 | kfree(state); |
219 | 220 | ||
220 | return(0); | 221 | return 0; |
221 | } | 222 | } |
222 | 223 | ||
223 | /* /dev/mixer file operations */ | 224 | /* /dev/mixer file operations */ |
224 | 225 | ||
225 | static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file, | 226 | static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file, |
226 | unsigned int cmd, unsigned long arg) | 227 | unsigned int cmd, unsigned long arg) |
227 | { | 228 | { |
228 | struct hostmixer_state *state = file->private_data; | 229 | struct hostmixer_state *state = file->private_data; |
229 | 230 | ||
230 | #ifdef DEBUG | 231 | #ifdef DEBUG |
231 | printk("hostmixer: ioctl called\n"); | 232 | printk(KERN_DEBUG "hostmixer: ioctl called\n"); |
232 | #endif | 233 | #endif |
233 | 234 | ||
234 | return(os_ioctl_generic(state->fd, cmd, arg)); | 235 | return os_ioctl_generic(state->fd, cmd, arg); |
235 | } | 236 | } |
236 | 237 | ||
237 | static int hostmixer_open_mixdev(struct inode *inode, struct file *file) | 238 | static int hostmixer_open_mixdev(struct inode *inode, struct file *file) |
@@ -241,26 +242,29 @@ static int hostmixer_open_mixdev(struct inode *inode, struct file *file) | |||
241 | int ret; | 242 | int ret; |
242 | 243 | ||
243 | #ifdef DEBUG | 244 | #ifdef DEBUG |
244 | printk("hostmixer: open called (host: %s)\n", mixer); | 245 | printk(KERN_DEBUG "hostmixer: open called (host: %s)\n", mixer); |
245 | #endif | 246 | #endif |
246 | 247 | ||
247 | state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL); | 248 | state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL); |
248 | if(state == NULL) return(-ENOMEM); | 249 | if (state == NULL) |
250 | return -ENOMEM; | ||
249 | 251 | ||
250 | if(file->f_mode & FMODE_READ) r = 1; | 252 | if (file->f_mode & FMODE_READ) |
251 | if(file->f_mode & FMODE_WRITE) w = 1; | 253 | r = 1; |
254 | if (file->f_mode & FMODE_WRITE) | ||
255 | w = 1; | ||
252 | 256 | ||
253 | ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); | 257 | ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); |
254 | 258 | ||
255 | if(ret < 0){ | 259 | if (ret < 0) { |
256 | printk("hostaudio_open_mixdev failed to open '%s', err = %d\n", | 260 | printk(KERN_ERR "hostaudio_open_mixdev failed to open '%s', " |
257 | dsp, -ret); | 261 | "err = %d\n", dsp, -ret); |
258 | kfree(state); | 262 | kfree(state); |
259 | return(ret); | 263 | return ret; |
260 | } | 264 | } |
261 | 265 | ||
262 | file->private_data = state; | 266 | file->private_data = state; |
263 | return(0); | 267 | return 0; |
264 | } | 268 | } |
265 | 269 | ||
266 | static int hostmixer_release(struct inode *inode, struct file *file) | 270 | static int hostmixer_release(struct inode *inode, struct file *file) |
@@ -268,13 +272,13 @@ static int hostmixer_release(struct inode *inode, struct file *file) | |||
268 | struct hostmixer_state *state = file->private_data; | 272 | struct hostmixer_state *state = file->private_data; |
269 | 273 | ||
270 | #ifdef DEBUG | 274 | #ifdef DEBUG |
271 | printk("hostmixer: release called\n"); | 275 | printk(KERN_DEBUG "hostmixer: release called\n"); |
272 | #endif | 276 | #endif |
273 | 277 | ||
274 | os_close_file(state->fd); | 278 | os_close_file(state->fd); |
275 | kfree(state); | 279 | kfree(state); |
276 | 280 | ||
277 | return(0); | 281 | return 0; |
278 | } | 282 | } |
279 | 283 | ||
280 | /* kernel module operations */ | 284 | /* kernel module operations */ |
@@ -314,13 +318,13 @@ static int __init hostaudio_init_module(void) | |||
314 | dsp, mixer); | 318 | dsp, mixer); |
315 | 319 | ||
316 | module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1); | 320 | module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1); |
317 | if(module_data.dev_audio < 0){ | 321 | if (module_data.dev_audio < 0) { |
318 | printk(KERN_ERR "hostaudio: couldn't register DSP device!\n"); | 322 | printk(KERN_ERR "hostaudio: couldn't register DSP device!\n"); |
319 | return -ENODEV; | 323 | return -ENODEV; |
320 | } | 324 | } |
321 | 325 | ||
322 | module_data.dev_mixer = register_sound_mixer(&hostmixer_fops, -1); | 326 | module_data.dev_mixer = register_sound_mixer(&hostmixer_fops, -1); |
323 | if(module_data.dev_mixer < 0){ | 327 | if (module_data.dev_mixer < 0) { |
324 | printk(KERN_ERR "hostmixer: couldn't register mixer " | 328 | printk(KERN_ERR "hostmixer: couldn't register mixer " |
325 | "device!\n"); | 329 | "device!\n"); |
326 | unregister_sound_dsp(module_data.dev_audio); | 330 | unregister_sound_dsp(module_data.dev_audio); |
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 3e0b68e297f2..76fe0b0da996 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c | |||
@@ -1,22 +1,14 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/kernel.h" | 6 | #include "linux/irqreturn.h" |
7 | #include "linux/sched.h" | ||
8 | #include "linux/slab.h" | ||
9 | #include "linux/list.h" | ||
10 | #include "linux/kd.h" | 7 | #include "linux/kd.h" |
11 | #include "linux/interrupt.h" | ||
12 | #include "asm/uaccess.h" | ||
13 | #include "chan_kern.h" | 8 | #include "chan_kern.h" |
9 | #include "irq_kern.h" | ||
14 | #include "irq_user.h" | 10 | #include "irq_user.h" |
15 | #include "line.h" | ||
16 | #include "kern.h" | ||
17 | #include "kern_util.h" | ||
18 | #include "os.h" | 11 | #include "os.h" |
19 | #include "irq_kern.h" | ||
20 | 12 | ||
21 | #define LINE_BUFSIZE 4096 | 13 | #define LINE_BUFSIZE 4096 |
22 | 14 | ||
@@ -35,12 +27,13 @@ static void line_timer_cb(struct work_struct *work) | |||
35 | { | 27 | { |
36 | struct line *line = container_of(work, struct line, task.work); | 28 | struct line *line = container_of(work, struct line, task.work); |
37 | 29 | ||
38 | if(!line->throttled) | 30 | if (!line->throttled) |
39 | chan_interrupt(&line->chan_list, &line->task, line->tty, | 31 | chan_interrupt(&line->chan_list, &line->task, line->tty, |
40 | line->driver->read_irq); | 32 | line->driver->read_irq); |
41 | } | 33 | } |
42 | 34 | ||
43 | /* Returns the free space inside the ring buffer of this line. | 35 | /* |
36 | * Returns the free space inside the ring buffer of this line. | ||
44 | * | 37 | * |
45 | * Should be called while holding line->lock (this does not modify datas). | 38 | * Should be called while holding line->lock (this does not modify datas). |
46 | */ | 39 | */ |
@@ -107,11 +100,12 @@ static int buffer_data(struct line *line, const char *buf, int len) | |||
107 | { | 100 | { |
108 | int end, room; | 101 | int end, room; |
109 | 102 | ||
110 | if(line->buffer == NULL){ | 103 | if (line->buffer == NULL) { |
111 | line->buffer = kmalloc(LINE_BUFSIZE, GFP_ATOMIC); | 104 | line->buffer = kmalloc(LINE_BUFSIZE, GFP_ATOMIC); |
112 | if (line->buffer == NULL) { | 105 | if (line->buffer == NULL) { |
113 | printk("buffer_data - atomic allocation failed\n"); | 106 | printk(KERN_ERR "buffer_data - atomic allocation " |
114 | return(0); | 107 | "failed\n"); |
108 | return 0; | ||
115 | } | 109 | } |
116 | line->head = line->buffer; | 110 | line->head = line->buffer; |
117 | line->tail = line->buffer; | 111 | line->tail = line->buffer; |
@@ -122,7 +116,7 @@ static int buffer_data(struct line *line, const char *buf, int len) | |||
122 | 116 | ||
123 | end = line->buffer + LINE_BUFSIZE - line->tail; | 117 | end = line->buffer + LINE_BUFSIZE - line->tail; |
124 | 118 | ||
125 | if (len < end){ | 119 | if (len < end) { |
126 | memcpy(line->tail, buf, len); | 120 | memcpy(line->tail, buf, len); |
127 | line->tail += len; | 121 | line->tail += len; |
128 | } | 122 | } |
@@ -162,8 +156,10 @@ static int flush_buffer(struct line *line) | |||
162 | if (n < 0) | 156 | if (n < 0) |
163 | return n; | 157 | return n; |
164 | if (n == count) { | 158 | if (n == count) { |
165 | /* We have flushed from ->head to buffer end, now we | 159 | /* |
166 | * must flush only from the beginning to ->tail.*/ | 160 | * We have flushed from ->head to buffer end, now we |
161 | * must flush only from the beginning to ->tail. | ||
162 | */ | ||
167 | line->head = line->buffer; | 163 | line->head = line->buffer; |
168 | } else { | 164 | } else { |
169 | line->head += n; | 165 | line->head += n; |
@@ -175,7 +171,7 @@ static int flush_buffer(struct line *line) | |||
175 | n = write_chan(&line->chan_list, line->head, count, | 171 | n = write_chan(&line->chan_list, line->head, count, |
176 | line->driver->write_irq); | 172 | line->driver->write_irq); |
177 | 173 | ||
178 | if(n < 0) | 174 | if (n < 0) |
179 | return n; | 175 | return n; |
180 | 176 | ||
181 | line->head += n; | 177 | line->head += n; |
@@ -189,19 +185,18 @@ void line_flush_buffer(struct tty_struct *tty) | |||
189 | int err; | 185 | int err; |
190 | 186 | ||
191 | /*XXX: copied from line_write, verify if it is correct!*/ | 187 | /*XXX: copied from line_write, verify if it is correct!*/ |
192 | if(tty->stopped) | 188 | if (tty->stopped) |
193 | return; | 189 | return; |
194 | 190 | ||
195 | spin_lock_irqsave(&line->lock, flags); | 191 | spin_lock_irqsave(&line->lock, flags); |
196 | err = flush_buffer(line); | 192 | err = flush_buffer(line); |
197 | /*if (err == 1) | ||
198 | err = 0;*/ | ||
199 | spin_unlock_irqrestore(&line->lock, flags); | 193 | spin_unlock_irqrestore(&line->lock, flags); |
200 | //return err; | ||
201 | } | 194 | } |
202 | 195 | ||
203 | /* We map both ->flush_chars and ->put_char (which go in pair) onto ->flush_buffer | 196 | /* |
204 | * and ->write. Hope it's not that bad.*/ | 197 | * We map both ->flush_chars and ->put_char (which go in pair) onto |
198 | * ->flush_buffer and ->write. Hope it's not that bad. | ||
199 | */ | ||
205 | void line_flush_chars(struct tty_struct *tty) | 200 | void line_flush_chars(struct tty_struct *tty) |
206 | { | 201 | { |
207 | line_flush_buffer(tty); | 202 | line_flush_buffer(tty); |
@@ -216,18 +211,15 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len) | |||
216 | { | 211 | { |
217 | struct line *line = tty->driver_data; | 212 | struct line *line = tty->driver_data; |
218 | unsigned long flags; | 213 | unsigned long flags; |
219 | int n, err, ret = 0; | 214 | int n, ret = 0; |
220 | 215 | ||
221 | if(tty->stopped) | 216 | if (tty->stopped) |
222 | return 0; | 217 | return 0; |
223 | 218 | ||
224 | spin_lock_irqsave(&line->lock, flags); | 219 | spin_lock_irqsave(&line->lock, flags); |
225 | if (line->head != line->tail) { | 220 | if (line->head != line->tail) |
226 | ret = buffer_data(line, buf, len); | 221 | ret = buffer_data(line, buf, len); |
227 | err = flush_buffer(line); | 222 | else { |
228 | if (err <= 0 && (err != -EAGAIN || !ret)) | ||
229 | ret = err; | ||
230 | } else { | ||
231 | n = write_chan(&line->chan_list, buf, len, | 223 | n = write_chan(&line->chan_list, buf, len, |
232 | line->driver->write_irq); | 224 | line->driver->write_irq); |
233 | if (n < 0) { | 225 | if (n < 0) { |
@@ -257,17 +249,17 @@ static const struct { | |||
257 | } tty_ioctls[] = { | 249 | } tty_ioctls[] = { |
258 | /* don't print these, they flood the log ... */ | 250 | /* don't print these, they flood the log ... */ |
259 | { TCGETS, NULL, "TCGETS" }, | 251 | { TCGETS, NULL, "TCGETS" }, |
260 | { TCSETS, NULL, "TCSETS" }, | 252 | { TCSETS, NULL, "TCSETS" }, |
261 | { TCSETSW, NULL, "TCSETSW" }, | 253 | { TCSETSW, NULL, "TCSETSW" }, |
262 | { TCFLSH, NULL, "TCFLSH" }, | 254 | { TCFLSH, NULL, "TCFLSH" }, |
263 | { TCSBRK, NULL, "TCSBRK" }, | 255 | { TCSBRK, NULL, "TCSBRK" }, |
264 | 256 | ||
265 | /* general tty stuff */ | 257 | /* general tty stuff */ |
266 | { TCSETSF, KERN_DEBUG, "TCSETSF" }, | 258 | { TCSETSF, KERN_DEBUG, "TCSETSF" }, |
267 | { TCGETA, KERN_DEBUG, "TCGETA" }, | 259 | { TCGETA, KERN_DEBUG, "TCGETA" }, |
268 | { TIOCMGET, KERN_DEBUG, "TIOCMGET" }, | 260 | { TIOCMGET, KERN_DEBUG, "TIOCMGET" }, |
269 | { TCSBRKP, KERN_DEBUG, "TCSBRKP" }, | 261 | { TCSBRKP, KERN_DEBUG, "TCSBRKP" }, |
270 | { TIOCMSET, KERN_DEBUG, "TIOCMSET" }, | 262 | { TIOCMSET, KERN_DEBUG, "TIOCMSET" }, |
271 | 263 | ||
272 | /* linux-specific ones */ | 264 | /* linux-specific ones */ |
273 | { TIOCLINUX, KERN_INFO, "TIOCLINUX" }, | 265 | { TIOCLINUX, KERN_INFO, "TIOCLINUX" }, |
@@ -324,12 +316,7 @@ int line_ioctl(struct tty_struct *tty, struct file * file, | |||
324 | for (i = 0; i < ARRAY_SIZE(tty_ioctls); i++) | 316 | for (i = 0; i < ARRAY_SIZE(tty_ioctls); i++) |
325 | if (cmd == tty_ioctls[i].cmd) | 317 | if (cmd == tty_ioctls[i].cmd) |
326 | break; | 318 | break; |
327 | if (i < ARRAY_SIZE(tty_ioctls)) { | 319 | if (i == ARRAY_SIZE(tty_ioctls)) { |
328 | if (NULL != tty_ioctls[i].level) | ||
329 | printk("%s%s: %s: ioctl %s called\n", | ||
330 | tty_ioctls[i].level, __FUNCTION__, | ||
331 | tty->name, tty_ioctls[i].name); | ||
332 | } else { | ||
333 | printk(KERN_ERR "%s: %s: unknown ioctl: 0x%x\n", | 320 | printk(KERN_ERR "%s: %s: unknown ioctl: 0x%x\n", |
334 | __FUNCTION__, tty->name, cmd); | 321 | __FUNCTION__, tty->name, cmd); |
335 | } | 322 | } |
@@ -355,11 +342,12 @@ void line_unthrottle(struct tty_struct *tty) | |||
355 | chan_interrupt(&line->chan_list, &line->task, tty, | 342 | chan_interrupt(&line->chan_list, &line->task, tty, |
356 | line->driver->read_irq); | 343 | line->driver->read_irq); |
357 | 344 | ||
358 | /* Maybe there is enough stuff pending that calling the interrupt | 345 | /* |
346 | * Maybe there is enough stuff pending that calling the interrupt | ||
359 | * throttles us again. In this case, line->throttled will be 1 | 347 | * throttles us again. In this case, line->throttled will be 1 |
360 | * again and we shouldn't turn the interrupt back on. | 348 | * again and we shouldn't turn the interrupt back on. |
361 | */ | 349 | */ |
362 | if(!line->throttled) | 350 | if (!line->throttled) |
363 | reactivate_chan(&line->chan_list, line->driver->read_irq); | 351 | reactivate_chan(&line->chan_list, line->driver->read_irq); |
364 | } | 352 | } |
365 | 353 | ||
@@ -370,27 +358,30 @@ static irqreturn_t line_write_interrupt(int irq, void *data) | |||
370 | struct tty_struct *tty = line->tty; | 358 | struct tty_struct *tty = line->tty; |
371 | int err; | 359 | int err; |
372 | 360 | ||
373 | /* Interrupts are disabled here because we registered the interrupt with | 361 | /* |
374 | * IRQF_DISABLED (see line_setup_irq).*/ | 362 | * Interrupts are disabled here because we registered the interrupt with |
363 | * IRQF_DISABLED (see line_setup_irq). | ||
364 | */ | ||
375 | 365 | ||
376 | spin_lock(&line->lock); | 366 | spin_lock(&line->lock); |
377 | err = flush_buffer(line); | 367 | err = flush_buffer(line); |
378 | if (err == 0) { | 368 | if (err == 0) { |
379 | return IRQ_NONE; | 369 | return IRQ_NONE; |
380 | } else if(err < 0) { | 370 | } else if (err < 0) { |
381 | line->head = line->buffer; | 371 | line->head = line->buffer; |
382 | line->tail = line->buffer; | 372 | line->tail = line->buffer; |
383 | } | 373 | } |
384 | spin_unlock(&line->lock); | 374 | spin_unlock(&line->lock); |
385 | 375 | ||
386 | if(tty == NULL) | 376 | if (tty == NULL) |
387 | return IRQ_NONE; | 377 | return IRQ_NONE; |
388 | 378 | ||
389 | if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && | 379 | if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && |
390 | (tty->ldisc.write_wakeup != NULL)) | 380 | (tty->ldisc.write_wakeup != NULL)) |
391 | (tty->ldisc.write_wakeup)(tty); | 381 | (tty->ldisc.write_wakeup)(tty); |
392 | 382 | ||
393 | /* BLOCKING mode | 383 | /* |
384 | * BLOCKING mode | ||
394 | * In blocking mode, everything sleeps on tty->write_wait. | 385 | * In blocking mode, everything sleeps on tty->write_wait. |
395 | * Sleeping in the console driver would break non-blocking | 386 | * Sleeping in the console driver would break non-blocking |
396 | * writes. | 387 | * writes. |
@@ -420,7 +411,8 @@ int line_setup_irq(int fd, int input, int output, struct line *line, void *data) | |||
420 | return err; | 411 | return err; |
421 | } | 412 | } |
422 | 413 | ||
423 | /* Normally, a driver like this can rely mostly on the tty layer | 414 | /* |
415 | * Normally, a driver like this can rely mostly on the tty layer | ||
424 | * locking, particularly when it comes to the driver structure. | 416 | * locking, particularly when it comes to the driver structure. |
425 | * However, in this case, mconsole requests can come in "from the | 417 | * However, in this case, mconsole requests can come in "from the |
426 | * side", and race with opens and closes. | 418 | * side", and race with opens and closes. |
@@ -442,11 +434,11 @@ int line_open(struct line *lines, struct tty_struct *tty) | |||
442 | int err = -ENODEV; | 434 | int err = -ENODEV; |
443 | 435 | ||
444 | spin_lock(&line->count_lock); | 436 | spin_lock(&line->count_lock); |
445 | if(!line->valid) | 437 | if (!line->valid) |
446 | goto out_unlock; | 438 | goto out_unlock; |
447 | 439 | ||
448 | err = 0; | 440 | err = 0; |
449 | if(tty->count > 1) | 441 | if (tty->count > 1) |
450 | goto out_unlock; | 442 | goto out_unlock; |
451 | 443 | ||
452 | spin_unlock(&line->count_lock); | 444 | spin_unlock(&line->count_lock); |
@@ -460,7 +452,7 @@ int line_open(struct line *lines, struct tty_struct *tty) | |||
460 | 452 | ||
461 | INIT_DELAYED_WORK(&line->task, line_timer_cb); | 453 | INIT_DELAYED_WORK(&line->task, line_timer_cb); |
462 | 454 | ||
463 | if(!line->sigio){ | 455 | if (!line->sigio) { |
464 | chan_enable_winch(&line->chan_list, tty); | 456 | chan_enable_winch(&line->chan_list, tty); |
465 | line->sigio = 1; | 457 | line->sigio = 1; |
466 | } | 458 | } |
@@ -481,20 +473,21 @@ void line_close(struct tty_struct *tty, struct file * filp) | |||
481 | { | 473 | { |
482 | struct line *line = tty->driver_data; | 474 | struct line *line = tty->driver_data; |
483 | 475 | ||
484 | /* If line_open fails (and tty->driver_data is never set), | 476 | /* |
477 | * If line_open fails (and tty->driver_data is never set), | ||
485 | * tty_open will call line_close. So just return in this case. | 478 | * tty_open will call line_close. So just return in this case. |
486 | */ | 479 | */ |
487 | if(line == NULL) | 480 | if (line == NULL) |
488 | return; | 481 | return; |
489 | 482 | ||
490 | /* We ignore the error anyway! */ | 483 | /* We ignore the error anyway! */ |
491 | flush_buffer(line); | 484 | flush_buffer(line); |
492 | 485 | ||
493 | spin_lock(&line->count_lock); | 486 | spin_lock(&line->count_lock); |
494 | if(!line->valid) | 487 | if (!line->valid) |
495 | goto out_unlock; | 488 | goto out_unlock; |
496 | 489 | ||
497 | if(tty->count > 1) | 490 | if (tty->count > 1) |
498 | goto out_unlock; | 491 | goto out_unlock; |
499 | 492 | ||
500 | spin_unlock(&line->count_lock); | 493 | spin_unlock(&line->count_lock); |
@@ -502,10 +495,10 @@ void line_close(struct tty_struct *tty, struct file * filp) | |||
502 | line->tty = NULL; | 495 | line->tty = NULL; |
503 | tty->driver_data = NULL; | 496 | tty->driver_data = NULL; |
504 | 497 | ||
505 | if(line->sigio){ | 498 | if (line->sigio) { |
506 | unregister_winch(tty); | 499 | unregister_winch(tty); |
507 | line->sigio = 0; | 500 | line->sigio = 0; |
508 | } | 501 | } |
509 | 502 | ||
510 | return; | 503 | return; |
511 | 504 | ||
@@ -529,12 +522,12 @@ static int setup_one_line(struct line *lines, int n, char *init, int init_prio, | |||
529 | 522 | ||
530 | spin_lock(&line->count_lock); | 523 | spin_lock(&line->count_lock); |
531 | 524 | ||
532 | if(line->tty != NULL){ | 525 | if (line->tty != NULL) { |
533 | *error_out = "Device is already open"; | 526 | *error_out = "Device is already open"; |
534 | goto out; | 527 | goto out; |
535 | } | 528 | } |
536 | 529 | ||
537 | if (line->init_pri <= init_prio){ | 530 | if (line->init_pri <= init_prio) { |
538 | line->init_pri = init_prio; | 531 | line->init_pri = init_prio; |
539 | if (!strcmp(init, "none")) | 532 | if (!strcmp(init, "none")) |
540 | line->valid = 0; | 533 | line->valid = 0; |
@@ -549,7 +542,8 @@ out: | |||
549 | return err; | 542 | return err; |
550 | } | 543 | } |
551 | 544 | ||
552 | /* Common setup code for both startup command line and mconsole initialization. | 545 | /* |
546 | * Common setup code for both startup command line and mconsole initialization. | ||
553 | * @lines contains the array (of size @num) to modify; | 547 | * @lines contains the array (of size @num) to modify; |
554 | * @init is the setup string; | 548 | * @init is the setup string; |
555 | * @error_out is an error string in the case of failure; | 549 | * @error_out is an error string in the case of failure; |
@@ -561,14 +555,16 @@ int line_setup(struct line *lines, unsigned int num, char *init, | |||
561 | int i, n, err; | 555 | int i, n, err; |
562 | char *end; | 556 | char *end; |
563 | 557 | ||
564 | if(*init == '=') { | 558 | if (*init == '=') { |
565 | /* We said con=/ssl= instead of con#=, so we are configuring all | 559 | /* |
566 | * consoles at once.*/ | 560 | * We said con=/ssl= instead of con#=, so we are configuring all |
561 | * consoles at once. | ||
562 | */ | ||
567 | n = -1; | 563 | n = -1; |
568 | } | 564 | } |
569 | else { | 565 | else { |
570 | n = simple_strtoul(init, &end, 0); | 566 | n = simple_strtoul(init, &end, 0); |
571 | if(*end != '='){ | 567 | if (*end != '=') { |
572 | *error_out = "Couldn't parse device number"; | 568 | *error_out = "Couldn't parse device number"; |
573 | return -EINVAL; | 569 | return -EINVAL; |
574 | } | 570 | } |
@@ -580,16 +576,16 @@ int line_setup(struct line *lines, unsigned int num, char *init, | |||
580 | *error_out = "Device number out of range"; | 576 | *error_out = "Device number out of range"; |
581 | return -EINVAL; | 577 | return -EINVAL; |
582 | } | 578 | } |
583 | else if (n >= 0){ | 579 | else if (n >= 0) { |
584 | err = setup_one_line(lines, n, init, INIT_ONE, error_out); | 580 | err = setup_one_line(lines, n, init, INIT_ONE, error_out); |
585 | if(err) | 581 | if (err) |
586 | return err; | 582 | return err; |
587 | } | 583 | } |
588 | else { | 584 | else { |
589 | for(i = 0; i < num; i++){ | 585 | for(i = 0; i < num; i++) { |
590 | err = setup_one_line(lines, i, init, INIT_ALL, | 586 | err = setup_one_line(lines, i, init, INIT_ALL, |
591 | error_out); | 587 | error_out); |
592 | if(err) | 588 | if (err) |
593 | return err; | 589 | return err; |
594 | } | 590 | } |
595 | } | 591 | } |
@@ -603,18 +599,18 @@ int line_config(struct line *lines, unsigned int num, char *str, | |||
603 | char *new; | 599 | char *new; |
604 | int n; | 600 | int n; |
605 | 601 | ||
606 | if(*str == '='){ | 602 | if (*str == '=') { |
607 | *error_out = "Can't configure all devices from mconsole"; | 603 | *error_out = "Can't configure all devices from mconsole"; |
608 | return -EINVAL; | 604 | return -EINVAL; |
609 | } | 605 | } |
610 | 606 | ||
611 | new = kstrdup(str, GFP_KERNEL); | 607 | new = kstrdup(str, GFP_KERNEL); |
612 | if(new == NULL){ | 608 | if (new == NULL) { |
613 | *error_out = "Failed to allocate memory"; | 609 | *error_out = "Failed to allocate memory"; |
614 | return -ENOMEM; | 610 | return -ENOMEM; |
615 | } | 611 | } |
616 | n = line_setup(lines, num, new, error_out); | 612 | n = line_setup(lines, num, new, error_out); |
617 | if(n < 0) | 613 | if (n < 0) |
618 | return n; | 614 | return n; |
619 | 615 | ||
620 | line = &lines[n]; | 616 | line = &lines[n]; |
@@ -629,12 +625,12 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, | |||
629 | int dev, n = 0; | 625 | int dev, n = 0; |
630 | 626 | ||
631 | dev = simple_strtoul(name, &end, 0); | 627 | dev = simple_strtoul(name, &end, 0); |
632 | if((*end != '\0') || (end == name)){ | 628 | if ((*end != '\0') || (end == name)) { |
633 | *error_out = "line_get_config failed to parse device number"; | 629 | *error_out = "line_get_config failed to parse device number"; |
634 | return 0; | 630 | return 0; |
635 | } | 631 | } |
636 | 632 | ||
637 | if((dev < 0) || (dev >= num)){ | 633 | if ((dev < 0) || (dev >= num)) { |
638 | *error_out = "device number out of range"; | 634 | *error_out = "device number out of range"; |
639 | return 0; | 635 | return 0; |
640 | } | 636 | } |
@@ -642,9 +638,9 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, | |||
642 | line = &lines[dev]; | 638 | line = &lines[dev]; |
643 | 639 | ||
644 | spin_lock(&line->count_lock); | 640 | spin_lock(&line->count_lock); |
645 | if(!line->valid) | 641 | if (!line->valid) |
646 | CONFIG_CHUNK(str, size, n, "none", 1); | 642 | CONFIG_CHUNK(str, size, n, "none", 1); |
647 | else if(line->tty == NULL) | 643 | else if (line->tty == NULL) |
648 | CONFIG_CHUNK(str, size, n, line->init_str, 1); | 644 | CONFIG_CHUNK(str, size, n, line->init_str, 1); |
649 | else n = chan_config_string(&line->chan_list, str, size, error_out); | 645 | else n = chan_config_string(&line->chan_list, str, size, error_out); |
650 | spin_unlock(&line->count_lock); | 646 | spin_unlock(&line->count_lock); |
@@ -655,16 +651,16 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, | |||
655 | int line_id(char **str, int *start_out, int *end_out) | 651 | int line_id(char **str, int *start_out, int *end_out) |
656 | { | 652 | { |
657 | char *end; | 653 | char *end; |
658 | int n; | 654 | int n; |
659 | 655 | ||
660 | n = simple_strtoul(*str, &end, 0); | 656 | n = simple_strtoul(*str, &end, 0); |
661 | if((*end != '\0') || (end == *str)) | 657 | if ((*end != '\0') || (end == *str)) |
662 | return -1; | 658 | return -1; |
663 | 659 | ||
664 | *str = end; | 660 | *str = end; |
665 | *start_out = n; | 661 | *start_out = n; |
666 | *end_out = n; | 662 | *end_out = n; |
667 | return n; | 663 | return n; |
668 | } | 664 | } |
669 | 665 | ||
670 | int line_remove(struct line *lines, unsigned int num, int n, char **error_out) | 666 | int line_remove(struct line *lines, unsigned int num, int n, char **error_out) |
@@ -674,7 +670,7 @@ int line_remove(struct line *lines, unsigned int num, int n, char **error_out) | |||
674 | 670 | ||
675 | sprintf(config, "%d=none", n); | 671 | sprintf(config, "%d=none", n); |
676 | err = line_setup(lines, num, config, error_out); | 672 | err = line_setup(lines, num, config, error_out); |
677 | if(err >= 0) | 673 | if (err >= 0) |
678 | err = 0; | 674 | err = 0; |
679 | return err; | 675 | return err; |
680 | } | 676 | } |
@@ -700,14 +696,14 @@ struct tty_driver *register_lines(struct line_driver *line_driver, | |||
700 | tty_set_operations(driver, ops); | 696 | tty_set_operations(driver, ops); |
701 | 697 | ||
702 | if (tty_register_driver(driver)) { | 698 | if (tty_register_driver(driver)) { |
703 | printk("%s: can't register %s driver\n", | 699 | printk(KERN_ERR "register_lines : can't register %s driver\n", |
704 | __FUNCTION__,line_driver->name); | 700 | line_driver->name); |
705 | put_tty_driver(driver); | 701 | put_tty_driver(driver); |
706 | return NULL; | 702 | return NULL; |
707 | } | 703 | } |
708 | 704 | ||
709 | for(i = 0; i < nlines; i++){ | 705 | for(i = 0; i < nlines; i++) { |
710 | if(!lines[i].valid) | 706 | if (!lines[i].valid) |
711 | tty_unregister_device(driver, i); | 707 | tty_unregister_device(driver, i); |
712 | } | 708 | } |
713 | 709 | ||
@@ -724,20 +720,20 @@ void lines_init(struct line *lines, int nlines, struct chan_opts *opts) | |||
724 | char *error; | 720 | char *error; |
725 | int i; | 721 | int i; |
726 | 722 | ||
727 | for(i = 0; i < nlines; i++){ | 723 | for(i = 0; i < nlines; i++) { |
728 | line = &lines[i]; | 724 | line = &lines[i]; |
729 | INIT_LIST_HEAD(&line->chan_list); | 725 | INIT_LIST_HEAD(&line->chan_list); |
730 | 726 | ||
731 | if(line->init_str == NULL) | 727 | if (line->init_str == NULL) |
732 | continue; | 728 | continue; |
733 | 729 | ||
734 | line->init_str = kstrdup(line->init_str, GFP_KERNEL); | 730 | line->init_str = kstrdup(line->init_str, GFP_KERNEL); |
735 | if(line->init_str == NULL) | 731 | if (line->init_str == NULL) |
736 | printk("lines_init - kstrdup returned NULL\n"); | 732 | printk(KERN_ERR "lines_init - kstrdup returned NULL\n"); |
737 | 733 | ||
738 | if(parse_chan_pair(line->init_str, line, i, opts, &error)){ | 734 | if (parse_chan_pair(line->init_str, line, i, opts, &error)) { |
739 | printk("parse_chan_pair failed for device %d : %s\n", | 735 | printk(KERN_ERR "parse_chan_pair failed for " |
740 | i, error); | 736 | "device %d : %s\n", i, error); |
741 | line->valid = 0; | 737 | line->valid = 0; |
742 | } | 738 | } |
743 | } | 739 | } |
@@ -775,14 +771,14 @@ static irqreturn_t winch_interrupt(int irq, void *data) | |||
775 | int err; | 771 | int err; |
776 | char c; | 772 | char c; |
777 | 773 | ||
778 | if(winch->fd != -1){ | 774 | if (winch->fd != -1) { |
779 | err = generic_read(winch->fd, &c, NULL); | 775 | err = generic_read(winch->fd, &c, NULL); |
780 | if(err < 0){ | 776 | if (err < 0) { |
781 | if(err != -EAGAIN){ | 777 | if (err != -EAGAIN) { |
782 | printk("winch_interrupt : read failed, " | 778 | printk(KERN_ERR "winch_interrupt : " |
783 | "errno = %d\n", -err); | 779 | "read failed, errno = %d\n", -err); |
784 | printk("fd %d is losing SIGWINCH support\n", | 780 | printk(KERN_ERR "fd %d is losing SIGWINCH " |
785 | winch->tty_fd); | 781 | "support\n", winch->tty_fd); |
786 | free_winch(winch, 0); | 782 | free_winch(winch, 0); |
787 | return IRQ_HANDLED; | 783 | return IRQ_HANDLED; |
788 | } | 784 | } |
@@ -797,7 +793,7 @@ static irqreturn_t winch_interrupt(int irq, void *data) | |||
797 | kill_pgrp(tty->pgrp, SIGWINCH, 1); | 793 | kill_pgrp(tty->pgrp, SIGWINCH, 1); |
798 | } | 794 | } |
799 | out: | 795 | out: |
800 | if(winch->fd != -1) | 796 | if (winch->fd != -1) |
801 | reactivate_fd(winch->fd, WINCH_IRQ); | 797 | reactivate_fd(winch->fd, WINCH_IRQ); |
802 | return IRQ_HANDLED; | 798 | return IRQ_HANDLED; |
803 | } | 799 | } |
@@ -809,7 +805,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, | |||
809 | 805 | ||
810 | winch = kmalloc(sizeof(*winch), GFP_KERNEL); | 806 | winch = kmalloc(sizeof(*winch), GFP_KERNEL); |
811 | if (winch == NULL) { | 807 | if (winch == NULL) { |
812 | printk("register_winch_irq - kmalloc failed\n"); | 808 | printk(KERN_ERR "register_winch_irq - kmalloc failed\n"); |
813 | goto cleanup; | 809 | goto cleanup; |
814 | } | 810 | } |
815 | 811 | ||
@@ -823,7 +819,8 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, | |||
823 | if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, | 819 | if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, |
824 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, | 820 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, |
825 | "winch", winch) < 0) { | 821 | "winch", winch) < 0) { |
826 | printk("register_winch_irq - failed to register IRQ\n"); | 822 | printk(KERN_ERR "register_winch_irq - failed to register " |
823 | "IRQ\n"); | ||
827 | goto out_free; | 824 | goto out_free; |
828 | } | 825 | } |
829 | 826 | ||
@@ -849,13 +846,13 @@ static void unregister_winch(struct tty_struct *tty) | |||
849 | 846 | ||
850 | spin_lock(&winch_handler_lock); | 847 | spin_lock(&winch_handler_lock); |
851 | 848 | ||
852 | list_for_each(ele, &winch_handlers){ | 849 | list_for_each(ele, &winch_handlers) { |
853 | winch = list_entry(ele, struct winch, list); | 850 | winch = list_entry(ele, struct winch, list); |
854 | if(winch->tty == tty){ | 851 | if (winch->tty == tty) { |
855 | free_winch(winch, 1); | 852 | free_winch(winch, 1); |
856 | break; | 853 | break; |
857 | } | 854 | } |
858 | } | 855 | } |
859 | spin_unlock(&winch_handler_lock); | 856 | spin_unlock(&winch_handler_lock); |
860 | } | 857 | } |
861 | 858 | ||
@@ -866,7 +863,7 @@ static void winch_cleanup(void) | |||
866 | 863 | ||
867 | spin_lock(&winch_handler_lock); | 864 | spin_lock(&winch_handler_lock); |
868 | 865 | ||
869 | list_for_each_safe(ele, next, &winch_handlers){ | 866 | list_for_each_safe(ele, next, &winch_handlers) { |
870 | winch = list_entry(ele, struct winch, list); | 867 | winch = list_entry(ele, struct winch, list); |
871 | free_winch(winch, 1); | 868 | free_winch(winch, 1); |
872 | } | 869 | } |
@@ -881,13 +878,13 @@ char *add_xterm_umid(char *base) | |||
881 | int len; | 878 | int len; |
882 | 879 | ||
883 | umid = get_umid(); | 880 | umid = get_umid(); |
884 | if(*umid == '\0') | 881 | if (*umid == '\0') |
885 | return base; | 882 | return base; |
886 | 883 | ||
887 | len = strlen(base) + strlen(" ()") + strlen(umid) + 1; | 884 | len = strlen(base) + strlen(" ()") + strlen(umid) + 1; |
888 | title = kmalloc(len, GFP_KERNEL); | 885 | title = kmalloc(len, GFP_KERNEL); |
889 | if(title == NULL){ | 886 | if (title == NULL) { |
890 | printk("Failed to allocate buffer for xterm title\n"); | 887 | printk(KERN_ERR "Failed to allocate buffer for xterm title\n"); |
891 | return base; | 888 | return base; |
892 | } | 889 | } |
893 | 890 | ||
diff --git a/arch/um/drivers/mcast.h b/arch/um/drivers/mcast.h index bc56af9d3e53..6fa282e896be 100644 --- a/arch/um/drivers/mcast.h +++ b/arch/um/drivers/mcast.h | |||
@@ -1,8 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #ifndef __DRIVERS_MCAST_H | ||
7 | #define __DRIVERS_MCAST_H | ||
8 | |||
6 | #include "net_user.h" | 9 | #include "net_user.h" |
7 | 10 | ||
8 | struct mcast_data { | 11 | struct mcast_data { |
@@ -18,13 +21,4 @@ extern const struct net_user_info mcast_user_info; | |||
18 | extern int mcast_user_write(int fd, void *buf, int len, | 21 | extern int mcast_user_write(int fd, void *buf, int len, |
19 | struct mcast_data *pri); | 22 | struct mcast_data *pri); |
20 | 23 | ||
21 | /* | 24 | #endif |
22 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
23 | * Emacs will notice this stuff at the end of the file and automatically | ||
24 | * adjust the settings for this buffer only. This must remain at the end | ||
25 | * of the file. | ||
26 | * --------------------------------------------------------------------------- | ||
27 | * Local variables: | ||
28 | * c-file-style: "linux" | ||
29 | * End: | ||
30 | */ | ||
diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c index e6b8e0dd72a8..822092f149be 100644 --- a/arch/um/drivers/mcast_kern.c +++ b/arch/um/drivers/mcast_kern.c | |||
@@ -1,24 +1,20 @@ | |||
1 | /* | 1 | /* |
2 | * user-mode-linux networking multicast transport | 2 | * user-mode-linux networking multicast transport |
3 | * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org> | 3 | * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org> |
4 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
4 | * | 5 | * |
5 | * based on the existing uml-networking code, which is | 6 | * based on the existing uml-networking code, which is |
6 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and | 7 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and |
7 | * James Leu (jleu@mindspring.net). | 8 | * James Leu (jleu@mindspring.net). |
8 | * Copyright (C) 2001 by various other people who didn't put their name here. | 9 | * Copyright (C) 2001 by various other people who didn't put their name here. |
9 | * | 10 | * |
10 | * Licensed under the GPL. | 11 | * Licensed under the GPL. |
11 | */ | 12 | */ |
12 | 13 | ||
13 | #include "linux/kernel.h" | ||
14 | #include "linux/init.h" | 14 | #include "linux/init.h" |
15 | #include "linux/netdevice.h" | 15 | #include <linux/netdevice.h> |
16 | #include "linux/etherdevice.h" | ||
17 | #include "linux/in.h" | ||
18 | #include "linux/inet.h" | ||
19 | #include "net_kern.h" | ||
20 | #include "net_user.h" | ||
21 | #include "mcast.h" | 16 | #include "mcast.h" |
17 | #include "net_kern.h" | ||
22 | 18 | ||
23 | struct mcast_init { | 19 | struct mcast_init { |
24 | char *addr; | 20 | char *addr; |
@@ -39,26 +35,20 @@ static void mcast_init(struct net_device *dev, void *data) | |||
39 | dpri->ttl = init->ttl; | 35 | dpri->ttl = init->ttl; |
40 | dpri->dev = dev; | 36 | dpri->dev = dev; |
41 | 37 | ||
42 | printk("mcast backend "); | 38 | printk("mcast backend multicast address: %s:%u, TTL:%u\n", |
43 | printk("multicast address: %s:%u, TTL:%u ", | ||
44 | dpri->addr, dpri->port, dpri->ttl); | 39 | dpri->addr, dpri->port, dpri->ttl); |
45 | |||
46 | printk("\n"); | ||
47 | } | 40 | } |
48 | 41 | ||
49 | static int mcast_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) | 42 | static int mcast_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) |
50 | { | 43 | { |
51 | *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); | 44 | return net_recvfrom(fd, skb_mac_header(skb), |
52 | if(*skb == NULL) return(-ENOMEM); | 45 | skb->dev->mtu + ETH_HEADER_OTHER); |
53 | return(net_recvfrom(fd, skb_mac_header(*skb), | ||
54 | (*skb)->dev->mtu + ETH_HEADER_OTHER)); | ||
55 | } | 46 | } |
56 | 47 | ||
57 | static int mcast_write(int fd, struct sk_buff **skb, | 48 | static int mcast_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) |
58 | struct uml_net_private *lp) | ||
59 | { | 49 | { |
60 | return mcast_user_write(fd, (*skb)->data, (*skb)->len, | 50 | return mcast_user_write(fd, skb->data, skb->len, |
61 | (struct mcast_data *) &lp->user); | 51 | (struct mcast_data *) &lp->user); |
62 | } | 52 | } |
63 | 53 | ||
64 | static const struct net_kern_info mcast_kern_info = { | 54 | static const struct net_kern_info mcast_kern_info = { |
@@ -81,34 +71,34 @@ int mcast_setup(char *str, char **mac_out, void *data) | |||
81 | 71 | ||
82 | remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str, | 72 | remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str, |
83 | NULL); | 73 | NULL); |
84 | if(remain != NULL){ | 74 | if (remain != NULL) { |
85 | printk(KERN_ERR "mcast_setup - Extra garbage on " | 75 | printk(KERN_ERR "mcast_setup - Extra garbage on " |
86 | "specification : '%s'\n", remain); | 76 | "specification : '%s'\n", remain); |
87 | return(0); | 77 | return 0; |
88 | } | 78 | } |
89 | 79 | ||
90 | if(port_str != NULL){ | 80 | if (port_str != NULL) { |
91 | init->port = simple_strtoul(port_str, &last, 10); | 81 | init->port = simple_strtoul(port_str, &last, 10); |
92 | if((*last != '\0') || (last == port_str)){ | 82 | if ((*last != '\0') || (last == port_str)) { |
93 | printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", | 83 | printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", |
94 | port_str); | 84 | port_str); |
95 | return(0); | 85 | return 0; |
96 | } | 86 | } |
97 | } | 87 | } |
98 | 88 | ||
99 | if(ttl_str != NULL){ | 89 | if (ttl_str != NULL) { |
100 | init->ttl = simple_strtoul(ttl_str, &last, 10); | 90 | init->ttl = simple_strtoul(ttl_str, &last, 10); |
101 | if((*last != '\0') || (last == ttl_str)){ | 91 | if ((*last != '\0') || (last == ttl_str)) { |
102 | printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n", | 92 | printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n", |
103 | ttl_str); | 93 | ttl_str); |
104 | return(0); | 94 | return 0; |
105 | } | 95 | } |
106 | } | 96 | } |
107 | 97 | ||
108 | printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr, | 98 | printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr, |
109 | init->port, init->ttl); | 99 | init->port, init->ttl); |
110 | 100 | ||
111 | return(1); | 101 | return 1; |
112 | } | 102 | } |
113 | 103 | ||
114 | static struct transport mcast_transport = { | 104 | static struct transport mcast_transport = { |
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c index 236a3dfc297d..5f647d7a7292 100644 --- a/arch/um/drivers/mcast_user.c +++ b/arch/um/drivers/mcast_user.c | |||
@@ -1,9 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * user-mode-linux networking multicast transport | 2 | * user-mode-linux networking multicast transport |
3 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
3 | * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org> | 4 | * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org> |
4 | * | 5 | * |
5 | * based on the existing uml-networking code, which is | 6 | * based on the existing uml-networking code, which is |
6 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and | 7 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and |
7 | * James Leu (jleu@mindspring.net). | 8 | * James Leu (jleu@mindspring.net). |
8 | * Copyright (C) 2001 by various other people who didn't put their name here. | 9 | * Copyright (C) 2001 by various other people who didn't put their name here. |
9 | * | 10 | * |
@@ -11,28 +12,22 @@ | |||
11 | * | 12 | * |
12 | */ | 13 | */ |
13 | 14 | ||
14 | #include <errno.h> | ||
15 | #include <unistd.h> | 15 | #include <unistd.h> |
16 | #include <sys/socket.h> | 16 | #include <errno.h> |
17 | #include <sys/un.h> | ||
18 | #include <sys/time.h> | ||
19 | #include <netinet/in.h> | 17 | #include <netinet/in.h> |
20 | #include "net_user.h" | ||
21 | #include "mcast.h" | 18 | #include "mcast.h" |
22 | #include "kern_util.h" | 19 | #include "net_user.h" |
23 | #include "user.h" | ||
24 | #include "os.h" | ||
25 | #include "um_malloc.h" | 20 | #include "um_malloc.h" |
26 | 21 | #include "user.h" | |
27 | #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) | ||
28 | 22 | ||
29 | static struct sockaddr_in *new_addr(char *addr, unsigned short port) | 23 | static struct sockaddr_in *new_addr(char *addr, unsigned short port) |
30 | { | 24 | { |
31 | struct sockaddr_in *sin; | 25 | struct sockaddr_in *sin; |
32 | 26 | ||
33 | sin = kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL); | 27 | sin = kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL); |
34 | if(sin == NULL){ | 28 | if (sin == NULL) { |
35 | printk("new_addr: allocation of sockaddr_in failed\n"); | 29 | printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in " |
30 | "failed\n"); | ||
36 | return NULL; | 31 | return NULL; |
37 | } | 32 | } |
38 | sin->sin_family = AF_INET; | 33 | sin->sin_family = AF_INET; |
@@ -71,17 +66,17 @@ static int mcast_open(void *data) | |||
71 | 66 | ||
72 | fd = socket(AF_INET, SOCK_DGRAM, 0); | 67 | fd = socket(AF_INET, SOCK_DGRAM, 0); |
73 | 68 | ||
74 | if (fd < 0){ | 69 | if (fd < 0) { |
75 | err = -errno; | 70 | err = -errno; |
76 | printk("mcast_open : data socket failed, errno = %d\n", | 71 | printk(UM_KERN_ERR "mcast_open : data socket failed, " |
77 | errno); | 72 | "errno = %d\n", errno); |
78 | goto out; | 73 | goto out; |
79 | } | 74 | } |
80 | 75 | ||
81 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { | 76 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { |
82 | err = -errno; | 77 | err = -errno; |
83 | printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", | 78 | printk(UM_KERN_ERR "mcast_open: SO_REUSEADDR failed, " |
84 | errno); | 79 | "errno = %d\n", errno); |
85 | goto out_close; | 80 | goto out_close; |
86 | } | 81 | } |
87 | 82 | ||
@@ -89,45 +84,46 @@ static int mcast_open(void *data) | |||
89 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, | 84 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, |
90 | sizeof(pri->ttl)) < 0) { | 85 | sizeof(pri->ttl)) < 0) { |
91 | err = -errno; | 86 | err = -errno; |
92 | printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", | 87 | printk(UM_KERN_ERR "mcast_open: IP_MULTICAST_TTL failed, " |
93 | errno); | 88 | "error = %d\n", errno); |
94 | goto out_close; | 89 | goto out_close; |
95 | } | 90 | } |
96 | 91 | ||
97 | /* set LOOP, so data does get fed back to local sockets */ | 92 | /* set LOOP, so data does get fed back to local sockets */ |
98 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { | 93 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { |
99 | err = -errno; | 94 | err = -errno; |
100 | printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", | 95 | printk(UM_KERN_ERR "mcast_open: IP_MULTICAST_LOOP failed, " |
101 | errno); | 96 | "error = %d\n", errno); |
102 | goto out_close; | 97 | goto out_close; |
103 | } | 98 | } |
104 | 99 | ||
105 | /* bind socket to mcast address */ | 100 | /* bind socket to mcast address */ |
106 | if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { | 101 | if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { |
107 | err = -errno; | 102 | err = -errno; |
108 | printk("mcast_open : data bind failed, errno = %d\n", errno); | 103 | printk(UM_KERN_ERR "mcast_open : data bind failed, " |
104 | "errno = %d\n", errno); | ||
109 | goto out_close; | 105 | goto out_close; |
110 | } | 106 | } |
111 | 107 | ||
112 | /* subscribe to the multicast group */ | 108 | /* subscribe to the multicast group */ |
113 | mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; | 109 | mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; |
114 | mreq.imr_interface.s_addr = 0; | 110 | mreq.imr_interface.s_addr = 0; |
115 | if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, | 111 | if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, |
116 | &mreq, sizeof(mreq)) < 0) { | 112 | &mreq, sizeof(mreq)) < 0) { |
117 | err = -errno; | 113 | err = -errno; |
118 | printk("mcast_open: IP_ADD_MEMBERSHIP failed, error = %d\n", | 114 | printk(UM_KERN_ERR "mcast_open: IP_ADD_MEMBERSHIP failed, " |
119 | errno); | 115 | "error = %d\n", errno); |
120 | printk("There appears not to be a multicast-capable network " | 116 | printk(UM_KERN_ERR "There appears not to be a multicast-" |
121 | "interface on the host.\n"); | 117 | "capable network interface on the host.\n"); |
122 | printk("eth0 should be configured in order to use the " | 118 | printk(UM_KERN_ERR "eth0 should be configured in order to use " |
123 | "multicast transport.\n"); | 119 | "the multicast transport.\n"); |
124 | goto out_close; | 120 | goto out_close; |
125 | } | 121 | } |
126 | 122 | ||
127 | return fd; | 123 | return fd; |
128 | 124 | ||
129 | out_close: | 125 | out_close: |
130 | os_close_file(fd); | 126 | close(fd); |
131 | out: | 127 | out: |
132 | return err; | 128 | return err; |
133 | } | 129 | } |
@@ -142,11 +138,11 @@ static void mcast_close(int fd, void *data) | |||
142 | mreq.imr_interface.s_addr = 0; | 138 | mreq.imr_interface.s_addr = 0; |
143 | if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP, | 139 | if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP, |
144 | &mreq, sizeof(mreq)) < 0) { | 140 | &mreq, sizeof(mreq)) < 0) { |
145 | printk("mcast_open: IP_DROP_MEMBERSHIP failed, error = %d\n", | 141 | printk(UM_KERN_ERR "mcast_open: IP_DROP_MEMBERSHIP failed, " |
146 | errno); | 142 | "error = %d\n", errno); |
147 | } | 143 | } |
148 | 144 | ||
149 | os_close_file(fd); | 145 | close(fd); |
150 | } | 146 | } |
151 | 147 | ||
152 | int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri) | 148 | int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri) |
@@ -156,18 +152,13 @@ int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri) | |||
156 | return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); | 152 | return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); |
157 | } | 153 | } |
158 | 154 | ||
159 | static int mcast_set_mtu(int mtu, void *data) | ||
160 | { | ||
161 | return mtu; | ||
162 | } | ||
163 | |||
164 | const struct net_user_info mcast_user_info = { | 155 | const struct net_user_info mcast_user_info = { |
165 | .init = mcast_user_init, | 156 | .init = mcast_user_init, |
166 | .open = mcast_open, | 157 | .open = mcast_open, |
167 | .close = mcast_close, | 158 | .close = mcast_close, |
168 | .remove = mcast_remove, | 159 | .remove = mcast_remove, |
169 | .set_mtu = mcast_set_mtu, | ||
170 | .add_address = NULL, | 160 | .add_address = NULL, |
171 | .delete_address = NULL, | 161 | .delete_address = NULL, |
172 | .max_packet = MAX_PACKET - ETH_HEADER_OTHER | 162 | .mtu = ETH_MAX_PACKET, |
163 | .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, | ||
173 | }; | 164 | }; |
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index d87090507401..0f3c7d14a6e3 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c | |||
@@ -1,44 +1,35 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) | 2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) |
3 | * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com) | 3 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
4 | * Licensed under the GPL | 4 | * Licensed under the GPL |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include "linux/kernel.h" | 7 | #include "linux/console.h" |
8 | #include "linux/slab.h" | ||
9 | #include "linux/init.h" | ||
10 | #include "linux/notifier.h" | ||
11 | #include "linux/reboot.h" | ||
12 | #include "linux/utsname.h" | ||
13 | #include "linux/ctype.h" | 8 | #include "linux/ctype.h" |
14 | #include "linux/interrupt.h" | 9 | #include "linux/interrupt.h" |
15 | #include "linux/sysrq.h" | 10 | #include "linux/list.h" |
16 | #include "linux/workqueue.h" | 11 | #include "linux/mm.h" |
17 | #include "linux/module.h" | 12 | #include "linux/module.h" |
18 | #include "linux/file.h" | 13 | #include "linux/notifier.h" |
19 | #include "linux/fs.h" | 14 | #include "linux/reboot.h" |
20 | #include "linux/namei.h" | ||
21 | #include "linux/proc_fs.h" | 15 | #include "linux/proc_fs.h" |
16 | #include "linux/slab.h" | ||
22 | #include "linux/syscalls.h" | 17 | #include "linux/syscalls.h" |
23 | #include "linux/list.h" | 18 | #include "linux/utsname.h" |
24 | #include "linux/mm.h" | 19 | #include "linux/workqueue.h" |
25 | #include "linux/console.h" | ||
26 | #include "asm/irq.h" | ||
27 | #include "asm/uaccess.h" | 20 | #include "asm/uaccess.h" |
21 | #include "init.h" | ||
22 | #include "irq_kern.h" | ||
23 | #include "irq_user.h" | ||
28 | #include "kern_util.h" | 24 | #include "kern_util.h" |
29 | #include "kern.h" | ||
30 | #include "mconsole.h" | 25 | #include "mconsole.h" |
31 | #include "mconsole_kern.h" | 26 | #include "mconsole_kern.h" |
32 | #include "irq_user.h" | ||
33 | #include "init.h" | ||
34 | #include "os.h" | 27 | #include "os.h" |
35 | #include "irq_kern.h" | ||
36 | #include "choose-mode.h" | ||
37 | 28 | ||
38 | static int do_unlink_socket(struct notifier_block *notifier, | 29 | static int do_unlink_socket(struct notifier_block *notifier, |
39 | unsigned long what, void *data) | 30 | unsigned long what, void *data) |
40 | { | 31 | { |
41 | return(mconsole_unlink_socket()); | 32 | return mconsole_unlink_socket(); |
42 | } | 33 | } |
43 | 34 | ||
44 | 35 | ||
@@ -59,10 +50,9 @@ static void mc_work_proc(struct work_struct *unused) | |||
59 | struct mconsole_entry *req; | 50 | struct mconsole_entry *req; |
60 | unsigned long flags; | 51 | unsigned long flags; |
61 | 52 | ||
62 | while(!list_empty(&mc_requests)){ | 53 | while (!list_empty(&mc_requests)) { |
63 | local_irq_save(flags); | 54 | local_irq_save(flags); |
64 | req = list_entry(mc_requests.next, struct mconsole_entry, | 55 | req = list_entry(mc_requests.next, struct mconsole_entry, list); |
65 | list); | ||
66 | list_del(&req->list); | 56 | list_del(&req->list); |
67 | local_irq_restore(flags); | 57 | local_irq_restore(flags); |
68 | req->request.cmd->handler(&req->request); | 58 | req->request.cmd->handler(&req->request); |
@@ -80,12 +70,12 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id) | |||
80 | static struct mc_request req; /* that's OK */ | 70 | static struct mc_request req; /* that's OK */ |
81 | 71 | ||
82 | fd = (long) dev_id; | 72 | fd = (long) dev_id; |
83 | while (mconsole_get_request(fd, &req)){ | 73 | while (mconsole_get_request(fd, &req)) { |
84 | if(req.cmd->context == MCONSOLE_INTR) | 74 | if (req.cmd->context == MCONSOLE_INTR) |
85 | (*req.cmd->handler)(&req); | 75 | (*req.cmd->handler)(&req); |
86 | else { | 76 | else { |
87 | new = kmalloc(sizeof(*new), GFP_NOWAIT); | 77 | new = kmalloc(sizeof(*new), GFP_NOWAIT); |
88 | if(new == NULL) | 78 | if (new == NULL) |
89 | mconsole_reply(&req, "Out of memory", 1, 0); | 79 | mconsole_reply(&req, "Out of memory", 1, 0); |
90 | else { | 80 | else { |
91 | new->request = req; | 81 | new->request = req; |
@@ -94,10 +84,10 @@ static irqreturn_t mconsole_interrupt(int irq, void *dev_id) | |||
94 | } | 84 | } |
95 | } | 85 | } |
96 | } | 86 | } |
97 | if(!list_empty(&mc_requests)) | 87 | if (!list_empty(&mc_requests)) |
98 | schedule_work(&mconsole_work); | 88 | schedule_work(&mconsole_work); |
99 | reactivate_fd(fd, MCONSOLE_IRQ); | 89 | reactivate_fd(fd, MCONSOLE_IRQ); |
100 | return(IRQ_HANDLED); | 90 | return IRQ_HANDLED; |
101 | } | 91 | } |
102 | 92 | ||
103 | void mconsole_version(struct mc_request *req) | 93 | void mconsole_version(struct mc_request *req) |
@@ -105,8 +95,8 @@ void mconsole_version(struct mc_request *req) | |||
105 | char version[256]; | 95 | char version[256]; |
106 | 96 | ||
107 | sprintf(version, "%s %s %s %s %s", utsname()->sysname, | 97 | sprintf(version, "%s %s %s %s %s", utsname()->sysname, |
108 | utsname()->nodename, utsname()->release, | 98 | utsname()->nodename, utsname()->release, utsname()->version, |
109 | utsname()->version, utsname()->machine); | 99 | utsname()->machine); |
110 | mconsole_reply(req, version, 0, 0); | 100 | mconsole_reply(req, version, 0, 0); |
111 | } | 101 | } |
112 | 102 | ||
@@ -118,7 +108,7 @@ void mconsole_log(struct mc_request *req) | |||
118 | ptr += strlen("log "); | 108 | ptr += strlen("log "); |
119 | 109 | ||
120 | len = req->len - (ptr - req->request.data); | 110 | len = req->len - (ptr - req->request.data); |
121 | printk("%.*s", len, ptr); | 111 | printk(KERN_WARNING "%.*s", len, ptr); |
122 | mconsole_reply(req, "", 0, 0); | 112 | mconsole_reply(req, "", 0, 0); |
123 | } | 113 | } |
124 | 114 | ||
@@ -137,17 +127,17 @@ void mconsole_proc(struct mc_request *req) | |||
137 | char *ptr = req->request.data, *buf; | 127 | char *ptr = req->request.data, *buf; |
138 | 128 | ||
139 | ptr += strlen("proc"); | 129 | ptr += strlen("proc"); |
140 | while(isspace(*ptr)) ptr++; | 130 | while (isspace(*ptr)) ptr++; |
141 | 131 | ||
142 | proc = get_fs_type("proc"); | 132 | proc = get_fs_type("proc"); |
143 | if(proc == NULL){ | 133 | if (proc == NULL) { |
144 | mconsole_reply(req, "procfs not registered", 1, 0); | 134 | mconsole_reply(req, "procfs not registered", 1, 0); |
145 | goto out; | 135 | goto out; |
146 | } | 136 | } |
147 | 137 | ||
148 | super = (*proc->get_sb)(proc, 0, NULL, NULL); | 138 | super = (*proc->get_sb)(proc, 0, NULL, NULL); |
149 | put_filesystem(proc); | 139 | put_filesystem(proc); |
150 | if(super == NULL){ | 140 | if (super == NULL) { |
151 | mconsole_reply(req, "Failed to get procfs superblock", 1, 0); | 141 | mconsole_reply(req, "Failed to get procfs superblock", 1, 0); |
152 | goto out; | 142 | goto out; |
153 | } | 143 | } |
@@ -162,29 +152,29 @@ void mconsole_proc(struct mc_request *req) | |||
162 | * if commenting out these two calls + the below read cycle. To | 152 | * if commenting out these two calls + the below read cycle. To |
163 | * make UML crash again, it was enough to readd either one.*/ | 153 | * make UML crash again, it was enough to readd either one.*/ |
164 | err = link_path_walk(ptr, &nd); | 154 | err = link_path_walk(ptr, &nd); |
165 | if(err){ | 155 | if (err) { |
166 | mconsole_reply(req, "Failed to look up file", 1, 0); | 156 | mconsole_reply(req, "Failed to look up file", 1, 0); |
167 | goto out_kill; | 157 | goto out_kill; |
168 | } | 158 | } |
169 | 159 | ||
170 | file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); | 160 | file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); |
171 | if(IS_ERR(file)){ | 161 | if (IS_ERR(file)) { |
172 | mconsole_reply(req, "Failed to open file", 1, 0); | 162 | mconsole_reply(req, "Failed to open file", 1, 0); |
173 | goto out_kill; | 163 | goto out_kill; |
174 | } | 164 | } |
175 | /*END*/ | 165 | /*END*/ |
176 | 166 | ||
177 | buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | 167 | buf = kmalloc(PAGE_SIZE, GFP_KERNEL); |
178 | if(buf == NULL){ | 168 | if (buf == NULL) { |
179 | mconsole_reply(req, "Failed to allocate buffer", 1, 0); | 169 | mconsole_reply(req, "Failed to allocate buffer", 1, 0); |
180 | goto out_fput; | 170 | goto out_fput; |
181 | } | 171 | } |
182 | 172 | ||
183 | if((file->f_op != NULL) && (file->f_op->read != NULL)){ | 173 | if ((file->f_op != NULL) && (file->f_op->read != NULL)) { |
184 | do { | 174 | do { |
185 | n = (*file->f_op->read)(file, buf, PAGE_SIZE - 1, | 175 | n = (*file->f_op->read)(file, buf, PAGE_SIZE - 1, |
186 | &file->f_pos); | 176 | &file->f_pos); |
187 | if(n >= 0){ | 177 | if (n >= 0) { |
188 | buf[n] = '\0'; | 178 | buf[n] = '\0'; |
189 | mconsole_reply(req, buf, 0, (n > 0)); | 179 | mconsole_reply(req, buf, 0, (n > 0)); |
190 | } | 180 | } |
@@ -193,7 +183,7 @@ void mconsole_proc(struct mc_request *req) | |||
193 | 1, 0); | 183 | 1, 0); |
194 | goto out_free; | 184 | goto out_free; |
195 | } | 185 | } |
196 | } while(n > 0); | 186 | } while (n > 0); |
197 | } | 187 | } |
198 | else mconsole_reply(req, "", 0, 0); | 188 | else mconsole_reply(req, "", 0, 0); |
199 | 189 | ||
@@ -217,18 +207,19 @@ void mconsole_proc(struct mc_request *req) | |||
217 | char *ptr = req->request.data; | 207 | char *ptr = req->request.data; |
218 | 208 | ||
219 | ptr += strlen("proc"); | 209 | ptr += strlen("proc"); |
220 | while(isspace(*ptr)) ptr++; | 210 | while (isspace(*ptr)) |
211 | ptr++; | ||
221 | snprintf(path, sizeof(path), "/proc/%s", ptr); | 212 | snprintf(path, sizeof(path), "/proc/%s", ptr); |
222 | 213 | ||
223 | fd = sys_open(path, 0, 0); | 214 | fd = sys_open(path, 0, 0); |
224 | if (fd < 0) { | 215 | if (fd < 0) { |
225 | mconsole_reply(req, "Failed to open file", 1, 0); | 216 | mconsole_reply(req, "Failed to open file", 1, 0); |
226 | printk("open %s: %d\n",path,fd); | 217 | printk(KERN_ERR "open %s: %d\n",path,fd); |
227 | goto out; | 218 | goto out; |
228 | } | 219 | } |
229 | 220 | ||
230 | buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | 221 | buf = kmalloc(PAGE_SIZE, GFP_KERNEL); |
231 | if(buf == NULL){ | 222 | if (buf == NULL) { |
232 | mconsole_reply(req, "Failed to allocate buffer", 1, 0); | 223 | mconsole_reply(req, "Failed to allocate buffer", 1, 0); |
233 | goto out_close; | 224 | goto out_close; |
234 | } | 225 | } |
@@ -239,7 +230,7 @@ void mconsole_proc(struct mc_request *req) | |||
239 | mconsole_reply(req, "Read of file failed", 1, 0); | 230 | mconsole_reply(req, "Read of file failed", 1, 0); |
240 | goto out_free; | 231 | goto out_free; |
241 | } | 232 | } |
242 | /*Begin the file content on his own line.*/ | 233 | /* Begin the file content on his own line. */ |
243 | if (first_chunk) { | 234 | if (first_chunk) { |
244 | mconsole_reply(req, "\n", 0, 1); | 235 | mconsole_reply(req, "\n", 0, 1); |
245 | first_chunk = 0; | 236 | first_chunk = 0; |
@@ -351,12 +342,12 @@ static struct mc_device *mconsole_find_dev(char *name) | |||
351 | struct list_head *ele; | 342 | struct list_head *ele; |
352 | struct mc_device *dev; | 343 | struct mc_device *dev; |
353 | 344 | ||
354 | list_for_each(ele, &mconsole_devices){ | 345 | list_for_each(ele, &mconsole_devices) { |
355 | dev = list_entry(ele, struct mc_device, list); | 346 | dev = list_entry(ele, struct mc_device, list); |
356 | if(!strncmp(name, dev->name, strlen(dev->name))) | 347 | if (!strncmp(name, dev->name, strlen(dev->name))) |
357 | return(dev); | 348 | return dev; |
358 | } | 349 | } |
359 | return(NULL); | 350 | return NULL; |
360 | } | 351 | } |
361 | 352 | ||
362 | #define UNPLUGGED_PER_PAGE \ | 353 | #define UNPLUGGED_PER_PAGE \ |
@@ -378,15 +369,15 @@ static int mem_config(char *str, char **error_out) | |||
378 | int err = -EINVAL, i, add; | 369 | int err = -EINVAL, i, add; |
379 | char *ret; | 370 | char *ret; |
380 | 371 | ||
381 | if(str[0] != '='){ | 372 | if (str[0] != '=') { |
382 | *error_out = "Expected '=' after 'mem'"; | 373 | *error_out = "Expected '=' after 'mem'"; |
383 | goto out; | 374 | goto out; |
384 | } | 375 | } |
385 | 376 | ||
386 | str++; | 377 | str++; |
387 | if(str[0] == '-') | 378 | if (str[0] == '-') |
388 | add = 0; | 379 | add = 0; |
389 | else if(str[0] == '+'){ | 380 | else if (str[0] == '+') { |
390 | add = 1; | 381 | add = 1; |
391 | } | 382 | } |
392 | else { | 383 | else { |
@@ -396,7 +387,7 @@ static int mem_config(char *str, char **error_out) | |||
396 | 387 | ||
397 | str++; | 388 | str++; |
398 | diff = memparse(str, &ret); | 389 | diff = memparse(str, &ret); |
399 | if(*ret != '\0'){ | 390 | if (*ret != '\0') { |
400 | *error_out = "Failed to parse memory increment"; | 391 | *error_out = "Failed to parse memory increment"; |
401 | goto out; | 392 | goto out; |
402 | } | 393 | } |
@@ -404,17 +395,17 @@ static int mem_config(char *str, char **error_out) | |||
404 | diff /= PAGE_SIZE; | 395 | diff /= PAGE_SIZE; |
405 | 396 | ||
406 | down(&plug_mem_mutex); | 397 | down(&plug_mem_mutex); |
407 | for(i = 0; i < diff; i++){ | 398 | for (i = 0; i < diff; i++) { |
408 | struct unplugged_pages *unplugged; | 399 | struct unplugged_pages *unplugged; |
409 | void *addr; | 400 | void *addr; |
410 | 401 | ||
411 | if(add){ | 402 | if (add) { |
412 | if(list_empty(&unplugged_pages)) | 403 | if (list_empty(&unplugged_pages)) |
413 | break; | 404 | break; |
414 | 405 | ||
415 | unplugged = list_entry(unplugged_pages.next, | 406 | unplugged = list_entry(unplugged_pages.next, |
416 | struct unplugged_pages, list); | 407 | struct unplugged_pages, list); |
417 | if(unplug_index > 0) | 408 | if (unplug_index > 0) |
418 | addr = unplugged->pages[--unplug_index]; | 409 | addr = unplugged->pages[--unplug_index]; |
419 | else { | 410 | else { |
420 | list_del(&unplugged->list); | 411 | list_del(&unplugged->list); |
@@ -429,11 +420,11 @@ static int mem_config(char *str, char **error_out) | |||
429 | struct page *page; | 420 | struct page *page; |
430 | 421 | ||
431 | page = alloc_page(GFP_ATOMIC); | 422 | page = alloc_page(GFP_ATOMIC); |
432 | if(page == NULL) | 423 | if (page == NULL) |
433 | break; | 424 | break; |
434 | 425 | ||
435 | unplugged = page_address(page); | 426 | unplugged = page_address(page); |
436 | if(unplug_index == UNPLUGGED_PER_PAGE){ | 427 | if (unplug_index == UNPLUGGED_PER_PAGE) { |
437 | list_add(&unplugged->list, &unplugged_pages); | 428 | list_add(&unplugged->list, &unplugged_pages); |
438 | unplug_index = 0; | 429 | unplug_index = 0; |
439 | } | 430 | } |
@@ -445,9 +436,9 @@ static int mem_config(char *str, char **error_out) | |||
445 | struct unplugged_pages, | 436 | struct unplugged_pages, |
446 | list); | 437 | list); |
447 | err = os_drop_memory(addr, PAGE_SIZE); | 438 | err = os_drop_memory(addr, PAGE_SIZE); |
448 | if(err){ | 439 | if (err) { |
449 | printk("Failed to release memory - " | 440 | printk(KERN_ERR "Failed to release " |
450 | "errno = %d\n", err); | 441 | "memory - errno = %d\n", err); |
451 | *error_out = "Failed to release memory"; | 442 | *error_out = "Failed to release memory"; |
452 | goto out_unlock; | 443 | goto out_unlock; |
453 | } | 444 | } |
@@ -501,10 +492,10 @@ static struct mc_device mem_mc = { | |||
501 | 492 | ||
502 | static int __init mem_mc_init(void) | 493 | static int __init mem_mc_init(void) |
503 | { | 494 | { |
504 | if(can_drop_memory()) | 495 | if (can_drop_memory()) |
505 | mconsole_register_dev(&mem_mc); | 496 | mconsole_register_dev(&mem_mc); |
506 | else printk("Can't release memory to the host - memory hotplug won't " | 497 | else printk(KERN_ERR "Can't release memory to the host - memory " |
507 | "be supported\n"); | 498 | "hotplug won't be supported\n"); |
508 | return 0; | 499 | return 0; |
509 | } | 500 | } |
510 | 501 | ||
@@ -519,7 +510,7 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int, | |||
519 | char default_buf[CONFIG_BUF_SIZE], *error, *buf; | 510 | char default_buf[CONFIG_BUF_SIZE], *error, *buf; |
520 | int n, size; | 511 | int n, size; |
521 | 512 | ||
522 | if(get_config == NULL){ | 513 | if (get_config == NULL) { |
523 | mconsole_reply(req, "No get_config routine defined", 1, 0); | 514 | mconsole_reply(req, "No get_config routine defined", 1, 0); |
524 | return; | 515 | return; |
525 | } | 516 | } |
@@ -528,30 +519,30 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int, | |||
528 | size = ARRAY_SIZE(default_buf); | 519 | size = ARRAY_SIZE(default_buf); |
529 | buf = default_buf; | 520 | buf = default_buf; |
530 | 521 | ||
531 | while(1){ | 522 | while (1) { |
532 | n = (*get_config)(name, buf, size, &error); | 523 | n = (*get_config)(name, buf, size, &error); |
533 | if(error != NULL){ | 524 | if (error != NULL) { |
534 | mconsole_reply(req, error, 1, 0); | 525 | mconsole_reply(req, error, 1, 0); |
535 | goto out; | 526 | goto out; |
536 | } | 527 | } |
537 | 528 | ||
538 | if(n <= size){ | 529 | if (n <= size) { |
539 | mconsole_reply(req, buf, 0, 0); | 530 | mconsole_reply(req, buf, 0, 0); |
540 | goto out; | 531 | goto out; |
541 | } | 532 | } |
542 | 533 | ||
543 | if(buf != default_buf) | 534 | if (buf != default_buf) |
544 | kfree(buf); | 535 | kfree(buf); |
545 | 536 | ||
546 | size = n; | 537 | size = n; |
547 | buf = kmalloc(size, GFP_KERNEL); | 538 | buf = kmalloc(size, GFP_KERNEL); |
548 | if(buf == NULL){ | 539 | if (buf == NULL) { |
549 | mconsole_reply(req, "Failed to allocate buffer", 1, 0); | 540 | mconsole_reply(req, "Failed to allocate buffer", 1, 0); |
550 | return; | 541 | return; |
551 | } | 542 | } |
552 | } | 543 | } |
553 | out: | 544 | out: |
554 | if(buf != default_buf) | 545 | if (buf != default_buf) |
555 | kfree(buf); | 546 | kfree(buf); |
556 | } | 547 | } |
557 | 548 | ||
@@ -562,19 +553,20 @@ void mconsole_config(struct mc_request *req) | |||
562 | int err; | 553 | int err; |
563 | 554 | ||
564 | ptr += strlen("config"); | 555 | ptr += strlen("config"); |
565 | while(isspace(*ptr)) ptr++; | 556 | while (isspace(*ptr)) |
557 | ptr++; | ||
566 | dev = mconsole_find_dev(ptr); | 558 | dev = mconsole_find_dev(ptr); |
567 | if(dev == NULL){ | 559 | if (dev == NULL) { |
568 | mconsole_reply(req, "Bad configuration option", 1, 0); | 560 | mconsole_reply(req, "Bad configuration option", 1, 0); |
569 | return; | 561 | return; |
570 | } | 562 | } |
571 | 563 | ||
572 | name = &ptr[strlen(dev->name)]; | 564 | name = &ptr[strlen(dev->name)]; |
573 | ptr = name; | 565 | ptr = name; |
574 | while((*ptr != '=') && (*ptr != '\0')) | 566 | while ((*ptr != '=') && (*ptr != '\0')) |
575 | ptr++; | 567 | ptr++; |
576 | 568 | ||
577 | if(*ptr == '='){ | 569 | if (*ptr == '=') { |
578 | err = (*dev->config)(name, &error_string); | 570 | err = (*dev->config)(name, &error_string); |
579 | mconsole_reply(req, error_string, err, 0); | 571 | mconsole_reply(req, error_string, err, 0); |
580 | } | 572 | } |
@@ -589,9 +581,9 @@ void mconsole_remove(struct mc_request *req) | |||
589 | int err, start, end, n; | 581 | int err, start, end, n; |
590 | 582 | ||
591 | ptr += strlen("remove"); | 583 | ptr += strlen("remove"); |
592 | while(isspace(*ptr)) ptr++; | 584 | while (isspace(*ptr)) ptr++; |
593 | dev = mconsole_find_dev(ptr); | 585 | dev = mconsole_find_dev(ptr); |
594 | if(dev == NULL){ | 586 | if (dev == NULL) { |
595 | mconsole_reply(req, "Bad remove option", 1, 0); | 587 | mconsole_reply(req, "Bad remove option", 1, 0); |
596 | return; | 588 | return; |
597 | } | 589 | } |
@@ -600,11 +592,11 @@ void mconsole_remove(struct mc_request *req) | |||
600 | 592 | ||
601 | err = 1; | 593 | err = 1; |
602 | n = (*dev->id)(&ptr, &start, &end); | 594 | n = (*dev->id)(&ptr, &start, &end); |
603 | if(n < 0){ | 595 | if (n < 0) { |
604 | err_msg = "Couldn't parse device number"; | 596 | err_msg = "Couldn't parse device number"; |
605 | goto out; | 597 | goto out; |
606 | } | 598 | } |
607 | else if((n < start) || (n > end)){ | 599 | else if ((n < start) || (n > end)) { |
608 | sprintf(error, "Invalid device number - must be between " | 600 | sprintf(error, "Invalid device number - must be between " |
609 | "%d and %d", start, end); | 601 | "%d and %d", start, end); |
610 | err_msg = error; | 602 | err_msg = error; |
@@ -613,16 +605,16 @@ void mconsole_remove(struct mc_request *req) | |||
613 | 605 | ||
614 | err_msg = NULL; | 606 | err_msg = NULL; |
615 | err = (*dev->remove)(n, &err_msg); | 607 | err = (*dev->remove)(n, &err_msg); |
616 | switch(err){ | 608 | switch(err) { |
617 | case 0: | 609 | case 0: |
618 | err_msg = ""; | 610 | err_msg = ""; |
619 | break; | 611 | break; |
620 | case -ENODEV: | 612 | case -ENODEV: |
621 | if(err_msg == NULL) | 613 | if (err_msg == NULL) |
622 | err_msg = "Device doesn't exist"; | 614 | err_msg = "Device doesn't exist"; |
623 | break; | 615 | break; |
624 | case -EBUSY: | 616 | case -EBUSY: |
625 | if(err_msg == NULL) | 617 | if (err_msg == NULL) |
626 | err_msg = "Device is currently open"; | 618 | err_msg = "Device is currently open"; |
627 | break; | 619 | break; |
628 | default: | 620 | default: |
@@ -640,35 +632,28 @@ struct mconsole_output { | |||
640 | static DEFINE_SPINLOCK(client_lock); | 632 | static DEFINE_SPINLOCK(client_lock); |
641 | static LIST_HEAD(clients); | 633 | static LIST_HEAD(clients); |
642 | static char console_buf[MCONSOLE_MAX_DATA]; | 634 | static char console_buf[MCONSOLE_MAX_DATA]; |
643 | static int console_index = 0; | ||
644 | 635 | ||
645 | static void console_write(struct console *console, const char *string, | 636 | static void console_write(struct console *console, const char *string, |
646 | unsigned len) | 637 | unsigned int len) |
647 | { | 638 | { |
648 | struct list_head *ele; | 639 | struct list_head *ele; |
649 | int n; | 640 | int n; |
650 | 641 | ||
651 | if(list_empty(&clients)) | 642 | if (list_empty(&clients)) |
652 | return; | 643 | return; |
653 | 644 | ||
654 | while(1){ | 645 | while (len > 0) { |
655 | n = min((size_t) len, ARRAY_SIZE(console_buf) - console_index); | 646 | n = min((size_t) len, ARRAY_SIZE(console_buf)); |
656 | strncpy(&console_buf[console_index], string, n); | 647 | strncpy(console_buf, string, n); |
657 | console_index += n; | ||
658 | string += n; | 648 | string += n; |
659 | len -= n; | 649 | len -= n; |
660 | if(len == 0) | ||
661 | return; | ||
662 | 650 | ||
663 | list_for_each(ele, &clients){ | 651 | list_for_each(ele, &clients) { |
664 | struct mconsole_output *entry; | 652 | struct mconsole_output *entry; |
665 | 653 | ||
666 | entry = list_entry(ele, struct mconsole_output, list); | 654 | entry = list_entry(ele, struct mconsole_output, list); |
667 | mconsole_reply_len(entry->req, console_buf, | 655 | mconsole_reply_len(entry->req, console_buf, n, 0, 1); |
668 | console_index, 0, 1); | ||
669 | } | 656 | } |
670 | |||
671 | console_index = 0; | ||
672 | } | 657 | } |
673 | } | 658 | } |
674 | 659 | ||
@@ -698,8 +683,7 @@ static void with_console(struct mc_request *req, void (*proc)(void *), | |||
698 | 683 | ||
699 | (*proc)(arg); | 684 | (*proc)(arg); |
700 | 685 | ||
701 | mconsole_reply_len(req, console_buf, console_index, 0, 0); | 686 | mconsole_reply_len(req, "", 0, 0, 0); |
702 | console_index = 0; | ||
703 | 687 | ||
704 | spin_lock_irqsave(&client_lock, flags); | 688 | spin_lock_irqsave(&client_lock, flags); |
705 | list_del(&entry.list); | 689 | list_del(&entry.list); |
@@ -707,6 +691,9 @@ static void with_console(struct mc_request *req, void (*proc)(void *), | |||
707 | } | 691 | } |
708 | 692 | ||
709 | #ifdef CONFIG_MAGIC_SYSRQ | 693 | #ifdef CONFIG_MAGIC_SYSRQ |
694 | |||
695 | #include <linux/sysrq.h> | ||
696 | |||
710 | static void sysrq_proc(void *arg) | 697 | static void sysrq_proc(void *arg) |
711 | { | 698 | { |
712 | char *op = arg; | 699 | char *op = arg; |
@@ -718,12 +705,13 @@ void mconsole_sysrq(struct mc_request *req) | |||
718 | char *ptr = req->request.data; | 705 | char *ptr = req->request.data; |
719 | 706 | ||
720 | ptr += strlen("sysrq"); | 707 | ptr += strlen("sysrq"); |
721 | while(isspace(*ptr)) ptr++; | 708 | while (isspace(*ptr)) ptr++; |
722 | 709 | ||
723 | /* With 'b', the system will shut down without a chance to reply, | 710 | /* |
711 | * With 'b', the system will shut down without a chance to reply, | ||
724 | * so in this case, we reply first. | 712 | * so in this case, we reply first. |
725 | */ | 713 | */ |
726 | if(*ptr == 'b') | 714 | if (*ptr == 'b') |
727 | mconsole_reply(req, "", 0, 0); | 715 | mconsole_reply(req, "", 0, 0); |
728 | 716 | ||
729 | with_console(req, sysrq_proc, ptr); | 717 | with_console(req, sysrq_proc, ptr); |
@@ -735,8 +723,6 @@ void mconsole_sysrq(struct mc_request *req) | |||
735 | } | 723 | } |
736 | #endif | 724 | #endif |
737 | 725 | ||
738 | #ifdef CONFIG_MODE_SKAS | ||
739 | |||
740 | static void stack_proc(void *arg) | 726 | static void stack_proc(void *arg) |
741 | { | 727 | { |
742 | struct task_struct *from = current, *to = arg; | 728 | struct task_struct *from = current, *to = arg; |
@@ -745,29 +731,34 @@ static void stack_proc(void *arg) | |||
745 | switch_to(from, to, from); | 731 | switch_to(from, to, from); |
746 | } | 732 | } |
747 | 733 | ||
748 | /* Mconsole stack trace | 734 | /* |
735 | * Mconsole stack trace | ||
749 | * Added by Allan Graves, Jeff Dike | 736 | * Added by Allan Graves, Jeff Dike |
750 | * Dumps a stacks registers to the linux console. | 737 | * Dumps a stacks registers to the linux console. |
751 | * Usage stack <pid>. | 738 | * Usage stack <pid>. |
752 | */ | 739 | */ |
753 | static void do_stack_trace(struct mc_request *req) | 740 | void mconsole_stack(struct mc_request *req) |
754 | { | 741 | { |
755 | char *ptr = req->request.data; | 742 | char *ptr = req->request.data; |
756 | int pid_requested= -1; | 743 | int pid_requested= -1; |
757 | struct task_struct *from = NULL; | 744 | struct task_struct *from = NULL; |
758 | struct task_struct *to = NULL; | 745 | struct task_struct *to = NULL; |
759 | 746 | ||
760 | /* Would be nice: | 747 | /* |
748 | * Would be nice: | ||
761 | * 1) Send showregs output to mconsole. | 749 | * 1) Send showregs output to mconsole. |
762 | * 2) Add a way to stack dump all pids. | 750 | * 2) Add a way to stack dump all pids. |
763 | */ | 751 | */ |
764 | 752 | ||
765 | ptr += strlen("stack"); | 753 | ptr += strlen("stack"); |
766 | while(isspace(*ptr)) ptr++; | 754 | while (isspace(*ptr)) |
755 | ptr++; | ||
767 | 756 | ||
768 | /* Should really check for multiple pids or reject bad args here */ | 757 | /* |
758 | * Should really check for multiple pids or reject bad args here | ||
759 | */ | ||
769 | /* What do the arguments in mconsole_reply mean? */ | 760 | /* What do the arguments in mconsole_reply mean? */ |
770 | if(sscanf(ptr, "%d", &pid_requested) == 0){ | 761 | if (sscanf(ptr, "%d", &pid_requested) == 0) { |
771 | mconsole_reply(req, "Please specify a pid", 1, 0); | 762 | mconsole_reply(req, "Please specify a pid", 1, 0); |
772 | return; | 763 | return; |
773 | } | 764 | } |
@@ -775,25 +766,15 @@ static void do_stack_trace(struct mc_request *req) | |||
775 | from = current; | 766 | from = current; |
776 | 767 | ||
777 | to = find_task_by_pid(pid_requested); | 768 | to = find_task_by_pid(pid_requested); |
778 | if((to == NULL) || (pid_requested == 0)) { | 769 | if ((to == NULL) || (pid_requested == 0)) { |
779 | mconsole_reply(req, "Couldn't find that pid", 1, 0); | 770 | mconsole_reply(req, "Couldn't find that pid", 1, 0); |
780 | return; | 771 | return; |
781 | } | 772 | } |
782 | with_console(req, stack_proc, to); | 773 | with_console(req, stack_proc, to); |
783 | } | 774 | } |
784 | #endif /* CONFIG_MODE_SKAS */ | ||
785 | 775 | ||
786 | void mconsole_stack(struct mc_request *req) | 776 | /* |
787 | { | 777 | * Changed by mconsole_setup, which is __setup, and called before SMP is |
788 | /* This command doesn't work in TT mode, so let's check and then | ||
789 | * get out of here | ||
790 | */ | ||
791 | CHOOSE_MODE(mconsole_reply(req, "Sorry, this doesn't work in TT mode", | ||
792 | 1, 0), | ||
793 | do_stack_trace(req)); | ||
794 | } | ||
795 | |||
796 | /* Changed by mconsole_setup, which is __setup, and called before SMP is | ||
797 | * active. | 778 | * active. |
798 | */ | 779 | */ |
799 | static char *notify_socket = NULL; | 780 | static char *notify_socket = NULL; |
@@ -805,13 +786,14 @@ static int __init mconsole_init(void) | |||
805 | int err; | 786 | int err; |
806 | char file[256]; | 787 | char file[256]; |
807 | 788 | ||
808 | if(umid_file_name("mconsole", file, sizeof(file))) return(-1); | 789 | if (umid_file_name("mconsole", file, sizeof(file))) |
790 | return -1; | ||
809 | snprintf(mconsole_socket_name, sizeof(file), "%s", file); | 791 | snprintf(mconsole_socket_name, sizeof(file), "%s", file); |
810 | 792 | ||
811 | sock = os_create_unix_socket(file, sizeof(file), 1); | 793 | sock = os_create_unix_socket(file, sizeof(file), 1); |
812 | if (sock < 0){ | 794 | if (sock < 0) { |
813 | printk("Failed to initialize management console\n"); | 795 | printk(KERN_ERR "Failed to initialize management console\n"); |
814 | return(1); | 796 | return 1; |
815 | } | 797 | } |
816 | 798 | ||
817 | register_reboot_notifier(&reboot_notifier); | 799 | register_reboot_notifier(&reboot_notifier); |
@@ -819,14 +801,14 @@ static int __init mconsole_init(void) | |||
819 | err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt, | 801 | err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt, |
820 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, | 802 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, |
821 | "mconsole", (void *)sock); | 803 | "mconsole", (void *)sock); |
822 | if (err){ | 804 | if (err) { |
823 | printk("Failed to get IRQ for management console\n"); | 805 | printk(KERN_ERR "Failed to get IRQ for management console\n"); |
824 | return(1); | 806 | return 1; |
825 | } | 807 | } |
826 | 808 | ||
827 | if(notify_socket != NULL){ | 809 | if (notify_socket != NULL) { |
828 | notify_socket = kstrdup(notify_socket, GFP_KERNEL); | 810 | notify_socket = kstrdup(notify_socket, GFP_KERNEL); |
829 | if(notify_socket != NULL) | 811 | if (notify_socket != NULL) |
830 | mconsole_notify(notify_socket, MCONSOLE_SOCKET, | 812 | mconsole_notify(notify_socket, MCONSOLE_SOCKET, |
831 | mconsole_socket_name, | 813 | mconsole_socket_name, |
832 | strlen(mconsole_socket_name) + 1); | 814 | strlen(mconsole_socket_name) + 1); |
@@ -834,9 +816,9 @@ static int __init mconsole_init(void) | |||
834 | "string\n"); | 816 | "string\n"); |
835 | } | 817 | } |
836 | 818 | ||
837 | printk("mconsole (version %d) initialized on %s\n", | 819 | printk(KERN_INFO "mconsole (version %d) initialized on %s\n", |
838 | MCONSOLE_VERSION, mconsole_socket_name); | 820 | MCONSOLE_VERSION, mconsole_socket_name); |
839 | return(0); | 821 | return 0; |
840 | } | 822 | } |
841 | 823 | ||
842 | __initcall(mconsole_init); | 824 | __initcall(mconsole_init); |
@@ -847,10 +829,10 @@ static int write_proc_mconsole(struct file *file, const char __user *buffer, | |||
847 | char *buf; | 829 | char *buf; |
848 | 830 | ||
849 | buf = kmalloc(count + 1, GFP_KERNEL); | 831 | buf = kmalloc(count + 1, GFP_KERNEL); |
850 | if(buf == NULL) | 832 | if (buf == NULL) |
851 | return(-ENOMEM); | 833 | return -ENOMEM; |
852 | 834 | ||
853 | if(copy_from_user(buf, buffer, count)){ | 835 | if (copy_from_user(buf, buffer, count)) { |
854 | count = -EFAULT; | 836 | count = -EFAULT; |
855 | goto out; | 837 | goto out; |
856 | } | 838 | } |
@@ -860,24 +842,26 @@ static int write_proc_mconsole(struct file *file, const char __user *buffer, | |||
860 | mconsole_notify(notify_socket, MCONSOLE_USER_NOTIFY, buf, count); | 842 | mconsole_notify(notify_socket, MCONSOLE_USER_NOTIFY, buf, count); |
861 | out: | 843 | out: |
862 | kfree(buf); | 844 | kfree(buf); |
863 | return(count); | 845 | return count; |
864 | } | 846 | } |
865 | 847 | ||
866 | static int create_proc_mconsole(void) | 848 | static int create_proc_mconsole(void) |
867 | { | 849 | { |
868 | struct proc_dir_entry *ent; | 850 | struct proc_dir_entry *ent; |
869 | 851 | ||
870 | if(notify_socket == NULL) return(0); | 852 | if (notify_socket == NULL) |
853 | return 0; | ||
871 | 854 | ||
872 | ent = create_proc_entry("mconsole", S_IFREG | 0200, NULL); | 855 | ent = create_proc_entry("mconsole", S_IFREG | 0200, NULL); |
873 | if(ent == NULL){ | 856 | if (ent == NULL) { |
874 | printk(KERN_INFO "create_proc_mconsole : create_proc_entry failed\n"); | 857 | printk(KERN_INFO "create_proc_mconsole : create_proc_entry " |
875 | return(0); | 858 | "failed\n"); |
859 | return 0; | ||
876 | } | 860 | } |
877 | 861 | ||
878 | ent->read_proc = NULL; | 862 | ent->read_proc = NULL; |
879 | ent->write_proc = write_proc_mconsole; | 863 | ent->write_proc = write_proc_mconsole; |
880 | return(0); | 864 | return 0; |
881 | } | 865 | } |
882 | 866 | ||
883 | static DEFINE_SPINLOCK(notify_spinlock); | 867 | static DEFINE_SPINLOCK(notify_spinlock); |
@@ -894,19 +878,19 @@ void unlock_notify(void) | |||
894 | 878 | ||
895 | __initcall(create_proc_mconsole); | 879 | __initcall(create_proc_mconsole); |
896 | 880 | ||
897 | #define NOTIFY "=notify:" | 881 | #define NOTIFY "notify:" |
898 | 882 | ||
899 | static int mconsole_setup(char *str) | 883 | static int mconsole_setup(char *str) |
900 | { | 884 | { |
901 | if(!strncmp(str, NOTIFY, strlen(NOTIFY))){ | 885 | if (!strncmp(str, NOTIFY, strlen(NOTIFY))) { |
902 | str += strlen(NOTIFY); | 886 | str += strlen(NOTIFY); |
903 | notify_socket = str; | 887 | notify_socket = str; |
904 | } | 888 | } |
905 | else printk(KERN_ERR "mconsole_setup : Unknown option - '%s'\n", str); | 889 | else printk(KERN_ERR "mconsole_setup : Unknown option - '%s'\n", str); |
906 | return(1); | 890 | return 1; |
907 | } | 891 | } |
908 | 892 | ||
909 | __setup("mconsole", mconsole_setup); | 893 | __setup("mconsole=", mconsole_setup); |
910 | 894 | ||
911 | __uml_help(mconsole_setup, | 895 | __uml_help(mconsole_setup, |
912 | "mconsole=notify:<socket>\n" | 896 | "mconsole=notify:<socket>\n" |
@@ -921,11 +905,12 @@ static int notify_panic(struct notifier_block *self, unsigned long unused1, | |||
921 | { | 905 | { |
922 | char *message = ptr; | 906 | char *message = ptr; |
923 | 907 | ||
924 | if(notify_socket == NULL) return(0); | 908 | if (notify_socket == NULL) |
909 | return 0; | ||
925 | 910 | ||
926 | mconsole_notify(notify_socket, MCONSOLE_PANIC, message, | 911 | mconsole_notify(notify_socket, MCONSOLE_PANIC, message, |
927 | strlen(message) + 1); | 912 | strlen(message) + 1); |
928 | return(0); | 913 | return 0; |
929 | } | 914 | } |
930 | 915 | ||
931 | static struct notifier_block panic_exit_notifier = { | 916 | static struct notifier_block panic_exit_notifier = { |
@@ -938,14 +923,14 @@ static int add_notifier(void) | |||
938 | { | 923 | { |
939 | atomic_notifier_chain_register(&panic_notifier_list, | 924 | atomic_notifier_chain_register(&panic_notifier_list, |
940 | &panic_exit_notifier); | 925 | &panic_exit_notifier); |
941 | return(0); | 926 | return 0; |
942 | } | 927 | } |
943 | 928 | ||
944 | __initcall(add_notifier); | 929 | __initcall(add_notifier); |
945 | 930 | ||
946 | char *mconsole_notify_socket(void) | 931 | char *mconsole_notify_socket(void) |
947 | { | 932 | { |
948 | return(notify_socket); | 933 | return notify_socket; |
949 | } | 934 | } |
950 | 935 | ||
951 | EXPORT_SYMBOL(mconsole_notify_socket); | 936 | EXPORT_SYMBOL(mconsole_notify_socket); |
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index f31e71546e52..430c024a19b0 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c | |||
@@ -1,25 +1,22 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) | 2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) |
3 | * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com) | 3 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
4 | * Licensed under the GPL | 4 | * Licensed under the GPL |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <stdio.h> | ||
8 | #include <stdlib.h> | ||
9 | #include <errno.h> | 7 | #include <errno.h> |
10 | #include <signal.h> | 8 | #include <string.h> |
9 | #include <unistd.h> | ||
11 | #include <sys/socket.h> | 10 | #include <sys/socket.h> |
12 | #include <sys/types.h> | ||
13 | #include <sys/uio.h> | 11 | #include <sys/uio.h> |
14 | #include <sys/un.h> | 12 | #include <sys/un.h> |
15 | #include <unistd.h> | 13 | #include "kern_constants.h" |
16 | #include "user.h" | ||
17 | #include "sysdep/ptrace.h" | ||
18 | #include "mconsole.h" | 14 | #include "mconsole.h" |
19 | #include "os.h" | 15 | #include "user.h" |
20 | 16 | ||
21 | static struct mconsole_command commands[] = { | 17 | static struct mconsole_command commands[] = { |
22 | /* With uts namespaces, uts information becomes process-specific, so | 18 | /* |
19 | * With uts namespaces, uts information becomes process-specific, so | ||
23 | * we need a process context. If we try handling this in interrupt | 20 | * we need a process context. If we try handling this in interrupt |
24 | * context, we may hit an exiting process without a valid uts | 21 | * context, we may hit an exiting process without a valid uts |
25 | * namespace. | 22 | * namespace. |
@@ -36,7 +33,7 @@ static struct mconsole_command commands[] = { | |||
36 | { "go", mconsole_go, MCONSOLE_INTR }, | 33 | { "go", mconsole_go, MCONSOLE_INTR }, |
37 | { "log", mconsole_log, MCONSOLE_INTR }, | 34 | { "log", mconsole_log, MCONSOLE_INTR }, |
38 | { "proc", mconsole_proc, MCONSOLE_PROC }, | 35 | { "proc", mconsole_proc, MCONSOLE_PROC }, |
39 | { "stack", mconsole_stack, MCONSOLE_INTR }, | 36 | { "stack", mconsole_stack, MCONSOLE_INTR }, |
40 | }; | 37 | }; |
41 | 38 | ||
42 | /* Initialized in mconsole_init, which is an initcall */ | 39 | /* Initialized in mconsole_init, which is an initcall */ |
@@ -44,21 +41,21 @@ char mconsole_socket_name[256]; | |||
44 | 41 | ||
45 | int mconsole_reply_v0(struct mc_request *req, char *reply) | 42 | int mconsole_reply_v0(struct mc_request *req, char *reply) |
46 | { | 43 | { |
47 | struct iovec iov; | 44 | struct iovec iov; |
48 | struct msghdr msg; | 45 | struct msghdr msg; |
49 | 46 | ||
50 | iov.iov_base = reply; | 47 | iov.iov_base = reply; |
51 | iov.iov_len = strlen(reply); | 48 | iov.iov_len = strlen(reply); |
52 | 49 | ||
53 | msg.msg_name = &(req->origin); | 50 | msg.msg_name = &(req->origin); |
54 | msg.msg_namelen = req->originlen; | 51 | msg.msg_namelen = req->originlen; |
55 | msg.msg_iov = &iov; | 52 | msg.msg_iov = &iov; |
56 | msg.msg_iovlen = 1; | 53 | msg.msg_iovlen = 1; |
57 | msg.msg_control = NULL; | 54 | msg.msg_control = NULL; |
58 | msg.msg_controllen = 0; | 55 | msg.msg_controllen = 0; |
59 | msg.msg_flags = 0; | 56 | msg.msg_flags = 0; |
60 | 57 | ||
61 | return sendmsg(req->originating_fd, &msg, 0); | 58 | return sendmsg(req->originating_fd, &msg, 0); |
62 | } | 59 | } |
63 | 60 | ||
64 | static struct mconsole_command *mconsole_parse(struct mc_request *req) | 61 | static struct mconsole_command *mconsole_parse(struct mc_request *req) |
@@ -66,10 +63,10 @@ static struct mconsole_command *mconsole_parse(struct mc_request *req) | |||
66 | struct mconsole_command *cmd; | 63 | struct mconsole_command *cmd; |
67 | int i; | 64 | int i; |
68 | 65 | ||
69 | for(i = 0; i < ARRAY_SIZE(commands); i++){ | 66 | for (i = 0; i < ARRAY_SIZE(commands); i++) { |
70 | cmd = &commands[i]; | 67 | cmd = &commands[i]; |
71 | if(!strncmp(req->request.data, cmd->command, | 68 | if (!strncmp(req->request.data, cmd->command, |
72 | strlen(cmd->command))){ | 69 | strlen(cmd->command))) { |
73 | return cmd; | 70 | return cmd; |
74 | } | 71 | } |
75 | } | 72 | } |
@@ -94,9 +91,9 @@ int mconsole_get_request(int fd, struct mc_request *req) | |||
94 | 91 | ||
95 | req->originating_fd = fd; | 92 | req->originating_fd = fd; |
96 | 93 | ||
97 | if(req->request.magic != MCONSOLE_MAGIC){ | 94 | if (req->request.magic != MCONSOLE_MAGIC) { |
98 | /* Unversioned request */ | 95 | /* Unversioned request */ |
99 | len = MIN(sizeof(req->request.data) - 1, | 96 | len = MIN(sizeof(req->request.data) - 1, |
100 | strlen((char *) &req->request)); | 97 | strlen((char *) &req->request)); |
101 | memmove(req->request.data, &req->request, len); | 98 | memmove(req->request.data, &req->request, len); |
102 | req->request.data[len] = '\0'; | 99 | req->request.data[len] = '\0'; |
@@ -107,32 +104,33 @@ int mconsole_get_request(int fd, struct mc_request *req) | |||
107 | 104 | ||
108 | mconsole_reply_v0(req, "ERR Version 0 mconsole clients are " | 105 | mconsole_reply_v0(req, "ERR Version 0 mconsole clients are " |
109 | "not supported by this driver"); | 106 | "not supported by this driver"); |
110 | return(0); | 107 | return 0; |
111 | } | 108 | } |
112 | 109 | ||
113 | if(req->request.len >= MCONSOLE_MAX_DATA){ | 110 | if (req->request.len >= MCONSOLE_MAX_DATA) { |
114 | mconsole_reply(req, "Request too large", 1, 0); | 111 | mconsole_reply(req, "Request too large", 1, 0); |
115 | return(0); | 112 | return 0; |
116 | } | 113 | } |
117 | if(req->request.version != MCONSOLE_VERSION){ | 114 | if (req->request.version != MCONSOLE_VERSION) { |
118 | mconsole_reply(req, "This driver only supports version " | 115 | mconsole_reply(req, "This driver only supports version " |
119 | STRING(MCONSOLE_VERSION) " clients", 1, 0); | 116 | STRING(MCONSOLE_VERSION) " clients", 1, 0); |
120 | } | 117 | } |
121 | 118 | ||
122 | req->request.data[req->request.len] = '\0'; | 119 | req->request.data[req->request.len] = '\0'; |
123 | req->cmd = mconsole_parse(req); | 120 | req->cmd = mconsole_parse(req); |
124 | if(req->cmd == NULL){ | 121 | if (req->cmd == NULL) { |
125 | mconsole_reply(req, "Unknown command", 1, 0); | 122 | mconsole_reply(req, "Unknown command", 1, 0); |
126 | return(0); | 123 | return 0; |
127 | } | 124 | } |
128 | 125 | ||
129 | return(1); | 126 | return 1; |
130 | } | 127 | } |
131 | 128 | ||
132 | int mconsole_reply_len(struct mc_request *req, const char *str, int total, | 129 | int mconsole_reply_len(struct mc_request *req, const char *str, int total, |
133 | int err, int more) | 130 | int err, int more) |
134 | { | 131 | { |
135 | /* XXX This is a stack consumption problem. It'd be nice to | 132 | /* |
133 | * XXX This is a stack consumption problem. It'd be nice to | ||
136 | * make it global and serialize access to it, but there are a | 134 | * make it global and serialize access to it, but there are a |
137 | * ton of callers to this function. | 135 | * ton of callers to this function. |
138 | */ | 136 | */ |
@@ -147,7 +145,7 @@ int mconsole_reply_len(struct mc_request *req, const char *str, int total, | |||
147 | 145 | ||
148 | len = MIN(total, MCONSOLE_MAX_DATA - 1); | 146 | len = MIN(total, MCONSOLE_MAX_DATA - 1); |
149 | 147 | ||
150 | if(len == total) reply.more = more; | 148 | if (len == total) reply.more = more; |
151 | else reply.more = 1; | 149 | else reply.more = 1; |
152 | 150 | ||
153 | memcpy(reply.data, str, len); | 151 | memcpy(reply.data, str, len); |
@@ -161,9 +159,10 @@ int mconsole_reply_len(struct mc_request *req, const char *str, int total, | |||
161 | n = sendto(req->originating_fd, &reply, len, 0, | 159 | n = sendto(req->originating_fd, &reply, len, 0, |
162 | (struct sockaddr *) req->origin, req->originlen); | 160 | (struct sockaddr *) req->origin, req->originlen); |
163 | 161 | ||
164 | if(n < 0) return(-errno); | 162 | if (n < 0) |
165 | } while(total > 0); | 163 | return -errno; |
166 | return(0); | 164 | } while (total > 0); |
165 | return 0; | ||
167 | } | 166 | } |
168 | 167 | ||
169 | int mconsole_reply(struct mc_request *req, const char *str, int err, int more) | 168 | int mconsole_reply(struct mc_request *req, const char *str, int err, int more) |
@@ -187,18 +186,18 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len) | |||
187 | int n, err = 0; | 186 | int n, err = 0; |
188 | 187 | ||
189 | lock_notify(); | 188 | lock_notify(); |
190 | if(notify_sock < 0){ | 189 | if (notify_sock < 0) { |
191 | notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0); | 190 | notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0); |
192 | if(notify_sock < 0){ | 191 | if (notify_sock < 0) { |
193 | err = -errno; | 192 | err = -errno; |
194 | printk("mconsole_notify - socket failed, errno = %d\n", | 193 | printk(UM_KERN_ERR "mconsole_notify - socket failed, " |
195 | err); | 194 | "errno = %d\n", errno); |
196 | } | 195 | } |
197 | } | 196 | } |
198 | unlock_notify(); | 197 | unlock_notify(); |
199 | 198 | ||
200 | if(err) | 199 | if (err) |
201 | return(err); | 200 | return err; |
202 | 201 | ||
203 | target.sun_family = AF_UNIX; | 202 | target.sun_family = AF_UNIX; |
204 | strcpy(target.sun_path, sock_name); | 203 | strcpy(target.sun_path, sock_name); |
@@ -212,22 +211,12 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len) | |||
212 | 211 | ||
213 | err = 0; | 212 | err = 0; |
214 | len = sizeof(packet) + packet.len - sizeof(packet.data); | 213 | len = sizeof(packet) + packet.len - sizeof(packet.data); |
215 | n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target, | 214 | n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target, |
216 | sizeof(target)); | 215 | sizeof(target)); |
217 | if(n < 0){ | 216 | if (n < 0) { |
218 | err = -errno; | 217 | err = -errno; |
219 | printk("mconsole_notify - sendto failed, errno = %d\n", errno); | 218 | printk(UM_KERN_ERR "mconsole_notify - sendto failed, " |
219 | "errno = %d\n", errno); | ||
220 | } | 220 | } |
221 | return(err); | 221 | return err; |
222 | } | 222 | } |
223 | |||
224 | /* | ||
225 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
226 | * Emacs will notice this stuff at the end of the file and automatically | ||
227 | * adjust the settings for this buffer only. This must remain at the end | ||
228 | * of the file. | ||
229 | * --------------------------------------------------------------------------- | ||
230 | * Local variables: | ||
231 | * c-file-style: "linux" | ||
232 | * End: | ||
233 | */ | ||
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c index 867666a02339..67b2f55a602f 100644 --- a/arch/um/drivers/mmapper_kern.c +++ b/arch/um/drivers/mmapper_kern.c | |||
@@ -9,27 +9,29 @@ | |||
9 | * | 9 | * |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/init.h> | 12 | #include <linux/stddef.h> |
13 | #include <linux/module.h> | 13 | #include <linux/types.h> |
14 | #include <linux/mm.h> | ||
15 | #include <linux/fs.h> | 14 | #include <linux/fs.h> |
15 | #include <linux/init.h> | ||
16 | #include <linux/miscdevice.h> | 16 | #include <linux/miscdevice.h> |
17 | #include <linux/module.h> | ||
18 | #include <linux/mm.h> | ||
17 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
18 | #include "mem_user.h" | 20 | #include "mem_user.h" |
19 | 21 | ||
20 | /* These are set in mmapper_init, which is called at boot time */ | 22 | /* These are set in mmapper_init, which is called at boot time */ |
21 | static unsigned long mmapper_size; | 23 | static unsigned long mmapper_size; |
22 | static unsigned long p_buf = 0; | 24 | static unsigned long p_buf; |
23 | static char *v_buf = NULL; | 25 | static char *v_buf; |
24 | 26 | ||
25 | static ssize_t | 27 | static ssize_t mmapper_read(struct file *file, char __user *buf, size_t count, |
26 | mmapper_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | 28 | loff_t *ppos) |
27 | { | 29 | { |
28 | return simple_read_from_buffer(buf, count, ppos, v_buf, mmapper_size); | 30 | return simple_read_from_buffer(buf, count, ppos, v_buf, mmapper_size); |
29 | } | 31 | } |
30 | 32 | ||
31 | static ssize_t | 33 | static ssize_t mmapper_write(struct file *file, const char __user *buf, |
32 | mmapper_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | 34 | size_t count, loff_t *ppos) |
33 | { | 35 | { |
34 | if (*ppos > mmapper_size) | 36 | if (*ppos > mmapper_size) |
35 | return -EINVAL; | 37 | return -EINVAL; |
@@ -39,48 +41,46 @@ mmapper_write(struct file *file, const char __user *buf, size_t count, loff_t *p | |||
39 | 41 | ||
40 | if (copy_from_user(&v_buf[*ppos], buf, count)) | 42 | if (copy_from_user(&v_buf[*ppos], buf, count)) |
41 | return -EFAULT; | 43 | return -EFAULT; |
42 | 44 | ||
43 | return count; | 45 | return count; |
44 | } | 46 | } |
45 | 47 | ||
46 | static int | 48 | static int mmapper_ioctl(struct inode *inode, struct file *file, |
47 | mmapper_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 49 | unsigned int cmd, unsigned long arg) |
48 | unsigned long arg) | ||
49 | { | 50 | { |
50 | return(-ENOIOCTLCMD); | 51 | return -ENOIOCTLCMD; |
51 | } | 52 | } |
52 | 53 | ||
53 | static int | 54 | static int mmapper_mmap(struct file *file, struct vm_area_struct *vma) |
54 | mmapper_mmap(struct file *file, struct vm_area_struct * vma) | ||
55 | { | 55 | { |
56 | int ret = -EINVAL; | 56 | int ret = -EINVAL; |
57 | int size; | 57 | int size; |
58 | 58 | ||
59 | if (vma->vm_pgoff != 0) | 59 | if (vma->vm_pgoff != 0) |
60 | goto out; | 60 | goto out; |
61 | 61 | ||
62 | size = vma->vm_end - vma->vm_start; | 62 | size = vma->vm_end - vma->vm_start; |
63 | if(size > mmapper_size) return(-EFAULT); | 63 | if (size > mmapper_size) |
64 | return -EFAULT; | ||
64 | 65 | ||
65 | /* XXX A comment above remap_pfn_range says it should only be | 66 | /* |
67 | * XXX A comment above remap_pfn_range says it should only be | ||
66 | * called when the mm semaphore is held | 68 | * called when the mm semaphore is held |
67 | */ | 69 | */ |
68 | if (remap_pfn_range(vma, vma->vm_start, p_buf >> PAGE_SHIFT, size, | 70 | if (remap_pfn_range(vma, vma->vm_start, p_buf >> PAGE_SHIFT, size, |
69 | vma->vm_page_prot)) | 71 | vma->vm_page_prot)) |
70 | goto out; | 72 | goto out; |
71 | ret = 0; | 73 | ret = 0; |
72 | out: | 74 | out: |
73 | return ret; | 75 | return ret; |
74 | } | 76 | } |
75 | 77 | ||
76 | static int | 78 | static int mmapper_open(struct inode *inode, struct file *file) |
77 | mmapper_open(struct inode *inode, struct file *file) | ||
78 | { | 79 | { |
79 | return 0; | 80 | return 0; |
80 | } | 81 | } |
81 | 82 | ||
82 | static int | 83 | static int mmapper_release(struct inode *inode, struct file *file) |
83 | mmapper_release(struct inode *inode, struct file *file) | ||
84 | { | 84 | { |
85 | return 0; | 85 | return 0; |
86 | } | 86 | } |
@@ -95,7 +95,9 @@ static const struct file_operations mmapper_fops = { | |||
95 | .release = mmapper_release, | 95 | .release = mmapper_release, |
96 | }; | 96 | }; |
97 | 97 | ||
98 | /* No locking needed - only used (and modified) by below initcall and exitcall. */ | 98 | /* |
99 | * No locking needed - only used (and modified) by below initcall and exitcall. | ||
100 | */ | ||
99 | static struct miscdevice mmapper_dev = { | 101 | static struct miscdevice mmapper_dev = { |
100 | .minor = MISC_DYNAMIC_MINOR, | 102 | .minor = MISC_DYNAMIC_MINOR, |
101 | .name = "mmapper", | 103 | .name = "mmapper", |
@@ -109,13 +111,13 @@ static int __init mmapper_init(void) | |||
109 | printk(KERN_INFO "Mapper v0.1\n"); | 111 | printk(KERN_INFO "Mapper v0.1\n"); |
110 | 112 | ||
111 | v_buf = (char *) find_iomem("mmapper", &mmapper_size); | 113 | v_buf = (char *) find_iomem("mmapper", &mmapper_size); |
112 | if(mmapper_size == 0){ | 114 | if (mmapper_size == 0) { |
113 | printk(KERN_ERR "mmapper_init - find_iomem failed\n"); | 115 | printk(KERN_ERR "mmapper_init - find_iomem failed\n"); |
114 | goto out; | 116 | goto out; |
115 | } | 117 | } |
116 | 118 | ||
117 | err = misc_register(&mmapper_dev); | 119 | err = misc_register(&mmapper_dev); |
118 | if(err){ | 120 | if (err) { |
119 | printk(KERN_ERR "mmapper - misc_register failed, err = %d\n", | 121 | printk(KERN_ERR "mmapper - misc_register failed, err = %d\n", |
120 | err); | 122 | err); |
121 | goto out; | 123 | goto out; |
@@ -136,9 +138,3 @@ module_exit(mmapper_exit); | |||
136 | 138 | ||
137 | MODULE_AUTHOR("Greg Lonnon <glonnon@ridgerun.com>"); | 139 | MODULE_AUTHOR("Greg Lonnon <glonnon@ridgerun.com>"); |
138 | MODULE_DESCRIPTION("DSPLinux simulator mmapper driver"); | 140 | MODULE_DESCRIPTION("DSPLinux simulator mmapper driver"); |
139 | /* | ||
140 | * --------------------------------------------------------------------------- | ||
141 | * Local variables: | ||
142 | * c-file-style: "linux" | ||
143 | * End: | ||
144 | */ | ||
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index d35d0c1ee7f4..8c01fa81a1ae 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c | |||
@@ -1,33 +1,28 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and | 3 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and |
3 | * James Leu (jleu@mindspring.net). | 4 | * James Leu (jleu@mindspring.net). |
4 | * Copyright (C) 2001 by various other people who didn't put their name here. | 5 | * Copyright (C) 2001 by various other people who didn't put their name here. |
5 | * Licensed under the GPL. | 6 | * Licensed under the GPL. |
6 | */ | 7 | */ |
7 | 8 | ||
8 | #include "linux/kernel.h" | 9 | #include <linux/bootmem.h> |
9 | #include "linux/netdevice.h" | 10 | #include <linux/etherdevice.h> |
10 | #include "linux/rtnetlink.h" | 11 | #include <linux/ethtool.h> |
11 | #include "linux/skbuff.h" | 12 | #include <linux/inetdevice.h> |
12 | #include "linux/socket.h" | 13 | #include <linux/init.h> |
13 | #include "linux/spinlock.h" | 14 | #include <linux/list.h> |
14 | #include "linux/module.h" | 15 | #include <linux/netdevice.h> |
15 | #include "linux/init.h" | 16 | #include <linux/platform_device.h> |
16 | #include "linux/etherdevice.h" | 17 | #include <linux/rtnetlink.h> |
17 | #include "linux/list.h" | 18 | #include <linux/skbuff.h> |
18 | #include "linux/inetdevice.h" | 19 | #include <linux/spinlock.h> |
19 | #include "linux/ctype.h" | ||
20 | #include "linux/bootmem.h" | ||
21 | #include "linux/ethtool.h" | ||
22 | #include "linux/platform_device.h" | ||
23 | #include "asm/uaccess.h" | ||
24 | #include "kern_util.h" | ||
25 | #include "net_kern.h" | ||
26 | #include "net_user.h" | ||
27 | #include "mconsole_kern.h" | ||
28 | #include "init.h" | 20 | #include "init.h" |
29 | #include "irq_user.h" | ||
30 | #include "irq_kern.h" | 21 | #include "irq_kern.h" |
22 | #include "irq_user.h" | ||
23 | #include "mconsole_kern.h" | ||
24 | #include "net_kern.h" | ||
25 | #include "net_user.h" | ||
31 | 26 | ||
32 | static inline void set_ether_mac(struct net_device *dev, unsigned char *addr) | 27 | static inline void set_ether_mac(struct net_device *dev, unsigned char *addr) |
33 | { | 28 | { |
@@ -39,6 +34,46 @@ static inline void set_ether_mac(struct net_device *dev, unsigned char *addr) | |||
39 | static DEFINE_SPINLOCK(opened_lock); | 34 | static DEFINE_SPINLOCK(opened_lock); |
40 | static LIST_HEAD(opened); | 35 | static LIST_HEAD(opened); |
41 | 36 | ||
37 | /* | ||
38 | * The drop_skb is used when we can't allocate an skb. The | ||
39 | * packet is read into drop_skb in order to get the data off the | ||
40 | * connection to the host. | ||
41 | * It is reallocated whenever a maximum packet size is seen which is | ||
42 | * larger than any seen before. update_drop_skb is called from | ||
43 | * eth_configure when a new interface is added. | ||
44 | */ | ||
45 | static DEFINE_SPINLOCK(drop_lock); | ||
46 | static struct sk_buff *drop_skb; | ||
47 | static int drop_max; | ||
48 | |||
49 | static int update_drop_skb(int max) | ||
50 | { | ||
51 | struct sk_buff *new; | ||
52 | unsigned long flags; | ||
53 | int err = 0; | ||
54 | |||
55 | spin_lock_irqsave(&drop_lock, flags); | ||
56 | |||
57 | if (max <= drop_max) | ||
58 | goto out; | ||
59 | |||
60 | err = -ENOMEM; | ||
61 | new = dev_alloc_skb(max); | ||
62 | if (new == NULL) | ||
63 | goto out; | ||
64 | |||
65 | skb_put(new, max); | ||
66 | |||
67 | kfree_skb(drop_skb); | ||
68 | drop_skb = new; | ||
69 | drop_max = max; | ||
70 | err = 0; | ||
71 | out: | ||
72 | spin_unlock_irqrestore(&drop_lock, flags); | ||
73 | |||
74 | return err; | ||
75 | } | ||
76 | |||
42 | static int uml_net_rx(struct net_device *dev) | 77 | static int uml_net_rx(struct net_device *dev) |
43 | { | 78 | { |
44 | struct uml_net_private *lp = dev->priv; | 79 | struct uml_net_private *lp = dev->priv; |
@@ -46,16 +81,19 @@ static int uml_net_rx(struct net_device *dev) | |||
46 | struct sk_buff *skb; | 81 | struct sk_buff *skb; |
47 | 82 | ||
48 | /* If we can't allocate memory, try again next round. */ | 83 | /* If we can't allocate memory, try again next round. */ |
49 | skb = dev_alloc_skb(dev->mtu); | 84 | skb = dev_alloc_skb(lp->max_packet); |
50 | if (skb == NULL) { | 85 | if (skb == NULL) { |
86 | drop_skb->dev = dev; | ||
87 | /* Read a packet into drop_skb and don't do anything with it. */ | ||
88 | (*lp->read)(lp->fd, drop_skb, lp); | ||
51 | lp->stats.rx_dropped++; | 89 | lp->stats.rx_dropped++; |
52 | return 0; | 90 | return 0; |
53 | } | 91 | } |
54 | 92 | ||
55 | skb->dev = dev; | 93 | skb->dev = dev; |
56 | skb_put(skb, dev->mtu); | 94 | skb_put(skb, lp->max_packet); |
57 | skb_reset_mac_header(skb); | 95 | skb_reset_mac_header(skb); |
58 | pkt_len = (*lp->read)(lp->fd, &skb, lp); | 96 | pkt_len = (*lp->read)(lp->fd, skb, lp); |
59 | 97 | ||
60 | if (pkt_len > 0) { | 98 | if (pkt_len > 0) { |
61 | skb_trim(skb, pkt_len); | 99 | skb_trim(skb, pkt_len); |
@@ -84,12 +122,12 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id) | |||
84 | struct uml_net_private *lp = dev->priv; | 122 | struct uml_net_private *lp = dev->priv; |
85 | int err; | 123 | int err; |
86 | 124 | ||
87 | if(!netif_running(dev)) | 125 | if (!netif_running(dev)) |
88 | return(IRQ_NONE); | 126 | return IRQ_NONE; |
89 | 127 | ||
90 | spin_lock(&lp->lock); | 128 | spin_lock(&lp->lock); |
91 | while((err = uml_net_rx(dev)) > 0) ; | 129 | while ((err = uml_net_rx(dev)) > 0) ; |
92 | if(err < 0) { | 130 | if (err < 0) { |
93 | printk(KERN_ERR | 131 | printk(KERN_ERR |
94 | "Device '%s' read returned %d, shutting it down\n", | 132 | "Device '%s' read returned %d, shutting it down\n", |
95 | dev->name, err); | 133 | dev->name, err); |
@@ -115,20 +153,20 @@ static int uml_net_open(struct net_device *dev) | |||
115 | struct uml_net_private *lp = dev->priv; | 153 | struct uml_net_private *lp = dev->priv; |
116 | int err; | 154 | int err; |
117 | 155 | ||
118 | if(lp->fd >= 0){ | 156 | if (lp->fd >= 0) { |
119 | err = -ENXIO; | 157 | err = -ENXIO; |
120 | goto out; | 158 | goto out; |
121 | } | 159 | } |
122 | 160 | ||
123 | lp->fd = (*lp->open)(&lp->user); | 161 | lp->fd = (*lp->open)(&lp->user); |
124 | if(lp->fd < 0){ | 162 | if (lp->fd < 0) { |
125 | err = lp->fd; | 163 | err = lp->fd; |
126 | goto out; | 164 | goto out; |
127 | } | 165 | } |
128 | 166 | ||
129 | err = um_request_irq(dev->irq, lp->fd, IRQ_READ, uml_net_interrupt, | 167 | err = um_request_irq(dev->irq, lp->fd, IRQ_READ, uml_net_interrupt, |
130 | IRQF_DISABLED | IRQF_SHARED, dev->name, dev); | 168 | IRQF_DISABLED | IRQF_SHARED, dev->name, dev); |
131 | if(err != 0){ | 169 | if (err != 0) { |
132 | printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err); | 170 | printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err); |
133 | err = -ENETUNREACH; | 171 | err = -ENETUNREACH; |
134 | goto out_close; | 172 | goto out_close; |
@@ -141,7 +179,7 @@ static int uml_net_open(struct net_device *dev) | |||
141 | * is full when we get here. In this case, new data is never queued, | 179 | * is full when we get here. In this case, new data is never queued, |
142 | * SIGIOs never arrive, and the net never works. | 180 | * SIGIOs never arrive, and the net never works. |
143 | */ | 181 | */ |
144 | while((err = uml_net_rx(dev)) > 0) ; | 182 | while ((err = uml_net_rx(dev)) > 0) ; |
145 | 183 | ||
146 | spin_lock(&opened_lock); | 184 | spin_lock(&opened_lock); |
147 | list_add(&lp->list, &opened); | 185 | list_add(&lp->list, &opened); |
@@ -149,7 +187,7 @@ static int uml_net_open(struct net_device *dev) | |||
149 | 187 | ||
150 | return 0; | 188 | return 0; |
151 | out_close: | 189 | out_close: |
152 | if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); | 190 | if (lp->close != NULL) (*lp->close)(lp->fd, &lp->user); |
153 | lp->fd = -1; | 191 | lp->fd = -1; |
154 | out: | 192 | out: |
155 | return err; | 193 | return err; |
@@ -162,7 +200,7 @@ static int uml_net_close(struct net_device *dev) | |||
162 | netif_stop_queue(dev); | 200 | netif_stop_queue(dev); |
163 | 201 | ||
164 | free_irq(dev->irq, dev); | 202 | free_irq(dev->irq, dev); |
165 | if(lp->close != NULL) | 203 | if (lp->close != NULL) |
166 | (*lp->close)(lp->fd, &lp->user); | 204 | (*lp->close)(lp->fd, &lp->user); |
167 | lp->fd = -1; | 205 | lp->fd = -1; |
168 | 206 | ||
@@ -183,9 +221,9 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
183 | 221 | ||
184 | spin_lock_irqsave(&lp->lock, flags); | 222 | spin_lock_irqsave(&lp->lock, flags); |
185 | 223 | ||
186 | len = (*lp->write)(lp->fd, &skb, lp); | 224 | len = (*lp->write)(lp->fd, skb, lp); |
187 | 225 | ||
188 | if(len == skb->len) { | 226 | if (len == skb->len) { |
189 | lp->stats.tx_packets++; | 227 | lp->stats.tx_packets++; |
190 | lp->stats.tx_bytes += skb->len; | 228 | lp->stats.tx_bytes += skb->len; |
191 | dev->trans_start = jiffies; | 229 | dev->trans_start = jiffies; |
@@ -194,7 +232,7 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
194 | /* this is normally done in the interrupt when tx finishes */ | 232 | /* this is normally done in the interrupt when tx finishes */ |
195 | netif_wake_queue(dev); | 233 | netif_wake_queue(dev); |
196 | } | 234 | } |
197 | else if(len == 0){ | 235 | else if (len == 0) { |
198 | netif_start_queue(dev); | 236 | netif_start_queue(dev); |
199 | lp->stats.tx_dropped++; | 237 | lp->stats.tx_dropped++; |
200 | } | 238 | } |
@@ -218,8 +256,10 @@ static struct net_device_stats *uml_net_get_stats(struct net_device *dev) | |||
218 | 256 | ||
219 | static void uml_net_set_multicast_list(struct net_device *dev) | 257 | static void uml_net_set_multicast_list(struct net_device *dev) |
220 | { | 258 | { |
221 | if (dev->flags & IFF_PROMISC) return; | 259 | if (dev->flags & IFF_PROMISC) |
222 | else if (dev->mc_count) dev->flags |= IFF_ALLMULTI; | 260 | return; |
261 | else if (dev->mc_count) | ||
262 | dev->flags |= IFF_ALLMULTI; | ||
223 | else dev->flags &= ~IFF_ALLMULTI; | 263 | else dev->flags &= ~IFF_ALLMULTI; |
224 | } | 264 | } |
225 | 265 | ||
@@ -243,22 +283,9 @@ static int uml_net_set_mac(struct net_device *dev, void *addr) | |||
243 | 283 | ||
244 | static int uml_net_change_mtu(struct net_device *dev, int new_mtu) | 284 | static int uml_net_change_mtu(struct net_device *dev, int new_mtu) |
245 | { | 285 | { |
246 | struct uml_net_private *lp = dev->priv; | ||
247 | int err = 0; | ||
248 | |||
249 | spin_lock_irq(&lp->lock); | ||
250 | |||
251 | new_mtu = (*lp->set_mtu)(new_mtu, &lp->user); | ||
252 | if(new_mtu < 0){ | ||
253 | err = new_mtu; | ||
254 | goto out; | ||
255 | } | ||
256 | |||
257 | dev->mtu = new_mtu; | 286 | dev->mtu = new_mtu; |
258 | 287 | ||
259 | out: | 288 | return 0; |
260 | spin_unlock_irq(&lp->lock); | ||
261 | return err; | ||
262 | } | 289 | } |
263 | 290 | ||
264 | static void uml_net_get_drvinfo(struct net_device *dev, | 291 | static void uml_net_get_drvinfo(struct net_device *dev, |
@@ -288,13 +315,13 @@ static void setup_etheraddr(char *str, unsigned char *addr, char *name) | |||
288 | char *end; | 315 | char *end; |
289 | int i; | 316 | int i; |
290 | 317 | ||
291 | if(str == NULL) | 318 | if (str == NULL) |
292 | goto random; | 319 | goto random; |
293 | 320 | ||
294 | for(i=0;i<6;i++){ | 321 | for (i = 0;i < 6; i++) { |
295 | addr[i] = simple_strtoul(str, &end, 16); | 322 | addr[i] = simple_strtoul(str, &end, 16); |
296 | if((end == str) || | 323 | if ((end == str) || |
297 | ((*end != ':') && (*end != ',') && (*end != '\0'))){ | 324 | ((*end != ':') && (*end != ',') && (*end != '\0'))) { |
298 | printk(KERN_ERR | 325 | printk(KERN_ERR |
299 | "setup_etheraddr: failed to parse '%s' " | 326 | "setup_etheraddr: failed to parse '%s' " |
300 | "as an ethernet address\n", str); | 327 | "as an ethernet address\n", str); |
@@ -349,7 +376,7 @@ static void net_device_release(struct device *dev) | |||
349 | struct net_device *netdev = device->dev; | 376 | struct net_device *netdev = device->dev; |
350 | struct uml_net_private *lp = netdev->priv; | 377 | struct uml_net_private *lp = netdev->priv; |
351 | 378 | ||
352 | if(lp->remove != NULL) | 379 | if (lp->remove != NULL) |
353 | (*lp->remove)(&lp->user); | 380 | (*lp->remove)(&lp->user); |
354 | list_del(&device->list); | 381 | list_del(&device->list); |
355 | kfree(device); | 382 | kfree(device); |
@@ -413,7 +440,7 @@ static void eth_configure(int n, void *init, char *mac, | |||
413 | device->pdev.name = DRIVER_NAME; | 440 | device->pdev.name = DRIVER_NAME; |
414 | device->pdev.dev.release = net_device_release; | 441 | device->pdev.dev.release = net_device_release; |
415 | device->pdev.dev.driver_data = device; | 442 | device->pdev.dev.driver_data = device; |
416 | if(platform_device_register(&device->pdev)) | 443 | if (platform_device_register(&device->pdev)) |
417 | goto out_free_netdev; | 444 | goto out_free_netdev; |
418 | SET_NETDEV_DEV(dev,&device->pdev.dev); | 445 | SET_NETDEV_DEV(dev,&device->pdev.dev); |
419 | 446 | ||
@@ -430,6 +457,7 @@ static void eth_configure(int n, void *init, char *mac, | |||
430 | .dev = dev, | 457 | .dev = dev, |
431 | .fd = -1, | 458 | .fd = -1, |
432 | .mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0}, | 459 | .mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0}, |
460 | .max_packet = transport->user->max_packet, | ||
433 | .protocol = transport->kern->protocol, | 461 | .protocol = transport->kern->protocol, |
434 | .open = transport->user->open, | 462 | .open = transport->user->open, |
435 | .close = transport->user->close, | 463 | .close = transport->user->close, |
@@ -437,8 +465,7 @@ static void eth_configure(int n, void *init, char *mac, | |||
437 | .read = transport->kern->read, | 465 | .read = transport->kern->read, |
438 | .write = transport->kern->write, | 466 | .write = transport->kern->write, |
439 | .add_address = transport->user->add_address, | 467 | .add_address = transport->user->add_address, |
440 | .delete_address = transport->user->delete_address, | 468 | .delete_address = transport->user->delete_address }); |
441 | .set_mtu = transport->user->set_mtu }); | ||
442 | 469 | ||
443 | init_timer(&lp->tl); | 470 | init_timer(&lp->tl); |
444 | spin_lock_init(&lp->lock); | 471 | spin_lock_init(&lp->lock); |
@@ -450,7 +477,7 @@ static void eth_configure(int n, void *init, char *mac, | |||
450 | goto out_unregister; | 477 | goto out_unregister; |
451 | 478 | ||
452 | set_ether_mac(dev, device->mac); | 479 | set_ether_mac(dev, device->mac); |
453 | dev->mtu = transport->user->max_packet; | 480 | dev->mtu = transport->user->mtu; |
454 | dev->open = uml_net_open; | 481 | dev->open = uml_net_open; |
455 | dev->hard_start_xmit = uml_net_start_xmit; | 482 | dev->hard_start_xmit = uml_net_start_xmit; |
456 | dev->stop = uml_net_close; | 483 | dev->stop = uml_net_close; |
@@ -463,6 +490,10 @@ static void eth_configure(int n, void *init, char *mac, | |||
463 | dev->watchdog_timeo = (HZ >> 1); | 490 | dev->watchdog_timeo = (HZ >> 1); |
464 | dev->irq = UM_ETH_IRQ; | 491 | dev->irq = UM_ETH_IRQ; |
465 | 492 | ||
493 | err = update_drop_skb(lp->max_packet); | ||
494 | if (err) | ||
495 | goto out_undo_user_init; | ||
496 | |||
466 | rtnl_lock(); | 497 | rtnl_lock(); |
467 | err = register_netdevice(dev); | 498 | err = register_netdevice(dev); |
468 | rtnl_unlock(); | 499 | rtnl_unlock(); |
@@ -493,9 +524,9 @@ static struct uml_net *find_device(int n) | |||
493 | struct list_head *ele; | 524 | struct list_head *ele; |
494 | 525 | ||
495 | spin_lock(&devices_lock); | 526 | spin_lock(&devices_lock); |
496 | list_for_each(ele, &devices){ | 527 | list_for_each(ele, &devices) { |
497 | device = list_entry(ele, struct uml_net, list); | 528 | device = list_entry(ele, struct uml_net, list); |
498 | if(device->index == n) | 529 | if (device->index == n) |
499 | goto out; | 530 | goto out; |
500 | } | 531 | } |
501 | device = NULL; | 532 | device = NULL; |
@@ -511,19 +542,19 @@ static int eth_parse(char *str, int *index_out, char **str_out, | |||
511 | int n, err = -EINVAL;; | 542 | int n, err = -EINVAL;; |
512 | 543 | ||
513 | n = simple_strtoul(str, &end, 0); | 544 | n = simple_strtoul(str, &end, 0); |
514 | if(end == str){ | 545 | if (end == str) { |
515 | *error_out = "Bad device number"; | 546 | *error_out = "Bad device number"; |
516 | return err; | 547 | return err; |
517 | } | 548 | } |
518 | 549 | ||
519 | str = end; | 550 | str = end; |
520 | if(*str != '='){ | 551 | if (*str != '=') { |
521 | *error_out = "Expected '=' after device number"; | 552 | *error_out = "Expected '=' after device number"; |
522 | return err; | 553 | return err; |
523 | } | 554 | } |
524 | 555 | ||
525 | str++; | 556 | str++; |
526 | if(find_device(n)){ | 557 | if (find_device(n)) { |
527 | *error_out = "Device already configured"; | 558 | *error_out = "Device already configured"; |
528 | return err; | 559 | return err; |
529 | } | 560 | } |
@@ -551,20 +582,20 @@ static int check_transport(struct transport *transport, char *eth, int n, | |||
551 | int len; | 582 | int len; |
552 | 583 | ||
553 | len = strlen(transport->name); | 584 | len = strlen(transport->name); |
554 | if(strncmp(eth, transport->name, len)) | 585 | if (strncmp(eth, transport->name, len)) |
555 | return 0; | 586 | return 0; |
556 | 587 | ||
557 | eth += len; | 588 | eth += len; |
558 | if(*eth == ',') | 589 | if (*eth == ',') |
559 | eth++; | 590 | eth++; |
560 | else if(*eth != '\0') | 591 | else if (*eth != '\0') |
561 | return 0; | 592 | return 0; |
562 | 593 | ||
563 | *init_out = kmalloc(transport->setup_size, GFP_KERNEL); | 594 | *init_out = kmalloc(transport->setup_size, GFP_KERNEL); |
564 | if(*init_out == NULL) | 595 | if (*init_out == NULL) |
565 | return 1; | 596 | return 1; |
566 | 597 | ||
567 | if(!transport->setup(eth, mac_out, *init_out)){ | 598 | if (!transport->setup(eth, mac_out, *init_out)) { |
568 | kfree(*init_out); | 599 | kfree(*init_out); |
569 | *init_out = NULL; | 600 | *init_out = NULL; |
570 | } | 601 | } |
@@ -584,13 +615,13 @@ void register_transport(struct transport *new) | |||
584 | list_add(&new->list, &transports); | 615 | list_add(&new->list, &transports); |
585 | spin_unlock(&transports_lock); | 616 | spin_unlock(&transports_lock); |
586 | 617 | ||
587 | list_for_each_safe(ele, next, ð_cmd_line){ | 618 | list_for_each_safe(ele, next, ð_cmd_line) { |
588 | eth = list_entry(ele, struct eth_init, list); | 619 | eth = list_entry(ele, struct eth_init, list); |
589 | match = check_transport(new, eth->init, eth->index, &init, | 620 | match = check_transport(new, eth->init, eth->index, &init, |
590 | &mac); | 621 | &mac); |
591 | if(!match) | 622 | if (!match) |
592 | continue; | 623 | continue; |
593 | else if(init != NULL){ | 624 | else if (init != NULL) { |
594 | eth_configure(eth->index, init, mac, new); | 625 | eth_configure(eth->index, init, mac, new); |
595 | kfree(init); | 626 | kfree(init); |
596 | } | 627 | } |
@@ -607,11 +638,11 @@ static int eth_setup_common(char *str, int index) | |||
607 | int found = 0; | 638 | int found = 0; |
608 | 639 | ||
609 | spin_lock(&transports_lock); | 640 | spin_lock(&transports_lock); |
610 | list_for_each(ele, &transports){ | 641 | list_for_each(ele, &transports) { |
611 | transport = list_entry(ele, struct transport, list); | 642 | transport = list_entry(ele, struct transport, list); |
612 | if(!check_transport(transport, str, index, &init, &mac)) | 643 | if (!check_transport(transport, str, index, &init, &mac)) |
613 | continue; | 644 | continue; |
614 | if(init != NULL){ | 645 | if (init != NULL) { |
615 | eth_configure(index, init, mac, transport); | 646 | eth_configure(index, init, mac, transport); |
616 | kfree(init); | 647 | kfree(init); |
617 | } | 648 | } |
@@ -630,15 +661,15 @@ static int __init eth_setup(char *str) | |||
630 | int n, err; | 661 | int n, err; |
631 | 662 | ||
632 | err = eth_parse(str, &n, &str, &error); | 663 | err = eth_parse(str, &n, &str, &error); |
633 | if(err){ | 664 | if (err) { |
634 | printk(KERN_ERR "eth_setup - Couldn't parse '%s' : %s\n", | 665 | printk(KERN_ERR "eth_setup - Couldn't parse '%s' : %s\n", |
635 | str, error); | 666 | str, error); |
636 | return 1; | 667 | return 1; |
637 | } | 668 | } |
638 | 669 | ||
639 | new = alloc_bootmem(sizeof(*new)); | 670 | new = alloc_bootmem(sizeof(*new)); |
640 | if (new == NULL){ | 671 | if (new == NULL) { |
641 | printk("eth_init : alloc_bootmem failed\n"); | 672 | printk(KERN_ERR "eth_init : alloc_bootmem failed\n"); |
642 | return 1; | 673 | return 1; |
643 | } | 674 | } |
644 | 675 | ||
@@ -661,36 +692,36 @@ static int net_config(char *str, char **error_out) | |||
661 | int n, err; | 692 | int n, err; |
662 | 693 | ||
663 | err = eth_parse(str, &n, &str, error_out); | 694 | err = eth_parse(str, &n, &str, error_out); |
664 | if(err) | 695 | if (err) |
665 | return err; | 696 | return err; |
666 | 697 | ||
667 | /* This string is broken up and the pieces used by the underlying | 698 | /* This string is broken up and the pieces used by the underlying |
668 | * driver. So, it is freed only if eth_setup_common fails. | 699 | * driver. So, it is freed only if eth_setup_common fails. |
669 | */ | 700 | */ |
670 | str = kstrdup(str, GFP_KERNEL); | 701 | str = kstrdup(str, GFP_KERNEL); |
671 | if(str == NULL){ | 702 | if (str == NULL) { |
672 | *error_out = "net_config failed to strdup string"; | 703 | *error_out = "net_config failed to strdup string"; |
673 | return -ENOMEM; | 704 | return -ENOMEM; |
674 | } | 705 | } |
675 | err = !eth_setup_common(str, n); | 706 | err = !eth_setup_common(str, n); |
676 | if(err) | 707 | if (err) |
677 | kfree(str); | 708 | kfree(str); |
678 | return(err); | 709 | return err; |
679 | } | 710 | } |
680 | 711 | ||
681 | static int net_id(char **str, int *start_out, int *end_out) | 712 | static int net_id(char **str, int *start_out, int *end_out) |
682 | { | 713 | { |
683 | char *end; | 714 | char *end; |
684 | int n; | 715 | int n; |
685 | 716 | ||
686 | n = simple_strtoul(*str, &end, 0); | 717 | n = simple_strtoul(*str, &end, 0); |
687 | if((*end != '\0') || (end == *str)) | 718 | if ((*end != '\0') || (end == *str)) |
688 | return -1; | 719 | return -1; |
689 | 720 | ||
690 | *start_out = n; | 721 | *start_out = n; |
691 | *end_out = n; | 722 | *end_out = n; |
692 | *str = end; | 723 | *str = end; |
693 | return n; | 724 | return n; |
694 | } | 725 | } |
695 | 726 | ||
696 | static int net_remove(int n, char **error_out) | 727 | static int net_remove(int n, char **error_out) |
@@ -700,12 +731,12 @@ static int net_remove(int n, char **error_out) | |||
700 | struct uml_net_private *lp; | 731 | struct uml_net_private *lp; |
701 | 732 | ||
702 | device = find_device(n); | 733 | device = find_device(n); |
703 | if(device == NULL) | 734 | if (device == NULL) |
704 | return -ENODEV; | 735 | return -ENODEV; |
705 | 736 | ||
706 | dev = device->dev; | 737 | dev = device->dev; |
707 | lp = dev->priv; | 738 | lp = dev->priv; |
708 | if(lp->fd > 0) | 739 | if (lp->fd > 0) |
709 | return -EBUSY; | 740 | return -EBUSY; |
710 | unregister_netdev(dev); | 741 | unregister_netdev(dev); |
711 | platform_device_unregister(&device->pdev); | 742 | platform_device_unregister(&device->pdev); |
@@ -731,13 +762,13 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event, | |||
731 | void (*proc)(unsigned char *, unsigned char *, void *); | 762 | void (*proc)(unsigned char *, unsigned char *, void *); |
732 | unsigned char addr_buf[4], netmask_buf[4]; | 763 | unsigned char addr_buf[4], netmask_buf[4]; |
733 | 764 | ||
734 | if(dev->open != uml_net_open) | 765 | if (dev->open != uml_net_open) |
735 | return NOTIFY_DONE; | 766 | return NOTIFY_DONE; |
736 | 767 | ||
737 | lp = dev->priv; | 768 | lp = dev->priv; |
738 | 769 | ||
739 | proc = NULL; | 770 | proc = NULL; |
740 | switch (event){ | 771 | switch (event) { |
741 | case NETDEV_UP: | 772 | case NETDEV_UP: |
742 | proc = lp->add_address; | 773 | proc = lp->add_address; |
743 | break; | 774 | break; |
@@ -745,7 +776,7 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event, | |||
745 | proc = lp->delete_address; | 776 | proc = lp->delete_address; |
746 | break; | 777 | break; |
747 | } | 778 | } |
748 | if(proc != NULL){ | 779 | if (proc != NULL) { |
749 | memcpy(addr_buf, &ifa->ifa_address, sizeof(addr_buf)); | 780 | memcpy(addr_buf, &ifa->ifa_address, sizeof(addr_buf)); |
750 | memcpy(netmask_buf, &ifa->ifa_mask, sizeof(netmask_buf)); | 781 | memcpy(netmask_buf, &ifa->ifa_mask, sizeof(netmask_buf)); |
751 | (*proc)(addr_buf, netmask_buf, &lp->user); | 782 | (*proc)(addr_buf, netmask_buf, &lp->user); |
@@ -773,13 +804,13 @@ static int uml_net_init(void) | |||
773 | * addresses which have already been set up get handled properly. | 804 | * addresses which have already been set up get handled properly. |
774 | */ | 805 | */ |
775 | spin_lock(&opened_lock); | 806 | spin_lock(&opened_lock); |
776 | list_for_each(ele, &opened){ | 807 | list_for_each(ele, &opened) { |
777 | lp = list_entry(ele, struct uml_net_private, list); | 808 | lp = list_entry(ele, struct uml_net_private, list); |
778 | ip = lp->dev->ip_ptr; | 809 | ip = lp->dev->ip_ptr; |
779 | if(ip == NULL) | 810 | if (ip == NULL) |
780 | continue; | 811 | continue; |
781 | in = ip->ifa_list; | 812 | in = ip->ifa_list; |
782 | while(in != NULL){ | 813 | while (in != NULL) { |
783 | uml_inetaddr_event(NULL, NETDEV_UP, in); | 814 | uml_inetaddr_event(NULL, NETDEV_UP, in); |
784 | in = in->ifa_next; | 815 | in = in->ifa_next; |
785 | } | 816 | } |
@@ -797,12 +828,12 @@ static void close_devices(void) | |||
797 | struct uml_net_private *lp; | 828 | struct uml_net_private *lp; |
798 | 829 | ||
799 | spin_lock(&opened_lock); | 830 | spin_lock(&opened_lock); |
800 | list_for_each(ele, &opened){ | 831 | list_for_each(ele, &opened) { |
801 | lp = list_entry(ele, struct uml_net_private, list); | 832 | lp = list_entry(ele, struct uml_net_private, list); |
802 | free_irq(lp->dev->irq, lp->dev); | 833 | free_irq(lp->dev->irq, lp->dev); |
803 | if((lp->close != NULL) && (lp->fd >= 0)) | 834 | if ((lp->close != NULL) && (lp->fd >= 0)) |
804 | (*lp->close)(lp->fd, &lp->user); | 835 | (*lp->close)(lp->fd, &lp->user); |
805 | if(lp->remove != NULL) | 836 | if (lp->remove != NULL) |
806 | (*lp->remove)(&lp->user); | 837 | (*lp->remove)(&lp->user); |
807 | } | 838 | } |
808 | spin_unlock(&opened_lock); | 839 | spin_unlock(&opened_lock); |
@@ -810,19 +841,6 @@ static void close_devices(void) | |||
810 | 841 | ||
811 | __uml_exitcall(close_devices); | 842 | __uml_exitcall(close_devices); |
812 | 843 | ||
813 | struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra) | ||
814 | { | ||
815 | if((skb != NULL) && (skb_tailroom(skb) < extra)){ | ||
816 | struct sk_buff *skb2; | ||
817 | |||
818 | skb2 = skb_copy_expand(skb, 0, extra, GFP_ATOMIC); | ||
819 | dev_kfree_skb(skb); | ||
820 | skb = skb2; | ||
821 | } | ||
822 | if(skb != NULL) skb_put(skb, extra); | ||
823 | return(skb); | ||
824 | } | ||
825 | |||
826 | void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, | 844 | void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, |
827 | void *), | 845 | void *), |
828 | void *arg) | 846 | void *arg) |
@@ -832,9 +850,9 @@ void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, | |||
832 | struct in_ifaddr *in; | 850 | struct in_ifaddr *in; |
833 | unsigned char address[4], netmask[4]; | 851 | unsigned char address[4], netmask[4]; |
834 | 852 | ||
835 | if(ip == NULL) return; | 853 | if (ip == NULL) return; |
836 | in = ip->ifa_list; | 854 | in = ip->ifa_list; |
837 | while(in != NULL){ | 855 | while (in != NULL) { |
838 | memcpy(address, &in->ifa_address, sizeof(address)); | 856 | memcpy(address, &in->ifa_address, sizeof(address)); |
839 | memcpy(netmask, &in->ifa_mask, sizeof(netmask)); | 857 | memcpy(netmask, &in->ifa_mask, sizeof(netmask)); |
840 | (*cb)(address, netmask, arg); | 858 | (*cb)(address, netmask, arg); |
@@ -849,15 +867,15 @@ int dev_netmask(void *d, void *m) | |||
849 | struct in_ifaddr *in; | 867 | struct in_ifaddr *in; |
850 | __be32 *mask_out = m; | 868 | __be32 *mask_out = m; |
851 | 869 | ||
852 | if(ip == NULL) | 870 | if (ip == NULL) |
853 | return(1); | 871 | return 1; |
854 | 872 | ||
855 | in = ip->ifa_list; | 873 | in = ip->ifa_list; |
856 | if(in == NULL) | 874 | if (in == NULL) |
857 | return(1); | 875 | return 1; |
858 | 876 | ||
859 | *mask_out = in->ifa_mask; | 877 | *mask_out = in->ifa_mask; |
860 | return(0); | 878 | return 0; |
861 | } | 879 | } |
862 | 880 | ||
863 | void *get_output_buffer(int *len_out) | 881 | void *get_output_buffer(int *len_out) |
@@ -865,7 +883,7 @@ void *get_output_buffer(int *len_out) | |||
865 | void *ret; | 883 | void *ret; |
866 | 884 | ||
867 | ret = (void *) __get_free_pages(GFP_KERNEL, 0); | 885 | ret = (void *) __get_free_pages(GFP_KERNEL, 0); |
868 | if(ret) *len_out = PAGE_SIZE; | 886 | if (ret) *len_out = PAGE_SIZE; |
869 | else *len_out = 0; | 887 | else *len_out = 0; |
870 | return ret; | 888 | return ret; |
871 | } | 889 | } |
@@ -881,16 +899,16 @@ int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out, | |||
881 | char *remain; | 899 | char *remain; |
882 | 900 | ||
883 | remain = split_if_spec(str, dev_name, mac_out, gate_addr, NULL); | 901 | remain = split_if_spec(str, dev_name, mac_out, gate_addr, NULL); |
884 | if(remain != NULL){ | 902 | if (remain != NULL) { |
885 | printk("tap_setup_common - Extra garbage on specification : " | 903 | printk(KERN_ERR "tap_setup_common - Extra garbage on " |
886 | "'%s'\n", remain); | 904 | "specification : '%s'\n", remain); |
887 | return(1); | 905 | return 1; |
888 | } | 906 | } |
889 | 907 | ||
890 | return(0); | 908 | return 0; |
891 | } | 909 | } |
892 | 910 | ||
893 | unsigned short eth_protocol(struct sk_buff *skb) | 911 | unsigned short eth_protocol(struct sk_buff *skb) |
894 | { | 912 | { |
895 | return(eth_type_trans(skb, skb->dev)); | 913 | return eth_type_trans(skb, skb->dev); |
896 | } | 914 | } |
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c index da946e3e1bf2..90d7f2e8ead8 100644 --- a/arch/um/drivers/net_user.c +++ b/arch/um/drivers/net_user.c | |||
@@ -1,34 +1,32 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stddef.h> | ||
7 | #include <stdarg.h> | ||
8 | #include <unistd.h> | ||
9 | #include <stdio.h> | 6 | #include <stdio.h> |
7 | #include <unistd.h> | ||
8 | #include <stdarg.h> | ||
10 | #include <errno.h> | 9 | #include <errno.h> |
11 | #include <stdlib.h> | 10 | #include <stddef.h> |
12 | #include <string.h> | 11 | #include <string.h> |
13 | #include <sys/socket.h> | 12 | #include <sys/socket.h> |
14 | #include <sys/wait.h> | 13 | #include <sys/wait.h> |
15 | #include <sys/time.h> | ||
16 | #include "user.h" | ||
17 | #include "kern_util.h" | ||
18 | #include "net_user.h" | 14 | #include "net_user.h" |
15 | #include "kern_constants.h" | ||
19 | #include "os.h" | 16 | #include "os.h" |
20 | #include "um_malloc.h" | 17 | #include "um_malloc.h" |
21 | #include "kern_constants.h" | 18 | #include "user.h" |
22 | 19 | ||
23 | int tap_open_common(void *dev, char *gate_addr) | 20 | int tap_open_common(void *dev, char *gate_addr) |
24 | { | 21 | { |
25 | int tap_addr[4]; | 22 | int tap_addr[4]; |
26 | 23 | ||
27 | if(gate_addr == NULL) | 24 | if (gate_addr == NULL) |
28 | return 0; | 25 | return 0; |
29 | if(sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], | 26 | if (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], |
30 | &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4){ | 27 | &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4) { |
31 | printk("Invalid tap IP address - '%s'\n", gate_addr); | 28 | printk(UM_KERN_ERR "Invalid tap IP address - '%s'\n", |
29 | gate_addr); | ||
32 | return -EINVAL; | 30 | return -EINVAL; |
33 | } | 31 | } |
34 | return 0; | 32 | return 0; |
@@ -38,15 +36,15 @@ void tap_check_ips(char *gate_addr, unsigned char *eth_addr) | |||
38 | { | 36 | { |
39 | int tap_addr[4]; | 37 | int tap_addr[4]; |
40 | 38 | ||
41 | if((gate_addr != NULL) && | 39 | if ((gate_addr != NULL) && |
42 | (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], | 40 | (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], |
43 | &tap_addr[1], &tap_addr[2], &tap_addr[3]) == 4) && | 41 | &tap_addr[1], &tap_addr[2], &tap_addr[3]) == 4) && |
44 | (eth_addr[0] == tap_addr[0]) && | 42 | (eth_addr[0] == tap_addr[0]) && |
45 | (eth_addr[1] == tap_addr[1]) && | 43 | (eth_addr[1] == tap_addr[1]) && |
46 | (eth_addr[2] == tap_addr[2]) && | 44 | (eth_addr[2] == tap_addr[2]) && |
47 | (eth_addr[3] == tap_addr[3])){ | 45 | (eth_addr[3] == tap_addr[3])) { |
48 | printk("The tap IP address and the UML eth IP address" | 46 | printk(UM_KERN_ERR "The tap IP address and the UML eth IP " |
49 | " must be different\n"); | 47 | "address must be different\n"); |
50 | } | 48 | } |
51 | } | 49 | } |
52 | 50 | ||
@@ -57,24 +55,28 @@ void read_output(int fd, char *output, int len) | |||
57 | char c; | 55 | char c; |
58 | char *str; | 56 | char *str; |
59 | 57 | ||
60 | if(output == NULL){ | 58 | if (output == NULL) { |
61 | output = &c; | 59 | output = &c; |
62 | len = sizeof(c); | 60 | len = sizeof(c); |
63 | } | 61 | } |
64 | 62 | ||
65 | *output = '\0'; | 63 | *output = '\0'; |
66 | ret = os_read_file(fd, &remain, sizeof(remain)); | 64 | ret = read(fd, &remain, sizeof(remain)); |
67 | 65 | ||
68 | if (ret != sizeof(remain)) { | 66 | if (ret != sizeof(remain)) { |
67 | if (ret < 0) | ||
68 | ret = -errno; | ||
69 | expected = sizeof(remain); | 69 | expected = sizeof(remain); |
70 | str = "length"; | 70 | str = "length"; |
71 | goto err; | 71 | goto err; |
72 | } | 72 | } |
73 | 73 | ||
74 | while(remain != 0){ | 74 | while (remain != 0) { |
75 | expected = (remain < len) ? remain : len; | 75 | expected = (remain < len) ? remain : len; |
76 | ret = os_read_file(fd, output, expected); | 76 | ret = read(fd, output, expected); |
77 | if (ret != expected) { | 77 | if (ret != expected) { |
78 | if (ret < 0) | ||
79 | ret = -errno; | ||
78 | str = "data"; | 80 | str = "data"; |
79 | goto err; | 81 | goto err; |
80 | } | 82 | } |
@@ -85,20 +87,22 @@ void read_output(int fd, char *output, int len) | |||
85 | 87 | ||
86 | err: | 88 | err: |
87 | if (ret < 0) | 89 | if (ret < 0) |
88 | printk("read_output - read of %s failed, errno = %d\n", str, -ret); | 90 | printk(UM_KERN_ERR "read_output - read of %s failed, " |
91 | "errno = %d\n", str, -ret); | ||
89 | else | 92 | else |
90 | printk("read_output - read of %s failed, read only %d of %d bytes\n", str, ret, expected); | 93 | printk(UM_KERN_ERR "read_output - read of %s failed, read only " |
94 | "%d of %d bytes\n", str, ret, expected); | ||
91 | } | 95 | } |
92 | 96 | ||
93 | int net_read(int fd, void *buf, int len) | 97 | int net_read(int fd, void *buf, int len) |
94 | { | 98 | { |
95 | int n; | 99 | int n; |
96 | 100 | ||
97 | n = os_read_file(fd, buf, len); | 101 | n = read(fd, buf, len); |
98 | 102 | ||
99 | if(n == -EAGAIN) | 103 | if ((n < 0) && (errno == EAGAIN)) |
100 | return 0; | 104 | return 0; |
101 | else if(n == 0) | 105 | else if (n == 0) |
102 | return -ENOTCONN; | 106 | return -ENOTCONN; |
103 | return n; | 107 | return n; |
104 | } | 108 | } |
@@ -108,12 +112,12 @@ int net_recvfrom(int fd, void *buf, int len) | |||
108 | int n; | 112 | int n; |
109 | 113 | ||
110 | CATCH_EINTR(n = recvfrom(fd, buf, len, 0, NULL, NULL)); | 114 | CATCH_EINTR(n = recvfrom(fd, buf, len, 0, NULL, NULL)); |
111 | if(n < 0){ | 115 | if (n < 0) { |
112 | if(errno == EAGAIN) | 116 | if (errno == EAGAIN) |
113 | return 0; | 117 | return 0; |
114 | return -errno; | 118 | return -errno; |
115 | } | 119 | } |
116 | else if(n == 0) | 120 | else if (n == 0) |
117 | return -ENOTCONN; | 121 | return -ENOTCONN; |
118 | return n; | 122 | return n; |
119 | } | 123 | } |
@@ -122,11 +126,11 @@ int net_write(int fd, void *buf, int len) | |||
122 | { | 126 | { |
123 | int n; | 127 | int n; |
124 | 128 | ||
125 | n = os_write_file(fd, buf, len); | 129 | n = write(fd, buf, len); |
126 | 130 | ||
127 | if(n == -EAGAIN) | 131 | if ((n < 0) && (errno == EAGAIN)) |
128 | return 0; | 132 | return 0; |
129 | else if(n == 0) | 133 | else if (n == 0) |
130 | return -ENOTCONN; | 134 | return -ENOTCONN; |
131 | return n; | 135 | return n; |
132 | } | 136 | } |
@@ -136,12 +140,12 @@ int net_send(int fd, void *buf, int len) | |||
136 | int n; | 140 | int n; |
137 | 141 | ||
138 | CATCH_EINTR(n = send(fd, buf, len, 0)); | 142 | CATCH_EINTR(n = send(fd, buf, len, 0)); |
139 | if(n < 0){ | 143 | if (n < 0) { |
140 | if(errno == EAGAIN) | 144 | if (errno == EAGAIN) |
141 | return 0; | 145 | return 0; |
142 | return -errno; | 146 | return -errno; |
143 | } | 147 | } |
144 | else if(n == 0) | 148 | else if (n == 0) |
145 | return -ENOTCONN; | 149 | return -ENOTCONN; |
146 | return n; | 150 | return n; |
147 | } | 151 | } |
@@ -152,12 +156,12 @@ int net_sendto(int fd, void *buf, int len, void *to, int sock_len) | |||
152 | 156 | ||
153 | CATCH_EINTR(n = sendto(fd, buf, len, 0, (struct sockaddr *) to, | 157 | CATCH_EINTR(n = sendto(fd, buf, len, 0, (struct sockaddr *) to, |
154 | sock_len)); | 158 | sock_len)); |
155 | if(n < 0){ | 159 | if (n < 0) { |
156 | if(errno == EAGAIN) | 160 | if (errno == EAGAIN) |
157 | return 0; | 161 | return 0; |
158 | return -errno; | 162 | return -errno; |
159 | } | 163 | } |
160 | else if(n == 0) | 164 | else if (n == 0) |
161 | return -ENOTCONN; | 165 | return -ENOTCONN; |
162 | return n; | 166 | return n; |
163 | } | 167 | } |
@@ -171,7 +175,7 @@ static void change_pre_exec(void *arg) | |||
171 | { | 175 | { |
172 | struct change_pre_exec_data *data = arg; | 176 | struct change_pre_exec_data *data = arg; |
173 | 177 | ||
174 | os_close_file(data->close_me); | 178 | close(data->close_me); |
175 | dup2(data->stdout, 1); | 179 | dup2(data->stdout, 1); |
176 | } | 180 | } |
177 | 181 | ||
@@ -181,8 +185,9 @@ static int change_tramp(char **argv, char *output, int output_len) | |||
181 | struct change_pre_exec_data pe_data; | 185 | struct change_pre_exec_data pe_data; |
182 | 186 | ||
183 | err = os_pipe(fds, 1, 0); | 187 | err = os_pipe(fds, 1, 0); |
184 | if(err < 0){ | 188 | if (err < 0) { |
185 | printk("change_tramp - pipe failed, err = %d\n", -err); | 189 | printk(UM_KERN_ERR "change_tramp - pipe failed, err = %d\n", |
190 | -err); | ||
186 | return err; | 191 | return err; |
187 | } | 192 | } |
188 | pe_data.close_me = fds[0]; | 193 | pe_data.close_me = fds[0]; |
@@ -192,8 +197,8 @@ static int change_tramp(char **argv, char *output, int output_len) | |||
192 | if (pid > 0) /* Avoid hang as we won't get data in failure case. */ | 197 | if (pid > 0) /* Avoid hang as we won't get data in failure case. */ |
193 | read_output(fds[0], output, output_len); | 198 | read_output(fds[0], output, output_len); |
194 | 199 | ||
195 | os_close_file(fds[0]); | 200 | close(fds[0]); |
196 | os_close_file(fds[1]); | 201 | close(fds[1]); |
197 | 202 | ||
198 | if (pid > 0) | 203 | if (pid > 0) |
199 | CATCH_EINTR(err = waitpid(pid, NULL, 0)); | 204 | CATCH_EINTR(err = waitpid(pid, NULL, 0)); |
@@ -206,25 +211,26 @@ static void change(char *dev, char *what, unsigned char *addr, | |||
206 | char addr_buf[sizeof("255.255.255.255\0")]; | 211 | char addr_buf[sizeof("255.255.255.255\0")]; |
207 | char netmask_buf[sizeof("255.255.255.255\0")]; | 212 | char netmask_buf[sizeof("255.255.255.255\0")]; |
208 | char version[sizeof("nnnnn\0")]; | 213 | char version[sizeof("nnnnn\0")]; |
209 | char *argv[] = { "uml_net", version, what, dev, addr_buf, | 214 | char *argv[] = { "uml_net", version, what, dev, addr_buf, |
210 | netmask_buf, NULL }; | 215 | netmask_buf, NULL }; |
211 | char *output; | 216 | char *output; |
212 | int output_len, pid; | 217 | int output_len, pid; |
213 | 218 | ||
214 | sprintf(version, "%d", UML_NET_VERSION); | 219 | sprintf(version, "%d", UML_NET_VERSION); |
215 | sprintf(addr_buf, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); | 220 | sprintf(addr_buf, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); |
216 | sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1], | 221 | sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1], |
217 | netmask[2], netmask[3]); | 222 | netmask[2], netmask[3]); |
218 | 223 | ||
219 | output_len = UM_KERN_PAGE_SIZE; | 224 | output_len = UM_KERN_PAGE_SIZE; |
220 | output = kmalloc(output_len, UM_GFP_KERNEL); | 225 | output = kmalloc(output_len, UM_GFP_KERNEL); |
221 | if(output == NULL) | 226 | if (output == NULL) |
222 | printk("change : failed to allocate output buffer\n"); | 227 | printk(UM_KERN_ERR "change : failed to allocate output " |
228 | "buffer\n"); | ||
223 | 229 | ||
224 | pid = change_tramp(argv, output, output_len); | 230 | pid = change_tramp(argv, output, output_len); |
225 | if(pid < 0) return; | 231 | if (pid < 0) return; |
226 | 232 | ||
227 | if(output != NULL){ | 233 | if (output != NULL) { |
228 | printk("%s", output); | 234 | printk("%s", output); |
229 | kfree(output); | 235 | kfree(output); |
230 | } | 236 | } |
@@ -246,13 +252,13 @@ char *split_if_spec(char *str, ...) | |||
246 | va_list ap; | 252 | va_list ap; |
247 | 253 | ||
248 | va_start(ap, str); | 254 | va_start(ap, str); |
249 | while((arg = va_arg(ap, char **)) != NULL){ | 255 | while ((arg = va_arg(ap, char **)) != NULL) { |
250 | if(*str == '\0') | 256 | if (*str == '\0') |
251 | return NULL; | 257 | return NULL; |
252 | end = strchr(str, ','); | 258 | end = strchr(str, ','); |
253 | if(end != str) | 259 | if (end != str) |
254 | *arg = str; | 260 | *arg = str; |
255 | if(end == NULL) | 261 | if (end == NULL) |
256 | return NULL; | 262 | return NULL; |
257 | *end++ = '\0'; | 263 | *end++ = '\0'; |
258 | str = end; | 264 | str = end; |
diff --git a/arch/um/drivers/null.c b/arch/um/drivers/null.c index 9016c68beee8..21ad3d7932b3 100644 --- a/arch/um/drivers/null.c +++ b/arch/um/drivers/null.c | |||
@@ -1,10 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdlib.h> | 6 | #include <stddef.h> |
7 | #include <errno.h> | 7 | #include <errno.h> |
8 | #include <fcntl.h> | ||
8 | #include "chan_user.h" | 9 | #include "chan_user.h" |
9 | #include "os.h" | 10 | #include "os.h" |
10 | 11 | ||
@@ -13,19 +14,23 @@ static int null_chan; | |||
13 | 14 | ||
14 | static void *null_init(char *str, int device, const struct chan_opts *opts) | 15 | static void *null_init(char *str, int device, const struct chan_opts *opts) |
15 | { | 16 | { |
16 | return(&null_chan); | 17 | return &null_chan; |
17 | } | 18 | } |
18 | 19 | ||
19 | static int null_open(int input, int output, int primary, void *d, | 20 | static int null_open(int input, int output, int primary, void *d, |
20 | char **dev_out) | 21 | char **dev_out) |
21 | { | 22 | { |
23 | int fd; | ||
24 | |||
22 | *dev_out = NULL; | 25 | *dev_out = NULL; |
23 | return(os_open_file(DEV_NULL, of_rdwr(OPENFLAGS()), 0)); | 26 | |
27 | fd = open(DEV_NULL, O_RDWR); | ||
28 | return (fd < 0) ? -errno : fd; | ||
24 | } | 29 | } |
25 | 30 | ||
26 | static int null_read(int fd, char *c_out, void *unused) | 31 | static int null_read(int fd, char *c_out, void *unused) |
27 | { | 32 | { |
28 | return(-ENODEV); | 33 | return -ENODEV; |
29 | } | 34 | } |
30 | 35 | ||
31 | static void null_free(void *data) | 36 | static void null_free(void *data) |
@@ -44,14 +49,3 @@ const struct chan_ops null_ops = { | |||
44 | .free = null_free, | 49 | .free = null_free, |
45 | .winch = 0, | 50 | .winch = 0, |
46 | }; | 51 | }; |
47 | |||
48 | /* | ||
49 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
50 | * Emacs will notice this stuff at the end of the file and automatically | ||
51 | * adjust the settings for this buffer only. This must remain at the end | ||
52 | * of the file. | ||
53 | * --------------------------------------------------------------------------- | ||
54 | * Local variables: | ||
55 | * c-file-style: "linux" | ||
56 | * End: | ||
57 | */ | ||
diff --git a/arch/um/drivers/pcap_kern.c b/arch/um/drivers/pcap_kern.c index c329931673d6..3a750dd39be1 100644 --- a/arch/um/drivers/pcap_kern.c +++ b/arch/um/drivers/pcap_kern.c | |||
@@ -1,13 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike <jdike@karaya.com> | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL. | 3 | * Licensed under the GPL. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/init.h" | 6 | #include "linux/init.h" |
7 | #include "linux/netdevice.h" | 7 | #include <linux/netdevice.h> |
8 | #include "linux/etherdevice.h" | ||
9 | #include "net_kern.h" | 8 | #include "net_kern.h" |
10 | #include "net_user.h" | ||
11 | #include "pcap_user.h" | 9 | #include "pcap_user.h" |
12 | 10 | ||
13 | struct pcap_init { | 11 | struct pcap_init { |
@@ -33,19 +31,14 @@ void pcap_init(struct net_device *dev, void *data) | |||
33 | printk("pcap backend, host interface %s\n", ppri->host_if); | 31 | printk("pcap backend, host interface %s\n", ppri->host_if); |
34 | } | 32 | } |
35 | 33 | ||
36 | static int pcap_read(int fd, struct sk_buff **skb, | 34 | static int pcap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) |
37 | struct uml_net_private *lp) | ||
38 | { | 35 | { |
39 | *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); | 36 | return pcap_user_read(fd, skb_mac_header(skb), |
40 | if(*skb == NULL) | 37 | skb->dev->mtu + ETH_HEADER_OTHER, |
41 | return -ENOMEM; | ||
42 | |||
43 | return pcap_user_read(fd, skb_mac_header(*skb), | ||
44 | (*skb)->dev->mtu + ETH_HEADER_OTHER, | ||
45 | (struct pcap_data *) &lp->user); | 38 | (struct pcap_data *) &lp->user); |
46 | } | 39 | } |
47 | 40 | ||
48 | static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) | 41 | static int pcap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) |
49 | { | 42 | { |
50 | return -EPERM; | 43 | return -EPERM; |
51 | } | 44 | } |
@@ -71,28 +64,29 @@ int pcap_setup(char *str, char **mac_out, void *data) | |||
71 | 64 | ||
72 | remain = split_if_spec(str, &host_if, &init->filter, | 65 | remain = split_if_spec(str, &host_if, &init->filter, |
73 | &options[0], &options[1], mac_out, NULL); | 66 | &options[0], &options[1], mac_out, NULL); |
74 | if(remain != NULL){ | 67 | if (remain != NULL) { |
75 | printk(KERN_ERR "pcap_setup - Extra garbage on " | 68 | printk(KERN_ERR "pcap_setup - Extra garbage on " |
76 | "specification : '%s'\n", remain); | 69 | "specification : '%s'\n", remain); |
77 | return 0; | 70 | return 0; |
78 | } | 71 | } |
79 | 72 | ||
80 | if(host_if != NULL) | 73 | if (host_if != NULL) |
81 | init->host_if = host_if; | 74 | init->host_if = host_if; |
82 | 75 | ||
83 | for(i = 0; i < ARRAY_SIZE(options); i++){ | 76 | for (i = 0; i < ARRAY_SIZE(options); i++) { |
84 | if(options[i] == NULL) | 77 | if (options[i] == NULL) |
85 | continue; | 78 | continue; |
86 | if(!strcmp(options[i], "promisc")) | 79 | if (!strcmp(options[i], "promisc")) |
87 | init->promisc = 1; | 80 | init->promisc = 1; |
88 | else if(!strcmp(options[i], "nopromisc")) | 81 | else if (!strcmp(options[i], "nopromisc")) |
89 | init->promisc = 0; | 82 | init->promisc = 0; |
90 | else if(!strcmp(options[i], "optimize")) | 83 | else if (!strcmp(options[i], "optimize")) |
91 | init->optimize = 1; | 84 | init->optimize = 1; |
92 | else if(!strcmp(options[i], "nooptimize")) | 85 | else if (!strcmp(options[i], "nooptimize")) |
93 | init->optimize = 0; | 86 | init->optimize = 0; |
94 | else { | 87 | else { |
95 | printk("pcap_setup : bad option - '%s'\n", options[i]); | 88 | printk(KERN_ERR "pcap_setup : bad option - '%s'\n", |
89 | options[i]); | ||
96 | return 0; | 90 | return 0; |
97 | } | 91 | } |
98 | } | 92 | } |
diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c index 1316456e2a28..e9809356c530 100644 --- a/arch/um/drivers/pcap_user.c +++ b/arch/um/drivers/pcap_user.c | |||
@@ -1,21 +1,17 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike <jdike@karaya.com> | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL. | 3 | * Licensed under the GPL. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <unistd.h> | ||
7 | #include <stdlib.h> | ||
8 | #include <string.h> | ||
9 | #include <errno.h> | 6 | #include <errno.h> |
10 | #include <pcap.h> | 7 | #include <pcap.h> |
8 | #include <string.h> | ||
11 | #include <asm/types.h> | 9 | #include <asm/types.h> |
12 | #include "net_user.h" | 10 | #include "net_user.h" |
13 | #include "pcap_user.h" | 11 | #include "pcap_user.h" |
14 | #include "user.h" | ||
15 | #include "um_malloc.h" | ||
16 | #include "kern_constants.h" | 12 | #include "kern_constants.h" |
17 | 13 | #include "um_malloc.h" | |
18 | #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) | 14 | #include "user.h" |
19 | 15 | ||
20 | #define PCAP_FD(p) (*(int *)(p)) | 16 | #define PCAP_FD(p) (*(int *)(p)) |
21 | 17 | ||
@@ -25,8 +21,9 @@ static int pcap_user_init(void *data, void *dev) | |||
25 | pcap_t *p; | 21 | pcap_t *p; |
26 | char errors[PCAP_ERRBUF_SIZE]; | 22 | char errors[PCAP_ERRBUF_SIZE]; |
27 | 23 | ||
28 | p = pcap_open_live(pri->host_if, MAX_PACKET, pri->promisc, 0, errors); | 24 | p = pcap_open_live(pri->host_if, ETH_MAX_PACKET + ETH_HEADER_OTHER, |
29 | if(p == NULL){ | 25 | pri->promisc, 0, errors); |
26 | if (p == NULL) { | ||
30 | printk(UM_KERN_ERR "pcap_user_init : pcap_open_live failed - " | 27 | printk(UM_KERN_ERR "pcap_user_init : pcap_open_live failed - " |
31 | "'%s'\n", errors); | 28 | "'%s'\n", errors); |
32 | return -EINVAL; | 29 | return -EINVAL; |
@@ -43,50 +40,55 @@ static int pcap_open(void *data) | |||
43 | __u32 netmask; | 40 | __u32 netmask; |
44 | int err; | 41 | int err; |
45 | 42 | ||
46 | if(pri->pcap == NULL) | 43 | if (pri->pcap == NULL) |
47 | return -ENODEV; | 44 | return -ENODEV; |
48 | 45 | ||
49 | if(pri->filter != NULL){ | 46 | if (pri->filter != NULL) { |
50 | err = dev_netmask(pri->dev, &netmask); | 47 | err = dev_netmask(pri->dev, &netmask); |
51 | if(err < 0){ | 48 | if (err < 0) { |
52 | printk(UM_KERN_ERR "pcap_open : dev_netmask failed\n"); | 49 | printk(UM_KERN_ERR "pcap_open : dev_netmask failed\n"); |
53 | return -EIO; | 50 | return -EIO; |
54 | } | 51 | } |
55 | 52 | ||
56 | pri->compiled = kmalloc(sizeof(struct bpf_program), UM_GFP_KERNEL); | 53 | pri->compiled = kmalloc(sizeof(struct bpf_program), |
57 | if(pri->compiled == NULL){ | 54 | UM_GFP_KERNEL); |
55 | if (pri->compiled == NULL) { | ||
58 | printk(UM_KERN_ERR "pcap_open : kmalloc failed\n"); | 56 | printk(UM_KERN_ERR "pcap_open : kmalloc failed\n"); |
59 | return -ENOMEM; | 57 | return -ENOMEM; |
60 | } | 58 | } |
61 | 59 | ||
62 | err = pcap_compile(pri->pcap, | 60 | err = pcap_compile(pri->pcap, |
63 | (struct bpf_program *) pri->compiled, | 61 | (struct bpf_program *) pri->compiled, |
64 | pri->filter, pri->optimize, netmask); | 62 | pri->filter, pri->optimize, netmask); |
65 | if(err < 0){ | 63 | if (err < 0) { |
66 | printk(UM_KERN_ERR "pcap_open : pcap_compile failed - " | 64 | printk(UM_KERN_ERR "pcap_open : pcap_compile failed - " |
67 | "'%s'\n", pcap_geterr(pri->pcap)); | 65 | "'%s'\n", pcap_geterr(pri->pcap)); |
68 | return -EIO; | 66 | goto out; |
69 | } | 67 | } |
70 | 68 | ||
71 | err = pcap_setfilter(pri->pcap, pri->compiled); | 69 | err = pcap_setfilter(pri->pcap, pri->compiled); |
72 | if(err < 0){ | 70 | if (err < 0) { |
73 | printk(UM_KERN_ERR "pcap_open : pcap_setfilter " | 71 | printk(UM_KERN_ERR "pcap_open : pcap_setfilter " |
74 | "failed - '%s'\n", pcap_geterr(pri->pcap)); | 72 | "failed - '%s'\n", pcap_geterr(pri->pcap)); |
75 | return -EIO; | 73 | goto out; |
76 | } | 74 | } |
77 | } | 75 | } |
78 | 76 | ||
79 | return PCAP_FD(pri->pcap); | 77 | return PCAP_FD(pri->pcap); |
78 | |||
79 | out: | ||
80 | kfree(pri->compiled); | ||
81 | return -EIO; | ||
80 | } | 82 | } |
81 | 83 | ||
82 | static void pcap_remove(void *data) | 84 | static void pcap_remove(void *data) |
83 | { | 85 | { |
84 | struct pcap_data *pri = data; | 86 | struct pcap_data *pri = data; |
85 | 87 | ||
86 | if(pri->compiled != NULL) | 88 | if (pri->compiled != NULL) |
87 | pcap_freecode(pri->compiled); | 89 | pcap_freecode(pri->compiled); |
88 | 90 | ||
89 | if(pri->pcap != NULL) | 91 | if (pri->pcap != NULL) |
90 | pcap_close(pri->pcap); | 92 | pcap_close(pri->pcap); |
91 | } | 93 | } |
92 | 94 | ||
@@ -95,7 +97,7 @@ struct pcap_handler_data { | |||
95 | int len; | 97 | int len; |
96 | }; | 98 | }; |
97 | 99 | ||
98 | static void handler(u_char *data, const struct pcap_pkthdr *header, | 100 | static void handler(u_char *data, const struct pcap_pkthdr *header, |
99 | const u_char *packet) | 101 | const u_char *packet) |
100 | { | 102 | { |
101 | int len; | 103 | int len; |
@@ -115,12 +117,12 @@ int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri) | |||
115 | int n; | 117 | int n; |
116 | 118 | ||
117 | n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata); | 119 | n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata); |
118 | if(n < 0){ | 120 | if (n < 0) { |
119 | printk(UM_KERN_ERR "pcap_dispatch failed - %s\n", | 121 | printk(UM_KERN_ERR "pcap_dispatch failed - %s\n", |
120 | pcap_geterr(pri->pcap)); | 122 | pcap_geterr(pri->pcap)); |
121 | return -EIO; | 123 | return -EIO; |
122 | } | 124 | } |
123 | else if(n == 0) | 125 | else if (n == 0) |
124 | return 0; | 126 | return 0; |
125 | return hdata.len; | 127 | return hdata.len; |
126 | } | 128 | } |
@@ -130,8 +132,8 @@ const struct net_user_info pcap_user_info = { | |||
130 | .open = pcap_open, | 132 | .open = pcap_open, |
131 | .close = NULL, | 133 | .close = NULL, |
132 | .remove = pcap_remove, | 134 | .remove = pcap_remove, |
133 | .set_mtu = NULL, | ||
134 | .add_address = NULL, | 135 | .add_address = NULL, |
135 | .delete_address = NULL, | 136 | .delete_address = NULL, |
136 | .max_packet = MAX_PACKET - ETH_HEADER_OTHER | 137 | .mtu = ETH_MAX_PACKET, |
138 | .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, | ||
137 | }; | 139 | }; |
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index 1c8efd95c421..330543b3129b 100644 --- a/arch/um/drivers/port_kern.c +++ b/arch/um/drivers/port_kern.c | |||
@@ -1,24 +1,16 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/list.h" | 6 | #include "linux/completion.h" |
7 | #include "linux/sched.h" | ||
8 | #include "linux/slab.h" | ||
9 | #include "linux/interrupt.h" | 7 | #include "linux/interrupt.h" |
10 | #include "linux/spinlock.h" | 8 | #include "linux/list.h" |
11 | #include "linux/errno.h" | ||
12 | #include "asm/atomic.h" | 9 | #include "asm/atomic.h" |
13 | #include "asm/semaphore.h" | ||
14 | #include "asm/errno.h" | ||
15 | #include "kern_util.h" | ||
16 | #include "kern.h" | ||
17 | #include "irq_user.h" | ||
18 | #include "irq_kern.h" | ||
19 | #include "port.h" | ||
20 | #include "init.h" | 10 | #include "init.h" |
11 | #include "irq_kern.h" | ||
21 | #include "os.h" | 12 | #include "os.h" |
13 | #include "port.h" | ||
22 | 14 | ||
23 | struct port_list { | 15 | struct port_list { |
24 | struct list_head list; | 16 | struct list_head list; |
@@ -53,8 +45,8 @@ static irqreturn_t pipe_interrupt(int irq, void *data) | |||
53 | int fd; | 45 | int fd; |
54 | 46 | ||
55 | fd = os_rcv_fd(conn->socket[0], &conn->helper_pid); | 47 | fd = os_rcv_fd(conn->socket[0], &conn->helper_pid); |
56 | if(fd < 0){ | 48 | if (fd < 0) { |
57 | if(fd == -EAGAIN) | 49 | if (fd == -EAGAIN) |
58 | return IRQ_NONE; | 50 | return IRQ_NONE; |
59 | 51 | ||
60 | printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", | 52 | printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", |
@@ -81,18 +73,18 @@ static irqreturn_t pipe_interrupt(int irq, void *data) | |||
81 | static int port_accept(struct port_list *port) | 73 | static int port_accept(struct port_list *port) |
82 | { | 74 | { |
83 | struct connection *conn; | 75 | struct connection *conn; |
84 | int fd, socket[2], pid, ret = 0; | 76 | int fd, socket[2], pid; |
85 | 77 | ||
86 | fd = port_connection(port->fd, socket, &pid); | 78 | fd = port_connection(port->fd, socket, &pid); |
87 | if(fd < 0){ | 79 | if (fd < 0) { |
88 | if(fd != -EAGAIN) | 80 | if (fd != -EAGAIN) |
89 | printk(KERN_ERR "port_accept : port_connection " | 81 | printk(KERN_ERR "port_accept : port_connection " |
90 | "returned %d\n", -fd); | 82 | "returned %d\n", -fd); |
91 | goto out; | 83 | goto out; |
92 | } | 84 | } |
93 | 85 | ||
94 | conn = kmalloc(sizeof(*conn), GFP_ATOMIC); | 86 | conn = kmalloc(sizeof(*conn), GFP_ATOMIC); |
95 | if(conn == NULL){ | 87 | if (conn == NULL) { |
96 | printk(KERN_ERR "port_accept : failed to allocate " | 88 | printk(KERN_ERR "port_accept : failed to allocate " |
97 | "connection\n"); | 89 | "connection\n"); |
98 | goto out_close; | 90 | goto out_close; |
@@ -104,17 +96,17 @@ static int port_accept(struct port_list *port) | |||
104 | .telnetd_pid = pid, | 96 | .telnetd_pid = pid, |
105 | .port = port }); | 97 | .port = port }); |
106 | 98 | ||
107 | if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, | 99 | if (um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, |
108 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, | 100 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, |
109 | "telnetd", conn)){ | 101 | "telnetd", conn)) { |
110 | printk(KERN_ERR "port_accept : failed to get IRQ for " | 102 | printk(KERN_ERR "port_accept : failed to get IRQ for " |
111 | "telnetd\n"); | 103 | "telnetd\n"); |
112 | goto out_free; | 104 | goto out_free; |
113 | } | 105 | } |
114 | 106 | ||
115 | if(atomic_read(&port->wait_count) == 0){ | 107 | if (atomic_read(&port->wait_count) == 0) { |
116 | os_write_file(fd, NO_WAITER_MSG, sizeof(NO_WAITER_MSG)); | 108 | os_write_file(fd, NO_WAITER_MSG, sizeof(NO_WAITER_MSG)); |
117 | printk("No one waiting for port\n"); | 109 | printk(KERN_ERR "No one waiting for port\n"); |
118 | } | 110 | } |
119 | list_add(&conn->list, &port->pending); | 111 | list_add(&conn->list, &port->pending); |
120 | return 1; | 112 | return 1; |
@@ -123,28 +115,29 @@ static int port_accept(struct port_list *port) | |||
123 | kfree(conn); | 115 | kfree(conn); |
124 | out_close: | 116 | out_close: |
125 | os_close_file(fd); | 117 | os_close_file(fd); |
126 | if(pid != -1) | 118 | os_kill_process(pid, 1); |
127 | os_kill_process(pid, 1); | ||
128 | out: | 119 | out: |
129 | return ret; | 120 | return 0; |
130 | } | 121 | } |
131 | 122 | ||
132 | static DECLARE_MUTEX(ports_sem); | 123 | static DECLARE_MUTEX(ports_sem); |
133 | static LIST_HEAD(ports); | 124 | static LIST_HEAD(ports); |
134 | 125 | ||
135 | void port_work_proc(struct work_struct *unused) | 126 | static void port_work_proc(struct work_struct *unused) |
136 | { | 127 | { |
137 | struct port_list *port; | 128 | struct port_list *port; |
138 | struct list_head *ele; | 129 | struct list_head *ele; |
139 | unsigned long flags; | 130 | unsigned long flags; |
140 | 131 | ||
141 | local_irq_save(flags); | 132 | local_irq_save(flags); |
142 | list_for_each(ele, &ports){ | 133 | list_for_each(ele, &ports) { |
143 | port = list_entry(ele, struct port_list, list); | 134 | port = list_entry(ele, struct port_list, list); |
144 | if(!port->has_connection) | 135 | if (!port->has_connection) |
145 | continue; | 136 | continue; |
137 | |||
146 | reactivate_fd(port->fd, ACCEPT_IRQ); | 138 | reactivate_fd(port->fd, ACCEPT_IRQ); |
147 | while(port_accept(port)) ; | 139 | while (port_accept(port)) |
140 | ; | ||
148 | port->has_connection = 0; | 141 | port->has_connection = 0; |
149 | } | 142 | } |
150 | local_irq_restore(flags); | 143 | local_irq_restore(flags); |
@@ -169,25 +162,27 @@ void *port_data(int port_num) | |||
169 | int fd; | 162 | int fd; |
170 | 163 | ||
171 | down(&ports_sem); | 164 | down(&ports_sem); |
172 | list_for_each(ele, &ports){ | 165 | list_for_each(ele, &ports) { |
173 | port = list_entry(ele, struct port_list, list); | 166 | port = list_entry(ele, struct port_list, list); |
174 | if(port->port == port_num) goto found; | 167 | if (port->port == port_num) |
168 | goto found; | ||
175 | } | 169 | } |
176 | port = kmalloc(sizeof(struct port_list), GFP_KERNEL); | 170 | port = kmalloc(sizeof(struct port_list), GFP_KERNEL); |
177 | if(port == NULL){ | 171 | if (port == NULL) { |
178 | printk(KERN_ERR "Allocation of port list failed\n"); | 172 | printk(KERN_ERR "Allocation of port list failed\n"); |
179 | goto out; | 173 | goto out; |
180 | } | 174 | } |
181 | 175 | ||
182 | fd = port_listen_fd(port_num); | 176 | fd = port_listen_fd(port_num); |
183 | if(fd < 0){ | 177 | if (fd < 0) { |
184 | printk(KERN_ERR "binding to port %d failed, errno = %d\n", | 178 | printk(KERN_ERR "binding to port %d failed, errno = %d\n", |
185 | port_num, -fd); | 179 | port_num, -fd); |
186 | goto out_free; | 180 | goto out_free; |
187 | } | 181 | } |
188 | if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, | 182 | |
183 | if (um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, | ||
189 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, | 184 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, |
190 | "port", port)){ | 185 | "port", port)) { |
191 | printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); | 186 | printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); |
192 | goto out_close; | 187 | goto out_close; |
193 | } | 188 | } |
@@ -206,7 +201,7 @@ void *port_data(int port_num) | |||
206 | 201 | ||
207 | found: | 202 | found: |
208 | dev = kmalloc(sizeof(struct port_dev), GFP_KERNEL); | 203 | dev = kmalloc(sizeof(struct port_dev), GFP_KERNEL); |
209 | if(dev == NULL){ | 204 | if (dev == NULL) { |
210 | printk(KERN_ERR "Allocation of port device entry failed\n"); | 205 | printk(KERN_ERR "Allocation of port device entry failed\n"); |
211 | goto out; | 206 | goto out; |
212 | } | 207 | } |
@@ -216,10 +211,10 @@ void *port_data(int port_num) | |||
216 | .telnetd_pid = -1 }); | 211 | .telnetd_pid = -1 }); |
217 | goto out; | 212 | goto out; |
218 | 213 | ||
219 | out_free: | ||
220 | kfree(port); | ||
221 | out_close: | 214 | out_close: |
222 | os_close_file(fd); | 215 | os_close_file(fd); |
216 | out_free: | ||
217 | kfree(port); | ||
223 | out: | 218 | out: |
224 | up(&ports_sem); | 219 | up(&ports_sem); |
225 | return dev; | 220 | return dev; |
@@ -233,9 +228,9 @@ int port_wait(void *data) | |||
233 | int fd; | 228 | int fd; |
234 | 229 | ||
235 | atomic_inc(&port->wait_count); | 230 | atomic_inc(&port->wait_count); |
236 | while(1){ | 231 | while (1) { |
237 | fd = -ERESTARTSYS; | 232 | fd = -ERESTARTSYS; |
238 | if(wait_for_completion_interruptible(&port->done)) | 233 | if (wait_for_completion_interruptible(&port->done)) |
239 | goto out; | 234 | goto out; |
240 | 235 | ||
241 | spin_lock(&port->lock); | 236 | spin_lock(&port->lock); |
@@ -258,7 +253,8 @@ int port_wait(void *data) | |||
258 | */ | 253 | */ |
259 | free_irq(TELNETD_IRQ, conn); | 254 | free_irq(TELNETD_IRQ, conn); |
260 | 255 | ||
261 | if(conn->fd >= 0) break; | 256 | if (conn->fd >= 0) |
257 | break; | ||
262 | os_close_file(conn->fd); | 258 | os_close_file(conn->fd); |
263 | kfree(conn); | 259 | kfree(conn); |
264 | } | 260 | } |
@@ -276,9 +272,9 @@ void port_remove_dev(void *d) | |||
276 | { | 272 | { |
277 | struct port_dev *dev = d; | 273 | struct port_dev *dev = d; |
278 | 274 | ||
279 | if(dev->helper_pid != -1) | 275 | if (dev->helper_pid != -1) |
280 | os_kill_process(dev->helper_pid, 0); | 276 | os_kill_process(dev->helper_pid, 0); |
281 | if(dev->telnetd_pid != -1) | 277 | if (dev->telnetd_pid != -1) |
282 | os_kill_process(dev->telnetd_pid, 1); | 278 | os_kill_process(dev->telnetd_pid, 1); |
283 | dev->helper_pid = -1; | 279 | dev->helper_pid = -1; |
284 | dev->telnetd_pid = -1; | 280 | dev->telnetd_pid = -1; |
@@ -297,7 +293,7 @@ static void free_port(void) | |||
297 | struct list_head *ele; | 293 | struct list_head *ele; |
298 | struct port_list *port; | 294 | struct port_list *port; |
299 | 295 | ||
300 | list_for_each(ele, &ports){ | 296 | list_for_each(ele, &ports) { |
301 | port = list_entry(ele, struct port_list, list); | 297 | port = list_entry(ele, struct port_list, list); |
302 | free_irq_by_fd(port->fd); | 298 | free_irq_by_fd(port->fd); |
303 | os_close_file(port->fd); | 299 | os_close_file(port->fd); |
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c index c799b00012c7..addd75902656 100644 --- a/arch/um/drivers/port_user.c +++ b/arch/um/drivers/port_user.c | |||
@@ -1,24 +1,20 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdio.h> | 6 | #include <stdio.h> |
7 | #include <stddef.h> | ||
8 | #include <stdlib.h> | 7 | #include <stdlib.h> |
9 | #include <string.h> | ||
10 | #include <errno.h> | 8 | #include <errno.h> |
11 | #include <unistd.h> | ||
12 | #include <termios.h> | 9 | #include <termios.h> |
13 | #include <sys/socket.h> | 10 | #include <unistd.h> |
14 | #include <sys/un.h> | ||
15 | #include <netinet/in.h> | 11 | #include <netinet/in.h> |
16 | #include "kern_util.h" | ||
17 | #include "user.h" | ||
18 | #include "chan_user.h" | 12 | #include "chan_user.h" |
19 | #include "port.h" | 13 | #include "kern_constants.h" |
20 | #include "os.h" | 14 | #include "os.h" |
15 | #include "port.h" | ||
21 | #include "um_malloc.h" | 16 | #include "um_malloc.h" |
17 | #include "user.h" | ||
22 | 18 | ||
23 | struct port_chan { | 19 | struct port_chan { |
24 | int raw; | 20 | int raw; |
@@ -34,24 +30,25 @@ static void *port_init(char *str, int device, const struct chan_opts *opts) | |||
34 | char *end; | 30 | char *end; |
35 | int port; | 31 | int port; |
36 | 32 | ||
37 | if(*str != ':'){ | 33 | if (*str != ':') { |
38 | printk("port_init : channel type 'port' must specify a " | 34 | printk(UM_KERN_ERR "port_init : channel type 'port' must " |
39 | "port number\n"); | 35 | "specify a port number\n"); |
40 | return NULL; | 36 | return NULL; |
41 | } | 37 | } |
42 | str++; | 38 | str++; |
43 | port = strtoul(str, &end, 0); | 39 | port = strtoul(str, &end, 0); |
44 | if((*end != '\0') || (end == str)){ | 40 | if ((*end != '\0') || (end == str)) { |
45 | printk("port_init : couldn't parse port '%s'\n", str); | 41 | printk(UM_KERN_ERR "port_init : couldn't parse port '%s'\n", |
42 | str); | ||
46 | return NULL; | 43 | return NULL; |
47 | } | 44 | } |
48 | 45 | ||
49 | kern_data = port_data(port); | 46 | kern_data = port_data(port); |
50 | if(kern_data == NULL) | 47 | if (kern_data == NULL) |
51 | return NULL; | 48 | return NULL; |
52 | 49 | ||
53 | data = kmalloc(sizeof(*data), UM_GFP_KERNEL); | 50 | data = kmalloc(sizeof(*data), UM_GFP_KERNEL); |
54 | if(data == NULL) | 51 | if (data == NULL) |
55 | goto err; | 52 | goto err; |
56 | 53 | ||
57 | *data = ((struct port_chan) { .raw = opts->raw, | 54 | *data = ((struct port_chan) { .raw = opts->raw, |
@@ -79,13 +76,13 @@ static int port_open(int input, int output, int primary, void *d, | |||
79 | int fd, err; | 76 | int fd, err; |
80 | 77 | ||
81 | fd = port_wait(data->kernel_data); | 78 | fd = port_wait(data->kernel_data); |
82 | if((fd >= 0) && data->raw){ | 79 | if ((fd >= 0) && data->raw) { |
83 | CATCH_EINTR(err = tcgetattr(fd, &data->tt)); | 80 | CATCH_EINTR(err = tcgetattr(fd, &data->tt)); |
84 | if(err) | 81 | if (err) |
85 | return err; | 82 | return err; |
86 | 83 | ||
87 | err = raw(fd); | 84 | err = raw(fd); |
88 | if(err) | 85 | if (err) |
89 | return err; | 86 | return err; |
90 | } | 87 | } |
91 | *dev_out = data->dev; | 88 | *dev_out = data->dev; |
@@ -119,11 +116,11 @@ int port_listen_fd(int port) | |||
119 | int fd, err, arg; | 116 | int fd, err, arg; |
120 | 117 | ||
121 | fd = socket(PF_INET, SOCK_STREAM, 0); | 118 | fd = socket(PF_INET, SOCK_STREAM, 0); |
122 | if(fd == -1) | 119 | if (fd == -1) |
123 | return -errno; | 120 | return -errno; |
124 | 121 | ||
125 | arg = 1; | 122 | arg = 1; |
126 | if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) < 0){ | 123 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) < 0) { |
127 | err = -errno; | 124 | err = -errno; |
128 | goto out; | 125 | goto out; |
129 | } | 126 | } |
@@ -131,23 +128,23 @@ int port_listen_fd(int port) | |||
131 | addr.sin_family = AF_INET; | 128 | addr.sin_family = AF_INET; |
132 | addr.sin_port = htons(port); | 129 | addr.sin_port = htons(port); |
133 | addr.sin_addr.s_addr = htonl(INADDR_ANY); | 130 | addr.sin_addr.s_addr = htonl(INADDR_ANY); |
134 | if(bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0){ | 131 | if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { |
135 | err = -errno; | 132 | err = -errno; |
136 | goto out; | 133 | goto out; |
137 | } | 134 | } |
138 | 135 | ||
139 | if(listen(fd, 1) < 0){ | 136 | if (listen(fd, 1) < 0) { |
140 | err = -errno; | 137 | err = -errno; |
141 | goto out; | 138 | goto out; |
142 | } | 139 | } |
143 | 140 | ||
144 | err = os_set_fd_block(fd, 0); | 141 | err = os_set_fd_block(fd, 0); |
145 | if(err < 0) | 142 | if (err < 0) |
146 | goto out; | 143 | goto out; |
147 | 144 | ||
148 | return fd; | 145 | return fd; |
149 | out: | 146 | out: |
150 | os_close_file(fd); | 147 | close(fd); |
151 | return err; | 148 | return err; |
152 | } | 149 | } |
153 | 150 | ||
@@ -163,10 +160,10 @@ void port_pre_exec(void *arg) | |||
163 | dup2(data->sock_fd, 0); | 160 | dup2(data->sock_fd, 0); |
164 | dup2(data->sock_fd, 1); | 161 | dup2(data->sock_fd, 1); |
165 | dup2(data->sock_fd, 2); | 162 | dup2(data->sock_fd, 2); |
166 | os_close_file(data->sock_fd); | 163 | close(data->sock_fd); |
167 | dup2(data->pipe_fd, 3); | 164 | dup2(data->pipe_fd, 3); |
168 | os_shutdown_socket(3, 1, 0); | 165 | shutdown(3, SHUT_RD); |
169 | os_close_file(data->pipe_fd); | 166 | close(data->pipe_fd); |
170 | } | 167 | } |
171 | 168 | ||
172 | int port_connection(int fd, int *socket, int *pid_out) | 169 | int port_connection(int fd, int *socket, int *pid_out) |
@@ -176,12 +173,12 @@ int port_connection(int fd, int *socket, int *pid_out) | |||
176 | "/usr/lib/uml/port-helper", NULL }; | 173 | "/usr/lib/uml/port-helper", NULL }; |
177 | struct port_pre_exec_data data; | 174 | struct port_pre_exec_data data; |
178 | 175 | ||
179 | new = os_accept_connection(fd); | 176 | new = accept(fd, NULL, 0); |
180 | if(new < 0) | 177 | if (new < 0) |
181 | return new; | 178 | return -errno; |
182 | 179 | ||
183 | err = os_pipe(socket, 0, 0); | 180 | err = os_pipe(socket, 0, 0); |
184 | if(err < 0) | 181 | if (err < 0) |
185 | goto out_close; | 182 | goto out_close; |
186 | 183 | ||
187 | data = ((struct port_pre_exec_data) | 184 | data = ((struct port_pre_exec_data) |
@@ -189,18 +186,18 @@ int port_connection(int fd, int *socket, int *pid_out) | |||
189 | .pipe_fd = socket[1] }); | 186 | .pipe_fd = socket[1] }); |
190 | 187 | ||
191 | err = run_helper(port_pre_exec, &data, argv); | 188 | err = run_helper(port_pre_exec, &data, argv); |
192 | if(err < 0) | 189 | if (err < 0) |
193 | goto out_shutdown; | 190 | goto out_shutdown; |
194 | 191 | ||
195 | *pid_out = err; | 192 | *pid_out = err; |
196 | return new; | 193 | return new; |
197 | 194 | ||
198 | out_shutdown: | 195 | out_shutdown: |
199 | os_shutdown_socket(socket[0], 1, 1); | 196 | shutdown(socket[0], SHUT_RDWR); |
200 | os_close_file(socket[0]); | 197 | close(socket[0]); |
201 | os_shutdown_socket(socket[1], 1, 1); | 198 | shutdown(socket[1], SHUT_RDWR); |
202 | os_close_file(socket[1]); | 199 | close(socket[1]); |
203 | out_close: | 200 | out_close: |
204 | os_close_file(new); | 201 | close(new); |
205 | return err; | 202 | return err; |
206 | } | 203 | } |
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c index 1e3fd619a837..49c79dda6046 100644 --- a/arch/um/drivers/pty.c +++ b/arch/um/drivers/pty.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
@@ -6,16 +6,16 @@ | |||
6 | #include <stdio.h> | 6 | #include <stdio.h> |
7 | #include <stdlib.h> | 7 | #include <stdlib.h> |
8 | #include <unistd.h> | 8 | #include <unistd.h> |
9 | #include <string.h> | ||
10 | #include <fcntl.h> | ||
11 | #include <errno.h> | 9 | #include <errno.h> |
10 | #include <fcntl.h> | ||
11 | #include <string.h> | ||
12 | #include <termios.h> | 12 | #include <termios.h> |
13 | #include <sys/stat.h> | 13 | #include <sys/stat.h> |
14 | #include "chan_user.h" | 14 | #include "chan_user.h" |
15 | #include "os.h" | ||
16 | #include "user.h" | ||
17 | #include "kern_constants.h" | 15 | #include "kern_constants.h" |
16 | #include "os.h" | ||
18 | #include "um_malloc.h" | 17 | #include "um_malloc.h" |
18 | #include "user.h" | ||
19 | 19 | ||
20 | struct pty_chan { | 20 | struct pty_chan { |
21 | void (*announce)(char *dev_name, int dev); | 21 | void (*announce)(char *dev_name, int dev); |
@@ -33,7 +33,7 @@ static void *pty_chan_init(char *str, int device, const struct chan_opts *opts) | |||
33 | if (data == NULL) | 33 | if (data == NULL) |
34 | return NULL; | 34 | return NULL; |
35 | 35 | ||
36 | *data = ((struct pty_chan) { .announce = opts->announce, | 36 | *data = ((struct pty_chan) { .announce = opts->announce, |
37 | .dev = device, | 37 | .dev = device, |
38 | .raw = opts->raw }); | 38 | .raw = opts->raw }); |
39 | return data; | 39 | return data; |
@@ -56,11 +56,11 @@ static int pts_open(int input, int output, int primary, void *d, | |||
56 | if (data->raw) { | 56 | if (data->raw) { |
57 | CATCH_EINTR(err = tcgetattr(fd, &data->tt)); | 57 | CATCH_EINTR(err = tcgetattr(fd, &data->tt)); |
58 | if (err) | 58 | if (err) |
59 | return err; | 59 | goto out_close; |
60 | 60 | ||
61 | err = raw(fd); | 61 | err = raw(fd); |
62 | if (err) | 62 | if (err) |
63 | return err; | 63 | goto out_close; |
64 | } | 64 | } |
65 | 65 | ||
66 | dev = ptsname(fd); | 66 | dev = ptsname(fd); |
@@ -71,6 +71,10 @@ static int pts_open(int input, int output, int primary, void *d, | |||
71 | (*data->announce)(dev, data->dev); | 71 | (*data->announce)(dev, data->dev); |
72 | 72 | ||
73 | return fd; | 73 | return fd; |
74 | |||
75 | out_close: | ||
76 | close(fd); | ||
77 | return err; | ||
74 | } | 78 | } |
75 | 79 | ||
76 | static int getmaster(char *line) | 80 | static int getmaster(char *line) |
@@ -97,7 +101,7 @@ static int getmaster(char *line) | |||
97 | *tp = 't'; | 101 | *tp = 't'; |
98 | err = access(line, R_OK | W_OK); | 102 | err = access(line, R_OK | W_OK); |
99 | *tp = 'p'; | 103 | *tp = 'p'; |
100 | if(!err) | 104 | if (!err) |
101 | return master; | 105 | return master; |
102 | close(master); | 106 | close(master); |
103 | } | 107 | } |
@@ -119,12 +123,14 @@ static int pty_open(int input, int output, int primary, void *d, | |||
119 | if (fd < 0) | 123 | if (fd < 0) |
120 | return fd; | 124 | return fd; |
121 | 125 | ||
122 | if(data->raw){ | 126 | if (data->raw) { |
123 | err = raw(fd); | 127 | err = raw(fd); |
124 | if (err) | 128 | if (err) { |
129 | close(fd); | ||
125 | return err; | 130 | return err; |
131 | } | ||
126 | } | 132 | } |
127 | 133 | ||
128 | if (data->announce) | 134 | if (data->announce) |
129 | (*data->announce)(dev, data->dev); | 135 | (*data->announce)(dev, data->dev); |
130 | 136 | ||
diff --git a/arch/um/drivers/slip_kern.c b/arch/um/drivers/slip_kern.c index 125c44f77638..ae67e7158e71 100644 --- a/arch/um/drivers/slip_kern.c +++ b/arch/um/drivers/slip_kern.c | |||
@@ -1,11 +1,12 @@ | |||
1 | #include "linux/kernel.h" | 1 | /* |
2 | #include "linux/stddef.h" | 2 | * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | #include "linux/init.h" | 3 | * Licensed under the GPL. |
4 | #include "linux/netdevice.h" | 4 | */ |
5 | #include "linux/if_arp.h" | 5 | |
6 | #include <linux/if_arp.h> | ||
7 | #include <linux/init.h> | ||
8 | #include <linux/netdevice.h> | ||
6 | #include "net_kern.h" | 9 | #include "net_kern.h" |
7 | #include "net_user.h" | ||
8 | #include "kern.h" | ||
9 | #include "slip.h" | 10 | #include "slip.h" |
10 | 11 | ||
11 | struct slip_init { | 12 | struct slip_init { |
@@ -43,21 +44,19 @@ void slip_init(struct net_device *dev, void *data) | |||
43 | 44 | ||
44 | static unsigned short slip_protocol(struct sk_buff *skbuff) | 45 | static unsigned short slip_protocol(struct sk_buff *skbuff) |
45 | { | 46 | { |
46 | return(htons(ETH_P_IP)); | 47 | return htons(ETH_P_IP); |
47 | } | 48 | } |
48 | 49 | ||
49 | static int slip_read(int fd, struct sk_buff **skb, | 50 | static int slip_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) |
50 | struct uml_net_private *lp) | ||
51 | { | 51 | { |
52 | return(slip_user_read(fd, skb_mac_header(*skb), (*skb)->dev->mtu, | 52 | return slip_user_read(fd, skb_mac_header(skb), skb->dev->mtu, |
53 | (struct slip_data *) &lp->user)); | 53 | (struct slip_data *) &lp->user); |
54 | } | 54 | } |
55 | 55 | ||
56 | static int slip_write(int fd, struct sk_buff **skb, | 56 | static int slip_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) |
57 | struct uml_net_private *lp) | ||
58 | { | 57 | { |
59 | return(slip_user_write(fd, (*skb)->data, (*skb)->len, | 58 | return slip_user_write(fd, skb->data, skb->len, |
60 | (struct slip_data *) &lp->user)); | 59 | (struct slip_data *) &lp->user); |
61 | } | 60 | } |
62 | 61 | ||
63 | const struct net_kern_info slip_kern_info = { | 62 | const struct net_kern_info slip_kern_info = { |
@@ -71,12 +70,11 @@ static int slip_setup(char *str, char **mac_out, void *data) | |||
71 | { | 70 | { |
72 | struct slip_init *init = data; | 71 | struct slip_init *init = data; |
73 | 72 | ||
74 | *init = ((struct slip_init) | 73 | *init = ((struct slip_init) { .gate_addr = NULL }); |
75 | { .gate_addr = NULL }); | ||
76 | 74 | ||
77 | if(str[0] != '\0') | 75 | if (str[0] != '\0') |
78 | init->gate_addr = str; | 76 | init->gate_addr = str; |
79 | return(1); | 77 | return 1; |
80 | } | 78 | } |
81 | 79 | ||
82 | static struct transport slip_transport = { | 80 | static struct transport slip_transport = { |
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c index c0b73c28cff0..5f06204d6871 100644 --- a/arch/um/drivers/slip_user.c +++ b/arch/um/drivers/slip_user.c | |||
@@ -1,21 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
3 | * Licensed under the GPL. | ||
4 | */ | ||
5 | |||
1 | #include <stdio.h> | 6 | #include <stdio.h> |
2 | #include <stdlib.h> | 7 | #include <stdlib.h> |
3 | #include <unistd.h> | 8 | #include <unistd.h> |
4 | #include <stddef.h> | ||
5 | #include <sched.h> | ||
6 | #include <string.h> | ||
7 | #include <errno.h> | 9 | #include <errno.h> |
10 | #include <fcntl.h> | ||
11 | #include <string.h> | ||
8 | #include <sys/termios.h> | 12 | #include <sys/termios.h> |
9 | #include <sys/wait.h> | 13 | #include <sys/wait.h> |
10 | #include <sys/signal.h> | 14 | #include "kern_constants.h" |
11 | #include "kern_util.h" | ||
12 | #include "user.h" | ||
13 | #include "net_user.h" | 15 | #include "net_user.h" |
14 | #include "slip.h" | ||
15 | #include "slip_common.h" | ||
16 | #include "os.h" | 16 | #include "os.h" |
17 | #include "slip.h" | ||
17 | #include "um_malloc.h" | 18 | #include "um_malloc.h" |
18 | #include "kern_constants.h" | 19 | #include "user.h" |
19 | 20 | ||
20 | static int slip_user_init(void *data, void *dev) | 21 | static int slip_user_init(void *data, void *dev) |
21 | { | 22 | { |
@@ -31,8 +32,9 @@ static int set_up_tty(int fd) | |||
31 | struct termios tios; | 32 | struct termios tios; |
32 | 33 | ||
33 | if (tcgetattr(fd, &tios) < 0) { | 34 | if (tcgetattr(fd, &tios) < 0) { |
34 | printk("could not get initial terminal attributes\n"); | 35 | printk(UM_KERN_ERR "could not get initial terminal " |
35 | return(-1); | 36 | "attributes\n"); |
37 | return -1; | ||
36 | } | 38 | } |
37 | 39 | ||
38 | tios.c_cflag = CS8 | CREAD | HUPCL | CLOCAL; | 40 | tios.c_cflag = CS8 | CREAD | HUPCL | CLOCAL; |
@@ -48,10 +50,10 @@ static int set_up_tty(int fd) | |||
48 | cfsetispeed(&tios, B38400); | 50 | cfsetispeed(&tios, B38400); |
49 | 51 | ||
50 | if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { | 52 | if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { |
51 | printk("failed to set terminal attributes\n"); | 53 | printk(UM_KERN_ERR "failed to set terminal attributes\n"); |
52 | return(-1); | 54 | return -1; |
53 | } | 55 | } |
54 | return(0); | 56 | return 0; |
55 | } | 57 | } |
56 | 58 | ||
57 | struct slip_pre_exec_data { | 59 | struct slip_pre_exec_data { |
@@ -64,9 +66,11 @@ static void slip_pre_exec(void *arg) | |||
64 | { | 66 | { |
65 | struct slip_pre_exec_data *data = arg; | 67 | struct slip_pre_exec_data *data = arg; |
66 | 68 | ||
67 | if(data->stdin >= 0) dup2(data->stdin, 0); | 69 | if (data->stdin >= 0) |
70 | dup2(data->stdin, 0); | ||
68 | dup2(data->stdout, 1); | 71 | dup2(data->stdout, 1); |
69 | if(data->close_me >= 0) os_close_file(data->close_me); | 72 | if (data->close_me >= 0) |
73 | close(data->close_me); | ||
70 | } | 74 | } |
71 | 75 | ||
72 | static int slip_tramp(char **argv, int fd) | 76 | static int slip_tramp(char **argv, int fd) |
@@ -76,8 +80,9 @@ static int slip_tramp(char **argv, int fd) | |||
76 | int status, pid, fds[2], err, output_len; | 80 | int status, pid, fds[2], err, output_len; |
77 | 81 | ||
78 | err = os_pipe(fds, 1, 0); | 82 | err = os_pipe(fds, 1, 0); |
79 | if(err < 0){ | 83 | if (err < 0) { |
80 | printk("slip_tramp : pipe failed, err = %d\n", -err); | 84 | printk(UM_KERN_ERR "slip_tramp : pipe failed, err = %d\n", |
85 | -err); | ||
81 | goto out; | 86 | goto out; |
82 | } | 87 | } |
83 | 88 | ||
@@ -86,41 +91,42 @@ static int slip_tramp(char **argv, int fd) | |||
86 | pe_data.stdout = fds[1]; | 91 | pe_data.stdout = fds[1]; |
87 | pe_data.close_me = fds[0]; | 92 | pe_data.close_me = fds[0]; |
88 | err = run_helper(slip_pre_exec, &pe_data, argv); | 93 | err = run_helper(slip_pre_exec, &pe_data, argv); |
89 | if(err < 0) | 94 | if (err < 0) |
90 | goto out_close; | 95 | goto out_close; |
91 | pid = err; | 96 | pid = err; |
92 | 97 | ||
93 | output_len = UM_KERN_PAGE_SIZE; | 98 | output_len = UM_KERN_PAGE_SIZE; |
94 | output = kmalloc(output_len, UM_GFP_KERNEL); | 99 | output = kmalloc(output_len, UM_GFP_KERNEL); |
95 | if(output == NULL){ | 100 | if (output == NULL) { |
96 | printk("slip_tramp : failed to allocate output buffer\n"); | 101 | printk(UM_KERN_ERR "slip_tramp : failed to allocate output " |
102 | "buffer\n"); | ||
97 | os_kill_process(pid, 1); | 103 | os_kill_process(pid, 1); |
98 | err = -ENOMEM; | 104 | err = -ENOMEM; |
99 | goto out_free; | 105 | goto out_free; |
100 | } | 106 | } |
101 | 107 | ||
102 | os_close_file(fds[1]); | 108 | close(fds[1]); |
103 | read_output(fds[0], output, output_len); | 109 | read_output(fds[0], output, output_len); |
104 | printk("%s", output); | 110 | printk("%s", output); |
105 | 111 | ||
106 | CATCH_EINTR(err = waitpid(pid, &status, 0)); | 112 | CATCH_EINTR(err = waitpid(pid, &status, 0)); |
107 | if(err < 0) | 113 | if (err < 0) |
108 | err = errno; | 114 | err = errno; |
109 | else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){ | 115 | else if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) { |
110 | printk("'%s' didn't exit with status 0\n", argv[0]); | 116 | printk(UM_KERN_ERR "'%s' didn't exit with status 0\n", argv[0]); |
111 | err = -EINVAL; | 117 | err = -EINVAL; |
112 | } | 118 | } |
113 | else err = 0; | 119 | else err = 0; |
114 | 120 | ||
115 | os_close_file(fds[0]); | 121 | close(fds[0]); |
116 | 122 | ||
117 | out_free: | 123 | out_free: |
118 | kfree(output); | 124 | kfree(output); |
119 | return err; | 125 | return err; |
120 | 126 | ||
121 | out_close: | 127 | out_close: |
122 | os_close_file(fds[0]); | 128 | close(fds[0]); |
123 | os_close_file(fds[1]); | 129 | close(fds[1]); |
124 | out: | 130 | out: |
125 | return err; | 131 | return err; |
126 | } | 132 | } |
@@ -130,60 +136,64 @@ static int slip_open(void *data) | |||
130 | struct slip_data *pri = data; | 136 | struct slip_data *pri = data; |
131 | char version_buf[sizeof("nnnnn\0")]; | 137 | char version_buf[sizeof("nnnnn\0")]; |
132 | char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; | 138 | char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; |
133 | char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf, | 139 | char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf, |
134 | NULL }; | 140 | NULL }; |
135 | int sfd, mfd, err; | 141 | int sfd, mfd, err; |
136 | 142 | ||
137 | err = get_pty(); | 143 | err = get_pty(); |
138 | if(err < 0){ | 144 | if (err < 0) { |
139 | printk("slip-open : Failed to open pty, err = %d\n", -err); | 145 | printk(UM_KERN_ERR "slip-open : Failed to open pty, err = %d\n", |
146 | -err); | ||
140 | goto out; | 147 | goto out; |
141 | } | 148 | } |
142 | mfd = err; | 149 | mfd = err; |
143 | 150 | ||
144 | err = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0); | 151 | err = open(ptsname(mfd), O_RDWR, 0); |
145 | if(err < 0){ | 152 | if (err < 0) { |
146 | printk("Couldn't open tty for slip line, err = %d\n", -err); | 153 | printk(UM_KERN_ERR "Couldn't open tty for slip line, " |
154 | "err = %d\n", -err); | ||
147 | goto out_close; | 155 | goto out_close; |
148 | } | 156 | } |
149 | sfd = err; | 157 | sfd = err; |
150 | 158 | ||
151 | if(set_up_tty(sfd)) | 159 | if (set_up_tty(sfd)) |
152 | goto out_close2; | 160 | goto out_close2; |
153 | 161 | ||
154 | pri->slave = sfd; | 162 | pri->slave = sfd; |
155 | pri->slip.pos = 0; | 163 | pri->slip.pos = 0; |
156 | pri->slip.esc = 0; | 164 | pri->slip.esc = 0; |
157 | if(pri->gate_addr != NULL){ | 165 | if (pri->gate_addr != NULL) { |
158 | sprintf(version_buf, "%d", UML_NET_VERSION); | 166 | sprintf(version_buf, "%d", UML_NET_VERSION); |
159 | strcpy(gate_buf, pri->gate_addr); | 167 | strcpy(gate_buf, pri->gate_addr); |
160 | 168 | ||
161 | err = slip_tramp(argv, sfd); | 169 | err = slip_tramp(argv, sfd); |
162 | 170 | ||
163 | if(err < 0){ | 171 | if (err < 0) { |
164 | printk("slip_tramp failed - err = %d\n", -err); | 172 | printk(UM_KERN_ERR "slip_tramp failed - err = %d\n", |
173 | -err); | ||
165 | goto out_close2; | 174 | goto out_close2; |
166 | } | 175 | } |
167 | err = os_get_ifname(pri->slave, pri->name); | 176 | err = os_get_ifname(pri->slave, pri->name); |
168 | if(err < 0){ | 177 | if (err < 0) { |
169 | printk("get_ifname failed, err = %d\n", -err); | 178 | printk(UM_KERN_ERR "get_ifname failed, err = %d\n", |
179 | -err); | ||
170 | goto out_close2; | 180 | goto out_close2; |
171 | } | 181 | } |
172 | iter_addresses(pri->dev, open_addr, pri->name); | 182 | iter_addresses(pri->dev, open_addr, pri->name); |
173 | } | 183 | } |
174 | else { | 184 | else { |
175 | err = os_set_slip(sfd); | 185 | err = os_set_slip(sfd); |
176 | if(err < 0){ | 186 | if (err < 0) { |
177 | printk("Failed to set slip discipline encapsulation - " | 187 | printk(UM_KERN_ERR "Failed to set slip discipline " |
178 | "err = %d\n", -err); | 188 | "encapsulation - err = %d\n", -err); |
179 | goto out_close2; | 189 | goto out_close2; |
180 | } | 190 | } |
181 | } | 191 | } |
182 | return(mfd); | 192 | return mfd; |
183 | out_close2: | 193 | out_close2: |
184 | os_close_file(sfd); | 194 | close(sfd); |
185 | out_close: | 195 | out_close: |
186 | os_close_file(mfd); | 196 | close(mfd); |
187 | out: | 197 | out: |
188 | return err; | 198 | return err; |
189 | } | 199 | } |
@@ -192,21 +202,21 @@ static void slip_close(int fd, void *data) | |||
192 | { | 202 | { |
193 | struct slip_data *pri = data; | 203 | struct slip_data *pri = data; |
194 | char version_buf[sizeof("nnnnn\0")]; | 204 | char version_buf[sizeof("nnnnn\0")]; |
195 | char *argv[] = { "uml_net", version_buf, "slip", "down", pri->name, | 205 | char *argv[] = { "uml_net", version_buf, "slip", "down", pri->name, |
196 | NULL }; | 206 | NULL }; |
197 | int err; | 207 | int err; |
198 | 208 | ||
199 | if(pri->gate_addr != NULL) | 209 | if (pri->gate_addr != NULL) |
200 | iter_addresses(pri->dev, close_addr, pri->name); | 210 | iter_addresses(pri->dev, close_addr, pri->name); |
201 | 211 | ||
202 | sprintf(version_buf, "%d", UML_NET_VERSION); | 212 | sprintf(version_buf, "%d", UML_NET_VERSION); |
203 | 213 | ||
204 | err = slip_tramp(argv, pri->slave); | 214 | err = slip_tramp(argv, pri->slave); |
205 | 215 | ||
206 | if(err != 0) | 216 | if (err != 0) |
207 | printk("slip_tramp failed - errno = %d\n", -err); | 217 | printk(UM_KERN_ERR "slip_tramp failed - errno = %d\n", -err); |
208 | os_close_file(fd); | 218 | close(fd); |
209 | os_close_file(pri->slave); | 219 | close(pri->slave); |
210 | pri->slave = -1; | 220 | pri->slave = -1; |
211 | } | 221 | } |
212 | 222 | ||
@@ -220,17 +230,13 @@ int slip_user_write(int fd, void *buf, int len, struct slip_data *pri) | |||
220 | return slip_proto_write(fd, buf, len, &pri->slip); | 230 | return slip_proto_write(fd, buf, len, &pri->slip); |
221 | } | 231 | } |
222 | 232 | ||
223 | static int slip_set_mtu(int mtu, void *data) | ||
224 | { | ||
225 | return(mtu); | ||
226 | } | ||
227 | |||
228 | static void slip_add_addr(unsigned char *addr, unsigned char *netmask, | 233 | static void slip_add_addr(unsigned char *addr, unsigned char *netmask, |
229 | void *data) | 234 | void *data) |
230 | { | 235 | { |
231 | struct slip_data *pri = data; | 236 | struct slip_data *pri = data; |
232 | 237 | ||
233 | if(pri->slave < 0) return; | 238 | if (pri->slave < 0) |
239 | return; | ||
234 | open_addr(addr, netmask, pri->name); | 240 | open_addr(addr, netmask, pri->name); |
235 | } | 241 | } |
236 | 242 | ||
@@ -239,7 +245,8 @@ static void slip_del_addr(unsigned char *addr, unsigned char *netmask, | |||
239 | { | 245 | { |
240 | struct slip_data *pri = data; | 246 | struct slip_data *pri = data; |
241 | 247 | ||
242 | if(pri->slave < 0) return; | 248 | if (pri->slave < 0) |
249 | return; | ||
243 | close_addr(addr, netmask, pri->name); | 250 | close_addr(addr, netmask, pri->name); |
244 | } | 251 | } |
245 | 252 | ||
@@ -248,8 +255,8 @@ const struct net_user_info slip_user_info = { | |||
248 | .open = slip_open, | 255 | .open = slip_open, |
249 | .close = slip_close, | 256 | .close = slip_close, |
250 | .remove = NULL, | 257 | .remove = NULL, |
251 | .set_mtu = slip_set_mtu, | ||
252 | .add_address = slip_add_addr, | 258 | .add_address = slip_add_addr, |
253 | .delete_address = slip_del_addr, | 259 | .delete_address = slip_del_addr, |
254 | .max_packet = BUF_SIZE | 260 | .mtu = BUF_SIZE, |
261 | .max_packet = BUF_SIZE, | ||
255 | }; | 262 | }; |
diff --git a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c index 0a0324a6d290..240ee650865d 100644 --- a/arch/um/drivers/slirp_kern.c +++ b/arch/um/drivers/slirp_kern.c | |||
@@ -1,11 +1,14 @@ | |||
1 | #include "linux/kernel.h" | 1 | /* |
2 | #include "linux/stddef.h" | 2 | * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL. | ||
4 | */ | ||
5 | |||
6 | #include <linux/if_arp.h> | ||
3 | #include "linux/init.h" | 7 | #include "linux/init.h" |
4 | #include "linux/netdevice.h" | 8 | #include <linux/netdevice.h> |
5 | #include "linux/if_arp.h" | 9 | #include <linux/string.h> |
6 | #include "net_kern.h" | 10 | #include "net_kern.h" |
7 | #include "net_user.h" | 11 | #include "net_user.h" |
8 | #include "kern.h" | ||
9 | #include "slirp.h" | 12 | #include "slirp.h" |
10 | 13 | ||
11 | struct slirp_init { | 14 | struct slirp_init { |
@@ -39,29 +42,26 @@ void slirp_init(struct net_device *dev, void *data) | |||
39 | dev->tx_queue_len = 256; | 42 | dev->tx_queue_len = 256; |
40 | dev->flags = IFF_NOARP; | 43 | dev->flags = IFF_NOARP; |
41 | printk("SLIRP backend - command line:"); | 44 | printk("SLIRP backend - command line:"); |
42 | for(i=0;spri->argw.argv[i]!=NULL;i++) { | 45 | for (i = 0; spri->argw.argv[i] != NULL; i++) |
43 | printk(" '%s'",spri->argw.argv[i]); | 46 | printk(" '%s'",spri->argw.argv[i]); |
44 | } | ||
45 | printk("\n"); | 47 | printk("\n"); |
46 | } | 48 | } |
47 | 49 | ||
48 | static unsigned short slirp_protocol(struct sk_buff *skbuff) | 50 | static unsigned short slirp_protocol(struct sk_buff *skbuff) |
49 | { | 51 | { |
50 | return(htons(ETH_P_IP)); | 52 | return htons(ETH_P_IP); |
51 | } | 53 | } |
52 | 54 | ||
53 | static int slirp_read(int fd, struct sk_buff **skb, | 55 | static int slirp_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) |
54 | struct uml_net_private *lp) | ||
55 | { | 56 | { |
56 | return(slirp_user_read(fd, skb_mac_header(*skb), (*skb)->dev->mtu, | 57 | return slirp_user_read(fd, skb_mac_header(skb), skb->dev->mtu, |
57 | (struct slirp_data *) &lp->user)); | 58 | (struct slirp_data *) &lp->user); |
58 | } | 59 | } |
59 | 60 | ||
60 | static int slirp_write(int fd, struct sk_buff **skb, | 61 | static int slirp_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) |
61 | struct uml_net_private *lp) | ||
62 | { | 62 | { |
63 | return(slirp_user_write(fd, (*skb)->data, (*skb)->len, | 63 | return slirp_user_write(fd, skb->data, skb->len, |
64 | (struct slirp_data *) &lp->user)); | 64 | (struct slirp_data *) &lp->user); |
65 | } | 65 | } |
66 | 66 | ||
67 | const struct net_kern_info slirp_kern_info = { | 67 | const struct net_kern_info slirp_kern_info = { |
@@ -76,31 +76,32 @@ static int slirp_setup(char *str, char **mac_out, void *data) | |||
76 | struct slirp_init *init = data; | 76 | struct slirp_init *init = data; |
77 | int i=0; | 77 | int i=0; |
78 | 78 | ||
79 | *init = ((struct slirp_init) | 79 | *init = ((struct slirp_init) { .argw = { { "slirp", NULL } } }); |
80 | { .argw = { { "slirp", NULL } } }); | ||
81 | 80 | ||
82 | str = split_if_spec(str, mac_out, NULL); | 81 | str = split_if_spec(str, mac_out, NULL); |
83 | 82 | ||
84 | if(str == NULL) { /* no command line given after MAC addr */ | 83 | if (str == NULL) /* no command line given after MAC addr */ |
85 | return(1); | 84 | return 1; |
86 | } | ||
87 | 85 | ||
88 | do { | 86 | do { |
89 | if(i>=SLIRP_MAX_ARGS-1) { | 87 | if (i >= SLIRP_MAX_ARGS - 1) { |
90 | printk("slirp_setup: truncating slirp arguments\n"); | 88 | printk(KERN_WARNING "slirp_setup: truncating slirp " |
89 | "arguments\n"); | ||
91 | break; | 90 | break; |
92 | } | 91 | } |
93 | init->argw.argv[i++] = str; | 92 | init->argw.argv[i++] = str; |
94 | while(*str && *str!=',') { | 93 | while(*str && *str!=',') { |
95 | if(*str=='_') *str=' '; | 94 | if (*str == '_') |
95 | *str=' '; | ||
96 | str++; | 96 | str++; |
97 | } | 97 | } |
98 | if(*str!=',') | 98 | if (*str != ',') |
99 | break; | 99 | break; |
100 | *str++='\0'; | 100 | *str++ = '\0'; |
101 | } while(1); | 101 | } while (1); |
102 | init->argw.argv[i]=NULL; | 102 | |
103 | return(1); | 103 | init->argw.argv[i] = NULL; |
104 | return 1; | ||
104 | } | 105 | } |
105 | 106 | ||
106 | static struct transport slirp_transport = { | 107 | static struct transport slirp_transport = { |
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c index 0e462f64f227..1865089ff41a 100644 --- a/arch/um/drivers/slirp_user.c +++ b/arch/um/drivers/slirp_user.c | |||
@@ -1,18 +1,17 @@ | |||
1 | #include <stdio.h> | 1 | /* |
2 | #include <stdlib.h> | 2 | * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL. | ||
4 | */ | ||
5 | |||
3 | #include <unistd.h> | 6 | #include <unistd.h> |
4 | #include <stddef.h> | ||
5 | #include <sched.h> | ||
6 | #include <string.h> | ||
7 | #include <errno.h> | 7 | #include <errno.h> |
8 | #include <string.h> | ||
8 | #include <sys/wait.h> | 9 | #include <sys/wait.h> |
9 | #include <sys/signal.h> | 10 | #include "kern_constants.h" |
10 | #include "kern_util.h" | ||
11 | #include "user.h" | ||
12 | #include "net_user.h" | 11 | #include "net_user.h" |
13 | #include "slirp.h" | ||
14 | #include "slip_common.h" | ||
15 | #include "os.h" | 12 | #include "os.h" |
13 | #include "slirp.h" | ||
14 | #include "user.h" | ||
16 | 15 | ||
17 | static int slirp_user_init(void *data, void *dev) | 16 | static int slirp_user_init(void *data, void *dev) |
18 | { | 17 | { |
@@ -31,8 +30,10 @@ static void slirp_pre_exec(void *arg) | |||
31 | { | 30 | { |
32 | struct slirp_pre_exec_data *data = arg; | 31 | struct slirp_pre_exec_data *data = arg; |
33 | 32 | ||
34 | if(data->stdin != -1) dup2(data->stdin, 0); | 33 | if (data->stdin != -1) |
35 | if(data->stdout != -1) dup2(data->stdout, 1); | 34 | dup2(data->stdin, 0); |
35 | if (data->stdout != -1) | ||
36 | dup2(data->stdout, 1); | ||
36 | } | 37 | } |
37 | 38 | ||
38 | static int slirp_tramp(char **argv, int fd) | 39 | static int slirp_tramp(char **argv, int fd) |
@@ -44,7 +45,7 @@ static int slirp_tramp(char **argv, int fd) | |||
44 | pe_data.stdout = fd; | 45 | pe_data.stdout = fd; |
45 | pid = run_helper(slirp_pre_exec, &pe_data, argv); | 46 | pid = run_helper(slirp_pre_exec, &pe_data, argv); |
46 | 47 | ||
47 | return(pid); | 48 | return pid; |
48 | } | 49 | } |
49 | 50 | ||
50 | static int slirp_open(void *data) | 51 | static int slirp_open(void *data) |
@@ -53,12 +54,12 @@ static int slirp_open(void *data) | |||
53 | int fds[2], pid, err; | 54 | int fds[2], pid, err; |
54 | 55 | ||
55 | err = os_pipe(fds, 1, 1); | 56 | err = os_pipe(fds, 1, 1); |
56 | if(err) | 57 | if (err) |
57 | return(err); | 58 | return err; |
58 | 59 | ||
59 | err = slirp_tramp(pri->argw.argv, fds[1]); | 60 | err = slirp_tramp(pri->argw.argv, fds[1]); |
60 | if(err < 0){ | 61 | if (err < 0) { |
61 | printk("slirp_tramp failed - errno = %d\n", -err); | 62 | printk(UM_KERN_ERR "slirp_tramp failed - errno = %d\n", -err); |
62 | goto out; | 63 | goto out; |
63 | } | 64 | } |
64 | pid = err; | 65 | pid = err; |
@@ -68,10 +69,10 @@ static int slirp_open(void *data) | |||
68 | pri->slip.esc = 0; | 69 | pri->slip.esc = 0; |
69 | pri->pid = err; | 70 | pri->pid = err; |
70 | 71 | ||
71 | return(fds[0]); | 72 | return fds[0]; |
72 | out: | 73 | out: |
73 | os_close_file(fds[0]); | 74 | close(fds[0]); |
74 | os_close_file(fds[1]); | 75 | close(fds[1]); |
75 | return err; | 76 | return err; |
76 | } | 77 | } |
77 | 78 | ||
@@ -80,31 +81,33 @@ static void slirp_close(int fd, void *data) | |||
80 | struct slirp_data *pri = data; | 81 | struct slirp_data *pri = data; |
81 | int status,err; | 82 | int status,err; |
82 | 83 | ||
83 | os_close_file(fd); | 84 | close(fd); |
84 | os_close_file(pri->slave); | 85 | close(pri->slave); |
85 | 86 | ||
86 | pri->slave = -1; | 87 | pri->slave = -1; |
87 | 88 | ||
88 | if(pri->pid<1) { | 89 | if (pri->pid<1) { |
89 | printk("slirp_close: no child process to shut down\n"); | 90 | printk(UM_KERN_ERR "slirp_close: no child process to shut " |
91 | "down\n"); | ||
90 | return; | 92 | return; |
91 | } | 93 | } |
92 | 94 | ||
93 | #if 0 | 95 | #if 0 |
94 | if(kill(pri->pid, SIGHUP)<0) { | 96 | if (kill(pri->pid, SIGHUP)<0) { |
95 | printk("slirp_close: sending hangup to %d failed (%d)\n", | 97 | printk(UM_KERN_ERR "slirp_close: sending hangup to %d failed " |
96 | pri->pid, errno); | 98 | "(%d)\n", pri->pid, errno); |
97 | } | 99 | } |
98 | #endif | 100 | #endif |
99 | 101 | ||
100 | CATCH_EINTR(err = waitpid(pri->pid, &status, WNOHANG)); | 102 | CATCH_EINTR(err = waitpid(pri->pid, &status, WNOHANG)); |
101 | if(err < 0) { | 103 | if (err < 0) { |
102 | printk("slirp_close: waitpid returned %d\n", errno); | 104 | printk(UM_KERN_ERR "slirp_close: waitpid returned %d\n", errno); |
103 | return; | 105 | return; |
104 | } | 106 | } |
105 | 107 | ||
106 | if(err == 0) { | 108 | if (err == 0) { |
107 | printk("slirp_close: process %d has not exited\n", pri->pid); | 109 | printk(UM_KERN_ERR "slirp_close: process %d has not exited\n", |
110 | pri->pid); | ||
108 | return; | 111 | return; |
109 | } | 112 | } |
110 | 113 | ||
@@ -121,18 +124,13 @@ int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri) | |||
121 | return slip_proto_write(fd, buf, len, &pri->slip); | 124 | return slip_proto_write(fd, buf, len, &pri->slip); |
122 | } | 125 | } |
123 | 126 | ||
124 | static int slirp_set_mtu(int mtu, void *data) | ||
125 | { | ||
126 | return(mtu); | ||
127 | } | ||
128 | |||
129 | const struct net_user_info slirp_user_info = { | 127 | const struct net_user_info slirp_user_info = { |
130 | .init = slirp_user_init, | 128 | .init = slirp_user_init, |
131 | .open = slirp_open, | 129 | .open = slirp_open, |
132 | .close = slirp_close, | 130 | .close = slirp_close, |
133 | .remove = NULL, | 131 | .remove = NULL, |
134 | .set_mtu = slirp_set_mtu, | ||
135 | .add_address = NULL, | 132 | .add_address = NULL, |
136 | .delete_address = NULL, | 133 | .delete_address = NULL, |
137 | .max_packet = BUF_SIZE | 134 | .mtu = BUF_SIZE, |
135 | .max_packet = BUF_SIZE, | ||
138 | }; | 136 | }; |
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c index a9f87e19c5bf..c930fedc5172 100644 --- a/arch/um/drivers/tty.c +++ b/arch/um/drivers/tty.c | |||
@@ -1,16 +1,16 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdio.h> | ||
7 | #include <termios.h> | ||
8 | #include <errno.h> | 6 | #include <errno.h> |
9 | #include <unistd.h> | 7 | #include <fcntl.h> |
8 | #include <termios.h> | ||
10 | #include "chan_user.h" | 9 | #include "chan_user.h" |
11 | #include "user.h" | 10 | #include "kern_constants.h" |
12 | #include "os.h" | 11 | #include "os.h" |
13 | #include "um_malloc.h" | 12 | #include "um_malloc.h" |
13 | #include "user.h" | ||
14 | 14 | ||
15 | struct tty_chan { | 15 | struct tty_chan { |
16 | char *dev; | 16 | char *dev; |
@@ -22,15 +22,15 @@ static void *tty_chan_init(char *str, int device, const struct chan_opts *opts) | |||
22 | { | 22 | { |
23 | struct tty_chan *data; | 23 | struct tty_chan *data; |
24 | 24 | ||
25 | if(*str != ':'){ | 25 | if (*str != ':') { |
26 | printk("tty_init : channel type 'tty' must specify " | 26 | printk(UM_KERN_ERR "tty_init : channel type 'tty' must specify " |
27 | "a device\n"); | 27 | "a device\n"); |
28 | return NULL; | 28 | return NULL; |
29 | } | 29 | } |
30 | str++; | 30 | str++; |
31 | 31 | ||
32 | data = kmalloc(sizeof(*data), UM_GFP_KERNEL); | 32 | data = kmalloc(sizeof(*data), UM_GFP_KERNEL); |
33 | if(data == NULL) | 33 | if (data == NULL) |
34 | return NULL; | 34 | return NULL; |
35 | *data = ((struct tty_chan) { .dev = str, | 35 | *data = ((struct tty_chan) { .dev = str, |
36 | .raw = opts->raw }); | 36 | .raw = opts->raw }); |
@@ -42,19 +42,26 @@ static int tty_open(int input, int output, int primary, void *d, | |||
42 | char **dev_out) | 42 | char **dev_out) |
43 | { | 43 | { |
44 | struct tty_chan *data = d; | 44 | struct tty_chan *data = d; |
45 | int fd, err; | 45 | int fd, err, mode = 0; |
46 | |||
47 | if (input && output) | ||
48 | mode = O_RDWR; | ||
49 | else if (input) | ||
50 | mode = O_RDONLY; | ||
51 | else if (output) | ||
52 | mode = O_WRONLY; | ||
46 | 53 | ||
47 | fd = os_open_file(data->dev, of_set_rw(OPENFLAGS(), input, output), 0); | 54 | fd = open(data->dev, mode); |
48 | if(fd < 0) | 55 | if (fd < 0) |
49 | return fd; | 56 | return -errno; |
50 | 57 | ||
51 | if(data->raw){ | 58 | if (data->raw) { |
52 | CATCH_EINTR(err = tcgetattr(fd, &data->tt)); | 59 | CATCH_EINTR(err = tcgetattr(fd, &data->tt)); |
53 | if(err) | 60 | if (err) |
54 | return err; | 61 | return err; |
55 | 62 | ||
56 | err = raw(fd); | 63 | err = raw(fd); |
57 | if(err) | 64 | if (err) |
58 | return err; | 65 | return err; |
59 | } | 66 | } |
60 | 67 | ||
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 0eabe73c964d..25b248a02507 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c | |||
@@ -615,7 +615,7 @@ static int ubd_open_dev(struct ubd *ubd_dev) | |||
615 | blk_queue_max_sectors(ubd_dev->queue, 8 * sizeof(long)); | 615 | blk_queue_max_sectors(ubd_dev->queue, 8 * sizeof(long)); |
616 | 616 | ||
617 | err = -ENOMEM; | 617 | err = -ENOMEM; |
618 | ubd_dev->cow.bitmap = (void *) vmalloc(ubd_dev->cow.bitmap_len); | 618 | ubd_dev->cow.bitmap = vmalloc(ubd_dev->cow.bitmap_len); |
619 | if(ubd_dev->cow.bitmap == NULL){ | 619 | if(ubd_dev->cow.bitmap == NULL){ |
620 | printk(KERN_ERR "Failed to vmalloc COW bitmap\n"); | 620 | printk(KERN_ERR "Failed to vmalloc COW bitmap\n"); |
621 | goto error; | 621 | goto error; |
diff --git a/arch/um/drivers/vde.h b/arch/um/drivers/vde.h new file mode 100644 index 000000000000..fc3a05902ba1 --- /dev/null +++ b/arch/um/drivers/vde.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org). | ||
3 | * Licensed under the GPL. | ||
4 | */ | ||
5 | |||
6 | #ifndef __UM_VDE_H__ | ||
7 | #define __UM_VDE_H__ | ||
8 | |||
9 | struct vde_data { | ||
10 | char *vde_switch; | ||
11 | char *descr; | ||
12 | void *args; | ||
13 | void *conn; | ||
14 | void *dev; | ||
15 | }; | ||
16 | |||
17 | struct vde_init { | ||
18 | char *vde_switch; | ||
19 | char *descr; | ||
20 | int port; | ||
21 | char *group; | ||
22 | int mode; | ||
23 | }; | ||
24 | |||
25 | extern const struct net_user_info vde_user_info; | ||
26 | |||
27 | extern void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init); | ||
28 | |||
29 | extern int vde_user_read(void *conn, void *buf, int len); | ||
30 | extern int vde_user_write(void *conn, void *buf, int len); | ||
31 | |||
32 | #endif | ||
diff --git a/arch/um/drivers/vde_kern.c b/arch/um/drivers/vde_kern.c new file mode 100644 index 000000000000..add7e722defb --- /dev/null +++ b/arch/um/drivers/vde_kern.c | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org). | ||
3 | * Licensed under the GPL. | ||
4 | * | ||
5 | * Transport usage: | ||
6 | * ethN=vde,<vde_switch>,<mac addr>,<port>,<group>,<mode>,<description> | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include "linux/init.h" | ||
11 | #include <linux/netdevice.h> | ||
12 | #include "net_kern.h" | ||
13 | #include "net_user.h" | ||
14 | #include "vde.h" | ||
15 | |||
16 | static void vde_init(struct net_device *dev, void *data) | ||
17 | { | ||
18 | struct vde_init *init = data; | ||
19 | struct uml_net_private *pri; | ||
20 | struct vde_data *vpri; | ||
21 | |||
22 | pri = dev->priv; | ||
23 | vpri = (struct vde_data *) pri->user; | ||
24 | |||
25 | vpri->vde_switch = init->vde_switch; | ||
26 | vpri->descr = init->descr ? init->descr : "UML vde_transport"; | ||
27 | vpri->args = NULL; | ||
28 | vpri->conn = NULL; | ||
29 | vpri->dev = dev; | ||
30 | |||
31 | printk("vde backend - %s, ", vpri->vde_switch ? | ||
32 | vpri->vde_switch : "(default socket)"); | ||
33 | |||
34 | vde_init_libstuff(vpri, init); | ||
35 | |||
36 | printk("\n"); | ||
37 | } | ||
38 | |||
39 | static int vde_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) | ||
40 | { | ||
41 | struct vde_data *pri = (struct vde_data *) &lp->user; | ||
42 | |||
43 | if (pri->conn != NULL) | ||
44 | return vde_user_read(pri->conn, skb_mac_header(skb), | ||
45 | skb->dev->mtu + ETH_HEADER_OTHER); | ||
46 | |||
47 | printk(KERN_ERR "vde_read - we have no VDECONN to read from"); | ||
48 | return -EBADF; | ||
49 | } | ||
50 | |||
51 | static int vde_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) | ||
52 | { | ||
53 | struct vde_data *pri = (struct vde_data *) &lp->user; | ||
54 | |||
55 | if (pri->conn != NULL) | ||
56 | return vde_user_write((void *)pri->conn, skb->data, | ||
57 | skb->len); | ||
58 | |||
59 | printk(KERN_ERR "vde_write - we have no VDECONN to write to"); | ||
60 | return -EBADF; | ||
61 | } | ||
62 | |||
63 | static const struct net_kern_info vde_kern_info = { | ||
64 | .init = vde_init, | ||
65 | .protocol = eth_protocol, | ||
66 | .read = vde_read, | ||
67 | .write = vde_write, | ||
68 | }; | ||
69 | |||
70 | static int vde_setup(char *str, char **mac_out, void *data) | ||
71 | { | ||
72 | struct vde_init *init = data; | ||
73 | char *remain, *port_str = NULL, *mode_str = NULL, *last; | ||
74 | |||
75 | *init = ((struct vde_init) | ||
76 | { .vde_switch = NULL, | ||
77 | .descr = NULL, | ||
78 | .port = 0, | ||
79 | .group = NULL, | ||
80 | .mode = 0 }); | ||
81 | |||
82 | remain = split_if_spec(str, &init->vde_switch, mac_out, &port_str, | ||
83 | &init->group, &mode_str, &init->descr, NULL); | ||
84 | |||
85 | if (remain != NULL) | ||
86 | printk(KERN_WARNING "vde_setup - Ignoring extra data :" | ||
87 | "'%s'\n", remain); | ||
88 | |||
89 | if (port_str != NULL) { | ||
90 | init->port = simple_strtoul(port_str, &last, 10); | ||
91 | if ((*last != '\0') || (last == port_str)) { | ||
92 | printk(KERN_ERR "vde_setup - Bad port : '%s'\n", | ||
93 | port_str); | ||
94 | return 0; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | if (mode_str != NULL) { | ||
99 | init->mode = simple_strtoul(mode_str, &last, 8); | ||
100 | if ((*last != '\0') || (last == mode_str)) { | ||
101 | printk(KERN_ERR "vde_setup - Bad mode : '%s'\n", | ||
102 | mode_str); | ||
103 | return 0; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | printk(KERN_INFO "Configured vde device: %s\n", init->vde_switch ? | ||
108 | init->vde_switch : "(default socket)"); | ||
109 | |||
110 | return 1; | ||
111 | } | ||
112 | |||
113 | static struct transport vde_transport = { | ||
114 | .list = LIST_HEAD_INIT(vde_transport.list), | ||
115 | .name = "vde", | ||
116 | .setup = vde_setup, | ||
117 | .user = &vde_user_info, | ||
118 | .kern = &vde_kern_info, | ||
119 | .private_size = sizeof(struct vde_data), | ||
120 | .setup_size = sizeof(struct vde_init), | ||
121 | }; | ||
122 | |||
123 | static int register_vde(void) | ||
124 | { | ||
125 | register_transport(&vde_transport); | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | late_initcall(register_vde); | ||
diff --git a/arch/um/drivers/vde_user.c b/arch/um/drivers/vde_user.c new file mode 100644 index 000000000000..d9941fe5f931 --- /dev/null +++ b/arch/um/drivers/vde_user.c | |||
@@ -0,0 +1,127 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org). | ||
3 | * Licensed under the GPL. | ||
4 | */ | ||
5 | |||
6 | #include <stddef.h> | ||
7 | #include <errno.h> | ||
8 | #include <libvdeplug.h> | ||
9 | #include "kern_constants.h" | ||
10 | #include "net_user.h" | ||
11 | #include "um_malloc.h" | ||
12 | #include "user.h" | ||
13 | #include "vde.h" | ||
14 | |||
15 | static int vde_user_init(void *data, void *dev) | ||
16 | { | ||
17 | struct vde_data *pri = data; | ||
18 | VDECONN *conn = NULL; | ||
19 | int err = -EINVAL; | ||
20 | |||
21 | pri->dev = dev; | ||
22 | |||
23 | conn = vde_open(pri->vde_switch, pri->descr, pri->args); | ||
24 | |||
25 | if (conn == NULL) { | ||
26 | err = -errno; | ||
27 | printk(UM_KERN_ERR "vde_user_init: vde_open failed, " | ||
28 | "errno = %d\n", errno); | ||
29 | return err; | ||
30 | } | ||
31 | |||
32 | printk(UM_KERN_INFO "vde backend - connection opened\n"); | ||
33 | |||
34 | pri->conn = conn; | ||
35 | |||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | static int vde_user_open(void *data) | ||
40 | { | ||
41 | struct vde_data *pri = data; | ||
42 | |||
43 | if (pri->conn != NULL) | ||
44 | return vde_datafd(pri->conn); | ||
45 | |||
46 | printk(UM_KERN_WARNING "vde_open - we have no VDECONN to open"); | ||
47 | return -EINVAL; | ||
48 | } | ||
49 | |||
50 | static void vde_remove(void *data) | ||
51 | { | ||
52 | struct vde_data *pri = data; | ||
53 | |||
54 | if (pri->conn != NULL) { | ||
55 | printk(UM_KERN_INFO "vde backend - closing connection\n"); | ||
56 | vde_close(pri->conn); | ||
57 | pri->conn = NULL; | ||
58 | kfree(pri->args); | ||
59 | pri->args = NULL; | ||
60 | return; | ||
61 | } | ||
62 | |||
63 | printk(UM_KERN_WARNING "vde_remove - we have no VDECONN to remove"); | ||
64 | } | ||
65 | |||
66 | const struct net_user_info vde_user_info = { | ||
67 | .init = vde_user_init, | ||
68 | .open = vde_user_open, | ||
69 | .close = NULL, | ||
70 | .remove = vde_remove, | ||
71 | .add_address = NULL, | ||
72 | .delete_address = NULL, | ||
73 | .mtu = ETH_MAX_PACKET, | ||
74 | .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, | ||
75 | }; | ||
76 | |||
77 | void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init) | ||
78 | { | ||
79 | struct vde_open_args *args; | ||
80 | |||
81 | vpri->args = kmalloc(sizeof(struct vde_open_args), UM_GFP_KERNEL); | ||
82 | if (vpri->args == NULL) { | ||
83 | printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args" | ||
84 | "allocation failed"); | ||
85 | return; | ||
86 | } | ||
87 | |||
88 | args = vpri->args; | ||
89 | |||
90 | args->port = init->port; | ||
91 | args->group = init->group; | ||
92 | args->mode = init->mode ? init->mode : 0700; | ||
93 | |||
94 | args->port ? printk(UM_KERN_INFO "port %d", args->port) : | ||
95 | printk(UM_KERN_INFO "undefined port"); | ||
96 | } | ||
97 | |||
98 | int vde_user_read(void *conn, void *buf, int len) | ||
99 | { | ||
100 | VDECONN *vconn = conn; | ||
101 | int rv; | ||
102 | |||
103 | if (vconn == NULL) | ||
104 | return 0; | ||
105 | |||
106 | rv = vde_recv(vconn, buf, len, 0); | ||
107 | if (rv < 0) { | ||
108 | if (errno == EAGAIN) | ||
109 | return 0; | ||
110 | return -errno; | ||
111 | } | ||
112 | else if (rv == 0) | ||
113 | return -ENOTCONN; | ||
114 | |||
115 | return rv; | ||
116 | } | ||
117 | |||
118 | int vde_user_write(void *conn, void *buf, int len) | ||
119 | { | ||
120 | VDECONN *vconn = conn; | ||
121 | |||
122 | if (vconn == NULL) | ||
123 | return 0; | ||
124 | |||
125 | return vde_send(vconn, buf, len, 0); | ||
126 | } | ||
127 | |||
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index fd817e541543..8a1c18a9b240 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c | |||
@@ -1,20 +1,21 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdlib.h> | 6 | #include <stddef.h> |
7 | #include <stdio.h> | 7 | #include <stdio.h> |
8 | #include <stdlib.h> | ||
8 | #include <unistd.h> | 9 | #include <unistd.h> |
9 | #include <string.h> | ||
10 | #include <errno.h> | 10 | #include <errno.h> |
11 | #include <string.h> | ||
11 | #include <termios.h> | 12 | #include <termios.h> |
12 | #include "chan_user.h" | 13 | #include "chan_user.h" |
14 | #include "kern_constants.h" | ||
13 | #include "os.h" | 15 | #include "os.h" |
14 | #include "init.h" | 16 | #include "um_malloc.h" |
15 | #include "user.h" | 17 | #include "user.h" |
16 | #include "xterm.h" | 18 | #include "xterm.h" |
17 | #include "kern_constants.h" | ||
18 | 19 | ||
19 | struct xterm_chan { | 20 | struct xterm_chan { |
20 | int pid; | 21 | int pid; |
@@ -29,7 +30,7 @@ static void *xterm_init(char *str, int device, const struct chan_opts *opts) | |||
29 | { | 30 | { |
30 | struct xterm_chan *data; | 31 | struct xterm_chan *data; |
31 | 32 | ||
32 | data = malloc(sizeof(*data)); | 33 | data = kmalloc(sizeof(*data), UM_GFP_KERNEL); |
33 | if (data == NULL) | 34 | if (data == NULL) |
34 | return NULL; | 35 | return NULL; |
35 | *data = ((struct xterm_chan) { .pid = -1, | 36 | *data = ((struct xterm_chan) { .pid = -1, |
@@ -95,8 +96,10 @@ static int xterm_open(int input, int output, int primary, void *d, | |||
95 | if (access(argv[4], X_OK) < 0) | 96 | if (access(argv[4], X_OK) < 0) |
96 | argv[4] = "port-helper"; | 97 | argv[4] = "port-helper"; |
97 | 98 | ||
98 | /* Check that DISPLAY is set, this doesn't guarantee the xterm | 99 | /* |
99 | * will work but w/o it we can be pretty sure it won't. */ | 100 | * Check that DISPLAY is set, this doesn't guarantee the xterm |
101 | * will work but w/o it we can be pretty sure it won't. | ||
102 | */ | ||
100 | if (getenv("DISPLAY") == NULL) { | 103 | if (getenv("DISPLAY") == NULL) { |
101 | printk(UM_KERN_ERR "xterm_open: $DISPLAY not set.\n"); | 104 | printk(UM_KERN_ERR "xterm_open: $DISPLAY not set.\n"); |
102 | return -ENODEV; | 105 | return -ENODEV; |
@@ -195,7 +198,7 @@ static int xterm_open(int input, int output, int primary, void *d, | |||
195 | static void xterm_close(int fd, void *d) | 198 | static void xterm_close(int fd, void *d) |
196 | { | 199 | { |
197 | struct xterm_chan *data = d; | 200 | struct xterm_chan *data = d; |
198 | 201 | ||
199 | if (data->pid != -1) | 202 | if (data->pid != -1) |
200 | os_kill_process(data->pid, 1); | 203 | os_kill_process(data->pid, 1); |
201 | data->pid = -1; | 204 | data->pid = -1; |
@@ -207,11 +210,6 @@ static void xterm_close(int fd, void *d) | |||
207 | os_close_file(fd); | 210 | os_close_file(fd); |
208 | } | 211 | } |
209 | 212 | ||
210 | static void xterm_free(void *d) | ||
211 | { | ||
212 | free(d); | ||
213 | } | ||
214 | |||
215 | const struct chan_ops xterm_ops = { | 213 | const struct chan_ops xterm_ops = { |
216 | .type = "xterm", | 214 | .type = "xterm", |
217 | .init = xterm_init, | 215 | .init = xterm_init, |
@@ -221,6 +219,6 @@ const struct chan_ops xterm_ops = { | |||
221 | .write = generic_write, | 219 | .write = generic_write, |
222 | .console_write = generic_console_write, | 220 | .console_write = generic_console_write, |
223 | .window_size = generic_window_size, | 221 | .window_size = generic_window_size, |
224 | .free = xterm_free, | 222 | .free = generic_free, |
225 | .winch = 1, | 223 | .winch = 1, |
226 | }; | 224 | }; |
diff --git a/arch/um/include/arch.h b/arch/um/include/arch.h index 10ad52daa8c5..49c601ff2bac 100644 --- a/arch/um/include/arch.h +++ b/arch/um/include/arch.h | |||
@@ -9,7 +9,7 @@ | |||
9 | #include "sysdep/ptrace.h" | 9 | #include "sysdep/ptrace.h" |
10 | 10 | ||
11 | extern void arch_check_bugs(void); | 11 | extern void arch_check_bugs(void); |
12 | extern int arch_fixup(unsigned long address, union uml_pt_regs *regs); | 12 | extern int arch_fixup(unsigned long address, struct uml_pt_regs *regs); |
13 | extern int arch_handle_signal(int sig, union uml_pt_regs *regs); | 13 | extern int arch_handle_signal(int sig, struct uml_pt_regs *regs); |
14 | 14 | ||
15 | #endif | 15 | #endif |
diff --git a/arch/um/include/as-layout.h b/arch/um/include/as-layout.h index fccf187bf4e1..a5cdf953e04a 100644 --- a/arch/um/include/as-layout.h +++ b/arch/um/include/as-layout.h | |||
@@ -6,6 +6,28 @@ | |||
6 | #ifndef __START_H__ | 6 | #ifndef __START_H__ |
7 | #define __START_H__ | 7 | #define __START_H__ |
8 | 8 | ||
9 | #include "uml-config.h" | ||
10 | #include "kern_constants.h" | ||
11 | |||
12 | /* | ||
13 | * Assembly doesn't want any casting, but C does, so define these | ||
14 | * without casts here, and define new symbols with casts inside the C | ||
15 | * section. | ||
16 | */ | ||
17 | #define ASM_STUB_CODE (UML_CONFIG_TOP_ADDR - 2 * UM_KERN_PAGE_SIZE) | ||
18 | #define ASM_STUB_DATA (UML_CONFIG_TOP_ADDR - UM_KERN_PAGE_SIZE) | ||
19 | #define ASM_STUB_START ASM_STUB_CODE | ||
20 | |||
21 | /* | ||
22 | * This file is included by the assembly stubs, which just want the | ||
23 | * definitions above. | ||
24 | */ | ||
25 | #ifndef __ASSEMBLY__ | ||
26 | |||
27 | #define STUB_CODE ((unsigned long) ASM_STUB_CODE) | ||
28 | #define STUB_DATA ((unsigned long) ASM_STUB_DATA) | ||
29 | #define STUB_START ((unsigned long) ASM_STUB_START) | ||
30 | |||
9 | #include "sysdep/ptrace.h" | 31 | #include "sysdep/ptrace.h" |
10 | 32 | ||
11 | struct cpu_task { | 33 | struct cpu_task { |
@@ -28,8 +50,9 @@ extern unsigned long _unprotected_end; | |||
28 | extern unsigned long brk_start; | 50 | extern unsigned long brk_start; |
29 | 51 | ||
30 | extern int linux_main(int argc, char **argv); | 52 | extern int linux_main(int argc, char **argv); |
31 | extern void set_cmdline(char *cmd); | ||
32 | 53 | ||
33 | extern void (*sig_info[])(int, union uml_pt_regs *); | 54 | extern void (*sig_info[])(int, struct uml_pt_regs *); |
55 | |||
56 | #endif | ||
34 | 57 | ||
35 | #endif | 58 | #endif |
diff --git a/arch/um/include/choose-mode.h b/arch/um/include/choose-mode.h deleted file mode 100644 index b87b36a87d91..000000000000 --- a/arch/um/include/choose-mode.h +++ /dev/null | |||
@@ -1,38 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __CHOOSE_MODE_H__ | ||
7 | #define __CHOOSE_MODE_H__ | ||
8 | |||
9 | #include "uml-config.h" | ||
10 | |||
11 | #if defined(UML_CONFIG_MODE_TT) && defined(UML_CONFIG_MODE_SKAS) | ||
12 | #define CHOOSE_MODE(tt, skas) (mode_tt ? (tt) : (skas)) | ||
13 | |||
14 | extern int mode_tt; | ||
15 | static inline void *__choose_mode(void *tt, void *skas) { | ||
16 | return mode_tt ? tt : skas; | ||
17 | } | ||
18 | |||
19 | #define __CHOOSE_MODE(tt, skas) (*( (typeof(tt) *) __choose_mode(&(tt), &(skas)))) | ||
20 | |||
21 | #elif defined(UML_CONFIG_MODE_SKAS) | ||
22 | #define CHOOSE_MODE(tt, skas) (skas) | ||
23 | |||
24 | #elif defined(UML_CONFIG_MODE_TT) | ||
25 | #define CHOOSE_MODE(tt, skas) (tt) | ||
26 | |||
27 | #else | ||
28 | #error CONFIG_MODE_SKAS and CONFIG_MODE_TT are both disabled | ||
29 | #endif | ||
30 | |||
31 | #define CHOOSE_MODE_PROC(tt, skas, args...) \ | ||
32 | CHOOSE_MODE(tt(args), skas(args)) | ||
33 | |||
34 | #ifndef __CHOOSE_MODE | ||
35 | #define __CHOOSE_MODE(tt, skas) CHOOSE_MODE(tt, skas) | ||
36 | #endif | ||
37 | |||
38 | #endif | ||
diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h index 6eee343e53eb..0edab695ed4e 100644 --- a/arch/um/include/common-offsets.h +++ b/arch/um/include/common-offsets.h | |||
@@ -1,15 +1,13 @@ | |||
1 | /* for use by sys-$SUBARCH/kernel-offsets.c */ | 1 | /* for use by sys-$SUBARCH/kernel-offsets.c */ |
2 | 2 | ||
3 | DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE); | 3 | DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE); |
4 | #ifdef CONFIG_MODE_TT | ||
5 | OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid); | ||
6 | #endif | ||
7 | 4 | ||
8 | OFFSET(HOST_TASK_REGS, task_struct, thread.regs); | 5 | OFFSET(HOST_TASK_REGS, task_struct, thread.regs); |
9 | OFFSET(HOST_TASK_PID, task_struct, pid); | 6 | OFFSET(HOST_TASK_PID, task_struct, pid); |
10 | 7 | ||
11 | DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE); | 8 | DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE); |
12 | DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK); | 9 | DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK); |
10 | DEFINE(UM_KERN_PAGE_SHIFT, PAGE_SHIFT); | ||
13 | DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC); | 11 | DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC); |
14 | 12 | ||
15 | DEFINE_STR(UM_KERN_EMERG, KERN_EMERG); | 13 | DEFINE_STR(UM_KERN_EMERG, KERN_EMERG); |
@@ -34,3 +32,9 @@ DEFINE(UM_GFP_ATOMIC, GFP_ATOMIC); | |||
34 | DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx)); | 32 | DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx)); |
35 | 33 | ||
36 | DEFINE(UM_THREAD_SIZE, THREAD_SIZE); | 34 | DEFINE(UM_THREAD_SIZE, THREAD_SIZE); |
35 | |||
36 | DEFINE(UM_HZ, HZ); | ||
37 | |||
38 | DEFINE(UM_USEC_PER_SEC, USEC_PER_SEC); | ||
39 | DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC); | ||
40 | DEFINE(UM_NSEC_PER_USEC, NSEC_PER_USEC); | ||
diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h index 15d311b9be9e..884a9c17eea0 100644 --- a/arch/um/include/irq_user.h +++ b/arch/um/include/irq_user.h | |||
@@ -1,12 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #ifndef __IRQ_USER_H__ | 6 | #ifndef __IRQ_USER_H__ |
7 | #define __IRQ_USER_H__ | 7 | #define __IRQ_USER_H__ |
8 | 8 | ||
9 | #include "uml-config.h" | 9 | #include "sysdep/ptrace.h" |
10 | 10 | ||
11 | struct irq_fd { | 11 | struct irq_fd { |
12 | struct irq_fd *next; | 12 | struct irq_fd *next; |
@@ -21,7 +21,7 @@ struct irq_fd { | |||
21 | 21 | ||
22 | enum { IRQ_READ, IRQ_WRITE }; | 22 | enum { IRQ_READ, IRQ_WRITE }; |
23 | 23 | ||
24 | extern void sigio_handler(int sig, union uml_pt_regs *regs); | 24 | extern void sigio_handler(int sig, struct uml_pt_regs *regs); |
25 | extern int activate_fd(int irq, int fd, int type, void *dev_id); | 25 | extern int activate_fd(int irq, int fd, int type, void *dev_id); |
26 | extern void free_irq_by_irq_and_dev(unsigned int irq, void *dev_id); | 26 | extern void free_irq_by_irq_and_dev(unsigned int irq, void *dev_id); |
27 | extern void free_irq_by_fd(int fd); | 27 | extern void free_irq_by_fd(int fd); |
@@ -30,8 +30,4 @@ extern void deactivate_fd(int fd, int irqnum); | |||
30 | extern int deactivate_all_fds(void); | 30 | extern int deactivate_all_fds(void); |
31 | extern int activate_ipi(int fd, int pid); | 31 | extern int activate_ipi(int fd, int pid); |
32 | 32 | ||
33 | #ifdef CONFIG_MODE_TT | ||
34 | extern void forward_interrupts(int pid); | ||
35 | #endif | ||
36 | |||
37 | #endif | 33 | #endif |
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h index 6c2be26f1d7d..74ce8e5370a6 100644 --- a/arch/um/include/kern_util.h +++ b/arch/um/include/kern_util.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -8,9 +8,8 @@ | |||
8 | 8 | ||
9 | #include "sysdep/ptrace.h" | 9 | #include "sysdep/ptrace.h" |
10 | #include "sysdep/faultinfo.h" | 10 | #include "sysdep/faultinfo.h" |
11 | #include "uml-config.h" | ||
12 | 11 | ||
13 | typedef void (*kern_hndl)(int, union uml_pt_regs *); | 12 | typedef void (*kern_hndl)(int, struct uml_pt_regs *); |
14 | 13 | ||
15 | struct kern_handlers { | 14 | struct kern_handlers { |
16 | kern_hndl relay_signal; | 15 | kern_hndl relay_signal; |
@@ -34,9 +33,6 @@ extern int nsyscalls; | |||
34 | UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1) | 33 | UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1) |
35 | 34 | ||
36 | extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg); | 35 | extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg); |
37 | #ifdef UML_CONFIG_MODE_TT | ||
38 | extern unsigned long stack_sp(unsigned long page); | ||
39 | #endif | ||
40 | extern int kernel_thread_proc(void *data); | 36 | extern int kernel_thread_proc(void *data); |
41 | extern void syscall_segv(int sig); | 37 | extern void syscall_segv(int sig); |
42 | extern int current_pid(void); | 38 | extern int current_pid(void); |
@@ -44,7 +40,7 @@ extern unsigned long alloc_stack(int order, int atomic); | |||
44 | extern int do_signal(void); | 40 | extern int do_signal(void); |
45 | extern int is_stack_fault(unsigned long sp); | 41 | extern int is_stack_fault(unsigned long sp); |
46 | extern unsigned long segv(struct faultinfo fi, unsigned long ip, | 42 | extern unsigned long segv(struct faultinfo fi, unsigned long ip, |
47 | int is_user, union uml_pt_regs *regs); | 43 | int is_user, struct uml_pt_regs *regs); |
48 | extern int handle_page_fault(unsigned long address, unsigned long ip, | 44 | extern int handle_page_fault(unsigned long address, unsigned long ip, |
49 | int is_write, int is_user, int *code_out); | 45 | int is_write, int is_user, int *code_out); |
50 | extern void syscall_ready(void); | 46 | extern void syscall_ready(void); |
@@ -57,7 +53,7 @@ extern int need_finish_fork(void); | |||
57 | extern void free_stack(unsigned long stack, int order); | 53 | extern void free_stack(unsigned long stack, int order); |
58 | extern void add_input_request(int op, void (*proc)(int), void *arg); | 54 | extern void add_input_request(int op, void (*proc)(int), void *arg); |
59 | extern char *current_cmd(void); | 55 | extern char *current_cmd(void); |
60 | extern void timer_handler(int sig, union uml_pt_regs *regs); | 56 | extern void timer_handler(int sig, struct uml_pt_regs *regs); |
61 | extern int set_signals(int enable); | 57 | extern int set_signals(int enable); |
62 | extern int pid_to_processor_id(int pid); | 58 | extern int pid_to_processor_id(int pid); |
63 | extern void deliver_signals(void *t); | 59 | extern void deliver_signals(void *t); |
@@ -67,9 +63,8 @@ extern void finish_fork(void); | |||
67 | extern void paging_init(void); | 63 | extern void paging_init(void); |
68 | extern void init_flush_vm(void); | 64 | extern void init_flush_vm(void); |
69 | extern void *syscall_sp(void *t); | 65 | extern void *syscall_sp(void *t); |
70 | extern void syscall_trace(union uml_pt_regs *regs, int entryexit); | 66 | extern void syscall_trace(struct uml_pt_regs *regs, int entryexit); |
71 | extern int hz(void); | 67 | extern unsigned int do_IRQ(int irq, struct uml_pt_regs *regs); |
72 | extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs); | ||
73 | extern void interrupt_end(void); | 68 | extern void interrupt_end(void); |
74 | extern void initial_thread_cb(void (*proc)(void *), void *arg); | 69 | extern void initial_thread_cb(void (*proc)(void *), void *arg); |
75 | extern int debugger_signal(int status, int pid); | 70 | extern int debugger_signal(int status, int pid); |
@@ -79,10 +74,9 @@ extern int init_ptrace_proxy(int idle_pid, int startup, int stop); | |||
79 | extern int init_parent_proxy(int pid); | 74 | extern int init_parent_proxy(int pid); |
80 | extern int singlestepping(void *t); | 75 | extern int singlestepping(void *t); |
81 | extern void check_stack_overflow(void *ptr); | 76 | extern void check_stack_overflow(void *ptr); |
82 | extern void relay_signal(int sig, union uml_pt_regs *regs); | 77 | extern void relay_signal(int sig, struct uml_pt_regs *regs); |
83 | extern int user_context(unsigned long sp); | 78 | extern int user_context(unsigned long sp); |
84 | extern void timer_irq(union uml_pt_regs *regs); | 79 | extern void timer_irq(struct uml_pt_regs *regs); |
85 | extern void unprotect_stack(unsigned long stack); | ||
86 | extern void do_uml_exitcalls(void); | 80 | extern void do_uml_exitcalls(void); |
87 | extern int attach_debugger(int idle_pid, int pid, int stop); | 81 | extern int attach_debugger(int idle_pid, int pid, int stop); |
88 | extern int config_gdb(char *str); | 82 | extern int config_gdb(char *str); |
@@ -113,11 +107,9 @@ extern void time_init_kern(void); | |||
113 | 107 | ||
114 | /* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */ | 108 | /* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */ |
115 | extern int __cant_sleep(void); | 109 | extern int __cant_sleep(void); |
116 | extern void sigio_handler(int sig, union uml_pt_regs *regs); | 110 | extern void sigio_handler(int sig, struct uml_pt_regs *regs); |
117 | 111 | extern void copy_sc(struct uml_pt_regs *regs, void *from); | |
118 | extern void copy_sc(union uml_pt_regs *regs, void *from); | ||
119 | |||
120 | extern unsigned long to_irq_stack(unsigned long *mask_out); | 112 | extern unsigned long to_irq_stack(unsigned long *mask_out); |
121 | unsigned long from_irq_stack(int nested); | 113 | unsigned long from_irq_stack(int nested); |
122 | 114 | extern int start_uml(void); | |
123 | #endif | 115 | #endif |
diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h index b282839c1625..c139ae1d6826 100644 --- a/arch/um/include/mconsole.h +++ b/arch/um/include/mconsole.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) | 2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) |
3 | * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) | 3 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
4 | * Licensed under the GPL | 4 | * Licensed under the GPL |
5 | */ | 5 | */ |
6 | 6 | ||
@@ -63,7 +63,7 @@ struct mc_request | |||
63 | 63 | ||
64 | struct mconsole_request request; | 64 | struct mconsole_request request; |
65 | struct mconsole_command *cmd; | 65 | struct mconsole_command *cmd; |
66 | union uml_pt_regs regs; | 66 | struct uml_pt_regs regs; |
67 | }; | 67 | }; |
68 | 68 | ||
69 | extern char mconsole_socket_name[]; | 69 | extern char mconsole_socket_name[]; |
@@ -96,14 +96,3 @@ extern void lock_notify(void); | |||
96 | extern void unlock_notify(void); | 96 | extern void unlock_notify(void); |
97 | 97 | ||
98 | #endif | 98 | #endif |
99 | |||
100 | /* | ||
101 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
102 | * Emacs will notice this stuff at the end of the file and automatically | ||
103 | * adjust the settings for this buffer only. This must remain at the end | ||
104 | * of the file. | ||
105 | * --------------------------------------------------------------------------- | ||
106 | * Local variables: | ||
107 | * c-file-style: "linux" | ||
108 | * End: | ||
109 | */ | ||
diff --git a/arch/um/include/mem.h b/arch/um/include/mem.h index e8ff0d8fa610..5cd40e99e8d5 100644 --- a/arch/um/include/mem.h +++ b/arch/um/include/mem.h | |||
@@ -1,18 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002, 2003 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #ifndef __MEM_H__ | 6 | #ifndef __MEM_H__ |
7 | #define __MEM_H__ | 7 | #define __MEM_H__ |
8 | 8 | ||
9 | #include "linux/types.h" | 9 | extern int phys_mapping(unsigned long phys, unsigned long long *offset_out); |
10 | |||
11 | extern int phys_mapping(unsigned long phys, __u64 *offset_out); | ||
12 | extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w); | ||
13 | extern int is_remapped(void *virt); | ||
14 | extern int physmem_remove_mapping(void *virt); | ||
15 | extern void physmem_forget_descriptor(int fd); | ||
16 | 10 | ||
17 | extern unsigned long uml_physmem; | 11 | extern unsigned long uml_physmem; |
18 | static inline unsigned long to_phys(void *virt) | 12 | static inline unsigned long to_phys(void *virt) |
@@ -26,14 +20,3 @@ static inline void *to_virt(unsigned long phys) | |||
26 | } | 20 | } |
27 | 21 | ||
28 | #endif | 22 | #endif |
29 | |||
30 | /* | ||
31 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
32 | * Emacs will notice this stuff at the end of the file and automatically | ||
33 | * adjust the settings for this buffer only. This must remain at the end | ||
34 | * of the file. | ||
35 | * --------------------------------------------------------------------------- | ||
36 | * Local variables: | ||
37 | * c-file-style: "linux" | ||
38 | * End: | ||
39 | */ | ||
diff --git a/arch/um/include/mode.h b/arch/um/include/mode.h deleted file mode 100644 index 786cf563eb05..000000000000 --- a/arch/um/include/mode.h +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __MODE_H__ | ||
7 | #define __MODE_H__ | ||
8 | |||
9 | #include "uml-config.h" | ||
10 | |||
11 | #ifdef UML_CONFIG_MODE_TT | ||
12 | #include "mode-tt.h" | ||
13 | #endif | ||
14 | |||
15 | #ifdef UML_CONFIG_MODE_SKAS | ||
16 | #include "mode-skas.h" | ||
17 | #endif | ||
18 | |||
19 | #endif | ||
20 | |||
21 | /* | ||
22 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
23 | * Emacs will notice this stuff at the end of the file and automatically | ||
24 | * adjust the settings for this buffer only. This must remain at the end | ||
25 | * of the file. | ||
26 | * --------------------------------------------------------------------------- | ||
27 | * Local variables: | ||
28 | * c-file-style: "linux" | ||
29 | * End: | ||
30 | */ | ||
diff --git a/arch/um/include/mode_kern.h b/arch/um/include/mode_kern.h deleted file mode 100644 index 88e5e77bf517..000000000000 --- a/arch/um/include/mode_kern.h +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __MODE_KERN_H__ | ||
7 | #define __MODE_KERN_H__ | ||
8 | |||
9 | #ifdef CONFIG_MODE_TT | ||
10 | #include "mode_kern_tt.h" | ||
11 | #endif | ||
12 | |||
13 | #ifdef CONFIG_MODE_SKAS | ||
14 | #include "mode_kern_skas.h" | ||
15 | #endif | ||
16 | |||
17 | #endif | ||
diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h index 9237056b9103..d843c7924a7c 100644 --- a/arch/um/include/net_kern.h +++ b/arch/um/include/net_kern.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -30,24 +30,24 @@ struct uml_net_private { | |||
30 | struct work_struct work; | 30 | struct work_struct work; |
31 | int fd; | 31 | int fd; |
32 | unsigned char mac[ETH_ALEN]; | 32 | unsigned char mac[ETH_ALEN]; |
33 | int max_packet; | ||
33 | unsigned short (*protocol)(struct sk_buff *); | 34 | unsigned short (*protocol)(struct sk_buff *); |
34 | int (*open)(void *); | 35 | int (*open)(void *); |
35 | void (*close)(int, void *); | 36 | void (*close)(int, void *); |
36 | void (*remove)(void *); | 37 | void (*remove)(void *); |
37 | int (*read)(int, struct sk_buff **skb, struct uml_net_private *); | 38 | int (*read)(int, struct sk_buff *skb, struct uml_net_private *); |
38 | int (*write)(int, struct sk_buff **skb, struct uml_net_private *); | 39 | int (*write)(int, struct sk_buff *skb, struct uml_net_private *); |
39 | 40 | ||
40 | void (*add_address)(unsigned char *, unsigned char *, void *); | 41 | void (*add_address)(unsigned char *, unsigned char *, void *); |
41 | void (*delete_address)(unsigned char *, unsigned char *, void *); | 42 | void (*delete_address)(unsigned char *, unsigned char *, void *); |
42 | int (*set_mtu)(int mtu, void *); | ||
43 | char user[0]; | 43 | char user[0]; |
44 | }; | 44 | }; |
45 | 45 | ||
46 | struct net_kern_info { | 46 | struct net_kern_info { |
47 | void (*init)(struct net_device *, void *); | 47 | void (*init)(struct net_device *, void *); |
48 | unsigned short (*protocol)(struct sk_buff *); | 48 | unsigned short (*protocol)(struct sk_buff *); |
49 | int (*read)(int, struct sk_buff **skb, struct uml_net_private *); | 49 | int (*read)(int, struct sk_buff *skb, struct uml_net_private *); |
50 | int (*write)(int, struct sk_buff **skb, struct uml_net_private *); | 50 | int (*write)(int, struct sk_buff *skb, struct uml_net_private *); |
51 | }; | 51 | }; |
52 | 52 | ||
53 | struct transport { | 53 | struct transport { |
@@ -62,7 +62,6 @@ struct transport { | |||
62 | 62 | ||
63 | extern struct net_device *ether_init(int); | 63 | extern struct net_device *ether_init(int); |
64 | extern unsigned short ether_protocol(struct sk_buff *); | 64 | extern unsigned short ether_protocol(struct sk_buff *); |
65 | extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra); | ||
66 | extern int tap_setup_common(char *str, char *type, char **dev_name, | 65 | extern int tap_setup_common(char *str, char *type, char **dev_name, |
67 | char **mac_out, char **gate_addr); | 66 | char **mac_out, char **gate_addr); |
68 | extern void register_transport(struct transport *new); | 67 | extern void register_transport(struct transport *new); |
diff --git a/arch/um/include/net_user.h b/arch/um/include/net_user.h index cfe7c50634b9..63bee158cd8e 100644 --- a/arch/um/include/net_user.h +++ b/arch/um/include/net_user.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -18,10 +18,10 @@ struct net_user_info { | |||
18 | int (*open)(void *); | 18 | int (*open)(void *); |
19 | void (*close)(int, void *); | 19 | void (*close)(int, void *); |
20 | void (*remove)(void *); | 20 | void (*remove)(void *); |
21 | int (*set_mtu)(int mtu, void *); | ||
22 | void (*add_address)(unsigned char *, unsigned char *, void *); | 21 | void (*add_address)(unsigned char *, unsigned char *, void *); |
23 | void (*delete_address)(unsigned char *, unsigned char *, void *); | 22 | void (*delete_address)(unsigned char *, unsigned char *, void *); |
24 | int max_packet; | 23 | int max_packet; |
24 | int mtu; | ||
25 | }; | 25 | }; |
26 | 26 | ||
27 | extern void ether_user_init(void *data, void *dev); | 27 | extern void ether_user_init(void *data, void *dev); |
diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 930b261ea483..fbf0a87c6eaa 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h | |||
@@ -1,20 +1,18 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #ifndef __OS_H__ | 6 | #ifndef __OS_H__ |
7 | #define __OS_H__ | 7 | #define __OS_H__ |
8 | 8 | ||
9 | #include "uml-config.h" | 9 | #include <stdarg.h> |
10 | #include "asm/types.h" | ||
11 | #include "../os/include/file.h" | ||
12 | #include "sysdep/ptrace.h" | ||
13 | #include "kern_util.h" | ||
14 | #include "skas/mm_id.h" | ||
15 | #include "irq_user.h" | 10 | #include "irq_user.h" |
11 | #include "kern_util.h" | ||
12 | #include "longjmp.h" | ||
13 | #include "mm_id.h" | ||
16 | #include "sysdep/tls.h" | 14 | #include "sysdep/tls.h" |
17 | #include "sysdep/archsetjmp.h" | 15 | #include "../os/include/file.h" |
18 | 16 | ||
19 | #define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR)) | 17 | #define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR)) |
20 | 18 | ||
@@ -130,18 +128,15 @@ static inline struct openflags of_cloexec(struct openflags flags) | |||
130 | extern int os_stat_file(const char *file_name, struct uml_stat *buf); | 128 | extern int os_stat_file(const char *file_name, struct uml_stat *buf); |
131 | extern int os_stat_fd(const int fd, struct uml_stat *buf); | 129 | extern int os_stat_fd(const int fd, struct uml_stat *buf); |
132 | extern int os_access(const char *file, int mode); | 130 | extern int os_access(const char *file, int mode); |
133 | extern void os_print_error(int error, const char* str); | ||
134 | extern int os_get_exec_close(int fd, int *close_on_exec); | 131 | extern int os_get_exec_close(int fd, int *close_on_exec); |
135 | extern int os_set_exec_close(int fd, int close_on_exec); | 132 | extern int os_set_exec_close(int fd); |
136 | extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg); | 133 | extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg); |
137 | extern int os_window_size(int fd, int *rows, int *cols); | ||
138 | extern int os_new_tty_pgrp(int fd, int pid); | ||
139 | extern int os_get_ifname(int fd, char *namebuf); | 134 | extern int os_get_ifname(int fd, char *namebuf); |
140 | extern int os_set_slip(int fd); | 135 | extern int os_set_slip(int fd); |
141 | extern int os_set_owner(int fd, int pid); | 136 | extern int os_set_owner(int fd, int pid); |
142 | extern int os_mode_fd(int fd, int mode); | 137 | extern int os_mode_fd(int fd, int mode); |
143 | 138 | ||
144 | extern int os_seek_file(int fd, __u64 offset); | 139 | extern int os_seek_file(int fd, unsigned long long offset); |
145 | extern int os_open_file(char *file, struct openflags flags, int mode); | 140 | extern int os_open_file(char *file, struct openflags flags, int mode); |
146 | extern int os_read_file(int fd, void *buf, int len); | 141 | extern int os_read_file(int fd, void *buf, int len); |
147 | extern int os_write_file(int fd, const void *buf, int count); | 142 | extern int os_write_file(int fd, const void *buf, int count); |
@@ -179,11 +174,7 @@ extern void check_host_supports_tls(int *supports_tls, int *tls_min); | |||
179 | 174 | ||
180 | /* Make sure they are clear when running in TT mode. Required by | 175 | /* Make sure they are clear when running in TT mode. Required by |
181 | * SEGV_MAYBE_FIXABLE */ | 176 | * SEGV_MAYBE_FIXABLE */ |
182 | #ifdef UML_CONFIG_MODE_SKAS | ||
183 | #define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0) | 177 | #define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0) |
184 | #else | ||
185 | #define clear_can_do_skas() do {} while (0) | ||
186 | #endif | ||
187 | 178 | ||
188 | /* mem.c */ | 179 | /* mem.c */ |
189 | extern int create_mem_file(unsigned long long len); | 180 | extern int create_mem_file(unsigned long long len); |
@@ -194,20 +185,13 @@ extern int os_process_parent(int pid); | |||
194 | extern void os_stop_process(int pid); | 185 | extern void os_stop_process(int pid); |
195 | extern void os_kill_process(int pid, int reap_child); | 186 | extern void os_kill_process(int pid, int reap_child); |
196 | extern void os_kill_ptraced_process(int pid, int reap_child); | 187 | extern void os_kill_ptraced_process(int pid, int reap_child); |
197 | #ifdef UML_CONFIG_MODE_TT | ||
198 | extern void os_usr1_process(int pid); | ||
199 | #endif | ||
200 | extern long os_ptrace_ldt(long pid, long addr, long data); | 188 | extern long os_ptrace_ldt(long pid, long addr, long data); |
201 | 189 | ||
202 | extern int os_getpid(void); | 190 | extern int os_getpid(void); |
203 | extern int os_getpgrp(void); | 191 | extern int os_getpgrp(void); |
204 | 192 | ||
205 | #ifdef UML_CONFIG_MODE_TT | ||
206 | extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)); | ||
207 | extern void stop(void); | ||
208 | #endif | ||
209 | extern void init_new_thread_signals(void); | 193 | extern void init_new_thread_signals(void); |
210 | extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr); | 194 | extern int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr); |
211 | 195 | ||
212 | extern int os_map_memory(void *virt, int fd, unsigned long long off, | 196 | extern int os_map_memory(void *virt, int fd, unsigned long long off, |
213 | unsigned long len, int r, int w, int x); | 197 | unsigned long len, int r, int w, int x); |
@@ -218,21 +202,9 @@ extern int os_drop_memory(void *addr, int length); | |||
218 | extern int can_drop_memory(void); | 202 | extern int can_drop_memory(void); |
219 | extern void os_flush_stdout(void); | 203 | extern void os_flush_stdout(void); |
220 | 204 | ||
221 | /* tt.c | ||
222 | * for tt mode only (will be deleted in future...) | ||
223 | */ | ||
224 | extern void forward_ipi(int fd, int pid); | ||
225 | extern void kill_child_dead(int pid); | ||
226 | extern int wait_for_stop(int pid, int sig, int cont_type, void *relay); | ||
227 | extern int protect_memory(unsigned long addr, unsigned long len, | ||
228 | int r, int w, int x, int must_succeed); | ||
229 | extern void forward_pending_sigio(int target); | ||
230 | extern int start_fork_tramp(void *arg, unsigned long temp_stack, | ||
231 | int clone_flags, int (*tramp)(void *)); | ||
232 | |||
233 | /* uaccess.c */ | 205 | /* uaccess.c */ |
234 | extern unsigned long __do_user_copy(void *to, const void *from, int n, | 206 | extern unsigned long __do_user_copy(void *to, const void *from, int n, |
235 | void **fault_addr, void **fault_catcher, | 207 | void **fault_addr, jmp_buf **fault_catcher, |
236 | void (*op)(void *to, const void *from, | 208 | void (*op)(void *to, const void *from, |
237 | int n), int *faulted_out); | 209 | int n), int *faulted_out); |
238 | 210 | ||
@@ -255,6 +227,7 @@ extern int set_umid(char *name); | |||
255 | extern char *get_umid(void); | 227 | extern char *get_umid(void); |
256 | 228 | ||
257 | /* signal.c */ | 229 | /* signal.c */ |
230 | extern void timer_init(void); | ||
258 | extern void set_sigstack(void *sig_stack, int size); | 231 | extern void set_sigstack(void *sig_stack, int size); |
259 | extern void remove_sigstack(void); | 232 | extern void remove_sigstack(void); |
260 | extern void set_handler(int sig, void (*handler)(int), int flags, ...); | 233 | extern void set_handler(int sig, void (*handler)(int), int flags, ...); |
@@ -266,7 +239,6 @@ extern int set_signals(int enable); | |||
266 | 239 | ||
267 | /* trap.c */ | 240 | /* trap.c */ |
268 | extern void os_fill_handlinfo(struct kern_handlers h); | 241 | extern void os_fill_handlinfo(struct kern_handlers h); |
269 | extern void do_longjmp(void *p, int val); | ||
270 | 242 | ||
271 | /* util.c */ | 243 | /* util.c */ |
272 | extern void stack_protections(unsigned long address); | 244 | extern void stack_protections(unsigned long address); |
@@ -277,17 +249,12 @@ extern int setjmp_wrapper(void (*proc)(void *, void *), ...); | |||
277 | extern void os_dump_core(void); | 249 | extern void os_dump_core(void); |
278 | 250 | ||
279 | /* time.c */ | 251 | /* time.c */ |
280 | #define BILLION (1000 * 1000 * 1000) | 252 | extern void idle_sleep(unsigned long long nsecs); |
281 | 253 | extern int set_interval(void); | |
282 | extern void switch_timers(int to_real); | 254 | extern int timer_one_shot(int ticks); |
283 | extern void idle_sleep(int secs); | 255 | extern long long disable_timer(void); |
284 | extern int set_interval(int is_virtual); | ||
285 | #ifdef CONFIG_MODE_TT | ||
286 | extern void enable_timer(void); | ||
287 | #endif | ||
288 | extern void disable_timer(void); | ||
289 | extern void uml_idle_timer(void); | 256 | extern void uml_idle_timer(void); |
290 | extern unsigned long long os_nsecs(void); | 257 | extern long long os_nsecs(void); |
291 | 258 | ||
292 | /* skas/mem.c */ | 259 | /* skas/mem.c */ |
293 | extern long run_syscall_stub(struct mm_id * mm_idp, | 260 | extern long run_syscall_stub(struct mm_id * mm_idp, |
@@ -308,7 +275,9 @@ extern int protect(struct mm_id * mm_idp, unsigned long addr, | |||
308 | extern int is_skas_winch(int pid, int fd, void *data); | 275 | extern int is_skas_winch(int pid, int fd, void *data); |
309 | extern int start_userspace(unsigned long stub_stack); | 276 | extern int start_userspace(unsigned long stub_stack); |
310 | extern int copy_context_skas0(unsigned long stack, int pid); | 277 | extern int copy_context_skas0(unsigned long stack, int pid); |
311 | extern void userspace(union uml_pt_regs *regs); | 278 | extern void save_registers(int pid, struct uml_pt_regs *regs); |
279 | extern void restore_registers(int pid, struct uml_pt_regs *regs); | ||
280 | extern void userspace(struct uml_pt_regs *regs); | ||
312 | extern void map_stub_pages(int fd, unsigned long code, | 281 | extern void map_stub_pages(int fd, unsigned long code, |
313 | unsigned long data, unsigned long stack); | 282 | unsigned long data, unsigned long stack); |
314 | extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)); | 283 | extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)); |
diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h index f845b3629a6d..0e27406a43a4 100644 --- a/arch/um/include/registers.h +++ b/arch/um/include/registers.h | |||
@@ -9,13 +9,15 @@ | |||
9 | #include "sysdep/ptrace.h" | 9 | #include "sysdep/ptrace.h" |
10 | #include "sysdep/archsetjmp.h" | 10 | #include "sysdep/archsetjmp.h" |
11 | 11 | ||
12 | extern void init_thread_registers(union uml_pt_regs *to); | 12 | extern void init_thread_registers(struct uml_pt_regs *to); |
13 | extern int save_fp_registers(int pid, unsigned long *fp_regs); | 13 | extern int save_fp_registers(int pid, unsigned long *fp_regs); |
14 | extern int restore_fp_registers(int pid, unsigned long *fp_regs); | 14 | extern int restore_fp_registers(int pid, unsigned long *fp_regs); |
15 | extern void save_registers(int pid, union uml_pt_regs *regs); | 15 | extern int save_fpx_registers(int pid, unsigned long *fp_regs); |
16 | extern void restore_registers(int pid, union uml_pt_regs *regs); | 16 | extern int restore_fpx_registers(int pid, unsigned long *fp_regs); |
17 | extern void save_registers(int pid, struct uml_pt_regs *regs); | ||
18 | extern void restore_registers(int pid, struct uml_pt_regs *regs); | ||
17 | extern void init_registers(int pid); | 19 | extern void init_registers(int pid); |
18 | extern void get_safe_registers(unsigned long * regs, unsigned long * fp_regs); | 20 | extern void get_safe_registers(unsigned long *regs); |
19 | extern unsigned long get_thread_reg(int reg, jmp_buf *buf); | 21 | extern unsigned long get_thread_reg(int reg, jmp_buf *buf); |
20 | 22 | ||
21 | #endif | 23 | #endif |
diff --git a/arch/um/include/skas/mmu-skas.h b/arch/um/include/skas/mmu-skas.h deleted file mode 100644 index b26986c0c3d2..000000000000 --- a/arch/um/include/skas/mmu-skas.h +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __SKAS_MMU_H | ||
7 | #define __SKAS_MMU_H | ||
8 | |||
9 | #include "mm_id.h" | ||
10 | #include "asm/ldt.h" | ||
11 | |||
12 | struct mmu_context_skas { | ||
13 | struct mm_id id; | ||
14 | unsigned long last_page_table; | ||
15 | #ifdef CONFIG_3_LEVEL_PGTABLES | ||
16 | unsigned long last_pmd; | ||
17 | #endif | ||
18 | uml_ldt_t ldt; | ||
19 | }; | ||
20 | |||
21 | extern void switch_mm_skas(struct mm_id * mm_idp); | ||
22 | |||
23 | #endif | ||
diff --git a/arch/um/include/skas/mode-skas.h b/arch/um/include/skas/mode-skas.h index 8bc6916bbbb1..e065feb000df 100644 --- a/arch/um/include/skas/mode-skas.h +++ b/arch/um/include/skas/mode-skas.h | |||
@@ -1,18 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #ifndef __MODE_SKAS_H__ | 6 | #ifndef __MODE_SKAS_H__ |
7 | #define __MODE_SKAS_H__ | 7 | #define __MODE_SKAS_H__ |
8 | 8 | ||
9 | #include <sysdep/ptrace.h> | ||
10 | |||
11 | extern unsigned long exec_regs[]; | ||
12 | extern unsigned long exec_fp_regs[]; | ||
13 | extern unsigned long exec_fpx_regs[]; | ||
14 | extern int have_fpx_regs; | ||
15 | |||
16 | extern void kill_off_processes_skas(void); | 9 | extern void kill_off_processes_skas(void); |
17 | 10 | ||
18 | #endif | 11 | #endif |
diff --git a/arch/um/include/skas/mode_kern_skas.h b/arch/um/include/skas/mode_kern_skas.h deleted file mode 100644 index 8ee6285dfacc..000000000000 --- a/arch/um/include/skas/mode_kern_skas.h +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __SKAS_MODE_KERN_H__ | ||
7 | #define __SKAS_MODE_KERN_H__ | ||
8 | |||
9 | #include "linux/sched.h" | ||
10 | #include "asm/page.h" | ||
11 | #include "asm/ptrace.h" | ||
12 | |||
13 | extern void flush_thread_skas(void); | ||
14 | extern void switch_to_skas(void *prev, void *next); | ||
15 | extern void start_thread_skas(struct pt_regs *regs, unsigned long eip, | ||
16 | unsigned long esp); | ||
17 | extern int copy_thread_skas(int nr, unsigned long clone_flags, | ||
18 | unsigned long sp, unsigned long stack_top, | ||
19 | struct task_struct *p, struct pt_regs *regs); | ||
20 | extern void release_thread_skas(struct task_struct *task); | ||
21 | extern void init_idle_skas(void); | ||
22 | extern void flush_tlb_kernel_range_skas(unsigned long start, | ||
23 | unsigned long end); | ||
24 | extern void flush_tlb_kernel_vm_skas(void); | ||
25 | extern void __flush_tlb_one_skas(unsigned long addr); | ||
26 | extern void flush_tlb_range_skas(struct vm_area_struct *vma, | ||
27 | unsigned long start, unsigned long end); | ||
28 | extern void flush_tlb_mm_skas(struct mm_struct *mm); | ||
29 | extern void force_flush_all_skas(void); | ||
30 | extern long execute_syscall_skas(void *r); | ||
31 | extern void before_mem_skas(unsigned long unused); | ||
32 | extern unsigned long set_task_sizes_skas(unsigned long *task_size_out); | ||
33 | extern int start_uml_skas(void); | ||
34 | extern int external_pid_skas(struct task_struct *task); | ||
35 | extern int thread_pid_skas(struct task_struct *task); | ||
36 | extern void flush_tlb_page_skas(struct vm_area_struct *vma, | ||
37 | unsigned long address); | ||
38 | |||
39 | #define kmem_end_skas (host_task_size - 1024 * 1024) | ||
40 | |||
41 | #endif | ||
diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h index e88926b16072..b073f8a86bd3 100644 --- a/arch/um/include/skas/skas.h +++ b/arch/um/include/skas/skas.h | |||
@@ -1,12 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #ifndef __SKAS_H | 6 | #ifndef __SKAS_H |
7 | #define __SKAS_H | 7 | #define __SKAS_H |
8 | 8 | ||
9 | #include "mm_id.h" | ||
10 | #include "sysdep/ptrace.h" | 9 | #include "sysdep/ptrace.h" |
11 | 10 | ||
12 | extern int userspace_pid[]; | 11 | extern int userspace_pid[]; |
@@ -15,7 +14,7 @@ extern int skas_needs_stub; | |||
15 | 14 | ||
16 | extern int user_thread(unsigned long stack, int flags); | 15 | extern int user_thread(unsigned long stack, int flags); |
17 | extern void new_thread_handler(void); | 16 | extern void new_thread_handler(void); |
18 | extern void handle_syscall(union uml_pt_regs *regs); | 17 | extern void handle_syscall(struct uml_pt_regs *regs); |
19 | extern int new_mm(unsigned long stack); | 18 | extern int new_mm(unsigned long stack); |
20 | extern void get_skas_faultinfo(int pid, struct faultinfo * fi); | 19 | extern void get_skas_faultinfo(int pid, struct faultinfo * fi); |
21 | extern long execute_syscall_skas(void *r); | 20 | extern long execute_syscall_skas(void *r); |
diff --git a/arch/um/include/skas/uaccess-skas.h b/arch/um/include/skas/uaccess-skas.h deleted file mode 100644 index 224a75f4c025..000000000000 --- a/arch/um/include/skas/uaccess-skas.h +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __SKAS_UACCESS_H | ||
7 | #define __SKAS_UACCESS_H | ||
8 | |||
9 | #include "asm/errno.h" | ||
10 | |||
11 | /* No SKAS-specific checking. */ | ||
12 | #define access_ok_skas(type, addr, size) 0 | ||
13 | |||
14 | extern int copy_from_user_skas(void *to, const void __user *from, int n); | ||
15 | extern int copy_to_user_skas(void __user *to, const void *from, int n); | ||
16 | extern int strncpy_from_user_skas(char *dst, const char __user *src, int count); | ||
17 | extern int __clear_user_skas(void __user *mem, int len); | ||
18 | extern int clear_user_skas(void __user *mem, int len); | ||
19 | extern int strnlen_user_skas(const void __user *str, int len); | ||
20 | |||
21 | #endif | ||
diff --git a/arch/um/include/sysdep-i386/kernel-offsets.h b/arch/um/include/sysdep-i386/kernel-offsets.h index 97ec9d894d75..5868526b5eef 100644 --- a/arch/um/include/sysdep-i386/kernel-offsets.h +++ b/arch/um/include/sysdep-i386/kernel-offsets.h | |||
@@ -17,6 +17,5 @@ | |||
17 | 17 | ||
18 | void foo(void) | 18 | void foo(void) |
19 | { | 19 | { |
20 | OFFSET(HOST_TASK_DEBUGREGS, task_struct, thread.arch.debugregs); | ||
21 | #include <common-offsets.h> | 20 | #include <common-offsets.h> |
22 | } | 21 | } |
diff --git a/arch/um/include/sysdep-i386/ptrace.h b/arch/um/include/sysdep-i386/ptrace.h index 52b398bcafcf..11c08969d134 100644 --- a/arch/um/include/sysdep-i386/ptrace.h +++ b/arch/um/include/sysdep-i386/ptrace.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -9,17 +9,11 @@ | |||
9 | #include "uml-config.h" | 9 | #include "uml-config.h" |
10 | #include "user_constants.h" | 10 | #include "user_constants.h" |
11 | #include "sysdep/faultinfo.h" | 11 | #include "sysdep/faultinfo.h" |
12 | #include "choose-mode.h" | ||
13 | 12 | ||
14 | #define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long)) | 13 | #define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long)) |
15 | #define MAX_REG_OFFSET (UM_FRAME_SIZE) | 14 | #define MAX_REG_OFFSET (UM_FRAME_SIZE) |
16 | 15 | ||
17 | #ifdef UML_CONFIG_PT_PROXY | ||
18 | extern void update_debugregs(int seq); | ||
19 | #else | ||
20 | static inline void update_debugregs(int seq) {} | 16 | static inline void update_debugregs(int seq) {} |
21 | #endif | ||
22 | |||
23 | 17 | ||
24 | /* syscall emulation path in ptrace */ | 18 | /* syscall emulation path in ptrace */ |
25 | 19 | ||
@@ -31,12 +25,6 @@ void set_using_sysemu(int value); | |||
31 | int get_using_sysemu(void); | 25 | int get_using_sysemu(void); |
32 | extern int sysemu_supported; | 26 | extern int sysemu_supported; |
33 | 27 | ||
34 | #ifdef UML_CONFIG_MODE_TT | ||
35 | #include "sysdep/sc.h" | ||
36 | #endif | ||
37 | |||
38 | #ifdef UML_CONFIG_MODE_SKAS | ||
39 | |||
40 | #include "skas_ptregs.h" | 28 | #include "skas_ptregs.h" |
41 | 29 | ||
42 | #define REGS_IP(r) ((r)[HOST_IP]) | 30 | #define REGS_IP(r) ((r)[HOST_IP]) |
@@ -60,70 +48,36 @@ extern int sysemu_supported; | |||
60 | 48 | ||
61 | #define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r)) | 49 | #define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r)) |
62 | 50 | ||
63 | #endif | ||
64 | #ifndef PTRACE_SYSEMU_SINGLESTEP | 51 | #ifndef PTRACE_SYSEMU_SINGLESTEP |
65 | #define PTRACE_SYSEMU_SINGLESTEP 32 | 52 | #define PTRACE_SYSEMU_SINGLESTEP 32 |
66 | #endif | 53 | #endif |
67 | 54 | ||
68 | union uml_pt_regs { | 55 | struct uml_pt_regs { |
69 | #ifdef UML_CONFIG_MODE_TT | 56 | unsigned long gp[MAX_REG_NR]; |
70 | struct tt_regs { | 57 | struct faultinfo faultinfo; |
71 | long syscall; | 58 | long syscall; |
72 | void *sc; | 59 | int is_user; |
73 | struct faultinfo faultinfo; | ||
74 | } tt; | ||
75 | #endif | ||
76 | #ifdef UML_CONFIG_MODE_SKAS | ||
77 | struct skas_regs { | ||
78 | unsigned long regs[MAX_REG_NR]; | ||
79 | unsigned long fp[HOST_FP_SIZE]; | ||
80 | unsigned long xfp[HOST_XFP_SIZE]; | ||
81 | struct faultinfo faultinfo; | ||
82 | long syscall; | ||
83 | int is_user; | ||
84 | } skas; | ||
85 | #endif | ||
86 | }; | 60 | }; |
87 | 61 | ||
88 | #define EMPTY_UML_PT_REGS { } | 62 | #define EMPTY_UML_PT_REGS { } |
89 | 63 | ||
90 | extern int mode_tt; | 64 | #define UPT_IP(r) REGS_IP((r)->gp) |
91 | 65 | #define UPT_SP(r) REGS_SP((r)->gp) | |
92 | #define UPT_SC(r) ((r)->tt.sc) | 66 | #define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp) |
93 | #define UPT_IP(r) \ | 67 | #define UPT_EAX(r) REGS_EAX((r)->gp) |
94 | __CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs)) | 68 | #define UPT_EBX(r) REGS_EBX((r)->gp) |
95 | #define UPT_SP(r) \ | 69 | #define UPT_ECX(r) REGS_ECX((r)->gp) |
96 | __CHOOSE_MODE(SC_SP(UPT_SC(r)), REGS_SP((r)->skas.regs)) | 70 | #define UPT_EDX(r) REGS_EDX((r)->gp) |
97 | #define UPT_EFLAGS(r) \ | 71 | #define UPT_ESI(r) REGS_ESI((r)->gp) |
98 | __CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs)) | 72 | #define UPT_EDI(r) REGS_EDI((r)->gp) |
99 | #define UPT_EAX(r) \ | 73 | #define UPT_EBP(r) REGS_EBP((r)->gp) |
100 | __CHOOSE_MODE(SC_EAX(UPT_SC(r)), REGS_EAX((r)->skas.regs)) | 74 | #define UPT_ORIG_EAX(r) ((r)->syscall) |
101 | #define UPT_EBX(r) \ | 75 | #define UPT_CS(r) REGS_CS((r)->gp) |
102 | __CHOOSE_MODE(SC_EBX(UPT_SC(r)), REGS_EBX((r)->skas.regs)) | 76 | #define UPT_SS(r) REGS_SS((r)->gp) |
103 | #define UPT_ECX(r) \ | 77 | #define UPT_DS(r) REGS_DS((r)->gp) |
104 | __CHOOSE_MODE(SC_ECX(UPT_SC(r)), REGS_ECX((r)->skas.regs)) | 78 | #define UPT_ES(r) REGS_ES((r)->gp) |
105 | #define UPT_EDX(r) \ | 79 | #define UPT_FS(r) REGS_FS((r)->gp) |
106 | __CHOOSE_MODE(SC_EDX(UPT_SC(r)), REGS_EDX((r)->skas.regs)) | 80 | #define UPT_GS(r) REGS_GS((r)->gp) |
107 | #define UPT_ESI(r) \ | ||
108 | __CHOOSE_MODE(SC_ESI(UPT_SC(r)), REGS_ESI((r)->skas.regs)) | ||
109 | #define UPT_EDI(r) \ | ||
110 | __CHOOSE_MODE(SC_EDI(UPT_SC(r)), REGS_EDI((r)->skas.regs)) | ||
111 | #define UPT_EBP(r) \ | ||
112 | __CHOOSE_MODE(SC_EBP(UPT_SC(r)), REGS_EBP((r)->skas.regs)) | ||
113 | #define UPT_ORIG_EAX(r) \ | ||
114 | __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall) | ||
115 | #define UPT_CS(r) \ | ||
116 | __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) | ||
117 | #define UPT_SS(r) \ | ||
118 | __CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs)) | ||
119 | #define UPT_DS(r) \ | ||
120 | __CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs)) | ||
121 | #define UPT_ES(r) \ | ||
122 | __CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs)) | ||
123 | #define UPT_FS(r) \ | ||
124 | __CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs)) | ||
125 | #define UPT_GS(r) \ | ||
126 | __CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs)) | ||
127 | 81 | ||
128 | #define UPT_SYSCALL_ARG1(r) UPT_EBX(r) | 82 | #define UPT_SYSCALL_ARG1(r) UPT_EBX(r) |
129 | #define UPT_SYSCALL_ARG2(r) UPT_ECX(r) | 83 | #define UPT_SYSCALL_ARG2(r) UPT_ECX(r) |
@@ -134,20 +88,19 @@ extern int mode_tt; | |||
134 | 88 | ||
135 | extern int user_context(unsigned long sp); | 89 | extern int user_context(unsigned long sp); |
136 | 90 | ||
137 | #define UPT_IS_USER(r) \ | 91 | #define UPT_IS_USER(r) ((r)->is_user) |
138 | CHOOSE_MODE(user_context(UPT_SP(r)), (r)->skas.is_user) | ||
139 | 92 | ||
140 | struct syscall_args { | 93 | struct syscall_args { |
141 | unsigned long args[6]; | 94 | unsigned long args[6]; |
142 | }; | 95 | }; |
143 | 96 | ||
144 | #define SYSCALL_ARGS(r) ((struct syscall_args) \ | 97 | #define SYSCALL_ARGS(r) ((struct syscall_args) \ |
145 | { .args = { UPT_SYSCALL_ARG1(r), \ | 98 | { .args = { UPT_SYSCALL_ARG1(r), \ |
146 | UPT_SYSCALL_ARG2(r), \ | 99 | UPT_SYSCALL_ARG2(r), \ |
147 | UPT_SYSCALL_ARG3(r), \ | 100 | UPT_SYSCALL_ARG3(r), \ |
148 | UPT_SYSCALL_ARG4(r), \ | 101 | UPT_SYSCALL_ARG4(r), \ |
149 | UPT_SYSCALL_ARG5(r), \ | 102 | UPT_SYSCALL_ARG5(r), \ |
150 | UPT_SYSCALL_ARG6(r) } } ) | 103 | UPT_SYSCALL_ARG6(r) } } ) |
151 | 104 | ||
152 | #define UPT_REG(regs, reg) \ | 105 | #define UPT_REG(regs, reg) \ |
153 | ({ unsigned long val; \ | 106 | ({ unsigned long val; \ |
@@ -175,7 +128,6 @@ struct syscall_args { | |||
175 | } \ | 128 | } \ |
176 | val; \ | 129 | val; \ |
177 | }) | 130 | }) |
178 | |||
179 | 131 | ||
180 | #define UPT_SET(regs, reg, val) \ | 132 | #define UPT_SET(regs, reg, val) \ |
181 | do { \ | 133 | do { \ |
@@ -204,29 +156,16 @@ struct syscall_args { | |||
204 | } while (0) | 156 | } while (0) |
205 | 157 | ||
206 | #define UPT_SET_SYSCALL_RETURN(r, res) \ | 158 | #define UPT_SET_SYSCALL_RETURN(r, res) \ |
207 | CHOOSE_MODE(SC_SET_SYSCALL_RETURN(UPT_SC(r), (res)), \ | 159 | REGS_SET_SYSCALL_RETURN((r)->regs, (res)) |
208 | REGS_SET_SYSCALL_RETURN((r)->skas.regs, (res))) | ||
209 | 160 | ||
210 | #define UPT_RESTART_SYSCALL(r) \ | 161 | #define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp) |
211 | CHOOSE_MODE(SC_RESTART_SYSCALL(UPT_SC(r)), \ | ||
212 | REGS_RESTART_SYSCALL((r)->skas.regs)) | ||
213 | 162 | ||
214 | #define UPT_ORIG_SYSCALL(r) UPT_EAX(r) | 163 | #define UPT_ORIG_SYSCALL(r) UPT_EAX(r) |
215 | #define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r) | 164 | #define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r) |
216 | #define UPT_SYSCALL_RET(r) UPT_EAX(r) | 165 | #define UPT_SYSCALL_RET(r) UPT_EAX(r) |
217 | 166 | ||
218 | #define UPT_FAULTINFO(r) \ | 167 | #define UPT_FAULTINFO(r) (&(r)->faultinfo) |
219 | CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo)) | ||
220 | 168 | ||
221 | #endif | 169 | extern void arch_init_registers(int pid); |
222 | 170 | ||
223 | /* | 171 | #endif |
224 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
225 | * Emacs will notice this stuff at the end of the file and automatically | ||
226 | * adjust the settings for this buffer only. This must remain at the end | ||
227 | * of the file. | ||
228 | * --------------------------------------------------------------------------- | ||
229 | * Local variables: | ||
230 | * c-file-style: "linux" | ||
231 | * End: | ||
232 | */ | ||
diff --git a/arch/um/include/sysdep-i386/sigcontext.h b/arch/um/include/sysdep-i386/sigcontext.h index 23fd2644d7ed..67e77122aa45 100644 --- a/arch/um/include/sysdep-i386/sigcontext.h +++ b/arch/um/include/sysdep-i386/sigcontext.h | |||
@@ -1,19 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #ifndef __SYS_SIGCONTEXT_I386_H | 6 | #ifndef __SYS_SIGCONTEXT_I386_H |
7 | #define __SYS_SIGCONTEXT_I386_H | 7 | #define __SYS_SIGCONTEXT_I386_H |
8 | 8 | ||
9 | #include "uml-config.h" | 9 | #include "sysdep/sc.h" |
10 | #include <sysdep/sc.h> | ||
11 | 10 | ||
12 | #define IP_RESTART_SYSCALL(ip) ((ip) -= 2) | 11 | #define IP_RESTART_SYSCALL(ip) ((ip) -= 2) |
13 | 12 | ||
14 | #define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc)) | ||
15 | #define SC_SET_SYSCALL_RETURN(sc, result) SC_EAX(sc) = (result) | ||
16 | |||
17 | #define GET_FAULTINFO_FROM_SC(fi,sc) \ | 13 | #define GET_FAULTINFO_FROM_SC(fi,sc) \ |
18 | { \ | 14 | { \ |
19 | (fi).cr2 = SC_CR2(sc); \ | 15 | (fi).cr2 = SC_CR2(sc); \ |
@@ -21,32 +17,10 @@ | |||
21 | (fi).trap_no = SC_TRAPNO(sc); \ | 17 | (fi).trap_no = SC_TRAPNO(sc); \ |
22 | } | 18 | } |
23 | 19 | ||
24 | /* ptrace expects that, at the start of a system call, %eax contains | ||
25 | * -ENOSYS, so this makes it so. | ||
26 | */ | ||
27 | #define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0) | ||
28 | |||
29 | /* This is Page Fault */ | 20 | /* This is Page Fault */ |
30 | #define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14) | 21 | #define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14) |
31 | 22 | ||
32 | /* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */ | 23 | /* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */ |
33 | #ifdef UML_CONFIG_MODE_SKAS | ||
34 | #define SEGV_MAYBE_FIXABLE(fi) ((fi)->trap_no == 0 && ptrace_faultinfo) | 24 | #define SEGV_MAYBE_FIXABLE(fi) ((fi)->trap_no == 0 && ptrace_faultinfo) |
35 | #else | ||
36 | #define SEGV_MAYBE_FIXABLE(fi) 0 | ||
37 | #endif | ||
38 | |||
39 | extern unsigned long *sc_sigmask(void *sc_ptr); | ||
40 | extern int sc_get_fpregs(unsigned long buf, void *sc_ptr); | ||
41 | 25 | ||
42 | #endif | 26 | #endif |
43 | /* | ||
44 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
45 | * Emacs will notice this stuff at the end of the file and automatically | ||
46 | * adjust the settings for this buffer only. This must remain at the end | ||
47 | * of the file. | ||
48 | * --------------------------------------------------------------------------- | ||
49 | * Local variables: | ||
50 | * c-file-style: "linux" | ||
51 | * End: | ||
52 | */ | ||
diff --git a/arch/um/include/sysdep-i386/stub.h b/arch/um/include/sysdep-i386/stub.h index 4fffae75ba53..8c097b87fca7 100644 --- a/arch/um/include/sysdep-i386/stub.h +++ b/arch/um/include/sysdep-i386/stub.h | |||
@@ -9,7 +9,7 @@ | |||
9 | #include <sys/mman.h> | 9 | #include <sys/mman.h> |
10 | #include <asm/ptrace.h> | 10 | #include <asm/ptrace.h> |
11 | #include <asm/unistd.h> | 11 | #include <asm/unistd.h> |
12 | #include <asm/page.h> | 12 | #include "as-layout.h" |
13 | #include "stub-data.h" | 13 | #include "stub-data.h" |
14 | #include "kern_constants.h" | 14 | #include "kern_constants.h" |
15 | #include "uml-config.h" | 15 | #include "uml-config.h" |
@@ -19,7 +19,7 @@ extern void stub_clone_handler(void); | |||
19 | 19 | ||
20 | #define STUB_SYSCALL_RET EAX | 20 | #define STUB_SYSCALL_RET EAX |
21 | #define STUB_MMAP_NR __NR_mmap2 | 21 | #define STUB_MMAP_NR __NR_mmap2 |
22 | #define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT) | 22 | #define MMAP_OFFSET(o) ((o) >> UM_KERN_PAGE_SHIFT) |
23 | 23 | ||
24 | static inline long stub_syscall0(long syscall) | 24 | static inline long stub_syscall0(long syscall) |
25 | { | 25 | { |
@@ -90,12 +90,12 @@ static inline void remap_stack(int fd, unsigned long offset) | |||
90 | { | 90 | { |
91 | __asm__ volatile ("movl %%eax,%%ebp ; movl %0,%%eax ; int $0x80 ;" | 91 | __asm__ volatile ("movl %%eax,%%ebp ; movl %0,%%eax ; int $0x80 ;" |
92 | "movl %7, %%ebx ; movl %%eax, (%%ebx)" | 92 | "movl %7, %%ebx ; movl %%eax, (%%ebx)" |
93 | : : "g" (STUB_MMAP_NR), "b" (UML_CONFIG_STUB_DATA), | 93 | : : "g" (STUB_MMAP_NR), "b" (STUB_DATA), |
94 | "c" (UM_KERN_PAGE_SIZE), | 94 | "c" (UM_KERN_PAGE_SIZE), |
95 | "d" (PROT_READ | PROT_WRITE), | 95 | "d" (PROT_READ | PROT_WRITE), |
96 | "S" (MAP_FIXED | MAP_SHARED), "D" (fd), | 96 | "S" (MAP_FIXED | MAP_SHARED), "D" (fd), |
97 | "a" (offset), | 97 | "a" (offset), |
98 | "i" (&((struct stub_data *) UML_CONFIG_STUB_DATA)->err) | 98 | "i" (&((struct stub_data *) STUB_DATA)->err) |
99 | : "memory"); | 99 | : "memory"); |
100 | } | 100 | } |
101 | 101 | ||
diff --git a/arch/um/include/sysdep-i386/thread.h b/arch/um/include/sysdep-i386/thread.h deleted file mode 100644 index 243fed44d780..000000000000 --- a/arch/um/include/sysdep-i386/thread.h +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | #ifndef __UM_THREAD_H | ||
2 | #define __UM_THREAD_H | ||
3 | |||
4 | #include <kern_constants.h> | ||
5 | |||
6 | #define TASK_DEBUGREGS(task) ((unsigned long *) &(((char *) (task))[HOST_TASK_DEBUGREGS])) | ||
7 | #ifdef UML_CONFIG_MODE_TT | ||
8 | #define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[HOST_TASK_EXTERN_PID])) | ||
9 | #endif | ||
10 | |||
11 | #endif | ||
diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h index 62403bd99661..9ea44d111f33 100644 --- a/arch/um/include/sysdep-x86_64/ptrace.h +++ b/arch/um/include/sysdep-x86_64/ptrace.h | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 2003 PathScale, Inc. | 2 | * Copyright 2003 PathScale, Inc. |
3 | * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
3 | * | 4 | * |
4 | * Licensed under the GPL | 5 | * Licensed under the GPL |
5 | */ | 6 | */ |
@@ -14,11 +15,6 @@ | |||
14 | #define MAX_REG_OFFSET (UM_FRAME_SIZE) | 15 | #define MAX_REG_OFFSET (UM_FRAME_SIZE) |
15 | #define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long)) | 16 | #define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long)) |
16 | 17 | ||
17 | #ifdef UML_CONFIG_MODE_TT | ||
18 | #include "sysdep/sc.h" | ||
19 | #endif | ||
20 | |||
21 | #ifdef UML_CONFIG_MODE_SKAS | ||
22 | #include "skas_ptregs.h" | 18 | #include "skas_ptregs.h" |
23 | 19 | ||
24 | #define REGS_IP(r) ((r)[HOST_IP]) | 20 | #define REGS_IP(r) ((r)[HOST_IP]) |
@@ -88,78 +84,51 @@ | |||
88 | 84 | ||
89 | #define REGS_ERR(r) ((r)->fault_type) | 85 | #define REGS_ERR(r) ((r)->fault_type) |
90 | 86 | ||
91 | #endif | 87 | struct uml_pt_regs { |
92 | 88 | unsigned long gp[MAX_REG_NR]; | |
93 | #include "choose-mode.h" | 89 | struct faultinfo faultinfo; |
94 | 90 | long syscall; | |
95 | /* XXX */ | 91 | int is_user; |
96 | union uml_pt_regs { | ||
97 | #ifdef UML_CONFIG_MODE_TT | ||
98 | struct tt_regs { | ||
99 | long syscall; | ||
100 | unsigned long orig_rax; | ||
101 | void *sc; | ||
102 | struct faultinfo faultinfo; | ||
103 | } tt; | ||
104 | #endif | ||
105 | #ifdef UML_CONFIG_MODE_SKAS | ||
106 | struct skas_regs { | ||
107 | unsigned long regs[MAX_REG_NR]; | ||
108 | unsigned long fp[HOST_FP_SIZE]; | ||
109 | struct faultinfo faultinfo; | ||
110 | long syscall; | ||
111 | int is_user; | ||
112 | } skas; | ||
113 | #endif | ||
114 | }; | 92 | }; |
115 | 93 | ||
116 | #define EMPTY_UML_PT_REGS { } | 94 | #define EMPTY_UML_PT_REGS { } |
117 | 95 | ||
118 | /* XXX */ | 96 | #define UPT_RBX(r) REGS_RBX((r)->gp) |
119 | extern int mode_tt; | 97 | #define UPT_RCX(r) REGS_RCX((r)->gp) |
120 | 98 | #define UPT_RDX(r) REGS_RDX((r)->gp) | |
121 | #define UPT_RBX(r) __CHOOSE_MODE(SC_RBX(UPT_SC(r)), REGS_RBX((r)->skas.regs)) | 99 | #define UPT_RSI(r) REGS_RSI((r)->gp) |
122 | #define UPT_RCX(r) __CHOOSE_MODE(SC_RCX(UPT_SC(r)), REGS_RCX((r)->skas.regs)) | 100 | #define UPT_RDI(r) REGS_RDI((r)->gp) |
123 | #define UPT_RDX(r) __CHOOSE_MODE(SC_RDX(UPT_SC(r)), REGS_RDX((r)->skas.regs)) | 101 | #define UPT_RBP(r) REGS_RBP((r)->gp) |
124 | #define UPT_RSI(r) __CHOOSE_MODE(SC_RSI(UPT_SC(r)), REGS_RSI((r)->skas.regs)) | 102 | #define UPT_RAX(r) REGS_RAX((r)->gp) |
125 | #define UPT_RDI(r) __CHOOSE_MODE(SC_RDI(UPT_SC(r)), REGS_RDI((r)->skas.regs)) | 103 | #define UPT_R8(r) REGS_R8((r)->gp) |
126 | #define UPT_RBP(r) __CHOOSE_MODE(SC_RBP(UPT_SC(r)), REGS_RBP((r)->skas.regs)) | 104 | #define UPT_R9(r) REGS_R9((r)->gp) |
127 | #define UPT_RAX(r) __CHOOSE_MODE(SC_RAX(UPT_SC(r)), REGS_RAX((r)->skas.regs)) | 105 | #define UPT_R10(r) REGS_R10((r)->gp) |
128 | #define UPT_R8(r) __CHOOSE_MODE(SC_R8(UPT_SC(r)), REGS_R8((r)->skas.regs)) | 106 | #define UPT_R11(r) REGS_R11((r)->gp) |
129 | #define UPT_R9(r) __CHOOSE_MODE(SC_R9(UPT_SC(r)), REGS_R9((r)->skas.regs)) | 107 | #define UPT_R12(r) REGS_R12((r)->gp) |
130 | #define UPT_R10(r) __CHOOSE_MODE(SC_R10(UPT_SC(r)), REGS_R10((r)->skas.regs)) | 108 | #define UPT_R13(r) REGS_R13((r)->gp) |
131 | #define UPT_R11(r) __CHOOSE_MODE(SC_R11(UPT_SC(r)), REGS_R11((r)->skas.regs)) | 109 | #define UPT_R14(r) REGS_R14((r)->gp) |
132 | #define UPT_R12(r) __CHOOSE_MODE(SC_R12(UPT_SC(r)), REGS_R12((r)->skas.regs)) | 110 | #define UPT_R15(r) REGS_R15((r)->gp) |
133 | #define UPT_R13(r) __CHOOSE_MODE(SC_R13(UPT_SC(r)), REGS_R13((r)->skas.regs)) | 111 | #define UPT_CS(r) REGS_CS((r)->gp) |
134 | #define UPT_R14(r) __CHOOSE_MODE(SC_R14(UPT_SC(r)), REGS_R14((r)->skas.regs)) | 112 | #define UPT_FS_BASE(r) REGS_FS_BASE((r)->gp) |
135 | #define UPT_R15(r) __CHOOSE_MODE(SC_R15(UPT_SC(r)), REGS_R15((r)->skas.regs)) | 113 | #define UPT_FS(r) REGS_FS((r)->gp) |
136 | #define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) | 114 | #define UPT_GS_BASE(r) REGS_GS_BASE((r)->gp) |
137 | #define UPT_FS_BASE(r) \ | 115 | #define UPT_GS(r) REGS_GS((r)->gp) |
138 | __CHOOSE_MODE(SC_FS_BASE(UPT_SC(r)), REGS_FS_BASE((r)->skas.regs)) | 116 | #define UPT_DS(r) REGS_DS((r)->gp) |
139 | #define UPT_FS(r) __CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs)) | 117 | #define UPT_ES(r) REGS_ES((r)->gp) |
140 | #define UPT_GS_BASE(r) \ | 118 | #define UPT_CS(r) REGS_CS((r)->gp) |
141 | __CHOOSE_MODE(SC_GS_BASE(UPT_SC(r)), REGS_GS_BASE((r)->skas.regs)) | 119 | #define UPT_SS(r) REGS_SS((r)->gp) |
142 | #define UPT_GS(r) __CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs)) | 120 | #define UPT_ORIG_RAX(r) REGS_ORIG_RAX((r)->gp) |
143 | #define UPT_DS(r) __CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs)) | 121 | |
144 | #define UPT_ES(r) __CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs)) | 122 | #define UPT_IP(r) REGS_IP((r)->gp) |
145 | #define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) | 123 | #define UPT_SP(r) REGS_SP((r)->gp) |
146 | #define UPT_SS(r) __CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs)) | 124 | |
147 | #define UPT_ORIG_RAX(r) \ | 125 | #define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp) |
148 | __CHOOSE_MODE((r)->tt.orig_rax, REGS_ORIG_RAX((r)->skas.regs)) | 126 | #define UPT_SYSCALL_NR(r) ((r)->syscall) |
149 | |||
150 | #define UPT_IP(r) __CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs)) | ||
151 | #define UPT_SP(r) __CHOOSE_MODE(SC_SP(UPT_SC(r)), REGS_SP((r)->skas.regs)) | ||
152 | |||
153 | #define UPT_EFLAGS(r) \ | ||
154 | __CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs)) | ||
155 | #define UPT_SC(r) ((r)->tt.sc) | ||
156 | #define UPT_SYSCALL_NR(r) __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall) | ||
157 | #define UPT_SYSCALL_RET(r) UPT_RAX(r) | 127 | #define UPT_SYSCALL_RET(r) UPT_RAX(r) |
158 | 128 | ||
159 | extern int user_context(unsigned long sp); | 129 | extern int user_context(unsigned long sp); |
160 | 130 | ||
161 | #define UPT_IS_USER(r) \ | 131 | #define UPT_IS_USER(r) ((r)->is_user) |
162 | CHOOSE_MODE(user_context(UPT_SP(r)), (r)->skas.is_user) | ||
163 | 132 | ||
164 | #define UPT_SYSCALL_ARG1(r) UPT_RDI(r) | 133 | #define UPT_SYSCALL_ARG1(r) UPT_RDI(r) |
165 | #define UPT_SYSCALL_ARG2(r) UPT_RSI(r) | 134 | #define UPT_SYSCALL_ARG2(r) UPT_RSI(r) |
@@ -173,101 +142,99 @@ struct syscall_args { | |||
173 | }; | 142 | }; |
174 | 143 | ||
175 | #define SYSCALL_ARGS(r) ((struct syscall_args) \ | 144 | #define SYSCALL_ARGS(r) ((struct syscall_args) \ |
176 | { .args = { UPT_SYSCALL_ARG1(r), \ | 145 | { .args = { UPT_SYSCALL_ARG1(r), \ |
177 | UPT_SYSCALL_ARG2(r), \ | 146 | UPT_SYSCALL_ARG2(r), \ |
178 | UPT_SYSCALL_ARG3(r), \ | 147 | UPT_SYSCALL_ARG3(r), \ |
179 | UPT_SYSCALL_ARG4(r), \ | 148 | UPT_SYSCALL_ARG4(r), \ |
180 | UPT_SYSCALL_ARG5(r), \ | 149 | UPT_SYSCALL_ARG5(r), \ |
181 | UPT_SYSCALL_ARG6(r) } } ) | 150 | UPT_SYSCALL_ARG6(r) } } ) |
182 | 151 | ||
183 | #define UPT_REG(regs, reg) \ | 152 | #define UPT_REG(regs, reg) \ |
184 | ({ unsigned long val; \ | 153 | ({ unsigned long val; \ |
185 | switch(reg){ \ | 154 | switch(reg){ \ |
186 | case R8: val = UPT_R8(regs); break; \ | 155 | case R8: val = UPT_R8(regs); break; \ |
187 | case R9: val = UPT_R9(regs); break; \ | 156 | case R9: val = UPT_R9(regs); break; \ |
188 | case R10: val = UPT_R10(regs); break; \ | 157 | case R10: val = UPT_R10(regs); break; \ |
189 | case R11: val = UPT_R11(regs); break; \ | 158 | case R11: val = UPT_R11(regs); break; \ |
190 | case R12: val = UPT_R12(regs); break; \ | 159 | case R12: val = UPT_R12(regs); break; \ |
191 | case R13: val = UPT_R13(regs); break; \ | 160 | case R13: val = UPT_R13(regs); break; \ |
192 | case R14: val = UPT_R14(regs); break; \ | 161 | case R14: val = UPT_R14(regs); break; \ |
193 | case R15: val = UPT_R15(regs); break; \ | 162 | case R15: val = UPT_R15(regs); break; \ |
194 | case RIP: val = UPT_IP(regs); break; \ | 163 | case RIP: val = UPT_IP(regs); break; \ |
195 | case RSP: val = UPT_SP(regs); break; \ | 164 | case RSP: val = UPT_SP(regs); break; \ |
196 | case RAX: val = UPT_RAX(regs); break; \ | 165 | case RAX: val = UPT_RAX(regs); break; \ |
197 | case RBX: val = UPT_RBX(regs); break; \ | 166 | case RBX: val = UPT_RBX(regs); break; \ |
198 | case RCX: val = UPT_RCX(regs); break; \ | 167 | case RCX: val = UPT_RCX(regs); break; \ |
199 | case RDX: val = UPT_RDX(regs); break; \ | 168 | case RDX: val = UPT_RDX(regs); break; \ |
200 | case RSI: val = UPT_RSI(regs); break; \ | 169 | case RSI: val = UPT_RSI(regs); break; \ |
201 | case RDI: val = UPT_RDI(regs); break; \ | 170 | case RDI: val = UPT_RDI(regs); break; \ |
202 | case RBP: val = UPT_RBP(regs); break; \ | 171 | case RBP: val = UPT_RBP(regs); break; \ |
203 | case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \ | 172 | case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \ |
204 | case CS: val = UPT_CS(regs); break; \ | 173 | case CS: val = UPT_CS(regs); break; \ |
205 | case SS: val = UPT_SS(regs); break; \ | 174 | case SS: val = UPT_SS(regs); break; \ |
206 | case FS_BASE: val = UPT_FS_BASE(regs); break; \ | 175 | case FS_BASE: val = UPT_FS_BASE(regs); break; \ |
207 | case GS_BASE: val = UPT_GS_BASE(regs); break; \ | 176 | case GS_BASE: val = UPT_GS_BASE(regs); break; \ |
208 | case DS: val = UPT_DS(regs); break; \ | 177 | case DS: val = UPT_DS(regs); break; \ |
209 | case ES: val = UPT_ES(regs); break; \ | 178 | case ES: val = UPT_ES(regs); break; \ |
210 | case FS : val = UPT_FS (regs); break; \ | 179 | case FS : val = UPT_FS (regs); break; \ |
211 | case GS: val = UPT_GS(regs); break; \ | 180 | case GS: val = UPT_GS(regs); break; \ |
212 | case EFLAGS: val = UPT_EFLAGS(regs); break; \ | 181 | case EFLAGS: val = UPT_EFLAGS(regs); break; \ |
213 | default : \ | 182 | default : \ |
214 | panic("Bad register in UPT_REG : %d\n", reg); \ | 183 | panic("Bad register in UPT_REG : %d\n", reg); \ |
215 | val = -1; \ | 184 | val = -1; \ |
216 | } \ | 185 | } \ |
217 | val; \ | 186 | val; \ |
218 | }) | 187 | }) |
219 | 188 | ||
220 | 189 | ||
221 | #define UPT_SET(regs, reg, val) \ | 190 | #define UPT_SET(regs, reg, val) \ |
222 | ({ unsigned long __upt_val = val; \ | 191 | ({ unsigned long __upt_val = val; \ |
223 | switch(reg){ \ | 192 | switch(reg){ \ |
224 | case R8: UPT_R8(regs) = __upt_val; break; \ | 193 | case R8: UPT_R8(regs) = __upt_val; break; \ |
225 | case R9: UPT_R9(regs) = __upt_val; break; \ | 194 | case R9: UPT_R9(regs) = __upt_val; break; \ |
226 | case R10: UPT_R10(regs) = __upt_val; break; \ | 195 | case R10: UPT_R10(regs) = __upt_val; break; \ |
227 | case R11: UPT_R11(regs) = __upt_val; break; \ | 196 | case R11: UPT_R11(regs) = __upt_val; break; \ |
228 | case R12: UPT_R12(regs) = __upt_val; break; \ | 197 | case R12: UPT_R12(regs) = __upt_val; break; \ |
229 | case R13: UPT_R13(regs) = __upt_val; break; \ | 198 | case R13: UPT_R13(regs) = __upt_val; break; \ |
230 | case R14: UPT_R14(regs) = __upt_val; break; \ | 199 | case R14: UPT_R14(regs) = __upt_val; break; \ |
231 | case R15: UPT_R15(regs) = __upt_val; break; \ | 200 | case R15: UPT_R15(regs) = __upt_val; break; \ |
232 | case RIP: UPT_IP(regs) = __upt_val; break; \ | 201 | case RIP: UPT_IP(regs) = __upt_val; break; \ |
233 | case RSP: UPT_SP(regs) = __upt_val; break; \ | 202 | case RSP: UPT_SP(regs) = __upt_val; break; \ |
234 | case RAX: UPT_RAX(regs) = __upt_val; break; \ | 203 | case RAX: UPT_RAX(regs) = __upt_val; break; \ |
235 | case RBX: UPT_RBX(regs) = __upt_val; break; \ | 204 | case RBX: UPT_RBX(regs) = __upt_val; break; \ |
236 | case RCX: UPT_RCX(regs) = __upt_val; break; \ | 205 | case RCX: UPT_RCX(regs) = __upt_val; break; \ |
237 | case RDX: UPT_RDX(regs) = __upt_val; break; \ | 206 | case RDX: UPT_RDX(regs) = __upt_val; break; \ |
238 | case RSI: UPT_RSI(regs) = __upt_val; break; \ | 207 | case RSI: UPT_RSI(regs) = __upt_val; break; \ |
239 | case RDI: UPT_RDI(regs) = __upt_val; break; \ | 208 | case RDI: UPT_RDI(regs) = __upt_val; break; \ |
240 | case RBP: UPT_RBP(regs) = __upt_val; break; \ | 209 | case RBP: UPT_RBP(regs) = __upt_val; break; \ |
241 | case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \ | 210 | case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \ |
242 | case CS: UPT_CS(regs) = __upt_val; break; \ | 211 | case CS: UPT_CS(regs) = __upt_val; break; \ |
243 | case SS: UPT_SS(regs) = __upt_val; break; \ | 212 | case SS: UPT_SS(regs) = __upt_val; break; \ |
244 | case FS_BASE: UPT_FS_BASE(regs) = __upt_val; break; \ | 213 | case FS_BASE: UPT_FS_BASE(regs) = __upt_val; break; \ |
245 | case GS_BASE: UPT_GS_BASE(regs) = __upt_val; break; \ | 214 | case GS_BASE: UPT_GS_BASE(regs) = __upt_val; break; \ |
246 | case DS: UPT_DS(regs) = __upt_val; break; \ | 215 | case DS: UPT_DS(regs) = __upt_val; break; \ |
247 | case ES: UPT_ES(regs) = __upt_val; break; \ | 216 | case ES: UPT_ES(regs) = __upt_val; break; \ |
248 | case FS: UPT_FS(regs) = __upt_val; break; \ | 217 | case FS: UPT_FS(regs) = __upt_val; break; \ |
249 | case GS: UPT_GS(regs) = __upt_val; break; \ | 218 | case GS: UPT_GS(regs) = __upt_val; break; \ |
250 | case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \ | 219 | case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \ |
251 | default : \ | 220 | default : \ |
252 | panic("Bad register in UPT_SET : %d\n", reg); \ | 221 | panic("Bad register in UPT_SET : %d\n", reg); \ |
253 | break; \ | 222 | break; \ |
254 | } \ | 223 | } \ |
255 | __upt_val; \ | 224 | __upt_val; \ |
256 | }) | 225 | }) |
257 | 226 | ||
258 | #define UPT_SET_SYSCALL_RETURN(r, res) \ | 227 | #define UPT_SET_SYSCALL_RETURN(r, res) \ |
259 | CHOOSE_MODE(SC_SET_SYSCALL_RETURN(UPT_SC(r), (res)), \ | 228 | REGS_SET_SYSCALL_RETURN((r)->regs, (res)) |
260 | REGS_SET_SYSCALL_RETURN((r)->skas.regs, (res))) | 229 | |
230 | #define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp) | ||
261 | 231 | ||
262 | #define UPT_RESTART_SYSCALL(r) \ | 232 | #define UPT_SEGV_IS_FIXABLE(r) REGS_SEGV_IS_FIXABLE(&r->skas) |
263 | CHOOSE_MODE(SC_RESTART_SYSCALL(UPT_SC(r)), \ | ||
264 | REGS_RESTART_SYSCALL((r)->skas.regs)) | ||
265 | 233 | ||
266 | #define UPT_SEGV_IS_FIXABLE(r) \ | 234 | #define UPT_FAULTINFO(r) (&(r)->faultinfo) |
267 | CHOOSE_MODE(SC_SEGV_IS_FIXABLE(UPT_SC(r)), \ | ||
268 | REGS_SEGV_IS_FIXABLE(&r->skas)) | ||
269 | 235 | ||
270 | #define UPT_FAULTINFO(r) \ | 236 | static inline void arch_init_registers(int pid) |
271 | CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo)) | 237 | { |
238 | } | ||
272 | 239 | ||
273 | #endif | 240 | #endif |
diff --git a/arch/um/include/sysdep-x86_64/sigcontext.h b/arch/um/include/sysdep-x86_64/sigcontext.h index 41073235e7ad..0155133b1458 100644 --- a/arch/um/include/sysdep-x86_64/sigcontext.h +++ b/arch/um/include/sysdep-x86_64/sigcontext.h | |||
@@ -11,43 +11,17 @@ | |||
11 | 11 | ||
12 | #define IP_RESTART_SYSCALL(ip) ((ip) -= 2) | 12 | #define IP_RESTART_SYSCALL(ip) ((ip) -= 2) |
13 | 13 | ||
14 | #define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc)) | 14 | #define GET_FAULTINFO_FROM_SC(fi, sc) \ |
15 | #define SC_SET_SYSCALL_RETURN(sc, result) SC_RAX(sc) = (result) | ||
16 | |||
17 | #define SC_FAULT_ADDR(sc) SC_CR2(sc) | ||
18 | #define SC_FAULT_TYPE(sc) SC_ERR(sc) | ||
19 | |||
20 | #define GET_FAULTINFO_FROM_SC(fi,sc) \ | ||
21 | { \ | 15 | { \ |
22 | (fi).cr2 = SC_CR2(sc); \ | 16 | (fi).cr2 = SC_CR2(sc); \ |
23 | (fi).error_code = SC_ERR(sc); \ | 17 | (fi).error_code = SC_ERR(sc); \ |
24 | (fi).trap_no = SC_TRAPNO(sc); \ | 18 | (fi).trap_no = SC_TRAPNO(sc); \ |
25 | } | 19 | } |
26 | 20 | ||
27 | /* ptrace expects that, at the start of a system call, %eax contains | ||
28 | * -ENOSYS, so this makes it so. | ||
29 | */ | ||
30 | |||
31 | #define SC_START_SYSCALL(sc) do SC_RAX(sc) = -ENOSYS; while(0) | ||
32 | |||
33 | /* This is Page Fault */ | 21 | /* This is Page Fault */ |
34 | #define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14) | 22 | #define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14) |
35 | 23 | ||
36 | /* No broken SKAS API, which doesn't pass trap_no, here. */ | 24 | /* No broken SKAS API, which doesn't pass trap_no, here. */ |
37 | #define SEGV_MAYBE_FIXABLE(fi) 0 | 25 | #define SEGV_MAYBE_FIXABLE(fi) 0 |
38 | 26 | ||
39 | extern unsigned long *sc_sigmask(void *sc_ptr); | ||
40 | |||
41 | #endif | 27 | #endif |
42 | |||
43 | /* | ||
44 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
45 | * Emacs will notice this stuff at the end of the file and automatically | ||
46 | * adjust the settings for this buffer only. This must remain at the end | ||
47 | * of the file. | ||
48 | * --------------------------------------------------------------------------- | ||
49 | * Local variables: | ||
50 | * c-file-style: "linux" | ||
51 | * End: | ||
52 | */ | ||
53 | |||
diff --git a/arch/um/include/sysdep-x86_64/stub.h b/arch/um/include/sysdep-x86_64/stub.h index 92e989f81761..655f9c2de3ac 100644 --- a/arch/um/include/sysdep-x86_64/stub.h +++ b/arch/um/include/sysdep-x86_64/stub.h | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <sys/mman.h> | 9 | #include <sys/mman.h> |
10 | #include <asm/unistd.h> | 10 | #include <asm/unistd.h> |
11 | #include <sysdep/ptrace_user.h> | 11 | #include <sysdep/ptrace_user.h> |
12 | #include "as-layout.h" | ||
12 | #include "stub-data.h" | 13 | #include "stub-data.h" |
13 | #include "kern_constants.h" | 14 | #include "kern_constants.h" |
14 | #include "uml-config.h" | 15 | #include "uml-config.h" |
@@ -94,13 +95,13 @@ static inline void remap_stack(long fd, unsigned long offset) | |||
94 | { | 95 | { |
95 | __asm__ volatile ("movq %4,%%r10 ; movq %5,%%r8 ; " | 96 | __asm__ volatile ("movq %4,%%r10 ; movq %5,%%r8 ; " |
96 | "movq %6, %%r9; " __syscall "; movq %7, %%rbx ; " | 97 | "movq %6, %%r9; " __syscall "; movq %7, %%rbx ; " |
97 | "movq %%rax, (%%rbx)": | 98 | "movq %%rax, (%%rbx)": |
98 | : "a" (STUB_MMAP_NR), "D" (UML_CONFIG_STUB_DATA), | 99 | : "a" (STUB_MMAP_NR), "D" (STUB_DATA), |
99 | "S" (UM_KERN_PAGE_SIZE), | 100 | "S" (UM_KERN_PAGE_SIZE), |
100 | "d" (PROT_READ | PROT_WRITE), | 101 | "d" (PROT_READ | PROT_WRITE), |
101 | "g" (MAP_FIXED | MAP_SHARED), "g" (fd), | 102 | "g" (MAP_FIXED | MAP_SHARED), "g" (fd), |
102 | "g" (offset), | 103 | "g" (offset), |
103 | "i" (&((struct stub_data *) UML_CONFIG_STUB_DATA)->err) | 104 | "i" (&((struct stub_data *) STUB_DATA)->err) |
104 | : __syscall_clobber, "r10", "r8", "r9" ); | 105 | : __syscall_clobber, "r10", "r8", "r9" ); |
105 | } | 106 | } |
106 | 107 | ||
diff --git a/arch/um/include/sysdep-x86_64/thread.h b/arch/um/include/sysdep-x86_64/thread.h deleted file mode 100644 index cbef3e1697f4..000000000000 --- a/arch/um/include/sysdep-x86_64/thread.h +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | #ifndef __UM_THREAD_H | ||
2 | #define __UM_THREAD_H | ||
3 | |||
4 | #include <kern_constants.h> | ||
5 | |||
6 | #ifdef UML_CONFIG_MODE_TT | ||
7 | #define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[HOST_TASK_EXTERN_PID])) | ||
8 | #endif | ||
9 | |||
10 | #endif | ||
diff --git a/arch/um/include/task.h b/arch/um/include/task.h index 6375ba7203c9..3fe726b3cf48 100644 --- a/arch/um/include/task.h +++ b/arch/um/include/task.h | |||
@@ -3,7 +3,7 @@ | |||
3 | 3 | ||
4 | #include <kern_constants.h> | 4 | #include <kern_constants.h> |
5 | 5 | ||
6 | #define TASK_REGS(task) ((union uml_pt_regs *) &(((char *) (task))[HOST_TASK_REGS])) | 6 | #define TASK_REGS(task) ((struct uml_pt_regs *) &(((char *) (task))[HOST_TASK_REGS])) |
7 | #define TASK_PID(task) *((int *) &(((char *) (task))[HOST_TASK_PID])) | 7 | #define TASK_PID(task) *((int *) &(((char *) (task))[HOST_TASK_PID])) |
8 | 8 | ||
9 | #endif | 9 | #endif |
diff --git a/arch/um/include/tlb.h b/arch/um/include/tlb.h index bcd1a4afb842..ecd2265b301b 100644 --- a/arch/um/include/tlb.h +++ b/arch/um/include/tlb.h | |||
@@ -8,34 +8,7 @@ | |||
8 | 8 | ||
9 | #include "um_mmu.h" | 9 | #include "um_mmu.h" |
10 | 10 | ||
11 | struct host_vm_op { | ||
12 | enum { NONE, MMAP, MUNMAP, MPROTECT } type; | ||
13 | union { | ||
14 | struct { | ||
15 | unsigned long addr; | ||
16 | unsigned long len; | ||
17 | unsigned int prot; | ||
18 | int fd; | ||
19 | __u64 offset; | ||
20 | } mmap; | ||
21 | struct { | ||
22 | unsigned long addr; | ||
23 | unsigned long len; | ||
24 | } munmap; | ||
25 | struct { | ||
26 | unsigned long addr; | ||
27 | unsigned long len; | ||
28 | unsigned int prot; | ||
29 | } mprotect; | ||
30 | } u; | ||
31 | }; | ||
32 | |||
33 | extern void force_flush_all(void); | 11 | extern void force_flush_all(void); |
34 | extern void fix_range_common(struct mm_struct *mm, unsigned long start_addr, | ||
35 | unsigned long end_addr, int force, | ||
36 | int (*do_ops)(union mm_context *, | ||
37 | struct host_vm_op *, int, int, | ||
38 | void **)); | ||
39 | extern int flush_tlb_kernel_range_common(unsigned long start, | 12 | extern int flush_tlb_kernel_range_common(unsigned long start, |
40 | unsigned long end); | 13 | unsigned long end); |
41 | 14 | ||
diff --git a/arch/um/include/tt/debug.h b/arch/um/include/tt/debug.h deleted file mode 100644 index 9778fa838296..000000000000 --- a/arch/um/include/tt/debug.h +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) and | ||
3 | * Lars Brinkhoff. | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #ifndef __UML_TT_DEBUG_H | ||
8 | #define __UML_TT_DEBUG_H | ||
9 | |||
10 | extern int debugger_proxy(int status, pid_t pid); | ||
11 | extern void child_proxy(pid_t pid, int status); | ||
12 | extern void init_proxy (pid_t pid, int waiting, int status); | ||
13 | extern int start_debugger(char *prog, int startup, int stop, int *debugger_fd); | ||
14 | extern void fake_child_exit(void); | ||
15 | extern int gdb_config(char *str); | ||
16 | extern int gdb_remove(int unused); | ||
17 | |||
18 | #endif | ||
diff --git a/arch/um/include/tt/mmu-tt.h b/arch/um/include/tt/mmu-tt.h deleted file mode 100644 index 572a78b22587..000000000000 --- a/arch/um/include/tt/mmu-tt.h +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __TT_MMU_H | ||
7 | #define __TT_MMU_H | ||
8 | |||
9 | struct mmu_context_tt { | ||
10 | }; | ||
11 | |||
12 | #endif | ||
diff --git a/arch/um/include/tt/mode-tt.h b/arch/um/include/tt/mode-tt.h deleted file mode 100644 index 2823cd56eea2..000000000000 --- a/arch/um/include/tt/mode-tt.h +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __MODE_TT_H__ | ||
7 | #define __MODE_TT_H__ | ||
8 | |||
9 | #include "sysdep/ptrace.h" | ||
10 | |||
11 | enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB }; | ||
12 | |||
13 | extern int tracing_pid; | ||
14 | |||
15 | extern int tracer(int (*init_proc)(void *), void *sp); | ||
16 | extern void sig_handler_common_tt(int sig, void *sc); | ||
17 | extern void syscall_handler_tt(int sig, union uml_pt_regs *regs); | ||
18 | extern void reboot_tt(void); | ||
19 | extern void halt_tt(void); | ||
20 | extern int is_tracer_winch(int pid, int fd, void *data); | ||
21 | extern void kill_off_processes_tt(void); | ||
22 | |||
23 | #endif | ||
diff --git a/arch/um/include/tt/mode_kern_tt.h b/arch/um/include/tt/mode_kern_tt.h deleted file mode 100644 index a4fc63057195..000000000000 --- a/arch/um/include/tt/mode_kern_tt.h +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __TT_MODE_KERN_H__ | ||
7 | #define __TT_MODE_KERN_H__ | ||
8 | |||
9 | #include "linux/sched.h" | ||
10 | #include "asm/page.h" | ||
11 | #include "asm/ptrace.h" | ||
12 | #include "asm/uaccess.h" | ||
13 | |||
14 | extern void switch_to_tt(void *prev, void *next); | ||
15 | extern void flush_thread_tt(void); | ||
16 | extern void start_thread_tt(struct pt_regs *regs, unsigned long eip, | ||
17 | unsigned long esp); | ||
18 | extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, | ||
19 | unsigned long stack_top, struct task_struct *p, | ||
20 | struct pt_regs *regs); | ||
21 | extern void release_thread_tt(struct task_struct *task); | ||
22 | extern void initial_thread_cb_tt(void (*proc)(void *), void *arg); | ||
23 | extern void init_idle_tt(void); | ||
24 | extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end); | ||
25 | extern void flush_tlb_kernel_vm_tt(void); | ||
26 | extern void __flush_tlb_one_tt(unsigned long addr); | ||
27 | extern void flush_tlb_range_tt(struct vm_area_struct *vma, | ||
28 | unsigned long start, unsigned long end); | ||
29 | extern void flush_tlb_mm_tt(struct mm_struct *mm); | ||
30 | extern void force_flush_all_tt(void); | ||
31 | extern long execute_syscall_tt(void *r); | ||
32 | extern void before_mem_tt(unsigned long brk_start); | ||
33 | extern unsigned long set_task_sizes_tt(unsigned long *task_size_out); | ||
34 | extern int start_uml_tt(void); | ||
35 | extern int external_pid_tt(struct task_struct *task); | ||
36 | extern int thread_pid_tt(struct task_struct *task); | ||
37 | |||
38 | #define kmem_end_tt (host_task_size - ABOVE_KMEM) | ||
39 | |||
40 | #endif | ||
diff --git a/arch/um/include/tt/tt.h b/arch/um/include/tt/tt.h deleted file mode 100644 index acb8356e1f98..000000000000 --- a/arch/um/include/tt/tt.h +++ /dev/null | |||
@@ -1,37 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __TT_H__ | ||
7 | #define __TT_H__ | ||
8 | |||
9 | #include "sysdep/ptrace.h" | ||
10 | |||
11 | extern int gdb_pid; | ||
12 | extern int debug; | ||
13 | extern int debug_stop; | ||
14 | extern int debug_trace; | ||
15 | |||
16 | extern int honeypot; | ||
17 | |||
18 | extern int fork_tramp(void *sig_stack); | ||
19 | extern int do_proc_op(void *t, int proc_id); | ||
20 | extern int tracer(int (*init_proc)(void *), void *sp); | ||
21 | extern void attach_process(int pid); | ||
22 | extern void tracer_panic(char *format, ...) | ||
23 | __attribute__ ((format (printf, 1, 2))); | ||
24 | extern void set_init_pid(int pid); | ||
25 | extern int set_user_mode(void *task); | ||
26 | extern void set_tracing(void *t, int tracing); | ||
27 | extern int is_tracing(void *task); | ||
28 | extern void syscall_handler(int sig, union uml_pt_regs *regs); | ||
29 | extern void exit_kernel(int pid, void *task); | ||
30 | extern void do_syscall(void *task, int pid, int local_using_sysemu); | ||
31 | extern void do_sigtrap(void *task); | ||
32 | extern int is_valid_pid(int pid); | ||
33 | extern void remap_data(void *segment_start, void *segment_end, int w); | ||
34 | extern long execute_syscall_tt(void *r); | ||
35 | |||
36 | #endif | ||
37 | |||
diff --git a/arch/um/include/tt/uaccess-tt.h b/arch/um/include/tt/uaccess-tt.h deleted file mode 100644 index 13a64f61fcf4..000000000000 --- a/arch/um/include/tt/uaccess-tt.h +++ /dev/null | |||
@@ -1,46 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __TT_UACCESS_H | ||
7 | #define __TT_UACCESS_H | ||
8 | |||
9 | #include "linux/string.h" | ||
10 | #include "linux/sched.h" | ||
11 | #include "asm/processor.h" | ||
12 | #include "asm/errno.h" | ||
13 | #include "asm/current.h" | ||
14 | #include "asm/a.out.h" | ||
15 | #include "uml_uaccess.h" | ||
16 | |||
17 | #define ABOVE_KMEM (16 * 1024 * 1024) | ||
18 | |||
19 | extern unsigned long end_vm; | ||
20 | extern unsigned long uml_physmem; | ||
21 | |||
22 | #define is_stack(addr, size) \ | ||
23 | (((unsigned long) (addr) < STACK_TOP) && \ | ||
24 | ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \ | ||
25 | (((unsigned long) (addr) + (size)) <= STACK_TOP)) | ||
26 | |||
27 | #define access_ok_tt(type, addr, size) \ | ||
28 | (is_stack(addr, size)) | ||
29 | |||
30 | extern int __do_copy_from_user(void *to, const void *from, int n, | ||
31 | void **fault_addr, void **fault_catcher); | ||
32 | extern int __do_strncpy_from_user(char *dst, const char *src, size_t n, | ||
33 | void **fault_addr, void **fault_catcher); | ||
34 | extern int __do_clear_user(void *mem, size_t len, void **fault_addr, | ||
35 | void **fault_catcher); | ||
36 | extern int __do_strnlen_user(const char *str, unsigned long n, | ||
37 | void **fault_addr, void **fault_catcher); | ||
38 | |||
39 | extern int copy_from_user_tt(void *to, const void __user *from, int n); | ||
40 | extern int copy_to_user_tt(void __user *to, const void *from, int n); | ||
41 | extern int strncpy_from_user_tt(char *dst, const char __user *src, int count); | ||
42 | extern int __clear_user_tt(void __user *mem, int len); | ||
43 | extern int clear_user_tt(void __user *mem, int len); | ||
44 | extern int strnlen_user_tt(const void __user *str, int len); | ||
45 | |||
46 | #endif | ||
diff --git a/arch/um/include/um_mmu.h b/arch/um/include/um_mmu.h index 0fa643238300..8855d8df512f 100644 --- a/arch/um/include/um_mmu.h +++ b/arch/um/include/um_mmu.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -7,34 +7,22 @@ | |||
7 | #define __ARCH_UM_MMU_H | 7 | #define __ARCH_UM_MMU_H |
8 | 8 | ||
9 | #include "uml-config.h" | 9 | #include "uml-config.h" |
10 | #include "choose-mode.h" | 10 | #include "mm_id.h" |
11 | #include "asm/ldt.h" | ||
11 | 12 | ||
12 | #ifdef UML_CONFIG_MODE_TT | 13 | typedef struct mm_context { |
13 | #include "mmu-tt.h" | 14 | struct mm_id id; |
15 | unsigned long last_page_table; | ||
16 | #ifdef CONFIG_3_LEVEL_PGTABLES | ||
17 | unsigned long last_pmd; | ||
14 | #endif | 18 | #endif |
19 | struct uml_ldt ldt; | ||
20 | } mm_context_t; | ||
15 | 21 | ||
16 | #ifdef UML_CONFIG_MODE_SKAS | 22 | extern void __switch_mm(struct mm_id * mm_idp); |
17 | #include "mmu-skas.h" | ||
18 | #endif | ||
19 | 23 | ||
20 | typedef union mm_context { | 24 | /* Avoid tangled inclusion with asm/ldt.h */ |
21 | #ifdef UML_CONFIG_MODE_TT | 25 | extern long init_new_ldt(struct mm_context *to_mm, struct mm_context *from_mm); |
22 | struct mmu_context_tt tt; | 26 | extern void free_ldt(struct mm_context *mm); |
23 | #endif | ||
24 | #ifdef UML_CONFIG_MODE_SKAS | ||
25 | struct mmu_context_skas skas; | ||
26 | #endif | ||
27 | } mm_context_t; | ||
28 | 27 | ||
29 | #endif | 28 | #endif |
30 | |||
31 | /* | ||
32 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
33 | * Emacs will notice this stuff at the end of the file and automatically | ||
34 | * adjust the settings for this buffer only. This must remain at the end | ||
35 | * of the file. | ||
36 | * --------------------------------------------------------------------------- | ||
37 | * Local variables: | ||
38 | * c-file-style: "linux" | ||
39 | * End: | ||
40 | */ | ||
diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h index 5126a99b5961..fdfc06b85605 100644 --- a/arch/um/include/um_uaccess.h +++ b/arch/um/include/um_uaccess.h | |||
@@ -1,26 +1,16 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #ifndef __ARCH_UM_UACCESS_H | 6 | #ifndef __ARCH_UM_UACCESS_H |
7 | #define __ARCH_UM_UACCESS_H | 7 | #define __ARCH_UM_UACCESS_H |
8 | 8 | ||
9 | #include "choose-mode.h" | ||
10 | |||
11 | #ifdef CONFIG_MODE_TT | ||
12 | #include "uaccess-tt.h" | ||
13 | #endif | ||
14 | |||
15 | #ifdef CONFIG_MODE_SKAS | ||
16 | #include "uaccess-skas.h" | ||
17 | #endif | ||
18 | |||
19 | #include "asm/fixmap.h" | 9 | #include "asm/fixmap.h" |
20 | 10 | ||
21 | #define __under_task_size(addr, size) \ | 11 | #define __under_task_size(addr, size) \ |
22 | (((unsigned long) (addr) < TASK_SIZE) && \ | 12 | (((unsigned long) (addr) < TASK_SIZE) && \ |
23 | (((unsigned long) (addr) + (size)) < TASK_SIZE)) | 13 | (((unsigned long) (addr) + (size)) < TASK_SIZE)) |
24 | 14 | ||
25 | #define __access_ok_vsyscall(type, addr, size) \ | 15 | #define __access_ok_vsyscall(type, addr, size) \ |
26 | ((type == VERIFY_READ) && \ | 16 | ((type == VERIFY_READ) && \ |
@@ -35,20 +25,14 @@ | |||
35 | (__addr_range_nowrap(addr, size) && \ | 25 | (__addr_range_nowrap(addr, size) && \ |
36 | (__under_task_size(addr, size) || \ | 26 | (__under_task_size(addr, size) || \ |
37 | __access_ok_vsyscall(type, addr, size) || \ | 27 | __access_ok_vsyscall(type, addr, size) || \ |
38 | segment_eq(get_fs(), KERNEL_DS) || \ | 28 | segment_eq(get_fs(), KERNEL_DS))) |
39 | CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size))) | ||
40 | 29 | ||
41 | static inline int copy_from_user(void *to, const void __user *from, int n) | 30 | extern int copy_from_user(void *to, const void __user *from, int n); |
42 | { | 31 | extern int copy_to_user(void __user *to, const void *from, int n); |
43 | return(CHOOSE_MODE_PROC(copy_from_user_tt, copy_from_user_skas, to, | ||
44 | from, n)); | ||
45 | } | ||
46 | 32 | ||
47 | static inline int copy_to_user(void __user *to, const void *from, int n) | 33 | extern int __do_copy_to_user(void *to, const void *from, int n, |
48 | { | 34 | void **fault_addr, jmp_buf **fault_catcher); |
49 | return(CHOOSE_MODE_PROC(copy_to_user_tt, copy_to_user_skas, to, | 35 | extern void __do_copy(void *to, const void *from, int n); |
50 | from, n)); | ||
51 | } | ||
52 | 36 | ||
53 | /* | 37 | /* |
54 | * strncpy_from_user: - Copy a NUL terminated string from userspace. | 38 | * strncpy_from_user: - Copy a NUL terminated string from userspace. |
@@ -69,11 +53,7 @@ static inline int copy_to_user(void __user *to, const void *from, int n) | |||
69 | * and returns @count. | 53 | * and returns @count. |
70 | */ | 54 | */ |
71 | 55 | ||
72 | static inline int strncpy_from_user(char *dst, const char __user *src, int count) | 56 | extern int strncpy_from_user(char *dst, const char __user *src, int count); |
73 | { | ||
74 | return(CHOOSE_MODE_PROC(strncpy_from_user_tt, strncpy_from_user_skas, | ||
75 | dst, src, count)); | ||
76 | } | ||
77 | 57 | ||
78 | /* | 58 | /* |
79 | * __clear_user: - Zero a block of memory in user space, with less checking. | 59 | * __clear_user: - Zero a block of memory in user space, with less checking. |
@@ -86,10 +66,7 @@ static inline int strncpy_from_user(char *dst, const char __user *src, int count | |||
86 | * Returns number of bytes that could not be cleared. | 66 | * Returns number of bytes that could not be cleared. |
87 | * On success, this will be zero. | 67 | * On success, this will be zero. |
88 | */ | 68 | */ |
89 | static inline int __clear_user(void *mem, int len) | 69 | extern int __clear_user(void __user *mem, int len); |
90 | { | ||
91 | return(CHOOSE_MODE_PROC(__clear_user_tt, __clear_user_skas, mem, len)); | ||
92 | } | ||
93 | 70 | ||
94 | /* | 71 | /* |
95 | * clear_user: - Zero a block of memory in user space. | 72 | * clear_user: - Zero a block of memory in user space. |
@@ -101,10 +78,7 @@ static inline int __clear_user(void *mem, int len) | |||
101 | * Returns number of bytes that could not be cleared. | 78 | * Returns number of bytes that could not be cleared. |
102 | * On success, this will be zero. | 79 | * On success, this will be zero. |
103 | */ | 80 | */ |
104 | static inline int clear_user(void __user *mem, int len) | 81 | extern int clear_user(void __user *mem, int len); |
105 | { | ||
106 | return(CHOOSE_MODE_PROC(clear_user_tt, clear_user_skas, mem, len)); | ||
107 | } | ||
108 | 82 | ||
109 | /* | 83 | /* |
110 | * strlen_user: - Get the size of a string in user space. | 84 | * strlen_user: - Get the size of a string in user space. |
@@ -117,20 +91,6 @@ static inline int clear_user(void __user *mem, int len) | |||
117 | * On exception, returns 0. | 91 | * On exception, returns 0. |
118 | * If the string is too long, returns a value greater than @n. | 92 | * If the string is too long, returns a value greater than @n. |
119 | */ | 93 | */ |
120 | static inline int strnlen_user(const void __user *str, long len) | 94 | extern int strnlen_user(const void __user *str, int len); |
121 | { | ||
122 | return(CHOOSE_MODE_PROC(strnlen_user_tt, strnlen_user_skas, str, len)); | ||
123 | } | ||
124 | 95 | ||
125 | #endif | 96 | #endif |
126 | |||
127 | /* | ||
128 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
129 | * Emacs will notice this stuff at the end of the file and automatically | ||
130 | * adjust the settings for this buffer only. This must remain at the end | ||
131 | * of the file. | ||
132 | * --------------------------------------------------------------------------- | ||
133 | * Local variables: | ||
134 | * c-file-style: "linux" | ||
135 | * End: | ||
136 | */ | ||
diff --git a/arch/um/include/uml_uaccess.h b/arch/um/include/uml_uaccess.h deleted file mode 100644 index c0df11d06f5e..000000000000 --- a/arch/um/include/uml_uaccess.h +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __UML_UACCESS_H__ | ||
7 | #define __UML_UACCESS_H__ | ||
8 | |||
9 | extern int __do_copy_to_user(void *to, const void *from, int n, | ||
10 | void **fault_addr, void **fault_catcher); | ||
11 | void __do_copy(void *to, const void *from, int n); | ||
12 | |||
13 | #endif | ||
14 | |||
15 | /* | ||
16 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
17 | * Emacs will notice this stuff at the end of the file and automatically | ||
18 | * adjust the settings for this buffer only. This must remain at the end | ||
19 | * of the file. | ||
20 | * --------------------------------------------------------------------------- | ||
21 | * Local variables: | ||
22 | * c-file-style: "linux" | ||
23 | * End: | ||
24 | */ | ||
diff --git a/arch/um/include/user.h b/arch/um/include/user.h index d380e6d91a90..99033ff28a78 100644 --- a/arch/um/include/user.h +++ b/arch/um/include/user.h | |||
@@ -14,10 +14,12 @@ | |||
14 | */ | 14 | */ |
15 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) | 15 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
16 | 16 | ||
17 | /* | 17 | /* This is to get size_t */ |
18 | * This will provide the size_t definition in both kernel and userspace builds | 18 | #ifdef __KERNEL__ |
19 | */ | ||
20 | #include <linux/types.h> | 19 | #include <linux/types.h> |
20 | #else | ||
21 | #include <stddef.h> | ||
22 | #endif | ||
21 | 23 | ||
22 | extern void panic(const char *fmt, ...) | 24 | extern void panic(const char *fmt, ...) |
23 | __attribute__ ((format (printf, 1, 2))); | 25 | __attribute__ ((format (printf, 1, 2))); |
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index c5cf4a0827b0..499e5e95e609 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | # | 1 | # |
2 | # Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | # Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux,intel}.com) |
3 | # Licensed under the GPL | 3 | # Licensed under the GPL |
4 | # | 4 | # |
5 | 5 | ||
@@ -9,15 +9,12 @@ clean-files := | |||
9 | obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \ | 9 | obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \ |
10 | physmem.o process.o ptrace.o reboot.o sigio.o \ | 10 | physmem.o process.o ptrace.o reboot.o sigio.o \ |
11 | signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \ | 11 | signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \ |
12 | um_arch.o umid.o | 12 | um_arch.o umid.o skas/ |
13 | 13 | ||
14 | obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o | 14 | obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o |
15 | obj-$(CONFIG_GPROF) += gprof_syms.o | 15 | obj-$(CONFIG_GPROF) += gprof_syms.o |
16 | obj-$(CONFIG_GCOV) += gmon_syms.o | 16 | obj-$(CONFIG_GCOV) += gmon_syms.o |
17 | 17 | ||
18 | obj-$(CONFIG_MODE_TT) += tt/ | ||
19 | obj-$(CONFIG_MODE_SKAS) += skas/ | ||
20 | |||
21 | USER_OBJS := config.o | 18 | USER_OBJS := config.o |
22 | 19 | ||
23 | include arch/um/scripts/Makefile.rules | 20 | include arch/um/scripts/Makefile.rules |
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S index 41850906116e..3866f4960f04 100644 --- a/arch/um/kernel/dyn.lds.S +++ b/arch/um/kernel/dyn.lds.S | |||
@@ -10,8 +10,6 @@ SECTIONS | |||
10 | PROVIDE (__executable_start = START); | 10 | PROVIDE (__executable_start = START); |
11 | . = START + SIZEOF_HEADERS; | 11 | . = START + SIZEOF_HEADERS; |
12 | .interp : { *(.interp) } | 12 | .interp : { *(.interp) } |
13 | /* Used in arch/um/kernel/mem.c. Any memory between START and __binary_start | ||
14 | * is remapped.*/ | ||
15 | __binary_start = .; | 13 | __binary_start = .; |
16 | . = ALIGN(4096); /* Init code and data */ | 14 | . = ALIGN(4096); /* Init code and data */ |
17 | _text = .; | 15 | _text = .; |
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index ce6828fd396f..8196450451cd 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c | |||
@@ -1,35 +1,44 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/slab.h" | 6 | #include "linux/stddef.h" |
7 | #include "linux/fs.h" | ||
7 | #include "linux/smp_lock.h" | 8 | #include "linux/smp_lock.h" |
8 | #include "linux/ptrace.h" | 9 | #include "linux/ptrace.h" |
9 | #include "linux/fs.h" | 10 | #include "linux/sched.h" |
10 | #include "asm/ptrace.h" | 11 | #include "asm/current.h" |
11 | #include "asm/pgtable.h" | 12 | #include "asm/processor.h" |
12 | #include "asm/tlbflush.h" | ||
13 | #include "asm/uaccess.h" | 13 | #include "asm/uaccess.h" |
14 | #include "kern_util.h" | ||
15 | #include "as-layout.h" | 14 | #include "as-layout.h" |
16 | #include "mem_user.h" | 15 | #include "mem_user.h" |
17 | #include "kern.h" | 16 | #include "skas.h" |
18 | #include "irq_user.h" | ||
19 | #include "tlb.h" | ||
20 | #include "os.h" | 17 | #include "os.h" |
21 | #include "choose-mode.h" | ||
22 | #include "mode_kern.h" | ||
23 | 18 | ||
24 | void flush_thread(void) | 19 | void flush_thread(void) |
25 | { | 20 | { |
21 | void *data = NULL; | ||
22 | unsigned long end = proc_mm ? task_size : STUB_START; | ||
23 | int ret; | ||
24 | |||
26 | arch_flush_thread(¤t->thread.arch); | 25 | arch_flush_thread(¤t->thread.arch); |
27 | CHOOSE_MODE(flush_thread_tt(), flush_thread_skas()); | 26 | |
27 | ret = unmap(¤t->mm->context.id, 0, end, 1, &data); | ||
28 | if (ret) { | ||
29 | printk(KERN_ERR "flush_thread - clearing address space failed, " | ||
30 | "err = %d\n", ret); | ||
31 | force_sig(SIGKILL, current); | ||
32 | } | ||
33 | |||
34 | __switch_mm(¤t->mm->context.id); | ||
28 | } | 35 | } |
29 | 36 | ||
30 | void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) | 37 | void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) |
31 | { | 38 | { |
32 | CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp); | 39 | set_fs(USER_DS); |
40 | PT_REGS_IP(regs) = eip; | ||
41 | PT_REGS_SP(regs) = esp; | ||
33 | } | 42 | } |
34 | 43 | ||
35 | #ifdef CONFIG_TTY_LOG | 44 | #ifdef CONFIG_TTY_LOG |
@@ -39,7 +48,7 @@ extern void log_exec(char **argv, void *tty); | |||
39 | static long execve1(char *file, char __user * __user *argv, | 48 | static long execve1(char *file, char __user * __user *argv, |
40 | char __user *__user *env) | 49 | char __user *__user *env) |
41 | { | 50 | { |
42 | long error; | 51 | long error; |
43 | #ifdef CONFIG_TTY_LOG | 52 | #ifdef CONFIG_TTY_LOG |
44 | struct tty_struct *tty; | 53 | struct tty_struct *tty; |
45 | 54 | ||
@@ -49,17 +58,16 @@ static long execve1(char *file, char __user * __user *argv, | |||
49 | log_exec(argv, tty); | 58 | log_exec(argv, tty); |
50 | mutex_unlock(&tty_mutex); | 59 | mutex_unlock(&tty_mutex); |
51 | #endif | 60 | #endif |
52 | error = do_execve(file, argv, env, ¤t->thread.regs); | 61 | error = do_execve(file, argv, env, ¤t->thread.regs); |
53 | if (error == 0){ | 62 | if (error == 0) { |
54 | task_lock(current); | 63 | task_lock(current); |
55 | current->ptrace &= ~PT_DTRACE; | 64 | current->ptrace &= ~PT_DTRACE; |
56 | #ifdef SUBARCH_EXECVE1 | 65 | #ifdef SUBARCH_EXECVE1 |
57 | SUBARCH_EXECVE1(¤t->thread.regs.regs); | 66 | SUBARCH_EXECVE1(¤t->thread.regs.regs); |
58 | #endif | 67 | #endif |
59 | task_unlock(current); | 68 | task_unlock(current); |
60 | set_cmdline(current_cmd()); | 69 | } |
61 | } | 70 | return error; |
62 | return(error); | ||
63 | } | 71 | } |
64 | 72 | ||
65 | long um_execve(char *file, char __user *__user *argv, char __user *__user *env) | 73 | long um_execve(char *file, char __user *__user *argv, char __user *__user *env) |
@@ -67,9 +75,9 @@ long um_execve(char *file, char __user *__user *argv, char __user *__user *env) | |||
67 | long err; | 75 | long err; |
68 | 76 | ||
69 | err = execve1(file, argv, env); | 77 | err = execve1(file, argv, env); |
70 | if(!err) | 78 | if (!err) |
71 | do_longjmp(current->thread.exec_buf, 1); | 79 | UML_LONGJMP(current->thread.exec_buf, 1); |
72 | return(err); | 80 | return err; |
73 | } | 81 | } |
74 | 82 | ||
75 | long sys_execve(char __user *file, char __user *__user *argv, | 83 | long sys_execve(char __user *file, char __user *__user *argv, |
@@ -86,5 +94,5 @@ long sys_execve(char __user *file, char __user *__user *argv, | |||
86 | putname(filename); | 94 | putname(filename); |
87 | out: | 95 | out: |
88 | unlock_kernel(); | 96 | unlock_kernel(); |
89 | return(error); | 97 | return error; |
90 | } | 98 | } |
diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c index cba516e6c99a..dcfceca95052 100644 --- a/arch/um/kernel/init_task.c +++ b/arch/um/kernel/init_task.c | |||
@@ -3,16 +3,12 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/mm.h" | ||
7 | #include "linux/fs.h" | ||
8 | #include "linux/module.h" | ||
9 | #include "linux/sched.h" | 6 | #include "linux/sched.h" |
10 | #include "linux/init_task.h" | 7 | #include "linux/init_task.h" |
8 | #include "linux/fs.h" | ||
9 | #include "linux/module.h" | ||
11 | #include "linux/mqueue.h" | 10 | #include "linux/mqueue.h" |
12 | #include "asm/uaccess.h" | 11 | #include "asm/uaccess.h" |
13 | #include "asm/pgtable.h" | ||
14 | #include "mem_user.h" | ||
15 | #include "os.h" | ||
16 | 12 | ||
17 | static struct fs_struct init_fs = INIT_FS; | 13 | static struct fs_struct init_fs = INIT_FS; |
18 | struct mm_struct init_mm = INIT_MM(init_mm); | 14 | struct mm_struct init_mm = INIT_MM(init_mm); |
@@ -46,8 +42,3 @@ union thread_union init_thread_union | |||
46 | union thread_union cpu0_irqstack | 42 | union thread_union cpu0_irqstack |
47 | __attribute__((__section__(".data.init_irqstack"))) = | 43 | __attribute__((__section__(".data.init_irqstack"))) = |
48 | { INIT_THREAD_INFO(init_task) }; | 44 | { INIT_THREAD_INFO(init_task) }; |
49 | |||
50 | void unprotect_stack(unsigned long stack) | ||
51 | { | ||
52 | os_protect_memory((void *) stack, THREAD_SIZE, 1, 1, 0); | ||
53 | } | ||
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index cf0dd9cf8c43..277fce17b088 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c | |||
@@ -1,37 +1,19 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | * Derived (i.e. mostly copied) from arch/i386/kernel/irq.c: | 4 | * Derived (i.e. mostly copied) from arch/i386/kernel/irq.c: |
5 | * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar | 5 | * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include "linux/kernel.h" | 8 | #include "linux/cpumask.h" |
9 | #include "linux/module.h" | 9 | #include "linux/hardirq.h" |
10 | #include "linux/smp.h" | ||
11 | #include "linux/kernel_stat.h" | ||
12 | #include "linux/interrupt.h" | 10 | #include "linux/interrupt.h" |
13 | #include "linux/random.h" | 11 | #include "linux/kernel_stat.h" |
14 | #include "linux/slab.h" | 12 | #include "linux/module.h" |
15 | #include "linux/file.h" | ||
16 | #include "linux/proc_fs.h" | ||
17 | #include "linux/init.h" | ||
18 | #include "linux/seq_file.h" | 13 | #include "linux/seq_file.h" |
19 | #include "linux/profile.h" | 14 | #include "as-layout.h" |
20 | #include "linux/hardirq.h" | ||
21 | #include "asm/irq.h" | ||
22 | #include "asm/hw_irq.h" | ||
23 | #include "asm/atomic.h" | ||
24 | #include "asm/signal.h" | ||
25 | #include "asm/system.h" | ||
26 | #include "asm/errno.h" | ||
27 | #include "asm/uaccess.h" | ||
28 | #include "kern_util.h" | 15 | #include "kern_util.h" |
29 | #include "irq_user.h" | ||
30 | #include "irq_kern.h" | ||
31 | #include "os.h" | 16 | #include "os.h" |
32 | #include "sigio.h" | ||
33 | #include "misc_constants.h" | ||
34 | #include "as-layout.h" | ||
35 | 17 | ||
36 | /* | 18 | /* |
37 | * Generic, controller-independent functions: | 19 | * Generic, controller-independent functions: |
@@ -71,9 +53,8 @@ int show_interrupts(struct seq_file *p, void *v) | |||
71 | seq_putc(p, '\n'); | 53 | seq_putc(p, '\n'); |
72 | skip: | 54 | skip: |
73 | spin_unlock_irqrestore(&irq_desc[i].lock, flags); | 55 | spin_unlock_irqrestore(&irq_desc[i].lock, flags); |
74 | } else if (i == NR_IRQS) { | 56 | } else if (i == NR_IRQS) |
75 | seq_putc(p, '\n'); | 57 | seq_putc(p, '\n'); |
76 | } | ||
77 | 58 | ||
78 | return 0; | 59 | return 0; |
79 | } | 60 | } |
@@ -91,7 +72,7 @@ static struct irq_fd **last_irq_ptr = &active_fds; | |||
91 | 72 | ||
92 | extern void free_irqs(void); | 73 | extern void free_irqs(void); |
93 | 74 | ||
94 | void sigio_handler(int sig, union uml_pt_regs *regs) | 75 | void sigio_handler(int sig, struct uml_pt_regs *regs) |
95 | { | 76 | { |
96 | struct irq_fd *irq_fd; | 77 | struct irq_fd *irq_fd; |
97 | int n; | 78 | int n; |
@@ -102,11 +83,13 @@ void sigio_handler(int sig, union uml_pt_regs *regs) | |||
102 | while (1) { | 83 | while (1) { |
103 | n = os_waiting_for_events(active_fds); | 84 | n = os_waiting_for_events(active_fds); |
104 | if (n <= 0) { | 85 | if (n <= 0) { |
105 | if(n == -EINTR) continue; | 86 | if (n == -EINTR) |
87 | continue; | ||
106 | else break; | 88 | else break; |
107 | } | 89 | } |
108 | 90 | ||
109 | for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { | 91 | for (irq_fd = active_fds; irq_fd != NULL; |
92 | irq_fd = irq_fd->next) { | ||
110 | if (irq_fd->current_events != 0) { | 93 | if (irq_fd->current_events != 0) { |
111 | irq_fd->current_events = 0; | 94 | irq_fd->current_events = 0; |
112 | do_IRQ(irq_fd->irq, regs); | 95 | do_IRQ(irq_fd->irq, regs); |
@@ -138,8 +121,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id) | |||
138 | 121 | ||
139 | if (type == IRQ_READ) | 122 | if (type == IRQ_READ) |
140 | events = UM_POLLIN | UM_POLLPRI; | 123 | events = UM_POLLIN | UM_POLLPRI; |
141 | else | 124 | else events = UM_POLLOUT; |
142 | events = UM_POLLOUT; | ||
143 | *new_fd = ((struct irq_fd) { .next = NULL, | 125 | *new_fd = ((struct irq_fd) { .next = NULL, |
144 | .id = dev_id, | 126 | .id = dev_id, |
145 | .fd = fd, | 127 | .fd = fd, |
@@ -153,9 +135,10 @@ int activate_fd(int irq, int fd, int type, void *dev_id) | |||
153 | spin_lock_irqsave(&irq_lock, flags); | 135 | spin_lock_irqsave(&irq_lock, flags); |
154 | for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { | 136 | for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { |
155 | if ((irq_fd->fd == fd) && (irq_fd->type == type)) { | 137 | if ((irq_fd->fd == fd) && (irq_fd->type == type)) { |
156 | printk("Registering fd %d twice\n", fd); | 138 | printk(KERN_ERR "Registering fd %d twice\n", fd); |
157 | printk("Irqs : %d, %d\n", irq_fd->irq, irq); | 139 | printk(KERN_ERR "Irqs : %d, %d\n", irq_fd->irq, irq); |
158 | printk("Ids : 0x%p, 0x%p\n", irq_fd->id, dev_id); | 140 | printk(KERN_ERR "Ids : 0x%p, 0x%p\n", irq_fd->id, |
141 | dev_id); | ||
159 | goto out_unlock; | 142 | goto out_unlock; |
160 | } | 143 | } |
161 | } | 144 | } |
@@ -171,7 +154,8 @@ int activate_fd(int irq, int fd, int type, void *dev_id) | |||
171 | if (n == 0) | 154 | if (n == 0) |
172 | break; | 155 | break; |
173 | 156 | ||
174 | /* n > 0 | 157 | /* |
158 | * n > 0 | ||
175 | * It means we couldn't put new pollfd to current pollfds | 159 | * It means we couldn't put new pollfd to current pollfds |
176 | * and tmp_fds is NULL or too small for new pollfds array. | 160 | * and tmp_fds is NULL or too small for new pollfds array. |
177 | * Needed size is equal to n as minimum. | 161 | * Needed size is equal to n as minimum. |
@@ -197,7 +181,8 @@ int activate_fd(int irq, int fd, int type, void *dev_id) | |||
197 | 181 | ||
198 | spin_unlock_irqrestore(&irq_lock, flags); | 182 | spin_unlock_irqrestore(&irq_lock, flags); |
199 | 183 | ||
200 | /* This calls activate_fd, so it has to be outside the critical | 184 | /* |
185 | * This calls activate_fd, so it has to be outside the critical | ||
201 | * section. | 186 | * section. |
202 | */ | 187 | */ |
203 | maybe_sigio_broken(fd, (type == IRQ_READ)); | 188 | maybe_sigio_broken(fd, (type == IRQ_READ)); |
@@ -264,13 +249,14 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out) | |||
264 | i++; | 249 | i++; |
265 | } | 250 | } |
266 | if (irq == NULL) { | 251 | if (irq == NULL) { |
267 | printk("find_irq_by_fd doesn't have descriptor %d\n", fd); | 252 | printk(KERN_ERR "find_irq_by_fd doesn't have descriptor %d\n", |
253 | fd); | ||
268 | goto out; | 254 | goto out; |
269 | } | 255 | } |
270 | fdi = os_get_pollfd(i); | 256 | fdi = os_get_pollfd(i); |
271 | if ((fdi != -1) && (fdi != fd)) { | 257 | if ((fdi != -1) && (fdi != fd)) { |
272 | printk("find_irq_by_fd - mismatch between active_fds and " | 258 | printk(KERN_ERR "find_irq_by_fd - mismatch between active_fds " |
273 | "pollfds, fd %d vs %d, need %d\n", irq->fd, | 259 | "and pollfds, fd %d vs %d, need %d\n", irq->fd, |
274 | fdi, fd); | 260 | fdi, fd); |
275 | irq = NULL; | 261 | irq = NULL; |
276 | goto out; | 262 | goto out; |
@@ -306,7 +292,7 @@ void deactivate_fd(int fd, int irqnum) | |||
306 | 292 | ||
307 | spin_lock_irqsave(&irq_lock, flags); | 293 | spin_lock_irqsave(&irq_lock, flags); |
308 | irq = find_irq_by_fd(fd, irqnum, &i); | 294 | irq = find_irq_by_fd(fd, irqnum, &i); |
309 | if(irq == NULL){ | 295 | if (irq == NULL) { |
310 | spin_unlock_irqrestore(&irq_lock, flags); | 296 | spin_unlock_irqrestore(&irq_lock, flags); |
311 | return; | 297 | return; |
312 | } | 298 | } |
@@ -339,36 +325,12 @@ int deactivate_all_fds(void) | |||
339 | return 0; | 325 | return 0; |
340 | } | 326 | } |
341 | 327 | ||
342 | #ifdef CONFIG_MODE_TT | ||
343 | void forward_interrupts(int pid) | ||
344 | { | ||
345 | struct irq_fd *irq; | ||
346 | unsigned long flags; | ||
347 | int err; | ||
348 | |||
349 | spin_lock_irqsave(&irq_lock, flags); | ||
350 | for (irq = active_fds; irq != NULL; irq = irq->next) { | ||
351 | err = os_set_owner(irq->fd, pid); | ||
352 | if (err < 0) { | ||
353 | /* XXX Just remove the irq rather than | ||
354 | * print out an infinite stream of these | ||
355 | */ | ||
356 | printk("Failed to forward %d to pid %d, err = %d\n", | ||
357 | irq->fd, pid, -err); | ||
358 | } | ||
359 | |||
360 | irq->pid = pid; | ||
361 | } | ||
362 | spin_unlock_irqrestore(&irq_lock, flags); | ||
363 | } | ||
364 | #endif | ||
365 | |||
366 | /* | 328 | /* |
367 | * do_IRQ handles all normal device IRQ's (the special | 329 | * do_IRQ handles all normal device IRQ's (the special |
368 | * SMP cross-CPU interrupts have their own specific | 330 | * SMP cross-CPU interrupts have their own specific |
369 | * handlers). | 331 | * handlers). |
370 | */ | 332 | */ |
371 | unsigned int do_IRQ(int irq, union uml_pt_regs *regs) | 333 | unsigned int do_IRQ(int irq, struct uml_pt_regs *regs) |
372 | { | 334 | { |
373 | struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs); | 335 | struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs); |
374 | irq_enter(); | 336 | irq_enter(); |
@@ -396,8 +358,10 @@ int um_request_irq(unsigned int irq, int fd, int type, | |||
396 | EXPORT_SYMBOL(um_request_irq); | 358 | EXPORT_SYMBOL(um_request_irq); |
397 | EXPORT_SYMBOL(reactivate_fd); | 359 | EXPORT_SYMBOL(reactivate_fd); |
398 | 360 | ||
399 | /* hw_interrupt_type must define (startup || enable) && | 361 | /* |
400 | * (shutdown || disable) && end */ | 362 | * hw_interrupt_type must define (startup || enable) && |
363 | * (shutdown || disable) && end | ||
364 | */ | ||
401 | static void dummy(unsigned int irq) | 365 | static void dummy(unsigned int irq) |
402 | { | 366 | { |
403 | } | 367 | } |
@@ -446,7 +410,8 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler) | |||
446 | 410 | ||
447 | err = os_pipe(fds, 1, 1); | 411 | err = os_pipe(fds, 1, 1); |
448 | if (err) { | 412 | if (err) { |
449 | printk("init_aio_irq - os_pipe failed, err = %d\n", -err); | 413 | printk(KERN_ERR "init_aio_irq - os_pipe failed, err = %d\n", |
414 | -err); | ||
450 | goto out; | 415 | goto out; |
451 | } | 416 | } |
452 | 417 | ||
@@ -454,7 +419,8 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler) | |||
454 | IRQF_DISABLED | IRQF_SAMPLE_RANDOM, name, | 419 | IRQF_DISABLED | IRQF_SAMPLE_RANDOM, name, |
455 | (void *) (long) fds[0]); | 420 | (void *) (long) fds[0]); |
456 | if (err) { | 421 | if (err) { |
457 | printk("init_aio_irq - : um_request_irq failed, err = %d\n", | 422 | printk(KERN_ERR "init_aio_irq - : um_request_irq failed, " |
423 | "err = %d\n", | ||
458 | err); | 424 | err); |
459 | goto out_close; | 425 | goto out_close; |
460 | } | 426 | } |
@@ -525,8 +491,9 @@ unsigned long to_irq_stack(unsigned long *mask_out) | |||
525 | int nested; | 491 | int nested; |
526 | 492 | ||
527 | mask = xchg(&pending_mask, *mask_out); | 493 | mask = xchg(&pending_mask, *mask_out); |
528 | if(mask != 0){ | 494 | if (mask != 0) { |
529 | /* If any interrupts come in at this point, we want to | 495 | /* |
496 | * If any interrupts come in at this point, we want to | ||
530 | * make sure that their bits aren't lost by our | 497 | * make sure that their bits aren't lost by our |
531 | * putting our bit in. So, this loop accumulates bits | 498 | * putting our bit in. So, this loop accumulates bits |
532 | * until xchg returns the same value that we put in. | 499 | * until xchg returns the same value that we put in. |
@@ -538,13 +505,13 @@ unsigned long to_irq_stack(unsigned long *mask_out) | |||
538 | do { | 505 | do { |
539 | old |= mask; | 506 | old |= mask; |
540 | mask = xchg(&pending_mask, old); | 507 | mask = xchg(&pending_mask, old); |
541 | } while(mask != old); | 508 | } while (mask != old); |
542 | return 1; | 509 | return 1; |
543 | } | 510 | } |
544 | 511 | ||
545 | ti = current_thread_info(); | 512 | ti = current_thread_info(); |
546 | nested = (ti->real_thread != NULL); | 513 | nested = (ti->real_thread != NULL); |
547 | if(!nested){ | 514 | if (!nested) { |
548 | struct task_struct *task; | 515 | struct task_struct *task; |
549 | struct thread_info *tti; | 516 | struct thread_info *tti; |
550 | 517 | ||
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c index 7b3e53fb8070..1b388b41d95d 100644 --- a/arch/um/kernel/ksyms.c +++ b/arch/um/kernel/ksyms.c | |||
@@ -1,22 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 - 2004 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/module.h" | 6 | #include "linux/module.h" |
7 | #include "linux/string.h" | 7 | #include "linux/syscalls.h" |
8 | #include "linux/smp_lock.h" | 8 | #include "asm/a.out.h" |
9 | #include "linux/spinlock.h" | ||
10 | #include "linux/highmem.h" | ||
11 | #include "asm/current.h" | ||
12 | #include "asm/processor.h" | ||
13 | #include "asm/unistd.h" | ||
14 | #include "asm/pgalloc.h" | ||
15 | #include "asm/pgtable.h" | ||
16 | #include "asm/page.h" | ||
17 | #include "asm/tlbflush.h" | 9 | #include "asm/tlbflush.h" |
18 | #include "kern_util.h" | 10 | #include "asm/uaccess.h" |
19 | #include "as-layout.h" | 11 | #include "as-layout.h" |
12 | #include "kern_util.h" | ||
20 | #include "mem_user.h" | 13 | #include "mem_user.h" |
21 | #include "os.h" | 14 | #include "os.h" |
22 | 15 | ||
@@ -34,30 +27,19 @@ EXPORT_SYMBOL(get_kmem_end); | |||
34 | EXPORT_SYMBOL(high_physmem); | 27 | EXPORT_SYMBOL(high_physmem); |
35 | EXPORT_SYMBOL(empty_zero_page); | 28 | EXPORT_SYMBOL(empty_zero_page); |
36 | EXPORT_SYMBOL(um_virt_to_phys); | 29 | EXPORT_SYMBOL(um_virt_to_phys); |
37 | EXPORT_SYMBOL(mode_tt); | ||
38 | EXPORT_SYMBOL(handle_page_fault); | 30 | EXPORT_SYMBOL(handle_page_fault); |
39 | EXPORT_SYMBOL(find_iomem); | 31 | EXPORT_SYMBOL(find_iomem); |
40 | 32 | ||
41 | #ifdef CONFIG_MODE_TT | 33 | EXPORT_SYMBOL(strnlen_user); |
42 | EXPORT_SYMBOL(stop); | 34 | EXPORT_SYMBOL(strncpy_from_user); |
43 | EXPORT_SYMBOL(strncpy_from_user_tt); | 35 | EXPORT_SYMBOL(copy_to_user); |
44 | EXPORT_SYMBOL(copy_from_user_tt); | 36 | EXPORT_SYMBOL(copy_from_user); |
45 | EXPORT_SYMBOL(copy_to_user_tt); | 37 | EXPORT_SYMBOL(clear_user); |
46 | #endif | ||
47 | |||
48 | #ifdef CONFIG_MODE_SKAS | ||
49 | EXPORT_SYMBOL(strnlen_user_skas); | ||
50 | EXPORT_SYMBOL(strncpy_from_user_skas); | ||
51 | EXPORT_SYMBOL(copy_to_user_skas); | ||
52 | EXPORT_SYMBOL(copy_from_user_skas); | ||
53 | EXPORT_SYMBOL(clear_user_skas); | ||
54 | #endif | ||
55 | EXPORT_SYMBOL(uml_strdup); | 38 | EXPORT_SYMBOL(uml_strdup); |
56 | 39 | ||
57 | EXPORT_SYMBOL(os_stat_fd); | 40 | EXPORT_SYMBOL(os_stat_fd); |
58 | EXPORT_SYMBOL(os_stat_file); | 41 | EXPORT_SYMBOL(os_stat_file); |
59 | EXPORT_SYMBOL(os_access); | 42 | EXPORT_SYMBOL(os_access); |
60 | EXPORT_SYMBOL(os_print_error); | ||
61 | EXPORT_SYMBOL(os_get_exec_close); | 43 | EXPORT_SYMBOL(os_get_exec_close); |
62 | EXPORT_SYMBOL(os_set_exec_close); | 44 | EXPORT_SYMBOL(os_set_exec_close); |
63 | EXPORT_SYMBOL(os_getpid); | 45 | EXPORT_SYMBOL(os_getpid); |
@@ -85,9 +67,6 @@ EXPORT_SYMBOL(run_helper); | |||
85 | EXPORT_SYMBOL(start_thread); | 67 | EXPORT_SYMBOL(start_thread); |
86 | EXPORT_SYMBOL(dump_thread); | 68 | EXPORT_SYMBOL(dump_thread); |
87 | 69 | ||
88 | EXPORT_SYMBOL(do_gettimeofday); | ||
89 | EXPORT_SYMBOL(do_settimeofday); | ||
90 | |||
91 | #ifdef CONFIG_SMP | 70 | #ifdef CONFIG_SMP |
92 | 71 | ||
93 | /* required for SMP */ | 72 | /* required for SMP */ |
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index d2b11f242698..8456397f5f4d 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include "as-layout.h" | 17 | #include "as-layout.h" |
18 | #include "kern.h" | 18 | #include "kern.h" |
19 | #include "mem_user.h" | 19 | #include "mem_user.h" |
20 | #include "uml_uaccess.h" | 20 | #include "um_uaccess.h" |
21 | #include "os.h" | 21 | #include "os.h" |
22 | #include "linux/types.h" | 22 | #include "linux/types.h" |
23 | #include "linux/string.h" | 23 | #include "linux/string.h" |
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index 5ee7e851bbc1..e66432f42485 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c | |||
@@ -1,25 +1,17 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/mm.h" | ||
7 | #include "linux/rbtree.h" | ||
8 | #include "linux/slab.h" | ||
9 | #include "linux/vmalloc.h" | ||
10 | #include "linux/bootmem.h" | 6 | #include "linux/bootmem.h" |
11 | #include "linux/module.h" | 7 | #include "linux/mm.h" |
12 | #include "linux/pfn.h" | 8 | #include "linux/pfn.h" |
13 | #include "asm/types.h" | 9 | #include "asm/page.h" |
14 | #include "asm/pgtable.h" | ||
15 | #include "kern_util.h" | ||
16 | #include "as-layout.h" | 10 | #include "as-layout.h" |
17 | #include "mode_kern.h" | 11 | #include "init.h" |
18 | #include "mem.h" | 12 | #include "kern.h" |
19 | #include "mem_user.h" | 13 | #include "mem_user.h" |
20 | #include "os.h" | 14 | #include "os.h" |
21 | #include "kern.h" | ||
22 | #include "init.h" | ||
23 | 15 | ||
24 | static int physmem_fd = -1; | 16 | static int physmem_fd = -1; |
25 | 17 | ||
@@ -49,10 +41,10 @@ int __init init_maps(unsigned long physmem, unsigned long iomem, | |||
49 | total_len = phys_len + iomem_len + highmem_len; | 41 | total_len = phys_len + iomem_len + highmem_len; |
50 | 42 | ||
51 | map = alloc_bootmem_low_pages(total_len); | 43 | map = alloc_bootmem_low_pages(total_len); |
52 | if(map == NULL) | 44 | if (map == NULL) |
53 | return -ENOMEM; | 45 | return -ENOMEM; |
54 | 46 | ||
55 | for(i = 0; i < total_pages; i++){ | 47 | for (i = 0; i < total_pages; i++) { |
56 | p = &map[i]; | 48 | p = &map[i]; |
57 | memset(p, 0, sizeof(struct page)); | 49 | memset(p, 0, sizeof(struct page)); |
58 | SetPageReserved(p); | 50 | SetPageReserved(p); |
@@ -68,8 +60,8 @@ static unsigned long kmem_top = 0; | |||
68 | 60 | ||
69 | unsigned long get_kmem_end(void) | 61 | unsigned long get_kmem_end(void) |
70 | { | 62 | { |
71 | if(kmem_top == 0) | 63 | if (kmem_top == 0) |
72 | kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas); | 64 | kmem_top = host_task_size - 1024 * 1024; |
73 | return kmem_top; | 65 | return kmem_top; |
74 | } | 66 | } |
75 | 67 | ||
@@ -81,9 +73,9 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len, | |||
81 | 73 | ||
82 | fd = phys_mapping(phys, &offset); | 74 | fd = phys_mapping(phys, &offset); |
83 | err = os_map_memory((void *) virt, fd, offset, len, r, w, x); | 75 | err = os_map_memory((void *) virt, fd, offset, len, r, w, x); |
84 | if(err) { | 76 | if (err) { |
85 | if(err == -ENOMEM) | 77 | if (err == -ENOMEM) |
86 | printk("try increasing the host's " | 78 | printk(KERN_ERR "try increasing the host's " |
87 | "/proc/sys/vm/max_map_count to <physical " | 79 | "/proc/sys/vm/max_map_count to <physical " |
88 | "memory size>/4096\n"); | 80 | "memory size>/4096\n"); |
89 | panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, " | 81 | panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, " |
@@ -105,13 +97,16 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end, | |||
105 | 97 | ||
106 | offset = uml_reserved - uml_physmem; | 98 | offset = uml_reserved - uml_physmem; |
107 | err = os_map_memory((void *) uml_reserved, physmem_fd, offset, | 99 | err = os_map_memory((void *) uml_reserved, physmem_fd, offset, |
108 | len - offset, 1, 1, 0); | 100 | len - offset, 1, 1, 1); |
109 | if(err < 0){ | 101 | if (err < 0) { |
110 | os_print_error(err, "Mapping memory"); | 102 | printf("setup_physmem - mapping %ld bytes of memory at 0x%p " |
103 | "failed - errno = %d\n", len - offset, | ||
104 | (void *) uml_reserved, err); | ||
111 | exit(1); | 105 | exit(1); |
112 | } | 106 | } |
113 | 107 | ||
114 | /* Special kludge - This page will be mapped in to userspace processes | 108 | /* |
109 | * Special kludge - This page will be mapped in to userspace processes | ||
115 | * from physmem_fd, so it needs to be written out there. | 110 | * from physmem_fd, so it needs to be written out there. |
116 | */ | 111 | */ |
117 | os_seek_file(physmem_fd, __pa(&__syscall_stub_start)); | 112 | os_seek_file(physmem_fd, __pa(&__syscall_stub_start)); |
@@ -122,20 +117,20 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end, | |||
122 | len - bootmap_size - reserve); | 117 | len - bootmap_size - reserve); |
123 | } | 118 | } |
124 | 119 | ||
125 | int phys_mapping(unsigned long phys, __u64 *offset_out) | 120 | int phys_mapping(unsigned long phys, unsigned long long *offset_out) |
126 | { | 121 | { |
127 | int fd = -1; | 122 | int fd = -1; |
128 | 123 | ||
129 | if(phys < physmem_size){ | 124 | if (phys < physmem_size) { |
130 | fd = physmem_fd; | 125 | fd = physmem_fd; |
131 | *offset_out = phys; | 126 | *offset_out = phys; |
132 | } | 127 | } |
133 | else if(phys < __pa(end_iomem)){ | 128 | else if (phys < __pa(end_iomem)) { |
134 | struct iomem_region *region = iomem_regions; | 129 | struct iomem_region *region = iomem_regions; |
135 | 130 | ||
136 | while(region != NULL){ | 131 | while (region != NULL) { |
137 | if((phys >= region->phys) && | 132 | if ((phys >= region->phys) && |
138 | (phys < region->phys + region->size)){ | 133 | (phys < region->phys + region->size)) { |
139 | fd = region->fd; | 134 | fd = region->fd; |
140 | *offset_out = phys - region->phys; | 135 | *offset_out = phys - region->phys; |
141 | break; | 136 | break; |
@@ -143,7 +138,7 @@ int phys_mapping(unsigned long phys, __u64 *offset_out) | |||
143 | region = region->next; | 138 | region = region->next; |
144 | } | 139 | } |
145 | } | 140 | } |
146 | else if(phys < __pa(end_iomem) + highmem){ | 141 | else if (phys < __pa(end_iomem) + highmem) { |
147 | fd = physmem_fd; | 142 | fd = physmem_fd; |
148 | *offset_out = phys - iomem_size; | 143 | *offset_out = phys - iomem_size; |
149 | } | 144 | } |
@@ -188,8 +183,8 @@ unsigned long find_iomem(char *driver, unsigned long *len_out) | |||
188 | { | 183 | { |
189 | struct iomem_region *region = iomem_regions; | 184 | struct iomem_region *region = iomem_regions; |
190 | 185 | ||
191 | while(region != NULL){ | 186 | while (region != NULL) { |
192 | if(!strcmp(region->driver, driver)){ | 187 | if (!strcmp(region->driver, driver)) { |
193 | *len_out = region->size; | 188 | *len_out = region->size; |
194 | return region->virt; | 189 | return region->virt; |
195 | } | 190 | } |
@@ -206,12 +201,12 @@ int setup_iomem(void) | |||
206 | unsigned long iomem_start = high_physmem + PAGE_SIZE; | 201 | unsigned long iomem_start = high_physmem + PAGE_SIZE; |
207 | int err; | 202 | int err; |
208 | 203 | ||
209 | while(region != NULL){ | 204 | while (region != NULL) { |
210 | err = os_map_memory((void *) iomem_start, region->fd, 0, | 205 | err = os_map_memory((void *) iomem_start, region->fd, 0, |
211 | region->size, 1, 1, 0); | 206 | region->size, 1, 1, 0); |
212 | if(err) | 207 | if (err) |
213 | printk("Mapping iomem region for driver '%s' failed, " | 208 | printk(KERN_ERR "Mapping iomem region for driver '%s' " |
214 | "errno = %d\n", region->driver, -err); | 209 | "failed, errno = %d\n", region->driver, -err); |
215 | else { | 210 | else { |
216 | region->virt = iomem_start; | 211 | region->virt = iomem_start; |
217 | region->phys = __pa(region->virt); | 212 | region->phys = __pa(region->virt); |
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index bfa52f206bb6..0eae00b3e588 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c | |||
@@ -1,53 +1,30 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Copyright 2003 PathScale, Inc. | 3 | * Copyright 2003 PathScale, Inc. |
4 | * Licensed under the GPL | 4 | * Licensed under the GPL |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include "linux/kernel.h" | 7 | #include "linux/stddef.h" |
8 | #include "linux/sched.h" | 8 | #include "linux/err.h" |
9 | #include "linux/interrupt.h" | 9 | #include "linux/hardirq.h" |
10 | #include "linux/string.h" | ||
11 | #include "linux/mm.h" | 10 | #include "linux/mm.h" |
12 | #include "linux/slab.h" | 11 | #include "linux/personality.h" |
13 | #include "linux/utsname.h" | ||
14 | #include "linux/fs.h" | ||
15 | #include "linux/utime.h" | ||
16 | #include "linux/smp_lock.h" | ||
17 | #include "linux/module.h" | ||
18 | #include "linux/init.h" | ||
19 | #include "linux/capability.h" | ||
20 | #include "linux/vmalloc.h" | ||
21 | #include "linux/spinlock.h" | ||
22 | #include "linux/proc_fs.h" | 12 | #include "linux/proc_fs.h" |
23 | #include "linux/ptrace.h" | 13 | #include "linux/ptrace.h" |
24 | #include "linux/random.h" | 14 | #include "linux/random.h" |
25 | #include "linux/personality.h" | 15 | #include "linux/sched.h" |
26 | #include "asm/unistd.h" | 16 | #include "linux/tick.h" |
27 | #include "asm/mman.h" | 17 | #include "linux/threads.h" |
28 | #include "asm/segment.h" | ||
29 | #include "asm/stat.h" | ||
30 | #include "asm/pgtable.h" | 18 | #include "asm/pgtable.h" |
31 | #include "asm/processor.h" | ||
32 | #include "asm/tlbflush.h" | ||
33 | #include "asm/uaccess.h" | 19 | #include "asm/uaccess.h" |
34 | #include "asm/user.h" | ||
35 | #include "kern_util.h" | ||
36 | #include "as-layout.h" | 20 | #include "as-layout.h" |
37 | #include "kern.h" | 21 | #include "kern_util.h" |
38 | #include "signal_kern.h" | ||
39 | #include "init.h" | ||
40 | #include "irq_user.h" | ||
41 | #include "mem_user.h" | ||
42 | #include "tlb.h" | ||
43 | #include "frame_kern.h" | ||
44 | #include "sigcontext.h" | ||
45 | #include "os.h" | 22 | #include "os.h" |
46 | #include "mode.h" | 23 | #include "skas.h" |
47 | #include "mode_kern.h" | 24 | #include "tlb.h" |
48 | #include "choose-mode.h" | ||
49 | 25 | ||
50 | /* This is a per-cpu array. A processor only modifies its entry and it only | 26 | /* |
27 | * This is a per-cpu array. A processor only modifies its entry and it only | ||
51 | * cares about its entry, so it's OK if another processor is modifying its | 28 | * cares about its entry, so it's OK if another processor is modifying its |
52 | * entry. | 29 | * entry. |
53 | */ | 30 | */ |
@@ -55,15 +32,16 @@ struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; | |||
55 | 32 | ||
56 | static inline int external_pid(struct task_struct *task) | 33 | static inline int external_pid(struct task_struct *task) |
57 | { | 34 | { |
58 | return CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task); | 35 | /* FIXME: Need to look up userspace_pid by cpu */ |
36 | return userspace_pid[0]; | ||
59 | } | 37 | } |
60 | 38 | ||
61 | int pid_to_processor_id(int pid) | 39 | int pid_to_processor_id(int pid) |
62 | { | 40 | { |
63 | int i; | 41 | int i; |
64 | 42 | ||
65 | for(i = 0; i < ncpus; i++){ | 43 | for(i = 0; i < ncpus; i++) { |
66 | if(cpu_tasks[i].pid == pid) | 44 | if (cpu_tasks[i].pid == pid) |
67 | return i; | 45 | return i; |
68 | } | 46 | } |
69 | return -1; | 47 | return -1; |
@@ -82,9 +60,9 @@ unsigned long alloc_stack(int order, int atomic) | |||
82 | if (atomic) | 60 | if (atomic) |
83 | flags = GFP_ATOMIC; | 61 | flags = GFP_ATOMIC; |
84 | page = __get_free_pages(flags, order); | 62 | page = __get_free_pages(flags, order); |
85 | if(page == 0) | 63 | if (page == 0) |
86 | return 0; | 64 | return 0; |
87 | stack_protections(page); | 65 | |
88 | return page; | 66 | return page; |
89 | } | 67 | } |
90 | 68 | ||
@@ -105,6 +83,8 @@ static inline void set_current(struct task_struct *task) | |||
105 | { external_pid(task), task }); | 83 | { external_pid(task), task }); |
106 | } | 84 | } |
107 | 85 | ||
86 | extern void arch_switch_to(struct task_struct *from, struct task_struct *to); | ||
87 | |||
108 | void *_switch_to(void *prev, void *next, void *last) | 88 | void *_switch_to(void *prev, void *next, void *last) |
109 | { | 89 | { |
110 | struct task_struct *from = prev; | 90 | struct task_struct *from = prev; |
@@ -114,9 +94,14 @@ void *_switch_to(void *prev, void *next, void *last) | |||
114 | set_current(to); | 94 | set_current(to); |
115 | 95 | ||
116 | do { | 96 | do { |
117 | current->thread.saved_task = NULL ; | 97 | current->thread.saved_task = NULL; |
118 | CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next); | 98 | |
119 | if(current->thread.saved_task) | 99 | switch_threads(&from->thread.switch_buf, |
100 | &to->thread.switch_buf); | ||
101 | |||
102 | arch_switch_to(current->thread.prev_sched, current); | ||
103 | |||
104 | if (current->thread.saved_task) | ||
120 | show_regs(&(current->thread.regs)); | 105 | show_regs(&(current->thread.regs)); |
121 | next= current->thread.saved_task; | 106 | next= current->thread.saved_task; |
122 | prev= current; | 107 | prev= current; |
@@ -128,20 +113,14 @@ void *_switch_to(void *prev, void *next, void *last) | |||
128 | 113 | ||
129 | void interrupt_end(void) | 114 | void interrupt_end(void) |
130 | { | 115 | { |
131 | if(need_resched()) | 116 | if (need_resched()) |
132 | schedule(); | 117 | schedule(); |
133 | if(test_tsk_thread_flag(current, TIF_SIGPENDING)) | 118 | if (test_tsk_thread_flag(current, TIF_SIGPENDING)) |
134 | do_signal(); | 119 | do_signal(); |
135 | } | 120 | } |
136 | 121 | ||
137 | void release_thread(struct task_struct *task) | ||
138 | { | ||
139 | CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task)); | ||
140 | } | ||
141 | |||
142 | void exit_thread(void) | 122 | void exit_thread(void) |
143 | { | 123 | { |
144 | unprotect_stack((unsigned long) current_thread); | ||
145 | } | 124 | } |
146 | 125 | ||
147 | void *get_current(void) | 126 | void *get_current(void) |
@@ -149,28 +128,99 @@ void *get_current(void) | |||
149 | return current; | 128 | return current; |
150 | } | 129 | } |
151 | 130 | ||
131 | extern void schedule_tail(struct task_struct *prev); | ||
132 | |||
133 | /* | ||
134 | * This is called magically, by its address being stuffed in a jmp_buf | ||
135 | * and being longjmp-d to. | ||
136 | */ | ||
137 | void new_thread_handler(void) | ||
138 | { | ||
139 | int (*fn)(void *), n; | ||
140 | void *arg; | ||
141 | |||
142 | if (current->thread.prev_sched != NULL) | ||
143 | schedule_tail(current->thread.prev_sched); | ||
144 | current->thread.prev_sched = NULL; | ||
145 | |||
146 | fn = current->thread.request.u.thread.proc; | ||
147 | arg = current->thread.request.u.thread.arg; | ||
148 | |||
149 | /* | ||
150 | * The return value is 1 if the kernel thread execs a process, | ||
151 | * 0 if it just exits | ||
152 | */ | ||
153 | n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); | ||
154 | if (n == 1) { | ||
155 | /* Handle any immediate reschedules or signals */ | ||
156 | interrupt_end(); | ||
157 | userspace(¤t->thread.regs.regs); | ||
158 | } | ||
159 | else do_exit(0); | ||
160 | } | ||
161 | |||
162 | /* Called magically, see new_thread_handler above */ | ||
163 | void fork_handler(void) | ||
164 | { | ||
165 | force_flush_all(); | ||
166 | if (current->thread.prev_sched == NULL) | ||
167 | panic("blech"); | ||
168 | |||
169 | schedule_tail(current->thread.prev_sched); | ||
170 | |||
171 | /* | ||
172 | * XXX: if interrupt_end() calls schedule, this call to | ||
173 | * arch_switch_to isn't needed. We could want to apply this to | ||
174 | * improve performance. -bb | ||
175 | */ | ||
176 | arch_switch_to(current->thread.prev_sched, current); | ||
177 | |||
178 | current->thread.prev_sched = NULL; | ||
179 | |||
180 | /* Handle any immediate reschedules or signals */ | ||
181 | interrupt_end(); | ||
182 | |||
183 | userspace(¤t->thread.regs.regs); | ||
184 | } | ||
185 | |||
152 | int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, | 186 | int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, |
153 | unsigned long stack_top, struct task_struct * p, | 187 | unsigned long stack_top, struct task_struct * p, |
154 | struct pt_regs *regs) | 188 | struct pt_regs *regs) |
155 | { | 189 | { |
156 | int ret; | 190 | void (*handler)(void); |
191 | int ret = 0; | ||
157 | 192 | ||
158 | p->thread = (struct thread_struct) INIT_THREAD; | 193 | p->thread = (struct thread_struct) INIT_THREAD; |
159 | ret = CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr, | ||
160 | clone_flags, sp, stack_top, p, regs); | ||
161 | 194 | ||
162 | if (ret || !current->thread.forking) | 195 | if (current->thread.forking) { |
163 | goto out; | 196 | memcpy(&p->thread.regs.regs, ®s->regs, |
197 | sizeof(p->thread.regs.regs)); | ||
198 | REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.gp, 0); | ||
199 | if (sp != 0) | ||
200 | REGS_SP(p->thread.regs.regs.gp) = sp; | ||
164 | 201 | ||
165 | clear_flushed_tls(p); | 202 | handler = fork_handler; |
166 | 203 | ||
167 | /* | 204 | arch_copy_thread(¤t->thread.arch, &p->thread.arch); |
168 | * Set a new TLS for the child thread? | 205 | } |
169 | */ | 206 | else { |
170 | if (clone_flags & CLONE_SETTLS) | 207 | init_thread_registers(&p->thread.regs.regs); |
171 | ret = arch_copy_tls(p); | 208 | p->thread.request.u.thread = current->thread.request.u.thread; |
209 | handler = new_thread_handler; | ||
210 | } | ||
211 | |||
212 | new_thread(task_stack_page(p), &p->thread.switch_buf, handler); | ||
213 | |||
214 | if (current->thread.forking) { | ||
215 | clear_flushed_tls(p); | ||
216 | |||
217 | /* | ||
218 | * Set a new TLS for the child thread? | ||
219 | */ | ||
220 | if (clone_flags & CLONE_SETTLS) | ||
221 | ret = arch_copy_tls(p); | ||
222 | } | ||
172 | 223 | ||
173 | out: | ||
174 | return ret; | 224 | return ret; |
175 | } | 225 | } |
176 | 226 | ||
@@ -179,39 +229,35 @@ void initial_thread_cb(void (*proc)(void *), void *arg) | |||
179 | int save_kmalloc_ok = kmalloc_ok; | 229 | int save_kmalloc_ok = kmalloc_ok; |
180 | 230 | ||
181 | kmalloc_ok = 0; | 231 | kmalloc_ok = 0; |
182 | CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc, | 232 | initial_thread_cb_skas(proc, arg); |
183 | arg); | ||
184 | kmalloc_ok = save_kmalloc_ok; | 233 | kmalloc_ok = save_kmalloc_ok; |
185 | } | 234 | } |
186 | 235 | ||
187 | #ifdef CONFIG_MODE_TT | ||
188 | unsigned long stack_sp(unsigned long page) | ||
189 | { | ||
190 | return page + PAGE_SIZE - sizeof(void *); | ||
191 | } | ||
192 | #endif | ||
193 | |||
194 | void default_idle(void) | 236 | void default_idle(void) |
195 | { | 237 | { |
196 | CHOOSE_MODE(uml_idle_timer(), (void) 0); | 238 | unsigned long long nsecs; |
197 | 239 | ||
198 | while(1){ | 240 | while(1) { |
199 | /* endless idle loop with no priority at all */ | 241 | /* endless idle loop with no priority at all */ |
200 | 242 | ||
201 | /* | 243 | /* |
202 | * although we are an idle CPU, we do not want to | 244 | * although we are an idle CPU, we do not want to |
203 | * get into the scheduler unnecessarily. | 245 | * get into the scheduler unnecessarily. |
204 | */ | 246 | */ |
205 | if(need_resched()) | 247 | if (need_resched()) |
206 | schedule(); | 248 | schedule(); |
207 | 249 | ||
208 | idle_sleep(10); | 250 | tick_nohz_stop_sched_tick(); |
251 | nsecs = disable_timer(); | ||
252 | idle_sleep(nsecs); | ||
253 | tick_nohz_restart_sched_tick(); | ||
209 | } | 254 | } |
210 | } | 255 | } |
211 | 256 | ||
212 | void cpu_idle(void) | 257 | void cpu_idle(void) |
213 | { | 258 | { |
214 | CHOOSE_MODE(init_idle_tt(), init_idle_skas()); | 259 | cpu_tasks[current_thread->cpu].pid = os_getpid(); |
260 | default_idle(); | ||
215 | } | 261 | } |
216 | 262 | ||
217 | void *um_virt_to_phys(struct task_struct *task, unsigned long addr, | 263 | void *um_virt_to_phys(struct task_struct *task, unsigned long addr, |
@@ -223,26 +269,26 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr, | |||
223 | pte_t *pte; | 269 | pte_t *pte; |
224 | pte_t ptent; | 270 | pte_t ptent; |
225 | 271 | ||
226 | if(task->mm == NULL) | 272 | if (task->mm == NULL) |
227 | return ERR_PTR(-EINVAL); | 273 | return ERR_PTR(-EINVAL); |
228 | pgd = pgd_offset(task->mm, addr); | 274 | pgd = pgd_offset(task->mm, addr); |
229 | if(!pgd_present(*pgd)) | 275 | if (!pgd_present(*pgd)) |
230 | return ERR_PTR(-EINVAL); | 276 | return ERR_PTR(-EINVAL); |
231 | 277 | ||
232 | pud = pud_offset(pgd, addr); | 278 | pud = pud_offset(pgd, addr); |
233 | if(!pud_present(*pud)) | 279 | if (!pud_present(*pud)) |
234 | return ERR_PTR(-EINVAL); | 280 | return ERR_PTR(-EINVAL); |
235 | 281 | ||
236 | pmd = pmd_offset(pud, addr); | 282 | pmd = pmd_offset(pud, addr); |
237 | if(!pmd_present(*pmd)) | 283 | if (!pmd_present(*pmd)) |
238 | return ERR_PTR(-EINVAL); | 284 | return ERR_PTR(-EINVAL); |
239 | 285 | ||
240 | pte = pte_offset_kernel(pmd, addr); | 286 | pte = pte_offset_kernel(pmd, addr); |
241 | ptent = *pte; | 287 | ptent = *pte; |
242 | if(!pte_present(ptent)) | 288 | if (!pte_present(ptent)) |
243 | return ERR_PTR(-EINVAL); | 289 | return ERR_PTR(-EINVAL); |
244 | 290 | ||
245 | if(pte_out != NULL) | 291 | if (pte_out != NULL) |
246 | *pte_out = ptent; | 292 | *pte_out = ptent; |
247 | return (void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK); | 293 | return (void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK); |
248 | } | 294 | } |
@@ -315,7 +361,7 @@ int smp_sigio_handler(void) | |||
315 | #ifdef CONFIG_SMP | 361 | #ifdef CONFIG_SMP |
316 | int cpu = current_thread->cpu; | 362 | int cpu = current_thread->cpu; |
317 | IPI_handler(cpu); | 363 | IPI_handler(cpu); |
318 | if(cpu != 0) | 364 | if (cpu != 0) |
319 | return 1; | 365 | return 1; |
320 | #endif | 366 | #endif |
321 | return 0; | 367 | return 0; |
@@ -343,7 +389,8 @@ int get_using_sysemu(void) | |||
343 | 389 | ||
344 | static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data) | 390 | static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data) |
345 | { | 391 | { |
346 | if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/ | 392 | if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) |
393 | /* No overflow */ | ||
347 | *eof = 1; | 394 | *eof = 1; |
348 | 395 | ||
349 | return strlen(buf); | 396 | return strlen(buf); |
@@ -358,7 +405,8 @@ static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned | |||
358 | 405 | ||
359 | if (tmp[0] >= '0' && tmp[0] <= '2') | 406 | if (tmp[0] >= '0' && tmp[0] <= '2') |
360 | set_using_sysemu(tmp[0] - '0'); | 407 | set_using_sysemu(tmp[0] - '0'); |
361 | return count; /*We use the first char, but pretend to write everything*/ | 408 | /* We use the first char, but pretend to write everything */ |
409 | return count; | ||
362 | } | 410 | } |
363 | 411 | ||
364 | int __init make_proc_sysemu(void) | 412 | int __init make_proc_sysemu(void) |
@@ -388,10 +436,10 @@ int singlestepping(void * t) | |||
388 | struct task_struct *task = t ? t : current; | 436 | struct task_struct *task = t ? t : current; |
389 | 437 | ||
390 | if ( ! (task->ptrace & PT_DTRACE) ) | 438 | if ( ! (task->ptrace & PT_DTRACE) ) |
391 | return(0); | 439 | return 0; |
392 | 440 | ||
393 | if (task->thread.singlestep_syscall) | 441 | if (task->thread.singlestep_syscall) |
394 | return(1); | 442 | return 1; |
395 | 443 | ||
396 | return 2; | 444 | return 2; |
397 | } | 445 | } |
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 6916c8888dba..a0eba0833068 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c | |||
@@ -1,35 +1,27 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/sched.h" | ||
7 | #include "linux/mm.h" | ||
8 | #include "linux/errno.h" | ||
9 | #include "linux/smp_lock.h" | ||
10 | #include "linux/security.h" | ||
11 | #include "linux/ptrace.h" | ||
12 | #include "linux/audit.h" | 6 | #include "linux/audit.h" |
7 | #include "linux/ptrace.h" | ||
8 | #include "linux/sched.h" | ||
9 | #include "asm/uaccess.h" | ||
13 | #ifdef CONFIG_PROC_MM | 10 | #ifdef CONFIG_PROC_MM |
14 | #include "linux/proc_mm.h" | 11 | #include "proc_mm.h" |
15 | #endif | 12 | #endif |
16 | #include "asm/ptrace.h" | ||
17 | #include "asm/uaccess.h" | ||
18 | #include "kern_util.h" | ||
19 | #include "skas_ptrace.h" | 13 | #include "skas_ptrace.h" |
20 | #include "sysdep/ptrace.h" | ||
21 | #include "os.h" | ||
22 | 14 | ||
23 | static inline void set_singlestepping(struct task_struct *child, int on) | 15 | static inline void set_singlestepping(struct task_struct *child, int on) |
24 | { | 16 | { |
25 | if (on) | 17 | if (on) |
26 | child->ptrace |= PT_DTRACE; | 18 | child->ptrace |= PT_DTRACE; |
27 | else | 19 | else |
28 | child->ptrace &= ~PT_DTRACE; | 20 | child->ptrace &= ~PT_DTRACE; |
29 | child->thread.singlestep_syscall = 0; | 21 | child->thread.singlestep_syscall = 0; |
30 | 22 | ||
31 | #ifdef SUBARCH_SET_SINGLESTEPPING | 23 | #ifdef SUBARCH_SET_SINGLESTEPPING |
32 | SUBARCH_SET_SINGLESTEPPING(child, on); | 24 | SUBARCH_SET_SINGLESTEPPING(child, on); |
33 | #endif | 25 | #endif |
34 | } | 26 | } |
35 | 27 | ||
@@ -37,8 +29,8 @@ static inline void set_singlestepping(struct task_struct *child, int on) | |||
37 | * Called by kernel/ptrace.c when detaching.. | 29 | * Called by kernel/ptrace.c when detaching.. |
38 | */ | 30 | */ |
39 | void ptrace_disable(struct task_struct *child) | 31 | void ptrace_disable(struct task_struct *child) |
40 | { | 32 | { |
41 | set_singlestepping(child,0); | 33 | set_singlestepping(child,0); |
42 | } | 34 | } |
43 | 35 | ||
44 | extern int peek_user(struct task_struct * child, long addr, long data); | 36 | extern int peek_user(struct task_struct * child, long addr, long data); |
@@ -50,40 +42,40 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
50 | unsigned long __user *p = (void __user *)(unsigned long)data; | 42 | unsigned long __user *p = (void __user *)(unsigned long)data; |
51 | 43 | ||
52 | switch (request) { | 44 | switch (request) { |
53 | /* when I and D space are separate, these will need to be fixed. */ | 45 | /* read word at location addr. */ |
54 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 46 | case PTRACE_PEEKTEXT: |
55 | case PTRACE_PEEKDATA: | 47 | case PTRACE_PEEKDATA: |
56 | ret = generic_ptrace_peekdata(child, addr, data); | 48 | ret = generic_ptrace_peekdata(child, addr, data); |
57 | break; | 49 | break; |
58 | 50 | ||
59 | /* read the word at location addr in the USER area. */ | 51 | /* read the word at location addr in the USER area. */ |
60 | case PTRACE_PEEKUSR: | 52 | case PTRACE_PEEKUSR: |
61 | ret = peek_user(child, addr, data); | 53 | ret = peek_user(child, addr, data); |
62 | break; | 54 | break; |
63 | 55 | ||
64 | /* when I and D space are separate, this will have to be fixed. */ | 56 | /* write the word at location addr. */ |
65 | case PTRACE_POKETEXT: /* write the word at location addr. */ | 57 | case PTRACE_POKETEXT: |
66 | case PTRACE_POKEDATA: | 58 | case PTRACE_POKEDATA: |
67 | ret = generic_ptrace_pokedata(child, addr, data); | 59 | ret = generic_ptrace_pokedata(child, addr, data); |
68 | break; | 60 | break; |
69 | 61 | ||
70 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ | 62 | /* write the word at location addr in the USER area */ |
71 | ret = poke_user(child, addr, data); | 63 | case PTRACE_POKEUSR: |
72 | break; | 64 | ret = poke_user(child, addr, data); |
65 | break; | ||
73 | 66 | ||
74 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ | 67 | /* continue and stop at next (return from) syscall */ |
75 | case PTRACE_CONT: { /* restart after signal. */ | 68 | case PTRACE_SYSCALL: |
69 | /* restart after signal. */ | ||
70 | case PTRACE_CONT: { | ||
76 | ret = -EIO; | 71 | ret = -EIO; |
77 | if (!valid_signal(data)) | 72 | if (!valid_signal(data)) |
78 | break; | 73 | break; |
79 | 74 | ||
80 | set_singlestepping(child, 0); | 75 | set_singlestepping(child, 0); |
81 | if (request == PTRACE_SYSCALL) { | 76 | if (request == PTRACE_SYSCALL) |
82 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 77 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
83 | } | 78 | else clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
84 | else { | ||
85 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
86 | } | ||
87 | child->exit_code = data; | 79 | child->exit_code = data; |
88 | wake_up_process(child); | 80 | wake_up_process(child); |
89 | ret = 0; | 81 | ret = 0; |
@@ -91,8 +83,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
91 | } | 83 | } |
92 | 84 | ||
93 | /* | 85 | /* |
94 | * make the child exit. Best I can do is send it a sigkill. | 86 | * make the child exit. Best I can do is send it a sigkill. |
95 | * perhaps it should be put in the status that it wants to | 87 | * perhaps it should be put in the status that it wants to |
96 | * exit. | 88 | * exit. |
97 | */ | 89 | */ |
98 | case PTRACE_KILL: { | 90 | case PTRACE_KILL: { |
@@ -100,7 +92,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
100 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | 92 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ |
101 | break; | 93 | break; |
102 | 94 | ||
103 | set_singlestepping(child, 0); | 95 | set_singlestepping(child, 0); |
104 | child->exit_code = SIGKILL; | 96 | child->exit_code = SIGKILL; |
105 | wake_up_process(child); | 97 | wake_up_process(child); |
106 | break; | 98 | break; |
@@ -111,7 +103,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
111 | if (!valid_signal(data)) | 103 | if (!valid_signal(data)) |
112 | break; | 104 | break; |
113 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 105 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
114 | set_singlestepping(child, 1); | 106 | set_singlestepping(child, 1); |
115 | child->exit_code = data; | 107 | child->exit_code = data; |
116 | /* give it a chance to run. */ | 108 | /* give it a chance to run. */ |
117 | wake_up_process(child); | 109 | wake_up_process(child); |
@@ -119,11 +111,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
119 | break; | 111 | break; |
120 | } | 112 | } |
121 | 113 | ||
122 | case PTRACE_DETACH: | ||
123 | /* detach a process that was attached. */ | ||
124 | ret = ptrace_detach(child, data); | ||
125 | break; | ||
126 | |||
127 | #ifdef PTRACE_GETREGS | 114 | #ifdef PTRACE_GETREGS |
128 | case PTRACE_GETREGS: { /* Get all gp regs from the child. */ | 115 | case PTRACE_GETREGS: { /* Get all gp regs from the child. */ |
129 | if (!access_ok(VERIFY_WRITE, p, MAX_REG_OFFSET)) { | 116 | if (!access_ok(VERIFY_WRITE, p, MAX_REG_OFFSET)) { |
@@ -156,22 +143,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
156 | #endif | 143 | #endif |
157 | #ifdef PTRACE_GETFPREGS | 144 | #ifdef PTRACE_GETFPREGS |
158 | case PTRACE_GETFPREGS: /* Get the child FPU state. */ | 145 | case PTRACE_GETFPREGS: /* Get the child FPU state. */ |
159 | ret = get_fpregs(data, child); | 146 | ret = get_fpregs((struct user_i387_struct __user *) data, |
147 | child); | ||
160 | break; | 148 | break; |
161 | #endif | 149 | #endif |
162 | #ifdef PTRACE_SETFPREGS | 150 | #ifdef PTRACE_SETFPREGS |
163 | case PTRACE_SETFPREGS: /* Set the child FPU state. */ | 151 | case PTRACE_SETFPREGS: /* Set the child FPU state. */ |
164 | ret = set_fpregs(data, child); | 152 | ret = set_fpregs((struct user_i387_struct __user *) data, |
165 | break; | 153 | child); |
166 | #endif | ||
167 | #ifdef PTRACE_GETFPXREGS | ||
168 | case PTRACE_GETFPXREGS: /* Get the child FPU state. */ | ||
169 | ret = get_fpxregs(data, child); | ||
170 | break; | ||
171 | #endif | ||
172 | #ifdef PTRACE_SETFPXREGS | ||
173 | case PTRACE_SETFPXREGS: /* Set the child FPU state. */ | ||
174 | ret = set_fpxregs(data, child); | ||
175 | break; | 154 | break; |
176 | #endif | 155 | #endif |
177 | case PTRACE_GET_THREAD_AREA: | 156 | case PTRACE_GET_THREAD_AREA: |
@@ -185,14 +164,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
185 | break; | 164 | break; |
186 | 165 | ||
187 | case PTRACE_FAULTINFO: { | 166 | case PTRACE_FAULTINFO: { |
188 | /* Take the info from thread->arch->faultinfo, | 167 | /* |
168 | * Take the info from thread->arch->faultinfo, | ||
189 | * but transfer max. sizeof(struct ptrace_faultinfo). | 169 | * but transfer max. sizeof(struct ptrace_faultinfo). |
190 | * On i386, ptrace_faultinfo is smaller! | 170 | * On i386, ptrace_faultinfo is smaller! |
191 | */ | 171 | */ |
192 | ret = copy_to_user(p, &child->thread.arch.faultinfo, | 172 | ret = copy_to_user(p, &child->thread.arch.faultinfo, |
193 | sizeof(struct ptrace_faultinfo)); | 173 | sizeof(struct ptrace_faultinfo)); |
194 | if(ret) | ||
195 | break; | ||
196 | break; | 174 | break; |
197 | } | 175 | } |
198 | 176 | ||
@@ -200,12 +178,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
200 | case PTRACE_LDT: { | 178 | case PTRACE_LDT: { |
201 | struct ptrace_ldt ldt; | 179 | struct ptrace_ldt ldt; |
202 | 180 | ||
203 | if(copy_from_user(&ldt, p, sizeof(ldt))){ | 181 | if (copy_from_user(&ldt, p, sizeof(ldt))) { |
204 | ret = -EIO; | 182 | ret = -EIO; |
205 | break; | 183 | break; |
206 | } | 184 | } |
207 | 185 | ||
208 | /* This one is confusing, so just punt and return -EIO for | 186 | /* |
187 | * This one is confusing, so just punt and return -EIO for | ||
209 | * now | 188 | * now |
210 | */ | 189 | */ |
211 | ret = -EIO; | 190 | ret = -EIO; |
@@ -217,7 +196,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
217 | struct mm_struct *old = child->mm; | 196 | struct mm_struct *old = child->mm; |
218 | struct mm_struct *new = proc_mm_get_mm(data); | 197 | struct mm_struct *new = proc_mm_get_mm(data); |
219 | 198 | ||
220 | if(IS_ERR(new)){ | 199 | if (IS_ERR(new)) { |
221 | ret = PTR_ERR(new); | 200 | ret = PTR_ERR(new); |
222 | break; | 201 | break; |
223 | } | 202 | } |
@@ -231,20 +210,22 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
231 | } | 210 | } |
232 | #endif | 211 | #endif |
233 | #ifdef PTRACE_ARCH_PRCTL | 212 | #ifdef PTRACE_ARCH_PRCTL |
234 | case PTRACE_ARCH_PRCTL: | 213 | case PTRACE_ARCH_PRCTL: |
235 | /* XXX Calls ptrace on the host - needs some SMP thinking */ | 214 | /* XXX Calls ptrace on the host - needs some SMP thinking */ |
236 | ret = arch_prctl_skas(child, data, (void *) addr); | 215 | ret = arch_prctl(child, data, (void *) addr); |
237 | break; | 216 | break; |
238 | #endif | 217 | #endif |
239 | default: | 218 | default: |
240 | ret = ptrace_request(child, request, addr, data); | 219 | ret = ptrace_request(child, request, addr, data); |
220 | if (ret == -EIO) | ||
221 | ret = subarch_ptrace(child, request, addr, data); | ||
241 | break; | 222 | break; |
242 | } | 223 | } |
243 | 224 | ||
244 | return ret; | 225 | return ret; |
245 | } | 226 | } |
246 | 227 | ||
247 | void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs, | 228 | void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs, |
248 | int error_code) | 229 | int error_code) |
249 | { | 230 | { |
250 | struct siginfo info; | 231 | struct siginfo info; |
@@ -260,10 +241,11 @@ void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs, | |||
260 | force_sig_info(SIGTRAP, &info, tsk); | 241 | force_sig_info(SIGTRAP, &info, tsk); |
261 | } | 242 | } |
262 | 243 | ||
263 | /* XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and | 244 | /* |
245 | * XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and | ||
264 | * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check | 246 | * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check |
265 | */ | 247 | */ |
266 | void syscall_trace(union uml_pt_regs *regs, int entryexit) | 248 | void syscall_trace(struct uml_pt_regs *regs, int entryexit) |
267 | { | 249 | { |
268 | int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit; | 250 | int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit; |
269 | int tracesysgood; | 251 | int tracesysgood; |
@@ -277,7 +259,7 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit) | |||
277 | UPT_SYSCALL_ARG3(regs), | 259 | UPT_SYSCALL_ARG3(regs), |
278 | UPT_SYSCALL_ARG4(regs)); | 260 | UPT_SYSCALL_ARG4(regs)); |
279 | else audit_syscall_exit(AUDITSC_RESULT(UPT_SYSCALL_RET(regs)), | 261 | else audit_syscall_exit(AUDITSC_RESULT(UPT_SYSCALL_RET(regs)), |
280 | UPT_SYSCALL_RET(regs)); | 262 | UPT_SYSCALL_RET(regs)); |
281 | } | 263 | } |
282 | 264 | ||
283 | /* Fake a debug trap */ | 265 | /* Fake a debug trap */ |
@@ -290,15 +272,18 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit) | |||
290 | if (!(current->ptrace & PT_PTRACED)) | 272 | if (!(current->ptrace & PT_PTRACED)) |
291 | return; | 273 | return; |
292 | 274 | ||
293 | /* the 0x80 provides a way for the tracing parent to distinguish | 275 | /* |
294 | between a syscall stop and SIGTRAP delivery */ | 276 | * the 0x80 provides a way for the tracing parent to distinguish |
277 | * between a syscall stop and SIGTRAP delivery | ||
278 | */ | ||
295 | tracesysgood = (current->ptrace & PT_TRACESYSGOOD); | 279 | tracesysgood = (current->ptrace & PT_TRACESYSGOOD); |
296 | ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0)); | 280 | ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0)); |
297 | 281 | ||
298 | if (entryexit) /* force do_signal() --> is_syscall() */ | 282 | if (entryexit) /* force do_signal() --> is_syscall() */ |
299 | set_thread_flag(TIF_SIGPENDING); | 283 | set_thread_flag(TIF_SIGPENDING); |
300 | 284 | ||
301 | /* this isn't the same as continuing with a signal, but it will do | 285 | /* |
286 | * this isn't the same as continuing with a signal, but it will do | ||
302 | * for normal use. strace only continues with a signal if the | 287 | * for normal use. strace only continues with a signal if the |
303 | * stopping signal is not SIGTRAP. -brl | 288 | * stopping signal is not SIGTRAP. -brl |
304 | */ | 289 | */ |
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index 7e4305a1fd3c..04cebcf0679f 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c | |||
@@ -1,60 +1,53 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/module.h" | ||
7 | #include "linux/sched.h" | 6 | #include "linux/sched.h" |
8 | #include "asm/smp.h" | ||
9 | #include "kern_util.h" | ||
10 | #include "kern.h" | ||
11 | #include "os.h" | 7 | #include "os.h" |
12 | #include "mode.h" | 8 | #include "skas.h" |
13 | #include "choose-mode.h" | ||
14 | 9 | ||
15 | void (*pm_power_off)(void); | 10 | void (*pm_power_off)(void); |
16 | 11 | ||
17 | #ifdef CONFIG_SMP | ||
18 | static void kill_idlers(int me) | ||
19 | { | ||
20 | #ifdef CONFIG_MODE_TT | ||
21 | struct task_struct *p; | ||
22 | int i; | ||
23 | |||
24 | for(i = 0; i < ARRAY_SIZE(idle_threads); i++){ | ||
25 | p = idle_threads[i]; | ||
26 | if((p != NULL) && (p->thread.mode.tt.extern_pid != me)) | ||
27 | os_kill_process(p->thread.mode.tt.extern_pid, 0); | ||
28 | } | ||
29 | #endif | ||
30 | } | ||
31 | #endif | ||
32 | |||
33 | static void kill_off_processes(void) | 12 | static void kill_off_processes(void) |
34 | { | 13 | { |
35 | CHOOSE_MODE(kill_off_processes_tt(), kill_off_processes_skas()); | 14 | if(proc_mm) |
36 | #ifdef CONFIG_SMP | 15 | /* |
37 | kill_idlers(os_getpid()); | 16 | * FIXME: need to loop over userspace_pids |
38 | #endif | 17 | */ |
18 | os_kill_ptraced_process(userspace_pid[0], 1); | ||
19 | else { | ||
20 | struct task_struct *p; | ||
21 | int pid, me; | ||
22 | |||
23 | me = os_getpid(); | ||
24 | for_each_process(p){ | ||
25 | if(p->mm == NULL) | ||
26 | continue; | ||
27 | |||
28 | pid = p->mm->context.id.u.pid; | ||
29 | os_kill_ptraced_process(pid, 1); | ||
30 | } | ||
31 | } | ||
39 | } | 32 | } |
40 | 33 | ||
41 | void uml_cleanup(void) | 34 | void uml_cleanup(void) |
42 | { | 35 | { |
43 | kmalloc_ok = 0; | 36 | kmalloc_ok = 0; |
44 | do_uml_exitcalls(); | 37 | do_uml_exitcalls(); |
45 | kill_off_processes(); | 38 | kill_off_processes(); |
46 | } | 39 | } |
47 | 40 | ||
48 | void machine_restart(char * __unused) | 41 | void machine_restart(char * __unused) |
49 | { | 42 | { |
50 | uml_cleanup(); | 43 | uml_cleanup(); |
51 | CHOOSE_MODE(reboot_tt(), reboot_skas()); | 44 | reboot_skas(); |
52 | } | 45 | } |
53 | 46 | ||
54 | void machine_power_off(void) | 47 | void machine_power_off(void) |
55 | { | 48 | { |
56 | uml_cleanup(); | 49 | uml_cleanup(); |
57 | CHOOSE_MODE(halt_tt(), halt_skas()); | 50 | halt_skas(); |
58 | } | 51 | } |
59 | 52 | ||
60 | void machine_halt(void) | 53 | void machine_halt(void) |
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c index c4020c3d7857..19cb97733937 100644 --- a/arch/um/kernel/signal.c +++ b/arch/um/kernel/signal.c | |||
@@ -1,29 +1,17 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/stddef.h" | ||
7 | #include "linux/sys.h" | ||
8 | #include "linux/sched.h" | ||
9 | #include "linux/wait.h" | ||
10 | #include "linux/kernel.h" | ||
11 | #include "linux/smp_lock.h" | ||
12 | #include "linux/module.h" | 6 | #include "linux/module.h" |
13 | #include "linux/slab.h" | ||
14 | #include "linux/tty.h" | ||
15 | #include "linux/binfmts.h" | ||
16 | #include "linux/ptrace.h" | 7 | #include "linux/ptrace.h" |
8 | #include "linux/sched.h" | ||
9 | #include "asm/siginfo.h" | ||
17 | #include "asm/signal.h" | 10 | #include "asm/signal.h" |
18 | #include "asm/uaccess.h" | ||
19 | #include "asm/unistd.h" | 11 | #include "asm/unistd.h" |
20 | #include "asm/ucontext.h" | ||
21 | #include "kern_util.h" | ||
22 | #include "signal_kern.h" | ||
23 | #include "kern.h" | ||
24 | #include "frame_kern.h" | 12 | #include "frame_kern.h" |
13 | #include "kern_util.h" | ||
25 | #include "sigcontext.h" | 14 | #include "sigcontext.h" |
26 | #include "mode.h" | ||
27 | 15 | ||
28 | EXPORT_SYMBOL(block_signals); | 16 | EXPORT_SYMBOL(block_signals); |
29 | EXPORT_SYMBOL(unblock_signals); | 17 | EXPORT_SYMBOL(unblock_signals); |
@@ -46,9 +34,9 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr, | |||
46 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 34 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
47 | 35 | ||
48 | /* Did we come from a system call? */ | 36 | /* Did we come from a system call? */ |
49 | if(PT_REGS_SYSCALL_NR(regs) >= 0){ | 37 | if (PT_REGS_SYSCALL_NR(regs) >= 0) { |
50 | /* If so, check system call restarting.. */ | 38 | /* If so, check system call restarting.. */ |
51 | switch(PT_REGS_SYSCALL_RET(regs)){ | 39 | switch(PT_REGS_SYSCALL_RET(regs)) { |
52 | case -ERESTART_RESTARTBLOCK: | 40 | case -ERESTART_RESTARTBLOCK: |
53 | case -ERESTARTNOHAND: | 41 | case -ERESTARTNOHAND: |
54 | PT_REGS_SYSCALL_RET(regs) = -EINTR; | 42 | PT_REGS_SYSCALL_RET(regs) = -EINTR; |
@@ -68,17 +56,17 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr, | |||
68 | } | 56 | } |
69 | 57 | ||
70 | sp = PT_REGS_SP(regs); | 58 | sp = PT_REGS_SP(regs); |
71 | if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) | 59 | if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) |
72 | sp = current->sas_ss_sp + current->sas_ss_size; | 60 | sp = current->sas_ss_sp + current->sas_ss_size; |
73 | 61 | ||
74 | #ifdef CONFIG_ARCH_HAS_SC_SIGNALS | 62 | #ifdef CONFIG_ARCH_HAS_SC_SIGNALS |
75 | if(!(ka->sa.sa_flags & SA_SIGINFO)) | 63 | if (!(ka->sa.sa_flags & SA_SIGINFO)) |
76 | err = setup_signal_stack_sc(sp, signr, ka, regs, oldset); | 64 | err = setup_signal_stack_sc(sp, signr, ka, regs, oldset); |
77 | else | 65 | else |
78 | #endif | 66 | #endif |
79 | err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset); | 67 | err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset); |
80 | 68 | ||
81 | if(err){ | 69 | if (err) { |
82 | spin_lock_irq(¤t->sighand->siglock); | 70 | spin_lock_irq(¤t->sighand->siglock); |
83 | current->blocked = *oldset; | 71 | current->blocked = *oldset; |
84 | recalc_sigpending(); | 72 | recalc_sigpending(); |
@@ -88,7 +76,7 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr, | |||
88 | spin_lock_irq(¤t->sighand->siglock); | 76 | spin_lock_irq(¤t->sighand->siglock); |
89 | sigorsets(¤t->blocked, ¤t->blocked, | 77 | sigorsets(¤t->blocked, ¤t->blocked, |
90 | &ka->sa.sa_mask); | 78 | &ka->sa.sa_mask); |
91 | if(!(ka->sa.sa_flags & SA_NODEFER)) | 79 | if (!(ka->sa.sa_flags & SA_NODEFER)) |
92 | sigaddset(¤t->blocked, signr); | 80 | sigaddset(¤t->blocked, signr); |
93 | recalc_sigpending(); | 81 | recalc_sigpending(); |
94 | spin_unlock_irq(¤t->sighand->siglock); | 82 | spin_unlock_irq(¤t->sighand->siglock); |
@@ -109,14 +97,16 @@ static int kern_do_signal(struct pt_regs *regs) | |||
109 | else | 97 | else |
110 | oldset = ¤t->blocked; | 98 | oldset = ¤t->blocked; |
111 | 99 | ||
112 | while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){ | 100 | while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) { |
113 | handled_sig = 1; | 101 | handled_sig = 1; |
114 | /* Whee! Actually deliver the signal. */ | 102 | /* Whee! Actually deliver the signal. */ |
115 | if(!handle_signal(regs, sig, &ka_copy, &info, oldset)){ | 103 | if (!handle_signal(regs, sig, &ka_copy, &info, oldset)) { |
116 | /* a signal was successfully delivered; the saved | 104 | /* |
105 | * a signal was successfully delivered; the saved | ||
117 | * sigmask will have been stored in the signal frame, | 106 | * sigmask will have been stored in the signal frame, |
118 | * and will be restored by sigreturn, so we can simply | 107 | * and will be restored by sigreturn, so we can simply |
119 | * clear the TIF_RESTORE_SIGMASK flag */ | 108 | * clear the TIF_RESTORE_SIGMASK flag |
109 | */ | ||
120 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | 110 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
121 | clear_thread_flag(TIF_RESTORE_SIGMASK); | 111 | clear_thread_flag(TIF_RESTORE_SIGMASK); |
122 | break; | 112 | break; |
@@ -124,9 +114,9 @@ static int kern_do_signal(struct pt_regs *regs) | |||
124 | } | 114 | } |
125 | 115 | ||
126 | /* Did we come from a system call? */ | 116 | /* Did we come from a system call? */ |
127 | if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){ | 117 | if (!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)) { |
128 | /* Restart the system call - no handlers present */ | 118 | /* Restart the system call - no handlers present */ |
129 | switch(PT_REGS_SYSCALL_RET(regs)){ | 119 | switch(PT_REGS_SYSCALL_RET(regs)) { |
130 | case -ERESTARTNOHAND: | 120 | case -ERESTARTNOHAND: |
131 | case -ERESTARTSYS: | 121 | case -ERESTARTSYS: |
132 | case -ERESTARTNOINTR: | 122 | case -ERESTARTNOINTR: |
@@ -137,22 +127,25 @@ static int kern_do_signal(struct pt_regs *regs) | |||
137 | PT_REGS_ORIG_SYSCALL(regs) = __NR_restart_syscall; | 127 | PT_REGS_ORIG_SYSCALL(regs) = __NR_restart_syscall; |
138 | PT_REGS_RESTART_SYSCALL(regs); | 128 | PT_REGS_RESTART_SYSCALL(regs); |
139 | break; | 129 | break; |
140 | } | 130 | } |
141 | } | 131 | } |
142 | 132 | ||
143 | /* This closes a way to execute a system call on the host. If | 133 | /* |
134 | * This closes a way to execute a system call on the host. If | ||
144 | * you set a breakpoint on a system call instruction and singlestep | 135 | * you set a breakpoint on a system call instruction and singlestep |
145 | * from it, the tracing thread used to PTRACE_SINGLESTEP the process | 136 | * from it, the tracing thread used to PTRACE_SINGLESTEP the process |
146 | * rather than PTRACE_SYSCALL it, allowing the system call to execute | 137 | * rather than PTRACE_SYSCALL it, allowing the system call to execute |
147 | * on the host. The tracing thread will check this flag and | 138 | * on the host. The tracing thread will check this flag and |
148 | * PTRACE_SYSCALL if necessary. | 139 | * PTRACE_SYSCALL if necessary. |
149 | */ | 140 | */ |
150 | if(current->ptrace & PT_DTRACE) | 141 | if (current->ptrace & PT_DTRACE) |
151 | current->thread.singlestep_syscall = | 142 | current->thread.singlestep_syscall = |
152 | is_syscall(PT_REGS_IP(¤t->thread.regs)); | 143 | is_syscall(PT_REGS_IP(¤t->thread.regs)); |
153 | 144 | ||
154 | /* if there's no signal to deliver, we just put the saved sigmask | 145 | /* |
155 | * back */ | 146 | * if there's no signal to deliver, we just put the saved sigmask |
147 | * back | ||
148 | */ | ||
156 | if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) { | 149 | if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) { |
157 | clear_thread_flag(TIF_RESTORE_SIGMASK); | 150 | clear_thread_flag(TIF_RESTORE_SIGMASK); |
158 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | 151 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); |
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile index 3e3fa7e7e3cf..0b76d8869c94 100644 --- a/arch/um/kernel/skas/Makefile +++ b/arch/um/kernel/skas/Makefile | |||
@@ -1,9 +1,9 @@ | |||
1 | # | 1 | # |
2 | # Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com) | 2 | # Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | # Licensed under the GPL | 3 | # Licensed under the GPL |
4 | # | 4 | # |
5 | 5 | ||
6 | obj-y := clone.o exec.o mem.o mmu.o process.o syscall.o tlb.o uaccess.o | 6 | obj-y := clone.o mmu.o process.o syscall.o uaccess.o |
7 | 7 | ||
8 | # clone.o is in the stub, so it can't be built with profiling | 8 | # clone.o is in the stub, so it can't be built with profiling |
9 | # GCC hardened also auto-enables -fpic, but we need %ebx so it can't work -> | 9 | # GCC hardened also auto-enables -fpic, but we need %ebx so it can't work -> |
diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c index 47b812b3bca8..d119f4f7d897 100644 --- a/arch/um/kernel/skas/clone.c +++ b/arch/um/kernel/skas/clone.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <sys/time.h> | 4 | #include <sys/time.h> |
5 | #include <asm/unistd.h> | 5 | #include <asm/unistd.h> |
6 | #include <asm/page.h> | 6 | #include <asm/page.h> |
7 | #include "as-layout.h" | ||
7 | #include "ptrace_user.h" | 8 | #include "ptrace_user.h" |
8 | #include "skas.h" | 9 | #include "skas.h" |
9 | #include "stub-data.h" | 10 | #include "stub-data.h" |
@@ -21,12 +22,11 @@ | |||
21 | void __attribute__ ((__section__ (".__syscall_stub"))) | 22 | void __attribute__ ((__section__ (".__syscall_stub"))) |
22 | stub_clone_handler(void) | 23 | stub_clone_handler(void) |
23 | { | 24 | { |
24 | struct stub_data *data = (struct stub_data *) UML_CONFIG_STUB_DATA; | 25 | struct stub_data *data = (struct stub_data *) STUB_DATA; |
25 | long err; | 26 | long err; |
26 | 27 | ||
27 | err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD, | 28 | err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD, |
28 | UML_CONFIG_STUB_DATA + UM_KERN_PAGE_SIZE / 2 - | 29 | STUB_DATA + UM_KERN_PAGE_SIZE / 2 - sizeof(void *)); |
29 | sizeof(void *)); | ||
30 | if(err != 0) | 30 | if(err != 0) |
31 | goto out; | 31 | goto out; |
32 | 32 | ||
diff --git a/arch/um/kernel/skas/exec.c b/arch/um/kernel/skas/exec.c deleted file mode 100644 index 580eb6468949..000000000000 --- a/arch/um/kernel/skas/exec.c +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/kernel.h" | ||
7 | #include "asm/current.h" | ||
8 | #include "asm/page.h" | ||
9 | #include "asm/signal.h" | ||
10 | #include "asm/ptrace.h" | ||
11 | #include "asm/uaccess.h" | ||
12 | #include "asm/mmu_context.h" | ||
13 | #include "tlb.h" | ||
14 | #include "skas.h" | ||
15 | #include "um_mmu.h" | ||
16 | #include "os.h" | ||
17 | |||
18 | void flush_thread_skas(void) | ||
19 | { | ||
20 | void *data = NULL; | ||
21 | unsigned long end = proc_mm ? task_size : CONFIG_STUB_START; | ||
22 | int ret; | ||
23 | |||
24 | ret = unmap(¤t->mm->context.skas.id, 0, end, 1, &data); | ||
25 | if(ret){ | ||
26 | printk("flush_thread_skas - clearing address space failed, " | ||
27 | "err = %d\n", ret); | ||
28 | force_sig(SIGKILL, current); | ||
29 | } | ||
30 | |||
31 | switch_mm_skas(¤t->mm->context.skas.id); | ||
32 | } | ||
33 | |||
34 | void start_thread_skas(struct pt_regs *regs, unsigned long eip, | ||
35 | unsigned long esp) | ||
36 | { | ||
37 | set_fs(USER_DS); | ||
38 | PT_REGS_IP(regs) = eip; | ||
39 | PT_REGS_SP(regs) = esp; | ||
40 | } | ||
diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c deleted file mode 100644 index 7c18dfcd7d8e..000000000000 --- a/arch/um/kernel/skas/mem.c +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/mm.h" | ||
7 | #include "asm/pgtable.h" | ||
8 | #include "mem_user.h" | ||
9 | #include "skas.h" | ||
10 | |||
11 | unsigned long set_task_sizes_skas(unsigned long *task_size_out) | ||
12 | { | ||
13 | /* Round up to the nearest 4M */ | ||
14 | unsigned long host_task_size = ROUND_4M((unsigned long) | ||
15 | &host_task_size); | ||
16 | |||
17 | if (!skas_needs_stub) | ||
18 | *task_size_out = host_task_size; | ||
19 | else *task_size_out = CONFIG_STUB_START & PGDIR_MASK; | ||
20 | |||
21 | return host_task_size; | ||
22 | } | ||
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 2c6d090a2e87..f859ec306cd5 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c | |||
@@ -1,20 +1,13 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/sched.h" | ||
7 | #include "linux/list.h" | ||
8 | #include "linux/spinlock.h" | ||
9 | #include "linux/slab.h" | ||
10 | #include "linux/errno.h" | ||
11 | #include "linux/mm.h" | 6 | #include "linux/mm.h" |
12 | #include "asm/current.h" | 7 | #include "linux/sched.h" |
13 | #include "asm/segment.h" | ||
14 | #include "asm/mmu.h" | ||
15 | #include "asm/pgalloc.h" | 8 | #include "asm/pgalloc.h" |
16 | #include "asm/pgtable.h" | 9 | #include "asm/pgtable.h" |
17 | #include "asm/ldt.h" | 10 | #include "as-layout.h" |
18 | #include "os.h" | 11 | #include "os.h" |
19 | #include "skas.h" | 12 | #include "skas.h" |
20 | 13 | ||
@@ -41,10 +34,11 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc, | |||
41 | if (!pte) | 34 | if (!pte) |
42 | goto out_pte; | 35 | goto out_pte; |
43 | 36 | ||
44 | /* There's an interaction between the skas0 stub pages, stack | 37 | /* |
38 | * There's an interaction between the skas0 stub pages, stack | ||
45 | * randomization, and the BUG at the end of exit_mmap. exit_mmap | 39 | * randomization, and the BUG at the end of exit_mmap. exit_mmap |
46 | * checks that the number of page tables freed is the same as had | 40 | * checks that the number of page tables freed is the same as had |
47 | * been allocated. If the stack is on the last page table page, | 41 | * been allocated. If the stack is on the last page table page, |
48 | * then the stack pte page will be freed, and if not, it won't. To | 42 | * then the stack pte page will be freed, and if not, it won't. To |
49 | * avoid having to know where the stack is, or if the process mapped | 43 | * avoid having to know where the stack is, or if the process mapped |
50 | * something at the top of its address space for some other reason, | 44 | * something at the top of its address space for some other reason, |
@@ -54,76 +48,77 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc, | |||
54 | * destroy_context_skas. | 48 | * destroy_context_skas. |
55 | */ | 49 | */ |
56 | 50 | ||
57 | mm->context.skas.last_page_table = pmd_page_vaddr(*pmd); | 51 | mm->context.last_page_table = pmd_page_vaddr(*pmd); |
58 | #ifdef CONFIG_3_LEVEL_PGTABLES | 52 | #ifdef CONFIG_3_LEVEL_PGTABLES |
59 | mm->context.skas.last_pmd = (unsigned long) __va(pud_val(*pud)); | 53 | mm->context.last_pmd = (unsigned long) __va(pud_val(*pud)); |
60 | #endif | 54 | #endif |
61 | 55 | ||
62 | *pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT)); | 56 | *pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT)); |
63 | *pte = pte_mkread(*pte); | 57 | *pte = pte_mkread(*pte); |
64 | return(0); | 58 | return 0; |
65 | 59 | ||
66 | out_pmd: | 60 | out_pmd: |
67 | pud_free(pud); | 61 | pud_free(pud); |
68 | out_pte: | 62 | out_pte: |
69 | pmd_free(pmd); | 63 | pmd_free(pmd); |
70 | out: | 64 | out: |
71 | return(-ENOMEM); | 65 | return -ENOMEM; |
72 | } | 66 | } |
73 | 67 | ||
74 | int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) | 68 | int init_new_context(struct task_struct *task, struct mm_struct *mm) |
75 | { | 69 | { |
76 | struct mmu_context_skas *from_mm = NULL; | 70 | struct mm_context *from_mm = NULL; |
77 | struct mmu_context_skas *to_mm = &mm->context.skas; | 71 | struct mm_context *to_mm = &mm->context; |
78 | unsigned long stack = 0; | 72 | unsigned long stack = 0; |
79 | int ret = -ENOMEM; | 73 | int ret = -ENOMEM; |
80 | 74 | ||
81 | if(skas_needs_stub){ | 75 | if (skas_needs_stub) { |
82 | stack = get_zeroed_page(GFP_KERNEL); | 76 | stack = get_zeroed_page(GFP_KERNEL); |
83 | if(stack == 0) | 77 | if (stack == 0) |
84 | goto out; | 78 | goto out; |
85 | 79 | ||
86 | /* This zeros the entry that pgd_alloc didn't, needed since | 80 | /* |
81 | * This zeros the entry that pgd_alloc didn't, needed since | ||
87 | * we are about to reinitialize it, and want mm.nr_ptes to | 82 | * we are about to reinitialize it, and want mm.nr_ptes to |
88 | * be accurate. | 83 | * be accurate. |
89 | */ | 84 | */ |
90 | mm->pgd[USER_PTRS_PER_PGD] = __pgd(0); | 85 | mm->pgd[USER_PTRS_PER_PGD] = __pgd(0); |
91 | 86 | ||
92 | ret = init_stub_pte(mm, CONFIG_STUB_CODE, | 87 | ret = init_stub_pte(mm, STUB_CODE, |
93 | (unsigned long) &__syscall_stub_start); | 88 | (unsigned long) &__syscall_stub_start); |
94 | if(ret) | 89 | if (ret) |
95 | goto out_free; | 90 | goto out_free; |
96 | 91 | ||
97 | ret = init_stub_pte(mm, CONFIG_STUB_DATA, stack); | 92 | ret = init_stub_pte(mm, STUB_DATA, stack); |
98 | if(ret) | 93 | if (ret) |
99 | goto out_free; | 94 | goto out_free; |
100 | 95 | ||
101 | mm->nr_ptes--; | 96 | mm->nr_ptes--; |
102 | } | 97 | } |
103 | 98 | ||
104 | to_mm->id.stack = stack; | 99 | to_mm->id.stack = stack; |
105 | if(current->mm != NULL && current->mm != &init_mm) | 100 | if (current->mm != NULL && current->mm != &init_mm) |
106 | from_mm = ¤t->mm->context.skas; | 101 | from_mm = ¤t->mm->context; |
107 | 102 | ||
108 | if(proc_mm){ | 103 | if (proc_mm) { |
109 | ret = new_mm(stack); | 104 | ret = new_mm(stack); |
110 | if(ret < 0){ | 105 | if (ret < 0) { |
111 | printk("init_new_context_skas - new_mm failed, " | 106 | printk(KERN_ERR "init_new_context_skas - " |
112 | "errno = %d\n", ret); | 107 | "new_mm failed, errno = %d\n", ret); |
113 | goto out_free; | 108 | goto out_free; |
114 | } | 109 | } |
115 | to_mm->id.u.mm_fd = ret; | 110 | to_mm->id.u.mm_fd = ret; |
116 | } | 111 | } |
117 | else { | 112 | else { |
118 | if(from_mm) | 113 | if (from_mm) |
119 | to_mm->id.u.pid = copy_context_skas0(stack, | 114 | to_mm->id.u.pid = copy_context_skas0(stack, |
120 | from_mm->id.u.pid); | 115 | from_mm->id.u.pid); |
121 | else to_mm->id.u.pid = start_userspace(stack); | 116 | else to_mm->id.u.pid = start_userspace(stack); |
122 | } | 117 | } |
123 | 118 | ||
124 | ret = init_new_ldt(to_mm, from_mm); | 119 | ret = init_new_ldt(to_mm, from_mm); |
125 | if(ret < 0){ | 120 | if (ret < 0) { |
126 | printk("init_new_context_skas - init_ldt" | 121 | printk(KERN_ERR "init_new_context_skas - init_ldt" |
127 | " failed, errno = %d\n", ret); | 122 | " failed, errno = %d\n", ret); |
128 | goto out_free; | 123 | goto out_free; |
129 | } | 124 | } |
@@ -131,22 +126,22 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) | |||
131 | return 0; | 126 | return 0; |
132 | 127 | ||
133 | out_free: | 128 | out_free: |
134 | if(to_mm->id.stack != 0) | 129 | if (to_mm->id.stack != 0) |
135 | free_page(to_mm->id.stack); | 130 | free_page(to_mm->id.stack); |
136 | out: | 131 | out: |
137 | return ret; | 132 | return ret; |
138 | } | 133 | } |
139 | 134 | ||
140 | void destroy_context_skas(struct mm_struct *mm) | 135 | void destroy_context(struct mm_struct *mm) |
141 | { | 136 | { |
142 | struct mmu_context_skas *mmu = &mm->context.skas; | 137 | struct mm_context *mmu = &mm->context; |
143 | 138 | ||
144 | if(proc_mm) | 139 | if (proc_mm) |
145 | os_close_file(mmu->id.u.mm_fd); | 140 | os_close_file(mmu->id.u.mm_fd); |
146 | else | 141 | else |
147 | os_kill_ptraced_process(mmu->id.u.pid, 1); | 142 | os_kill_ptraced_process(mmu->id.u.pid, 1); |
148 | 143 | ||
149 | if(!proc_mm || !ptrace_faultinfo){ | 144 | if (!proc_mm || !ptrace_faultinfo) { |
150 | free_page(mmu->id.stack); | 145 | free_page(mmu->id.stack); |
151 | pte_lock_deinit(virt_to_page(mmu->last_page_table)); | 146 | pte_lock_deinit(virt_to_page(mmu->last_page_table)); |
152 | pte_free_kernel((pte_t *) mmu->last_page_table); | 147 | pte_free_kernel((pte_t *) mmu->last_page_table); |
@@ -155,4 +150,6 @@ void destroy_context_skas(struct mm_struct *mm) | |||
155 | pmd_free((pmd_t *) mmu->last_pmd); | 150 | pmd_free((pmd_t *) mmu->last_pmd); |
156 | #endif | 151 | #endif |
157 | } | 152 | } |
153 | |||
154 | free_ldt(mmu); | ||
158 | } | 155 | } |
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 48051a98525f..fce389c2342f 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c | |||
@@ -1,146 +1,26 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/sched.h" | ||
7 | #include "linux/slab.h" | ||
8 | #include "linux/ptrace.h" | ||
9 | #include "linux/proc_fs.h" | ||
10 | #include "linux/file.h" | ||
11 | #include "linux/errno.h" | ||
12 | #include "linux/init.h" | 6 | #include "linux/init.h" |
13 | #include "asm/uaccess.h" | 7 | #include "linux/sched.h" |
14 | #include "asm/atomic.h" | ||
15 | #include "kern_util.h" | ||
16 | #include "as-layout.h" | 8 | #include "as-layout.h" |
17 | #include "skas.h" | ||
18 | #include "os.h" | 9 | #include "os.h" |
19 | #include "tlb.h" | 10 | #include "skas.h" |
20 | #include "kern.h" | ||
21 | #include "mode.h" | ||
22 | #include "registers.h" | ||
23 | |||
24 | void switch_to_skas(void *prev, void *next) | ||
25 | { | ||
26 | struct task_struct *from, *to; | ||
27 | |||
28 | from = prev; | ||
29 | to = next; | ||
30 | |||
31 | /* XXX need to check runqueues[cpu].idle */ | ||
32 | if(current->pid == 0) | ||
33 | switch_timers(0); | ||
34 | |||
35 | switch_threads(&from->thread.mode.skas.switch_buf, | ||
36 | &to->thread.mode.skas.switch_buf); | ||
37 | |||
38 | arch_switch_to_skas(current->thread.prev_sched, current); | ||
39 | |||
40 | if(current->pid == 0) | ||
41 | switch_timers(1); | ||
42 | } | ||
43 | |||
44 | extern void schedule_tail(struct task_struct *prev); | ||
45 | |||
46 | /* This is called magically, by its address being stuffed in a jmp_buf | ||
47 | * and being longjmp-d to. | ||
48 | */ | ||
49 | void new_thread_handler(void) | ||
50 | { | ||
51 | int (*fn)(void *), n; | ||
52 | void *arg; | ||
53 | |||
54 | if(current->thread.prev_sched != NULL) | ||
55 | schedule_tail(current->thread.prev_sched); | ||
56 | current->thread.prev_sched = NULL; | ||
57 | |||
58 | fn = current->thread.request.u.thread.proc; | ||
59 | arg = current->thread.request.u.thread.arg; | ||
60 | |||
61 | /* The return value is 1 if the kernel thread execs a process, | ||
62 | * 0 if it just exits | ||
63 | */ | ||
64 | n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); | ||
65 | if(n == 1){ | ||
66 | /* Handle any immediate reschedules or signals */ | ||
67 | interrupt_end(); | ||
68 | userspace(¤t->thread.regs.regs); | ||
69 | } | ||
70 | else do_exit(0); | ||
71 | } | ||
72 | |||
73 | void release_thread_skas(struct task_struct *task) | ||
74 | { | ||
75 | } | ||
76 | |||
77 | /* Called magically, see new_thread_handler above */ | ||
78 | void fork_handler(void) | ||
79 | { | ||
80 | force_flush_all(); | ||
81 | if(current->thread.prev_sched == NULL) | ||
82 | panic("blech"); | ||
83 | |||
84 | schedule_tail(current->thread.prev_sched); | ||
85 | |||
86 | /* XXX: if interrupt_end() calls schedule, this call to | ||
87 | * arch_switch_to_skas isn't needed. We could want to apply this to | ||
88 | * improve performance. -bb */ | ||
89 | arch_switch_to_skas(current->thread.prev_sched, current); | ||
90 | |||
91 | current->thread.prev_sched = NULL; | ||
92 | |||
93 | /* Handle any immediate reschedules or signals */ | ||
94 | interrupt_end(); | ||
95 | |||
96 | userspace(¤t->thread.regs.regs); | ||
97 | } | ||
98 | |||
99 | int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, | ||
100 | unsigned long stack_top, struct task_struct * p, | ||
101 | struct pt_regs *regs) | ||
102 | { | ||
103 | void (*handler)(void); | ||
104 | |||
105 | if(current->thread.forking){ | ||
106 | memcpy(&p->thread.regs.regs.skas, ®s->regs.skas, | ||
107 | sizeof(p->thread.regs.regs.skas)); | ||
108 | REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0); | ||
109 | if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp; | ||
110 | |||
111 | handler = fork_handler; | ||
112 | |||
113 | arch_copy_thread(¤t->thread.arch, &p->thread.arch); | ||
114 | } | ||
115 | else { | ||
116 | init_thread_registers(&p->thread.regs.regs); | ||
117 | p->thread.request.u.thread = current->thread.request.u.thread; | ||
118 | handler = new_thread_handler; | ||
119 | } | ||
120 | |||
121 | new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf, | ||
122 | handler); | ||
123 | return(0); | ||
124 | } | ||
125 | 11 | ||
126 | int new_mm(unsigned long stack) | 12 | int new_mm(unsigned long stack) |
127 | { | 13 | { |
128 | int fd; | 14 | int fd; |
129 | 15 | ||
130 | fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); | 16 | fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); |
131 | if(fd < 0) | 17 | if (fd < 0) |
132 | return(fd); | 18 | return fd; |
133 | 19 | ||
134 | if(skas_needs_stub) | 20 | if (skas_needs_stub) |
135 | map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); | 21 | map_stub_pages(fd, STUB_CODE, STUB_DATA, stack); |
136 | 22 | ||
137 | return(fd); | 23 | return fd; |
138 | } | ||
139 | |||
140 | void init_idle_skas(void) | ||
141 | { | ||
142 | cpu_tasks[current_thread->cpu].pid = os_getpid(); | ||
143 | default_idle(); | ||
144 | } | 24 | } |
145 | 25 | ||
146 | extern void start_kernel(void); | 26 | extern void start_kernel(void); |
@@ -158,67 +38,32 @@ static int __init start_kernel_proc(void *unused) | |||
158 | cpu_online_map = cpumask_of_cpu(0); | 38 | cpu_online_map = cpumask_of_cpu(0); |
159 | #endif | 39 | #endif |
160 | start_kernel(); | 40 | start_kernel(); |
161 | return(0); | 41 | return 0; |
162 | } | 42 | } |
163 | 43 | ||
164 | extern int userspace_pid[]; | 44 | extern int userspace_pid[]; |
165 | 45 | ||
166 | extern char cpu0_irqstack[]; | 46 | extern char cpu0_irqstack[]; |
167 | 47 | ||
168 | int __init start_uml_skas(void) | 48 | int __init start_uml(void) |
169 | { | 49 | { |
170 | stack_protections((unsigned long) &cpu0_irqstack); | 50 | stack_protections((unsigned long) &cpu0_irqstack); |
171 | set_sigstack(cpu0_irqstack, THREAD_SIZE); | 51 | set_sigstack(cpu0_irqstack, THREAD_SIZE); |
172 | if(proc_mm) | 52 | if (proc_mm) |
173 | userspace_pid[0] = start_userspace(0); | 53 | userspace_pid[0] = start_userspace(0); |
174 | 54 | ||
175 | init_new_thread_signals(); | 55 | init_new_thread_signals(); |
176 | 56 | ||
177 | init_task.thread.request.u.thread.proc = start_kernel_proc; | 57 | init_task.thread.request.u.thread.proc = start_kernel_proc; |
178 | init_task.thread.request.u.thread.arg = NULL; | 58 | init_task.thread.request.u.thread.arg = NULL; |
179 | return(start_idle_thread(task_stack_page(&init_task), | 59 | return start_idle_thread(task_stack_page(&init_task), |
180 | &init_task.thread.mode.skas.switch_buf)); | 60 | &init_task.thread.switch_buf); |
181 | } | ||
182 | |||
183 | int external_pid_skas(struct task_struct *task) | ||
184 | { | ||
185 | /* FIXME: Need to look up userspace_pid by cpu */ | ||
186 | return(userspace_pid[0]); | ||
187 | } | ||
188 | |||
189 | int thread_pid_skas(struct task_struct *task) | ||
190 | { | ||
191 | /* FIXME: Need to look up userspace_pid by cpu */ | ||
192 | return(userspace_pid[0]); | ||
193 | } | ||
194 | |||
195 | void kill_off_processes_skas(void) | ||
196 | { | ||
197 | if(proc_mm) | ||
198 | /* | ||
199 | * FIXME: need to loop over userspace_pids in | ||
200 | * kill_off_processes_skas | ||
201 | */ | ||
202 | os_kill_ptraced_process(userspace_pid[0], 1); | ||
203 | else { | ||
204 | struct task_struct *p; | ||
205 | int pid, me; | ||
206 | |||
207 | me = os_getpid(); | ||
208 | for_each_process(p){ | ||
209 | if(p->mm == NULL) | ||
210 | continue; | ||
211 | |||
212 | pid = p->mm->context.skas.id.u.pid; | ||
213 | os_kill_ptraced_process(pid, 1); | ||
214 | } | ||
215 | } | ||
216 | } | 61 | } |
217 | 62 | ||
218 | unsigned long current_stub_stack(void) | 63 | unsigned long current_stub_stack(void) |
219 | { | 64 | { |
220 | if(current->mm == NULL) | 65 | if (current->mm == NULL) |
221 | return(0); | 66 | return 0; |
222 | 67 | ||
223 | return(current->mm->context.skas.id.stack); | 68 | return current->mm->context.id.stack; |
224 | } | 69 | } |
diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c index 0ae4eea21be4..50b476f2b38d 100644 --- a/arch/um/kernel/skas/syscall.c +++ b/arch/um/kernel/skas/syscall.c | |||
@@ -1,19 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/sys.h" | 6 | #include "linux/kernel.h" |
7 | #include "linux/ptrace.h" | 7 | #include "linux/ptrace.h" |
8 | #include "asm/errno.h" | ||
9 | #include "asm/unistd.h" | ||
10 | #include "asm/ptrace.h" | ||
11 | #include "asm/current.h" | ||
12 | #include "sysdep/syscalls.h" | ||
13 | #include "kern_util.h" | 8 | #include "kern_util.h" |
14 | #include "syscall.h" | 9 | #include "sysdep/ptrace.h" |
10 | #include "sysdep/syscalls.h" | ||
15 | 11 | ||
16 | void handle_syscall(union uml_pt_regs *r) | 12 | void handle_syscall(struct uml_pt_regs *r) |
17 | { | 13 | { |
18 | struct pt_regs *regs = container_of(r, struct pt_regs, regs); | 14 | struct pt_regs *regs = container_of(r, struct pt_regs, regs); |
19 | long result; | 15 | long result; |
@@ -24,7 +20,8 @@ void handle_syscall(union uml_pt_regs *r) | |||
24 | current->thread.nsyscalls++; | 20 | current->thread.nsyscalls++; |
25 | nsyscalls++; | 21 | nsyscalls++; |
26 | 22 | ||
27 | /* This should go in the declaration of syscall, but when I do that, | 23 | /* |
24 | * This should go in the declaration of syscall, but when I do that, | ||
28 | * strace -f -c bash -c 'ls ; ls' breaks, sometimes not tracing | 25 | * strace -f -c bash -c 'ls ; ls' breaks, sometimes not tracing |
29 | * children at all, sometimes hanging when bash doesn't see the first | 26 | * children at all, sometimes hanging when bash doesn't see the first |
30 | * ls exit. | 27 | * ls exit. |
@@ -33,11 +30,11 @@ void handle_syscall(union uml_pt_regs *r) | |||
33 | * in case it's a compiler bug. | 30 | * in case it's a compiler bug. |
34 | */ | 31 | */ |
35 | syscall = UPT_SYSCALL_NR(r); | 32 | syscall = UPT_SYSCALL_NR(r); |
36 | if((syscall >= NR_syscalls) || (syscall < 0)) | 33 | if ((syscall >= NR_syscalls) || (syscall < 0)) |
37 | result = -ENOSYS; | 34 | result = -ENOSYS; |
38 | else result = EXECUTE_SYSCALL(syscall, regs); | 35 | else result = EXECUTE_SYSCALL(syscall, regs); |
39 | 36 | ||
40 | REGS_SET_SYSCALL_RETURN(r->skas.regs, result); | 37 | REGS_SET_SYSCALL_RETURN(r->gp, result); |
41 | 38 | ||
42 | syscall_trace(r, 1); | 39 | syscall_trace(r, 1); |
43 | } | 40 | } |
diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c deleted file mode 100644 index c0f0693743ba..000000000000 --- a/arch/um/kernel/skas/tlb.c +++ /dev/null | |||
@@ -1,164 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Copyright 2003 PathScale, Inc. | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include "linux/stddef.h" | ||
8 | #include "linux/sched.h" | ||
9 | #include "linux/mm.h" | ||
10 | #include "asm/page.h" | ||
11 | #include "asm/pgtable.h" | ||
12 | #include "asm/mmu.h" | ||
13 | #include "mem_user.h" | ||
14 | #include "mem.h" | ||
15 | #include "skas.h" | ||
16 | #include "os.h" | ||
17 | #include "tlb.h" | ||
18 | |||
19 | static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last, | ||
20 | int finished, void **flush) | ||
21 | { | ||
22 | struct host_vm_op *op; | ||
23 | int i, ret = 0; | ||
24 | |||
25 | for(i = 0; i <= last && !ret; i++){ | ||
26 | op = &ops[i]; | ||
27 | switch(op->type){ | ||
28 | case MMAP: | ||
29 | ret = map(&mmu->skas.id, op->u.mmap.addr, | ||
30 | op->u.mmap.len, op->u.mmap.prot, | ||
31 | op->u.mmap.fd, op->u.mmap.offset, finished, | ||
32 | flush); | ||
33 | break; | ||
34 | case MUNMAP: | ||
35 | ret = unmap(&mmu->skas.id, op->u.munmap.addr, | ||
36 | op->u.munmap.len, finished, flush); | ||
37 | break; | ||
38 | case MPROTECT: | ||
39 | ret = protect(&mmu->skas.id, op->u.mprotect.addr, | ||
40 | op->u.mprotect.len, op->u.mprotect.prot, | ||
41 | finished, flush); | ||
42 | break; | ||
43 | default: | ||
44 | printk("Unknown op type %d in do_ops\n", op->type); | ||
45 | break; | ||
46 | } | ||
47 | } | ||
48 | |||
49 | return ret; | ||
50 | } | ||
51 | |||
52 | extern int proc_mm; | ||
53 | |||
54 | static void fix_range(struct mm_struct *mm, unsigned long start_addr, | ||
55 | unsigned long end_addr, int force) | ||
56 | { | ||
57 | if(!proc_mm && (end_addr > CONFIG_STUB_START)) | ||
58 | end_addr = CONFIG_STUB_START; | ||
59 | |||
60 | fix_range_common(mm, start_addr, end_addr, force, do_ops); | ||
61 | } | ||
62 | |||
63 | void __flush_tlb_one_skas(unsigned long addr) | ||
64 | { | ||
65 | flush_tlb_kernel_range_common(addr, addr + PAGE_SIZE); | ||
66 | } | ||
67 | |||
68 | void flush_tlb_range_skas(struct vm_area_struct *vma, unsigned long start, | ||
69 | unsigned long end) | ||
70 | { | ||
71 | if(vma->vm_mm == NULL) | ||
72 | flush_tlb_kernel_range_common(start, end); | ||
73 | else fix_range(vma->vm_mm, start, end, 0); | ||
74 | } | ||
75 | |||
76 | void flush_tlb_mm_skas(struct mm_struct *mm) | ||
77 | { | ||
78 | unsigned long end; | ||
79 | |||
80 | /* Don't bother flushing if this address space is about to be | ||
81 | * destroyed. | ||
82 | */ | ||
83 | if(atomic_read(&mm->mm_users) == 0) | ||
84 | return; | ||
85 | |||
86 | end = proc_mm ? task_size : CONFIG_STUB_START; | ||
87 | fix_range(mm, 0, end, 0); | ||
88 | } | ||
89 | |||
90 | void force_flush_all_skas(void) | ||
91 | { | ||
92 | struct mm_struct *mm = current->mm; | ||
93 | struct vm_area_struct *vma = mm->mmap; | ||
94 | |||
95 | while(vma != NULL) { | ||
96 | fix_range(mm, vma->vm_start, vma->vm_end, 1); | ||
97 | vma = vma->vm_next; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | void flush_tlb_page_skas(struct vm_area_struct *vma, unsigned long address) | ||
102 | { | ||
103 | pgd_t *pgd; | ||
104 | pud_t *pud; | ||
105 | pmd_t *pmd; | ||
106 | pte_t *pte; | ||
107 | struct mm_struct *mm = vma->vm_mm; | ||
108 | void *flush = NULL; | ||
109 | int r, w, x, prot, err = 0; | ||
110 | struct mm_id *mm_id; | ||
111 | |||
112 | pgd = pgd_offset(mm, address); | ||
113 | if(!pgd_present(*pgd)) | ||
114 | goto kill; | ||
115 | |||
116 | pud = pud_offset(pgd, address); | ||
117 | if(!pud_present(*pud)) | ||
118 | goto kill; | ||
119 | |||
120 | pmd = pmd_offset(pud, address); | ||
121 | if(!pmd_present(*pmd)) | ||
122 | goto kill; | ||
123 | |||
124 | pte = pte_offset_kernel(pmd, address); | ||
125 | |||
126 | r = pte_read(*pte); | ||
127 | w = pte_write(*pte); | ||
128 | x = pte_exec(*pte); | ||
129 | if (!pte_young(*pte)) { | ||
130 | r = 0; | ||
131 | w = 0; | ||
132 | } else if (!pte_dirty(*pte)) { | ||
133 | w = 0; | ||
134 | } | ||
135 | |||
136 | mm_id = &mm->context.skas.id; | ||
137 | prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | | ||
138 | (x ? UM_PROT_EXEC : 0)); | ||
139 | if(pte_newpage(*pte)){ | ||
140 | if(pte_present(*pte)){ | ||
141 | unsigned long long offset; | ||
142 | int fd; | ||
143 | |||
144 | fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset); | ||
145 | err = map(mm_id, address, PAGE_SIZE, prot, fd, offset, | ||
146 | 1, &flush); | ||
147 | } | ||
148 | else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush); | ||
149 | } | ||
150 | else if(pte_newprot(*pte)) | ||
151 | err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush); | ||
152 | |||
153 | if(err) | ||
154 | goto kill; | ||
155 | |||
156 | *pte = pte_mkuptodate(*pte); | ||
157 | |||
158 | return; | ||
159 | |||
160 | kill: | ||
161 | printk("Failed to flush page for address 0x%lx\n", address); | ||
162 | force_sig(SIGKILL, current); | ||
163 | } | ||
164 | |||
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index 8912cec0fe43..1d8b119f2d0e 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c | |||
@@ -1,18 +1,14 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/compiler.h" | 6 | #include "linux/err.h" |
7 | #include "linux/stddef.h" | ||
8 | #include "linux/kernel.h" | ||
9 | #include "linux/string.h" | ||
10 | #include "linux/fs.h" | ||
11 | #include "linux/hardirq.h" | ||
12 | #include "linux/highmem.h" | 7 | #include "linux/highmem.h" |
8 | #include "linux/mm.h" | ||
9 | #include "asm/current.h" | ||
13 | #include "asm/page.h" | 10 | #include "asm/page.h" |
14 | #include "asm/pgtable.h" | 11 | #include "asm/pgtable.h" |
15 | #include "asm/uaccess.h" | ||
16 | #include "kern_util.h" | 12 | #include "kern_util.h" |
17 | #include "os.h" | 13 | #include "os.h" |
18 | 14 | ||
@@ -27,16 +23,16 @@ static unsigned long maybe_map(unsigned long virt, int is_write) | |||
27 | void *phys = um_virt_to_phys(current, virt, &pte); | 23 | void *phys = um_virt_to_phys(current, virt, &pte); |
28 | int dummy_code; | 24 | int dummy_code; |
29 | 25 | ||
30 | if(IS_ERR(phys) || (is_write && !pte_write(pte))){ | 26 | if (IS_ERR(phys) || (is_write && !pte_write(pte))) { |
31 | err = handle_page_fault(virt, 0, is_write, 1, &dummy_code); | 27 | err = handle_page_fault(virt, 0, is_write, 1, &dummy_code); |
32 | if(err) | 28 | if (err) |
33 | return(-1UL); | 29 | return -1UL; |
34 | phys = um_virt_to_phys(current, virt, NULL); | 30 | phys = um_virt_to_phys(current, virt, NULL); |
35 | } | 31 | } |
36 | if(IS_ERR(phys)) | 32 | if (IS_ERR(phys)) |
37 | phys = (void *) -1; | 33 | phys = (void *) -1; |
38 | 34 | ||
39 | return((unsigned long) phys); | 35 | return (unsigned long) phys; |
40 | } | 36 | } |
41 | 37 | ||
42 | static int do_op_one_page(unsigned long addr, int len, int is_write, | 38 | static int do_op_one_page(unsigned long addr, int len, int is_write, |
@@ -46,17 +42,18 @@ static int do_op_one_page(unsigned long addr, int len, int is_write, | |||
46 | int n; | 42 | int n; |
47 | 43 | ||
48 | addr = maybe_map(addr, is_write); | 44 | addr = maybe_map(addr, is_write); |
49 | if(addr == -1UL) | 45 | if (addr == -1UL) |
50 | return(-1); | 46 | return -1; |
51 | 47 | ||
52 | page = phys_to_page(addr); | 48 | page = phys_to_page(addr); |
53 | addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) + (addr & ~PAGE_MASK); | 49 | addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) + |
50 | (addr & ~PAGE_MASK); | ||
54 | 51 | ||
55 | n = (*op)(addr, len, arg); | 52 | n = (*op)(addr, len, arg); |
56 | 53 | ||
57 | kunmap_atomic(page, KM_UML_USERCOPY); | 54 | kunmap_atomic(page, KM_UML_USERCOPY); |
58 | 55 | ||
59 | return(n); | 56 | return n; |
60 | } | 57 | } |
61 | 58 | ||
62 | static void do_buffer_op(void *jmpbuf, void *arg_ptr) | 59 | static void do_buffer_op(void *jmpbuf, void *arg_ptr) |
@@ -81,21 +78,21 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr) | |||
81 | 78 | ||
82 | current->thread.fault_catcher = jmpbuf; | 79 | current->thread.fault_catcher = jmpbuf; |
83 | n = do_op_one_page(addr, size, is_write, op, arg); | 80 | n = do_op_one_page(addr, size, is_write, op, arg); |
84 | if(n != 0){ | 81 | if (n != 0) { |
85 | *res = (n < 0 ? remain : 0); | 82 | *res = (n < 0 ? remain : 0); |
86 | goto out; | 83 | goto out; |
87 | } | 84 | } |
88 | 85 | ||
89 | addr += size; | 86 | addr += size; |
90 | remain -= size; | 87 | remain -= size; |
91 | if(remain == 0){ | 88 | if (remain == 0) { |
92 | *res = 0; | 89 | *res = 0; |
93 | goto out; | 90 | goto out; |
94 | } | 91 | } |
95 | 92 | ||
96 | while(addr < ((addr + remain) & PAGE_MASK)){ | 93 | while(addr < ((addr + remain) & PAGE_MASK)) { |
97 | n = do_op_one_page(addr, PAGE_SIZE, is_write, op, arg); | 94 | n = do_op_one_page(addr, PAGE_SIZE, is_write, op, arg); |
98 | if(n != 0){ | 95 | if (n != 0) { |
99 | *res = (n < 0 ? remain : 0); | 96 | *res = (n < 0 ? remain : 0); |
100 | goto out; | 97 | goto out; |
101 | } | 98 | } |
@@ -103,13 +100,13 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr) | |||
103 | addr += PAGE_SIZE; | 100 | addr += PAGE_SIZE; |
104 | remain -= PAGE_SIZE; | 101 | remain -= PAGE_SIZE; |
105 | } | 102 | } |
106 | if(remain == 0){ | 103 | if (remain == 0) { |
107 | *res = 0; | 104 | *res = 0; |
108 | goto out; | 105 | goto out; |
109 | } | 106 | } |
110 | 107 | ||
111 | n = do_op_one_page(addr, remain, is_write, op, arg); | 108 | n = do_op_one_page(addr, remain, is_write, op, arg); |
112 | if(n != 0) | 109 | if (n != 0) |
113 | *res = (n < 0 ? remain : 0); | 110 | *res = (n < 0 ? remain : 0); |
114 | else *res = 0; | 111 | else *res = 0; |
115 | out: | 112 | out: |
@@ -124,10 +121,10 @@ static int buffer_op(unsigned long addr, int len, int is_write, | |||
124 | 121 | ||
125 | faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg, | 122 | faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg, |
126 | &res); | 123 | &res); |
127 | if(!faulted) | 124 | if (!faulted) |
128 | return(res); | 125 | return res; |
129 | 126 | ||
130 | return(addr + len - (unsigned long) current->thread.fault_addr); | 127 | return addr + len - (unsigned long) current->thread.fault_addr; |
131 | } | 128 | } |
132 | 129 | ||
133 | static int copy_chunk_from_user(unsigned long from, int len, void *arg) | 130 | static int copy_chunk_from_user(unsigned long from, int len, void *arg) |
@@ -136,19 +133,19 @@ static int copy_chunk_from_user(unsigned long from, int len, void *arg) | |||
136 | 133 | ||
137 | memcpy((void *) to, (void *) from, len); | 134 | memcpy((void *) to, (void *) from, len); |
138 | *to_ptr += len; | 135 | *to_ptr += len; |
139 | return(0); | 136 | return 0; |
140 | } | 137 | } |
141 | 138 | ||
142 | int copy_from_user_skas(void *to, const void __user *from, int n) | 139 | int copy_from_user(void *to, const void __user *from, int n) |
143 | { | 140 | { |
144 | if(segment_eq(get_fs(), KERNEL_DS)){ | 141 | if (segment_eq(get_fs(), KERNEL_DS)) { |
145 | memcpy(to, (__force void*)from, n); | 142 | memcpy(to, (__force void*)from, n); |
146 | return(0); | 143 | return 0; |
147 | } | 144 | } |
148 | 145 | ||
149 | return(access_ok(VERIFY_READ, from, n) ? | 146 | return access_ok(VERIFY_READ, from, n) ? |
150 | buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): | 147 | buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): |
151 | n); | 148 | n; |
152 | } | 149 | } |
153 | 150 | ||
154 | static int copy_chunk_to_user(unsigned long to, int len, void *arg) | 151 | static int copy_chunk_to_user(unsigned long to, int len, void *arg) |
@@ -157,19 +154,19 @@ static int copy_chunk_to_user(unsigned long to, int len, void *arg) | |||
157 | 154 | ||
158 | memcpy((void *) to, (void *) from, len); | 155 | memcpy((void *) to, (void *) from, len); |
159 | *from_ptr += len; | 156 | *from_ptr += len; |
160 | return(0); | 157 | return 0; |
161 | } | 158 | } |
162 | 159 | ||
163 | int copy_to_user_skas(void __user *to, const void *from, int n) | 160 | int copy_to_user(void __user *to, const void *from, int n) |
164 | { | 161 | { |
165 | if(segment_eq(get_fs(), KERNEL_DS)){ | 162 | if (segment_eq(get_fs(), KERNEL_DS)) { |
166 | memcpy((__force void*)to, from, n); | 163 | memcpy((__force void *) to, from, n); |
167 | return(0); | 164 | return 0; |
168 | } | 165 | } |
169 | 166 | ||
170 | return(access_ok(VERIFY_WRITE, to, n) ? | 167 | return access_ok(VERIFY_WRITE, to, n) ? |
171 | buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : | 168 | buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : |
172 | n); | 169 | n; |
173 | } | 170 | } |
174 | 171 | ||
175 | static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) | 172 | static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) |
@@ -181,51 +178,51 @@ static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) | |||
181 | n = strnlen(to, len); | 178 | n = strnlen(to, len); |
182 | *to_ptr += n; | 179 | *to_ptr += n; |
183 | 180 | ||
184 | if(n < len) | 181 | if (n < len) |
185 | return(1); | 182 | return 1; |
186 | return(0); | 183 | return 0; |
187 | } | 184 | } |
188 | 185 | ||
189 | int strncpy_from_user_skas(char *dst, const char __user *src, int count) | 186 | int strncpy_from_user(char *dst, const char __user *src, int count) |
190 | { | 187 | { |
191 | int n; | 188 | int n; |
192 | char *ptr = dst; | 189 | char *ptr = dst; |
193 | 190 | ||
194 | if(segment_eq(get_fs(), KERNEL_DS)){ | 191 | if (segment_eq(get_fs(), KERNEL_DS)) { |
195 | strncpy(dst, (__force void*)src, count); | 192 | strncpy(dst, (__force void *) src, count); |
196 | return(strnlen(dst, count)); | 193 | return strnlen(dst, count); |
197 | } | 194 | } |
198 | 195 | ||
199 | if(!access_ok(VERIFY_READ, src, 1)) | 196 | if (!access_ok(VERIFY_READ, src, 1)) |
200 | return(-EFAULT); | 197 | return -EFAULT; |
201 | 198 | ||
202 | n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, | 199 | n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, |
203 | &ptr); | 200 | &ptr); |
204 | if(n != 0) | 201 | if (n != 0) |
205 | return(-EFAULT); | 202 | return -EFAULT; |
206 | return(strnlen(dst, count)); | 203 | return strnlen(dst, count); |
207 | } | 204 | } |
208 | 205 | ||
209 | static int clear_chunk(unsigned long addr, int len, void *unused) | 206 | static int clear_chunk(unsigned long addr, int len, void *unused) |
210 | { | 207 | { |
211 | memset((void *) addr, 0, len); | 208 | memset((void *) addr, 0, len); |
212 | return(0); | 209 | return 0; |
213 | } | 210 | } |
214 | 211 | ||
215 | int __clear_user_skas(void __user *mem, int len) | 212 | int __clear_user(void __user *mem, int len) |
216 | { | 213 | { |
217 | return(buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL)); | 214 | return buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL); |
218 | } | 215 | } |
219 | 216 | ||
220 | int clear_user_skas(void __user *mem, int len) | 217 | int clear_user(void __user *mem, int len) |
221 | { | 218 | { |
222 | if(segment_eq(get_fs(), KERNEL_DS)){ | 219 | if (segment_eq(get_fs(), KERNEL_DS)) { |
223 | memset((__force void*)mem, 0, len); | 220 | memset((__force void*)mem, 0, len); |
224 | return(0); | 221 | return 0; |
225 | } | 222 | } |
226 | 223 | ||
227 | return(access_ok(VERIFY_WRITE, mem, len) ? | 224 | return access_ok(VERIFY_WRITE, mem, len) ? |
228 | buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len); | 225 | buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len; |
229 | } | 226 | } |
230 | 227 | ||
231 | static int strnlen_chunk(unsigned long str, int len, void *arg) | 228 | static int strnlen_chunk(unsigned long str, int len, void *arg) |
@@ -235,31 +232,20 @@ static int strnlen_chunk(unsigned long str, int len, void *arg) | |||
235 | n = strnlen((void *) str, len); | 232 | n = strnlen((void *) str, len); |
236 | *len_ptr += n; | 233 | *len_ptr += n; |
237 | 234 | ||
238 | if(n < len) | 235 | if (n < len) |
239 | return(1); | 236 | return 1; |
240 | return(0); | 237 | return 0; |
241 | } | 238 | } |
242 | 239 | ||
243 | int strnlen_user_skas(const void __user *str, int len) | 240 | int strnlen_user(const void __user *str, int len) |
244 | { | 241 | { |
245 | int count = 0, n; | 242 | int count = 0, n; |
246 | 243 | ||
247 | if(segment_eq(get_fs(), KERNEL_DS)) | 244 | if (segment_eq(get_fs(), KERNEL_DS)) |
248 | return(strnlen((__force char*)str, len) + 1); | 245 | return strnlen((__force char*)str, len) + 1; |
249 | 246 | ||
250 | n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count); | 247 | n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count); |
251 | if(n == 0) | 248 | if (n == 0) |
252 | return(count + 1); | 249 | return count + 1; |
253 | return(-EFAULT); | 250 | return -EFAULT; |
254 | } | 251 | } |
255 | |||
256 | /* | ||
257 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
258 | * Emacs will notice this stuff at the end of the file and automatically | ||
259 | * adjust the settings for this buffer only. This must remain at the end | ||
260 | * of the file. | ||
261 | * --------------------------------------------------------------------------- | ||
262 | * Local variables: | ||
263 | * c-file-style: "linux" | ||
264 | * End: | ||
265 | */ | ||
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c index e6a7778006ad..36d89cf8d20b 100644 --- a/arch/um/kernel/smp.c +++ b/arch/um/kernel/smp.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -56,12 +56,12 @@ void smp_send_stop(void) | |||
56 | int i; | 56 | int i; |
57 | 57 | ||
58 | printk(KERN_INFO "Stopping all CPUs..."); | 58 | printk(KERN_INFO "Stopping all CPUs..."); |
59 | for(i = 0; i < num_online_cpus(); i++){ | 59 | for (i = 0; i < num_online_cpus(); i++) { |
60 | if(i == current_thread->cpu) | 60 | if (i == current_thread->cpu) |
61 | continue; | 61 | continue; |
62 | os_write_file(cpu_data[i].ipi_pipe[1], "S", 1); | 62 | os_write_file(cpu_data[i].ipi_pipe[1], "S", 1); |
63 | } | 63 | } |
64 | printk("done\n"); | 64 | printk(KERN_INFO "done\n"); |
65 | } | 65 | } |
66 | 66 | ||
67 | static cpumask_t smp_commenced_mask = CPU_MASK_NONE; | 67 | static cpumask_t smp_commenced_mask = CPU_MASK_NONE; |
@@ -72,7 +72,7 @@ static int idle_proc(void *cpup) | |||
72 | int cpu = (int) cpup, err; | 72 | int cpu = (int) cpup, err; |
73 | 73 | ||
74 | err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1); | 74 | err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1); |
75 | if(err < 0) | 75 | if (err < 0) |
76 | panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err); | 76 | panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err); |
77 | 77 | ||
78 | os_set_fd_async(cpu_data[cpu].ipi_pipe[0], | 78 | os_set_fd_async(cpu_data[cpu].ipi_pipe[0], |
@@ -80,7 +80,7 @@ static int idle_proc(void *cpup) | |||
80 | 80 | ||
81 | wmb(); | 81 | wmb(); |
82 | if (cpu_test_and_set(cpu, cpu_callin_map)) { | 82 | if (cpu_test_and_set(cpu, cpu_callin_map)) { |
83 | printk("huh, CPU#%d already present??\n", cpu); | 83 | printk(KERN_ERR "huh, CPU#%d already present??\n", cpu); |
84 | BUG(); | 84 | BUG(); |
85 | } | 85 | } |
86 | 86 | ||
@@ -95,12 +95,11 @@ static int idle_proc(void *cpup) | |||
95 | static struct task_struct *idle_thread(int cpu) | 95 | static struct task_struct *idle_thread(int cpu) |
96 | { | 96 | { |
97 | struct task_struct *new_task; | 97 | struct task_struct *new_task; |
98 | unsigned char c; | ||
99 | 98 | ||
100 | current->thread.request.u.thread.proc = idle_proc; | 99 | current->thread.request.u.thread.proc = idle_proc; |
101 | current->thread.request.u.thread.arg = (void *) cpu; | 100 | current->thread.request.u.thread.arg = (void *) cpu; |
102 | new_task = fork_idle(cpu); | 101 | new_task = fork_idle(cpu); |
103 | if(IS_ERR(new_task)) | 102 | if (IS_ERR(new_task)) |
104 | panic("copy_process failed in idle_thread, error = %ld", | 103 | panic("copy_process failed in idle_thread, error = %ld", |
105 | PTR_ERR(new_task)); | 104 | PTR_ERR(new_task)); |
106 | 105 | ||
@@ -108,9 +107,7 @@ static struct task_struct *idle_thread(int cpu) | |||
108 | { .pid = new_task->thread.mode.tt.extern_pid, | 107 | { .pid = new_task->thread.mode.tt.extern_pid, |
109 | .task = new_task } ); | 108 | .task = new_task } ); |
110 | idle_threads[cpu] = new_task; | 109 | idle_threads[cpu] = new_task; |
111 | CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c, | 110 | panic("skas mode doesn't support SMP"); |
112 | sizeof(c)), | ||
113 | ({ panic("skas mode doesn't support SMP"); })); | ||
114 | return new_task; | 111 | return new_task; |
115 | } | 112 | } |
116 | 113 | ||
@@ -129,14 +126,14 @@ void smp_prepare_cpus(unsigned int maxcpus) | |||
129 | cpu_set(me, cpu_callin_map); | 126 | cpu_set(me, cpu_callin_map); |
130 | 127 | ||
131 | err = os_pipe(cpu_data[me].ipi_pipe, 1, 1); | 128 | err = os_pipe(cpu_data[me].ipi_pipe, 1, 1); |
132 | if(err < 0) | 129 | if (err < 0) |
133 | panic("CPU#0 failed to create IPI pipe, errno = %d", -err); | 130 | panic("CPU#0 failed to create IPI pipe, errno = %d", -err); |
134 | 131 | ||
135 | os_set_fd_async(cpu_data[me].ipi_pipe[0], | 132 | os_set_fd_async(cpu_data[me].ipi_pipe[0], |
136 | current->thread.mode.tt.extern_pid); | 133 | current->thread.mode.tt.extern_pid); |
137 | 134 | ||
138 | for(cpu = 1; cpu < ncpus; cpu++){ | 135 | for (cpu = 1; cpu < ncpus; cpu++) { |
139 | printk("Booting processor %d...\n", cpu); | 136 | printk(KERN_INFO "Booting processor %d...\n", cpu); |
140 | 137 | ||
141 | idle = idle_thread(cpu); | 138 | idle = idle_thread(cpu); |
142 | 139 | ||
@@ -147,8 +144,8 @@ void smp_prepare_cpus(unsigned int maxcpus) | |||
147 | cpu_relax(); | 144 | cpu_relax(); |
148 | 145 | ||
149 | if (cpu_isset(cpu, cpu_callin_map)) | 146 | if (cpu_isset(cpu, cpu_callin_map)) |
150 | printk("done\n"); | 147 | printk(KERN_INFO "done\n"); |
151 | else printk("failed\n"); | 148 | else printk(KERN_INFO "failed\n"); |
152 | } | 149 | } |
153 | } | 150 | } |
154 | 151 | ||
@@ -190,13 +187,14 @@ void IPI_handler(int cpu) | |||
190 | break; | 187 | break; |
191 | 188 | ||
192 | case 'S': | 189 | case 'S': |
193 | printk("CPU#%d stopping\n", cpu); | 190 | printk(KERN_INFO "CPU#%d stopping\n", cpu); |
194 | while(1) | 191 | while (1) |
195 | pause(); | 192 | pause(); |
196 | break; | 193 | break; |
197 | 194 | ||
198 | default: | 195 | default: |
199 | printk("CPU#%d received unknown IPI [%c]!\n", cpu, c); | 196 | printk(KERN_ERR "CPU#%d received unknown IPI [%c]!\n", |
197 | cpu, c); | ||
200 | break; | 198 | break; |
201 | } | 199 | } |
202 | } | 200 | } |
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index 7b3b67333ff3..b9d92b2089ae 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c | |||
@@ -1,27 +1,17 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/sched.h" | ||
7 | #include "linux/file.h" | 6 | #include "linux/file.h" |
8 | #include "linux/smp_lock.h" | ||
9 | #include "linux/mm.h" | ||
10 | #include "linux/fs.h" | 7 | #include "linux/fs.h" |
8 | #include "linux/mm.h" | ||
9 | #include "linux/sched.h" | ||
11 | #include "linux/utsname.h" | 10 | #include "linux/utsname.h" |
12 | #include "linux/msg.h" | 11 | #include "asm/current.h" |
13 | #include "linux/shm.h" | ||
14 | #include "linux/sys.h" | ||
15 | #include "linux/syscalls.h" | ||
16 | #include "linux/unistd.h" | ||
17 | #include "linux/slab.h" | ||
18 | #include "linux/utime.h" | ||
19 | #include "asm/mman.h" | 12 | #include "asm/mman.h" |
20 | #include "asm/uaccess.h" | 13 | #include "asm/uaccess.h" |
21 | #include "kern_util.h" | 14 | #include "asm/unistd.h" |
22 | #include "sysdep/syscalls.h" | ||
23 | #include "mode_kern.h" | ||
24 | #include "choose-mode.h" | ||
25 | 15 | ||
26 | /* Unlocked, I don't care if this is a bit off */ | 16 | /* Unlocked, I don't care if this is a bit off */ |
27 | int nsyscalls = 0; | 17 | int nsyscalls = 0; |
@@ -34,7 +24,7 @@ long sys_fork(void) | |||
34 | ret = do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), | 24 | ret = do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), |
35 | ¤t->thread.regs, 0, NULL, NULL); | 25 | ¤t->thread.regs, 0, NULL, NULL); |
36 | current->thread.forking = 0; | 26 | current->thread.forking = 0; |
37 | return(ret); | 27 | return ret; |
38 | } | 28 | } |
39 | 29 | ||
40 | long sys_vfork(void) | 30 | long sys_vfork(void) |
@@ -46,7 +36,7 @@ long sys_vfork(void) | |||
46 | UPT_SP(¤t->thread.regs.regs), | 36 | UPT_SP(¤t->thread.regs.regs), |
47 | ¤t->thread.regs, 0, NULL, NULL); | 37 | ¤t->thread.regs, 0, NULL, NULL); |
48 | current->thread.forking = 0; | 38 | current->thread.forking = 0; |
49 | return(ret); | 39 | return ret; |
50 | } | 40 | } |
51 | 41 | ||
52 | /* common code for old and new mmaps */ | 42 | /* common code for old and new mmaps */ |
@@ -92,15 +82,15 @@ long old_mmap(unsigned long addr, unsigned long len, | |||
92 | */ | 82 | */ |
93 | long sys_pipe(unsigned long __user * fildes) | 83 | long sys_pipe(unsigned long __user * fildes) |
94 | { | 84 | { |
95 | int fd[2]; | 85 | int fd[2]; |
96 | long error; | 86 | long error; |
97 | 87 | ||
98 | error = do_pipe(fd); | 88 | error = do_pipe(fd); |
99 | if (!error) { | 89 | if (!error) { |
100 | if (copy_to_user(fildes, fd, sizeof(fd))) | 90 | if (copy_to_user(fildes, fd, sizeof(fd))) |
101 | error = -EFAULT; | 91 | error = -EFAULT; |
102 | } | 92 | } |
103 | return error; | 93 | return error; |
104 | } | 94 | } |
105 | 95 | ||
106 | 96 | ||
@@ -124,7 +114,7 @@ long sys_olduname(struct oldold_utsname __user * name) | |||
124 | if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) | 114 | if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) |
125 | return -EFAULT; | 115 | return -EFAULT; |
126 | 116 | ||
127 | down_read(&uts_sem); | 117 | down_read(&uts_sem); |
128 | 118 | ||
129 | error = __copy_to_user(&name->sysname, &utsname()->sysname, | 119 | error = __copy_to_user(&name->sysname, &utsname()->sysname, |
130 | __OLD_UTS_LEN); | 120 | __OLD_UTS_LEN); |
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index 259c49da7ff5..1ac746a9eae1 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c | |||
@@ -1,189 +1,126 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/kernel.h" | 6 | #include "linux/clockchips.h" |
7 | #include "linux/module.h" | ||
8 | #include "linux/unistd.h" | ||
9 | #include "linux/stddef.h" | ||
10 | #include "linux/spinlock.h" | ||
11 | #include "linux/time.h" | ||
12 | #include "linux/sched.h" | ||
13 | #include "linux/interrupt.h" | 7 | #include "linux/interrupt.h" |
14 | #include "linux/init.h" | 8 | #include "linux/jiffies.h" |
15 | #include "linux/delay.h" | 9 | #include "linux/threads.h" |
16 | #include "linux/hrtimer.h" | ||
17 | #include "asm/irq.h" | 10 | #include "asm/irq.h" |
18 | #include "asm/param.h" | 11 | #include "asm/param.h" |
19 | #include "asm/current.h" | ||
20 | #include "kern_util.h" | 12 | #include "kern_util.h" |
21 | #include "mode.h" | ||
22 | #include "os.h" | 13 | #include "os.h" |
23 | 14 | ||
24 | int hz(void) | ||
25 | { | ||
26 | return(HZ); | ||
27 | } | ||
28 | |||
29 | /* | 15 | /* |
30 | * Scheduler clock - returns current time in nanosec units. | 16 | * Scheduler clock - returns current time in nanosec units. |
31 | */ | 17 | */ |
32 | unsigned long long sched_clock(void) | 18 | unsigned long long sched_clock(void) |
33 | { | 19 | { |
34 | return (unsigned long long)jiffies_64 * (1000000000 / HZ); | 20 | return (unsigned long long)jiffies_64 * (NSEC_PER_SEC / HZ); |
35 | } | 21 | } |
36 | 22 | ||
37 | #ifdef CONFIG_UML_REAL_TIME_CLOCK | 23 | void timer_handler(int sig, struct uml_pt_regs *regs) |
38 | static unsigned long long prev_nsecs[NR_CPUS]; | 24 | { |
39 | static long long delta[NR_CPUS]; /* Deviation per interval */ | 25 | unsigned long flags; |
40 | #endif | 26 | |
27 | local_irq_save(flags); | ||
28 | do_IRQ(TIMER_IRQ, regs); | ||
29 | local_irq_restore(flags); | ||
30 | } | ||
41 | 31 | ||
42 | void timer_irq(union uml_pt_regs *regs) | 32 | static void itimer_set_mode(enum clock_event_mode mode, |
33 | struct clock_event_device *evt) | ||
43 | { | 34 | { |
44 | unsigned long long ticks = 0; | 35 | switch(mode) { |
45 | #ifdef CONFIG_UML_REAL_TIME_CLOCK | 36 | case CLOCK_EVT_MODE_PERIODIC: |
46 | int c = cpu(); | 37 | set_interval(); |
47 | if(prev_nsecs[c]){ | 38 | break; |
48 | /* We've had 1 tick */ | 39 | |
49 | unsigned long long nsecs = os_nsecs(); | 40 | case CLOCK_EVT_MODE_SHUTDOWN: |
50 | 41 | case CLOCK_EVT_MODE_UNUSED: | |
51 | delta[c] += nsecs - prev_nsecs[c]; | 42 | case CLOCK_EVT_MODE_ONESHOT: |
52 | prev_nsecs[c] = nsecs; | 43 | disable_timer(); |
53 | 44 | break; | |
54 | /* Protect against the host clock being set backwards */ | 45 | |
55 | if(delta[c] < 0) | 46 | case CLOCK_EVT_MODE_RESUME: |
56 | delta[c] = 0; | 47 | break; |
57 | |||
58 | ticks += (delta[c] * HZ) / BILLION; | ||
59 | delta[c] -= (ticks * BILLION) / HZ; | ||
60 | } | ||
61 | else prev_nsecs[c] = os_nsecs(); | ||
62 | #else | ||
63 | ticks = 1; | ||
64 | #endif | ||
65 | while(ticks > 0){ | ||
66 | do_IRQ(TIMER_IRQ, regs); | ||
67 | ticks--; | ||
68 | } | 48 | } |
69 | } | 49 | } |
70 | 50 | ||
71 | /* Protects local_offset */ | 51 | static int itimer_next_event(unsigned long delta, |
72 | static DEFINE_SPINLOCK(timer_spinlock); | 52 | struct clock_event_device *evt) |
73 | static unsigned long long local_offset = 0; | ||
74 | |||
75 | static inline unsigned long long get_time(void) | ||
76 | { | 53 | { |
77 | unsigned long long nsecs; | 54 | return timer_one_shot(delta + 1); |
78 | unsigned long flags; | ||
79 | |||
80 | spin_lock_irqsave(&timer_spinlock, flags); | ||
81 | nsecs = os_nsecs(); | ||
82 | nsecs += local_offset; | ||
83 | spin_unlock_irqrestore(&timer_spinlock, flags); | ||
84 | |||
85 | return nsecs; | ||
86 | } | 55 | } |
87 | 56 | ||
88 | irqreturn_t um_timer(int irq, void *dev) | 57 | static struct clock_event_device itimer_clockevent = { |
58 | .name = "itimer", | ||
59 | .rating = 250, | ||
60 | .cpumask = CPU_MASK_ALL, | ||
61 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | ||
62 | .set_mode = itimer_set_mode, | ||
63 | .set_next_event = itimer_next_event, | ||
64 | .shift = 32, | ||
65 | .irq = 0, | ||
66 | }; | ||
67 | |||
68 | static irqreturn_t um_timer(int irq, void *dev) | ||
89 | { | 69 | { |
90 | unsigned long long nsecs; | 70 | (*itimer_clockevent.event_handler)(&itimer_clockevent); |
91 | unsigned long flags; | ||
92 | |||
93 | write_seqlock_irqsave(&xtime_lock, flags); | ||
94 | |||
95 | do_timer(1); | ||
96 | |||
97 | #ifdef CONFIG_UML_REAL_TIME_CLOCK | ||
98 | nsecs = get_time(); | ||
99 | #else | ||
100 | nsecs = (unsigned long long) xtime.tv_sec * BILLION + xtime.tv_nsec + | ||
101 | BILLION / HZ; | ||
102 | #endif | ||
103 | xtime.tv_sec = nsecs / NSEC_PER_SEC; | ||
104 | xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC; | ||
105 | |||
106 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
107 | 71 | ||
108 | return IRQ_HANDLED; | 72 | return IRQ_HANDLED; |
109 | } | 73 | } |
110 | 74 | ||
111 | static void register_timer(void) | 75 | static cycle_t itimer_read(void) |
76 | { | ||
77 | return os_nsecs(); | ||
78 | } | ||
79 | |||
80 | static struct clocksource itimer_clocksource = { | ||
81 | .name = "itimer", | ||
82 | .rating = 300, | ||
83 | .read = itimer_read, | ||
84 | .mask = CLOCKSOURCE_MASK(64), | ||
85 | .mult = 1, | ||
86 | .shift = 0, | ||
87 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
88 | }; | ||
89 | |||
90 | static void __init setup_itimer(void) | ||
112 | { | 91 | { |
113 | int err; | 92 | int err; |
114 | 93 | ||
115 | err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL); | 94 | err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL); |
116 | if(err != 0) | 95 | if (err != 0) |
117 | printk(KERN_ERR "register_timer : request_irq failed - " | 96 | printk(KERN_ERR "register_timer : request_irq failed - " |
118 | "errno = %d\n", -err); | 97 | "errno = %d\n", -err); |
119 | 98 | ||
120 | err = set_interval(1); | 99 | itimer_clockevent.mult = div_sc(HZ, NSEC_PER_SEC, 32); |
121 | if(err != 0) | 100 | itimer_clockevent.max_delta_ns = |
122 | printk(KERN_ERR "register_timer : set_interval failed - " | 101 | clockevent_delta2ns(60 * HZ, &itimer_clockevent); |
123 | "errno = %d\n", -err); | 102 | itimer_clockevent.min_delta_ns = |
103 | clockevent_delta2ns(1, &itimer_clockevent); | ||
104 | err = clocksource_register(&itimer_clocksource); | ||
105 | if (err) { | ||
106 | printk(KERN_ERR "clocksource_register returned %d\n", err); | ||
107 | return; | ||
108 | } | ||
109 | clockevents_register_device(&itimer_clockevent); | ||
124 | } | 110 | } |
125 | 111 | ||
126 | extern void (*late_time_init)(void); | 112 | extern void (*late_time_init)(void); |
127 | 113 | ||
128 | void time_init(void) | 114 | void __init time_init(void) |
129 | { | 115 | { |
130 | long long nsecs; | 116 | long long nsecs; |
131 | 117 | ||
132 | nsecs = os_nsecs(); | 118 | timer_init(); |
133 | set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION, | ||
134 | -nsecs % BILLION); | ||
135 | set_normalized_timespec(&xtime, nsecs / BILLION, nsecs % BILLION); | ||
136 | late_time_init = register_timer; | ||
137 | } | ||
138 | |||
139 | void do_gettimeofday(struct timeval *tv) | ||
140 | { | ||
141 | #ifdef CONFIG_UML_REAL_TIME_CLOCK | ||
142 | unsigned long long nsecs = get_time(); | ||
143 | #else | ||
144 | unsigned long long nsecs = (unsigned long long) xtime.tv_sec * BILLION + | ||
145 | xtime.tv_nsec; | ||
146 | #endif | ||
147 | tv->tv_sec = nsecs / NSEC_PER_SEC; | ||
148 | /* Careful about calculations here - this was originally done as | ||
149 | * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC | ||
150 | * which gave bogus (> 1000000) values. Dunno why, suspect gcc | ||
151 | * (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion | ||
152 | * problem that I missed. | ||
153 | */ | ||
154 | nsecs -= tv->tv_sec * NSEC_PER_SEC; | ||
155 | tv->tv_usec = (unsigned long) nsecs / NSEC_PER_USEC; | ||
156 | } | ||
157 | |||
158 | static inline void set_time(unsigned long long nsecs) | ||
159 | { | ||
160 | unsigned long long now; | ||
161 | unsigned long flags; | ||
162 | |||
163 | spin_lock_irqsave(&timer_spinlock, flags); | ||
164 | now = os_nsecs(); | ||
165 | local_offset = nsecs - now; | ||
166 | spin_unlock_irqrestore(&timer_spinlock, flags); | ||
167 | |||
168 | clock_was_set(); | ||
169 | } | ||
170 | |||
171 | int do_settimeofday(struct timespec *tv) | ||
172 | { | ||
173 | set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec); | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | 119 | ||
178 | void timer_handler(int sig, union uml_pt_regs *regs) | 120 | nsecs = os_nsecs(); |
179 | { | 121 | set_normalized_timespec(&wall_to_monotonic, -nsecs / NSEC_PER_SEC, |
180 | if(current_thread->cpu == 0) | 122 | -nsecs % NSEC_PER_SEC); |
181 | timer_irq(regs); | 123 | set_normalized_timespec(&xtime, nsecs / NSEC_PER_SEC, |
182 | local_irq_disable(); | 124 | nsecs % NSEC_PER_SEC); |
183 | irq_enter(); | 125 | late_time_init = setup_itimer; |
184 | update_process_times(CHOOSE_MODE( | ||
185 | (UPT_SC(regs) && user_context(UPT_SP(regs))), | ||
186 | (regs)->skas.is_user)); | ||
187 | irq_exit(); | ||
188 | local_irq_enable(); | ||
189 | } | 126 | } |
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c index 8a8d52851443..f4a0e407eee4 100644 --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c | |||
@@ -1,130 +1,182 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/mm.h" | 6 | #include "linux/mm.h" |
7 | #include "asm/page.h" | ||
8 | #include "asm/pgalloc.h" | ||
9 | #include "asm/pgtable.h" | 7 | #include "asm/pgtable.h" |
10 | #include "asm/tlbflush.h" | 8 | #include "asm/tlbflush.h" |
11 | #include "choose-mode.h" | ||
12 | #include "mode_kern.h" | ||
13 | #include "as-layout.h" | 9 | #include "as-layout.h" |
14 | #include "tlb.h" | ||
15 | #include "mem.h" | ||
16 | #include "mem_user.h" | 10 | #include "mem_user.h" |
17 | #include "os.h" | 11 | #include "os.h" |
12 | #include "skas.h" | ||
13 | #include "tlb.h" | ||
14 | |||
15 | struct host_vm_change { | ||
16 | struct host_vm_op { | ||
17 | enum { NONE, MMAP, MUNMAP, MPROTECT } type; | ||
18 | union { | ||
19 | struct { | ||
20 | unsigned long addr; | ||
21 | unsigned long len; | ||
22 | unsigned int prot; | ||
23 | int fd; | ||
24 | __u64 offset; | ||
25 | } mmap; | ||
26 | struct { | ||
27 | unsigned long addr; | ||
28 | unsigned long len; | ||
29 | } munmap; | ||
30 | struct { | ||
31 | unsigned long addr; | ||
32 | unsigned long len; | ||
33 | unsigned int prot; | ||
34 | } mprotect; | ||
35 | } u; | ||
36 | } ops[1]; | ||
37 | int index; | ||
38 | struct mm_id *id; | ||
39 | void *data; | ||
40 | int force; | ||
41 | }; | ||
42 | |||
43 | #define INIT_HVC(mm, force) \ | ||
44 | ((struct host_vm_change) \ | ||
45 | { .ops = { { .type = NONE } }, \ | ||
46 | .id = &mm->context.id, \ | ||
47 | .data = NULL, \ | ||
48 | .index = 0, \ | ||
49 | .force = force }) | ||
50 | |||
51 | static int do_ops(struct host_vm_change *hvc, int end, | ||
52 | int finished) | ||
53 | { | ||
54 | struct host_vm_op *op; | ||
55 | int i, ret = 0; | ||
56 | |||
57 | for (i = 0; i < end && !ret; i++) { | ||
58 | op = &hvc->ops[i]; | ||
59 | switch(op->type) { | ||
60 | case MMAP: | ||
61 | ret = map(hvc->id, op->u.mmap.addr, op->u.mmap.len, | ||
62 | op->u.mmap.prot, op->u.mmap.fd, | ||
63 | op->u.mmap.offset, finished, &hvc->data); | ||
64 | break; | ||
65 | case MUNMAP: | ||
66 | ret = unmap(hvc->id, op->u.munmap.addr, | ||
67 | op->u.munmap.len, finished, &hvc->data); | ||
68 | break; | ||
69 | case MPROTECT: | ||
70 | ret = protect(hvc->id, op->u.mprotect.addr, | ||
71 | op->u.mprotect.len, op->u.mprotect.prot, | ||
72 | finished, &hvc->data); | ||
73 | break; | ||
74 | default: | ||
75 | printk(KERN_ERR "Unknown op type %d in do_ops\n", | ||
76 | op->type); | ||
77 | break; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | return ret; | ||
82 | } | ||
18 | 83 | ||
19 | static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, | 84 | static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, |
20 | unsigned int prot, struct host_vm_op *ops, int *index, | 85 | unsigned int prot, struct host_vm_change *hvc) |
21 | int last_filled, union mm_context *mmu, void **flush, | ||
22 | int (*do_ops)(union mm_context *, struct host_vm_op *, | ||
23 | int, int, void **)) | ||
24 | { | 86 | { |
25 | __u64 offset; | 87 | __u64 offset; |
26 | struct host_vm_op *last; | 88 | struct host_vm_op *last; |
27 | int fd, ret = 0; | 89 | int fd, ret = 0; |
28 | 90 | ||
29 | fd = phys_mapping(phys, &offset); | 91 | fd = phys_mapping(phys, &offset); |
30 | if(*index != -1){ | 92 | if (hvc->index != 0) { |
31 | last = &ops[*index]; | 93 | last = &hvc->ops[hvc->index - 1]; |
32 | if((last->type == MMAP) && | 94 | if ((last->type == MMAP) && |
33 | (last->u.mmap.addr + last->u.mmap.len == virt) && | 95 | (last->u.mmap.addr + last->u.mmap.len == virt) && |
34 | (last->u.mmap.prot == prot) && (last->u.mmap.fd == fd) && | 96 | (last->u.mmap.prot == prot) && (last->u.mmap.fd == fd) && |
35 | (last->u.mmap.offset + last->u.mmap.len == offset)){ | 97 | (last->u.mmap.offset + last->u.mmap.len == offset)) { |
36 | last->u.mmap.len += len; | 98 | last->u.mmap.len += len; |
37 | return 0; | 99 | return 0; |
38 | } | 100 | } |
39 | } | 101 | } |
40 | 102 | ||
41 | if(*index == last_filled){ | 103 | if (hvc->index == ARRAY_SIZE(hvc->ops)) { |
42 | ret = (*do_ops)(mmu, ops, last_filled, 0, flush); | 104 | ret = do_ops(hvc, ARRAY_SIZE(hvc->ops), 0); |
43 | *index = -1; | 105 | hvc->index = 0; |
44 | } | 106 | } |
45 | 107 | ||
46 | ops[++*index] = ((struct host_vm_op) { .type = MMAP, | 108 | hvc->ops[hvc->index++] = ((struct host_vm_op) |
47 | .u = { .mmap = { | 109 | { .type = MMAP, |
48 | .addr = virt, | 110 | .u = { .mmap = { .addr = virt, |
49 | .len = len, | 111 | .len = len, |
50 | .prot = prot, | 112 | .prot = prot, |
51 | .fd = fd, | 113 | .fd = fd, |
52 | .offset = offset } | 114 | .offset = offset } |
53 | } }); | 115 | } }); |
54 | return ret; | 116 | return ret; |
55 | } | 117 | } |
56 | 118 | ||
57 | static int add_munmap(unsigned long addr, unsigned long len, | 119 | static int add_munmap(unsigned long addr, unsigned long len, |
58 | struct host_vm_op *ops, int *index, int last_filled, | 120 | struct host_vm_change *hvc) |
59 | union mm_context *mmu, void **flush, | ||
60 | int (*do_ops)(union mm_context *, struct host_vm_op *, | ||
61 | int, int, void **)) | ||
62 | { | 121 | { |
63 | struct host_vm_op *last; | 122 | struct host_vm_op *last; |
64 | int ret = 0; | 123 | int ret = 0; |
65 | 124 | ||
66 | if(*index != -1){ | 125 | if (hvc->index != 0) { |
67 | last = &ops[*index]; | 126 | last = &hvc->ops[hvc->index - 1]; |
68 | if((last->type == MUNMAP) && | 127 | if ((last->type == MUNMAP) && |
69 | (last->u.munmap.addr + last->u.mmap.len == addr)){ | 128 | (last->u.munmap.addr + last->u.mmap.len == addr)) { |
70 | last->u.munmap.len += len; | 129 | last->u.munmap.len += len; |
71 | return 0; | 130 | return 0; |
72 | } | 131 | } |
73 | } | 132 | } |
74 | 133 | ||
75 | if(*index == last_filled){ | 134 | if (hvc->index == ARRAY_SIZE(hvc->ops)) { |
76 | ret = (*do_ops)(mmu, ops, last_filled, 0, flush); | 135 | ret = do_ops(hvc, ARRAY_SIZE(hvc->ops), 0); |
77 | *index = -1; | 136 | hvc->index = 0; |
78 | } | 137 | } |
79 | 138 | ||
80 | ops[++*index] = ((struct host_vm_op) { .type = MUNMAP, | 139 | hvc->ops[hvc->index++] = ((struct host_vm_op) |
81 | .u = { .munmap = { | 140 | { .type = MUNMAP, |
82 | .addr = addr, | 141 | .u = { .munmap = { .addr = addr, |
83 | .len = len } } }); | 142 | .len = len } } }); |
84 | return ret; | 143 | return ret; |
85 | } | 144 | } |
86 | 145 | ||
87 | static int add_mprotect(unsigned long addr, unsigned long len, | 146 | static int add_mprotect(unsigned long addr, unsigned long len, |
88 | unsigned int prot, struct host_vm_op *ops, int *index, | 147 | unsigned int prot, struct host_vm_change *hvc) |
89 | int last_filled, union mm_context *mmu, void **flush, | ||
90 | int (*do_ops)(union mm_context *, struct host_vm_op *, | ||
91 | int, int, void **)) | ||
92 | { | 148 | { |
93 | struct host_vm_op *last; | 149 | struct host_vm_op *last; |
94 | int ret = 0; | 150 | int ret = 0; |
95 | 151 | ||
96 | if(*index != -1){ | 152 | if (hvc->index != 0) { |
97 | last = &ops[*index]; | 153 | last = &hvc->ops[hvc->index - 1]; |
98 | if((last->type == MPROTECT) && | 154 | if ((last->type == MPROTECT) && |
99 | (last->u.mprotect.addr + last->u.mprotect.len == addr) && | 155 | (last->u.mprotect.addr + last->u.mprotect.len == addr) && |
100 | (last->u.mprotect.prot == prot)){ | 156 | (last->u.mprotect.prot == prot)) { |
101 | last->u.mprotect.len += len; | 157 | last->u.mprotect.len += len; |
102 | return 0; | 158 | return 0; |
103 | } | 159 | } |
104 | } | 160 | } |
105 | 161 | ||
106 | if(*index == last_filled){ | 162 | if (hvc->index == ARRAY_SIZE(hvc->ops)) { |
107 | ret = (*do_ops)(mmu, ops, last_filled, 0, flush); | 163 | ret = do_ops(hvc, ARRAY_SIZE(hvc->ops), 0); |
108 | *index = -1; | 164 | hvc->index = 0; |
109 | } | 165 | } |
110 | 166 | ||
111 | ops[++*index] = ((struct host_vm_op) { .type = MPROTECT, | 167 | hvc->ops[hvc->index++] = ((struct host_vm_op) |
112 | .u = { .mprotect = { | 168 | { .type = MPROTECT, |
113 | .addr = addr, | 169 | .u = { .mprotect = { .addr = addr, |
114 | .len = len, | 170 | .len = len, |
115 | .prot = prot } } }); | 171 | .prot = prot } } }); |
116 | return ret; | 172 | return ret; |
117 | } | 173 | } |
118 | 174 | ||
119 | #define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1)) | 175 | #define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1)) |
120 | 176 | ||
121 | static inline int update_pte_range(pmd_t *pmd, unsigned long addr, | 177 | static inline int update_pte_range(pmd_t *pmd, unsigned long addr, |
122 | unsigned long end, struct host_vm_op *ops, | 178 | unsigned long end, |
123 | int last_op, int *op_index, int force, | 179 | struct host_vm_change *hvc) |
124 | union mm_context *mmu, void **flush, | ||
125 | int (*do_ops)(union mm_context *, | ||
126 | struct host_vm_op *, int, int, | ||
127 | void **)) | ||
128 | { | 180 | { |
129 | pte_t *pte; | 181 | pte_t *pte; |
130 | int r, w, x, prot, ret = 0; | 182 | int r, w, x, prot, ret = 0; |
@@ -142,29 +194,22 @@ static inline int update_pte_range(pmd_t *pmd, unsigned long addr, | |||
142 | } | 194 | } |
143 | prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | | 195 | prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | |
144 | (x ? UM_PROT_EXEC : 0)); | 196 | (x ? UM_PROT_EXEC : 0)); |
145 | if(force || pte_newpage(*pte)){ | 197 | if (hvc->force || pte_newpage(*pte)) { |
146 | if(pte_present(*pte)) | 198 | if (pte_present(*pte)) |
147 | ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK, | 199 | ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK, |
148 | PAGE_SIZE, prot, ops, op_index, | 200 | PAGE_SIZE, prot, hvc); |
149 | last_op, mmu, flush, do_ops); | 201 | else ret = add_munmap(addr, PAGE_SIZE, hvc); |
150 | else ret = add_munmap(addr, PAGE_SIZE, ops, op_index, | ||
151 | last_op, mmu, flush, do_ops); | ||
152 | } | 202 | } |
153 | else if(pte_newprot(*pte)) | 203 | else if (pte_newprot(*pte)) |
154 | ret = add_mprotect(addr, PAGE_SIZE, prot, ops, op_index, | 204 | ret = add_mprotect(addr, PAGE_SIZE, prot, hvc); |
155 | last_op, mmu, flush, do_ops); | ||
156 | *pte = pte_mkuptodate(*pte); | 205 | *pte = pte_mkuptodate(*pte); |
157 | } while (pte++, addr += PAGE_SIZE, ((addr != end) && !ret)); | 206 | } while (pte++, addr += PAGE_SIZE, ((addr != end) && !ret)); |
158 | return ret; | 207 | return ret; |
159 | } | 208 | } |
160 | 209 | ||
161 | static inline int update_pmd_range(pud_t *pud, unsigned long addr, | 210 | static inline int update_pmd_range(pud_t *pud, unsigned long addr, |
162 | unsigned long end, struct host_vm_op *ops, | 211 | unsigned long end, |
163 | int last_op, int *op_index, int force, | 212 | struct host_vm_change *hvc) |
164 | union mm_context *mmu, void **flush, | ||
165 | int (*do_ops)(union mm_context *, | ||
166 | struct host_vm_op *, int, int, | ||
167 | void **)) | ||
168 | { | 213 | { |
169 | pmd_t *pmd; | 214 | pmd_t *pmd; |
170 | unsigned long next; | 215 | unsigned long next; |
@@ -173,28 +218,20 @@ static inline int update_pmd_range(pud_t *pud, unsigned long addr, | |||
173 | pmd = pmd_offset(pud, addr); | 218 | pmd = pmd_offset(pud, addr); |
174 | do { | 219 | do { |
175 | next = pmd_addr_end(addr, end); | 220 | next = pmd_addr_end(addr, end); |
176 | if(!pmd_present(*pmd)){ | 221 | if (!pmd_present(*pmd)) { |
177 | if(force || pmd_newpage(*pmd)){ | 222 | if (hvc->force || pmd_newpage(*pmd)) { |
178 | ret = add_munmap(addr, next - addr, ops, | 223 | ret = add_munmap(addr, next - addr, hvc); |
179 | op_index, last_op, mmu, | ||
180 | flush, do_ops); | ||
181 | pmd_mkuptodate(*pmd); | 224 | pmd_mkuptodate(*pmd); |
182 | } | 225 | } |
183 | } | 226 | } |
184 | else ret = update_pte_range(pmd, addr, next, ops, last_op, | 227 | else ret = update_pte_range(pmd, addr, next, hvc); |
185 | op_index, force, mmu, flush, | ||
186 | do_ops); | ||
187 | } while (pmd++, addr = next, ((addr != end) && !ret)); | 228 | } while (pmd++, addr = next, ((addr != end) && !ret)); |
188 | return ret; | 229 | return ret; |
189 | } | 230 | } |
190 | 231 | ||
191 | static inline int update_pud_range(pgd_t *pgd, unsigned long addr, | 232 | static inline int update_pud_range(pgd_t *pgd, unsigned long addr, |
192 | unsigned long end, struct host_vm_op *ops, | 233 | unsigned long end, |
193 | int last_op, int *op_index, int force, | 234 | struct host_vm_change *hvc) |
194 | union mm_context *mmu, void **flush, | ||
195 | int (*do_ops)(union mm_context *, | ||
196 | struct host_vm_op *, int, int, | ||
197 | void **)) | ||
198 | { | 235 | { |
199 | pud_t *pud; | 236 | pud_t *pud; |
200 | unsigned long next; | 237 | unsigned long next; |
@@ -203,56 +240,45 @@ static inline int update_pud_range(pgd_t *pgd, unsigned long addr, | |||
203 | pud = pud_offset(pgd, addr); | 240 | pud = pud_offset(pgd, addr); |
204 | do { | 241 | do { |
205 | next = pud_addr_end(addr, end); | 242 | next = pud_addr_end(addr, end); |
206 | if(!pud_present(*pud)){ | 243 | if (!pud_present(*pud)) { |
207 | if(force || pud_newpage(*pud)){ | 244 | if (hvc->force || pud_newpage(*pud)) { |
208 | ret = add_munmap(addr, next - addr, ops, | 245 | ret = add_munmap(addr, next - addr, hvc); |
209 | op_index, last_op, mmu, | ||
210 | flush, do_ops); | ||
211 | pud_mkuptodate(*pud); | 246 | pud_mkuptodate(*pud); |
212 | } | 247 | } |
213 | } | 248 | } |
214 | else ret = update_pmd_range(pud, addr, next, ops, last_op, | 249 | else ret = update_pmd_range(pud, addr, next, hvc); |
215 | op_index, force, mmu, flush, | ||
216 | do_ops); | ||
217 | } while (pud++, addr = next, ((addr != end) && !ret)); | 250 | } while (pud++, addr = next, ((addr != end) && !ret)); |
218 | return ret; | 251 | return ret; |
219 | } | 252 | } |
220 | 253 | ||
221 | void fix_range_common(struct mm_struct *mm, unsigned long start_addr, | 254 | void fix_range_common(struct mm_struct *mm, unsigned long start_addr, |
222 | unsigned long end_addr, int force, | 255 | unsigned long end_addr, int force) |
223 | int (*do_ops)(union mm_context *, struct host_vm_op *, | ||
224 | int, int, void **)) | ||
225 | { | 256 | { |
226 | pgd_t *pgd; | 257 | pgd_t *pgd; |
227 | union mm_context *mmu = &mm->context; | 258 | struct host_vm_change hvc; |
228 | struct host_vm_op ops[1]; | ||
229 | unsigned long addr = start_addr, next; | 259 | unsigned long addr = start_addr, next; |
230 | int ret = 0, last_op = ARRAY_SIZE(ops) - 1, op_index = -1; | 260 | int ret = 0; |
231 | void *flush = NULL; | ||
232 | 261 | ||
233 | ops[0].type = NONE; | 262 | hvc = INIT_HVC(mm, force); |
234 | pgd = pgd_offset(mm, addr); | 263 | pgd = pgd_offset(mm, addr); |
235 | do { | 264 | do { |
236 | next = pgd_addr_end(addr, end_addr); | 265 | next = pgd_addr_end(addr, end_addr); |
237 | if(!pgd_present(*pgd)){ | 266 | if (!pgd_present(*pgd)) { |
238 | if (force || pgd_newpage(*pgd)){ | 267 | if (force || pgd_newpage(*pgd)) { |
239 | ret = add_munmap(addr, next - addr, ops, | 268 | ret = add_munmap(addr, next - addr, &hvc); |
240 | &op_index, last_op, mmu, | ||
241 | &flush, do_ops); | ||
242 | pgd_mkuptodate(*pgd); | 269 | pgd_mkuptodate(*pgd); |
243 | } | 270 | } |
244 | } | 271 | } |
245 | else ret = update_pud_range(pgd, addr, next, ops, last_op, | 272 | else ret = update_pud_range(pgd, addr, next, &hvc); |
246 | &op_index, force, mmu, &flush, | ||
247 | do_ops); | ||
248 | } while (pgd++, addr = next, ((addr != end_addr) && !ret)); | 273 | } while (pgd++, addr = next, ((addr != end_addr) && !ret)); |
249 | 274 | ||
250 | if(!ret) | 275 | if (!ret) |
251 | ret = (*do_ops)(mmu, ops, op_index, 1, &flush); | 276 | ret = do_ops(&hvc, hvc.index, 1); |
252 | 277 | ||
253 | /* This is not an else because ret is modified above */ | 278 | /* This is not an else because ret is modified above */ |
254 | if(ret) { | 279 | if (ret) { |
255 | printk("fix_range_common: failed, killing current process\n"); | 280 | printk(KERN_ERR "fix_range_common: failed, killing current " |
281 | "process\n"); | ||
256 | force_sig(SIGKILL, current); | 282 | force_sig(SIGKILL, current); |
257 | } | 283 | } |
258 | } | 284 | } |
@@ -268,17 +294,17 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) | |||
268 | int updated = 0, err; | 294 | int updated = 0, err; |
269 | 295 | ||
270 | mm = &init_mm; | 296 | mm = &init_mm; |
271 | for(addr = start; addr < end;){ | 297 | for (addr = start; addr < end;) { |
272 | pgd = pgd_offset(mm, addr); | 298 | pgd = pgd_offset(mm, addr); |
273 | if(!pgd_present(*pgd)){ | 299 | if (!pgd_present(*pgd)) { |
274 | last = ADD_ROUND(addr, PGDIR_SIZE); | 300 | last = ADD_ROUND(addr, PGDIR_SIZE); |
275 | if(last > end) | 301 | if (last > end) |
276 | last = end; | 302 | last = end; |
277 | if(pgd_newpage(*pgd)){ | 303 | if (pgd_newpage(*pgd)) { |
278 | updated = 1; | 304 | updated = 1; |
279 | err = os_unmap_memory((void *) addr, | 305 | err = os_unmap_memory((void *) addr, |
280 | last - addr); | 306 | last - addr); |
281 | if(err < 0) | 307 | if (err < 0) |
282 | panic("munmap failed, errno = %d\n", | 308 | panic("munmap failed, errno = %d\n", |
283 | -err); | 309 | -err); |
284 | } | 310 | } |
@@ -287,15 +313,15 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) | |||
287 | } | 313 | } |
288 | 314 | ||
289 | pud = pud_offset(pgd, addr); | 315 | pud = pud_offset(pgd, addr); |
290 | if(!pud_present(*pud)){ | 316 | if (!pud_present(*pud)) { |
291 | last = ADD_ROUND(addr, PUD_SIZE); | 317 | last = ADD_ROUND(addr, PUD_SIZE); |
292 | if(last > end) | 318 | if (last > end) |
293 | last = end; | 319 | last = end; |
294 | if(pud_newpage(*pud)){ | 320 | if (pud_newpage(*pud)) { |
295 | updated = 1; | 321 | updated = 1; |
296 | err = os_unmap_memory((void *) addr, | 322 | err = os_unmap_memory((void *) addr, |
297 | last - addr); | 323 | last - addr); |
298 | if(err < 0) | 324 | if (err < 0) |
299 | panic("munmap failed, errno = %d\n", | 325 | panic("munmap failed, errno = %d\n", |
300 | -err); | 326 | -err); |
301 | } | 327 | } |
@@ -304,15 +330,15 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) | |||
304 | } | 330 | } |
305 | 331 | ||
306 | pmd = pmd_offset(pud, addr); | 332 | pmd = pmd_offset(pud, addr); |
307 | if(!pmd_present(*pmd)){ | 333 | if (!pmd_present(*pmd)) { |
308 | last = ADD_ROUND(addr, PMD_SIZE); | 334 | last = ADD_ROUND(addr, PMD_SIZE); |
309 | if(last > end) | 335 | if (last > end) |
310 | last = end; | 336 | last = end; |
311 | if(pmd_newpage(*pmd)){ | 337 | if (pmd_newpage(*pmd)) { |
312 | updated = 1; | 338 | updated = 1; |
313 | err = os_unmap_memory((void *) addr, | 339 | err = os_unmap_memory((void *) addr, |
314 | last - addr); | 340 | last - addr); |
315 | if(err < 0) | 341 | if (err < 0) |
316 | panic("munmap failed, errno = %d\n", | 342 | panic("munmap failed, errno = %d\n", |
317 | -err); | 343 | -err); |
318 | } | 344 | } |
@@ -321,45 +347,110 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) | |||
321 | } | 347 | } |
322 | 348 | ||
323 | pte = pte_offset_kernel(pmd, addr); | 349 | pte = pte_offset_kernel(pmd, addr); |
324 | if(!pte_present(*pte) || pte_newpage(*pte)){ | 350 | if (!pte_present(*pte) || pte_newpage(*pte)) { |
325 | updated = 1; | 351 | updated = 1; |
326 | err = os_unmap_memory((void *) addr, | 352 | err = os_unmap_memory((void *) addr, |
327 | PAGE_SIZE); | 353 | PAGE_SIZE); |
328 | if(err < 0) | 354 | if (err < 0) |
329 | panic("munmap failed, errno = %d\n", | 355 | panic("munmap failed, errno = %d\n", |
330 | -err); | 356 | -err); |
331 | if(pte_present(*pte)) | 357 | if (pte_present(*pte)) |
332 | map_memory(addr, | 358 | map_memory(addr, |
333 | pte_val(*pte) & PAGE_MASK, | 359 | pte_val(*pte) & PAGE_MASK, |
334 | PAGE_SIZE, 1, 1, 1); | 360 | PAGE_SIZE, 1, 1, 1); |
335 | } | 361 | } |
336 | else if(pte_newprot(*pte)){ | 362 | else if (pte_newprot(*pte)) { |
337 | updated = 1; | 363 | updated = 1; |
338 | os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1); | 364 | os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1); |
339 | } | 365 | } |
340 | addr += PAGE_SIZE; | 366 | addr += PAGE_SIZE; |
341 | } | 367 | } |
342 | return(updated); | 368 | return updated; |
369 | } | ||
370 | |||
371 | void flush_tlb_page(struct vm_area_struct *vma, unsigned long address) | ||
372 | { | ||
373 | pgd_t *pgd; | ||
374 | pud_t *pud; | ||
375 | pmd_t *pmd; | ||
376 | pte_t *pte; | ||
377 | struct mm_struct *mm = vma->vm_mm; | ||
378 | void *flush = NULL; | ||
379 | int r, w, x, prot, err = 0; | ||
380 | struct mm_id *mm_id; | ||
381 | |||
382 | address &= PAGE_MASK; | ||
383 | pgd = pgd_offset(mm, address); | ||
384 | if (!pgd_present(*pgd)) | ||
385 | goto kill; | ||
386 | |||
387 | pud = pud_offset(pgd, address); | ||
388 | if (!pud_present(*pud)) | ||
389 | goto kill; | ||
390 | |||
391 | pmd = pmd_offset(pud, address); | ||
392 | if (!pmd_present(*pmd)) | ||
393 | goto kill; | ||
394 | |||
395 | pte = pte_offset_kernel(pmd, address); | ||
396 | |||
397 | r = pte_read(*pte); | ||
398 | w = pte_write(*pte); | ||
399 | x = pte_exec(*pte); | ||
400 | if (!pte_young(*pte)) { | ||
401 | r = 0; | ||
402 | w = 0; | ||
403 | } else if (!pte_dirty(*pte)) { | ||
404 | w = 0; | ||
405 | } | ||
406 | |||
407 | mm_id = &mm->context.id; | ||
408 | prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) | | ||
409 | (x ? UM_PROT_EXEC : 0)); | ||
410 | if (pte_newpage(*pte)) { | ||
411 | if (pte_present(*pte)) { | ||
412 | unsigned long long offset; | ||
413 | int fd; | ||
414 | |||
415 | fd = phys_mapping(pte_val(*pte) & PAGE_MASK, &offset); | ||
416 | err = map(mm_id, address, PAGE_SIZE, prot, fd, offset, | ||
417 | 1, &flush); | ||
418 | } | ||
419 | else err = unmap(mm_id, address, PAGE_SIZE, 1, &flush); | ||
420 | } | ||
421 | else if (pte_newprot(*pte)) | ||
422 | err = protect(mm_id, address, PAGE_SIZE, prot, 1, &flush); | ||
423 | |||
424 | if (err) | ||
425 | goto kill; | ||
426 | |||
427 | *pte = pte_mkuptodate(*pte); | ||
428 | |||
429 | return; | ||
430 | |||
431 | kill: | ||
432 | printk(KERN_ERR "Failed to flush page for address 0x%lx\n", address); | ||
433 | force_sig(SIGKILL, current); | ||
343 | } | 434 | } |
344 | 435 | ||
345 | pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) | 436 | pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) |
346 | { | 437 | { |
347 | return(pgd_offset(mm, address)); | 438 | return pgd_offset(mm, address); |
348 | } | 439 | } |
349 | 440 | ||
350 | pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address) | 441 | pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address) |
351 | { | 442 | { |
352 | return(pud_offset(pgd, address)); | 443 | return pud_offset(pgd, address); |
353 | } | 444 | } |
354 | 445 | ||
355 | pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address) | 446 | pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address) |
356 | { | 447 | { |
357 | return(pmd_offset(pud, address)); | 448 | return pmd_offset(pud, address); |
358 | } | 449 | } |
359 | 450 | ||
360 | pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) | 451 | pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) |
361 | { | 452 | { |
362 | return(pte_offset_kernel(pmd, address)); | 453 | return pte_offset_kernel(pmd, address); |
363 | } | 454 | } |
364 | 455 | ||
365 | pte_t *addr_pte(struct task_struct *task, unsigned long addr) | 456 | pte_t *addr_pte(struct task_struct *task, unsigned long addr) |
@@ -368,7 +459,7 @@ pte_t *addr_pte(struct task_struct *task, unsigned long addr) | |||
368 | pud_t *pud = pud_offset(pgd, addr); | 459 | pud_t *pud = pud_offset(pgd, addr); |
369 | pmd_t *pmd = pmd_offset(pud, addr); | 460 | pmd_t *pmd = pmd_offset(pud, addr); |
370 | 461 | ||
371 | return(pte_offset_map(pmd, addr)); | 462 | return pte_offset_map(pmd, addr); |
372 | } | 463 | } |
373 | 464 | ||
374 | void flush_tlb_all(void) | 465 | void flush_tlb_all(void) |
@@ -378,35 +469,58 @@ void flush_tlb_all(void) | |||
378 | 469 | ||
379 | void flush_tlb_kernel_range(unsigned long start, unsigned long end) | 470 | void flush_tlb_kernel_range(unsigned long start, unsigned long end) |
380 | { | 471 | { |
381 | CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt, | 472 | flush_tlb_kernel_range_common(start, end); |
382 | flush_tlb_kernel_range_common, start, end); | ||
383 | } | 473 | } |
384 | 474 | ||
385 | void flush_tlb_kernel_vm(void) | 475 | void flush_tlb_kernel_vm(void) |
386 | { | 476 | { |
387 | CHOOSE_MODE(flush_tlb_kernel_vm_tt(), | 477 | flush_tlb_kernel_range_common(start_vm, end_vm); |
388 | flush_tlb_kernel_range_common(start_vm, end_vm)); | ||
389 | } | 478 | } |
390 | 479 | ||
391 | void __flush_tlb_one(unsigned long addr) | 480 | void __flush_tlb_one(unsigned long addr) |
392 | { | 481 | { |
393 | CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr); | 482 | flush_tlb_kernel_range_common(addr, addr + PAGE_SIZE); |
483 | } | ||
484 | |||
485 | static void fix_range(struct mm_struct *mm, unsigned long start_addr, | ||
486 | unsigned long end_addr, int force) | ||
487 | { | ||
488 | if (!proc_mm && (end_addr > STUB_START)) | ||
489 | end_addr = STUB_START; | ||
490 | |||
491 | fix_range_common(mm, start_addr, end_addr, force); | ||
394 | } | 492 | } |
395 | 493 | ||
396 | void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | 494 | void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, |
397 | unsigned long end) | 495 | unsigned long end) |
398 | { | 496 | { |
399 | CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start, | 497 | if (vma->vm_mm == NULL) |
400 | end); | 498 | flush_tlb_kernel_range_common(start, end); |
499 | else fix_range(vma->vm_mm, start, end, 0); | ||
401 | } | 500 | } |
402 | 501 | ||
403 | void flush_tlb_mm(struct mm_struct *mm) | 502 | void flush_tlb_mm(struct mm_struct *mm) |
404 | { | 503 | { |
405 | CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm); | 504 | unsigned long end; |
505 | |||
506 | /* | ||
507 | * Don't bother flushing if this address space is about to be | ||
508 | * destroyed. | ||
509 | */ | ||
510 | if (atomic_read(&mm->mm_users) == 0) | ||
511 | return; | ||
512 | |||
513 | end = proc_mm ? task_size : STUB_START; | ||
514 | fix_range(mm, 0, end, 0); | ||
406 | } | 515 | } |
407 | 516 | ||
408 | void force_flush_all(void) | 517 | void force_flush_all(void) |
409 | { | 518 | { |
410 | CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas()); | 519 | struct mm_struct *mm = current->mm; |
411 | } | 520 | struct vm_area_struct *vma = mm->mmap; |
412 | 521 | ||
522 | while (vma != NULL) { | ||
523 | fix_range(mm, vma->vm_start, vma->vm_end, 1); | ||
524 | vma = vma->vm_next; | ||
525 | } | ||
526 | } | ||
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index 3850d53f79fd..bd060551e619 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c | |||
@@ -1,40 +1,24 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/kernel.h" | 6 | #include <linux/mm.h> |
7 | #include "asm/errno.h" | 7 | #include <linux/sched.h> |
8 | #include "linux/sched.h" | 8 | #include <linux/hardirq.h> |
9 | #include "linux/mm.h" | 9 | #include <asm/current.h> |
10 | #include "linux/spinlock.h" | 10 | #include <asm/pgtable.h> |
11 | #include "linux/init.h" | 11 | #include <asm/tlbflush.h> |
12 | #include "linux/ptrace.h" | ||
13 | #include "asm/semaphore.h" | ||
14 | #include "asm/pgtable.h" | ||
15 | #include "asm/pgalloc.h" | ||
16 | #include "asm/tlbflush.h" | ||
17 | #include "asm/a.out.h" | ||
18 | #include "asm/current.h" | ||
19 | #include "asm/irq.h" | ||
20 | #include "sysdep/sigcontext.h" | ||
21 | #include "kern_util.h" | ||
22 | #include "as-layout.h" | ||
23 | #include "arch.h" | 12 | #include "arch.h" |
24 | #include "kern.h" | 13 | #include "as-layout.h" |
25 | #include "chan_kern.h" | 14 | #include "kern_util.h" |
26 | #include "mconsole_kern.h" | ||
27 | #include "mem.h" | ||
28 | #include "mem_kern.h" | ||
29 | #include "sysdep/sigcontext.h" | ||
30 | #include "sysdep/ptrace.h" | ||
31 | #include "os.h" | ||
32 | #ifdef CONFIG_MODE_SKAS | ||
33 | #include "skas.h" | ||
34 | #endif | ||
35 | #include "os.h" | 15 | #include "os.h" |
16 | #include "sysdep/sigcontext.h" | ||
36 | 17 | ||
37 | /* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */ | 18 | /* |
19 | * Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by | ||
20 | * segv(). | ||
21 | */ | ||
38 | int handle_page_fault(unsigned long address, unsigned long ip, | 22 | int handle_page_fault(unsigned long address, unsigned long ip, |
39 | int is_write, int is_user, int *code_out) | 23 | int is_write, int is_user, int *code_out) |
40 | { | 24 | { |
@@ -48,31 +32,33 @@ int handle_page_fault(unsigned long address, unsigned long ip, | |||
48 | 32 | ||
49 | *code_out = SEGV_MAPERR; | 33 | *code_out = SEGV_MAPERR; |
50 | 34 | ||
51 | /* If the fault was during atomic operation, don't take the fault, just | 35 | /* |
52 | * fail. */ | 36 | * If the fault was during atomic operation, don't take the fault, just |
37 | * fail. | ||
38 | */ | ||
53 | if (in_atomic()) | 39 | if (in_atomic()) |
54 | goto out_nosemaphore; | 40 | goto out_nosemaphore; |
55 | 41 | ||
56 | down_read(&mm->mmap_sem); | 42 | down_read(&mm->mmap_sem); |
57 | vma = find_vma(mm, address); | 43 | vma = find_vma(mm, address); |
58 | if(!vma) | 44 | if (!vma) |
59 | goto out; | 45 | goto out; |
60 | else if(vma->vm_start <= address) | 46 | else if (vma->vm_start <= address) |
61 | goto good_area; | 47 | goto good_area; |
62 | else if(!(vma->vm_flags & VM_GROWSDOWN)) | 48 | else if (!(vma->vm_flags & VM_GROWSDOWN)) |
63 | goto out; | 49 | goto out; |
64 | else if(is_user && !ARCH_IS_STACKGROW(address)) | 50 | else if (is_user && !ARCH_IS_STACKGROW(address)) |
65 | goto out; | 51 | goto out; |
66 | else if(expand_stack(vma, address)) | 52 | else if (expand_stack(vma, address)) |
67 | goto out; | 53 | goto out; |
68 | 54 | ||
69 | good_area: | 55 | good_area: |
70 | *code_out = SEGV_ACCERR; | 56 | *code_out = SEGV_ACCERR; |
71 | if(is_write && !(vma->vm_flags & VM_WRITE)) | 57 | if (is_write && !(vma->vm_flags & VM_WRITE)) |
72 | goto out; | 58 | goto out; |
73 | 59 | ||
74 | /* Don't require VM_READ|VM_EXEC for write faults! */ | 60 | /* Don't require VM_READ|VM_EXEC for write faults! */ |
75 | if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC))) | 61 | if (!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC))) |
76 | goto out; | 62 | goto out; |
77 | 63 | ||
78 | do { | 64 | do { |
@@ -98,9 +84,10 @@ survive: | |||
98 | pud = pud_offset(pgd, address); | 84 | pud = pud_offset(pgd, address); |
99 | pmd = pmd_offset(pud, address); | 85 | pmd = pmd_offset(pud, address); |
100 | pte = pte_offset_kernel(pmd, address); | 86 | pte = pte_offset_kernel(pmd, address); |
101 | } while(!pte_present(*pte)); | 87 | } while (!pte_present(*pte)); |
102 | err = 0; | 88 | err = 0; |
103 | /* The below warning was added in place of | 89 | /* |
90 | * The below warning was added in place of | ||
104 | * pte_mkyoung(); if (is_write) pte_mkdirty(); | 91 | * pte_mkyoung(); if (is_write) pte_mkdirty(); |
105 | * If it's triggered, we'd see normally a hang here (a clean pte is | 92 | * If it's triggered, we'd see normally a hang here (a clean pte is |
106 | * marked read-only to emulate the dirty bit). | 93 | * marked read-only to emulate the dirty bit). |
@@ -114,7 +101,7 @@ survive: | |||
114 | out: | 101 | out: |
115 | up_read(&mm->mmap_sem); | 102 | up_read(&mm->mmap_sem); |
116 | out_nosemaphore: | 103 | out_nosemaphore: |
117 | return(err); | 104 | return err; |
118 | 105 | ||
119 | /* | 106 | /* |
120 | * We ran out of memory, or some other thing happened to us that made | 107 | * We ran out of memory, or some other thing happened to us that made |
@@ -141,11 +128,11 @@ static void bad_segv(struct faultinfo fi, unsigned long ip) | |||
141 | force_sig_info(SIGSEGV, &si, current); | 128 | force_sig_info(SIGSEGV, &si, current); |
142 | } | 129 | } |
143 | 130 | ||
144 | static void segv_handler(int sig, union uml_pt_regs *regs) | 131 | static void segv_handler(int sig, struct uml_pt_regs *regs) |
145 | { | 132 | { |
146 | struct faultinfo * fi = UPT_FAULTINFO(regs); | 133 | struct faultinfo * fi = UPT_FAULTINFO(regs); |
147 | 134 | ||
148 | if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){ | 135 | if (UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)) { |
149 | bad_segv(*fi, UPT_IP(regs)); | 136 | bad_segv(*fi, UPT_IP(regs)); |
150 | return; | 137 | return; |
151 | } | 138 | } |
@@ -159,45 +146,49 @@ static void segv_handler(int sig, union uml_pt_regs *regs) | |||
159 | * give us bad data! | 146 | * give us bad data! |
160 | */ | 147 | */ |
161 | unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, | 148 | unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, |
162 | union uml_pt_regs *regs) | 149 | struct uml_pt_regs *regs) |
163 | { | 150 | { |
164 | struct siginfo si; | 151 | struct siginfo si; |
165 | void *catcher; | 152 | jmp_buf *catcher; |
166 | int err; | 153 | int err; |
167 | int is_write = FAULT_WRITE(fi); | 154 | int is_write = FAULT_WRITE(fi); |
168 | unsigned long address = FAULT_ADDRESS(fi); | 155 | unsigned long address = FAULT_ADDRESS(fi); |
169 | 156 | ||
170 | if(!is_user && (address >= start_vm) && (address < end_vm)){ | 157 | if (!is_user && (address >= start_vm) && (address < end_vm)) { |
171 | flush_tlb_kernel_vm(); | 158 | flush_tlb_kernel_vm(); |
172 | return 0; | 159 | return 0; |
173 | } | 160 | } |
174 | else if(current->mm == NULL) { | 161 | else if (current->mm == NULL) { |
175 | show_regs(container_of(regs, struct pt_regs, regs)); | 162 | show_regs(container_of(regs, struct pt_regs, regs)); |
176 | panic("Segfault with no mm"); | 163 | panic("Segfault with no mm"); |
177 | } | 164 | } |
178 | 165 | ||
179 | if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi)) | 166 | if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi)) |
180 | err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); | 167 | err = handle_page_fault(address, ip, is_write, is_user, |
168 | &si.si_code); | ||
181 | else { | 169 | else { |
182 | err = -EFAULT; | 170 | err = -EFAULT; |
183 | /* A thread accessed NULL, we get a fault, but CR2 is invalid. | 171 | /* |
184 | * This code is used in __do_copy_from_user() of TT mode. */ | 172 | * A thread accessed NULL, we get a fault, but CR2 is invalid. |
173 | * This code is used in __do_copy_from_user() of TT mode. | ||
174 | * XXX tt mode is gone, so maybe this isn't needed any more | ||
175 | */ | ||
185 | address = 0; | 176 | address = 0; |
186 | } | 177 | } |
187 | 178 | ||
188 | catcher = current->thread.fault_catcher; | 179 | catcher = current->thread.fault_catcher; |
189 | if(!err) | 180 | if (!err) |
190 | return 0; | 181 | return 0; |
191 | else if(catcher != NULL){ | 182 | else if (catcher != NULL) { |
192 | current->thread.fault_addr = (void *) address; | 183 | current->thread.fault_addr = (void *) address; |
193 | do_longjmp(catcher, 1); | 184 | UML_LONGJMP(catcher, 1); |
194 | } | 185 | } |
195 | else if(current->thread.fault_addr != NULL) | 186 | else if (current->thread.fault_addr != NULL) |
196 | panic("fault_addr set but no fault catcher"); | 187 | panic("fault_addr set but no fault catcher"); |
197 | else if(!is_user && arch_fixup(ip, regs)) | 188 | else if (!is_user && arch_fixup(ip, regs)) |
198 | return 0; | 189 | return 0; |
199 | 190 | ||
200 | if(!is_user) { | 191 | if (!is_user) { |
201 | show_regs(container_of(regs, struct pt_regs, regs)); | 192 | show_regs(container_of(regs, struct pt_regs, regs)); |
202 | panic("Kernel mode fault at addr 0x%lx, ip 0x%lx", | 193 | panic("Kernel mode fault at addr 0x%lx, ip 0x%lx", |
203 | address, ip); | 194 | address, ip); |
@@ -211,7 +202,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, | |||
211 | current->thread.arch.faultinfo = fi; | 202 | current->thread.arch.faultinfo = fi; |
212 | force_sig_info(SIGBUS, &si, current); | 203 | force_sig_info(SIGBUS, &si, current); |
213 | } else if (err == -ENOMEM) { | 204 | } else if (err == -ENOMEM) { |
214 | printk("VM: killing process %s\n", current->comm); | 205 | printk(KERN_INFO "VM: killing process %s\n", current->comm); |
215 | do_exit(SIGKILL); | 206 | do_exit(SIGKILL); |
216 | } else { | 207 | } else { |
217 | BUG_ON(err != -EFAULT); | 208 | BUG_ON(err != -EFAULT); |
@@ -223,15 +214,15 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, | |||
223 | return 0; | 214 | return 0; |
224 | } | 215 | } |
225 | 216 | ||
226 | void relay_signal(int sig, union uml_pt_regs *regs) | 217 | void relay_signal(int sig, struct uml_pt_regs *regs) |
227 | { | 218 | { |
228 | if(arch_handle_signal(sig, regs)) | 219 | if (arch_handle_signal(sig, regs)) |
229 | return; | 220 | return; |
230 | 221 | ||
231 | if(!UPT_IS_USER(regs)){ | 222 | if (!UPT_IS_USER(regs)) { |
232 | if(sig == SIGBUS) | 223 | if (sig == SIGBUS) |
233 | printk("Bus error - the host /dev/shm or /tmp mount " | 224 | printk(KERN_ERR "Bus error - the host /dev/shm or /tmp " |
234 | "likely just ran out of space\n"); | 225 | "mount likely just ran out of space\n"); |
235 | panic("Kernel mode signal %d", sig); | 226 | panic("Kernel mode signal %d", sig); |
236 | } | 227 | } |
237 | 228 | ||
@@ -239,14 +230,14 @@ void relay_signal(int sig, union uml_pt_regs *regs) | |||
239 | force_sig(sig, current); | 230 | force_sig(sig, current); |
240 | } | 231 | } |
241 | 232 | ||
242 | static void bus_handler(int sig, union uml_pt_regs *regs) | 233 | static void bus_handler(int sig, struct uml_pt_regs *regs) |
243 | { | 234 | { |
244 | if(current->thread.fault_catcher != NULL) | 235 | if (current->thread.fault_catcher != NULL) |
245 | do_longjmp(current->thread.fault_catcher, 1); | 236 | UML_LONGJMP(current->thread.fault_catcher, 1); |
246 | else relay_signal(sig, regs); | 237 | else relay_signal(sig, regs); |
247 | } | 238 | } |
248 | 239 | ||
249 | static void winch(int sig, union uml_pt_regs *regs) | 240 | static void winch(int sig, struct uml_pt_regs *regs) |
250 | { | 241 | { |
251 | do_IRQ(WINCH_IRQ, regs); | 242 | do_IRQ(WINCH_IRQ, regs); |
252 | } | 243 | } |
diff --git a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile deleted file mode 100644 index 6939e5af8472..000000000000 --- a/arch/um/kernel/tt/Makefile +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | # | ||
2 | # Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) | ||
3 | # Licensed under the GPL | ||
4 | # | ||
5 | |||
6 | obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \ | ||
7 | syscall_kern.o syscall_user.o tlb.o tracer.o trap_user.o \ | ||
8 | uaccess.o uaccess_user.o | ||
9 | |||
10 | obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/ | ||
11 | |||
12 | USER_OBJS := gdb.o tracer.o | ||
13 | |||
14 | include arch/um/scripts/Makefile.rules | ||
diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c deleted file mode 100644 index 40126cb51801..000000000000 --- a/arch/um/kernel/tt/exec_kern.c +++ /dev/null | |||
@@ -1,84 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/kernel.h" | ||
7 | #include "linux/mm.h" | ||
8 | #include "asm/signal.h" | ||
9 | #include "asm/ptrace.h" | ||
10 | #include "asm/uaccess.h" | ||
11 | #include "asm/pgalloc.h" | ||
12 | #include "asm/tlbflush.h" | ||
13 | #include "kern_util.h" | ||
14 | #include "irq_user.h" | ||
15 | #include "mem_user.h" | ||
16 | #include "os.h" | ||
17 | #include "tlb.h" | ||
18 | #include "mode.h" | ||
19 | |||
20 | static int exec_tramp(void *sig_stack) | ||
21 | { | ||
22 | init_new_thread_stack(sig_stack, NULL); | ||
23 | init_new_thread_signals(); | ||
24 | os_stop_process(os_getpid()); | ||
25 | return(0); | ||
26 | } | ||
27 | |||
28 | void flush_thread_tt(void) | ||
29 | { | ||
30 | unsigned long stack; | ||
31 | int new_pid; | ||
32 | |||
33 | stack = alloc_stack(0, 0); | ||
34 | if(stack == 0){ | ||
35 | printk(KERN_ERR | ||
36 | "flush_thread : failed to allocate temporary stack\n"); | ||
37 | do_exit(SIGKILL); | ||
38 | } | ||
39 | |||
40 | new_pid = start_fork_tramp(task_stack_page(current), stack, 0, exec_tramp); | ||
41 | if(new_pid < 0){ | ||
42 | printk(KERN_ERR | ||
43 | "flush_thread : new thread failed, errno = %d\n", | ||
44 | -new_pid); | ||
45 | do_exit(SIGKILL); | ||
46 | } | ||
47 | |||
48 | if(current_thread->cpu == 0) | ||
49 | forward_interrupts(new_pid); | ||
50 | current->thread.request.op = OP_EXEC; | ||
51 | current->thread.request.u.exec.pid = new_pid; | ||
52 | unprotect_stack((unsigned long) current_thread); | ||
53 | os_usr1_process(os_getpid()); | ||
54 | change_sig(SIGUSR1, 1); | ||
55 | |||
56 | change_sig(SIGUSR1, 0); | ||
57 | enable_timer(); | ||
58 | free_page(stack); | ||
59 | protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); | ||
60 | stack_protections((unsigned long) current_thread); | ||
61 | force_flush_all(); | ||
62 | unblock_signals(); | ||
63 | } | ||
64 | |||
65 | void start_thread_tt(struct pt_regs *regs, unsigned long eip, | ||
66 | unsigned long esp) | ||
67 | { | ||
68 | set_fs(USER_DS); | ||
69 | flush_tlb_mm(current->mm); | ||
70 | PT_REGS_IP(regs) = eip; | ||
71 | PT_REGS_SP(regs) = esp; | ||
72 | PT_FIX_EXEC_STACK(esp); | ||
73 | } | ||
74 | |||
75 | /* | ||
76 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
77 | * Emacs will notice this stuff at the end of the file and automatically | ||
78 | * adjust the settings for this buffer only. This must remain at the end | ||
79 | * of the file. | ||
80 | * --------------------------------------------------------------------------- | ||
81 | * Local variables: | ||
82 | * c-file-style: "linux" | ||
83 | * End: | ||
84 | */ | ||
diff --git a/arch/um/kernel/tt/exec_user.c b/arch/um/kernel/tt/exec_user.c deleted file mode 100644 index 7b5f2181cf51..000000000000 --- a/arch/um/kernel/tt/exec_user.c +++ /dev/null | |||
@@ -1,56 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stdio.h> | ||
7 | #include <unistd.h> | ||
8 | #include <stdlib.h> | ||
9 | #include <sched.h> | ||
10 | #include <errno.h> | ||
11 | #include <sys/wait.h> | ||
12 | #include <signal.h> | ||
13 | #include "kern_util.h" | ||
14 | #include "user.h" | ||
15 | #include "ptrace_user.h" | ||
16 | #include "os.h" | ||
17 | |||
18 | void do_exec(int old_pid, int new_pid) | ||
19 | { | ||
20 | unsigned long regs[FRAME_SIZE]; | ||
21 | int err; | ||
22 | |||
23 | if((ptrace(PTRACE_ATTACH, new_pid, 0, 0) < 0) || | ||
24 | (ptrace(PTRACE_CONT, new_pid, 0, 0) < 0)) | ||
25 | tracer_panic("do_exec failed to attach proc - errno = %d", | ||
26 | errno); | ||
27 | |||
28 | CATCH_EINTR(err = waitpid(new_pid, 0, WUNTRACED)); | ||
29 | if (err < 0) | ||
30 | tracer_panic("do_exec failed to attach proc in waitpid - errno = %d", | ||
31 | errno); | ||
32 | |||
33 | if(ptrace_getregs(old_pid, regs) < 0) | ||
34 | tracer_panic("do_exec failed to get registers - errno = %d", | ||
35 | errno); | ||
36 | |||
37 | os_kill_ptraced_process(old_pid, 0); | ||
38 | |||
39 | if (ptrace(PTRACE_OLDSETOPTIONS, new_pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) | ||
40 | tracer_panic("do_exec: PTRACE_SETOPTIONS failed, errno = %d", errno); | ||
41 | |||
42 | if(ptrace_setregs(new_pid, regs) < 0) | ||
43 | tracer_panic("do_exec failed to start new proc - errno = %d", | ||
44 | errno); | ||
45 | } | ||
46 | |||
47 | /* | ||
48 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
49 | * Emacs will notice this stuff at the end of the file and automatically | ||
50 | * adjust the settings for this buffer only. This must remain at the end | ||
51 | * of the file. | ||
52 | * --------------------------------------------------------------------------- | ||
53 | * Local variables: | ||
54 | * c-file-style: "linux" | ||
55 | * End: | ||
56 | */ | ||
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c deleted file mode 100644 index 030e4658f36b..000000000000 --- a/arch/um/kernel/tt/gdb.c +++ /dev/null | |||
@@ -1,280 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stdio.h> | ||
7 | #include <stdlib.h> | ||
8 | #include <errno.h> | ||
9 | #include <string.h> | ||
10 | #include <signal.h> | ||
11 | #include <sys/types.h> | ||
12 | #include "ptrace_user.h" | ||
13 | #include "uml-config.h" | ||
14 | #include "kern_constants.h" | ||
15 | #include "chan_user.h" | ||
16 | #include "init.h" | ||
17 | #include "user.h" | ||
18 | #include "debug.h" | ||
19 | #include "kern_util.h" | ||
20 | #include "tt.h" | ||
21 | #include "sysdep/thread.h" | ||
22 | #include "os.h" | ||
23 | |||
24 | extern int debugger_pid; | ||
25 | extern int debugger_fd; | ||
26 | extern int debugger_parent; | ||
27 | |||
28 | int detach(int pid, int sig) | ||
29 | { | ||
30 | return(ptrace(PTRACE_DETACH, pid, 0, sig)); | ||
31 | } | ||
32 | |||
33 | int attach(int pid) | ||
34 | { | ||
35 | int err; | ||
36 | |||
37 | err = ptrace(PTRACE_ATTACH, pid, 0, 0); | ||
38 | if(err < 0) return(-errno); | ||
39 | else return(err); | ||
40 | } | ||
41 | |||
42 | int cont(int pid) | ||
43 | { | ||
44 | return(ptrace(PTRACE_CONT, pid, 0, 0)); | ||
45 | } | ||
46 | |||
47 | #ifdef UML_CONFIG_PT_PROXY | ||
48 | |||
49 | int debugger_signal(int status, pid_t pid) | ||
50 | { | ||
51 | return(debugger_proxy(status, pid)); | ||
52 | } | ||
53 | |||
54 | void child_signal(pid_t pid, int status) | ||
55 | { | ||
56 | child_proxy(pid, status); | ||
57 | } | ||
58 | |||
59 | static void gdb_announce(char *dev_name, int dev) | ||
60 | { | ||
61 | printf("gdb assigned device '%s'\n", dev_name); | ||
62 | } | ||
63 | |||
64 | static struct chan_opts opts = { | ||
65 | .announce = gdb_announce, | ||
66 | .xterm_title = "UML kernel debugger", | ||
67 | .raw = 0, | ||
68 | .tramp_stack = 0, | ||
69 | .in_kernel = 0, | ||
70 | }; | ||
71 | |||
72 | /* Accessed by the tracing thread, which automatically serializes access */ | ||
73 | static void *xterm_data; | ||
74 | static int xterm_fd; | ||
75 | |||
76 | extern void *xterm_init(char *, int, struct chan_opts *); | ||
77 | extern int xterm_open(int, int, int, void *, char **); | ||
78 | extern void xterm_close(int, void *); | ||
79 | |||
80 | int open_gdb_chan(void) | ||
81 | { | ||
82 | char stack[UM_KERN_PAGE_SIZE], *dummy; | ||
83 | |||
84 | opts.tramp_stack = (unsigned long) stack; | ||
85 | xterm_data = xterm_init("", 0, &opts); | ||
86 | xterm_fd = xterm_open(1, 1, 1, xterm_data, &dummy); | ||
87 | return(xterm_fd); | ||
88 | } | ||
89 | |||
90 | static void exit_debugger_cb(void *unused) | ||
91 | { | ||
92 | if(debugger_pid != -1){ | ||
93 | if(gdb_pid != -1){ | ||
94 | fake_child_exit(); | ||
95 | gdb_pid = -1; | ||
96 | } | ||
97 | else kill_child_dead(debugger_pid); | ||
98 | debugger_pid = -1; | ||
99 | if(debugger_parent != -1) | ||
100 | detach(debugger_parent, SIGINT); | ||
101 | } | ||
102 | if(xterm_data != NULL) xterm_close(xterm_fd, xterm_data); | ||
103 | } | ||
104 | |||
105 | static void exit_debugger(void) | ||
106 | { | ||
107 | initial_thread_cb(exit_debugger_cb, NULL); | ||
108 | } | ||
109 | |||
110 | __uml_exitcall(exit_debugger); | ||
111 | |||
112 | struct gdb_data { | ||
113 | char *str; | ||
114 | int err; | ||
115 | }; | ||
116 | |||
117 | extern char *linux_prog; | ||
118 | |||
119 | static void config_gdb_cb(void *arg) | ||
120 | { | ||
121 | struct gdb_data *data = arg; | ||
122 | void *task; | ||
123 | int pid; | ||
124 | |||
125 | data->err = -1; | ||
126 | if(debugger_pid != -1) exit_debugger_cb(NULL); | ||
127 | if(!strncmp(data->str, "pid,", strlen("pid,"))){ | ||
128 | data->str += strlen("pid,"); | ||
129 | pid = strtoul(data->str, NULL, 0); | ||
130 | task = cpu_tasks[0].task; | ||
131 | debugger_pid = attach_debugger(TASK_EXTERN_PID(task), pid, 0); | ||
132 | if(debugger_pid != -1){ | ||
133 | data->err = 0; | ||
134 | gdb_pid = pid; | ||
135 | } | ||
136 | return; | ||
137 | } | ||
138 | data->err = 0; | ||
139 | debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd); | ||
140 | init_proxy(debugger_pid, 0, 0); | ||
141 | } | ||
142 | |||
143 | int gdb_config(char *str, char **error_out) | ||
144 | { | ||
145 | struct gdb_data data; | ||
146 | |||
147 | if(*str++ != '=') return(-1); | ||
148 | data.str = str; | ||
149 | initial_thread_cb(config_gdb_cb, &data); | ||
150 | return(data.err); | ||
151 | } | ||
152 | |||
153 | void remove_gdb_cb(void *unused) | ||
154 | { | ||
155 | exit_debugger_cb(NULL); | ||
156 | } | ||
157 | |||
158 | int gdb_remove(int unused, char **error_out) | ||
159 | { | ||
160 | initial_thread_cb(remove_gdb_cb, NULL); | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | void signal_usr1(int sig) | ||
165 | { | ||
166 | if(debugger_pid != -1){ | ||
167 | printf("The debugger is already running\n"); | ||
168 | return; | ||
169 | } | ||
170 | debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd); | ||
171 | init_proxy(debugger_pid, 0, 0); | ||
172 | } | ||
173 | |||
174 | int init_ptrace_proxy(int idle_pid, int startup, int stop) | ||
175 | { | ||
176 | int pid, status; | ||
177 | |||
178 | pid = start_debugger(linux_prog, startup, stop, &debugger_fd); | ||
179 | status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL); | ||
180 | if(pid < 0){ | ||
181 | cont(idle_pid); | ||
182 | return(-1); | ||
183 | } | ||
184 | init_proxy(pid, 1, status); | ||
185 | return(pid); | ||
186 | } | ||
187 | |||
188 | int attach_debugger(int idle_pid, int pid, int stop) | ||
189 | { | ||
190 | int status = 0, err; | ||
191 | |||
192 | err = attach(pid); | ||
193 | if(err < 0){ | ||
194 | printf("Failed to attach pid %d, errno = %d\n", pid, -err); | ||
195 | return(-1); | ||
196 | } | ||
197 | if(stop) status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL); | ||
198 | init_proxy(pid, 1, status); | ||
199 | return(pid); | ||
200 | } | ||
201 | |||
202 | #ifdef notdef /* Put this back in when it does something useful */ | ||
203 | static int __init uml_gdb_init_setup(char *line, int *add) | ||
204 | { | ||
205 | gdb_init = uml_strdup(line); | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | __uml_setup("gdb=", uml_gdb_init_setup, | ||
210 | "gdb=<channel description>\n\n" | ||
211 | ); | ||
212 | #endif | ||
213 | |||
214 | static int __init uml_gdb_pid_setup(char *line, int *add) | ||
215 | { | ||
216 | gdb_pid = strtoul(line, NULL, 0); | ||
217 | *add = 0; | ||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | __uml_setup("gdb-pid=", uml_gdb_pid_setup, | ||
222 | "gdb-pid=<pid>\n" | ||
223 | " gdb-pid is used to attach an external debugger to UML. This may be\n" | ||
224 | " an already-running gdb or a debugger-like process like strace.\n\n" | ||
225 | ); | ||
226 | |||
227 | #else | ||
228 | |||
229 | int debugger_signal(int status, pid_t pid){ return(0); } | ||
230 | void child_signal(pid_t pid, int status){ } | ||
231 | int init_ptrace_proxy(int idle_pid, int startup, int stop) | ||
232 | { | ||
233 | printf("debug requested when CONFIG_PT_PROXY is off\n"); | ||
234 | kill_child_dead(idle_pid); | ||
235 | exit(1); | ||
236 | } | ||
237 | |||
238 | void signal_usr1(int sig) | ||
239 | { | ||
240 | printf("debug requested when CONFIG_PT_PROXY is off\n"); | ||
241 | } | ||
242 | |||
243 | int attach_debugger(int idle_pid, int pid, int stop) | ||
244 | { | ||
245 | printf("attach_debugger called when CONFIG_PT_PROXY " | ||
246 | "is off\n"); | ||
247 | return(-1); | ||
248 | } | ||
249 | |||
250 | int config_gdb(char *str) | ||
251 | { | ||
252 | return(-1); | ||
253 | } | ||
254 | |||
255 | int remove_gdb(void) | ||
256 | { | ||
257 | return(-1); | ||
258 | } | ||
259 | |||
260 | int init_parent_proxy(int pid) | ||
261 | { | ||
262 | return(-1); | ||
263 | } | ||
264 | |||
265 | void debugger_parent_signal(int status, int pid) | ||
266 | { | ||
267 | } | ||
268 | |||
269 | #endif | ||
270 | |||
271 | /* | ||
272 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
273 | * Emacs will notice this stuff at the end of the file and automatically | ||
274 | * adjust the settings for this buffer only. This must remain at the end | ||
275 | * of the file. | ||
276 | * --------------------------------------------------------------------------- | ||
277 | * Local variables: | ||
278 | * c-file-style: "linux" | ||
279 | * End: | ||
280 | */ | ||
diff --git a/arch/um/kernel/tt/gdb_kern.c b/arch/um/kernel/tt/gdb_kern.c deleted file mode 100644 index 03b06bc00771..000000000000 --- a/arch/um/kernel/tt/gdb_kern.c +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/init.h" | ||
7 | #include "mconsole_kern.h" | ||
8 | |||
9 | #ifdef CONFIG_MCONSOLE | ||
10 | |||
11 | extern int gdb_config(char *str, char **error_out); | ||
12 | extern int gdb_remove(int n, char **error_out); | ||
13 | |||
14 | static struct mc_device gdb_mc = { | ||
15 | .list = INIT_LIST_HEAD(gdb_mc.list), | ||
16 | .name = "gdb", | ||
17 | .config = gdb_config, | ||
18 | .remove = gdb_remove, | ||
19 | }; | ||
20 | |||
21 | int gdb_mc_init(void) | ||
22 | { | ||
23 | mconsole_register_dev(&gdb_mc); | ||
24 | return(0); | ||
25 | } | ||
26 | |||
27 | __initcall(gdb_mc_init); | ||
28 | |||
29 | #endif | ||
30 | |||
31 | /* | ||
32 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
33 | * Emacs will notice this stuff at the end of the file and automatically | ||
34 | * adjust the settings for this buffer only. This must remain at the end | ||
35 | * of the file. | ||
36 | * --------------------------------------------------------------------------- | ||
37 | * Local variables: | ||
38 | * c-file-style: "linux" | ||
39 | * End: | ||
40 | */ | ||
diff --git a/arch/um/kernel/tt/include/mode-tt.h b/arch/um/kernel/tt/include/mode-tt.h deleted file mode 100644 index e171e15fead5..000000000000 --- a/arch/um/kernel/tt/include/mode-tt.h +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __MODE_TT_H__ | ||
7 | #define __MODE_TT_H__ | ||
8 | |||
9 | #include "sysdep/ptrace.h" | ||
10 | |||
11 | enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB }; | ||
12 | |||
13 | extern int tracing_pid; | ||
14 | |||
15 | extern int tracer(int (*init_proc)(void *), void *sp); | ||
16 | extern void sig_handler_common_tt(int sig, void *sc); | ||
17 | extern void syscall_handler_tt(int sig, union uml_pt_regs *regs); | ||
18 | extern void reboot_tt(void); | ||
19 | extern void halt_tt(void); | ||
20 | extern int is_tracer_winch(int pid, int fd, void *data); | ||
21 | extern void kill_off_processes_tt(void); | ||
22 | |||
23 | #endif | ||
24 | |||
25 | /* | ||
26 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
27 | * Emacs will notice this stuff at the end of the file and automatically | ||
28 | * adjust the settings for this buffer only. This must remain at the end | ||
29 | * of the file. | ||
30 | * --------------------------------------------------------------------------- | ||
31 | * Local variables: | ||
32 | * c-file-style: "linux" | ||
33 | * End: | ||
34 | */ | ||
diff --git a/arch/um/kernel/tt/ksyms.c b/arch/um/kernel/tt/ksyms.c deleted file mode 100644 index 84a9385a8fef..000000000000 --- a/arch/um/kernel/tt/ksyms.c +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/module.h" | ||
7 | #include "asm/uaccess.h" | ||
8 | #include "mode.h" | ||
9 | |||
10 | EXPORT_SYMBOL(__do_copy_from_user); | ||
11 | EXPORT_SYMBOL(__do_copy_to_user); | ||
12 | EXPORT_SYMBOL(__do_strncpy_from_user); | ||
13 | EXPORT_SYMBOL(__do_strnlen_user); | ||
14 | EXPORT_SYMBOL(__do_clear_user); | ||
15 | EXPORT_SYMBOL(clear_user_tt); | ||
16 | |||
17 | EXPORT_SYMBOL(tracing_pid); | ||
18 | EXPORT_SYMBOL(honeypot); | ||
19 | |||
20 | /* | ||
21 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
22 | * Emacs will notice this stuff at the end of the file and automatically | ||
23 | * adjust the settings for this buffer only. This must remain at the end | ||
24 | * of the file. | ||
25 | * --------------------------------------------------------------------------- | ||
26 | * Local variables: | ||
27 | * c-file-style: "linux" | ||
28 | * End: | ||
29 | */ | ||
diff --git a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c deleted file mode 100644 index d0c3c4975f28..000000000000 --- a/arch/um/kernel/tt/mem.c +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/stddef.h" | ||
7 | #include "linux/mm.h" | ||
8 | #include "asm/uaccess.h" | ||
9 | #include "mem_user.h" | ||
10 | #include "kern_util.h" | ||
11 | #include "kern.h" | ||
12 | #include "tt.h" | ||
13 | |||
14 | void before_mem_tt(unsigned long brk_start) | ||
15 | { | ||
16 | if(debug) | ||
17 | remap_data(UML_ROUND_DOWN(&_stext), UML_ROUND_UP(&_etext), 1); | ||
18 | remap_data(UML_ROUND_DOWN(&_sdata), UML_ROUND_UP(&_edata), 1); | ||
19 | remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1); | ||
20 | } | ||
21 | |||
22 | #define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000) | ||
23 | #define START (CONFIG_TOP_ADDR - SIZE) | ||
24 | |||
25 | unsigned long set_task_sizes_tt(unsigned long *task_size_out) | ||
26 | { | ||
27 | unsigned long host_task_size; | ||
28 | |||
29 | /* Round up to the nearest 4M */ | ||
30 | host_task_size = ROUND_4M((unsigned long) &host_task_size); | ||
31 | *task_size_out = START; | ||
32 | |||
33 | return host_task_size; | ||
34 | } | ||
diff --git a/arch/um/kernel/tt/mem_user.c b/arch/um/kernel/tt/mem_user.c deleted file mode 100644 index 9774f6360c32..000000000000 --- a/arch/um/kernel/tt/mem_user.c +++ /dev/null | |||
@@ -1,49 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stdlib.h> | ||
7 | #include <stdio.h> | ||
8 | #include <unistd.h> | ||
9 | #include <string.h> | ||
10 | #include <errno.h> | ||
11 | #include <sys/mman.h> | ||
12 | #include "tt.h" | ||
13 | #include "mem_user.h" | ||
14 | #include "os.h" | ||
15 | |||
16 | void remap_data(void *segment_start, void *segment_end, int w) | ||
17 | { | ||
18 | void *addr; | ||
19 | unsigned long size; | ||
20 | int data, prot; | ||
21 | |||
22 | if(w) prot = PROT_WRITE; | ||
23 | else prot = 0; | ||
24 | prot |= PROT_READ | PROT_EXEC; | ||
25 | size = (unsigned long) segment_end - | ||
26 | (unsigned long) segment_start; | ||
27 | data = create_mem_file(size); | ||
28 | addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, data, 0); | ||
29 | if(addr == MAP_FAILED){ | ||
30 | perror("mapping new data segment"); | ||
31 | exit(1); | ||
32 | } | ||
33 | memcpy(addr, segment_start, size); | ||
34 | if(switcheroo(data, prot, addr, segment_start, size) < 0){ | ||
35 | printf("switcheroo failed\n"); | ||
36 | exit(1); | ||
37 | } | ||
38 | } | ||
39 | |||
40 | /* | ||
41 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
42 | * Emacs will notice this stuff at the end of the file and automatically | ||
43 | * adjust the settings for this buffer only. This must remain at the end | ||
44 | * of the file. | ||
45 | * --------------------------------------------------------------------------- | ||
46 | * Local variables: | ||
47 | * c-file-style: "linux" | ||
48 | * End: | ||
49 | */ | ||
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c deleted file mode 100644 index 74347adf81bf..000000000000 --- a/arch/um/kernel/tt/process_kern.c +++ /dev/null | |||
@@ -1,461 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/sched.h" | ||
7 | #include "linux/signal.h" | ||
8 | #include "linux/kernel.h" | ||
9 | #include "linux/interrupt.h" | ||
10 | #include "linux/ptrace.h" | ||
11 | #include "asm/system.h" | ||
12 | #include "asm/pgalloc.h" | ||
13 | #include "asm/ptrace.h" | ||
14 | #include "asm/tlbflush.h" | ||
15 | #include "irq_user.h" | ||
16 | #include "kern_util.h" | ||
17 | #include "os.h" | ||
18 | #include "kern.h" | ||
19 | #include "sigcontext.h" | ||
20 | #include "mem_user.h" | ||
21 | #include "tlb.h" | ||
22 | #include "mode.h" | ||
23 | #include "mode_kern.h" | ||
24 | #include "init.h" | ||
25 | #include "tt.h" | ||
26 | |||
27 | void switch_to_tt(void *prev, void *next) | ||
28 | { | ||
29 | struct task_struct *from, *to, *prev_sched; | ||
30 | unsigned long flags; | ||
31 | int err, vtalrm, alrm, prof, cpu; | ||
32 | char c; | ||
33 | |||
34 | from = prev; | ||
35 | to = next; | ||
36 | |||
37 | cpu = task_thread_info(from)->cpu; | ||
38 | if(cpu == 0) | ||
39 | forward_interrupts(to->thread.mode.tt.extern_pid); | ||
40 | #ifdef CONFIG_SMP | ||
41 | forward_ipi(cpu_data[cpu].ipi_pipe[0], to->thread.mode.tt.extern_pid); | ||
42 | #endif | ||
43 | local_irq_save(flags); | ||
44 | |||
45 | vtalrm = change_sig(SIGVTALRM, 0); | ||
46 | alrm = change_sig(SIGALRM, 0); | ||
47 | prof = change_sig(SIGPROF, 0); | ||
48 | |||
49 | forward_pending_sigio(to->thread.mode.tt.extern_pid); | ||
50 | |||
51 | c = 0; | ||
52 | |||
53 | /* Notice that here we "up" the semaphore on which "to" is waiting, and | ||
54 | * below (the read) we wait on this semaphore (which is implemented by | ||
55 | * switch_pipe) and go sleeping. Thus, after that, we have resumed in | ||
56 | * "to", and can't use any more the value of "from" (which is outdated), | ||
57 | * nor the value in "to" (since it was the task which stole us the CPU, | ||
58 | * which we don't care about). */ | ||
59 | |||
60 | err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c)); | ||
61 | if(err != sizeof(c)) | ||
62 | panic("write of switch_pipe failed, err = %d", -err); | ||
63 | |||
64 | if(from->thread.mode.tt.switch_pipe[0] == -1) | ||
65 | os_kill_process(os_getpid(), 0); | ||
66 | |||
67 | err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, | ||
68 | sizeof(c)); | ||
69 | if(err != sizeof(c)) | ||
70 | panic("read of switch_pipe failed, errno = %d", -err); | ||
71 | |||
72 | /* If the process that we have just scheduled away from has exited, | ||
73 | * then it needs to be killed here. The reason is that, even though | ||
74 | * it will kill itself when it next runs, that may be too late. Its | ||
75 | * stack will be freed, possibly before then, and if that happens, | ||
76 | * we have a use-after-free situation. So, it gets killed here | ||
77 | * in case it has not already killed itself. | ||
78 | */ | ||
79 | prev_sched = current->thread.prev_sched; | ||
80 | if(prev_sched->thread.mode.tt.switch_pipe[0] == -1) | ||
81 | os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1); | ||
82 | |||
83 | change_sig(SIGVTALRM, vtalrm); | ||
84 | change_sig(SIGALRM, alrm); | ||
85 | change_sig(SIGPROF, prof); | ||
86 | |||
87 | arch_switch_to_tt(prev_sched, current); | ||
88 | |||
89 | flush_tlb_all(); | ||
90 | local_irq_restore(flags); | ||
91 | } | ||
92 | |||
93 | void release_thread_tt(struct task_struct *task) | ||
94 | { | ||
95 | int pid = task->thread.mode.tt.extern_pid; | ||
96 | |||
97 | /* | ||
98 | * We first have to kill the other process, before | ||
99 | * closing its switch_pipe. Else it might wake up | ||
100 | * and receive "EOF" before we could kill it. | ||
101 | */ | ||
102 | if(os_getpid() != pid) | ||
103 | os_kill_process(pid, 0); | ||
104 | |||
105 | os_close_file(task->thread.mode.tt.switch_pipe[0]); | ||
106 | os_close_file(task->thread.mode.tt.switch_pipe[1]); | ||
107 | /* use switch_pipe as flag: thread is released */ | ||
108 | task->thread.mode.tt.switch_pipe[0] = -1; | ||
109 | } | ||
110 | |||
111 | void suspend_new_thread(int fd) | ||
112 | { | ||
113 | int err; | ||
114 | char c; | ||
115 | |||
116 | os_stop_process(os_getpid()); | ||
117 | err = os_read_file(fd, &c, sizeof(c)); | ||
118 | if(err != sizeof(c)) | ||
119 | panic("read failed in suspend_new_thread, err = %d", -err); | ||
120 | } | ||
121 | |||
122 | void schedule_tail(struct task_struct *prev); | ||
123 | |||
124 | static void new_thread_handler(int sig) | ||
125 | { | ||
126 | unsigned long disable; | ||
127 | int (*fn)(void *); | ||
128 | void *arg; | ||
129 | |||
130 | fn = current->thread.request.u.thread.proc; | ||
131 | arg = current->thread.request.u.thread.arg; | ||
132 | |||
133 | UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); | ||
134 | disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) | | ||
135 | (1 << (SIGIO - 1)) | (1 << (SIGPROF - 1)); | ||
136 | SC_SIGMASK(UPT_SC(¤t->thread.regs.regs)) &= ~disable; | ||
137 | |||
138 | suspend_new_thread(current->thread.mode.tt.switch_pipe[0]); | ||
139 | |||
140 | force_flush_all(); | ||
141 | if(current->thread.prev_sched != NULL) | ||
142 | schedule_tail(current->thread.prev_sched); | ||
143 | current->thread.prev_sched = NULL; | ||
144 | |||
145 | init_new_thread_signals(); | ||
146 | enable_timer(); | ||
147 | free_page(current->thread.temp_stack); | ||
148 | set_cmdline("(kernel thread)"); | ||
149 | |||
150 | change_sig(SIGUSR1, 1); | ||
151 | change_sig(SIGPROF, 1); | ||
152 | local_irq_enable(); | ||
153 | if(!run_kernel_thread(fn, arg, ¤t->thread.exec_buf)) | ||
154 | do_exit(0); | ||
155 | |||
156 | /* XXX No set_user_mode here because a newly execed process will | ||
157 | * immediately segfault on its non-existent IP, coming straight back | ||
158 | * to the signal handler, which will call set_user_mode on its way | ||
159 | * out. This should probably change since it's confusing. | ||
160 | */ | ||
161 | } | ||
162 | |||
163 | static int new_thread_proc(void *stack) | ||
164 | { | ||
165 | /* local_irq_disable is needed to block out signals until this thread is | ||
166 | * properly scheduled. Otherwise, the tracing thread will get mighty | ||
167 | * upset about any signals that arrive before that. | ||
168 | * This has the complication that it sets the saved signal mask in | ||
169 | * the sigcontext to block signals. This gets restored when this | ||
170 | * thread (or a descendant, since they get a copy of this sigcontext) | ||
171 | * returns to userspace. | ||
172 | * So, this is compensated for elsewhere. | ||
173 | * XXX There is still a small window until local_irq_disable() actually | ||
174 | * finishes where signals are possible - shouldn't be a problem in | ||
175 | * practice since SIGIO hasn't been forwarded here yet, and the | ||
176 | * local_irq_disable should finish before a SIGVTALRM has time to be | ||
177 | * delivered. | ||
178 | */ | ||
179 | |||
180 | local_irq_disable(); | ||
181 | init_new_thread_stack(stack, new_thread_handler); | ||
182 | os_usr1_process(os_getpid()); | ||
183 | change_sig(SIGUSR1, 1); | ||
184 | return(0); | ||
185 | } | ||
186 | |||
187 | /* Signal masking - signals are blocked at the start of fork_tramp. They | ||
188 | * are re-enabled when finish_fork_handler is entered by fork_tramp hitting | ||
189 | * itself with a SIGUSR1. set_user_mode has to be run with SIGUSR1 off, | ||
190 | * so it is blocked before it's called. They are re-enabled on sigreturn | ||
191 | * despite the fact that they were blocked when the SIGUSR1 was issued because | ||
192 | * copy_thread copies the parent's sigcontext, including the signal mask | ||
193 | * onto the signal frame. | ||
194 | */ | ||
195 | |||
196 | void finish_fork_handler(int sig) | ||
197 | { | ||
198 | UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); | ||
199 | suspend_new_thread(current->thread.mode.tt.switch_pipe[0]); | ||
200 | |||
201 | force_flush_all(); | ||
202 | if(current->thread.prev_sched != NULL) | ||
203 | schedule_tail(current->thread.prev_sched); | ||
204 | current->thread.prev_sched = NULL; | ||
205 | |||
206 | enable_timer(); | ||
207 | change_sig(SIGVTALRM, 1); | ||
208 | local_irq_enable(); | ||
209 | if(current->mm != current->parent->mm) | ||
210 | protect_memory(uml_reserved, high_physmem - uml_reserved, 1, | ||
211 | 1, 0, 1); | ||
212 | stack_protections((unsigned long) current_thread); | ||
213 | |||
214 | free_page(current->thread.temp_stack); | ||
215 | local_irq_disable(); | ||
216 | change_sig(SIGUSR1, 0); | ||
217 | set_user_mode(current); | ||
218 | } | ||
219 | |||
220 | int fork_tramp(void *stack) | ||
221 | { | ||
222 | local_irq_disable(); | ||
223 | arch_init_thread(); | ||
224 | init_new_thread_stack(stack, finish_fork_handler); | ||
225 | |||
226 | os_usr1_process(os_getpid()); | ||
227 | change_sig(SIGUSR1, 1); | ||
228 | return(0); | ||
229 | } | ||
230 | |||
231 | int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, | ||
232 | unsigned long stack_top, struct task_struct * p, | ||
233 | struct pt_regs *regs) | ||
234 | { | ||
235 | int (*tramp)(void *); | ||
236 | int new_pid, err; | ||
237 | unsigned long stack; | ||
238 | |||
239 | if(current->thread.forking) | ||
240 | tramp = fork_tramp; | ||
241 | else { | ||
242 | tramp = new_thread_proc; | ||
243 | p->thread.request.u.thread = current->thread.request.u.thread; | ||
244 | } | ||
245 | |||
246 | err = os_pipe(p->thread.mode.tt.switch_pipe, 1, 1); | ||
247 | if(err < 0){ | ||
248 | printk("copy_thread : pipe failed, err = %d\n", -err); | ||
249 | return(err); | ||
250 | } | ||
251 | |||
252 | stack = alloc_stack(0, 0); | ||
253 | if(stack == 0){ | ||
254 | printk(KERN_ERR "copy_thread : failed to allocate " | ||
255 | "temporary stack\n"); | ||
256 | return(-ENOMEM); | ||
257 | } | ||
258 | |||
259 | clone_flags &= CLONE_VM; | ||
260 | p->thread.temp_stack = stack; | ||
261 | new_pid = start_fork_tramp(task_stack_page(p), stack, clone_flags, tramp); | ||
262 | if(new_pid < 0){ | ||
263 | printk(KERN_ERR "copy_thread : clone failed - errno = %d\n", | ||
264 | -new_pid); | ||
265 | return(new_pid); | ||
266 | } | ||
267 | |||
268 | if(current->thread.forking){ | ||
269 | sc_to_sc(UPT_SC(&p->thread.regs.regs), UPT_SC(®s->regs)); | ||
270 | SC_SET_SYSCALL_RETURN(UPT_SC(&p->thread.regs.regs), 0); | ||
271 | if(sp != 0) | ||
272 | SC_SP(UPT_SC(&p->thread.regs.regs)) = sp; | ||
273 | } | ||
274 | p->thread.mode.tt.extern_pid = new_pid; | ||
275 | |||
276 | current->thread.request.op = OP_FORK; | ||
277 | current->thread.request.u.fork.pid = new_pid; | ||
278 | os_usr1_process(os_getpid()); | ||
279 | |||
280 | /* Enable the signal and then disable it to ensure that it is handled | ||
281 | * here, and nowhere else. | ||
282 | */ | ||
283 | change_sig(SIGUSR1, 1); | ||
284 | |||
285 | change_sig(SIGUSR1, 0); | ||
286 | err = 0; | ||
287 | return(err); | ||
288 | } | ||
289 | |||
290 | void reboot_tt(void) | ||
291 | { | ||
292 | current->thread.request.op = OP_REBOOT; | ||
293 | os_usr1_process(os_getpid()); | ||
294 | change_sig(SIGUSR1, 1); | ||
295 | } | ||
296 | |||
297 | void halt_tt(void) | ||
298 | { | ||
299 | current->thread.request.op = OP_HALT; | ||
300 | os_usr1_process(os_getpid()); | ||
301 | change_sig(SIGUSR1, 1); | ||
302 | } | ||
303 | |||
304 | void kill_off_processes_tt(void) | ||
305 | { | ||
306 | struct task_struct *p; | ||
307 | int me; | ||
308 | |||
309 | me = os_getpid(); | ||
310 | for_each_process(p){ | ||
311 | if(p->thread.mode.tt.extern_pid != me) | ||
312 | os_kill_process(p->thread.mode.tt.extern_pid, 0); | ||
313 | } | ||
314 | if(init_task.thread.mode.tt.extern_pid != me) | ||
315 | os_kill_process(init_task.thread.mode.tt.extern_pid, 0); | ||
316 | } | ||
317 | |||
318 | void initial_thread_cb_tt(void (*proc)(void *), void *arg) | ||
319 | { | ||
320 | if(os_getpid() == tracing_pid){ | ||
321 | (*proc)(arg); | ||
322 | } | ||
323 | else { | ||
324 | current->thread.request.op = OP_CB; | ||
325 | current->thread.request.u.cb.proc = proc; | ||
326 | current->thread.request.u.cb.arg = arg; | ||
327 | os_usr1_process(os_getpid()); | ||
328 | change_sig(SIGUSR1, 1); | ||
329 | |||
330 | change_sig(SIGUSR1, 0); | ||
331 | } | ||
332 | } | ||
333 | |||
334 | int do_proc_op(void *t, int proc_id) | ||
335 | { | ||
336 | struct task_struct *task; | ||
337 | struct thread_struct *thread; | ||
338 | int op, pid; | ||
339 | |||
340 | task = t; | ||
341 | thread = &task->thread; | ||
342 | op = thread->request.op; | ||
343 | switch(op){ | ||
344 | case OP_NONE: | ||
345 | case OP_TRACE_ON: | ||
346 | break; | ||
347 | case OP_EXEC: | ||
348 | pid = thread->request.u.exec.pid; | ||
349 | do_exec(thread->mode.tt.extern_pid, pid); | ||
350 | thread->mode.tt.extern_pid = pid; | ||
351 | cpu_tasks[task_thread_info(task)->cpu].pid = pid; | ||
352 | break; | ||
353 | case OP_FORK: | ||
354 | attach_process(thread->request.u.fork.pid); | ||
355 | break; | ||
356 | case OP_CB: | ||
357 | (*thread->request.u.cb.proc)(thread->request.u.cb.arg); | ||
358 | break; | ||
359 | case OP_REBOOT: | ||
360 | case OP_HALT: | ||
361 | break; | ||
362 | default: | ||
363 | tracer_panic("Bad op in do_proc_op"); | ||
364 | break; | ||
365 | } | ||
366 | thread->request.op = OP_NONE; | ||
367 | return(op); | ||
368 | } | ||
369 | |||
370 | void init_idle_tt(void) | ||
371 | { | ||
372 | default_idle(); | ||
373 | } | ||
374 | |||
375 | extern void start_kernel(void); | ||
376 | |||
377 | static int start_kernel_proc(void *unused) | ||
378 | { | ||
379 | int pid; | ||
380 | |||
381 | block_signals(); | ||
382 | pid = os_getpid(); | ||
383 | |||
384 | cpu_tasks[0].pid = pid; | ||
385 | cpu_tasks[0].task = current; | ||
386 | #ifdef CONFIG_SMP | ||
387 | cpu_online_map = cpumask_of_cpu(0); | ||
388 | #endif | ||
389 | if(debug) os_stop_process(pid); | ||
390 | start_kernel(); | ||
391 | return(0); | ||
392 | } | ||
393 | |||
394 | void set_tracing(void *task, int tracing) | ||
395 | { | ||
396 | ((struct task_struct *) task)->thread.mode.tt.tracing = tracing; | ||
397 | } | ||
398 | |||
399 | int is_tracing(void *t) | ||
400 | { | ||
401 | return (((struct task_struct *) t)->thread.mode.tt.tracing); | ||
402 | } | ||
403 | |||
404 | int set_user_mode(void *t) | ||
405 | { | ||
406 | struct task_struct *task; | ||
407 | |||
408 | task = t ? t : current; | ||
409 | if(task->thread.mode.tt.tracing) | ||
410 | return(1); | ||
411 | task->thread.request.op = OP_TRACE_ON; | ||
412 | os_usr1_process(os_getpid()); | ||
413 | return(0); | ||
414 | } | ||
415 | |||
416 | void set_init_pid(int pid) | ||
417 | { | ||
418 | int err; | ||
419 | |||
420 | init_task.thread.mode.tt.extern_pid = pid; | ||
421 | err = os_pipe(init_task.thread.mode.tt.switch_pipe, 1, 1); | ||
422 | if(err) | ||
423 | panic("Can't create switch pipe for init_task, errno = %d", | ||
424 | -err); | ||
425 | } | ||
426 | |||
427 | int start_uml_tt(void) | ||
428 | { | ||
429 | void *sp; | ||
430 | int pages; | ||
431 | |||
432 | pages = (1 << CONFIG_KERNEL_STACK_ORDER); | ||
433 | sp = task_stack_page(&init_task) + | ||
434 | pages * PAGE_SIZE - sizeof(unsigned long); | ||
435 | return(tracer(start_kernel_proc, sp)); | ||
436 | } | ||
437 | |||
438 | int external_pid_tt(struct task_struct *task) | ||
439 | { | ||
440 | return(task->thread.mode.tt.extern_pid); | ||
441 | } | ||
442 | |||
443 | int thread_pid_tt(struct task_struct *task) | ||
444 | { | ||
445 | return(task->thread.mode.tt.extern_pid); | ||
446 | } | ||
447 | |||
448 | int is_valid_pid(int pid) | ||
449 | { | ||
450 | struct task_struct *task; | ||
451 | |||
452 | read_lock(&tasklist_lock); | ||
453 | for_each_process(task){ | ||
454 | if(task->thread.mode.tt.extern_pid == pid){ | ||
455 | read_unlock(&tasklist_lock); | ||
456 | return(1); | ||
457 | } | ||
458 | } | ||
459 | read_unlock(&tasklist_lock); | ||
460 | return(0); | ||
461 | } | ||
diff --git a/arch/um/kernel/tt/ptproxy/Makefile b/arch/um/kernel/tt/ptproxy/Makefile deleted file mode 100644 index 3ad5b774de59..000000000000 --- a/arch/um/kernel/tt/ptproxy/Makefile +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | # | ||
2 | # Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | # Licensed under the GPL | ||
4 | # | ||
5 | |||
6 | obj-y = proxy.o ptrace.o sysdep.o wait.o | ||
7 | |||
8 | USER_OBJS := $(obj-y) | ||
9 | |||
10 | include arch/um/scripts/Makefile.rules | ||
diff --git a/arch/um/kernel/tt/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c deleted file mode 100644 index 420c23f311f3..000000000000 --- a/arch/um/kernel/tt/ptproxy/proxy.c +++ /dev/null | |||
@@ -1,377 +0,0 @@ | |||
1 | /********************************************************************** | ||
2 | proxy.c | ||
3 | |||
4 | Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing | ||
5 | terms and conditions. | ||
6 | |||
7 | Jeff Dike (jdike@karaya.com) : Modified for integration into uml | ||
8 | **********************************************************************/ | ||
9 | |||
10 | /* XXX This file shouldn't refer to CONFIG_* */ | ||
11 | |||
12 | #include <errno.h> | ||
13 | #include <stdio.h> | ||
14 | #include <stdlib.h> | ||
15 | #include <unistd.h> | ||
16 | #include <signal.h> | ||
17 | #include <string.h> | ||
18 | #include <termios.h> | ||
19 | #include <sys/wait.h> | ||
20 | #include <sys/types.h> | ||
21 | #include <sys/ioctl.h> | ||
22 | #include <asm/unistd.h> | ||
23 | #include "ptrace_user.h" | ||
24 | |||
25 | #include "ptproxy.h" | ||
26 | #include "sysdep.h" | ||
27 | #include "wait.h" | ||
28 | |||
29 | #include "user.h" | ||
30 | #include "os.h" | ||
31 | #include "tempfile.h" | ||
32 | |||
33 | static int debugger_wait(debugger_state *debugger, int *status, int options, | ||
34 | int (*syscall)(debugger_state *debugger, pid_t child), | ||
35 | int (*normal_return)(debugger_state *debugger, | ||
36 | pid_t unused), | ||
37 | int (*wait_return)(debugger_state *debugger, | ||
38 | pid_t unused)) | ||
39 | { | ||
40 | if(debugger->real_wait){ | ||
41 | debugger->handle_trace = normal_return; | ||
42 | syscall_continue(debugger->pid); | ||
43 | debugger->real_wait = 0; | ||
44 | return(1); | ||
45 | } | ||
46 | debugger->wait_status_ptr = status; | ||
47 | debugger->wait_options = options; | ||
48 | if((debugger->debugee != NULL) && debugger->debugee->event){ | ||
49 | syscall_continue(debugger->pid); | ||
50 | wait_for_stop(debugger->pid, SIGTRAP, PTRACE_SYSCALL, | ||
51 | NULL); | ||
52 | (*wait_return)(debugger, -1); | ||
53 | return(0); | ||
54 | } | ||
55 | else if(debugger->wait_options & WNOHANG){ | ||
56 | syscall_cancel(debugger->pid, 0); | ||
57 | debugger->handle_trace = syscall; | ||
58 | return(0); | ||
59 | } | ||
60 | else { | ||
61 | syscall_pause(debugger->pid); | ||
62 | debugger->handle_trace = wait_return; | ||
63 | debugger->waiting = 1; | ||
64 | } | ||
65 | return(1); | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * Handle debugger trap, i.e. syscall. | ||
70 | */ | ||
71 | |||
72 | int debugger_syscall(debugger_state *debugger, pid_t child) | ||
73 | { | ||
74 | long arg1, arg2, arg3, arg4, arg5, result; | ||
75 | int syscall, ret = 0; | ||
76 | |||
77 | syscall = get_syscall(debugger->pid, &arg1, &arg2, &arg3, &arg4, | ||
78 | &arg5); | ||
79 | |||
80 | switch(syscall){ | ||
81 | case __NR_execve: | ||
82 | /* execve never returns */ | ||
83 | debugger->handle_trace = debugger_syscall; | ||
84 | break; | ||
85 | |||
86 | case __NR_ptrace: | ||
87 | if(debugger->debugee->pid != 0) arg2 = debugger->debugee->pid; | ||
88 | if(!debugger->debugee->in_context) | ||
89 | child = debugger->debugee->pid; | ||
90 | result = proxy_ptrace(debugger, arg1, arg2, arg3, arg4, child, | ||
91 | &ret); | ||
92 | syscall_cancel(debugger->pid, result); | ||
93 | debugger->handle_trace = debugger_syscall; | ||
94 | return(ret); | ||
95 | |||
96 | #ifdef __NR_waitpid | ||
97 | case __NR_waitpid: | ||
98 | #endif | ||
99 | case __NR_wait4: | ||
100 | if(!debugger_wait(debugger, (int *) arg2, arg3, | ||
101 | debugger_syscall, debugger_normal_return, | ||
102 | proxy_wait_return)) | ||
103 | return(0); | ||
104 | break; | ||
105 | |||
106 | case __NR_kill: | ||
107 | if(!debugger->debugee->in_context) | ||
108 | child = debugger->debugee->pid; | ||
109 | if(arg1 == debugger->debugee->pid){ | ||
110 | result = kill(child, arg2); | ||
111 | syscall_cancel(debugger->pid, result); | ||
112 | debugger->handle_trace = debugger_syscall; | ||
113 | return(0); | ||
114 | } | ||
115 | else debugger->handle_trace = debugger_normal_return; | ||
116 | break; | ||
117 | |||
118 | default: | ||
119 | debugger->handle_trace = debugger_normal_return; | ||
120 | } | ||
121 | |||
122 | syscall_continue(debugger->pid); | ||
123 | return(0); | ||
124 | } | ||
125 | |||
126 | /* Used by the tracing thread */ | ||
127 | static debugger_state parent; | ||
128 | static int parent_syscall(debugger_state *debugger, int pid); | ||
129 | |||
130 | int init_parent_proxy(int pid) | ||
131 | { | ||
132 | parent = ((debugger_state) { .pid = pid, | ||
133 | .wait_options = 0, | ||
134 | .wait_status_ptr = NULL, | ||
135 | .waiting = 0, | ||
136 | .real_wait = 0, | ||
137 | .expecting_child = 0, | ||
138 | .handle_trace = parent_syscall, | ||
139 | .debugee = NULL } ); | ||
140 | return(0); | ||
141 | } | ||
142 | |||
143 | int parent_normal_return(debugger_state *debugger, pid_t unused) | ||
144 | { | ||
145 | debugger->handle_trace = parent_syscall; | ||
146 | syscall_continue(debugger->pid); | ||
147 | return(0); | ||
148 | } | ||
149 | |||
150 | static int parent_syscall(debugger_state *debugger, int pid) | ||
151 | { | ||
152 | long arg1, arg2, arg3, arg4, arg5; | ||
153 | int syscall; | ||
154 | |||
155 | syscall = get_syscall(pid, &arg1, &arg2, &arg3, &arg4, &arg5); | ||
156 | |||
157 | if((syscall == __NR_wait4) | ||
158 | #ifdef __NR_waitpid | ||
159 | || (syscall == __NR_waitpid) | ||
160 | #endif | ||
161 | ){ | ||
162 | debugger_wait(&parent, (int *) arg2, arg3, parent_syscall, | ||
163 | parent_normal_return, parent_wait_return); | ||
164 | } | ||
165 | else ptrace(PTRACE_SYSCALL, pid, 0, 0); | ||
166 | return(0); | ||
167 | } | ||
168 | |||
169 | int debugger_normal_return(debugger_state *debugger, pid_t unused) | ||
170 | { | ||
171 | debugger->handle_trace = debugger_syscall; | ||
172 | syscall_continue(debugger->pid); | ||
173 | return(0); | ||
174 | } | ||
175 | |||
176 | void debugger_cancelled_return(debugger_state *debugger, int result) | ||
177 | { | ||
178 | debugger->handle_trace = debugger_syscall; | ||
179 | syscall_set_result(debugger->pid, result); | ||
180 | syscall_continue(debugger->pid); | ||
181 | } | ||
182 | |||
183 | /* Used by the tracing thread */ | ||
184 | static debugger_state debugger; | ||
185 | static debugee_state debugee; | ||
186 | |||
187 | void init_proxy (pid_t debugger_pid, int stopped, int status) | ||
188 | { | ||
189 | debugger.pid = debugger_pid; | ||
190 | debugger.handle_trace = debugger_syscall; | ||
191 | debugger.debugee = &debugee; | ||
192 | debugger.waiting = 0; | ||
193 | debugger.real_wait = 0; | ||
194 | debugger.expecting_child = 0; | ||
195 | |||
196 | debugee.pid = 0; | ||
197 | debugee.traced = 0; | ||
198 | debugee.stopped = stopped; | ||
199 | debugee.event = 0; | ||
200 | debugee.zombie = 0; | ||
201 | debugee.died = 0; | ||
202 | debugee.wait_status = status; | ||
203 | debugee.in_context = 1; | ||
204 | } | ||
205 | |||
206 | int debugger_proxy(int status, int pid) | ||
207 | { | ||
208 | int ret = 0, sig; | ||
209 | |||
210 | if(WIFSTOPPED(status)){ | ||
211 | sig = WSTOPSIG(status); | ||
212 | if (sig == SIGTRAP) | ||
213 | ret = (*debugger.handle_trace)(&debugger, pid); | ||
214 | |||
215 | else if(sig == SIGCHLD){ | ||
216 | if(debugger.expecting_child){ | ||
217 | ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); | ||
218 | debugger.expecting_child = 0; | ||
219 | } | ||
220 | else if(debugger.waiting) | ||
221 | real_wait_return(&debugger); | ||
222 | else { | ||
223 | ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); | ||
224 | debugger.real_wait = 1; | ||
225 | } | ||
226 | } | ||
227 | else ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); | ||
228 | } | ||
229 | else if(WIFEXITED(status)){ | ||
230 | tracer_panic("debugger (pid %d) exited with status %d", | ||
231 | debugger.pid, WEXITSTATUS(status)); | ||
232 | } | ||
233 | else if(WIFSIGNALED(status)){ | ||
234 | tracer_panic("debugger (pid %d) exited with signal %d", | ||
235 | debugger.pid, WTERMSIG(status)); | ||
236 | } | ||
237 | else { | ||
238 | tracer_panic("proxy got unknown status (0x%x) on debugger " | ||
239 | "(pid %d)", status, debugger.pid); | ||
240 | } | ||
241 | return(ret); | ||
242 | } | ||
243 | |||
244 | void child_proxy(pid_t pid, int status) | ||
245 | { | ||
246 | debugee.event = 1; | ||
247 | debugee.wait_status = status; | ||
248 | |||
249 | if(WIFSTOPPED(status)){ | ||
250 | debugee.stopped = 1; | ||
251 | debugger.expecting_child = 1; | ||
252 | kill(debugger.pid, SIGCHLD); | ||
253 | } | ||
254 | else if(WIFEXITED(status) || WIFSIGNALED(status)){ | ||
255 | debugee.zombie = 1; | ||
256 | debugger.expecting_child = 1; | ||
257 | kill(debugger.pid, SIGCHLD); | ||
258 | } | ||
259 | else panic("proxy got unknown status (0x%x) on child (pid %d)", | ||
260 | status, pid); | ||
261 | } | ||
262 | |||
263 | void debugger_parent_signal(int status, int pid) | ||
264 | { | ||
265 | int sig; | ||
266 | |||
267 | if(WIFSTOPPED(status)){ | ||
268 | sig = WSTOPSIG(status); | ||
269 | if(sig == SIGTRAP) (*parent.handle_trace)(&parent, pid); | ||
270 | else ptrace(PTRACE_SYSCALL, pid, 0, sig); | ||
271 | } | ||
272 | } | ||
273 | |||
274 | void fake_child_exit(void) | ||
275 | { | ||
276 | int status, pid; | ||
277 | |||
278 | child_proxy(1, W_EXITCODE(0, 0)); | ||
279 | while(debugger.waiting == 1){ | ||
280 | CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED)); | ||
281 | if(pid != debugger.pid){ | ||
282 | printk("fake_child_exit - waitpid failed, " | ||
283 | "errno = %d\n", errno); | ||
284 | return; | ||
285 | } | ||
286 | debugger_proxy(status, debugger.pid); | ||
287 | } | ||
288 | CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED)); | ||
289 | if(pid != debugger.pid){ | ||
290 | printk("fake_child_exit - waitpid failed, " | ||
291 | "errno = %d\n", errno); | ||
292 | return; | ||
293 | } | ||
294 | if(ptrace(PTRACE_DETACH, debugger.pid, 0, SIGCONT) < 0) | ||
295 | printk("fake_child_exit - PTRACE_DETACH failed, errno = %d\n", | ||
296 | errno); | ||
297 | } | ||
298 | |||
299 | char gdb_init_string[] = | ||
300 | "att 1 \n\ | ||
301 | b panic \n\ | ||
302 | b stop \n\ | ||
303 | handle SIGWINCH nostop noprint pass \n\ | ||
304 | "; | ||
305 | |||
306 | int start_debugger(char *prog, int startup, int stop, int *fd_out) | ||
307 | { | ||
308 | int slave, child; | ||
309 | |||
310 | slave = open_gdb_chan(); | ||
311 | child = fork(); | ||
312 | if(child == 0){ | ||
313 | char *tempname = NULL; | ||
314 | int fd; | ||
315 | |||
316 | if(setsid() < 0) perror("setsid"); | ||
317 | if((dup2(slave, 0) < 0) || (dup2(slave, 1) < 0) || | ||
318 | (dup2(slave, 2) < 0)){ | ||
319 | printk("start_debugger : dup2 failed, errno = %d\n", | ||
320 | errno); | ||
321 | exit(1); | ||
322 | } | ||
323 | if(ioctl(0, TIOCSCTTY, 0) < 0){ | ||
324 | printk("start_debugger : TIOCSCTTY failed, " | ||
325 | "errno = %d\n", errno); | ||
326 | exit(1); | ||
327 | } | ||
328 | if(tcsetpgrp (1, os_getpid()) < 0){ | ||
329 | printk("start_debugger : tcsetpgrp failed, " | ||
330 | "errno = %d\n", errno); | ||
331 | #ifdef notdef | ||
332 | exit(1); | ||
333 | #endif | ||
334 | } | ||
335 | fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0); | ||
336 | if(fd < 0){ | ||
337 | printk("start_debugger : make_tempfile failed," | ||
338 | "err = %d\n", -fd); | ||
339 | exit(1); | ||
340 | } | ||
341 | os_write_file(fd, gdb_init_string, | ||
342 | sizeof(gdb_init_string) - 1); | ||
343 | if(startup){ | ||
344 | if(stop){ | ||
345 | os_write_file(fd, "b start_kernel\n", | ||
346 | strlen("b start_kernel\n")); | ||
347 | } | ||
348 | os_write_file(fd, "c\n", strlen("c\n")); | ||
349 | } | ||
350 | if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ | ||
351 | printk("start_debugger : PTRACE_TRACEME failed, " | ||
352 | "errno = %d\n", errno); | ||
353 | exit(1); | ||
354 | } | ||
355 | execlp("gdb", "gdb", "--command", tempname, prog, NULL); | ||
356 | printk("start_debugger : exec of gdb failed, errno = %d\n", | ||
357 | errno); | ||
358 | } | ||
359 | if(child < 0){ | ||
360 | printk("start_debugger : fork for gdb failed, errno = %d\n", | ||
361 | errno); | ||
362 | return(-1); | ||
363 | } | ||
364 | *fd_out = slave; | ||
365 | return(child); | ||
366 | } | ||
367 | |||
368 | /* | ||
369 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
370 | * Emacs will notice this stuff at the end of the file and automatically | ||
371 | * adjust the settings for this buffer only. This must remain at the end | ||
372 | * of the file. | ||
373 | * --------------------------------------------------------------------------- | ||
374 | * Local variables: | ||
375 | * c-file-style: "linux" | ||
376 | * End: | ||
377 | */ | ||
diff --git a/arch/um/kernel/tt/ptproxy/ptproxy.h b/arch/um/kernel/tt/ptproxy/ptproxy.h deleted file mode 100644 index 5eb0285b1968..000000000000 --- a/arch/um/kernel/tt/ptproxy/ptproxy.h +++ /dev/null | |||
@@ -1,61 +0,0 @@ | |||
1 | /********************************************************************** | ||
2 | ptproxy.h | ||
3 | |||
4 | Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing | ||
5 | terms and conditions. | ||
6 | **********************************************************************/ | ||
7 | |||
8 | #ifndef __PTPROXY_H | ||
9 | #define __PTPROXY_H | ||
10 | |||
11 | #include <sys/types.h> | ||
12 | |||
13 | typedef struct debugger debugger_state; | ||
14 | typedef struct debugee debugee_state; | ||
15 | |||
16 | struct debugger | ||
17 | { | ||
18 | pid_t pid; | ||
19 | int wait_options; | ||
20 | int *wait_status_ptr; | ||
21 | unsigned int waiting : 1; | ||
22 | unsigned int real_wait : 1; | ||
23 | unsigned int expecting_child : 1; | ||
24 | int (*handle_trace) (debugger_state *, pid_t); | ||
25 | |||
26 | debugee_state *debugee; | ||
27 | }; | ||
28 | |||
29 | struct debugee | ||
30 | { | ||
31 | pid_t pid; | ||
32 | int wait_status; | ||
33 | unsigned int died : 1; | ||
34 | unsigned int event : 1; | ||
35 | unsigned int stopped : 1; | ||
36 | unsigned int trace_singlestep : 1; | ||
37 | unsigned int trace_syscall : 1; | ||
38 | unsigned int traced : 1; | ||
39 | unsigned int zombie : 1; | ||
40 | unsigned int in_context : 1; | ||
41 | }; | ||
42 | |||
43 | extern int debugger_syscall(debugger_state *debugger, pid_t pid); | ||
44 | extern int debugger_normal_return (debugger_state *debugger, pid_t unused); | ||
45 | |||
46 | extern long proxy_ptrace (struct debugger *, int, pid_t, long, long, pid_t, | ||
47 | int *strace_out); | ||
48 | extern void debugger_cancelled_return(debugger_state *debugger, int result); | ||
49 | |||
50 | #endif | ||
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/kernel/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c deleted file mode 100644 index 4b4f6179b212..000000000000 --- a/arch/um/kernel/tt/ptproxy/ptrace.c +++ /dev/null | |||
@@ -1,237 +0,0 @@ | |||
1 | /********************************************************************** | ||
2 | ptrace.c | ||
3 | |||
4 | Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing | ||
5 | terms and conditions. | ||
6 | |||
7 | Jeff Dike (jdike@karaya.com) : Modified for integration into uml | ||
8 | **********************************************************************/ | ||
9 | |||
10 | #include <errno.h> | ||
11 | #include <unistd.h> | ||
12 | #include <signal.h> | ||
13 | #include <sys/types.h> | ||
14 | #include <sys/time.h> | ||
15 | #include <sys/wait.h> | ||
16 | |||
17 | #include "ptproxy.h" | ||
18 | #include "debug.h" | ||
19 | #include "kern_util.h" | ||
20 | #include "ptrace_user.h" | ||
21 | #include "tt.h" | ||
22 | #include "os.h" | ||
23 | |||
24 | long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2, | ||
25 | long arg3, long arg4, pid_t child, int *ret) | ||
26 | { | ||
27 | sigset_t relay; | ||
28 | long result; | ||
29 | int status; | ||
30 | |||
31 | *ret = 0; | ||
32 | if(debugger->debugee->died) return(-ESRCH); | ||
33 | |||
34 | switch(arg1){ | ||
35 | case PTRACE_ATTACH: | ||
36 | if(debugger->debugee->traced) return(-EPERM); | ||
37 | |||
38 | debugger->debugee->pid = arg2; | ||
39 | debugger->debugee->traced = 1; | ||
40 | |||
41 | if(is_valid_pid(arg2) && (arg2 != child)){ | ||
42 | debugger->debugee->in_context = 0; | ||
43 | kill(arg2, SIGSTOP); | ||
44 | debugger->debugee->event = 1; | ||
45 | debugger->debugee->wait_status = W_STOPCODE(SIGSTOP); | ||
46 | } | ||
47 | else { | ||
48 | debugger->debugee->in_context = 1; | ||
49 | if(debugger->debugee->stopped) | ||
50 | child_proxy(child, W_STOPCODE(SIGSTOP)); | ||
51 | else kill(child, SIGSTOP); | ||
52 | } | ||
53 | |||
54 | return(0); | ||
55 | |||
56 | case PTRACE_DETACH: | ||
57 | if(!debugger->debugee->traced) return(-EPERM); | ||
58 | |||
59 | debugger->debugee->traced = 0; | ||
60 | debugger->debugee->pid = 0; | ||
61 | if(!debugger->debugee->in_context) | ||
62 | kill(child, SIGCONT); | ||
63 | |||
64 | return(0); | ||
65 | |||
66 | case PTRACE_CONT: | ||
67 | if(!debugger->debugee->in_context) return(-EPERM); | ||
68 | *ret = PTRACE_CONT; | ||
69 | return(ptrace(PTRACE_CONT, child, arg3, arg4)); | ||
70 | |||
71 | #ifdef UM_HAVE_GETFPREGS | ||
72 | case PTRACE_GETFPREGS: | ||
73 | { | ||
74 | long regs[FP_FRAME_SIZE]; | ||
75 | int i, result; | ||
76 | |||
77 | result = ptrace(PTRACE_GETFPREGS, child, 0, regs); | ||
78 | if(result == -1) return(-errno); | ||
79 | |||
80 | for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) | ||
81 | ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i, | ||
82 | regs[i]); | ||
83 | return(result); | ||
84 | } | ||
85 | #endif | ||
86 | |||
87 | #ifdef UM_HAVE_GETFPXREGS | ||
88 | case PTRACE_GETFPXREGS: | ||
89 | { | ||
90 | long regs[FPX_FRAME_SIZE]; | ||
91 | int i, result; | ||
92 | |||
93 | result = ptrace(PTRACE_GETFPXREGS, child, 0, regs); | ||
94 | if(result == -1) return(-errno); | ||
95 | |||
96 | for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) | ||
97 | ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i, | ||
98 | regs[i]); | ||
99 | return(result); | ||
100 | } | ||
101 | #endif | ||
102 | |||
103 | #ifdef UM_HAVE_GETREGS | ||
104 | case PTRACE_GETREGS: | ||
105 | { | ||
106 | long regs[FRAME_SIZE]; | ||
107 | int i, result; | ||
108 | |||
109 | result = ptrace(PTRACE_GETREGS, child, 0, regs); | ||
110 | if(result == -1) return(-errno); | ||
111 | |||
112 | for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) | ||
113 | ptrace (PTRACE_POKEDATA, debugger->pid, | ||
114 | arg4 + 4 * i, regs[i]); | ||
115 | return(result); | ||
116 | } | ||
117 | break; | ||
118 | #endif | ||
119 | |||
120 | case PTRACE_KILL: | ||
121 | result = ptrace(PTRACE_KILL, child, arg3, arg4); | ||
122 | if(result == -1) return(-errno); | ||
123 | |||
124 | return(result); | ||
125 | |||
126 | case PTRACE_PEEKDATA: | ||
127 | case PTRACE_PEEKTEXT: | ||
128 | case PTRACE_PEEKUSR: | ||
129 | /* The value being read out could be -1, so we have to | ||
130 | * check errno to see if there's an error, and zero it | ||
131 | * beforehand so we're not faked out by an old error | ||
132 | */ | ||
133 | |||
134 | errno = 0; | ||
135 | result = ptrace(arg1, child, arg3, 0); | ||
136 | if((result == -1) && (errno != 0)) return(-errno); | ||
137 | |||
138 | result = ptrace(PTRACE_POKEDATA, debugger->pid, arg4, result); | ||
139 | if(result == -1) return(-errno); | ||
140 | |||
141 | return(result); | ||
142 | |||
143 | case PTRACE_POKEDATA: | ||
144 | case PTRACE_POKETEXT: | ||
145 | case PTRACE_POKEUSR: | ||
146 | result = ptrace(arg1, child, arg3, arg4); | ||
147 | if(result == -1) return(-errno); | ||
148 | |||
149 | if(arg1 == PTRACE_POKEUSR) ptrace_pokeuser(arg3, arg4); | ||
150 | return(result); | ||
151 | |||
152 | #ifdef UM_HAVE_SETFPREGS | ||
153 | case PTRACE_SETFPREGS: | ||
154 | { | ||
155 | long regs[FP_FRAME_SIZE]; | ||
156 | int i; | ||
157 | |||
158 | for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) | ||
159 | regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid, | ||
160 | arg4 + 4 * i, 0); | ||
161 | result = ptrace(PTRACE_SETFPREGS, child, 0, regs); | ||
162 | if(result == -1) return(-errno); | ||
163 | |||
164 | return(result); | ||
165 | } | ||
166 | #endif | ||
167 | |||
168 | #ifdef UM_HAVE_SETFPXREGS | ||
169 | case PTRACE_SETFPXREGS: | ||
170 | { | ||
171 | long regs[FPX_FRAME_SIZE]; | ||
172 | int i; | ||
173 | |||
174 | for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) | ||
175 | regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid, | ||
176 | arg4 + 4 * i, 0); | ||
177 | result = ptrace(PTRACE_SETFPXREGS, child, 0, regs); | ||
178 | if(result == -1) return(-errno); | ||
179 | |||
180 | return(result); | ||
181 | } | ||
182 | #endif | ||
183 | |||
184 | #ifdef UM_HAVE_SETREGS | ||
185 | case PTRACE_SETREGS: | ||
186 | { | ||
187 | long regs[FRAME_SIZE]; | ||
188 | int i; | ||
189 | |||
190 | for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) | ||
191 | regs[i] = ptrace(PTRACE_PEEKDATA, debugger->pid, | ||
192 | arg4 + 4 * i, 0); | ||
193 | result = ptrace(PTRACE_SETREGS, child, 0, regs); | ||
194 | if(result == -1) return(-errno); | ||
195 | |||
196 | return(result); | ||
197 | } | ||
198 | #endif | ||
199 | |||
200 | case PTRACE_SINGLESTEP: | ||
201 | if(!debugger->debugee->in_context) return(-EPERM); | ||
202 | sigemptyset(&relay); | ||
203 | sigaddset(&relay, SIGSEGV); | ||
204 | sigaddset(&relay, SIGILL); | ||
205 | sigaddset(&relay, SIGBUS); | ||
206 | result = ptrace(PTRACE_SINGLESTEP, child, arg3, arg4); | ||
207 | if(result == -1) return(-errno); | ||
208 | |||
209 | status = wait_for_stop(child, SIGTRAP, PTRACE_SINGLESTEP, | ||
210 | &relay); | ||
211 | child_proxy(child, status); | ||
212 | return(result); | ||
213 | |||
214 | case PTRACE_SYSCALL: | ||
215 | if(!debugger->debugee->in_context) return(-EPERM); | ||
216 | result = ptrace(PTRACE_SYSCALL, child, arg3, arg4); | ||
217 | if(result == -1) return(-errno); | ||
218 | |||
219 | *ret = PTRACE_SYSCALL; | ||
220 | return(result); | ||
221 | |||
222 | case PTRACE_TRACEME: | ||
223 | default: | ||
224 | return(-EINVAL); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | /* | ||
229 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
230 | * Emacs will notice this stuff at the end of the file and automatically | ||
231 | * adjust the settings for this buffer only. This must remain at the end | ||
232 | * of the file. | ||
233 | * --------------------------------------------------------------------------- | ||
234 | * Local variables: | ||
235 | * c-file-style: "linux" | ||
236 | * End: | ||
237 | */ | ||
diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c deleted file mode 100644 index e0e1ab0588ad..000000000000 --- a/arch/um/kernel/tt/ptproxy/sysdep.c +++ /dev/null | |||
@@ -1,70 +0,0 @@ | |||
1 | /********************************************************************** | ||
2 | sysdep.c | ||
3 | |||
4 | Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing | ||
5 | terms and conditions. | ||
6 | **********************************************************************/ | ||
7 | |||
8 | #include <stdio.h> | ||
9 | #include <string.h> | ||
10 | #include <stdlib.h> | ||
11 | #include <signal.h> | ||
12 | #include <errno.h> | ||
13 | #include <sys/types.h> | ||
14 | #include <linux/unistd.h> | ||
15 | #include "ptrace_user.h" | ||
16 | #include "user.h" | ||
17 | #include "os.h" | ||
18 | |||
19 | int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4, | ||
20 | long *arg5) | ||
21 | { | ||
22 | *arg1 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG1_OFFSET, 0); | ||
23 | *arg2 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG2_OFFSET, 0); | ||
24 | *arg3 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG3_OFFSET, 0); | ||
25 | *arg4 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG4_OFFSET, 0); | ||
26 | *arg5 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG5_OFFSET, 0); | ||
27 | return(ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, 0)); | ||
28 | } | ||
29 | |||
30 | void syscall_cancel(pid_t pid, int result) | ||
31 | { | ||
32 | if((ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, | ||
33 | __NR_getpid) < 0) || | ||
34 | (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) || | ||
35 | (wait_for_stop(pid, SIGTRAP, PTRACE_SYSCALL, NULL) < 0) || | ||
36 | (ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result) < 0) || | ||
37 | (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)) | ||
38 | printk("ptproxy: couldn't cancel syscall: errno = %d\n", | ||
39 | errno); | ||
40 | } | ||
41 | |||
42 | void syscall_set_result(pid_t pid, long result) | ||
43 | { | ||
44 | ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result); | ||
45 | } | ||
46 | |||
47 | void syscall_continue(pid_t pid) | ||
48 | { | ||
49 | ptrace(PTRACE_SYSCALL, pid, 0, 0); | ||
50 | } | ||
51 | |||
52 | int syscall_pause(pid_t pid) | ||
53 | { | ||
54 | if(ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_pause) < 0){ | ||
55 | printk("syscall_change - ptrace failed, errno = %d\n", errno); | ||
56 | return(-1); | ||
57 | } | ||
58 | return(0); | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
63 | * Emacs will notice this stuff at the end of the file and automatically | ||
64 | * adjust the settings for this buffer only. This must remain at the end | ||
65 | * of the file. | ||
66 | * --------------------------------------------------------------------------- | ||
67 | * Local variables: | ||
68 | * c-file-style: "linux" | ||
69 | * End: | ||
70 | */ | ||
diff --git a/arch/um/kernel/tt/ptproxy/sysdep.h b/arch/um/kernel/tt/ptproxy/sysdep.h deleted file mode 100644 index 735f488049aa..000000000000 --- a/arch/um/kernel/tt/ptproxy/sysdep.h +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | /********************************************************************** | ||
2 | sysdep.h | ||
3 | |||
4 | Copyright (C) 1999 Lars Brinkhoff. | ||
5 | Copyright (C) 2001 Jeff Dike (jdike@karaya.com) | ||
6 | See the file COPYING for licensing terms and conditions. | ||
7 | **********************************************************************/ | ||
8 | |||
9 | extern int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, | ||
10 | long *arg4, long *arg5); | ||
11 | extern void syscall_cancel (pid_t pid, long result); | ||
12 | extern void syscall_set_result (pid_t pid, long result); | ||
13 | extern void syscall_continue (pid_t pid); | ||
14 | extern int syscall_pause(pid_t pid); | ||
15 | |||
16 | /* | ||
17 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
18 | * Emacs will notice this stuff at the end of the file and automatically | ||
19 | * adjust the settings for this buffer only. This must remain at the end | ||
20 | * of the file. | ||
21 | * --------------------------------------------------------------------------- | ||
22 | * Local variables: | ||
23 | * c-file-style: "linux" | ||
24 | * End: | ||
25 | */ | ||
diff --git a/arch/um/kernel/tt/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c deleted file mode 100644 index bdd4af4b65fc..000000000000 --- a/arch/um/kernel/tt/ptproxy/wait.c +++ /dev/null | |||
@@ -1,85 +0,0 @@ | |||
1 | /********************************************************************** | ||
2 | wait.c | ||
3 | |||
4 | Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing | ||
5 | terms and conditions. | ||
6 | |||
7 | **********************************************************************/ | ||
8 | |||
9 | #include <errno.h> | ||
10 | #include <signal.h> | ||
11 | #include <sys/wait.h> | ||
12 | |||
13 | #include "ptproxy.h" | ||
14 | #include "sysdep.h" | ||
15 | #include "wait.h" | ||
16 | #include "ptrace_user.h" | ||
17 | #include "sysdep/ptrace.h" | ||
18 | #include "sysdep/sigcontext.h" | ||
19 | |||
20 | int proxy_wait_return(struct debugger *debugger, pid_t unused) | ||
21 | { | ||
22 | debugger->waiting = 0; | ||
23 | |||
24 | if(debugger->debugee->died || (debugger->wait_options & __WCLONE)){ | ||
25 | debugger_cancelled_return(debugger, -ECHILD); | ||
26 | return(0); | ||
27 | } | ||
28 | |||
29 | if(debugger->debugee->zombie && debugger->debugee->event) | ||
30 | debugger->debugee->died = 1; | ||
31 | |||
32 | if(debugger->debugee->event){ | ||
33 | debugger->debugee->event = 0; | ||
34 | ptrace(PTRACE_POKEDATA, debugger->pid, | ||
35 | debugger->wait_status_ptr, | ||
36 | debugger->debugee->wait_status); | ||
37 | /* if (wait4) | ||
38 | ptrace (PTRACE_POKEDATA, pid, rusage_ptr, ...); */ | ||
39 | debugger_cancelled_return(debugger, debugger->debugee->pid); | ||
40 | return(0); | ||
41 | } | ||
42 | |||
43 | /* pause will return -EINTR, which happens to be right for wait */ | ||
44 | debugger_normal_return(debugger, -1); | ||
45 | return(0); | ||
46 | } | ||
47 | |||
48 | int parent_wait_return(struct debugger *debugger, pid_t unused) | ||
49 | { | ||
50 | return(debugger_normal_return(debugger, -1)); | ||
51 | } | ||
52 | |||
53 | int real_wait_return(struct debugger *debugger) | ||
54 | { | ||
55 | unsigned long ip; | ||
56 | int pid; | ||
57 | |||
58 | pid = debugger->pid; | ||
59 | |||
60 | ip = ptrace(PTRACE_PEEKUSR, pid, PT_IP_OFFSET, 0); | ||
61 | IP_RESTART_SYSCALL(ip); | ||
62 | |||
63 | if(ptrace(PTRACE_POKEUSR, pid, PT_IP_OFFSET, ip) < 0) | ||
64 | tracer_panic("real_wait_return : Failed to restart system " | ||
65 | "call, errno = %d\n", errno); | ||
66 | |||
67 | if((ptrace(PTRACE_SYSCALL, debugger->pid, 0, SIGCHLD) < 0) || | ||
68 | (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) || | ||
69 | (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) || | ||
70 | debugger_normal_return(debugger, -1)) | ||
71 | tracer_panic("real_wait_return : gdb failed to wait, " | ||
72 | "errno = %d\n", errno); | ||
73 | return(0); | ||
74 | } | ||
75 | |||
76 | /* | ||
77 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
78 | * Emacs will notice this stuff at the end of the file and automatically | ||
79 | * adjust the settings for this buffer only. This must remain at the end | ||
80 | * of the file. | ||
81 | * --------------------------------------------------------------------------- | ||
82 | * Local variables: | ||
83 | * c-file-style: "linux" | ||
84 | * End: | ||
85 | */ | ||
diff --git a/arch/um/kernel/tt/ptproxy/wait.h b/arch/um/kernel/tt/ptproxy/wait.h deleted file mode 100644 index 542e73ee2cee..000000000000 --- a/arch/um/kernel/tt/ptproxy/wait.h +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | /********************************************************************** | ||
2 | wait.h | ||
3 | |||
4 | Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing | ||
5 | terms and conditions. | ||
6 | **********************************************************************/ | ||
7 | |||
8 | #ifndef __PTPROXY_WAIT_H | ||
9 | #define __PTPROXY_WAIT_H | ||
10 | |||
11 | extern int proxy_wait_return(struct debugger *debugger, pid_t unused); | ||
12 | extern int real_wait_return(struct debugger *debugger); | ||
13 | extern int parent_wait_return(struct debugger *debugger, pid_t unused); | ||
14 | |||
15 | #endif | ||
diff --git a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c deleted file mode 100644 index 293caa6d0c2d..000000000000 --- a/arch/um/kernel/tt/syscall_kern.c +++ /dev/null | |||
@@ -1,46 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/types.h" | ||
7 | #include "linux/utime.h" | ||
8 | #include "linux/sys.h" | ||
9 | #include "linux/ptrace.h" | ||
10 | #include "asm/unistd.h" | ||
11 | #include "asm/ptrace.h" | ||
12 | #include "asm/uaccess.h" | ||
13 | #include "asm/stat.h" | ||
14 | #include "sysdep/syscalls.h" | ||
15 | #include "sysdep/sigcontext.h" | ||
16 | #include "kern_util.h" | ||
17 | #include "syscall.h" | ||
18 | |||
19 | void syscall_handler_tt(int sig, struct pt_regs *regs) | ||
20 | { | ||
21 | void *sc; | ||
22 | long result; | ||
23 | int syscall; | ||
24 | |||
25 | sc = UPT_SC(®s->regs); | ||
26 | SC_START_SYSCALL(sc); | ||
27 | |||
28 | syscall = UPT_SYSCALL_NR(®s->regs); | ||
29 | syscall_trace(®s->regs, 0); | ||
30 | |||
31 | current->thread.nsyscalls++; | ||
32 | nsyscalls++; | ||
33 | |||
34 | if((syscall >= NR_syscalls) || (syscall < 0)) | ||
35 | result = -ENOSYS; | ||
36 | else result = EXECUTE_SYSCALL(syscall, regs); | ||
37 | |||
38 | /* regs->sc may have changed while the system call ran (there may | ||
39 | * have been an interrupt or segfault), so it needs to be refreshed. | ||
40 | */ | ||
41 | UPT_SC(®s->regs) = sc; | ||
42 | |||
43 | SC_SET_SYSCALL_RETURN(sc, result); | ||
44 | |||
45 | syscall_trace(®s->regs, 1); | ||
46 | } | ||
diff --git a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c deleted file mode 100644 index f52b47aff1d2..000000000000 --- a/arch/um/kernel/tt/syscall_user.c +++ /dev/null | |||
@@ -1,60 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <unistd.h> | ||
7 | #include <signal.h> | ||
8 | #include <errno.h> | ||
9 | #include <asm/unistd.h> | ||
10 | #include "sysdep/ptrace.h" | ||
11 | #include "sigcontext.h" | ||
12 | #include "ptrace_user.h" | ||
13 | #include "task.h" | ||
14 | #include "kern_util.h" | ||
15 | #include "syscall.h" | ||
16 | #include "tt.h" | ||
17 | |||
18 | void do_sigtrap(void *task) | ||
19 | { | ||
20 | UPT_SYSCALL_NR(TASK_REGS(task)) = -1; | ||
21 | } | ||
22 | |||
23 | void do_syscall(void *task, int pid, int local_using_sysemu) | ||
24 | { | ||
25 | unsigned long proc_regs[FRAME_SIZE]; | ||
26 | |||
27 | if(ptrace_getregs(pid, proc_regs) < 0) | ||
28 | tracer_panic("Couldn't read registers"); | ||
29 | |||
30 | UPT_SYSCALL_NR(TASK_REGS(task)) = PT_SYSCALL_NR(proc_regs); | ||
31 | |||
32 | #ifdef UPT_ORIGGPR2 | ||
33 | UPT_ORIGGPR2(TASK_REGS(task)) = REGS_ORIGGPR2(proc_regs); | ||
34 | #endif | ||
35 | |||
36 | if(((unsigned long *) PT_IP(proc_regs) >= &_stext) && | ||
37 | ((unsigned long *) PT_IP(proc_regs) <= &_etext)) | ||
38 | tracer_panic("I'm tracing myself and I can't get out"); | ||
39 | |||
40 | /* advanced sysemu mode set syscall number to -1 automatically */ | ||
41 | if (local_using_sysemu==2) | ||
42 | return; | ||
43 | |||
44 | /* syscall number -1 in sysemu skips syscall restarting in host */ | ||
45 | if(ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, | ||
46 | local_using_sysemu ? -1 : __NR_getpid) < 0) | ||
47 | tracer_panic("do_syscall : Nullifying syscall failed, " | ||
48 | "errno = %d", errno); | ||
49 | } | ||
50 | |||
51 | /* | ||
52 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
53 | * Emacs will notice this stuff at the end of the file and automatically | ||
54 | * adjust the settings for this buffer only. This must remain at the end | ||
55 | * of the file. | ||
56 | * --------------------------------------------------------------------------- | ||
57 | * Local variables: | ||
58 | * c-file-style: "linux" | ||
59 | * End: | ||
60 | */ | ||
diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c deleted file mode 100644 index 7caa24fe05df..000000000000 --- a/arch/um/kernel/tt/tlb.c +++ /dev/null | |||
@@ -1,120 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Copyright 2003 PathScale, Inc. | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include "linux/stddef.h" | ||
8 | #include "linux/kernel.h" | ||
9 | #include "linux/sched.h" | ||
10 | #include "linux/mm.h" | ||
11 | #include "asm/page.h" | ||
12 | #include "asm/pgtable.h" | ||
13 | #include "asm/uaccess.h" | ||
14 | #include "asm/tlbflush.h" | ||
15 | #include "mem_user.h" | ||
16 | #include "os.h" | ||
17 | #include "tlb.h" | ||
18 | |||
19 | static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last, | ||
20 | int finished, void **flush) | ||
21 | { | ||
22 | struct host_vm_op *op; | ||
23 | int i, ret=0; | ||
24 | |||
25 | for(i = 0; i <= last && !ret; i++){ | ||
26 | op = &ops[i]; | ||
27 | switch(op->type){ | ||
28 | case MMAP: | ||
29 | ret = os_map_memory((void *) op->u.mmap.addr, | ||
30 | op->u.mmap.fd, op->u.mmap.offset, | ||
31 | op->u.mmap.len, op->u.mmap.r, | ||
32 | op->u.mmap.w, op->u.mmap.x); | ||
33 | break; | ||
34 | case MUNMAP: | ||
35 | ret = os_unmap_memory((void *) op->u.munmap.addr, | ||
36 | op->u.munmap.len); | ||
37 | break; | ||
38 | case MPROTECT: | ||
39 | ret = protect_memory(op->u.mprotect.addr, | ||
40 | op->u.munmap.len, | ||
41 | op->u.mprotect.r, | ||
42 | op->u.mprotect.w, | ||
43 | op->u.mprotect.x, 1); | ||
44 | protect_memory(op->u.mprotect.addr, op->u.munmap.len, | ||
45 | op->u.mprotect.r, op->u.mprotect.w, | ||
46 | op->u.mprotect.x, 1); | ||
47 | break; | ||
48 | default: | ||
49 | printk("Unknown op type %d in do_ops\n", op->type); | ||
50 | break; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | return ret; | ||
55 | } | ||
56 | |||
57 | static void fix_range(struct mm_struct *mm, unsigned long start_addr, | ||
58 | unsigned long end_addr, int force) | ||
59 | { | ||
60 | if((current->thread.mode.tt.extern_pid != -1) && | ||
61 | (current->thread.mode.tt.extern_pid != os_getpid())) | ||
62 | panic("fix_range fixing wrong address space, current = 0x%p", | ||
63 | current); | ||
64 | |||
65 | fix_range_common(mm, start_addr, end_addr, force, do_ops); | ||
66 | } | ||
67 | |||
68 | atomic_t vmchange_seq = ATOMIC_INIT(1); | ||
69 | |||
70 | void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end) | ||
71 | { | ||
72 | if(flush_tlb_kernel_range_common(start, end)) | ||
73 | atomic_inc(&vmchange_seq); | ||
74 | } | ||
75 | |||
76 | void flush_tlb_kernel_vm_tt(void) | ||
77 | { | ||
78 | flush_tlb_kernel_range(start_vm, end_vm); | ||
79 | } | ||
80 | |||
81 | void __flush_tlb_one_tt(unsigned long addr) | ||
82 | { | ||
83 | flush_tlb_kernel_range(addr, addr + PAGE_SIZE); | ||
84 | } | ||
85 | |||
86 | void flush_tlb_range_tt(struct vm_area_struct *vma, unsigned long start, | ||
87 | unsigned long end) | ||
88 | { | ||
89 | if(vma->vm_mm != current->mm) return; | ||
90 | |||
91 | /* Assumes that the range start ... end is entirely within | ||
92 | * either process memory or kernel vm | ||
93 | */ | ||
94 | if((start >= start_vm) && (start < end_vm)){ | ||
95 | if(flush_tlb_kernel_range_common(start, end)) | ||
96 | atomic_inc(&vmchange_seq); | ||
97 | } | ||
98 | else fix_range(vma->vm_mm, start, end, 0); | ||
99 | } | ||
100 | |||
101 | void flush_tlb_mm_tt(struct mm_struct *mm) | ||
102 | { | ||
103 | unsigned long seq; | ||
104 | |||
105 | if(mm != current->mm) return; | ||
106 | |||
107 | fix_range(mm, 0, STACK_TOP, 0); | ||
108 | |||
109 | seq = atomic_read(&vmchange_seq); | ||
110 | if(current->thread.mode.tt.vm_seq == seq) | ||
111 | return; | ||
112 | current->thread.mode.tt.vm_seq = seq; | ||
113 | flush_tlb_kernel_range_common(start_vm, end_vm); | ||
114 | } | ||
115 | |||
116 | void force_flush_all_tt(void) | ||
117 | { | ||
118 | fix_range(current->mm, 0, STACK_TOP, 1); | ||
119 | flush_tlb_kernel_range_common(start_vm, end_vm); | ||
120 | } | ||
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c deleted file mode 100644 index c23588393f6e..000000000000 --- a/arch/um/kernel/tt/tracer.c +++ /dev/null | |||
@@ -1,461 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stdio.h> | ||
7 | #include <stdlib.h> | ||
8 | #include <stdarg.h> | ||
9 | #include <unistd.h> | ||
10 | #include <signal.h> | ||
11 | #include <errno.h> | ||
12 | #include <sched.h> | ||
13 | #include <string.h> | ||
14 | #include <sys/mman.h> | ||
15 | #include <sys/time.h> | ||
16 | #include <sys/wait.h> | ||
17 | #include "user.h" | ||
18 | #include "sysdep/ptrace.h" | ||
19 | #include "sigcontext.h" | ||
20 | #include "sysdep/sigcontext.h" | ||
21 | #include "os.h" | ||
22 | #include "mem_user.h" | ||
23 | #include "process.h" | ||
24 | #include "kern_util.h" | ||
25 | #include "chan_user.h" | ||
26 | #include "ptrace_user.h" | ||
27 | #include "irq_user.h" | ||
28 | #include "mode.h" | ||
29 | #include "tt.h" | ||
30 | |||
31 | static int tracer_winch[2]; | ||
32 | |||
33 | int is_tracer_winch(int pid, int fd, void *data) | ||
34 | { | ||
35 | if(pid != os_getpgrp()) | ||
36 | return(0); | ||
37 | |||
38 | register_winch_irq(tracer_winch[0], fd, -1, data); | ||
39 | return(1); | ||
40 | } | ||
41 | |||
42 | static void tracer_winch_handler(int sig) | ||
43 | { | ||
44 | int n; | ||
45 | char c = 1; | ||
46 | |||
47 | n = os_write_file(tracer_winch[1], &c, sizeof(c)); | ||
48 | if(n != sizeof(c)) | ||
49 | printk("tracer_winch_handler - write failed, err = %d\n", -n); | ||
50 | } | ||
51 | |||
52 | /* Called only by the tracing thread during initialization */ | ||
53 | |||
54 | static void setup_tracer_winch(void) | ||
55 | { | ||
56 | int err; | ||
57 | |||
58 | err = os_pipe(tracer_winch, 1, 1); | ||
59 | if(err < 0){ | ||
60 | printk("setup_tracer_winch : os_pipe failed, err = %d\n", -err); | ||
61 | return; | ||
62 | } | ||
63 | signal(SIGWINCH, tracer_winch_handler); | ||
64 | } | ||
65 | |||
66 | void attach_process(int pid) | ||
67 | { | ||
68 | if((ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) || | ||
69 | (ptrace(PTRACE_CONT, pid, 0, 0) < 0)) | ||
70 | tracer_panic("OP_FORK failed to attach pid"); | ||
71 | wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL); | ||
72 | if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) | ||
73 | tracer_panic("OP_FORK: PTRACE_SETOPTIONS failed, errno = %d", errno); | ||
74 | if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) | ||
75 | tracer_panic("OP_FORK failed to continue process"); | ||
76 | } | ||
77 | |||
78 | void tracer_panic(char *format, ...) | ||
79 | { | ||
80 | va_list ap; | ||
81 | |||
82 | va_start(ap, format); | ||
83 | vprintf(format, ap); | ||
84 | va_end(ap); | ||
85 | printf("\n"); | ||
86 | while(1) pause(); | ||
87 | } | ||
88 | |||
89 | static void tracer_segv(int sig, struct sigcontext sc) | ||
90 | { | ||
91 | struct faultinfo fi; | ||
92 | GET_FAULTINFO_FROM_SC(fi, &sc); | ||
93 | printf("Tracing thread segfault at address 0x%lx, ip 0x%lx\n", | ||
94 | FAULT_ADDRESS(fi), SC_IP(&sc)); | ||
95 | while(1) | ||
96 | pause(); | ||
97 | } | ||
98 | |||
99 | /* Changed early in boot, and then only read */ | ||
100 | int debug = 0; | ||
101 | int debug_stop = 1; | ||
102 | int debug_parent = 0; | ||
103 | int honeypot = 0; | ||
104 | |||
105 | static int signal_tramp(void *arg) | ||
106 | { | ||
107 | int (*proc)(void *); | ||
108 | |||
109 | if(honeypot && munmap((void *) (host_task_size - 0x10000000), | ||
110 | 0x10000000)) | ||
111 | panic("Unmapping stack failed"); | ||
112 | if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) | ||
113 | panic("ptrace PTRACE_TRACEME failed"); | ||
114 | os_stop_process(os_getpid()); | ||
115 | change_sig(SIGWINCH, 0); | ||
116 | signal(SIGUSR1, SIG_IGN); | ||
117 | change_sig(SIGCHLD, 0); | ||
118 | signal(SIGSEGV, (__sighandler_t) sig_handler); | ||
119 | set_cmdline("(idle thread)"); | ||
120 | set_init_pid(os_getpid()); | ||
121 | init_irq_signals(0); | ||
122 | proc = arg; | ||
123 | return((*proc)(NULL)); | ||
124 | } | ||
125 | |||
126 | static void sleeping_process_signal(int pid, int sig) | ||
127 | { | ||
128 | switch(sig){ | ||
129 | /* These two result from UML being ^Z-ed and bg-ed. PTRACE_CONT is | ||
130 | * right because the process must be in the kernel already. | ||
131 | */ | ||
132 | case SIGCONT: | ||
133 | case SIGTSTP: | ||
134 | if(ptrace(PTRACE_CONT, pid, 0, sig) < 0) | ||
135 | tracer_panic("sleeping_process_signal : Failed to " | ||
136 | "continue pid %d, signal = %d, " | ||
137 | "errno = %d\n", pid, sig, errno); | ||
138 | break; | ||
139 | |||
140 | /* This happens when the debugger (e.g. strace) is doing system call | ||
141 | * tracing on the kernel. During a context switch, the current task | ||
142 | * will be set to the incoming process and the outgoing process will | ||
143 | * hop into write and then read. Since it's not the current process | ||
144 | * any more, the trace of those will land here. So, we need to just | ||
145 | * PTRACE_SYSCALL it. | ||
146 | */ | ||
147 | case (SIGTRAP + 0x80): | ||
148 | if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) | ||
149 | tracer_panic("sleeping_process_signal : Failed to " | ||
150 | "PTRACE_SYSCALL pid %d, errno = %d\n", | ||
151 | pid, errno); | ||
152 | break; | ||
153 | case SIGSTOP: | ||
154 | break; | ||
155 | default: | ||
156 | tracer_panic("sleeping process %d got unexpected " | ||
157 | "signal : %d\n", pid, sig); | ||
158 | break; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | /* Accessed only by the tracing thread */ | ||
163 | int debugger_pid = -1; | ||
164 | int debugger_parent = -1; | ||
165 | int debugger_fd = -1; | ||
166 | int gdb_pid = -1; | ||
167 | |||
168 | struct { | ||
169 | int pid; | ||
170 | int signal; | ||
171 | unsigned long addr; | ||
172 | struct timeval time; | ||
173 | } signal_record[1024][32]; | ||
174 | |||
175 | int signal_index[32]; | ||
176 | int nsignals = 0; | ||
177 | int debug_trace = 0; | ||
178 | |||
179 | extern void signal_usr1(int sig); | ||
180 | |||
181 | int tracing_pid = -1; | ||
182 | |||
183 | int tracer(int (*init_proc)(void *), void *sp) | ||
184 | { | ||
185 | void *task = NULL; | ||
186 | int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0; | ||
187 | int proc_id = 0, n, err, old_tracing = 0, strace = 0; | ||
188 | int local_using_sysemu = 0; | ||
189 | |||
190 | signal(SIGPIPE, SIG_IGN); | ||
191 | setup_tracer_winch(); | ||
192 | tracing_pid = os_getpid(); | ||
193 | printf("tracing thread pid = %d\n", tracing_pid); | ||
194 | |||
195 | pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc); | ||
196 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); | ||
197 | if(n < 0){ | ||
198 | printf("waitpid on idle thread failed, errno = %d\n", errno); | ||
199 | exit(1); | ||
200 | } | ||
201 | if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) { | ||
202 | printf("Failed to PTRACE_SETOPTIONS for idle thread, errno = %d\n", errno); | ||
203 | exit(1); | ||
204 | } | ||
205 | if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){ | ||
206 | printf("Failed to continue idle thread, errno = %d\n", errno); | ||
207 | exit(1); | ||
208 | } | ||
209 | |||
210 | signal(SIGSEGV, (sighandler_t) tracer_segv); | ||
211 | signal(SIGUSR1, signal_usr1); | ||
212 | if(debug_trace){ | ||
213 | printf("Tracing thread pausing to be attached\n"); | ||
214 | stop(); | ||
215 | } | ||
216 | if(debug){ | ||
217 | if(gdb_pid != -1) | ||
218 | debugger_pid = attach_debugger(pid, gdb_pid, 1); | ||
219 | else debugger_pid = init_ptrace_proxy(pid, 1, debug_stop); | ||
220 | if(debug_parent){ | ||
221 | debugger_parent = os_process_parent(debugger_pid); | ||
222 | init_parent_proxy(debugger_parent); | ||
223 | err = attach(debugger_parent); | ||
224 | if(err){ | ||
225 | printf("Failed to attach debugger parent %d, " | ||
226 | "errno = %d\n", debugger_parent, -err); | ||
227 | debugger_parent = -1; | ||
228 | } | ||
229 | else { | ||
230 | if(ptrace(PTRACE_SYSCALL, debugger_parent, | ||
231 | 0, 0) < 0){ | ||
232 | printf("Failed to continue debugger " | ||
233 | "parent, errno = %d\n", errno); | ||
234 | debugger_parent = -1; | ||
235 | } | ||
236 | } | ||
237 | } | ||
238 | } | ||
239 | set_cmdline("(tracing thread)"); | ||
240 | while(1){ | ||
241 | CATCH_EINTR(pid = waitpid(-1, &status, WUNTRACED)); | ||
242 | if(pid <= 0){ | ||
243 | if(errno != ECHILD){ | ||
244 | printf("wait failed - errno = %d\n", errno); | ||
245 | } | ||
246 | continue; | ||
247 | } | ||
248 | if(pid == debugger_pid){ | ||
249 | int cont = 0; | ||
250 | |||
251 | if(WIFEXITED(status) || WIFSIGNALED(status)) | ||
252 | debugger_pid = -1; | ||
253 | /* XXX Figure out how to deal with gdb and SMP */ | ||
254 | else cont = debugger_signal(status, cpu_tasks[0].pid); | ||
255 | if(cont == PTRACE_SYSCALL) strace = 1; | ||
256 | continue; | ||
257 | } | ||
258 | else if(pid == debugger_parent){ | ||
259 | debugger_parent_signal(status, pid); | ||
260 | continue; | ||
261 | } | ||
262 | nsignals++; | ||
263 | if(WIFEXITED(status)) ; | ||
264 | #ifdef notdef | ||
265 | { | ||
266 | printf("Child %d exited with status %d\n", pid, | ||
267 | WEXITSTATUS(status)); | ||
268 | } | ||
269 | #endif | ||
270 | else if(WIFSIGNALED(status)){ | ||
271 | sig = WTERMSIG(status); | ||
272 | if(sig != 9){ | ||
273 | printf("Child %d exited with signal %d\n", pid, | ||
274 | sig); | ||
275 | } | ||
276 | } | ||
277 | else if(WIFSTOPPED(status)){ | ||
278 | proc_id = pid_to_processor_id(pid); | ||
279 | sig = WSTOPSIG(status); | ||
280 | if(proc_id == -1){ | ||
281 | sleeping_process_signal(pid, sig); | ||
282 | continue; | ||
283 | } | ||
284 | |||
285 | task = cpu_tasks[proc_id].task; | ||
286 | tracing = is_tracing(task); | ||
287 | old_tracing = tracing; | ||
288 | |||
289 | /* Assume: no syscall, when coming from user */ | ||
290 | if ( tracing ) | ||
291 | do_sigtrap(task); | ||
292 | |||
293 | switch(sig){ | ||
294 | case SIGUSR1: | ||
295 | sig = 0; | ||
296 | op = do_proc_op(task, proc_id); | ||
297 | switch(op){ | ||
298 | /* | ||
299 | * This is called when entering user mode; after | ||
300 | * this, we start intercepting syscalls. | ||
301 | * | ||
302 | * In fact, a process is started in kernel mode, | ||
303 | * so with is_tracing() == 0 (and that is reset | ||
304 | * when executing syscalls, since UML kernel has | ||
305 | * the right to do syscalls); | ||
306 | */ | ||
307 | case OP_TRACE_ON: | ||
308 | arch_leave_kernel(task, pid); | ||
309 | tracing = 1; | ||
310 | break; | ||
311 | case OP_REBOOT: | ||
312 | case OP_HALT: | ||
313 | unmap_physmem(); | ||
314 | kmalloc_ok = 0; | ||
315 | os_kill_ptraced_process(pid, 0); | ||
316 | /* Now let's reap remaining zombies */ | ||
317 | errno = 0; | ||
318 | do { | ||
319 | waitpid(-1, &status, | ||
320 | WUNTRACED); | ||
321 | } while (errno != ECHILD); | ||
322 | return(op == OP_REBOOT); | ||
323 | case OP_NONE: | ||
324 | printf("Detaching pid %d\n", pid); | ||
325 | detach(pid, SIGSTOP); | ||
326 | continue; | ||
327 | default: | ||
328 | break; | ||
329 | } | ||
330 | /* OP_EXEC switches host processes on us, | ||
331 | * we want to continue the new one. | ||
332 | */ | ||
333 | pid = cpu_tasks[proc_id].pid; | ||
334 | break; | ||
335 | case (SIGTRAP + 0x80): | ||
336 | if(!tracing && (debugger_pid != -1)){ | ||
337 | child_signal(pid, status & 0x7fff); | ||
338 | continue; | ||
339 | } | ||
340 | tracing = 0; | ||
341 | /* local_using_sysemu has been already set | ||
342 | * below, since if we are here, is_tracing() on | ||
343 | * the traced task was 1, i.e. the process had | ||
344 | * already run through one iteration of the | ||
345 | * loop which executed a OP_TRACE_ON request.*/ | ||
346 | do_syscall(task, pid, local_using_sysemu); | ||
347 | sig = SIGUSR2; | ||
348 | break; | ||
349 | case SIGTRAP: | ||
350 | if(!tracing && (debugger_pid != -1)){ | ||
351 | child_signal(pid, status); | ||
352 | continue; | ||
353 | } | ||
354 | tracing = 0; | ||
355 | break; | ||
356 | case SIGPROF: | ||
357 | if(tracing) sig = 0; | ||
358 | break; | ||
359 | case SIGCHLD: | ||
360 | case SIGHUP: | ||
361 | sig = 0; | ||
362 | break; | ||
363 | case SIGSEGV: | ||
364 | case SIGIO: | ||
365 | case SIGALRM: | ||
366 | case SIGVTALRM: | ||
367 | case SIGFPE: | ||
368 | case SIGBUS: | ||
369 | case SIGILL: | ||
370 | case SIGWINCH: | ||
371 | |||
372 | default: | ||
373 | tracing = 0; | ||
374 | break; | ||
375 | } | ||
376 | set_tracing(task, tracing); | ||
377 | |||
378 | if(!tracing && old_tracing) | ||
379 | arch_enter_kernel(task, pid); | ||
380 | |||
381 | if(!tracing && (debugger_pid != -1) && (sig != 0) && | ||
382 | (sig != SIGALRM) && (sig != SIGVTALRM) && | ||
383 | (sig != SIGSEGV) && (sig != SIGTRAP) && | ||
384 | (sig != SIGUSR2) && (sig != SIGIO) && | ||
385 | (sig != SIGFPE)){ | ||
386 | child_signal(pid, status); | ||
387 | continue; | ||
388 | } | ||
389 | |||
390 | local_using_sysemu = get_using_sysemu(); | ||
391 | |||
392 | if(tracing) | ||
393 | cont_type = SELECT_PTRACE_OPERATION(local_using_sysemu, | ||
394 | singlestepping(task)); | ||
395 | else if((debugger_pid != -1) && strace) | ||
396 | cont_type = PTRACE_SYSCALL; | ||
397 | else | ||
398 | cont_type = PTRACE_CONT; | ||
399 | |||
400 | if(ptrace(cont_type, pid, 0, sig) != 0){ | ||
401 | tracer_panic("ptrace failed to continue " | ||
402 | "process - errno = %d\n", | ||
403 | errno); | ||
404 | } | ||
405 | } | ||
406 | } | ||
407 | return(0); | ||
408 | } | ||
409 | |||
410 | static int __init uml_debug_setup(char *line, int *add) | ||
411 | { | ||
412 | char *next; | ||
413 | |||
414 | debug = 1; | ||
415 | *add = 0; | ||
416 | if(*line != '=') return(0); | ||
417 | line++; | ||
418 | |||
419 | while(line != NULL){ | ||
420 | next = strchr(line, ','); | ||
421 | if(next) *next++ = '\0'; | ||
422 | |||
423 | if(!strcmp(line, "go")) debug_stop = 0; | ||
424 | else if(!strcmp(line, "parent")) debug_parent = 1; | ||
425 | else printf("Unknown debug option : '%s'\n", line); | ||
426 | |||
427 | line = next; | ||
428 | } | ||
429 | return(0); | ||
430 | } | ||
431 | |||
432 | __uml_setup("debug", uml_debug_setup, | ||
433 | "debug\n" | ||
434 | " Starts up the kernel under the control of gdb. See the \n" | ||
435 | " kernel debugging tutorial and the debugging session pages\n" | ||
436 | " at http://user-mode-linux.sourceforge.net/ for more information.\n\n" | ||
437 | ); | ||
438 | |||
439 | static int __init uml_debugtrace_setup(char *line, int *add) | ||
440 | { | ||
441 | debug_trace = 1; | ||
442 | return 0; | ||
443 | } | ||
444 | __uml_setup("debugtrace", uml_debugtrace_setup, | ||
445 | "debugtrace\n" | ||
446 | " Causes the tracing thread to pause until it is attached by a\n" | ||
447 | " debugger and continued. This is mostly for debugging crashes\n" | ||
448 | " early during boot, and should be pretty much obsoleted by\n" | ||
449 | " the debug switch.\n\n" | ||
450 | ); | ||
451 | |||
452 | /* | ||
453 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
454 | * Emacs will notice this stuff at the end of the file and automatically | ||
455 | * adjust the settings for this buffer only. This must remain at the end | ||
456 | * of the file. | ||
457 | * --------------------------------------------------------------------------- | ||
458 | * Local variables: | ||
459 | * c-file-style: "linux" | ||
460 | * End: | ||
461 | */ | ||
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c deleted file mode 100644 index 3032eb5e2467..000000000000 --- a/arch/um/kernel/tt/trap_user.c +++ /dev/null | |||
@@ -1,70 +0,0 @@ | |||
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 <signal.h> | ||
9 | #include "sysdep/ptrace.h" | ||
10 | #include "sysdep/sigcontext.h" | ||
11 | #include "kern_util.h" | ||
12 | #include "task.h" | ||
13 | #include "tt.h" | ||
14 | #include "os.h" | ||
15 | |||
16 | void sig_handler_common_tt(int sig, void *sc_ptr) | ||
17 | { | ||
18 | struct sigcontext *sc = sc_ptr; | ||
19 | struct tt_regs save_regs, *r; | ||
20 | int save_errno = errno, is_user = 0; | ||
21 | void (*handler)(int, union uml_pt_regs *); | ||
22 | |||
23 | /* This is done because to allow SIGSEGV to be delivered inside a SEGV | ||
24 | * handler. This can happen in copy_user, and if SEGV is disabled, | ||
25 | * the process will die. | ||
26 | */ | ||
27 | if(sig == SIGSEGV) | ||
28 | change_sig(SIGSEGV, 1); | ||
29 | |||
30 | r = &TASK_REGS(get_current())->tt; | ||
31 | if ( sig == SIGFPE || sig == SIGSEGV || | ||
32 | sig == SIGBUS || sig == SIGILL || | ||
33 | sig == SIGTRAP ) { | ||
34 | GET_FAULTINFO_FROM_SC(r->faultinfo, sc); | ||
35 | } | ||
36 | save_regs = *r; | ||
37 | if (sc) | ||
38 | is_user = user_context(SC_SP(sc)); | ||
39 | r->sc = sc; | ||
40 | if(sig != SIGUSR2) | ||
41 | r->syscall = -1; | ||
42 | |||
43 | handler = sig_info[sig]; | ||
44 | |||
45 | /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */ | ||
46 | if (sig != SIGIO && sig != SIGWINCH && | ||
47 | sig != SIGVTALRM && sig != SIGALRM) | ||
48 | unblock_signals(); | ||
49 | |||
50 | handler(sig, (union uml_pt_regs *) r); | ||
51 | |||
52 | if(is_user){ | ||
53 | interrupt_end(); | ||
54 | block_signals(); | ||
55 | set_user_mode(NULL); | ||
56 | } | ||
57 | *r = save_regs; | ||
58 | errno = save_errno; | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
63 | * Emacs will notice this stuff at the end of the file and automatically | ||
64 | * adjust the settings for this buffer only. This must remain at the end | ||
65 | * of the file. | ||
66 | * --------------------------------------------------------------------------- | ||
67 | * Local variables: | ||
68 | * c-file-style: "linux" | ||
69 | * End: | ||
70 | */ | ||
diff --git a/arch/um/kernel/tt/uaccess.c b/arch/um/kernel/tt/uaccess.c deleted file mode 100644 index 1cb60726567e..000000000000 --- a/arch/um/kernel/tt/uaccess.c +++ /dev/null | |||
@@ -1,73 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/sched.h" | ||
7 | #include "asm/uaccess.h" | ||
8 | |||
9 | int copy_from_user_tt(void *to, const void __user *from, int n) | ||
10 | { | ||
11 | if(!access_ok(VERIFY_READ, from, n)) | ||
12 | return(n); | ||
13 | |||
14 | return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr, | ||
15 | ¤t->thread.fault_catcher)); | ||
16 | } | ||
17 | |||
18 | int copy_to_user_tt(void __user *to, const void *from, int n) | ||
19 | { | ||
20 | if(!access_ok(VERIFY_WRITE, to, n)) | ||
21 | return(n); | ||
22 | |||
23 | return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr, | ||
24 | ¤t->thread.fault_catcher)); | ||
25 | } | ||
26 | |||
27 | int strncpy_from_user_tt(char *dst, const char __user *src, int count) | ||
28 | { | ||
29 | int n; | ||
30 | |||
31 | if(!access_ok(VERIFY_READ, src, 1)) | ||
32 | return(-EFAULT); | ||
33 | |||
34 | n = __do_strncpy_from_user(dst, src, count, | ||
35 | ¤t->thread.fault_addr, | ||
36 | ¤t->thread.fault_catcher); | ||
37 | if(n < 0) return(-EFAULT); | ||
38 | return(n); | ||
39 | } | ||
40 | |||
41 | int __clear_user_tt(void __user *mem, int len) | ||
42 | { | ||
43 | return(__do_clear_user(mem, len, | ||
44 | ¤t->thread.fault_addr, | ||
45 | ¤t->thread.fault_catcher)); | ||
46 | } | ||
47 | |||
48 | int clear_user_tt(void __user *mem, int len) | ||
49 | { | ||
50 | if(!access_ok(VERIFY_WRITE, mem, len)) | ||
51 | return(len); | ||
52 | |||
53 | return(__do_clear_user(mem, len, ¤t->thread.fault_addr, | ||
54 | ¤t->thread.fault_catcher)); | ||
55 | } | ||
56 | |||
57 | int strnlen_user_tt(const void __user *str, int len) | ||
58 | { | ||
59 | return(__do_strnlen_user(str, len, | ||
60 | ¤t->thread.fault_addr, | ||
61 | ¤t->thread.fault_catcher)); | ||
62 | } | ||
63 | |||
64 | /* | ||
65 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
66 | * Emacs will notice this stuff at the end of the file and automatically | ||
67 | * adjust the settings for this buffer only. This must remain at the end | ||
68 | * of the file. | ||
69 | * --------------------------------------------------------------------------- | ||
70 | * Local variables: | ||
71 | * c-file-style: "linux" | ||
72 | * End: | ||
73 | */ | ||
diff --git a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c deleted file mode 100644 index 0e5c82c5e5b7..000000000000 --- a/arch/um/kernel/tt/uaccess_user.c +++ /dev/null | |||
@@ -1,105 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) | ||
3 | * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include <string.h> | ||
8 | #include "uml_uaccess.h" | ||
9 | #include "task.h" | ||
10 | #include "kern_util.h" | ||
11 | #include "os.h" | ||
12 | #include "longjmp.h" | ||
13 | |||
14 | int __do_copy_from_user(void *to, const void *from, int n, | ||
15 | void **fault_addr, void **fault_catcher) | ||
16 | { | ||
17 | struct tt_regs save = TASK_REGS(get_current())->tt; | ||
18 | unsigned long fault; | ||
19 | int faulted; | ||
20 | |||
21 | fault = __do_user_copy(to, from, n, fault_addr, fault_catcher, | ||
22 | __do_copy, &faulted); | ||
23 | TASK_REGS(get_current())->tt = save; | ||
24 | |||
25 | if(!faulted) | ||
26 | return 0; | ||
27 | else if (fault) | ||
28 | return n - (fault - (unsigned long) from); | ||
29 | else | ||
30 | /* In case of a general protection fault, we don't have the | ||
31 | * fault address, so NULL is used instead. Pretend we didn't | ||
32 | * copy anything. */ | ||
33 | return n; | ||
34 | } | ||
35 | |||
36 | static void __do_strncpy(void *dst, const void *src, int count) | ||
37 | { | ||
38 | strncpy(dst, src, count); | ||
39 | } | ||
40 | |||
41 | int __do_strncpy_from_user(char *dst, const char *src, unsigned long count, | ||
42 | void **fault_addr, void **fault_catcher) | ||
43 | { | ||
44 | struct tt_regs save = TASK_REGS(get_current())->tt; | ||
45 | unsigned long fault; | ||
46 | int faulted; | ||
47 | |||
48 | fault = __do_user_copy(dst, src, count, fault_addr, fault_catcher, | ||
49 | __do_strncpy, &faulted); | ||
50 | TASK_REGS(get_current())->tt = save; | ||
51 | |||
52 | if(!faulted) return(strlen(dst)); | ||
53 | else return(-1); | ||
54 | } | ||
55 | |||
56 | static void __do_clear(void *to, const void *from, int n) | ||
57 | { | ||
58 | memset(to, 0, n); | ||
59 | } | ||
60 | |||
61 | int __do_clear_user(void *mem, unsigned long len, | ||
62 | void **fault_addr, void **fault_catcher) | ||
63 | { | ||
64 | struct tt_regs save = TASK_REGS(get_current())->tt; | ||
65 | unsigned long fault; | ||
66 | int faulted; | ||
67 | |||
68 | fault = __do_user_copy(mem, NULL, len, fault_addr, fault_catcher, | ||
69 | __do_clear, &faulted); | ||
70 | TASK_REGS(get_current())->tt = save; | ||
71 | |||
72 | if(!faulted) return(0); | ||
73 | else return(len - (fault - (unsigned long) mem)); | ||
74 | } | ||
75 | |||
76 | int __do_strnlen_user(const char *str, unsigned long n, | ||
77 | void **fault_addr, void **fault_catcher) | ||
78 | { | ||
79 | struct tt_regs save = TASK_REGS(get_current())->tt; | ||
80 | int ret; | ||
81 | unsigned long *faddrp = (unsigned long *)fault_addr; | ||
82 | jmp_buf jbuf; | ||
83 | |||
84 | *fault_catcher = &jbuf; | ||
85 | if(UML_SETJMP(&jbuf) == 0) | ||
86 | ret = strlen(str) + 1; | ||
87 | else ret = *faddrp - (unsigned long) str; | ||
88 | |||
89 | *fault_addr = NULL; | ||
90 | *fault_catcher = NULL; | ||
91 | |||
92 | TASK_REGS(get_current())->tt = save; | ||
93 | return ret; | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
98 | * Emacs will notice this stuff at the end of the file and automatically | ||
99 | * adjust the settings for this buffer only. This must remain at the end | ||
100 | * of the file. | ||
101 | * --------------------------------------------------------------------------- | ||
102 | * Local variables: | ||
103 | * c-file-style: "linux" | ||
104 | * End: | ||
105 | */ | ||
diff --git a/arch/um/kernel/uaccess.c b/arch/um/kernel/uaccess.c index 054e3de0784e..d7436aacd26f 100644 --- a/arch/um/kernel/uaccess.c +++ b/arch/um/kernel/uaccess.c | |||
@@ -18,7 +18,7 @@ void __do_copy(void *to, const void *from, int n) | |||
18 | 18 | ||
19 | 19 | ||
20 | int __do_copy_to_user(void *to, const void *from, int n, | 20 | int __do_copy_to_user(void *to, const void *from, int n, |
21 | void **fault_addr, void **fault_catcher) | 21 | void **fault_addr, jmp_buf **fault_catcher) |
22 | { | 22 | { |
23 | unsigned long fault; | 23 | unsigned long fault; |
24 | int faulted; | 24 | int faulted; |
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index ecc458fe51b9..f1c71393f578 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c | |||
@@ -1,46 +1,24 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/kernel.h" | ||
7 | #include "linux/sched.h" | ||
8 | #include "linux/notifier.h" | ||
9 | #include "linux/mm.h" | ||
10 | #include "linux/types.h" | ||
11 | #include "linux/tty.h" | ||
12 | #include "linux/init.h" | ||
13 | #include "linux/bootmem.h" | ||
14 | #include "linux/spinlock.h" | ||
15 | #include "linux/utsname.h" | ||
16 | #include "linux/sysrq.h" | ||
17 | #include "linux/seq_file.h" | ||
18 | #include "linux/delay.h" | 6 | #include "linux/delay.h" |
7 | #include "linux/mm.h" | ||
19 | #include "linux/module.h" | 8 | #include "linux/module.h" |
9 | #include "linux/seq_file.h" | ||
10 | #include "linux/string.h" | ||
20 | #include "linux/utsname.h" | 11 | #include "linux/utsname.h" |
21 | #include "asm/page.h" | ||
22 | #include "asm/pgtable.h" | 12 | #include "asm/pgtable.h" |
23 | #include "asm/ptrace.h" | 13 | #include "asm/processor.h" |
24 | #include "asm/elf.h" | ||
25 | #include "asm/user.h" | ||
26 | #include "asm/setup.h" | 14 | #include "asm/setup.h" |
27 | #include "ubd_user.h" | ||
28 | #include "asm/current.h" | ||
29 | #include "kern_util.h" | ||
30 | #include "as-layout.h" | ||
31 | #include "arch.h" | 15 | #include "arch.h" |
16 | #include "as-layout.h" | ||
17 | #include "init.h" | ||
32 | #include "kern.h" | 18 | #include "kern.h" |
33 | #include "mem_user.h" | 19 | #include "mem_user.h" |
34 | #include "mem.h" | ||
35 | #include "initrd.h" | ||
36 | #include "init.h" | ||
37 | #include "os.h" | 20 | #include "os.h" |
38 | #include "choose-mode.h" | ||
39 | #include "mode_kern.h" | ||
40 | #include "mode.h" | ||
41 | #ifdef UML_CONFIG_MODE_SKAS | ||
42 | #include "skas.h" | 21 | #include "skas.h" |
43 | #endif | ||
44 | 22 | ||
45 | #define DEFAULT_COMMAND_LINE "root=98:0" | 23 | #define DEFAULT_COMMAND_LINE "root=98:0" |
46 | 24 | ||
@@ -53,7 +31,7 @@ static void __init add_arg(char *arg) | |||
53 | printf("add_arg: Too many command line arguments!\n"); | 31 | printf("add_arg: Too many command line arguments!\n"); |
54 | exit(1); | 32 | exit(1); |
55 | } | 33 | } |
56 | if(strlen(command_line) > 0) | 34 | if (strlen(command_line) > 0) |
57 | strcat(command_line, " "); | 35 | strcat(command_line, " "); |
58 | strcat(command_line, arg); | 36 | strcat(command_line, arg); |
59 | } | 37 | } |
@@ -70,8 +48,8 @@ struct cpuinfo_um boot_cpu_data = { | |||
70 | 48 | ||
71 | unsigned long thread_saved_pc(struct task_struct *task) | 49 | unsigned long thread_saved_pc(struct task_struct *task) |
72 | { | 50 | { |
73 | return os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas, | 51 | /* FIXME: Need to look up userspace_pid by cpu */ |
74 | task)); | 52 | return os_process_pc(userspace_pid[0]); |
75 | } | 53 | } |
76 | 54 | ||
77 | /* Changed in setup_arch, which is called in early boot */ | 55 | /* Changed in setup_arch, which is called in early boot */ |
@@ -90,7 +68,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
90 | seq_printf(m, "processor\t: %d\n", index); | 68 | seq_printf(m, "processor\t: %d\n", index); |
91 | seq_printf(m, "vendor_id\t: User Mode Linux\n"); | 69 | seq_printf(m, "vendor_id\t: User Mode Linux\n"); |
92 | seq_printf(m, "model name\t: UML\n"); | 70 | seq_printf(m, "model name\t: UML\n"); |
93 | seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas")); | 71 | seq_printf(m, "mode\t\t: skas\n"); |
94 | seq_printf(m, "host\t\t: %s\n", host_info); | 72 | seq_printf(m, "host\t\t: %s\n", host_info); |
95 | seq_printf(m, "bogomips\t: %lu.%02lu\n\n", | 73 | seq_printf(m, "bogomips\t: %lu.%02lu\n\n", |
96 | loops_per_jiffy/(500000/HZ), | 74 | loops_per_jiffy/(500000/HZ), |
@@ -132,44 +110,13 @@ unsigned long end_vm; | |||
132 | /* Set in uml_ncpus_setup */ | 110 | /* Set in uml_ncpus_setup */ |
133 | int ncpus = 1; | 111 | int ncpus = 1; |
134 | 112 | ||
135 | #ifdef CONFIG_CMDLINE_ON_HOST | ||
136 | /* Pointer set in linux_main, the array itself is private to each thread, | ||
137 | * and changed at address space creation time so this poses no concurrency | ||
138 | * problems. | ||
139 | */ | ||
140 | static char *argv1_begin = NULL; | ||
141 | static char *argv1_end = NULL; | ||
142 | #endif | ||
143 | |||
144 | /* Set in early boot */ | 113 | /* Set in early boot */ |
145 | static int have_root __initdata = 0; | 114 | static int have_root __initdata = 0; |
146 | 115 | ||
147 | /* Set in uml_mem_setup and modified in linux_main */ | 116 | /* Set in uml_mem_setup and modified in linux_main */ |
148 | long long physmem_size = 32 * 1024 * 1024; | 117 | long long physmem_size = 32 * 1024 * 1024; |
149 | 118 | ||
150 | void set_cmdline(char *cmd) | 119 | static char *usage_string = |
151 | { | ||
152 | #ifdef CONFIG_CMDLINE_ON_HOST | ||
153 | char *umid, *ptr; | ||
154 | |||
155 | if(CHOOSE_MODE(honeypot, 0)) return; | ||
156 | |||
157 | umid = get_umid(); | ||
158 | if(*umid != '\0'){ | ||
159 | snprintf(argv1_begin, | ||
160 | (argv1_end - argv1_begin) * sizeof(*ptr), | ||
161 | "(%s) ", umid); | ||
162 | ptr = &argv1_begin[strlen(argv1_begin)]; | ||
163 | } | ||
164 | else ptr = argv1_begin; | ||
165 | |||
166 | snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd); | ||
167 | memset(argv1_begin + strlen(argv1_begin), '\0', | ||
168 | argv1_end - argv1_begin - strlen(argv1_begin)); | ||
169 | #endif | ||
170 | } | ||
171 | |||
172 | static char *usage_string = | ||
173 | "User Mode Linux v%s\n" | 120 | "User Mode Linux v%s\n" |
174 | " available at http://user-mode-linux.sourceforge.net/\n\n"; | 121 | " available at http://user-mode-linux.sourceforge.net/\n\n"; |
175 | 122 | ||
@@ -201,13 +148,10 @@ __uml_setup("root=", uml_root_setup, | |||
201 | " root=/dev/ubd5\n\n" | 148 | " root=/dev/ubd5\n\n" |
202 | ); | 149 | ); |
203 | 150 | ||
204 | #ifndef CONFIG_MODE_TT | ||
205 | |||
206 | static int __init no_skas_debug_setup(char *line, int *add) | 151 | static int __init no_skas_debug_setup(char *line, int *add) |
207 | { | 152 | { |
208 | printf("'debug' is not necessary to gdb UML in skas mode - run \n"); | 153 | printf("'debug' is not necessary to gdb UML in skas mode - run \n"); |
209 | printf("'gdb linux' and disable CONFIG_CMDLINE_ON_HOST if gdb \n"); | 154 | printf("'gdb linux'"); |
210 | printf("doesn't work as expected\n"); | ||
211 | 155 | ||
212 | return 0; | 156 | return 0; |
213 | } | 157 | } |
@@ -217,8 +161,6 @@ __uml_setup("debug", no_skas_debug_setup, | |||
217 | " this flag is not needed to run gdb on UML in skas mode\n\n" | 161 | " this flag is not needed to run gdb on UML in skas mode\n\n" |
218 | ); | 162 | ); |
219 | 163 | ||
220 | #endif | ||
221 | |||
222 | #ifdef CONFIG_SMP | 164 | #ifdef CONFIG_SMP |
223 | static int __init uml_ncpus_setup(char *line, int *add) | 165 | static int __init uml_ncpus_setup(char *line, int *add) |
224 | { | 166 | { |
@@ -232,56 +174,10 @@ static int __init uml_ncpus_setup(char *line, int *add) | |||
232 | 174 | ||
233 | __uml_setup("ncpus=", uml_ncpus_setup, | 175 | __uml_setup("ncpus=", uml_ncpus_setup, |
234 | "ncpus=<# of desired CPUs>\n" | 176 | "ncpus=<# of desired CPUs>\n" |
235 | " This tells an SMP kernel how many virtual processors to start.\n\n" | 177 | " This tells an SMP kernel how many virtual processors to start.\n\n" |
236 | ); | 178 | ); |
237 | #endif | 179 | #endif |
238 | 180 | ||
239 | static int force_tt = 0; | ||
240 | |||
241 | #if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS) | ||
242 | #define DEFAULT_TT 0 | ||
243 | |||
244 | static int __init mode_tt_setup(char *line, int *add) | ||
245 | { | ||
246 | force_tt = 1; | ||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | #else | ||
251 | #ifdef CONFIG_MODE_SKAS | ||
252 | |||
253 | #define DEFAULT_TT 0 | ||
254 | |||
255 | static int __init mode_tt_setup(char *line, int *add) | ||
256 | { | ||
257 | printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n"); | ||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | #else | ||
262 | #ifdef CONFIG_MODE_TT | ||
263 | |||
264 | #define DEFAULT_TT 1 | ||
265 | |||
266 | static int __init mode_tt_setup(char *line, int *add) | ||
267 | { | ||
268 | printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n"); | ||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | #endif | ||
273 | #endif | ||
274 | #endif | ||
275 | |||
276 | __uml_setup("mode=tt", mode_tt_setup, | ||
277 | "mode=tt\n" | ||
278 | " When both CONFIG_MODE_TT and CONFIG_MODE_SKAS are enabled, this option\n" | ||
279 | " forces UML to run in tt (tracing thread) mode. It is not the default\n" | ||
280 | " because it's slower and less secure than skas mode.\n\n" | ||
281 | ); | ||
282 | |||
283 | int mode_tt = DEFAULT_TT; | ||
284 | |||
285 | static int __init Usage(char *line, int *add) | 181 | static int __init Usage(char *line, int *add) |
286 | { | 182 | { |
287 | const char **p; | 183 | const char **p; |
@@ -310,9 +206,8 @@ static int __init uml_checksetup(char *line, int *add) | |||
310 | int n; | 206 | int n; |
311 | 207 | ||
312 | n = strlen(p->str); | 208 | n = strlen(p->str); |
313 | if(!strncmp(line, p->str, n)){ | 209 | if (!strncmp(line, p->str, n) && p->setup_func(line + n, add)) |
314 | if (p->setup_func(line + n, add)) return 1; | 210 | return 1; |
315 | } | ||
316 | p++; | 211 | p++; |
317 | } | 212 | } |
318 | return 0; | 213 | return 0; |
@@ -323,7 +218,7 @@ static void __init uml_postsetup(void) | |||
323 | initcall_t *p; | 218 | initcall_t *p; |
324 | 219 | ||
325 | p = &__uml_postsetup_start; | 220 | p = &__uml_postsetup_start; |
326 | while(p < &__uml_postsetup_end){ | 221 | while(p < &__uml_postsetup_end) { |
327 | (*p)(); | 222 | (*p)(); |
328 | p++; | 223 | p++; |
329 | } | 224 | } |
@@ -339,6 +234,20 @@ EXPORT_SYMBOL(end_iomem); | |||
339 | 234 | ||
340 | extern char __binary_start; | 235 | extern char __binary_start; |
341 | 236 | ||
237 | static unsigned long set_task_sizes_skas(unsigned long *task_size_out) | ||
238 | { | ||
239 | /* Round up to the nearest 4M */ | ||
240 | unsigned long host_task_size = ROUND_4M((unsigned long) | ||
241 | &host_task_size); | ||
242 | |||
243 | if (!skas_needs_stub) | ||
244 | *task_size_out = host_task_size; | ||
245 | else | ||
246 | *task_size_out = STUB_START & PGDIR_MASK; | ||
247 | |||
248 | return host_task_size; | ||
249 | } | ||
250 | |||
342 | int __init linux_main(int argc, char **argv) | 251 | int __init linux_main(int argc, char **argv) |
343 | { | 252 | { |
344 | unsigned long avail, diff; | 253 | unsigned long avail, diff; |
@@ -346,45 +255,30 @@ int __init linux_main(int argc, char **argv) | |||
346 | unsigned int i, add; | 255 | unsigned int i, add; |
347 | char * mode; | 256 | char * mode; |
348 | 257 | ||
349 | for (i = 1; i < argc; i++){ | 258 | for (i = 1; i < argc; i++) { |
350 | if((i == 1) && (argv[i][0] == ' ')) continue; | 259 | if ((i == 1) && (argv[i][0] == ' ')) |
260 | continue; | ||
351 | add = 1; | 261 | add = 1; |
352 | uml_checksetup(argv[i], &add); | 262 | uml_checksetup(argv[i], &add); |
353 | if (add) | 263 | if (add) |
354 | add_arg(argv[i]); | 264 | add_arg(argv[i]); |
355 | } | 265 | } |
356 | if(have_root == 0) | 266 | if (have_root == 0) |
357 | add_arg(DEFAULT_COMMAND_LINE); | 267 | add_arg(DEFAULT_COMMAND_LINE); |
358 | 268 | ||
269 | /* OS sanity checks that need to happen before the kernel runs */ | ||
359 | os_early_checks(); | 270 | os_early_checks(); |
360 | if (force_tt) | ||
361 | clear_can_do_skas(); | ||
362 | mode_tt = force_tt ? 1 : !can_do_skas(); | ||
363 | #ifndef CONFIG_MODE_TT | ||
364 | if (mode_tt) { | ||
365 | /*Since CONFIG_MODE_TT is #undef'ed, force_tt cannot be 1. So, | ||
366 | * can_do_skas() returned 0, and the message is correct. */ | ||
367 | printf("Support for TT mode is disabled, and no SKAS support is present on the host.\n"); | ||
368 | exit(1); | ||
369 | } | ||
370 | #endif | ||
371 | 271 | ||
372 | #ifndef CONFIG_MODE_SKAS | 272 | can_do_skas(); |
373 | mode = "TT"; | 273 | |
374 | #else | 274 | if (proc_mm && ptrace_faultinfo) |
375 | /* Show to the user the result of selection */ | ||
376 | if (mode_tt) | ||
377 | mode = "TT"; | ||
378 | else if (proc_mm && ptrace_faultinfo) | ||
379 | mode = "SKAS3"; | 275 | mode = "SKAS3"; |
380 | else | 276 | else |
381 | mode = "SKAS0"; | 277 | mode = "SKAS0"; |
382 | #endif | ||
383 | 278 | ||
384 | printf("UML running in %s mode\n", mode); | 279 | printf("UML running in %s mode\n", mode); |
385 | 280 | ||
386 | host_task_size = CHOOSE_MODE_PROC(set_task_sizes_tt, | 281 | host_task_size = set_task_sizes_skas(&task_size); |
387 | set_task_sizes_skas, &task_size); | ||
388 | 282 | ||
389 | /* | 283 | /* |
390 | * Setting up handlers to 'sig_info' struct | 284 | * Setting up handlers to 'sig_info' struct |
@@ -392,13 +286,15 @@ int __init linux_main(int argc, char **argv) | |||
392 | os_fill_handlinfo(handlinfo_kern); | 286 | os_fill_handlinfo(handlinfo_kern); |
393 | 287 | ||
394 | brk_start = (unsigned long) sbrk(0); | 288 | brk_start = (unsigned long) sbrk(0); |
395 | CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); | 289 | |
396 | /* Increase physical memory size for exec-shield users | 290 | /* |
397 | so they actually get what they asked for. This should | 291 | * Increase physical memory size for exec-shield users |
398 | add zero for non-exec shield users */ | 292 | * so they actually get what they asked for. This should |
293 | * add zero for non-exec shield users | ||
294 | */ | ||
399 | 295 | ||
400 | diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); | 296 | diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); |
401 | if(diff > 1024 * 1024){ | 297 | if (diff > 1024 * 1024) { |
402 | printf("Adding %ld bytes to physical memory to account for " | 298 | printf("Adding %ld bytes to physical memory to account for " |
403 | "exec-shield gap\n", diff); | 299 | "exec-shield gap\n", diff); |
404 | physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); | 300 | physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); |
@@ -411,20 +307,16 @@ int __init linux_main(int argc, char **argv) | |||
411 | 307 | ||
412 | setup_machinename(init_utsname()->machine); | 308 | setup_machinename(init_utsname()->machine); |
413 | 309 | ||
414 | #ifdef CONFIG_CMDLINE_ON_HOST | ||
415 | argv1_begin = argv[1]; | ||
416 | argv1_end = &argv[1][strlen(argv[1])]; | ||
417 | #endif | ||
418 | |||
419 | highmem = 0; | 310 | highmem = 0; |
420 | iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK; | 311 | iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK; |
421 | max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC; | 312 | max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC; |
422 | 313 | ||
423 | /* Zones have to begin on a 1 << MAX_ORDER page boundary, | 314 | /* |
315 | * Zones have to begin on a 1 << MAX_ORDER page boundary, | ||
424 | * so this makes sure that's true for highmem | 316 | * so this makes sure that's true for highmem |
425 | */ | 317 | */ |
426 | max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1); | 318 | max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1); |
427 | if(physmem_size + iomem_size > max_physmem){ | 319 | if (physmem_size + iomem_size > max_physmem) { |
428 | highmem = physmem_size + iomem_size - max_physmem; | 320 | highmem = physmem_size + iomem_size - max_physmem; |
429 | physmem_size -= highmem; | 321 | physmem_size -= highmem; |
430 | #ifndef CONFIG_HIGHMEM | 322 | #ifndef CONFIG_HIGHMEM |
@@ -441,7 +333,7 @@ int __init linux_main(int argc, char **argv) | |||
441 | start_vm = VMALLOC_START; | 333 | start_vm = VMALLOC_START; |
442 | 334 | ||
443 | setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); | 335 | setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); |
444 | if(init_maps(physmem_size, iomem_size, highmem)){ | 336 | if (init_maps(physmem_size, iomem_size, highmem)) { |
445 | printf("Failed to allocate mem_map for %Lu bytes of physical " | 337 | printf("Failed to allocate mem_map for %Lu bytes of physical " |
446 | "memory and %Lu bytes of highmem\n", physmem_size, | 338 | "memory and %Lu bytes of highmem\n", physmem_size, |
447 | highmem); | 339 | highmem); |
@@ -450,10 +342,11 @@ int __init linux_main(int argc, char **argv) | |||
450 | 342 | ||
451 | virtmem_size = physmem_size; | 343 | virtmem_size = physmem_size; |
452 | avail = get_kmem_end() - start_vm; | 344 | avail = get_kmem_end() - start_vm; |
453 | if(physmem_size > avail) virtmem_size = avail; | 345 | if (physmem_size > avail) |
346 | virtmem_size = avail; | ||
454 | end_vm = start_vm + virtmem_size; | 347 | end_vm = start_vm + virtmem_size; |
455 | 348 | ||
456 | if(virtmem_size < physmem_size) | 349 | if (virtmem_size < physmem_size) |
457 | printf("Kernel virtual memory size shrunk to %lu bytes\n", | 350 | printf("Kernel virtual memory size shrunk to %lu bytes\n", |
458 | virtmem_size); | 351 | virtmem_size); |
459 | 352 | ||
@@ -462,7 +355,7 @@ int __init linux_main(int argc, char **argv) | |||
462 | stack_protections((unsigned long) &init_thread_info); | 355 | stack_protections((unsigned long) &init_thread_info); |
463 | os_flush_stdout(); | 356 | os_flush_stdout(); |
464 | 357 | ||
465 | return CHOOSE_MODE(start_uml_tt(), start_uml_skas()); | 358 | return start_uml(); |
466 | } | 359 | } |
467 | 360 | ||
468 | extern int uml_exitcode; | 361 | extern int uml_exitcode; |
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index 81acdc24348e..13df191e2b41 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S | |||
@@ -18,13 +18,6 @@ SECTIONS | |||
18 | 18 | ||
19 | . = START + SIZEOF_HEADERS; | 19 | . = START + SIZEOF_HEADERS; |
20 | 20 | ||
21 | #ifdef MODE_TT | ||
22 | .remap_data : { UNMAP_PATH (.data .bss) } | ||
23 | .remap : { UNMAP_PATH (.text) } | ||
24 | |||
25 | . = ALIGN(4096); /* Init code and data */ | ||
26 | #endif | ||
27 | |||
28 | _text = .; | 21 | _text = .; |
29 | _stext = .; | 22 | _stext = .; |
30 | __init_begin = .; | 23 | __init_begin = .; |
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index 2f8c79464015..8e129af8170d 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile | |||
@@ -1,23 +1,18 @@ | |||
1 | # | 1 | # |
2 | # Copyright (C) 2000 Jeff Dike (jdike@karaya.com) | 2 | # Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | # Licensed under the GPL | 3 | # Licensed under the GPL |
4 | # | 4 | # |
5 | 5 | ||
6 | obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \ | 6 | obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \ |
7 | sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o umid.o tls.o \ | 7 | registers.o sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o \ |
8 | user_syms.o util.o drivers/ sys-$(SUBARCH)/ | 8 | umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/ |
9 | |||
10 | obj-$(CONFIG_MODE_SKAS) += skas/ | ||
11 | |||
12 | obj-$(CONFIG_MODE_TT) += tt.o | ||
13 | user-objs-$(CONFIG_MODE_TT) += tt.o | ||
14 | 9 | ||
15 | obj-$(CONFIG_TTY_LOG) += tty_log.o | 10 | obj-$(CONFIG_TTY_LOG) += tty_log.o |
16 | user-objs-$(CONFIG_TTY_LOG) += tty_log.o | 11 | user-objs-$(CONFIG_TTY_LOG) += tty_log.o |
17 | 12 | ||
18 | USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \ | 13 | USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \ |
19 | main.o mem.o process.o sigio.o signal.o start_up.o time.o trap.o tty.o \ | 14 | main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \ |
20 | tls.o uaccess.o umid.o util.o | 15 | trap.o tty.o tls.o uaccess.o umid.o util.o |
21 | 16 | ||
22 | CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) | 17 | CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) |
23 | 18 | ||
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index 59348359f9ab..4158118c4a56 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c | |||
@@ -1,20 +1,19 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdlib.h> | ||
7 | #include <unistd.h> | 6 | #include <unistd.h> |
7 | #include <sched.h> | ||
8 | #include <signal.h> | 8 | #include <signal.h> |
9 | #include <errno.h> | 9 | #include <errno.h> |
10 | #include <sched.h> | 10 | #include <sys/time.h> |
11 | #include <sys/syscall.h> | 11 | #include <asm/unistd.h> |
12 | #include "os.h" | ||
13 | #include "aio.h" | 12 | #include "aio.h" |
14 | #include "init.h" | 13 | #include "init.h" |
15 | #include "user.h" | ||
16 | #include "mode.h" | ||
17 | #include "kern_constants.h" | 14 | #include "kern_constants.h" |
15 | #include "os.h" | ||
16 | #include "user.h" | ||
18 | 17 | ||
19 | struct aio_thread_req { | 18 | struct aio_thread_req { |
20 | enum aio_type type; | 19 | enum aio_type type; |
@@ -28,7 +27,8 @@ struct aio_thread_req { | |||
28 | #if defined(HAVE_AIO_ABI) | 27 | #if defined(HAVE_AIO_ABI) |
29 | #include <linux/aio_abi.h> | 28 | #include <linux/aio_abi.h> |
30 | 29 | ||
31 | /* If we have the headers, we are going to build with AIO enabled. | 30 | /* |
31 | * If we have the headers, we are going to build with AIO enabled. | ||
32 | * If we don't have aio in libc, we define the necessary stubs here. | 32 | * If we don't have aio in libc, we define the necessary stubs here. |
33 | */ | 33 | */ |
34 | 34 | ||
@@ -52,7 +52,8 @@ static long io_getevents(aio_context_t ctx_id, long min_nr, long nr, | |||
52 | 52 | ||
53 | #endif | 53 | #endif |
54 | 54 | ||
55 | /* The AIO_MMAP cases force the mmapped page into memory here | 55 | /* |
56 | * The AIO_MMAP cases force the mmapped page into memory here | ||
56 | * rather than in whatever place first touches the data. I used | 57 | * rather than in whatever place first touches the data. I used |
57 | * to do this by touching the page, but that's delicate because | 58 | * to do this by touching the page, but that's delicate because |
58 | * gcc is prone to optimizing that away. So, what's done here | 59 | * gcc is prone to optimizing that away. So, what's done here |
@@ -106,12 +107,12 @@ static int aio_thread(void *arg) | |||
106 | 107 | ||
107 | signal(SIGWINCH, SIG_IGN); | 108 | signal(SIGWINCH, SIG_IGN); |
108 | 109 | ||
109 | while(1){ | 110 | while (1) { |
110 | n = io_getevents(ctx, 1, 1, &event, NULL); | 111 | n = io_getevents(ctx, 1, 1, &event, NULL); |
111 | if(n < 0){ | 112 | if (n < 0) { |
112 | if(errno == EINTR) | 113 | if (errno == EINTR) |
113 | continue; | 114 | continue; |
114 | printk("aio_thread - io_getevents failed, " | 115 | printk(UM_KERN_ERR "aio_thread - io_getevents failed, " |
115 | "errno = %d\n", errno); | 116 | "errno = %d\n", errno); |
116 | } | 117 | } |
117 | else { | 118 | else { |
@@ -120,9 +121,9 @@ static int aio_thread(void *arg) | |||
120 | .err = event.res }); | 121 | .err = event.res }); |
121 | reply_fd = ((struct aio_context *) reply.data)->reply_fd; | 122 | reply_fd = ((struct aio_context *) reply.data)->reply_fd; |
122 | err = write(reply_fd, &reply, sizeof(reply)); | 123 | err = write(reply_fd, &reply, sizeof(reply)); |
123 | if(err != sizeof(reply)) | 124 | if (err != sizeof(reply)) |
124 | printk("aio_thread - write failed, fd = %d, " | 125 | printk(UM_KERN_ERR "aio_thread - write failed, " |
125 | "err = %d\n", reply_fd, errno); | 126 | "fd = %d, err = %d\n", reply_fd, errno); |
126 | } | 127 | } |
127 | } | 128 | } |
128 | return 0; | 129 | return 0; |
@@ -137,10 +138,10 @@ static int do_not_aio(struct aio_thread_req *req) | |||
137 | int n; | 138 | int n; |
138 | 139 | ||
139 | actual = lseek64(req->io_fd, req->offset, SEEK_SET); | 140 | actual = lseek64(req->io_fd, req->offset, SEEK_SET); |
140 | if(actual != req->offset) | 141 | if (actual != req->offset) |
141 | return -errno; | 142 | return -errno; |
142 | 143 | ||
143 | switch(req->type){ | 144 | switch(req->type) { |
144 | case AIO_READ: | 145 | case AIO_READ: |
145 | n = read(req->io_fd, req->buf, req->len); | 146 | n = read(req->io_fd, req->buf, req->len); |
146 | break; | 147 | break; |
@@ -151,11 +152,12 @@ static int do_not_aio(struct aio_thread_req *req) | |||
151 | n = read(req->io_fd, &c, sizeof(c)); | 152 | n = read(req->io_fd, &c, sizeof(c)); |
152 | break; | 153 | break; |
153 | default: | 154 | default: |
154 | printk("do_not_aio - bad request type : %d\n", req->type); | 155 | printk(UM_KERN_ERR "do_not_aio - bad request type : %d\n", |
156 | req->type); | ||
155 | return -EINVAL; | 157 | return -EINVAL; |
156 | } | 158 | } |
157 | 159 | ||
158 | if(n < 0) | 160 | if (n < 0) |
159 | return -errno; | 161 | return -errno; |
160 | return 0; | 162 | return 0; |
161 | } | 163 | } |
@@ -173,16 +175,18 @@ static int not_aio_thread(void *arg) | |||
173 | int err; | 175 | int err; |
174 | 176 | ||
175 | signal(SIGWINCH, SIG_IGN); | 177 | signal(SIGWINCH, SIG_IGN); |
176 | while(1){ | 178 | while (1) { |
177 | err = read(aio_req_fd_r, &req, sizeof(req)); | 179 | err = read(aio_req_fd_r, &req, sizeof(req)); |
178 | if(err != sizeof(req)){ | 180 | if (err != sizeof(req)) { |
179 | if(err < 0) | 181 | if (err < 0) |
180 | printk("not_aio_thread - read failed, " | 182 | printk(UM_KERN_ERR "not_aio_thread - " |
181 | "fd = %d, err = %d\n", aio_req_fd_r, | 183 | "read failed, fd = %d, err = %d\n", |
184 | aio_req_fd_r, | ||
182 | errno); | 185 | errno); |
183 | else { | 186 | else { |
184 | printk("not_aio_thread - short read, fd = %d, " | 187 | printk(UM_KERN_ERR "not_aio_thread - short " |
185 | "length = %d\n", aio_req_fd_r, err); | 188 | "read, fd = %d, length = %d\n", |
189 | aio_req_fd_r, err); | ||
186 | } | 190 | } |
187 | continue; | 191 | continue; |
188 | } | 192 | } |
@@ -190,9 +194,9 @@ static int not_aio_thread(void *arg) | |||
190 | reply = ((struct aio_thread_reply) { .data = req.aio, | 194 | reply = ((struct aio_thread_reply) { .data = req.aio, |
191 | .err = err }); | 195 | .err = err }); |
192 | err = write(req.aio->reply_fd, &reply, sizeof(reply)); | 196 | err = write(req.aio->reply_fd, &reply, sizeof(reply)); |
193 | if(err != sizeof(reply)) | 197 | if (err != sizeof(reply)) |
194 | printk("not_aio_thread - write failed, fd = %d, " | 198 | printk(UM_KERN_ERR "not_aio_thread - write failed, " |
195 | "err = %d\n", req.aio->reply_fd, errno); | 199 | "fd = %d, err = %d\n", req.aio->reply_fd, errno); |
196 | } | 200 | } |
197 | 201 | ||
198 | return 0; | 202 | return 0; |
@@ -203,35 +207,36 @@ static int init_aio_24(void) | |||
203 | int fds[2], err; | 207 | int fds[2], err; |
204 | 208 | ||
205 | err = os_pipe(fds, 1, 1); | 209 | err = os_pipe(fds, 1, 1); |
206 | if(err) | 210 | if (err) |
207 | goto out; | 211 | goto out; |
208 | 212 | ||
209 | aio_req_fd_w = fds[0]; | 213 | aio_req_fd_w = fds[0]; |
210 | aio_req_fd_r = fds[1]; | 214 | aio_req_fd_r = fds[1]; |
211 | 215 | ||
212 | err = os_set_fd_block(aio_req_fd_w, 0); | 216 | err = os_set_fd_block(aio_req_fd_w, 0); |
213 | if(err) | 217 | if (err) |
214 | goto out_close_pipe; | 218 | goto out_close_pipe; |
215 | 219 | ||
216 | err = run_helper_thread(not_aio_thread, NULL, | 220 | err = run_helper_thread(not_aio_thread, NULL, |
217 | CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack); | 221 | CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack); |
218 | if(err < 0) | 222 | if (err < 0) |
219 | goto out_close_pipe; | 223 | goto out_close_pipe; |
220 | 224 | ||
221 | aio_pid = err; | 225 | aio_pid = err; |
222 | goto out; | 226 | goto out; |
223 | 227 | ||
224 | out_close_pipe: | 228 | out_close_pipe: |
225 | os_close_file(fds[0]); | 229 | close(fds[0]); |
226 | os_close_file(fds[1]); | 230 | close(fds[1]); |
227 | aio_req_fd_w = -1; | 231 | aio_req_fd_w = -1; |
228 | aio_req_fd_r = -1; | 232 | aio_req_fd_r = -1; |
229 | out: | 233 | out: |
230 | #ifndef HAVE_AIO_ABI | 234 | #ifndef HAVE_AIO_ABI |
231 | printk("/usr/include/linux/aio_abi.h not present during build\n"); | 235 | printk(UM_KERN_INFO "/usr/include/linux/aio_abi.h not present during " |
236 | "build\n"); | ||
232 | #endif | 237 | #endif |
233 | printk("2.6 host AIO support not used - falling back to I/O " | 238 | printk(UM_KERN_INFO "2.6 host AIO support not used - falling back to " |
234 | "thread\n"); | 239 | "I/O thread\n"); |
235 | return 0; | 240 | return 0; |
236 | } | 241 | } |
237 | 242 | ||
@@ -241,21 +246,21 @@ static int init_aio_26(void) | |||
241 | { | 246 | { |
242 | int err; | 247 | int err; |
243 | 248 | ||
244 | if(io_setup(256, &ctx)){ | 249 | if (io_setup(256, &ctx)) { |
245 | err = -errno; | 250 | err = -errno; |
246 | printk("aio_thread failed to initialize context, err = %d\n", | 251 | printk(UM_KERN_ERR "aio_thread failed to initialize context, " |
247 | errno); | 252 | "err = %d\n", errno); |
248 | return err; | 253 | return err; |
249 | } | 254 | } |
250 | 255 | ||
251 | err = run_helper_thread(aio_thread, NULL, | 256 | err = run_helper_thread(aio_thread, NULL, |
252 | CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack); | 257 | CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack); |
253 | if(err < 0) | 258 | if (err < 0) |
254 | return err; | 259 | return err; |
255 | 260 | ||
256 | aio_pid = err; | 261 | aio_pid = err; |
257 | 262 | ||
258 | printk("Using 2.6 host AIO\n"); | 263 | printk(UM_KERN_INFO "Using 2.6 host AIO\n"); |
259 | return 0; | 264 | return 0; |
260 | } | 265 | } |
261 | 266 | ||
@@ -266,13 +271,13 @@ static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, | |||
266 | int err; | 271 | int err; |
267 | 272 | ||
268 | err = do_aio(ctx, type, io_fd, buf, len, offset, aio); | 273 | err = do_aio(ctx, type, io_fd, buf, len, offset, aio); |
269 | if(err){ | 274 | if (err) { |
270 | reply = ((struct aio_thread_reply) { .data = aio, | 275 | reply = ((struct aio_thread_reply) { .data = aio, |
271 | .err = err }); | 276 | .err = err }); |
272 | err = write(aio->reply_fd, &reply, sizeof(reply)); | 277 | err = write(aio->reply_fd, &reply, sizeof(reply)); |
273 | if(err != sizeof(reply)){ | 278 | if (err != sizeof(reply)) { |
274 | err = -errno; | 279 | err = -errno; |
275 | printk("submit_aio_26 - write failed, " | 280 | printk(UM_KERN_ERR "submit_aio_26 - write failed, " |
276 | "fd = %d, err = %d\n", aio->reply_fd, -err); | 281 | "fd = %d, err = %d\n", aio->reply_fd, -err); |
277 | } | 282 | } |
278 | else err = 0; | 283 | else err = 0; |
@@ -320,28 +325,24 @@ static int init_aio(void) | |||
320 | { | 325 | { |
321 | int err; | 326 | int err; |
322 | 327 | ||
323 | CHOOSE_MODE(({ if(!aio_24){ | 328 | if (!aio_24) { |
324 | printk("Disabling 2.6 AIO in tt mode\n"); | ||
325 | aio_24 = 1; | ||
326 | } }), (void) 0); | ||
327 | |||
328 | if(!aio_24){ | ||
329 | err = init_aio_26(); | 329 | err = init_aio_26(); |
330 | if(err && (errno == ENOSYS)){ | 330 | if (err && (errno == ENOSYS)) { |
331 | printk("2.6 AIO not supported on the host - " | 331 | printk(UM_KERN_INFO "2.6 AIO not supported on the " |
332 | "reverting to 2.4 AIO\n"); | 332 | "host - reverting to 2.4 AIO\n"); |
333 | aio_24 = 1; | 333 | aio_24 = 1; |
334 | } | 334 | } |
335 | else return err; | 335 | else return err; |
336 | } | 336 | } |
337 | 337 | ||
338 | if(aio_24) | 338 | if (aio_24) |
339 | return init_aio_24(); | 339 | return init_aio_24(); |
340 | 340 | ||
341 | return 0; | 341 | return 0; |
342 | } | 342 | } |
343 | 343 | ||
344 | /* The reason for the __initcall/__uml_exitcall asymmetry is that init_aio | 344 | /* |
345 | * The reason for the __initcall/__uml_exitcall asymmetry is that init_aio | ||
345 | * needs to be called when the kernel is running because it calls run_helper, | 346 | * needs to be called when the kernel is running because it calls run_helper, |
346 | * which needs get_free_page. exit_aio is a __uml_exitcall because the generic | 347 | * which needs get_free_page. exit_aio is a __uml_exitcall because the generic |
347 | * kernel does not run __exitcalls on shutdown, and can't because many of them | 348 | * kernel does not run __exitcalls on shutdown, and can't because many of them |
@@ -372,7 +373,7 @@ static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len, | |||
372 | int err; | 373 | int err; |
373 | 374 | ||
374 | err = write(aio_req_fd_w, &req, sizeof(req)); | 375 | err = write(aio_req_fd_w, &req, sizeof(req)); |
375 | if(err == sizeof(req)) | 376 | if (err == sizeof(req)) |
376 | err = 0; | 377 | err = 0; |
377 | else err = -errno; | 378 | else err = -errno; |
378 | 379 | ||
@@ -384,9 +385,8 @@ int submit_aio(enum aio_type type, int io_fd, char *buf, int len, | |||
384 | struct aio_context *aio) | 385 | struct aio_context *aio) |
385 | { | 386 | { |
386 | aio->reply_fd = reply_fd; | 387 | aio->reply_fd = reply_fd; |
387 | if(aio_24) | 388 | if (aio_24) |
388 | return submit_aio_24(type, io_fd, buf, len, offset, aio); | 389 | return submit_aio_24(type, io_fd, buf, len, offset, aio); |
389 | else { | 390 | else |
390 | return submit_aio_26(type, io_fd, buf, len, offset, aio); | 391 | return submit_aio_26(type, io_fd, buf, len, offset, aio); |
391 | } | ||
392 | } | 392 | } |
diff --git a/arch/um/os-Linux/drivers/etap.h b/arch/um/os-Linux/drivers/etap.h index 57ecdaf2f67e..ddffd41c3f3f 100644 --- a/arch/um/os-Linux/drivers/etap.h +++ b/arch/um/os-Linux/drivers/etap.h | |||
@@ -1,8 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #ifndef __DRIVERS_ETAP_H | ||
7 | #define __DRIVERS_ETAP_H | ||
8 | |||
6 | #include "net_user.h" | 9 | #include "net_user.h" |
7 | 10 | ||
8 | struct ethertap_data { | 11 | struct ethertap_data { |
@@ -15,13 +18,4 @@ struct ethertap_data { | |||
15 | 18 | ||
16 | extern const struct net_user_info ethertap_user_info; | 19 | extern const struct net_user_info ethertap_user_info; |
17 | 20 | ||
18 | /* | 21 | #endif |
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 index 12689141414d..04f11b9f1ac0 100644 --- a/arch/um/os-Linux/drivers/ethertap_kern.c +++ b/arch/um/os-Linux/drivers/ethertap_kern.c | |||
@@ -1,16 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and | 2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and |
3 | * James Leu (jleu@mindspring.net). | 3 | * James Leu (jleu@mindspring.net). |
4 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
4 | * Copyright (C) 2001 by various other people who didn't put their name here. | 5 | * Copyright (C) 2001 by various other people who didn't put their name here. |
5 | * Licensed under the GPL. | 6 | * Licensed under the GPL. |
6 | */ | 7 | */ |
7 | 8 | ||
8 | #include "linux/init.h" | 9 | #include "linux/init.h" |
9 | #include "linux/netdevice.h" | 10 | #include <linux/netdevice.h> |
10 | #include "linux/etherdevice.h" | ||
11 | #include "net_kern.h" | ||
12 | #include "net_user.h" | ||
13 | #include "etap.h" | 11 | #include "etap.h" |
12 | #include "net_kern.h" | ||
14 | 13 | ||
15 | struct ethertap_init { | 14 | struct ethertap_init { |
16 | char *dev_name; | 15 | char *dev_name; |
@@ -37,32 +36,24 @@ static void etap_init(struct net_device *dev, void *data) | |||
37 | printk("\n"); | 36 | printk("\n"); |
38 | } | 37 | } |
39 | 38 | ||
40 | static int etap_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) | 39 | static int etap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) |
41 | { | 40 | { |
42 | int len; | 41 | int len; |
43 | 42 | ||
44 | *skb = ether_adjust_skb(*skb, ETH_HEADER_ETHERTAP); | 43 | len = net_recvfrom(fd, skb_mac_header(skb), |
45 | if(*skb == NULL) return(-ENOMEM); | 44 | skb->dev->mtu + 2 + ETH_HEADER_ETHERTAP); |
46 | len = net_recvfrom(fd, skb_mac_header(*skb), | 45 | if (len <= 0) |
47 | (*skb)->dev->mtu + 2 * ETH_HEADER_ETHERTAP); | 46 | return(len); |
48 | if(len <= 0) return(len); | 47 | |
49 | skb_pull(*skb, 2); | 48 | skb_pull(skb, 2); |
50 | len -= 2; | 49 | len -= 2; |
51 | return(len); | 50 | return len; |
52 | } | 51 | } |
53 | 52 | ||
54 | static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) | 53 | static int etap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) |
55 | { | 54 | { |
56 | if(skb_headroom(*skb) < 2){ | 55 | skb_push(skb, 2); |
57 | struct sk_buff *skb2; | 56 | return net_send(fd, skb->data, skb->len); |
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 | } | 57 | } |
67 | 58 | ||
68 | const struct net_kern_info ethertap_kern_info = { | 59 | const struct net_kern_info ethertap_kern_info = { |
@@ -79,15 +70,15 @@ int ethertap_setup(char *str, char **mac_out, void *data) | |||
79 | *init = ((struct ethertap_init) | 70 | *init = ((struct ethertap_init) |
80 | { .dev_name = NULL, | 71 | { .dev_name = NULL, |
81 | .gate_addr = NULL }); | 72 | .gate_addr = NULL }); |
82 | if(tap_setup_common(str, "ethertap", &init->dev_name, mac_out, | 73 | if (tap_setup_common(str, "ethertap", &init->dev_name, mac_out, |
83 | &init->gate_addr)) | 74 | &init->gate_addr)) |
84 | return(0); | 75 | return 0; |
85 | if(init->dev_name == NULL){ | 76 | if (init->dev_name == NULL) { |
86 | printk("ethertap_setup : Missing tap device name\n"); | 77 | printk(KERN_ERR "ethertap_setup : Missing tap device name\n"); |
87 | return(0); | 78 | return 0; |
88 | } | 79 | } |
89 | 80 | ||
90 | return(1); | 81 | return 1; |
91 | } | 82 | } |
92 | 83 | ||
93 | static struct transport ethertap_transport = { | 84 | static struct transport ethertap_transport = { |
@@ -97,6 +88,7 @@ static struct transport ethertap_transport = { | |||
97 | .user = ðertap_user_info, | 88 | .user = ðertap_user_info, |
98 | .kern = ðertap_kern_info, | 89 | .kern = ðertap_kern_info, |
99 | .private_size = sizeof(struct ethertap_data), | 90 | .private_size = sizeof(struct ethertap_data), |
91 | .setup_size = sizeof(struct ethertap_init), | ||
100 | }; | 92 | }; |
101 | 93 | ||
102 | static int register_ethertap(void) | 94 | static int register_ethertap(void) |
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c index 61d3953c7ac9..4ff553603449 100644 --- a/arch/um/os-Linux/drivers/ethertap_user.c +++ b/arch/um/os-Linux/drivers/ethertap_user.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and | 3 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and |
3 | * James Leu (jleu@mindspring.net). | 4 | * James Leu (jleu@mindspring.net). |
4 | * Copyright (C) 2001 by various other people who didn't put their name here. | 5 | * Copyright (C) 2001 by various other people who didn't put their name here. |
@@ -7,20 +8,16 @@ | |||
7 | 8 | ||
8 | #include <stdio.h> | 9 | #include <stdio.h> |
9 | #include <unistd.h> | 10 | #include <unistd.h> |
10 | #include <stddef.h> | 11 | #include <errno.h> |
11 | #include <stdlib.h> | 12 | #include <string.h> |
12 | #include <sys/errno.h> | ||
13 | #include <sys/socket.h> | 13 | #include <sys/socket.h> |
14 | #include <sys/wait.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 "net_user.h" | ||
20 | #include "etap.h" | 15 | #include "etap.h" |
16 | #include "kern_constants.h" | ||
21 | #include "os.h" | 17 | #include "os.h" |
18 | #include "net_user.h" | ||
22 | #include "um_malloc.h" | 19 | #include "um_malloc.h" |
23 | #include "kern_constants.h" | 20 | #include "user.h" |
24 | 21 | ||
25 | #define MAX_PACKET ETH_MAX_PACKET | 22 | #define MAX_PACKET ETH_MAX_PACKET |
26 | 23 | ||
@@ -49,16 +46,18 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask, | |||
49 | memcpy(change.addr, addr, sizeof(change.addr)); | 46 | memcpy(change.addr, addr, sizeof(change.addr)); |
50 | memcpy(change.netmask, netmask, sizeof(change.netmask)); | 47 | memcpy(change.netmask, netmask, sizeof(change.netmask)); |
51 | CATCH_EINTR(n = write(fd, &change, sizeof(change))); | 48 | CATCH_EINTR(n = write(fd, &change, sizeof(change))); |
52 | if(n != sizeof(change)){ | 49 | if (n != sizeof(change)) { |
53 | printk("etap_change - request failed, err = %d\n", errno); | 50 | printk(UM_KERN_ERR "etap_change - request failed, err = %d\n", |
51 | errno); | ||
54 | return; | 52 | return; |
55 | } | 53 | } |
56 | 54 | ||
57 | output = kmalloc(UM_KERN_PAGE_SIZE, UM_GFP_KERNEL); | 55 | output = kmalloc(UM_KERN_PAGE_SIZE, UM_GFP_KERNEL); |
58 | if(output == NULL) | 56 | if (output == NULL) |
59 | printk("etap_change : Failed to allocate output buffer\n"); | 57 | printk(UM_KERN_ERR "etap_change : Failed to allocate output " |
58 | "buffer\n"); | ||
60 | read_output(fd, output, UM_KERN_PAGE_SIZE); | 59 | read_output(fd, output, UM_KERN_PAGE_SIZE); |
61 | if(output != NULL){ | 60 | if (output != NULL) { |
62 | printk("%s", output); | 61 | printk("%s", output); |
63 | kfree(output); | 62 | kfree(output); |
64 | } | 63 | } |
@@ -87,11 +86,11 @@ static void etap_pre_exec(void *arg) | |||
87 | struct etap_pre_exec_data *data = arg; | 86 | struct etap_pre_exec_data *data = arg; |
88 | 87 | ||
89 | dup2(data->control_remote, 1); | 88 | dup2(data->control_remote, 1); |
90 | os_close_file(data->data_me); | 89 | close(data->data_me); |
91 | os_close_file(data->control_me); | 90 | close(data->control_me); |
92 | } | 91 | } |
93 | 92 | ||
94 | static int etap_tramp(char *dev, char *gate, int control_me, | 93 | static int etap_tramp(char *dev, char *gate, int control_me, |
95 | int control_remote, int data_me, int data_remote) | 94 | int control_remote, int data_me, int data_remote) |
96 | { | 95 | { |
97 | struct etap_pre_exec_data pe_data; | 96 | struct etap_pre_exec_data pe_data; |
@@ -101,13 +100,13 @@ static int etap_tramp(char *dev, char *gate, int control_me, | |||
101 | char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; | 100 | char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; |
102 | char *setup_args[] = { "uml_net", version_buf, "ethertap", dev, | 101 | char *setup_args[] = { "uml_net", version_buf, "ethertap", dev, |
103 | data_fd_buf, gate_buf, NULL }; | 102 | data_fd_buf, gate_buf, NULL }; |
104 | char *nosetup_args[] = { "uml_net", version_buf, "ethertap", | 103 | char *nosetup_args[] = { "uml_net", version_buf, "ethertap", |
105 | dev, data_fd_buf, NULL }; | 104 | dev, data_fd_buf, NULL }; |
106 | char **args, c; | 105 | char **args, c; |
107 | 106 | ||
108 | sprintf(data_fd_buf, "%d", data_remote); | 107 | sprintf(data_fd_buf, "%d", data_remote); |
109 | sprintf(version_buf, "%d", UML_NET_VERSION); | 108 | sprintf(version_buf, "%d", UML_NET_VERSION); |
110 | if(gate != NULL){ | 109 | if (gate != NULL) { |
111 | strcpy(gate_buf, gate); | 110 | strcpy(gate_buf, gate); |
112 | args = setup_args; | 111 | args = setup_args; |
113 | } | 112 | } |
@@ -119,24 +118,26 @@ static int etap_tramp(char *dev, char *gate, int control_me, | |||
119 | pe_data.data_me = data_me; | 118 | pe_data.data_me = data_me; |
120 | pid = run_helper(etap_pre_exec, &pe_data, args); | 119 | pid = run_helper(etap_pre_exec, &pe_data, args); |
121 | 120 | ||
122 | if(pid < 0) | 121 | if (pid < 0) |
123 | err = pid; | 122 | err = pid; |
124 | os_close_file(data_remote); | 123 | close(data_remote); |
125 | os_close_file(control_remote); | 124 | close(control_remote); |
126 | CATCH_EINTR(n = read(control_me, &c, sizeof(c))); | 125 | CATCH_EINTR(n = read(control_me, &c, sizeof(c))); |
127 | if(n != sizeof(c)){ | 126 | if (n != sizeof(c)) { |
128 | err = -errno; | 127 | err = -errno; |
129 | printk("etap_tramp : read of status failed, err = %d\n", -err); | 128 | printk(UM_KERN_ERR "etap_tramp : read of status failed, " |
129 | "err = %d\n", -err); | ||
130 | return err; | 130 | return err; |
131 | } | 131 | } |
132 | if(c != 1){ | 132 | if (c != 1) { |
133 | printk("etap_tramp : uml_net failed\n"); | 133 | printk(UM_KERN_ERR "etap_tramp : uml_net failed\n"); |
134 | err = -EINVAL; | 134 | err = -EINVAL; |
135 | CATCH_EINTR(n = waitpid(pid, &status, 0)); | 135 | CATCH_EINTR(n = waitpid(pid, &status, 0)); |
136 | if(n < 0) | 136 | if (n < 0) |
137 | err = -errno; | 137 | err = -errno; |
138 | else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)) | 138 | else if (!WIFEXITED(status) || (WEXITSTATUS(status) != 1)) |
139 | printk("uml_net didn't exit with status 1\n"); | 139 | printk(UM_KERN_ERR "uml_net didn't exit with " |
140 | "status 1\n"); | ||
140 | } | 141 | } |
141 | return err; | 142 | return err; |
142 | } | 143 | } |
@@ -148,43 +149,56 @@ static int etap_open(void *data) | |||
148 | int data_fds[2], control_fds[2], err, output_len; | 149 | int data_fds[2], control_fds[2], err, output_len; |
149 | 150 | ||
150 | err = tap_open_common(pri->dev, pri->gate_addr); | 151 | err = tap_open_common(pri->dev, pri->gate_addr); |
151 | if(err) | 152 | if (err) |
152 | return err; | 153 | return err; |
153 | 154 | ||
154 | err = os_pipe(data_fds, 0, 0); | 155 | err = socketpair(AF_UNIX, SOCK_DGRAM, 0, data_fds); |
155 | if(err < 0){ | 156 | if (err) { |
156 | printk("data os_pipe failed - err = %d\n", -err); | 157 | err = -errno; |
158 | printk(UM_KERN_ERR "etap_open - data socketpair failed - " | ||
159 | "err = %d\n", errno); | ||
157 | return err; | 160 | return err; |
158 | } | 161 | } |
159 | 162 | ||
160 | err = os_pipe(control_fds, 1, 0); | 163 | err = socketpair(AF_UNIX, SOCK_STREAM, 0, control_fds); |
161 | if(err < 0){ | 164 | if (err) { |
162 | printk("control os_pipe failed - err = %d\n", -err); | 165 | err = -errno; |
163 | return err; | 166 | printk(UM_KERN_ERR "etap_open - control socketpair failed - " |
167 | "err = %d\n", errno); | ||
168 | goto out_close_data; | ||
164 | } | 169 | } |
165 | 170 | ||
166 | err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], | 171 | err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], |
167 | control_fds[1], data_fds[0], data_fds[1]); | 172 | control_fds[1], data_fds[0], data_fds[1]); |
168 | output_len = UM_KERN_PAGE_SIZE; | 173 | output_len = UM_KERN_PAGE_SIZE; |
169 | output = kmalloc(output_len, UM_GFP_KERNEL); | 174 | output = kmalloc(output_len, UM_GFP_KERNEL); |
170 | read_output(control_fds[0], output, output_len); | 175 | read_output(control_fds[0], output, output_len); |
171 | 176 | ||
172 | if(output == NULL) | 177 | if (output == NULL) |
173 | printk("etap_open : failed to allocate output buffer\n"); | 178 | printk(UM_KERN_ERR "etap_open : failed to allocate output " |
179 | "buffer\n"); | ||
174 | else { | 180 | else { |
175 | printk("%s", output); | 181 | printk("%s", output); |
176 | kfree(output); | 182 | kfree(output); |
177 | } | 183 | } |
178 | 184 | ||
179 | if(err < 0){ | 185 | if (err < 0) { |
180 | printk("etap_tramp failed - err = %d\n", -err); | 186 | printk(UM_KERN_ERR "etap_tramp failed - err = %d\n", -err); |
181 | return err; | 187 | goto out_close_control; |
182 | } | 188 | } |
183 | 189 | ||
184 | pri->data_fd = data_fds[0]; | 190 | pri->data_fd = data_fds[0]; |
185 | pri->control_fd = control_fds[0]; | 191 | pri->control_fd = control_fds[0]; |
186 | iter_addresses(pri->dev, etap_open_addr, &pri->control_fd); | 192 | iter_addresses(pri->dev, etap_open_addr, &pri->control_fd); |
187 | return data_fds[0]; | 193 | return data_fds[0]; |
194 | |||
195 | out_close_control: | ||
196 | close(control_fds[0]); | ||
197 | close(control_fds[1]); | ||
198 | out_close_data: | ||
199 | close(data_fds[0]); | ||
200 | close(data_fds[1]); | ||
201 | return err; | ||
188 | } | 202 | } |
189 | 203 | ||
190 | static void etap_close(int fd, void *data) | 204 | static void etap_close(int fd, void *data) |
@@ -192,37 +206,41 @@ static void etap_close(int fd, void *data) | |||
192 | struct ethertap_data *pri = data; | 206 | struct ethertap_data *pri = data; |
193 | 207 | ||
194 | iter_addresses(pri->dev, etap_close_addr, &pri->control_fd); | 208 | iter_addresses(pri->dev, etap_close_addr, &pri->control_fd); |
195 | os_close_file(fd); | 209 | close(fd); |
196 | os_shutdown_socket(pri->data_fd, 1, 1); | 210 | |
197 | os_close_file(pri->data_fd); | 211 | if (shutdown(pri->data_fd, SHUT_RDWR) < 0) |
212 | printk(UM_KERN_ERR "etap_close - shutdown data socket failed, " | ||
213 | "errno = %d\n", errno); | ||
214 | |||
215 | if (shutdown(pri->control_fd, SHUT_RDWR) < 0) | ||
216 | printk(UM_KERN_ERR "etap_close - shutdown control socket " | ||
217 | "failed, errno = %d\n", errno); | ||
218 | |||
219 | close(pri->data_fd); | ||
198 | pri->data_fd = -1; | 220 | pri->data_fd = -1; |
199 | os_close_file(pri->control_fd); | 221 | close(pri->control_fd); |
200 | pri->control_fd = -1; | 222 | pri->control_fd = -1; |
201 | } | 223 | } |
202 | 224 | ||
203 | static int etap_set_mtu(int mtu, void *data) | ||
204 | { | ||
205 | return mtu; | ||
206 | } | ||
207 | |||
208 | static void etap_add_addr(unsigned char *addr, unsigned char *netmask, | 225 | static void etap_add_addr(unsigned char *addr, unsigned char *netmask, |
209 | void *data) | 226 | void *data) |
210 | { | 227 | { |
211 | struct ethertap_data *pri = data; | 228 | struct ethertap_data *pri = data; |
212 | 229 | ||
213 | tap_check_ips(pri->gate_addr, addr); | 230 | tap_check_ips(pri->gate_addr, addr); |
214 | if(pri->control_fd == -1) | 231 | if (pri->control_fd == -1) |
215 | return; | 232 | return; |
216 | etap_open_addr(addr, netmask, &pri->control_fd); | 233 | etap_open_addr(addr, netmask, &pri->control_fd); |
217 | } | 234 | } |
218 | 235 | ||
219 | static void etap_del_addr(unsigned char *addr, unsigned char *netmask, | 236 | static void etap_del_addr(unsigned char *addr, unsigned char *netmask, |
220 | void *data) | 237 | void *data) |
221 | { | 238 | { |
222 | struct ethertap_data *pri = data; | 239 | struct ethertap_data *pri = data; |
223 | 240 | ||
224 | if(pri->control_fd == -1) | 241 | if (pri->control_fd == -1) |
225 | return; | 242 | return; |
243 | |||
226 | etap_close_addr(addr, netmask, &pri->control_fd); | 244 | etap_close_addr(addr, netmask, &pri->control_fd); |
227 | } | 245 | } |
228 | 246 | ||
@@ -231,8 +249,8 @@ const struct net_user_info ethertap_user_info = { | |||
231 | .open = etap_open, | 249 | .open = etap_open, |
232 | .close = etap_close, | 250 | .close = etap_close, |
233 | .remove = NULL, | 251 | .remove = NULL, |
234 | .set_mtu = etap_set_mtu, | ||
235 | .add_address = etap_add_addr, | 252 | .add_address = etap_add_addr, |
236 | .delete_address = etap_del_addr, | 253 | .delete_address = etap_del_addr, |
237 | .max_packet = MAX_PACKET - ETH_HEADER_ETHERTAP | 254 | .mtu = ETH_MAX_PACKET, |
255 | .max_packet = ETH_MAX_PACKET + ETH_HEADER_ETHERTAP, | ||
238 | }; | 256 | }; |
diff --git a/arch/um/os-Linux/drivers/tuntap.h b/arch/um/os-Linux/drivers/tuntap.h index d3e8d3af6245..f17c31586c84 100644 --- a/arch/um/os-Linux/drivers/tuntap.h +++ b/arch/um/os-Linux/drivers/tuntap.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -19,14 +19,3 @@ struct tuntap_data { | |||
19 | extern const struct net_user_info tuntap_user_info; | 19 | extern const struct net_user_info tuntap_user_info; |
20 | 20 | ||
21 | #endif | 21 | #endif |
22 | |||
23 | /* | ||
24 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
25 | * Emacs will notice this stuff at the end of the file and automatically | ||
26 | * adjust the settings for this buffer only. This must remain at the end | ||
27 | * of the file. | ||
28 | * --------------------------------------------------------------------------- | ||
29 | * Local variables: | ||
30 | * c-file-style: "linux" | ||
31 | * End: | ||
32 | */ | ||
diff --git a/arch/um/os-Linux/drivers/tuntap_kern.c b/arch/um/os-Linux/drivers/tuntap_kern.c index f1714e7fb1d0..9d384807b077 100644 --- a/arch/um/os-Linux/drivers/tuntap_kern.c +++ b/arch/um/os-Linux/drivers/tuntap_kern.c | |||
@@ -1,16 +1,13 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/stddef.h" | 6 | #include <linux/netdevice.h> |
7 | #include "linux/netdevice.h" | 7 | #include <linux/init.h> |
8 | #include "linux/etherdevice.h" | 8 | #include <linux/skbuff.h> |
9 | #include "linux/skbuff.h" | 9 | #include <asm/errno.h> |
10 | #include "linux/init.h" | ||
11 | #include "asm/errno.h" | ||
12 | #include "net_kern.h" | 10 | #include "net_kern.h" |
13 | #include "net_user.h" | ||
14 | #include "tuntap.h" | 11 | #include "tuntap.h" |
15 | 12 | ||
16 | struct tuntap_init { | 13 | struct tuntap_init { |
@@ -38,19 +35,15 @@ static void tuntap_init(struct net_device *dev, void *data) | |||
38 | printk("\n"); | 35 | printk("\n"); |
39 | } | 36 | } |
40 | 37 | ||
41 | static int tuntap_read(int fd, struct sk_buff **skb, | 38 | static int tuntap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) |
42 | struct uml_net_private *lp) | ||
43 | { | 39 | { |
44 | *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); | 40 | return net_read(fd, skb_mac_header(skb), |
45 | if(*skb == NULL) return(-ENOMEM); | 41 | skb->dev->mtu + ETH_HEADER_OTHER); |
46 | return(net_read(fd, skb_mac_header(*skb), | ||
47 | (*skb)->dev->mtu + ETH_HEADER_OTHER)); | ||
48 | } | 42 | } |
49 | 43 | ||
50 | static int tuntap_write(int fd, struct sk_buff **skb, | 44 | static int tuntap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) |
51 | struct uml_net_private *lp) | ||
52 | { | 45 | { |
53 | return(net_write(fd, (*skb)->data, (*skb)->len)); | 46 | return net_write(fd, skb->data, skb->len); |
54 | } | 47 | } |
55 | 48 | ||
56 | const struct net_kern_info tuntap_kern_info = { | 49 | const struct net_kern_info tuntap_kern_info = { |
@@ -67,11 +60,11 @@ int tuntap_setup(char *str, char **mac_out, void *data) | |||
67 | *init = ((struct tuntap_init) | 60 | *init = ((struct tuntap_init) |
68 | { .dev_name = NULL, | 61 | { .dev_name = NULL, |
69 | .gate_addr = NULL }); | 62 | .gate_addr = NULL }); |
70 | if(tap_setup_common(str, "tuntap", &init->dev_name, mac_out, | 63 | if (tap_setup_common(str, "tuntap", &init->dev_name, mac_out, |
71 | &init->gate_addr)) | 64 | &init->gate_addr)) |
72 | return(0); | 65 | return 0; |
73 | 66 | ||
74 | return(1); | 67 | return 1; |
75 | } | 68 | } |
76 | 69 | ||
77 | static struct transport tuntap_transport = { | 70 | static struct transport tuntap_transport = { |
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c index f848b4ea9343..6c55d3c8ead8 100644 --- a/arch/um/os-Linux/drivers/tuntap_user.c +++ b/arch/um/os-Linux/drivers/tuntap_user.c | |||
@@ -1,27 +1,22 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdio.h> | 6 | #include <stdio.h> |
7 | #include <stddef.h> | ||
8 | #include <stdlib.h> | ||
9 | #include <unistd.h> | 7 | #include <unistd.h> |
10 | #include <errno.h> | 8 | #include <errno.h> |
11 | #include <sys/wait.h> | 9 | #include <string.h> |
10 | #include <linux/if_tun.h> | ||
11 | #include <net/if.h> | ||
12 | #include <sys/ioctl.h> | ||
12 | #include <sys/socket.h> | 13 | #include <sys/socket.h> |
13 | #include <sys/un.h> | 14 | #include <sys/wait.h> |
14 | #include <sys/uio.h> | 15 | #include <sys/uio.h> |
15 | #include <sys/ioctl.h> | 16 | #include "kern_constants.h" |
16 | #include <net/if.h> | 17 | #include "os.h" |
17 | #include <linux/if_tun.h> | ||
18 | #include "net_user.h" | ||
19 | #include "tuntap.h" | 18 | #include "tuntap.h" |
20 | #include "kern_util.h" | ||
21 | #include "user.h" | 19 | #include "user.h" |
22 | #include "os.h" | ||
23 | |||
24 | #define MAX_PACKET ETH_MAX_PACKET | ||
25 | 20 | ||
26 | static int tuntap_user_init(void *data, void *dev) | 21 | static int tuntap_user_init(void *data, void *dev) |
27 | { | 22 | { |
@@ -37,7 +32,7 @@ static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask, | |||
37 | struct tuntap_data *pri = data; | 32 | struct tuntap_data *pri = data; |
38 | 33 | ||
39 | tap_check_ips(pri->gate_addr, addr); | 34 | tap_check_ips(pri->gate_addr, addr); |
40 | if((pri->fd == -1) || pri->fixed_config) | 35 | if ((pri->fd == -1) || pri->fixed_config) |
41 | return; | 36 | return; |
42 | open_addr(addr, netmask, pri->dev_name); | 37 | open_addr(addr, netmask, pri->dev_name); |
43 | } | 38 | } |
@@ -47,7 +42,7 @@ static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask, | |||
47 | { | 42 | { |
48 | struct tuntap_data *pri = data; | 43 | struct tuntap_data *pri = data; |
49 | 44 | ||
50 | if((pri->fd == -1) || pri->fixed_config) | 45 | if ((pri->fd == -1) || pri->fixed_config) |
51 | return; | 46 | return; |
52 | close_addr(addr, netmask, pri->dev_name); | 47 | close_addr(addr, netmask, pri->dev_name); |
53 | } | 48 | } |
@@ -62,7 +57,7 @@ static void tuntap_pre_exec(void *arg) | |||
62 | struct tuntap_pre_exec_data *data = arg; | 57 | struct tuntap_pre_exec_data *data = arg; |
63 | 58 | ||
64 | dup2(data->stdout, 1); | 59 | dup2(data->stdout, 1); |
65 | os_close_file(data->close_me); | 60 | close(data->close_me); |
66 | } | 61 | } |
67 | 62 | ||
68 | static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, | 63 | static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, |
@@ -85,14 +80,14 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, | |||
85 | 80 | ||
86 | pid = run_helper(tuntap_pre_exec, &data, argv); | 81 | pid = run_helper(tuntap_pre_exec, &data, argv); |
87 | 82 | ||
88 | if(pid < 0) | 83 | if (pid < 0) |
89 | return -pid; | 84 | return -pid; |
90 | 85 | ||
91 | os_close_file(remote); | 86 | close(remote); |
92 | 87 | ||
93 | msg.msg_name = NULL; | 88 | msg.msg_name = NULL; |
94 | msg.msg_namelen = 0; | 89 | msg.msg_namelen = 0; |
95 | if(buffer != NULL){ | 90 | if (buffer != NULL) { |
96 | iov = ((struct iovec) { buffer, buffer_len }); | 91 | iov = ((struct iovec) { buffer, buffer_len }); |
97 | msg.msg_iov = &iov; | 92 | msg.msg_iov = &iov; |
98 | msg.msg_iovlen = 1; | 93 | msg.msg_iovlen = 1; |
@@ -106,26 +101,28 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, | |||
106 | msg.msg_flags = 0; | 101 | msg.msg_flags = 0; |
107 | n = recvmsg(me, &msg, 0); | 102 | n = recvmsg(me, &msg, 0); |
108 | *used_out = n; | 103 | *used_out = n; |
109 | if(n < 0){ | 104 | if (n < 0) { |
110 | err = -errno; | 105 | err = -errno; |
111 | printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", | 106 | printk(UM_KERN_ERR "tuntap_open_tramp : recvmsg failed - " |
112 | errno); | 107 | "errno = %d\n", errno); |
113 | return err; | 108 | return err; |
114 | } | 109 | } |
115 | CATCH_EINTR(waitpid(pid, NULL, 0)); | 110 | CATCH_EINTR(waitpid(pid, NULL, 0)); |
116 | 111 | ||
117 | cmsg = CMSG_FIRSTHDR(&msg); | 112 | cmsg = CMSG_FIRSTHDR(&msg); |
118 | if(cmsg == NULL){ | 113 | if (cmsg == NULL) { |
119 | printk("tuntap_open_tramp : didn't receive a message\n"); | 114 | printk(UM_KERN_ERR "tuntap_open_tramp : didn't receive a " |
115 | "message\n"); | ||
120 | return -EINVAL; | 116 | return -EINVAL; |
121 | } | 117 | } |
122 | if((cmsg->cmsg_level != SOL_SOCKET) || | 118 | if ((cmsg->cmsg_level != SOL_SOCKET) || |
123 | (cmsg->cmsg_type != SCM_RIGHTS)){ | 119 | (cmsg->cmsg_type != SCM_RIGHTS)) { |
124 | printk("tuntap_open_tramp : didn't receive a descriptor\n"); | 120 | printk(UM_KERN_ERR "tuntap_open_tramp : didn't receive a " |
121 | "descriptor\n"); | ||
125 | return -EINVAL; | 122 | return -EINVAL; |
126 | } | 123 | } |
127 | *fd_out = ((int *) CMSG_DATA(cmsg))[0]; | 124 | *fd_out = ((int *) CMSG_DATA(cmsg))[0]; |
128 | os_set_exec_close(*fd_out, 1); | 125 | os_set_exec_close(*fd_out); |
129 | return 0; | 126 | return 0; |
130 | } | 127 | } |
131 | 128 | ||
@@ -137,47 +134,51 @@ static int tuntap_open(void *data) | |||
137 | int err, fds[2], len, used; | 134 | int err, fds[2], len, used; |
138 | 135 | ||
139 | err = tap_open_common(pri->dev, pri->gate_addr); | 136 | err = tap_open_common(pri->dev, pri->gate_addr); |
140 | if(err < 0) | 137 | if (err < 0) |
141 | return err; | 138 | return err; |
142 | 139 | ||
143 | if(pri->fixed_config){ | 140 | if (pri->fixed_config) { |
144 | pri->fd = os_open_file("/dev/net/tun", | 141 | pri->fd = os_open_file("/dev/net/tun", |
145 | of_cloexec(of_rdwr(OPENFLAGS())), 0); | 142 | of_cloexec(of_rdwr(OPENFLAGS())), 0); |
146 | if(pri->fd < 0){ | 143 | if (pri->fd < 0) { |
147 | printk("Failed to open /dev/net/tun, err = %d\n", | 144 | printk(UM_KERN_ERR "Failed to open /dev/net/tun, " |
148 | -pri->fd); | 145 | "err = %d\n", -pri->fd); |
149 | return pri->fd; | 146 | return pri->fd; |
150 | } | 147 | } |
151 | memset(&ifr, 0, sizeof(ifr)); | 148 | memset(&ifr, 0, sizeof(ifr)); |
152 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI; | 149 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI; |
153 | strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); | 150 | strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); |
154 | if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){ | 151 | if (ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0) { |
155 | err = -errno; | 152 | err = -errno; |
156 | printk("TUNSETIFF failed, errno = %d\n", errno); | 153 | printk(UM_KERN_ERR "TUNSETIFF failed, errno = %d\n", |
157 | os_close_file(pri->fd); | 154 | errno); |
155 | close(pri->fd); | ||
158 | return err; | 156 | return err; |
159 | } | 157 | } |
160 | } | 158 | } |
161 | else { | 159 | else { |
162 | err = os_pipe(fds, 0, 0); | 160 | err = socketpair(AF_UNIX, SOCK_DGRAM, 0, fds); |
163 | if(err < 0){ | 161 | if (err) { |
164 | printk("tuntap_open : os_pipe failed - err = %d\n", | 162 | err = -errno; |
165 | -err); | 163 | printk(UM_KERN_ERR "tuntap_open : socketpair failed - " |
164 | "errno = %d\n", errno); | ||
166 | return err; | 165 | return err; |
167 | } | 166 | } |
168 | 167 | ||
169 | buffer = get_output_buffer(&len); | 168 | buffer = get_output_buffer(&len); |
170 | if(buffer != NULL) len--; | 169 | if (buffer != NULL) |
170 | len--; | ||
171 | used = 0; | 171 | used = 0; |
172 | 172 | ||
173 | err = tuntap_open_tramp(pri->gate_addr, &pri->fd, fds[0], | 173 | err = tuntap_open_tramp(pri->gate_addr, &pri->fd, fds[0], |
174 | fds[1], buffer, len, &used); | 174 | fds[1], buffer, len, &used); |
175 | 175 | ||
176 | output = buffer; | 176 | output = buffer; |
177 | if(err < 0) { | 177 | if (err < 0) { |
178 | printk("%s", output); | 178 | printk("%s", output); |
179 | free_output_buffer(buffer); | 179 | free_output_buffer(buffer); |
180 | printk("tuntap_open_tramp failed - err = %d\n", -err); | 180 | printk(UM_KERN_ERR "tuntap_open_tramp failed - " |
181 | "err = %d\n", -err); | ||
181 | return err; | 182 | return err; |
182 | } | 183 | } |
183 | 184 | ||
@@ -186,7 +187,7 @@ static int tuntap_open(void *data) | |||
186 | printk("%s", output); | 187 | printk("%s", output); |
187 | free_output_buffer(buffer); | 188 | free_output_buffer(buffer); |
188 | 189 | ||
189 | os_close_file(fds[0]); | 190 | close(fds[0]); |
190 | iter_addresses(pri->dev, open_addr, pri->dev_name); | 191 | iter_addresses(pri->dev, open_addr, pri->dev_name); |
191 | } | 192 | } |
192 | 193 | ||
@@ -197,24 +198,19 @@ static void tuntap_close(int fd, void *data) | |||
197 | { | 198 | { |
198 | struct tuntap_data *pri = data; | 199 | struct tuntap_data *pri = data; |
199 | 200 | ||
200 | if(!pri->fixed_config) | 201 | if (!pri->fixed_config) |
201 | iter_addresses(pri->dev, close_addr, pri->dev_name); | 202 | iter_addresses(pri->dev, close_addr, pri->dev_name); |
202 | os_close_file(fd); | 203 | close(fd); |
203 | pri->fd = -1; | 204 | pri->fd = -1; |
204 | } | 205 | } |
205 | 206 | ||
206 | static int tuntap_set_mtu(int mtu, void *data) | ||
207 | { | ||
208 | return mtu; | ||
209 | } | ||
210 | |||
211 | const struct net_user_info tuntap_user_info = { | 207 | const struct net_user_info tuntap_user_info = { |
212 | .init = tuntap_user_init, | 208 | .init = tuntap_user_init, |
213 | .open = tuntap_open, | 209 | .open = tuntap_open, |
214 | .close = tuntap_close, | 210 | .close = tuntap_close, |
215 | .remove = NULL, | 211 | .remove = NULL, |
216 | .set_mtu = tuntap_set_mtu, | ||
217 | .add_address = tuntap_add_addr, | 212 | .add_address = tuntap_add_addr, |
218 | .delete_address = tuntap_del_addr, | 213 | .delete_address = tuntap_del_addr, |
219 | .max_packet = MAX_PACKET | 214 | .mtu = ETH_MAX_PACKET, |
215 | .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, | ||
220 | }; | 216 | }; |
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c index c3ecc2a84e0c..b542a3a021bf 100644 --- a/arch/um/os-Linux/file.c +++ b/arch/um/os-Linux/file.c | |||
@@ -82,13 +82,6 @@ int os_access(const char* file, int mode) | |||
82 | return 0; | 82 | return 0; |
83 | } | 83 | } |
84 | 84 | ||
85 | void os_print_error(int error, const char* str) | ||
86 | { | ||
87 | errno = error < 0 ? -error : error; | ||
88 | |||
89 | perror(str); | ||
90 | } | ||
91 | |||
92 | /* FIXME? required only by hostaudio (because it passes ioctls verbatim) */ | 85 | /* FIXME? required only by hostaudio (because it passes ioctls verbatim) */ |
93 | int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg) | 86 | int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg) |
94 | { | 87 | { |
@@ -101,30 +94,6 @@ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg) | |||
101 | return err; | 94 | return err; |
102 | } | 95 | } |
103 | 96 | ||
104 | int os_window_size(int fd, int *rows, int *cols) | ||
105 | { | ||
106 | struct winsize size; | ||
107 | |||
108 | if(ioctl(fd, TIOCGWINSZ, &size) < 0) | ||
109 | return -errno; | ||
110 | |||
111 | *rows = size.ws_row; | ||
112 | *cols = size.ws_col; | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | int os_new_tty_pgrp(int fd, int pid) | ||
118 | { | ||
119 | if(ioctl(fd, TIOCSCTTY, 0) < 0) | ||
120 | return -errno; | ||
121 | |||
122 | if(tcsetpgrp(fd, pid) < 0) | ||
123 | return -errno; | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | /* FIXME: ensure namebuf in os_get_if_name is big enough */ | 97 | /* FIXME: ensure namebuf in os_get_if_name is big enough */ |
129 | int os_get_ifname(int fd, char* namebuf) | 98 | int os_get_ifname(int fd, char* namebuf) |
130 | { | 99 | { |
@@ -205,19 +174,19 @@ int os_file_mode(char *file, struct openflags *mode_out) | |||
205 | 174 | ||
206 | *mode_out = OPENFLAGS(); | 175 | *mode_out = OPENFLAGS(); |
207 | 176 | ||
208 | err = os_access(file, OS_ACC_W_OK); | 177 | err = access(file, W_OK); |
209 | if((err < 0) && (err != -EACCES)) | 178 | if(err && (errno != EACCES)) |
210 | return(err); | 179 | return -errno; |
211 | 180 | else if(!err) | |
212 | *mode_out = of_write(*mode_out); | 181 | *mode_out = of_write(*mode_out); |
213 | |||
214 | err = os_access(file, OS_ACC_R_OK); | ||
215 | if((err < 0) && (err != -EACCES)) | ||
216 | return(err); | ||
217 | 182 | ||
218 | *mode_out = of_read(*mode_out); | 183 | err = access(file, R_OK); |
184 | if(err && (errno != EACCES)) | ||
185 | return -errno; | ||
186 | else if(!err) | ||
187 | *mode_out = of_read(*mode_out); | ||
219 | 188 | ||
220 | return(0); | 189 | return err; |
221 | } | 190 | } |
222 | 191 | ||
223 | int os_open_file(char *file, struct openflags flags, int mode) | 192 | int os_open_file(char *file, struct openflags flags, int mode) |
@@ -236,15 +205,15 @@ int os_open_file(char *file, struct openflags flags, int mode) | |||
236 | 205 | ||
237 | fd = open64(file, f, mode); | 206 | fd = open64(file, f, mode); |
238 | if(fd < 0) | 207 | if(fd < 0) |
239 | return(-errno); | 208 | return -errno; |
240 | 209 | ||
241 | if(flags.cl && fcntl(fd, F_SETFD, 1)){ | 210 | if(flags.cl && fcntl(fd, F_SETFD, 1)){ |
242 | err = -errno; | 211 | err = -errno; |
243 | os_close_file(fd); | 212 | close(fd); |
244 | return err; | 213 | return err; |
245 | } | 214 | } |
246 | 215 | ||
247 | return(fd); | 216 | return fd; |
248 | } | 217 | } |
249 | 218 | ||
250 | int os_connect_socket(char *name) | 219 | int os_connect_socket(char *name) |
@@ -280,9 +249,9 @@ void os_close_file(int fd) | |||
280 | close(fd); | 249 | close(fd); |
281 | } | 250 | } |
282 | 251 | ||
283 | int os_seek_file(int fd, __u64 offset) | 252 | int os_seek_file(int fd, unsigned long long offset) |
284 | { | 253 | { |
285 | __u64 actual; | 254 | unsigned long long actual; |
286 | 255 | ||
287 | actual = lseek64(fd, offset, SEEK_SET); | 256 | actual = lseek64(fd, offset, SEEK_SET); |
288 | if(actual != offset) | 257 | if(actual != offset) |
@@ -316,31 +285,33 @@ int os_file_size(char *file, unsigned long long *size_out) | |||
316 | err = os_stat_file(file, &buf); | 285 | err = os_stat_file(file, &buf); |
317 | if(err < 0){ | 286 | if(err < 0){ |
318 | printk("Couldn't stat \"%s\" : err = %d\n", file, -err); | 287 | printk("Couldn't stat \"%s\" : err = %d\n", file, -err); |
319 | return(err); | 288 | return err; |
320 | } | 289 | } |
321 | 290 | ||
322 | if(S_ISBLK(buf.ust_mode)){ | 291 | if(S_ISBLK(buf.ust_mode)){ |
323 | int fd; | 292 | int fd; |
324 | long blocks; | 293 | long blocks; |
325 | 294 | ||
326 | fd = os_open_file(file, of_read(OPENFLAGS()), 0); | 295 | fd = open(file, O_RDONLY, 0); |
327 | if(fd < 0){ | 296 | if(fd < 0) { |
328 | printk("Couldn't open \"%s\", errno = %d\n", file, -fd); | 297 | err = -errno; |
329 | return(fd); | 298 | printk("Couldn't open \"%s\", errno = %d\n", file, |
299 | errno); | ||
300 | return err; | ||
330 | } | 301 | } |
331 | if(ioctl(fd, BLKGETSIZE, &blocks) < 0){ | 302 | if(ioctl(fd, BLKGETSIZE, &blocks) < 0){ |
332 | err = -errno; | 303 | err = -errno; |
333 | printk("Couldn't get the block size of \"%s\", " | 304 | printk("Couldn't get the block size of \"%s\", " |
334 | "errno = %d\n", file, errno); | 305 | "errno = %d\n", file, errno); |
335 | os_close_file(fd); | 306 | close(fd); |
336 | return(err); | 307 | return err; |
337 | } | 308 | } |
338 | *size_out = ((long long) blocks) * 512; | 309 | *size_out = ((long long) blocks) * 512; |
339 | os_close_file(fd); | 310 | close(fd); |
340 | return(0); | ||
341 | } | 311 | } |
342 | *size_out = buf.ust_size; | 312 | else *size_out = buf.ust_size; |
343 | return(0); | 313 | |
314 | return 0; | ||
344 | } | 315 | } |
345 | 316 | ||
346 | int os_file_modtime(char *file, unsigned long *modtime) | 317 | int os_file_modtime(char *file, unsigned long *modtime) |
@@ -358,35 +329,28 @@ int os_file_modtime(char *file, unsigned long *modtime) | |||
358 | return 0; | 329 | return 0; |
359 | } | 330 | } |
360 | 331 | ||
361 | int os_get_exec_close(int fd, int* close_on_exec) | 332 | int os_get_exec_close(int fd, int *close_on_exec) |
362 | { | 333 | { |
363 | int ret; | 334 | int ret; |
364 | 335 | ||
365 | do { | 336 | CATCH_EINTR(ret = fcntl(fd, F_GETFD)); |
366 | ret = fcntl(fd, F_GETFD); | ||
367 | } while((ret < 0) && (errno == EINTR)) ; | ||
368 | 337 | ||
369 | if(ret < 0) | 338 | if(ret < 0) |
370 | return(-errno); | 339 | return -errno; |
371 | 340 | ||
372 | *close_on_exec = (ret&FD_CLOEXEC) ? 1 : 0; | 341 | *close_on_exec = (ret & FD_CLOEXEC) ? 1 : 0; |
373 | return(ret); | 342 | return ret; |
374 | } | 343 | } |
375 | 344 | ||
376 | int os_set_exec_close(int fd, int close_on_exec) | 345 | int os_set_exec_close(int fd) |
377 | { | 346 | { |
378 | int flag, err; | 347 | int err; |
379 | |||
380 | if(close_on_exec) flag = FD_CLOEXEC; | ||
381 | else flag = 0; | ||
382 | 348 | ||
383 | do { | 349 | CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC)); |
384 | err = fcntl(fd, F_SETFD, flag); | ||
385 | } while((err < 0) && (errno == EINTR)) ; | ||
386 | 350 | ||
387 | if(err < 0) | 351 | if(err < 0) |
388 | return(-errno); | 352 | return -errno; |
389 | return(err); | 353 | return err; |
390 | } | 354 | } |
391 | 355 | ||
392 | int os_pipe(int *fds, int stream, int close_on_exec) | 356 | int os_pipe(int *fds, int stream, int close_on_exec) |
@@ -395,16 +359,16 @@ int os_pipe(int *fds, int stream, int close_on_exec) | |||
395 | 359 | ||
396 | err = socketpair(AF_UNIX, type, 0, fds); | 360 | err = socketpair(AF_UNIX, type, 0, fds); |
397 | if(err < 0) | 361 | if(err < 0) |
398 | return(-errno); | 362 | return -errno; |
399 | 363 | ||
400 | if(!close_on_exec) | 364 | if(!close_on_exec) |
401 | return(0); | 365 | return 0; |
402 | 366 | ||
403 | err = os_set_exec_close(fds[0], 1); | 367 | err = os_set_exec_close(fds[0]); |
404 | if(err < 0) | 368 | if(err < 0) |
405 | goto error; | 369 | goto error; |
406 | 370 | ||
407 | err = os_set_exec_close(fds[1], 1); | 371 | err = os_set_exec_close(fds[1]); |
408 | if(err < 0) | 372 | if(err < 0) |
409 | goto error; | 373 | goto error; |
410 | 374 | ||
@@ -412,9 +376,9 @@ int os_pipe(int *fds, int stream, int close_on_exec) | |||
412 | 376 | ||
413 | error: | 377 | error: |
414 | printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err); | 378 | printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err); |
415 | os_close_file(fds[1]); | 379 | close(fds[1]); |
416 | os_close_file(fds[0]); | 380 | close(fds[0]); |
417 | return(err); | 381 | return err; |
418 | } | 382 | } |
419 | 383 | ||
420 | int os_set_fd_async(int fd, int owner) | 384 | int os_set_fd_async(int fd, int owner) |
@@ -561,7 +525,7 @@ int os_create_unix_socket(char *file, int len, int close_on_exec) | |||
561 | return -errno; | 525 | return -errno; |
562 | 526 | ||
563 | if(close_on_exec) { | 527 | if(close_on_exec) { |
564 | err = os_set_exec_close(sock, 1); | 528 | err = os_set_exec_close(sock); |
565 | if(err < 0) | 529 | if(err < 0) |
566 | printk("create_unix_socket : close_on_exec failed, " | 530 | printk("create_unix_socket : close_on_exec failed, " |
567 | "err = %d", -err); | 531 | "err = %d", -err); |
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index d81af7b8587a..7a72dbb61b0d 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <limits.h> | 11 | #include <limits.h> |
12 | #include <sys/signal.h> | 12 | #include <sys/signal.h> |
13 | #include <sys/wait.h> | 13 | #include <sys/wait.h> |
14 | #include <sys/socket.h> | ||
14 | #include "user.h" | 15 | #include "user.h" |
15 | #include "kern_util.h" | 16 | #include "kern_util.h" |
16 | #include "os.h" | 17 | #include "os.h" |
@@ -54,13 +55,14 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv) | |||
54 | if (stack == 0) | 55 | if (stack == 0) |
55 | return -ENOMEM; | 56 | return -ENOMEM; |
56 | 57 | ||
57 | ret = os_pipe(fds, 1, 0); | 58 | ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); |
58 | if (ret < 0) { | 59 | if (ret < 0) { |
59 | printk("run_helper : pipe failed, ret = %d\n", -ret); | 60 | ret = -errno; |
61 | printk("run_helper : pipe failed, errno = %d\n", errno); | ||
60 | goto out_free; | 62 | goto out_free; |
61 | } | 63 | } |
62 | 64 | ||
63 | ret = os_set_exec_close(fds[1], 1); | 65 | ret = os_set_exec_close(fds[1]); |
64 | if (ret < 0) { | 66 | if (ret < 0) { |
65 | printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n", | 67 | printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n", |
66 | -ret); | 68 | -ret); |
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c index a633fa8e0a94..6aa6f95d6524 100644 --- a/arch/um/os-Linux/irq.c +++ b/arch/um/os-Linux/irq.c | |||
@@ -145,11 +145,7 @@ void init_irq_signals(int on_sigstack) | |||
145 | 145 | ||
146 | flags = on_sigstack ? SA_ONSTACK : 0; | 146 | flags = on_sigstack ? SA_ONSTACK : 0; |
147 | 147 | ||
148 | set_handler(SIGVTALRM, (__sighandler_t) alarm_handler, | ||
149 | flags | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1); | ||
150 | set_handler(SIGALRM, (__sighandler_t) alarm_handler, | ||
151 | flags | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1); | ||
152 | set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART, | 148 | set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART, |
153 | SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); | 149 | SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); |
154 | signal(SIGWINCH, SIG_IGN); | 150 | signal(SIGWINCH, SIG_IGN); |
155 | } | 151 | } |
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index e85f4995a011..82c3778627b8 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c | |||
@@ -1,33 +1,21 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <unistd.h> | ||
7 | #include <stdio.h> | 6 | #include <stdio.h> |
8 | #include <stdlib.h> | 7 | #include <stdlib.h> |
9 | #include <string.h> | 8 | #include <unistd.h> |
10 | #include <signal.h> | ||
11 | #include <errno.h> | 9 | #include <errno.h> |
10 | #include <signal.h> | ||
11 | #include <string.h> | ||
12 | #include <sys/resource.h> | 12 | #include <sys/resource.h> |
13 | #include <sys/mman.h> | ||
14 | #include <sys/user.h> | ||
15 | #include <asm/page.h> | ||
16 | #include "kern_util.h" | ||
17 | #include "as-layout.h" | 13 | #include "as-layout.h" |
18 | #include "mem_user.h" | ||
19 | #include "irq_user.h" | ||
20 | #include "user.h" | ||
21 | #include "init.h" | 14 | #include "init.h" |
22 | #include "mode.h" | 15 | #include "kern_constants.h" |
23 | #include "choose-mode.h" | 16 | #include "kern_util.h" |
24 | #include "uml-config.h" | ||
25 | #include "os.h" | 17 | #include "os.h" |
26 | #include "um_malloc.h" | 18 | #include "um_malloc.h" |
27 | #include "kern_constants.h" | ||
28 | |||
29 | /* Set in main, unchanged thereafter */ | ||
30 | char *linux_prog; | ||
31 | 19 | ||
32 | #define PGD_BOUND (4 * 1024 * 1024) | 20 | #define PGD_BOUND (4 * 1024 * 1024) |
33 | #define STACKSIZE (8 * 1024 * 1024) | 21 | #define STACKSIZE (8 * 1024 * 1024) |
@@ -37,13 +25,13 @@ static void set_stklim(void) | |||
37 | { | 25 | { |
38 | struct rlimit lim; | 26 | struct rlimit lim; |
39 | 27 | ||
40 | if(getrlimit(RLIMIT_STACK, &lim) < 0){ | 28 | if (getrlimit(RLIMIT_STACK, &lim) < 0) { |
41 | perror("getrlimit"); | 29 | perror("getrlimit"); |
42 | exit(1); | 30 | exit(1); |
43 | } | 31 | } |
44 | if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){ | 32 | if ((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)) { |
45 | lim.rlim_cur = STACKSIZE; | 33 | lim.rlim_cur = STACKSIZE; |
46 | if(setrlimit(RLIMIT_STACK, &lim) < 0){ | 34 | if (setrlimit(RLIMIT_STACK, &lim) < 0) { |
47 | perror("setrlimit"); | 35 | perror("setrlimit"); |
48 | exit(1); | 36 | exit(1); |
49 | } | 37 | } |
@@ -55,7 +43,7 @@ static __init void do_uml_initcalls(void) | |||
55 | initcall_t *call; | 43 | initcall_t *call; |
56 | 44 | ||
57 | call = &__uml_initcall_start; | 45 | call = &__uml_initcall_start; |
58 | while (call < &__uml_initcall_end){ | 46 | while (call < &__uml_initcall_end) { |
59 | (*call)(); | 47 | (*call)(); |
60 | call++; | 48 | call++; |
61 | } | 49 | } |
@@ -74,7 +62,8 @@ static void install_fatal_handler(int sig) | |||
74 | /* All signals are enabled in this handler ... */ | 62 | /* All signals are enabled in this handler ... */ |
75 | sigemptyset(&action.sa_mask); | 63 | sigemptyset(&action.sa_mask); |
76 | 64 | ||
77 | /* ... including the signal being handled, plus we want the | 65 | /* |
66 | * ... including the signal being handled, plus we want the | ||
78 | * handler reset to the default behavior, so that if an exit | 67 | * handler reset to the default behavior, so that if an exit |
79 | * handler is hanging for some reason, the UML will just die | 68 | * handler is hanging for some reason, the UML will just die |
80 | * after this signal is sent a second time. | 69 | * after this signal is sent a second time. |
@@ -82,7 +71,7 @@ static void install_fatal_handler(int sig) | |||
82 | action.sa_flags = SA_RESETHAND | SA_NODEFER; | 71 | action.sa_flags = SA_RESETHAND | SA_NODEFER; |
83 | action.sa_restorer = NULL; | 72 | action.sa_restorer = NULL; |
84 | action.sa_handler = last_ditch_exit; | 73 | action.sa_handler = last_ditch_exit; |
85 | if(sigaction(sig, &action, NULL) < 0){ | 74 | if (sigaction(sig, &action, NULL) < 0) { |
86 | printf("failed to install handler for signal %d - errno = %d\n", | 75 | printf("failed to install handler for signal %d - errno = %d\n", |
87 | errno); | 76 | errno); |
88 | exit(1); | 77 | exit(1); |
@@ -98,7 +87,8 @@ static void setup_env_path(void) | |||
98 | int path_len = 0; | 87 | int path_len = 0; |
99 | 88 | ||
100 | old_path = getenv("PATH"); | 89 | old_path = getenv("PATH"); |
101 | /* if no PATH variable is set or it has an empty value | 90 | /* |
91 | * if no PATH variable is set or it has an empty value | ||
102 | * just use the default + /usr/lib/uml | 92 | * just use the default + /usr/lib/uml |
103 | */ | 93 | */ |
104 | if (!old_path || (path_len = strlen(old_path)) == 0) { | 94 | if (!old_path || (path_len = strlen(old_path)) == 0) { |
@@ -126,93 +116,68 @@ int __init main(int argc, char **argv, char **envp) | |||
126 | char **new_argv; | 116 | char **new_argv; |
127 | int ret, i, err; | 117 | int ret, i, err; |
128 | 118 | ||
129 | #ifdef UML_CONFIG_CMDLINE_ON_HOST | ||
130 | /* Allocate memory for thread command lines */ | ||
131 | if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){ | ||
132 | |||
133 | char padding[THREAD_NAME_LEN] = { | ||
134 | [ 0 ... THREAD_NAME_LEN - 2] = ' ', '\0' | ||
135 | }; | ||
136 | |||
137 | new_argv = malloc((argc + 2) * sizeof(char*)); | ||
138 | if(!new_argv) { | ||
139 | perror("Allocating extended argv"); | ||
140 | exit(1); | ||
141 | } | ||
142 | |||
143 | new_argv[0] = argv[0]; | ||
144 | new_argv[1] = padding; | ||
145 | |||
146 | for(i = 2; i <= argc; i++) | ||
147 | new_argv[i] = argv[i - 1]; | ||
148 | new_argv[argc + 1] = NULL; | ||
149 | |||
150 | execvp(new_argv[0], new_argv); | ||
151 | perror("execing with extended args"); | ||
152 | exit(1); | ||
153 | } | ||
154 | #endif | ||
155 | |||
156 | linux_prog = argv[0]; | ||
157 | |||
158 | set_stklim(); | 119 | set_stklim(); |
159 | 120 | ||
160 | setup_env_path(); | 121 | setup_env_path(); |
161 | 122 | ||
162 | new_argv = malloc((argc + 1) * sizeof(char *)); | 123 | new_argv = malloc((argc + 1) * sizeof(char *)); |
163 | if(new_argv == NULL){ | 124 | if (new_argv == NULL) { |
164 | perror("Mallocing argv"); | 125 | perror("Mallocing argv"); |
165 | exit(1); | 126 | exit(1); |
166 | } | 127 | } |
167 | for(i=0;i<argc;i++){ | 128 | for (i = 0; i < argc; i++) { |
168 | new_argv[i] = strdup(argv[i]); | 129 | new_argv[i] = strdup(argv[i]); |
169 | if(new_argv[i] == NULL){ | 130 | if (new_argv[i] == NULL) { |
170 | perror("Mallocing an arg"); | 131 | perror("Mallocing an arg"); |
171 | exit(1); | 132 | exit(1); |
172 | } | 133 | } |
173 | } | 134 | } |
174 | new_argv[argc] = NULL; | 135 | new_argv[argc] = NULL; |
175 | 136 | ||
176 | /* Allow these signals to bring down a UML if all other | 137 | /* |
138 | * Allow these signals to bring down a UML if all other | ||
177 | * methods of control fail. | 139 | * methods of control fail. |
178 | */ | 140 | */ |
179 | install_fatal_handler(SIGINT); | 141 | install_fatal_handler(SIGINT); |
180 | install_fatal_handler(SIGTERM); | 142 | install_fatal_handler(SIGTERM); |
181 | install_fatal_handler(SIGHUP); | 143 | install_fatal_handler(SIGHUP); |
182 | 144 | ||
183 | scan_elf_aux( envp); | 145 | scan_elf_aux(envp); |
184 | 146 | ||
185 | do_uml_initcalls(); | 147 | do_uml_initcalls(); |
186 | ret = linux_main(argc, argv); | 148 | ret = linux_main(argc, argv); |
187 | 149 | ||
188 | /* Disable SIGPROF - I have no idea why libc doesn't do this or turn | 150 | /* |
151 | * Disable SIGPROF - I have no idea why libc doesn't do this or turn | ||
189 | * off the profiling time, but UML dies with a SIGPROF just before | 152 | * off the profiling time, but UML dies with a SIGPROF just before |
190 | * exiting when profiling is active. | 153 | * exiting when profiling is active. |
191 | */ | 154 | */ |
192 | change_sig(SIGPROF, 0); | 155 | change_sig(SIGPROF, 0); |
193 | 156 | ||
194 | /* This signal stuff used to be in the reboot case. However, | 157 | /* |
158 | * This signal stuff used to be in the reboot case. However, | ||
195 | * sometimes a SIGVTALRM can come in when we're halting (reproducably | 159 | * sometimes a SIGVTALRM can come in when we're halting (reproducably |
196 | * when writing out gcov information, presumably because that takes | 160 | * when writing out gcov information, presumably because that takes |
197 | * some time) and cause a segfault. | 161 | * some time) and cause a segfault. |
198 | */ | 162 | */ |
199 | 163 | ||
200 | /* stop timers and set SIG*ALRM to be ignored */ | 164 | /* stop timers and set SIGVTALRM to be ignored */ |
201 | disable_timer(); | 165 | disable_timer(); |
202 | 166 | ||
203 | /* disable SIGIO for the fds and set SIGIO to be ignored */ | 167 | /* disable SIGIO for the fds and set SIGIO to be ignored */ |
204 | err = deactivate_all_fds(); | 168 | err = deactivate_all_fds(); |
205 | if(err) | 169 | if (err) |
206 | printf("deactivate_all_fds failed, errno = %d\n", -err); | 170 | printf("deactivate_all_fds failed, errno = %d\n", -err); |
207 | 171 | ||
208 | /* Let any pending signals fire now. This ensures | 172 | /* |
173 | * Let any pending signals fire now. This ensures | ||
209 | * that they won't be delivered after the exec, when | 174 | * that they won't be delivered after the exec, when |
210 | * they are definitely not expected. | 175 | * they are definitely not expected. |
211 | */ | 176 | */ |
212 | unblock_signals(); | 177 | unblock_signals(); |
213 | 178 | ||
214 | /* Reboot */ | 179 | /* Reboot */ |
215 | if(ret){ | 180 | if (ret) { |
216 | printf("\n"); | 181 | printf("\n"); |
217 | execvp(new_argv[0], new_argv); | 182 | execvp(new_argv[0], new_argv); |
218 | perror("Failed to exec kernel"); | 183 | perror("Failed to exec kernel"); |
@@ -222,26 +187,24 @@ int __init main(int argc, char **argv, char **envp) | |||
222 | return uml_exitcode; | 187 | return uml_exitcode; |
223 | } | 188 | } |
224 | 189 | ||
225 | #define CAN_KMALLOC() \ | ||
226 | (kmalloc_ok && CHOOSE_MODE((os_getpid() != tracing_pid), 1)) | ||
227 | |||
228 | extern void *__real_malloc(int); | 190 | extern void *__real_malloc(int); |
229 | 191 | ||
230 | void *__wrap_malloc(int size) | 192 | void *__wrap_malloc(int size) |
231 | { | 193 | { |
232 | void *ret; | 194 | void *ret; |
233 | 195 | ||
234 | if(!CAN_KMALLOC()) | 196 | if (!kmalloc_ok) |
235 | return __real_malloc(size); | 197 | return __real_malloc(size); |
236 | else if(size <= UM_KERN_PAGE_SIZE) | 198 | else if (size <= UM_KERN_PAGE_SIZE) |
237 | /* finding contiguous pages can be hard*/ | 199 | /* finding contiguous pages can be hard*/ |
238 | ret = kmalloc(size, UM_GFP_KERNEL); | 200 | ret = kmalloc(size, UM_GFP_KERNEL); |
239 | else ret = vmalloc(size); | 201 | else ret = vmalloc(size); |
240 | 202 | ||
241 | /* glibc people insist that if malloc fails, errno should be | 203 | /* |
204 | * glibc people insist that if malloc fails, errno should be | ||
242 | * set by malloc as well. So we do. | 205 | * set by malloc as well. So we do. |
243 | */ | 206 | */ |
244 | if(ret == NULL) | 207 | if (ret == NULL) |
245 | errno = ENOMEM; | 208 | errno = ENOMEM; |
246 | 209 | ||
247 | return ret; | 210 | return ret; |
@@ -251,7 +214,7 @@ void *__wrap_calloc(int n, int size) | |||
251 | { | 214 | { |
252 | void *ptr = __wrap_malloc(n * size); | 215 | void *ptr = __wrap_malloc(n * size); |
253 | 216 | ||
254 | if(ptr == NULL) | 217 | if (ptr == NULL) |
255 | return NULL; | 218 | return NULL; |
256 | memset(ptr, 0, n * size); | 219 | memset(ptr, 0, n * size); |
257 | return ptr; | 220 | return ptr; |
@@ -265,7 +228,8 @@ void __wrap_free(void *ptr) | |||
265 | { | 228 | { |
266 | unsigned long addr = (unsigned long) ptr; | 229 | unsigned long addr = (unsigned long) ptr; |
267 | 230 | ||
268 | /* We need to know how the allocation happened, so it can be correctly | 231 | /* |
232 | * We need to know how the allocation happened, so it can be correctly | ||
269 | * freed. This is done by seeing what region of memory the pointer is | 233 | * freed. This is done by seeing what region of memory the pointer is |
270 | * in - | 234 | * in - |
271 | * physical memory - kmalloc/kfree | 235 | * physical memory - kmalloc/kfree |
@@ -283,12 +247,12 @@ void __wrap_free(void *ptr) | |||
283 | * there is a possibility for memory leaks. | 247 | * there is a possibility for memory leaks. |
284 | */ | 248 | */ |
285 | 249 | ||
286 | if((addr >= uml_physmem) && (addr < high_physmem)){ | 250 | if ((addr >= uml_physmem) && (addr < high_physmem)) { |
287 | if(CAN_KMALLOC()) | 251 | if (kmalloc_ok) |
288 | kfree(ptr); | 252 | kfree(ptr); |
289 | } | 253 | } |
290 | else if((addr >= start_vm) && (addr < end_vm)){ | 254 | else if ((addr >= start_vm) && (addr < end_vm)) { |
291 | if(CAN_KMALLOC()) | 255 | if (kmalloc_ok) |
292 | vfree(ptr); | 256 | vfree(ptr); |
293 | } | 257 | } |
294 | else __real_free(ptr); | 258 | else __real_free(ptr); |
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index c6378c6d10d2..436f8d20b20f 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c | |||
@@ -218,7 +218,7 @@ int __init create_tmp_file(unsigned long long len) | |||
218 | 218 | ||
219 | err = fchmod(fd, 0777); | 219 | err = fchmod(fd, 0777); |
220 | if(err < 0){ | 220 | if(err < 0){ |
221 | perror("os_mode_fd"); | 221 | perror("fchmod"); |
222 | exit(1); | 222 | exit(1); |
223 | } | 223 | } |
224 | 224 | ||
@@ -226,7 +226,7 @@ int __init create_tmp_file(unsigned long long len) | |||
226 | * increase the file size by one byte, to the desired length. | 226 | * increase the file size by one byte, to the desired length. |
227 | */ | 227 | */ |
228 | if (lseek64(fd, len - 1, SEEK_SET) < 0) { | 228 | if (lseek64(fd, len - 1, SEEK_SET) < 0) { |
229 | perror("os_seek_file"); | 229 | perror("lseek64"); |
230 | exit(1); | 230 | exit(1); |
231 | } | 231 | } |
232 | 232 | ||
@@ -247,7 +247,7 @@ int __init create_mem_file(unsigned long long len) | |||
247 | 247 | ||
248 | fd = create_tmp_file(len); | 248 | fd = create_tmp_file(len); |
249 | 249 | ||
250 | err = os_set_exec_close(fd, 1); | 250 | err = os_set_exec_close(fd); |
251 | if(err < 0){ | 251 | if(err < 0){ |
252 | errno = -err; | 252 | errno = -err; |
253 | perror("exec_close"); | 253 | perror("exec_close"); |
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index e9c143297512..37781db4ceca 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c | |||
@@ -1,27 +1,24 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <unistd.h> | ||
7 | #include <stdio.h> | 6 | #include <stdio.h> |
7 | #include <unistd.h> | ||
8 | #include <errno.h> | 8 | #include <errno.h> |
9 | #include <signal.h> | 9 | #include <signal.h> |
10 | #include <fcntl.h> | ||
10 | #include <sys/mman.h> | 11 | #include <sys/mman.h> |
12 | #include <sys/ptrace.h> | ||
11 | #include <sys/wait.h> | 13 | #include <sys/wait.h> |
12 | #include <sys/mman.h> | 14 | #include <asm/unistd.h> |
13 | #include <sys/syscall.h> | 15 | #include "init.h" |
14 | #include "ptrace_user.h" | 16 | #include "kern_constants.h" |
17 | #include "longjmp.h" | ||
15 | #include "os.h" | 18 | #include "os.h" |
16 | #include "user.h" | ||
17 | #include "process.h" | 19 | #include "process.h" |
18 | #include "irq_user.h" | ||
19 | #include "kern_util.h" | ||
20 | #include "longjmp.h" | ||
21 | #include "skas_ptrace.h" | 20 | #include "skas_ptrace.h" |
22 | #include "kern_constants.h" | 21 | #include "user.h" |
23 | #include "uml-config.h" | ||
24 | #include "init.h" | ||
25 | 22 | ||
26 | #define ARBITRARY_ADDR -1 | 23 | #define ARBITRARY_ADDR -1 |
27 | #define FAILURE_PID -1 | 24 | #define FAILURE_PID -1 |
@@ -32,30 +29,32 @@ | |||
32 | unsigned long os_process_pc(int pid) | 29 | unsigned long os_process_pc(int pid) |
33 | { | 30 | { |
34 | char proc_stat[STAT_PATH_LEN], buf[256]; | 31 | char proc_stat[STAT_PATH_LEN], buf[256]; |
35 | unsigned long pc; | 32 | unsigned long pc = ARBITRARY_ADDR; |
36 | int fd, err; | 33 | int fd, err; |
37 | 34 | ||
38 | sprintf(proc_stat, "/proc/%d/stat", pid); | 35 | sprintf(proc_stat, "/proc/%d/stat", pid); |
39 | fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0); | 36 | fd = open(proc_stat, O_RDONLY, 0); |
40 | if(fd < 0){ | 37 | if (fd < 0) { |
41 | printk("os_process_pc - couldn't open '%s', err = %d\n", | 38 | printk(UM_KERN_ERR "os_process_pc - couldn't open '%s', " |
42 | proc_stat, -fd); | 39 | "errno = %d\n", proc_stat, errno); |
43 | return ARBITRARY_ADDR; | 40 | goto out; |
44 | } | 41 | } |
45 | CATCH_EINTR(err = read(fd, buf, sizeof(buf))); | 42 | CATCH_EINTR(err = read(fd, buf, sizeof(buf))); |
46 | if(err < 0){ | 43 | if (err < 0) { |
47 | printk("os_process_pc - couldn't read '%s', err = %d\n", | 44 | printk(UM_KERN_ERR "os_process_pc - couldn't read '%s', " |
48 | proc_stat, errno); | 45 | "err = %d\n", proc_stat, errno); |
49 | os_close_file(fd); | 46 | goto out_close; |
50 | return ARBITRARY_ADDR; | ||
51 | } | 47 | } |
52 | os_close_file(fd); | 48 | os_close_file(fd); |
53 | pc = ARBITRARY_ADDR; | 49 | pc = ARBITRARY_ADDR; |
54 | if(sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d " | 50 | if (sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d " |
55 | "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d " | 51 | "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d " |
56 | "%*d %*d %*d %*d %*d %lu", &pc) != 1){ | 52 | "%*d %*d %*d %*d %*d %lu", &pc) != 1) |
57 | printk("os_process_pc - couldn't find pc in '%s'\n", buf); | 53 | printk(UM_KERN_ERR "os_process_pc - couldn't find pc in '%s'\n", |
58 | } | 54 | buf); |
55 | out_close: | ||
56 | close(fd); | ||
57 | out: | ||
59 | return pc; | 58 | return pc; |
60 | } | 59 | } |
61 | 60 | ||
@@ -63,30 +62,32 @@ int os_process_parent(int pid) | |||
63 | { | 62 | { |
64 | char stat[STAT_PATH_LEN]; | 63 | char stat[STAT_PATH_LEN]; |
65 | char data[256]; | 64 | char data[256]; |
66 | int parent, n, fd; | 65 | int parent = FAILURE_PID, n, fd; |
67 | 66 | ||
68 | if(pid == -1) | 67 | if (pid == -1) |
69 | return -1; | 68 | return parent; |
70 | 69 | ||
71 | snprintf(stat, sizeof(stat), "/proc/%d/stat", pid); | 70 | snprintf(stat, sizeof(stat), "/proc/%d/stat", pid); |
72 | fd = os_open_file(stat, of_read(OPENFLAGS()), 0); | 71 | fd = open(stat, O_RDONLY, 0); |
73 | if(fd < 0){ | 72 | if (fd < 0) { |
74 | printk("Couldn't open '%s', err = %d\n", stat, -fd); | 73 | printk(UM_KERN_ERR "Couldn't open '%s', errno = %d\n", stat, |
75 | return FAILURE_PID; | 74 | errno); |
75 | return parent; | ||
76 | } | 76 | } |
77 | 77 | ||
78 | CATCH_EINTR(n = read(fd, data, sizeof(data))); | 78 | CATCH_EINTR(n = read(fd, data, sizeof(data))); |
79 | os_close_file(fd); | 79 | close(fd); |
80 | 80 | ||
81 | if(n < 0){ | 81 | if (n < 0) { |
82 | printk("Couldn't read '%s', err = %d\n", stat, errno); | 82 | printk(UM_KERN_ERR "Couldn't read '%s', errno = %d\n", stat, |
83 | return FAILURE_PID; | 83 | errno); |
84 | return parent; | ||
84 | } | 85 | } |
85 | 86 | ||
86 | parent = FAILURE_PID; | 87 | parent = FAILURE_PID; |
87 | n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent); | 88 | n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent); |
88 | if(n != 1) | 89 | if (n != 1) |
89 | printk("Failed to scan '%s'\n", data); | 90 | printk(UM_KERN_ERR "Failed to scan '%s'\n", data); |
90 | 91 | ||
91 | return parent; | 92 | return parent; |
92 | } | 93 | } |
@@ -99,9 +100,8 @@ void os_stop_process(int pid) | |||
99 | void os_kill_process(int pid, int reap_child) | 100 | void os_kill_process(int pid, int reap_child) |
100 | { | 101 | { |
101 | kill(pid, SIGKILL); | 102 | kill(pid, SIGKILL); |
102 | if(reap_child) | 103 | if (reap_child) |
103 | CATCH_EINTR(waitpid(pid, NULL, 0)); | 104 | CATCH_EINTR(waitpid(pid, NULL, 0)); |
104 | |||
105 | } | 105 | } |
106 | 106 | ||
107 | /* This is here uniquely to have access to the userspace errno, i.e. the one | 107 | /* This is here uniquely to have access to the userspace errno, i.e. the one |
@@ -129,17 +129,10 @@ void os_kill_ptraced_process(int pid, int reap_child) | |||
129 | kill(pid, SIGKILL); | 129 | kill(pid, SIGKILL); |
130 | ptrace(PTRACE_KILL, pid); | 130 | ptrace(PTRACE_KILL, pid); |
131 | ptrace(PTRACE_CONT, pid); | 131 | ptrace(PTRACE_CONT, pid); |
132 | if(reap_child) | 132 | if (reap_child) |
133 | CATCH_EINTR(waitpid(pid, NULL, 0)); | 133 | CATCH_EINTR(waitpid(pid, NULL, 0)); |
134 | } | 134 | } |
135 | 135 | ||
136 | #ifdef UML_CONFIG_MODE_TT | ||
137 | void os_usr1_process(int pid) | ||
138 | { | ||
139 | kill(pid, SIGUSR1); | ||
140 | } | ||
141 | #endif | ||
142 | |||
143 | /* Don't use the glibc version, which caches the result in TLS. It misses some | 136 | /* Don't use the glibc version, which caches the result in TLS. It misses some |
144 | * syscalls, and also breaks with clone(), which does not unshare the TLS. | 137 | * syscalls, and also breaks with clone(), which does not unshare the TLS. |
145 | */ | 138 | */ |
@@ -160,34 +153,35 @@ int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, | |||
160 | void *loc; | 153 | void *loc; |
161 | int prot; | 154 | int prot; |
162 | 155 | ||
163 | prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | | 156 | prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | |
164 | (x ? PROT_EXEC : 0); | 157 | (x ? PROT_EXEC : 0); |
165 | 158 | ||
166 | loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, | 159 | loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, |
167 | fd, off); | 160 | fd, off); |
168 | if(loc == MAP_FAILED) | 161 | if (loc == MAP_FAILED) |
169 | return -errno; | 162 | return -errno; |
170 | return 0; | 163 | return 0; |
171 | } | 164 | } |
172 | 165 | ||
173 | int os_protect_memory(void *addr, unsigned long len, int r, int w, int x) | 166 | int os_protect_memory(void *addr, unsigned long len, int r, int w, int x) |
174 | { | 167 | { |
175 | int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | | 168 | int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | |
176 | (x ? PROT_EXEC : 0)); | 169 | (x ? PROT_EXEC : 0)); |
177 | 170 | ||
178 | if(mprotect(addr, len, prot) < 0) | 171 | if (mprotect(addr, len, prot) < 0) |
179 | return -errno; | 172 | return -errno; |
180 | return 0; | 173 | |
174 | return 0; | ||
181 | } | 175 | } |
182 | 176 | ||
183 | int os_unmap_memory(void *addr, int len) | 177 | int os_unmap_memory(void *addr, int len) |
184 | { | 178 | { |
185 | int err; | 179 | int err; |
186 | 180 | ||
187 | err = munmap(addr, len); | 181 | err = munmap(addr, len); |
188 | if(err < 0) | 182 | if (err < 0) |
189 | return -errno; | 183 | return -errno; |
190 | return 0; | 184 | return 0; |
191 | } | 185 | } |
192 | 186 | ||
193 | #ifndef MADV_REMOVE | 187 | #ifndef MADV_REMOVE |
@@ -199,7 +193,7 @@ int os_drop_memory(void *addr, int length) | |||
199 | int err; | 193 | int err; |
200 | 194 | ||
201 | err = madvise(addr, length, MADV_REMOVE); | 195 | err = madvise(addr, length, MADV_REMOVE); |
202 | if(err < 0) | 196 | if (err < 0) |
203 | err = -errno; | 197 | err = -errno; |
204 | return err; | 198 | return err; |
205 | } | 199 | } |
@@ -209,22 +203,24 @@ int __init can_drop_memory(void) | |||
209 | void *addr; | 203 | void *addr; |
210 | int fd, ok = 0; | 204 | int fd, ok = 0; |
211 | 205 | ||
212 | printk("Checking host MADV_REMOVE support..."); | 206 | printk(UM_KERN_INFO "Checking host MADV_REMOVE support..."); |
213 | fd = create_mem_file(UM_KERN_PAGE_SIZE); | 207 | fd = create_mem_file(UM_KERN_PAGE_SIZE); |
214 | if(fd < 0){ | 208 | if (fd < 0) { |
215 | printk("Creating test memory file failed, err = %d\n", -fd); | 209 | printk(UM_KERN_ERR "Creating test memory file failed, " |
210 | "err = %d\n", -fd); | ||
216 | goto out; | 211 | goto out; |
217 | } | 212 | } |
218 | 213 | ||
219 | addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, | 214 | addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, |
220 | MAP_SHARED, fd, 0); | 215 | MAP_SHARED, fd, 0); |
221 | if(addr == MAP_FAILED){ | 216 | if (addr == MAP_FAILED) { |
222 | printk("Mapping test memory file failed, err = %d\n", -errno); | 217 | printk(UM_KERN_ERR "Mapping test memory file failed, " |
218 | "err = %d\n", -errno); | ||
223 | goto out_close; | 219 | goto out_close; |
224 | } | 220 | } |
225 | 221 | ||
226 | if(madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0){ | 222 | if (madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0) { |
227 | printk("MADV_REMOVE failed, err = %d\n", -errno); | 223 | printk(UM_KERN_ERR "MADV_REMOVE failed, err = %d\n", -errno); |
228 | goto out_unmap; | 224 | goto out_unmap; |
229 | } | 225 | } |
230 | 226 | ||
@@ -239,58 +235,31 @@ out: | |||
239 | return ok; | 235 | return ok; |
240 | } | 236 | } |
241 | 237 | ||
242 | #ifdef UML_CONFIG_MODE_TT | ||
243 | void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)) | ||
244 | { | ||
245 | int flags = 0, pages; | ||
246 | |||
247 | if(sig_stack != NULL){ | ||
248 | pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER); | ||
249 | set_sigstack(sig_stack, pages * UM_KERN_PAGE_SIZE); | ||
250 | flags = SA_ONSTACK; | ||
251 | } | ||
252 | if(usr1_handler){ | ||
253 | struct sigaction sa; | ||
254 | |||
255 | sa.sa_handler = usr1_handler; | ||
256 | sigemptyset(&sa.sa_mask); | ||
257 | sa.sa_flags = flags; | ||
258 | sa.sa_restorer = NULL; | ||
259 | if(sigaction(SIGUSR1, &sa, NULL) < 0) | ||
260 | panic("init_new_thread_stack - sigaction failed - " | ||
261 | "errno = %d\n", errno); | ||
262 | } | ||
263 | } | ||
264 | #endif | ||
265 | |||
266 | void init_new_thread_signals(void) | 238 | void init_new_thread_signals(void) |
267 | { | 239 | { |
268 | set_handler(SIGSEGV, (__sighandler_t) sig_handler, SA_ONSTACK, | 240 | set_handler(SIGSEGV, (__sighandler_t) sig_handler, SA_ONSTACK, |
269 | SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); | 241 | SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); |
270 | set_handler(SIGTRAP, (__sighandler_t) sig_handler, SA_ONSTACK, | 242 | set_handler(SIGTRAP, (__sighandler_t) sig_handler, SA_ONSTACK, |
271 | SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); | 243 | SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); |
272 | set_handler(SIGFPE, (__sighandler_t) sig_handler, SA_ONSTACK, | 244 | set_handler(SIGFPE, (__sighandler_t) sig_handler, SA_ONSTACK, |
273 | SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); | 245 | SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); |
274 | set_handler(SIGILL, (__sighandler_t) sig_handler, SA_ONSTACK, | 246 | set_handler(SIGILL, (__sighandler_t) sig_handler, SA_ONSTACK, |
275 | SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); | 247 | SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); |
276 | set_handler(SIGBUS, (__sighandler_t) sig_handler, SA_ONSTACK, | 248 | set_handler(SIGBUS, (__sighandler_t) sig_handler, SA_ONSTACK, |
277 | SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); | 249 | SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); |
278 | set_handler(SIGUSR2, (__sighandler_t) sig_handler, | ||
279 | SA_ONSTACK, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, | ||
280 | -1); | ||
281 | signal(SIGHUP, SIG_IGN); | 250 | signal(SIGHUP, SIG_IGN); |
282 | 251 | ||
283 | init_irq_signals(1); | 252 | init_irq_signals(1); |
284 | } | 253 | } |
285 | 254 | ||
286 | int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) | 255 | int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr) |
287 | { | 256 | { |
288 | jmp_buf buf; | 257 | jmp_buf buf; |
289 | int n; | 258 | int n; |
290 | 259 | ||
291 | *jmp_ptr = &buf; | 260 | *jmp_ptr = &buf; |
292 | n = UML_SETJMP(&buf); | 261 | n = UML_SETJMP(&buf); |
293 | if(n != 0) | 262 | if (n != 0) |
294 | return n; | 263 | return n; |
295 | (*fn)(arg); | 264 | (*fn)(arg); |
296 | return 0; | 265 | return 0; |
diff --git a/arch/um/os-Linux/registers.c b/arch/um/os-Linux/registers.c new file mode 100644 index 000000000000..a32ba6ab1211 --- /dev/null +++ b/arch/um/os-Linux/registers.c | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004 PathScale, Inc | ||
3 | * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include <errno.h> | ||
8 | #include <string.h> | ||
9 | #include <sys/ptrace.h> | ||
10 | #include "sysdep/ptrace.h" | ||
11 | #include "user.h" | ||
12 | |||
13 | /* This is set once at boot time and not changed thereafter */ | ||
14 | |||
15 | static unsigned long exec_regs[MAX_REG_NR]; | ||
16 | |||
17 | void init_thread_registers(struct uml_pt_regs *to) | ||
18 | { | ||
19 | memcpy(to->gp, exec_regs, sizeof(to->gp)); | ||
20 | } | ||
21 | |||
22 | void save_registers(int pid, struct uml_pt_regs *regs) | ||
23 | { | ||
24 | int err; | ||
25 | |||
26 | err = ptrace(PTRACE_GETREGS, pid, 0, regs->gp); | ||
27 | if (err < 0) | ||
28 | panic("save_registers - saving registers failed, errno = %d\n", | ||
29 | errno); | ||
30 | } | ||
31 | |||
32 | void restore_registers(int pid, struct uml_pt_regs *regs) | ||
33 | { | ||
34 | int err; | ||
35 | |||
36 | err = ptrace(PTRACE_SETREGS, pid, 0, regs->gp); | ||
37 | if (err < 0) | ||
38 | panic("restore_registers - saving registers failed, " | ||
39 | "errno = %d\n", errno); | ||
40 | } | ||
41 | |||
42 | void init_registers(int pid) | ||
43 | { | ||
44 | int err; | ||
45 | |||
46 | err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); | ||
47 | if (err) | ||
48 | panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", | ||
49 | errno); | ||
50 | |||
51 | arch_init_registers(pid); | ||
52 | } | ||
53 | |||
54 | void get_safe_registers(unsigned long *regs) | ||
55 | { | ||
56 | memcpy(regs, exec_regs, sizeof(exec_regs)); | ||
57 | } | ||
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index b98f7ea2d2f6..e9800b0b5689 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c | |||
@@ -1,26 +1,21 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2004 PathScale, Inc | 2 | * Copyright (C) 2004 PathScale, Inc |
3 | * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
3 | * Licensed under the GPL | 4 | * Licensed under the GPL |
4 | */ | 5 | */ |
5 | 6 | ||
6 | #include <signal.h> | ||
7 | #include <stdio.h> | ||
8 | #include <unistd.h> | ||
9 | #include <stdlib.h> | 7 | #include <stdlib.h> |
10 | #include <errno.h> | ||
11 | #include <stdarg.h> | 8 | #include <stdarg.h> |
12 | #include <string.h> | 9 | #include <errno.h> |
13 | #include <sys/mman.h> | 10 | #include <signal.h> |
14 | #include "user.h" | 11 | #include <strings.h> |
15 | #include "signal_kern.h" | ||
16 | #include "sysdep/sigcontext.h" | ||
17 | #include "sysdep/barrier.h" | ||
18 | #include "sigcontext.h" | ||
19 | #include "mode.h" | ||
20 | #include "os.h" | 12 | #include "os.h" |
13 | #include "sysdep/barrier.h" | ||
14 | #include "sysdep/sigcontext.h" | ||
15 | #include "user.h" | ||
21 | 16 | ||
22 | /* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled | 17 | /* |
23 | * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to | 18 | * These are the asynchronous signals. SIGPROF is excluded because we want to |
24 | * be able to profile all of UML, not just the non-critical sections. If | 19 | * be able to profile all of UML, not just the non-critical sections. If |
25 | * profiling is not thread-safe, then that is not my problem. We can disable | 20 | * profiling is not thread-safe, then that is not my problem. We can disable |
26 | * profiling when SMP is enabled in that case. | 21 | * profiling when SMP is enabled in that case. |
@@ -31,10 +26,8 @@ | |||
31 | #define SIGVTALRM_BIT 1 | 26 | #define SIGVTALRM_BIT 1 |
32 | #define SIGVTALRM_MASK (1 << SIGVTALRM_BIT) | 27 | #define SIGVTALRM_MASK (1 << SIGVTALRM_BIT) |
33 | 28 | ||
34 | #define SIGALRM_BIT 2 | 29 | /* |
35 | #define SIGALRM_MASK (1 << SIGALRM_BIT) | 30 | * These are used by both the signal handlers and |
36 | |||
37 | /* These are used by both the signal handlers and | ||
38 | * block/unblock_signals. I don't want modifications cached in a | 31 | * block/unblock_signals. I don't want modifications cached in a |
39 | * register - they must go straight to memory. | 32 | * register - they must go straight to memory. |
40 | */ | 33 | */ |
@@ -46,34 +39,27 @@ void sig_handler(int sig, struct sigcontext *sc) | |||
46 | int enabled; | 39 | int enabled; |
47 | 40 | ||
48 | enabled = signals_enabled; | 41 | enabled = signals_enabled; |
49 | if(!enabled && (sig == SIGIO)){ | 42 | if (!enabled && (sig == SIGIO)) { |
50 | pending |= SIGIO_MASK; | 43 | pending |= SIGIO_MASK; |
51 | return; | 44 | return; |
52 | } | 45 | } |
53 | 46 | ||
54 | block_signals(); | 47 | block_signals(); |
55 | 48 | ||
56 | CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, | 49 | sig_handler_common_skas(sig, sc); |
57 | sig, sc); | ||
58 | 50 | ||
59 | set_signals(enabled); | 51 | set_signals(enabled); |
60 | } | 52 | } |
61 | 53 | ||
62 | static void real_alarm_handler(int sig, struct sigcontext *sc) | 54 | static void real_alarm_handler(struct sigcontext *sc) |
63 | { | 55 | { |
64 | union uml_pt_regs regs; | 56 | struct uml_pt_regs regs; |
65 | 57 | ||
66 | if(sig == SIGALRM) | 58 | if (sc != NULL) |
67 | switch_timers(0); | ||
68 | |||
69 | if(sc != NULL) | ||
70 | copy_sc(®s, sc); | 59 | copy_sc(®s, sc); |
71 | regs.skas.is_user = 0; | 60 | regs.is_user = 0; |
72 | unblock_signals(); | 61 | unblock_signals(); |
73 | timer_handler(sig, ®s); | 62 | timer_handler(SIGVTALRM, ®s); |
74 | |||
75 | if(sig == SIGALRM) | ||
76 | switch_timers(1); | ||
77 | } | 63 | } |
78 | 64 | ||
79 | void alarm_handler(int sig, struct sigcontext *sc) | 65 | void alarm_handler(int sig, struct sigcontext *sc) |
@@ -81,27 +67,30 @@ void alarm_handler(int sig, struct sigcontext *sc) | |||
81 | int enabled; | 67 | int enabled; |
82 | 68 | ||
83 | enabled = signals_enabled; | 69 | enabled = signals_enabled; |
84 | if(!signals_enabled){ | 70 | if (!signals_enabled) { |
85 | if(sig == SIGVTALRM) | 71 | pending |= SIGVTALRM_MASK; |
86 | pending |= SIGVTALRM_MASK; | ||
87 | else pending |= SIGALRM_MASK; | ||
88 | |||
89 | return; | 72 | return; |
90 | } | 73 | } |
91 | 74 | ||
92 | block_signals(); | 75 | block_signals(); |
93 | 76 | ||
94 | real_alarm_handler(sig, sc); | 77 | real_alarm_handler(sc); |
95 | set_signals(enabled); | 78 | set_signals(enabled); |
96 | } | 79 | } |
97 | 80 | ||
81 | void timer_init(void) | ||
82 | { | ||
83 | set_handler(SIGVTALRM, (__sighandler_t) alarm_handler, | ||
84 | SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, -1); | ||
85 | } | ||
86 | |||
98 | void set_sigstack(void *sig_stack, int size) | 87 | void set_sigstack(void *sig_stack, int size) |
99 | { | 88 | { |
100 | stack_t stack = ((stack_t) { .ss_flags = 0, | 89 | stack_t stack = ((stack_t) { .ss_flags = 0, |
101 | .ss_sp = (__ptr_t) sig_stack, | 90 | .ss_sp = (__ptr_t) sig_stack, |
102 | .ss_size = size - sizeof(void *) }); | 91 | .ss_size = size - sizeof(void *) }); |
103 | 92 | ||
104 | if(sigaltstack(&stack, NULL) != 0) | 93 | if (sigaltstack(&stack, NULL) != 0) |
105 | panic("enabling signal stack failed, errno = %d\n", errno); | 94 | panic("enabling signal stack failed, errno = %d\n", errno); |
106 | } | 95 | } |
107 | 96 | ||
@@ -111,7 +100,7 @@ void remove_sigstack(void) | |||
111 | .ss_sp = NULL, | 100 | .ss_sp = NULL, |
112 | .ss_size = 0 }); | 101 | .ss_size = 0 }); |
113 | 102 | ||
114 | if(sigaltstack(&stack, NULL) != 0) | 103 | if (sigaltstack(&stack, NULL) != 0) |
115 | panic("disabling signal stack failed, errno = %d\n", errno); | 104 | panic("disabling signal stack failed, errno = %d\n", errno); |
116 | } | 105 | } |
117 | 106 | ||
@@ -135,26 +124,27 @@ void handle_signal(int sig, struct sigcontext *sc) | |||
135 | * with this interrupt. | 124 | * with this interrupt. |
136 | */ | 125 | */ |
137 | bail = to_irq_stack(&pending); | 126 | bail = to_irq_stack(&pending); |
138 | if(bail) | 127 | if (bail) |
139 | return; | 128 | return; |
140 | 129 | ||
141 | nested = pending & 1; | 130 | nested = pending & 1; |
142 | pending &= ~1; | 131 | pending &= ~1; |
143 | 132 | ||
144 | while((sig = ffs(pending)) != 0){ | 133 | while ((sig = ffs(pending)) != 0){ |
145 | sig--; | 134 | sig--; |
146 | pending &= ~(1 << sig); | 135 | pending &= ~(1 << sig); |
147 | (*handlers[sig])(sig, sc); | 136 | (*handlers[sig])(sig, sc); |
148 | } | 137 | } |
149 | 138 | ||
150 | /* Again, pending comes back with a mask of signals | 139 | /* |
140 | * Again, pending comes back with a mask of signals | ||
151 | * that arrived while tearing down the stack. If this | 141 | * that arrived while tearing down the stack. If this |
152 | * is non-zero, we just go back, set up the stack | 142 | * is non-zero, we just go back, set up the stack |
153 | * again, and handle the new interrupts. | 143 | * again, and handle the new interrupts. |
154 | */ | 144 | */ |
155 | if(!nested) | 145 | if (!nested) |
156 | pending = from_irq_stack(nested); | 146 | pending = from_irq_stack(nested); |
157 | } while(pending); | 147 | } while (pending); |
158 | } | 148 | } |
159 | 149 | ||
160 | extern void hard_handler(int sig); | 150 | extern void hard_handler(int sig); |
@@ -172,18 +162,18 @@ void set_handler(int sig, void (*handler)(int), int flags, ...) | |||
172 | sigemptyset(&action.sa_mask); | 162 | sigemptyset(&action.sa_mask); |
173 | 163 | ||
174 | va_start(ap, flags); | 164 | va_start(ap, flags); |
175 | while((mask = va_arg(ap, int)) != -1) | 165 | while ((mask = va_arg(ap, int)) != -1) |
176 | sigaddset(&action.sa_mask, mask); | 166 | sigaddset(&action.sa_mask, mask); |
177 | va_end(ap); | 167 | va_end(ap); |
178 | 168 | ||
179 | action.sa_flags = flags; | 169 | action.sa_flags = flags; |
180 | action.sa_restorer = NULL; | 170 | action.sa_restorer = NULL; |
181 | if(sigaction(sig, &action, NULL) < 0) | 171 | if (sigaction(sig, &action, NULL) < 0) |
182 | panic("sigaction failed - errno = %d\n", errno); | 172 | panic("sigaction failed - errno = %d\n", errno); |
183 | 173 | ||
184 | sigemptyset(&sig_mask); | 174 | sigemptyset(&sig_mask); |
185 | sigaddset(&sig_mask, sig); | 175 | sigaddset(&sig_mask, sig); |
186 | if(sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0) | 176 | if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0) |
187 | panic("sigprocmask failed - errno = %d\n", errno); | 177 | panic("sigprocmask failed - errno = %d\n", errno); |
188 | } | 178 | } |
189 | 179 | ||
@@ -194,13 +184,14 @@ int change_sig(int signal, int on) | |||
194 | sigemptyset(&sigset); | 184 | sigemptyset(&sigset); |
195 | sigaddset(&sigset, signal); | 185 | sigaddset(&sigset, signal); |
196 | sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old); | 186 | sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old); |
197 | return(!sigismember(&old, signal)); | 187 | return !sigismember(&old, signal); |
198 | } | 188 | } |
199 | 189 | ||
200 | void block_signals(void) | 190 | void block_signals(void) |
201 | { | 191 | { |
202 | signals_enabled = 0; | 192 | signals_enabled = 0; |
203 | /* This must return with signals disabled, so this barrier | 193 | /* |
194 | * This must return with signals disabled, so this barrier | ||
204 | * ensures that writes are flushed out before the return. | 195 | * ensures that writes are flushed out before the return. |
205 | * This might matter if gcc figures out how to inline this and | 196 | * This might matter if gcc figures out how to inline this and |
206 | * decides to shuffle this code into the caller. | 197 | * decides to shuffle this code into the caller. |
@@ -212,27 +203,31 @@ void unblock_signals(void) | |||
212 | { | 203 | { |
213 | int save_pending; | 204 | int save_pending; |
214 | 205 | ||
215 | if(signals_enabled == 1) | 206 | if (signals_enabled == 1) |
216 | return; | 207 | return; |
217 | 208 | ||
218 | /* We loop because the IRQ handler returns with interrupts off. So, | 209 | /* |
210 | * We loop because the IRQ handler returns with interrupts off. So, | ||
219 | * interrupts may have arrived and we need to re-enable them and | 211 | * interrupts may have arrived and we need to re-enable them and |
220 | * recheck pending. | 212 | * recheck pending. |
221 | */ | 213 | */ |
222 | while(1){ | 214 | while(1) { |
223 | /* Save and reset save_pending after enabling signals. This | 215 | /* |
216 | * Save and reset save_pending after enabling signals. This | ||
224 | * way, pending won't be changed while we're reading it. | 217 | * way, pending won't be changed while we're reading it. |
225 | */ | 218 | */ |
226 | signals_enabled = 1; | 219 | signals_enabled = 1; |
227 | 220 | ||
228 | /* Setting signals_enabled and reading pending must | 221 | /* |
222 | * Setting signals_enabled and reading pending must | ||
229 | * happen in this order. | 223 | * happen in this order. |
230 | */ | 224 | */ |
231 | mb(); | 225 | mb(); |
232 | 226 | ||
233 | save_pending = pending; | 227 | save_pending = pending; |
234 | if(save_pending == 0){ | 228 | if (save_pending == 0) { |
235 | /* This must return with signals enabled, so | 229 | /* |
230 | * This must return with signals enabled, so | ||
236 | * this barrier ensures that writes are | 231 | * this barrier ensures that writes are |
237 | * flushed out before the return. This might | 232 | * flushed out before the return. This might |
238 | * matter if gcc figures out how to inline | 233 | * matter if gcc figures out how to inline |
@@ -245,26 +240,24 @@ void unblock_signals(void) | |||
245 | 240 | ||
246 | pending = 0; | 241 | pending = 0; |
247 | 242 | ||
248 | /* We have pending interrupts, so disable signals, as the | 243 | /* |
244 | * We have pending interrupts, so disable signals, as the | ||
249 | * handlers expect them off when they are called. They will | 245 | * handlers expect them off when they are called. They will |
250 | * be enabled again above. | 246 | * be enabled again above. |
251 | */ | 247 | */ |
252 | 248 | ||
253 | signals_enabled = 0; | 249 | signals_enabled = 0; |
254 | 250 | ||
255 | /* Deal with SIGIO first because the alarm handler might | 251 | /* |
252 | * Deal with SIGIO first because the alarm handler might | ||
256 | * schedule, leaving the pending SIGIO stranded until we come | 253 | * schedule, leaving the pending SIGIO stranded until we come |
257 | * back here. | 254 | * back here. |
258 | */ | 255 | */ |
259 | if(save_pending & SIGIO_MASK) | 256 | if (save_pending & SIGIO_MASK) |
260 | CHOOSE_MODE_PROC(sig_handler_common_tt, | 257 | sig_handler_common_skas(SIGIO, NULL); |
261 | sig_handler_common_skas, SIGIO, NULL); | ||
262 | |||
263 | if(save_pending & SIGALRM_MASK) | ||
264 | real_alarm_handler(SIGALRM, NULL); | ||
265 | 258 | ||
266 | if(save_pending & SIGVTALRM_MASK) | 259 | if (save_pending & SIGVTALRM_MASK) |
267 | real_alarm_handler(SIGVTALRM, NULL); | 260 | real_alarm_handler(NULL); |
268 | } | 261 | } |
269 | } | 262 | } |
270 | 263 | ||
@@ -276,11 +269,11 @@ int get_signals(void) | |||
276 | int set_signals(int enable) | 269 | int set_signals(int enable) |
277 | { | 270 | { |
278 | int ret; | 271 | int ret; |
279 | if(signals_enabled == enable) | 272 | if (signals_enabled == enable) |
280 | return enable; | 273 | return enable; |
281 | 274 | ||
282 | ret = signals_enabled; | 275 | ret = signals_enabled; |
283 | if(enable) | 276 | if (enable) |
284 | unblock_signals(); | 277 | unblock_signals(); |
285 | else block_signals(); | 278 | else block_signals(); |
286 | 279 | ||
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c index 0f7df4eb903f..484e68f9f7ae 100644 --- a/arch/um/os-Linux/skas/mem.c +++ b/arch/um/os-Linux/skas/mem.c | |||
@@ -1,31 +1,26 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <signal.h> | 6 | #include <stddef.h> |
7 | #include <unistd.h> | ||
7 | #include <errno.h> | 8 | #include <errno.h> |
8 | #include <string.h> | 9 | #include <string.h> |
9 | #include <unistd.h> | ||
10 | #include <sys/mman.h> | 10 | #include <sys/mman.h> |
11 | #include <sys/wait.h> | 11 | #include "init.h" |
12 | #include <asm/page.h> | 12 | #include "kern_constants.h" |
13 | #include <asm/unistd.h> | 13 | #include "as-layout.h" |
14 | #include "mem_user.h" | 14 | #include "mm_id.h" |
15 | #include "mem.h" | ||
16 | #include "skas.h" | ||
17 | #include "user.h" | ||
18 | #include "os.h" | 15 | #include "os.h" |
19 | #include "proc_mm.h" | 16 | #include "proc_mm.h" |
20 | #include "ptrace_user.h" | 17 | #include "ptrace_user.h" |
21 | #include "kern_util.h" | ||
22 | #include "task.h" | ||
23 | #include "registers.h" | 18 | #include "registers.h" |
24 | #include "uml-config.h" | 19 | #include "skas.h" |
20 | #include "user.h" | ||
25 | #include "sysdep/ptrace.h" | 21 | #include "sysdep/ptrace.h" |
26 | #include "sysdep/stub.h" | 22 | #include "sysdep/stub.h" |
27 | #include "init.h" | 23 | #include "uml-config.h" |
28 | #include "kern_constants.h" | ||
29 | 24 | ||
30 | extern unsigned long batch_syscall_stub, __syscall_stub_start; | 25 | extern unsigned long batch_syscall_stub, __syscall_stub_start; |
31 | 26 | ||
@@ -34,7 +29,7 @@ extern void wait_stub_done(int pid); | |||
34 | static inline unsigned long *check_init_stack(struct mm_id * mm_idp, | 29 | static inline unsigned long *check_init_stack(struct mm_id * mm_idp, |
35 | unsigned long *stack) | 30 | unsigned long *stack) |
36 | { | 31 | { |
37 | if(stack == NULL) { | 32 | if (stack == NULL) { |
38 | stack = (unsigned long *) mm_idp->stack + 2; | 33 | stack = (unsigned long *) mm_idp->stack + 2; |
39 | *stack = 0; | 34 | *stack = 0; |
40 | } | 35 | } |
@@ -45,8 +40,8 @@ static unsigned long syscall_regs[MAX_REG_NR]; | |||
45 | 40 | ||
46 | static int __init init_syscall_regs(void) | 41 | static int __init init_syscall_regs(void) |
47 | { | 42 | { |
48 | get_safe_registers(syscall_regs, NULL); | 43 | get_safe_registers(syscall_regs); |
49 | syscall_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + | 44 | syscall_regs[REGS_IP_INDEX] = STUB_CODE + |
50 | ((unsigned long) &batch_syscall_stub - | 45 | ((unsigned long) &batch_syscall_stub - |
51 | (unsigned long) &__syscall_stub_start); | 46 | (unsigned long) &__syscall_stub_start); |
52 | return 0; | 47 | return 0; |
@@ -68,29 +63,30 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) | |||
68 | unsigned long * syscall; | 63 | unsigned long * syscall; |
69 | int err, pid = mm_idp->u.pid; | 64 | int err, pid = mm_idp->u.pid; |
70 | 65 | ||
71 | if(proc_mm) | 66 | if (proc_mm) |
72 | /* FIXME: Need to look up userspace_pid by cpu */ | 67 | /* FIXME: Need to look up userspace_pid by cpu */ |
73 | pid = userspace_pid[0]; | 68 | pid = userspace_pid[0]; |
74 | 69 | ||
75 | multi_count++; | 70 | multi_count++; |
76 | 71 | ||
77 | n = ptrace_setregs(pid, syscall_regs); | 72 | n = ptrace_setregs(pid, syscall_regs); |
78 | if(n < 0){ | 73 | if (n < 0) { |
79 | printk("Registers - \n"); | 74 | printk(UM_KERN_ERR "Registers - \n"); |
80 | for(i = 0; i < MAX_REG_NR; i++) | 75 | for (i = 0; i < MAX_REG_NR; i++) |
81 | printk("\t%d\t0x%lx\n", i, syscall_regs[i]); | 76 | printk(UM_KERN_ERR "\t%d\t0x%lx\n", i, syscall_regs[i]); |
82 | panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", | 77 | panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", |
83 | -n); | 78 | -n); |
84 | } | 79 | } |
85 | 80 | ||
86 | err = ptrace(PTRACE_CONT, pid, 0, 0); | 81 | err = ptrace(PTRACE_CONT, pid, 0, 0); |
87 | if(err) | 82 | if (err) |
88 | panic("Failed to continue stub, pid = %d, errno = %d\n", pid, | 83 | panic("Failed to continue stub, pid = %d, errno = %d\n", pid, |
89 | errno); | 84 | errno); |
90 | 85 | ||
91 | wait_stub_done(pid); | 86 | wait_stub_done(pid); |
92 | 87 | ||
93 | /* When the stub stops, we find the following values on the | 88 | /* |
89 | * When the stub stops, we find the following values on the | ||
94 | * beginning of the stack: | 90 | * beginning of the stack: |
95 | * (long )return_value | 91 | * (long )return_value |
96 | * (long )offset to failed sycall-data (0, if no error) | 92 | * (long )offset to failed sycall-data (0, if no error) |
@@ -98,26 +94,26 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) | |||
98 | ret = *((unsigned long *) mm_idp->stack); | 94 | ret = *((unsigned long *) mm_idp->stack); |
99 | offset = *((unsigned long *) mm_idp->stack + 1); | 95 | offset = *((unsigned long *) mm_idp->stack + 1); |
100 | if (offset) { | 96 | if (offset) { |
101 | data = (unsigned long *)(mm_idp->stack + | 97 | data = (unsigned long *)(mm_idp->stack + offset - STUB_DATA); |
102 | offset - UML_CONFIG_STUB_DATA); | 98 | printk(UM_KERN_ERR "do_syscall_stub : ret = %ld, offset = %ld, " |
103 | printk("do_syscall_stub : ret = %ld, offset = %ld, " | ||
104 | "data = %p\n", ret, offset, data); | 99 | "data = %p\n", ret, offset, data); |
105 | syscall = (unsigned long *)((unsigned long)data + data[0]); | 100 | syscall = (unsigned long *)((unsigned long)data + data[0]); |
106 | printk("do_syscall_stub: syscall %ld failed, return value = " | 101 | printk(UM_KERN_ERR "do_syscall_stub: syscall %ld failed, " |
107 | "0x%lx, expected return value = 0x%lx\n", | 102 | "return value = 0x%lx, expected return value = 0x%lx\n", |
108 | syscall[0], ret, syscall[7]); | 103 | syscall[0], ret, syscall[7]); |
109 | printk(" syscall parameters: " | 104 | printk(UM_KERN_ERR " syscall parameters: " |
110 | "0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", | 105 | "0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", |
111 | syscall[1], syscall[2], syscall[3], | 106 | syscall[1], syscall[2], syscall[3], |
112 | syscall[4], syscall[5], syscall[6]); | 107 | syscall[4], syscall[5], syscall[6]); |
113 | for(n = 1; n < data[0]/sizeof(long); n++) { | 108 | for (n = 1; n < data[0]/sizeof(long); n++) { |
114 | if(n == 1) | 109 | if (n == 1) |
115 | printk(" additional syscall data:"); | 110 | printk(UM_KERN_ERR " additional syscall " |
116 | if(n % 4 == 1) | 111 | "data:"); |
117 | printk("\n "); | 112 | if (n % 4 == 1) |
113 | printk("\n" UM_KERN_ERR " "); | ||
118 | printk(" 0x%lx", data[n]); | 114 | printk(" 0x%lx", data[n]); |
119 | } | 115 | } |
120 | if(n > 1) | 116 | if (n > 1) |
121 | printk("\n"); | 117 | printk("\n"); |
122 | } | 118 | } |
123 | else ret = 0; | 119 | else ret = 0; |
@@ -133,7 +129,7 @@ long run_syscall_stub(struct mm_id * mm_idp, int syscall, | |||
133 | { | 129 | { |
134 | unsigned long *stack = check_init_stack(mm_idp, *addr); | 130 | unsigned long *stack = check_init_stack(mm_idp, *addr); |
135 | 131 | ||
136 | if(done && *addr == NULL) | 132 | if (done && *addr == NULL) |
137 | single_count++; | 133 | single_count++; |
138 | 134 | ||
139 | *stack += sizeof(long); | 135 | *stack += sizeof(long); |
@@ -150,8 +146,8 @@ long run_syscall_stub(struct mm_id * mm_idp, int syscall, | |||
150 | *stack = 0; | 146 | *stack = 0; |
151 | multi_op_count++; | 147 | multi_op_count++; |
152 | 148 | ||
153 | if(!done && ((((unsigned long) stack) & ~UM_KERN_PAGE_MASK) < | 149 | if (!done && ((((unsigned long) stack) & ~UM_KERN_PAGE_MASK) < |
154 | UM_KERN_PAGE_SIZE - 10 * sizeof(long))){ | 150 | UM_KERN_PAGE_SIZE - 10 * sizeof(long))) { |
155 | *addr = stack; | 151 | *addr = stack; |
156 | return 0; | 152 | return 0; |
157 | } | 153 | } |
@@ -166,14 +162,15 @@ long syscall_stub_data(struct mm_id * mm_idp, | |||
166 | unsigned long *stack; | 162 | unsigned long *stack; |
167 | int ret = 0; | 163 | int ret = 0; |
168 | 164 | ||
169 | /* If *addr still is uninitialized, it *must* contain NULL. | 165 | /* |
166 | * If *addr still is uninitialized, it *must* contain NULL. | ||
170 | * Thus in this case do_syscall_stub correctly won't be called. | 167 | * Thus in this case do_syscall_stub correctly won't be called. |
171 | */ | 168 | */ |
172 | if((((unsigned long) *addr) & ~UM_KERN_PAGE_MASK) >= | 169 | if ((((unsigned long) *addr) & ~UM_KERN_PAGE_MASK) >= |
173 | UM_KERN_PAGE_SIZE - (10 + data_count) * sizeof(long)) { | 170 | UM_KERN_PAGE_SIZE - (10 + data_count) * sizeof(long)) { |
174 | ret = do_syscall_stub(mm_idp, addr); | 171 | ret = do_syscall_stub(mm_idp, addr); |
175 | /* in case of error, don't overwrite data on stack */ | 172 | /* in case of error, don't overwrite data on stack */ |
176 | if(ret) | 173 | if (ret) |
177 | return ret; | 174 | return ret; |
178 | } | 175 | } |
179 | 176 | ||
@@ -185,7 +182,7 @@ long syscall_stub_data(struct mm_id * mm_idp, | |||
185 | memcpy(stack + 1, data, data_count * sizeof(long)); | 182 | memcpy(stack + 1, data, data_count * sizeof(long)); |
186 | 183 | ||
187 | *stub_addr = (void *)(((unsigned long)(stack + 1) & | 184 | *stub_addr = (void *)(((unsigned long)(stack + 1) & |
188 | ~UM_KERN_PAGE_MASK) + UML_CONFIG_STUB_DATA); | 185 | ~UM_KERN_PAGE_MASK) + STUB_DATA); |
189 | 186 | ||
190 | return 0; | 187 | return 0; |
191 | } | 188 | } |
@@ -195,7 +192,7 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int prot, | |||
195 | { | 192 | { |
196 | int ret; | 193 | int ret; |
197 | 194 | ||
198 | if(proc_mm){ | 195 | if (proc_mm) { |
199 | struct proc_mm_op map; | 196 | struct proc_mm_op map; |
200 | int fd = mm_idp->u.mm_fd; | 197 | int fd = mm_idp->u.mm_fd; |
201 | 198 | ||
@@ -211,9 +208,10 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int prot, | |||
211 | .offset= offset | 208 | .offset= offset |
212 | } } } ); | 209 | } } } ); |
213 | CATCH_EINTR(ret = write(fd, &map, sizeof(map))); | 210 | CATCH_EINTR(ret = write(fd, &map, sizeof(map))); |
214 | if(ret != sizeof(map)){ | 211 | if (ret != sizeof(map)) { |
215 | ret = -errno; | 212 | ret = -errno; |
216 | printk("map : /proc/mm map failed, err = %d\n", -ret); | 213 | printk(UM_KERN_ERR "map : /proc/mm map failed, " |
214 | "err = %d\n", -ret); | ||
217 | } | 215 | } |
218 | else ret = 0; | 216 | else ret = 0; |
219 | } | 217 | } |
@@ -234,7 +232,7 @@ int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len, | |||
234 | { | 232 | { |
235 | int ret; | 233 | int ret; |
236 | 234 | ||
237 | if(proc_mm){ | 235 | if (proc_mm) { |
238 | struct proc_mm_op unmap; | 236 | struct proc_mm_op unmap; |
239 | int fd = mm_idp->u.mm_fd; | 237 | int fd = mm_idp->u.mm_fd; |
240 | 238 | ||
@@ -245,9 +243,10 @@ int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len, | |||
245 | (unsigned long) addr, | 243 | (unsigned long) addr, |
246 | .len = len } } } ); | 244 | .len = len } } } ); |
247 | CATCH_EINTR(ret = write(fd, &unmap, sizeof(unmap))); | 245 | CATCH_EINTR(ret = write(fd, &unmap, sizeof(unmap))); |
248 | if(ret != sizeof(unmap)){ | 246 | if (ret != sizeof(unmap)) { |
249 | ret = -errno; | 247 | ret = -errno; |
250 | printk("unmap - proc_mm write returned %d\n", ret); | 248 | printk(UM_KERN_ERR "unmap - proc_mm write returned " |
249 | "%d\n", ret); | ||
251 | } | 250 | } |
252 | else ret = 0; | 251 | else ret = 0; |
253 | } | 252 | } |
@@ -268,7 +267,7 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, | |||
268 | struct proc_mm_op protect; | 267 | struct proc_mm_op protect; |
269 | int ret; | 268 | int ret; |
270 | 269 | ||
271 | if(proc_mm){ | 270 | if (proc_mm) { |
272 | int fd = mm_idp->u.mm_fd; | 271 | int fd = mm_idp->u.mm_fd; |
273 | 272 | ||
274 | protect = ((struct proc_mm_op) { .op = MM_MPROTECT, | 273 | protect = ((struct proc_mm_op) { .op = MM_MPROTECT, |
@@ -280,9 +279,9 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, | |||
280 | .prot = prot } } } ); | 279 | .prot = prot } } } ); |
281 | 280 | ||
282 | CATCH_EINTR(ret = write(fd, &protect, sizeof(protect))); | 281 | CATCH_EINTR(ret = write(fd, &protect, sizeof(protect))); |
283 | if(ret != sizeof(protect)){ | 282 | if (ret != sizeof(protect)) { |
284 | ret = -errno; | 283 | ret = -errno; |
285 | printk("protect failed, err = %d", -ret); | 284 | printk(UM_KERN_ERR "protect failed, err = %d", -ret); |
286 | } | 285 | } |
287 | else ret = 0; | 286 | else ret = 0; |
288 | } | 287 | } |
@@ -295,7 +294,3 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, | |||
295 | 294 | ||
296 | return ret; | 295 | return ret; |
297 | } | 296 | } |
298 | |||
299 | void before_mem_skas(unsigned long unused) | ||
300 | { | ||
301 | } | ||
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index ba9af8d62055..d77c81d7068a 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c | |||
@@ -1,48 +1,38 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2002- 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdlib.h> | 6 | #include <stdlib.h> |
7 | #include <string.h> | ||
8 | #include <unistd.h> | 7 | #include <unistd.h> |
9 | #include <errno.h> | ||
10 | #include <signal.h> | ||
11 | #include <sched.h> | 8 | #include <sched.h> |
12 | #include "ptrace_user.h" | 9 | #include <errno.h> |
13 | #include <sys/wait.h> | 10 | #include <string.h> |
14 | #include <sys/mman.h> | 11 | #include <sys/mman.h> |
15 | #include <sys/user.h> | 12 | #include <sys/ptrace.h> |
16 | #include <sys/time.h> | 13 | #include <sys/wait.h> |
17 | #include <sys/syscall.h> | 14 | #include <asm/unistd.h> |
18 | #include <asm/types.h> | 15 | #include "as-layout.h" |
19 | #include "user.h" | ||
20 | #include "sysdep/ptrace.h" | ||
21 | #include "kern_util.h" | ||
22 | #include "skas.h" | ||
23 | #include "stub-data.h" | ||
24 | #include "mm_id.h" | ||
25 | #include "sysdep/sigcontext.h" | ||
26 | #include "sysdep/stub.h" | ||
27 | #include "os.h" | ||
28 | #include "proc_mm.h" | ||
29 | #include "skas_ptrace.h" | ||
30 | #include "chan_user.h" | 16 | #include "chan_user.h" |
31 | #include "registers.h" | 17 | #include "kern_constants.h" |
32 | #include "mem.h" | 18 | #include "mem.h" |
33 | #include "uml-config.h" | 19 | #include "os.h" |
34 | #include "process.h" | 20 | #include "process.h" |
35 | #include "longjmp.h" | 21 | #include "proc_mm.h" |
36 | #include "kern_constants.h" | 22 | #include "ptrace_user.h" |
37 | #include "as-layout.h" | 23 | #include "registers.h" |
24 | #include "skas.h" | ||
25 | #include "skas_ptrace.h" | ||
26 | #include "user.h" | ||
27 | #include "sysdep/stub.h" | ||
38 | 28 | ||
39 | int is_skas_winch(int pid, int fd, void *data) | 29 | int is_skas_winch(int pid, int fd, void *data) |
40 | { | 30 | { |
41 | if(pid != os_getpgrp()) | 31 | if (pid != getpgrp()) |
42 | return(0); | 32 | return 0; |
43 | 33 | ||
44 | register_winch_irq(-1, fd, -1, data, 0); | 34 | register_winch_irq(-1, fd, -1, data, 0); |
45 | return(1); | 35 | return 1; |
46 | } | 36 | } |
47 | 37 | ||
48 | static int ptrace_dump_regs(int pid) | 38 | static int ptrace_dump_regs(int pid) |
@@ -50,13 +40,12 @@ static int ptrace_dump_regs(int pid) | |||
50 | unsigned long regs[MAX_REG_NR]; | 40 | unsigned long regs[MAX_REG_NR]; |
51 | int i; | 41 | int i; |
52 | 42 | ||
53 | if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) | 43 | if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) |
54 | return -errno; | 44 | return -errno; |
55 | else { | 45 | |
56 | printk("Stub registers -\n"); | 46 | printk(UM_KERN_ERR "Stub registers -\n"); |
57 | for(i = 0; i < ARRAY_SIZE(regs); i++) | 47 | for (i = 0; i < ARRAY_SIZE(regs); i++) |
58 | printk("\t%d - %lx\n", i, regs[i]); | 48 | printk(UM_KERN_ERR "\t%d - %lx\n", i, regs[i]); |
59 | } | ||
60 | 49 | ||
61 | return 0; | 50 | return 0; |
62 | } | 51 | } |
@@ -74,27 +63,28 @@ void wait_stub_done(int pid) | |||
74 | { | 63 | { |
75 | int n, status, err; | 64 | int n, status, err; |
76 | 65 | ||
77 | while(1){ | 66 | while (1) { |
78 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); | 67 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); |
79 | if((n < 0) || !WIFSTOPPED(status)) | 68 | if ((n < 0) || !WIFSTOPPED(status)) |
80 | goto bad_wait; | 69 | goto bad_wait; |
81 | 70 | ||
82 | if(((1 << WSTOPSIG(status)) & STUB_SIG_MASK) == 0) | 71 | if (((1 << WSTOPSIG(status)) & STUB_SIG_MASK) == 0) |
83 | break; | 72 | break; |
84 | 73 | ||
85 | err = ptrace(PTRACE_CONT, pid, 0, 0); | 74 | err = ptrace(PTRACE_CONT, pid, 0, 0); |
86 | if(err) | 75 | if (err) |
87 | panic("wait_stub_done : continue failed, errno = %d\n", | 76 | panic("wait_stub_done : continue failed, errno = %d\n", |
88 | errno); | 77 | errno); |
89 | } | 78 | } |
90 | 79 | ||
91 | if(((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0) | 80 | if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0) |
92 | return; | 81 | return; |
93 | 82 | ||
94 | bad_wait: | 83 | bad_wait: |
95 | err = ptrace_dump_regs(pid); | 84 | err = ptrace_dump_regs(pid); |
96 | if(err) | 85 | if (err) |
97 | printk("Failed to get registers from stub, errno = %d\n", -err); | 86 | printk(UM_KERN_ERR "Failed to get registers from stub, " |
87 | "errno = %d\n", -err); | ||
98 | panic("wait_stub_done : failed to wait for SIGUSR1/SIGTRAP, pid = %d, " | 88 | panic("wait_stub_done : failed to wait for SIGUSR1/SIGTRAP, pid = %d, " |
99 | "n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status); | 89 | "n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status); |
100 | } | 90 | } |
@@ -105,9 +95,9 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi) | |||
105 | { | 95 | { |
106 | int err; | 96 | int err; |
107 | 97 | ||
108 | if(ptrace_faultinfo){ | 98 | if (ptrace_faultinfo) { |
109 | err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); | 99 | err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); |
110 | if(err) | 100 | if (err) |
111 | panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " | 101 | panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " |
112 | "errno = %d\n", errno); | 102 | "errno = %d\n", errno); |
113 | 103 | ||
@@ -119,52 +109,57 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi) | |||
119 | } | 109 | } |
120 | else { | 110 | else { |
121 | err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV); | 111 | err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV); |
122 | if(err) | 112 | if (err) |
123 | panic("Failed to continue stub, pid = %d, errno = %d\n", | 113 | panic("Failed to continue stub, pid = %d, errno = %d\n", |
124 | pid, errno); | 114 | pid, errno); |
125 | wait_stub_done(pid); | 115 | wait_stub_done(pid); |
126 | 116 | ||
127 | /* faultinfo is prepared by the stub-segv-handler at start of | 117 | /* |
118 | * faultinfo is prepared by the stub-segv-handler at start of | ||
128 | * the stub stack page. We just have to copy it. | 119 | * the stub stack page. We just have to copy it. |
129 | */ | 120 | */ |
130 | memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); | 121 | memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); |
131 | } | 122 | } |
132 | } | 123 | } |
133 | 124 | ||
134 | static void handle_segv(int pid, union uml_pt_regs * regs) | 125 | static void handle_segv(int pid, struct uml_pt_regs * regs) |
135 | { | 126 | { |
136 | get_skas_faultinfo(pid, ®s->skas.faultinfo); | 127 | get_skas_faultinfo(pid, ®s->faultinfo); |
137 | segv(regs->skas.faultinfo, 0, 1, NULL); | 128 | segv(regs->faultinfo, 0, 1, NULL); |
138 | } | 129 | } |
139 | 130 | ||
140 | /*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/ | 131 | /* |
141 | static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu) | 132 | * To use the same value of using_sysemu as the caller, ask it that value |
133 | * (in local_using_sysemu | ||
134 | */ | ||
135 | static void handle_trap(int pid, struct uml_pt_regs *regs, | ||
136 | int local_using_sysemu) | ||
142 | { | 137 | { |
143 | int err, status; | 138 | int err, status; |
144 | 139 | ||
145 | /* Mark this as a syscall */ | 140 | /* Mark this as a syscall */ |
146 | UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs); | 141 | UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->gp); |
147 | 142 | ||
148 | if (!local_using_sysemu) | 143 | if (!local_using_sysemu) |
149 | { | 144 | { |
150 | err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, | 145 | err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, |
151 | __NR_getpid); | 146 | __NR_getpid); |
152 | if(err < 0) | 147 | if (err < 0) |
153 | panic("handle_trap - nullifying syscall failed errno = %d\n", | 148 | panic("handle_trap - nullifying syscall failed, " |
154 | errno); | 149 | "errno = %d\n", errno); |
155 | 150 | ||
156 | err = ptrace(PTRACE_SYSCALL, pid, 0, 0); | 151 | err = ptrace(PTRACE_SYSCALL, pid, 0, 0); |
157 | if(err < 0) | 152 | if (err < 0) |
158 | panic("handle_trap - continuing to end of syscall failed, " | 153 | panic("handle_trap - continuing to end of syscall " |
159 | "errno = %d\n", errno); | 154 | "failed, errno = %d\n", errno); |
160 | 155 | ||
161 | CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); | 156 | CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); |
162 | if((err < 0) || !WIFSTOPPED(status) || | 157 | if ((err < 0) || !WIFSTOPPED(status) || |
163 | (WSTOPSIG(status) != SIGTRAP + 0x80)){ | 158 | (WSTOPSIG(status) != SIGTRAP + 0x80)) { |
164 | err = ptrace_dump_regs(pid); | 159 | err = ptrace_dump_regs(pid); |
165 | if(err) | 160 | if (err) |
166 | printk("Failed to get registers from process, " | 161 | printk(UM_KERN_ERR "Failed to get registers " |
167 | "errno = %d\n", -err); | 162 | "from process, errno = %d\n", -err); |
168 | panic("handle_trap - failed to wait at end of syscall, " | 163 | panic("handle_trap - failed to wait at end of syscall, " |
169 | "errno = %d, status = %d\n", errno, status); | 164 | "errno = %d, status = %d\n", errno, status); |
170 | } | 165 | } |
@@ -182,63 +177,64 @@ static int userspace_tramp(void *stack) | |||
182 | 177 | ||
183 | ptrace(PTRACE_TRACEME, 0, 0, 0); | 178 | ptrace(PTRACE_TRACEME, 0, 0, 0); |
184 | 179 | ||
185 | init_new_thread_signals(); | 180 | signal(SIGTERM, SIG_DFL); |
186 | err = set_interval(1); | 181 | err = set_interval(); |
187 | if(err) | 182 | if (err) |
188 | panic("userspace_tramp - setting timer failed, errno = %d\n", | 183 | panic("userspace_tramp - setting timer failed, errno = %d\n", |
189 | err); | 184 | err); |
190 | 185 | ||
191 | if(!proc_mm){ | 186 | if (!proc_mm) { |
192 | /* This has a pte, but it can't be mapped in with the usual | 187 | /* |
188 | * This has a pte, but it can't be mapped in with the usual | ||
193 | * tlb_flush mechanism because this is part of that mechanism | 189 | * tlb_flush mechanism because this is part of that mechanism |
194 | */ | 190 | */ |
195 | int fd; | 191 | int fd; |
196 | __u64 offset; | 192 | unsigned long long offset; |
197 | fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); | 193 | fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); |
198 | addr = mmap64((void *) UML_CONFIG_STUB_CODE, UM_KERN_PAGE_SIZE, | 194 | addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE, |
199 | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); | 195 | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); |
200 | if(addr == MAP_FAILED){ | 196 | if (addr == MAP_FAILED) { |
201 | printk("mapping mmap stub failed, errno = %d\n", | 197 | printk(UM_KERN_ERR "mapping mmap stub at 0x%lx failed, " |
202 | errno); | 198 | "errno = %d\n", STUB_CODE, errno); |
203 | exit(1); | 199 | exit(1); |
204 | } | 200 | } |
205 | 201 | ||
206 | if(stack != NULL){ | 202 | if (stack != NULL) { |
207 | fd = phys_mapping(to_phys(stack), &offset); | 203 | fd = phys_mapping(to_phys(stack), &offset); |
208 | addr = mmap((void *) UML_CONFIG_STUB_DATA, | 204 | addr = mmap((void *) STUB_DATA, |
209 | UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, | 205 | UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, |
210 | MAP_FIXED | MAP_SHARED, fd, offset); | 206 | MAP_FIXED | MAP_SHARED, fd, offset); |
211 | if(addr == MAP_FAILED){ | 207 | if (addr == MAP_FAILED) { |
212 | printk("mapping segfault stack failed, " | 208 | printk(UM_KERN_ERR "mapping segfault stack " |
213 | "errno = %d\n", errno); | 209 | "at 0x%lx failed, errno = %d\n", |
210 | STUB_DATA, errno); | ||
214 | exit(1); | 211 | exit(1); |
215 | } | 212 | } |
216 | } | 213 | } |
217 | } | 214 | } |
218 | if(!ptrace_faultinfo && (stack != NULL)){ | 215 | if (!ptrace_faultinfo && (stack != NULL)) { |
219 | struct sigaction sa; | 216 | struct sigaction sa; |
220 | 217 | ||
221 | unsigned long v = UML_CONFIG_STUB_CODE + | 218 | unsigned long v = STUB_CODE + |
222 | (unsigned long) stub_segv_handler - | 219 | (unsigned long) stub_segv_handler - |
223 | (unsigned long) &__syscall_stub_start; | 220 | (unsigned long) &__syscall_stub_start; |
224 | 221 | ||
225 | set_sigstack((void *) UML_CONFIG_STUB_DATA, UM_KERN_PAGE_SIZE); | 222 | set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE); |
226 | sigemptyset(&sa.sa_mask); | 223 | sigemptyset(&sa.sa_mask); |
227 | sigaddset(&sa.sa_mask, SIGIO); | 224 | sigaddset(&sa.sa_mask, SIGIO); |
228 | sigaddset(&sa.sa_mask, SIGWINCH); | 225 | sigaddset(&sa.sa_mask, SIGWINCH); |
229 | sigaddset(&sa.sa_mask, SIGALRM); | ||
230 | sigaddset(&sa.sa_mask, SIGVTALRM); | 226 | sigaddset(&sa.sa_mask, SIGVTALRM); |
231 | sigaddset(&sa.sa_mask, SIGUSR1); | 227 | sigaddset(&sa.sa_mask, SIGUSR1); |
232 | sa.sa_flags = SA_ONSTACK; | 228 | sa.sa_flags = SA_ONSTACK; |
233 | sa.sa_handler = (void *) v; | 229 | sa.sa_handler = (void *) v; |
234 | sa.sa_restorer = NULL; | 230 | sa.sa_restorer = NULL; |
235 | if(sigaction(SIGSEGV, &sa, NULL) < 0) | 231 | if (sigaction(SIGSEGV, &sa, NULL) < 0) |
236 | panic("userspace_tramp - setting SIGSEGV handler " | 232 | panic("userspace_tramp - setting SIGSEGV handler " |
237 | "failed - errno = %d\n", errno); | 233 | "failed - errno = %d\n", errno); |
238 | } | 234 | } |
239 | 235 | ||
240 | os_stop_process(os_getpid()); | 236 | kill(os_getpid(), SIGSTOP); |
241 | return(0); | 237 | return 0; |
242 | } | 238 | } |
243 | 239 | ||
244 | /* Each element set once, and only accessed by a single processor anyway */ | 240 | /* Each element set once, and only accessed by a single processor anyway */ |
@@ -255,44 +251,55 @@ int start_userspace(unsigned long stub_stack) | |||
255 | stack = mmap(NULL, UM_KERN_PAGE_SIZE, | 251 | stack = mmap(NULL, UM_KERN_PAGE_SIZE, |
256 | PROT_READ | PROT_WRITE | PROT_EXEC, | 252 | PROT_READ | PROT_WRITE | PROT_EXEC, |
257 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | 253 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
258 | if(stack == MAP_FAILED) | 254 | if (stack == MAP_FAILED) |
259 | panic("start_userspace : mmap failed, errno = %d", errno); | 255 | panic("start_userspace : mmap failed, errno = %d", errno); |
260 | sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); | 256 | sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); |
261 | 257 | ||
262 | flags = CLONE_FILES | SIGCHLD; | 258 | flags = CLONE_FILES | SIGCHLD; |
263 | if(proc_mm) flags |= CLONE_VM; | 259 | if (proc_mm) |
260 | flags |= CLONE_VM; | ||
261 | |||
264 | pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); | 262 | pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); |
265 | if(pid < 0) | 263 | if (pid < 0) |
266 | panic("start_userspace : clone failed, errno = %d", errno); | 264 | panic("start_userspace : clone failed, errno = %d", errno); |
267 | 265 | ||
268 | do { | 266 | do { |
269 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); | 267 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); |
270 | if(n < 0) | 268 | if (n < 0) |
271 | panic("start_userspace : wait failed, errno = %d", | 269 | panic("start_userspace : wait failed, errno = %d", |
272 | errno); | 270 | errno); |
273 | } while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); | 271 | } while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); |
274 | 272 | ||
275 | if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) | 273 | if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) |
276 | panic("start_userspace : expected SIGSTOP, got status = %d", | 274 | panic("start_userspace : expected SIGSTOP, got status = %d", |
277 | status); | 275 | status); |
278 | 276 | ||
279 | if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0) | 277 | if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, |
280 | panic("start_userspace : PTRACE_OLDSETOPTIONS failed, errno=%d\n", | 278 | (void *) PTRACE_O_TRACESYSGOOD) < 0) |
281 | errno); | 279 | panic("start_userspace : PTRACE_OLDSETOPTIONS failed, " |
280 | "errno = %d\n", errno); | ||
282 | 281 | ||
283 | if(munmap(stack, UM_KERN_PAGE_SIZE) < 0) | 282 | if (munmap(stack, UM_KERN_PAGE_SIZE) < 0) |
284 | panic("start_userspace : munmap failed, errno = %d\n", errno); | 283 | panic("start_userspace : munmap failed, errno = %d\n", errno); |
285 | 284 | ||
286 | return(pid); | 285 | return pid; |
287 | } | 286 | } |
288 | 287 | ||
289 | void userspace(union uml_pt_regs *regs) | 288 | void userspace(struct uml_pt_regs *regs) |
290 | { | 289 | { |
290 | struct itimerval timer; | ||
291 | unsigned long long nsecs, now; | ||
291 | int err, status, op, pid = userspace_pid[0]; | 292 | int err, status, op, pid = userspace_pid[0]; |
292 | /* To prevent races if using_sysemu changes under us.*/ | 293 | /* To prevent races if using_sysemu changes under us.*/ |
293 | int local_using_sysemu; | 294 | int local_using_sysemu; |
294 | 295 | ||
295 | while(1){ | 296 | if (getitimer(ITIMER_VIRTUAL, &timer)) |
297 | printk("Failed to get itimer, errno = %d\n", errno); | ||
298 | nsecs = timer.it_value.tv_sec * UM_NSEC_PER_SEC + | ||
299 | timer.it_value.tv_usec * UM_NSEC_PER_USEC; | ||
300 | nsecs += os_nsecs(); | ||
301 | |||
302 | while (1) { | ||
296 | restore_registers(pid, regs); | 303 | restore_registers(pid, regs); |
297 | 304 | ||
298 | /* Now we set local_using_sysemu to be used for one loop */ | 305 | /* Now we set local_using_sysemu to be used for one loop */ |
@@ -302,26 +309,28 @@ void userspace(union uml_pt_regs *regs) | |||
302 | singlestepping(NULL)); | 309 | singlestepping(NULL)); |
303 | 310 | ||
304 | err = ptrace(op, pid, 0, 0); | 311 | err = ptrace(op, pid, 0, 0); |
305 | if(err) | 312 | if (err) |
306 | panic("userspace - could not resume userspace process, " | 313 | panic("userspace - could not resume userspace process, " |
307 | "pid=%d, ptrace operation = %d, errno = %d\n", | 314 | "pid=%d, ptrace operation = %d, errno = %d\n", |
308 | pid, op, errno); | 315 | pid, op, errno); |
309 | 316 | ||
310 | CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); | 317 | CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); |
311 | if(err < 0) | 318 | if (err < 0) |
312 | panic("userspace - waitpid failed, errno = %d\n", | 319 | panic("userspace - waitpid failed, errno = %d\n", |
313 | errno); | 320 | errno); |
314 | 321 | ||
315 | regs->skas.is_user = 1; | 322 | regs->is_user = 1; |
316 | save_registers(pid, regs); | 323 | save_registers(pid, regs); |
317 | UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ | 324 | UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ |
318 | 325 | ||
319 | if(WIFSTOPPED(status)){ | 326 | if (WIFSTOPPED(status)) { |
320 | int sig = WSTOPSIG(status); | 327 | int sig = WSTOPSIG(status); |
321 | switch(sig){ | 328 | switch(sig) { |
322 | case SIGSEGV: | 329 | case SIGSEGV: |
323 | if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo){ | 330 | if (PTRACE_FULL_FAULTINFO || |
324 | get_skas_faultinfo(pid, ®s->skas.faultinfo); | 331 | !ptrace_faultinfo) { |
332 | get_skas_faultinfo(pid, | ||
333 | ®s->faultinfo); | ||
325 | (*sig_info[SIGSEGV])(SIGSEGV, regs); | 334 | (*sig_info[SIGSEGV])(SIGSEGV, regs); |
326 | } | 335 | } |
327 | else handle_segv(pid, regs); | 336 | else handle_segv(pid, regs); |
@@ -332,8 +341,20 @@ void userspace(union uml_pt_regs *regs) | |||
332 | case SIGTRAP: | 341 | case SIGTRAP: |
333 | relay_signal(SIGTRAP, regs); | 342 | relay_signal(SIGTRAP, regs); |
334 | break; | 343 | break; |
335 | case SIGIO: | ||
336 | case SIGVTALRM: | 344 | case SIGVTALRM: |
345 | now = os_nsecs(); | ||
346 | if(now < nsecs) | ||
347 | break; | ||
348 | block_signals(); | ||
349 | (*sig_info[sig])(sig, regs); | ||
350 | unblock_signals(); | ||
351 | nsecs = timer.it_value.tv_sec * | ||
352 | UM_NSEC_PER_SEC + | ||
353 | timer.it_value.tv_usec * | ||
354 | UM_NSEC_PER_USEC; | ||
355 | nsecs += os_nsecs(); | ||
356 | break; | ||
357 | case SIGIO: | ||
337 | case SIGILL: | 358 | case SIGILL: |
338 | case SIGBUS: | 359 | case SIGBUS: |
339 | case SIGFPE: | 360 | case SIGFPE: |
@@ -343,30 +364,29 @@ void userspace(union uml_pt_regs *regs) | |||
343 | unblock_signals(); | 364 | unblock_signals(); |
344 | break; | 365 | break; |
345 | default: | 366 | default: |
346 | printk("userspace - child stopped with signal " | 367 | printk(UM_KERN_ERR "userspace - child stopped " |
347 | "%d\n", sig); | 368 | "with signal %d\n", sig); |
348 | } | 369 | } |
349 | pid = userspace_pid[0]; | 370 | pid = userspace_pid[0]; |
350 | interrupt_end(); | 371 | interrupt_end(); |
351 | 372 | ||
352 | /* Avoid -ERESTARTSYS handling in host */ | 373 | /* Avoid -ERESTARTSYS handling in host */ |
353 | if(PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET) | 374 | if (PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET) |
354 | PT_SYSCALL_NR(regs->skas.regs) = -1; | 375 | PT_SYSCALL_NR(regs->gp) = -1; |
355 | } | 376 | } |
356 | } | 377 | } |
357 | } | 378 | } |
358 | 379 | ||
359 | static unsigned long thread_regs[MAX_REG_NR]; | 380 | static unsigned long thread_regs[MAX_REG_NR]; |
360 | static unsigned long thread_fp_regs[HOST_FP_SIZE]; | ||
361 | 381 | ||
362 | static int __init init_thread_regs(void) | 382 | static int __init init_thread_regs(void) |
363 | { | 383 | { |
364 | get_safe_registers(thread_regs, thread_fp_regs); | 384 | get_safe_registers(thread_regs); |
365 | /* Set parent's instruction pointer to start of clone-stub */ | 385 | /* Set parent's instruction pointer to start of clone-stub */ |
366 | thread_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + | 386 | thread_regs[REGS_IP_INDEX] = STUB_CODE + |
367 | (unsigned long) stub_clone_handler - | 387 | (unsigned long) stub_clone_handler - |
368 | (unsigned long) &__syscall_stub_start; | 388 | (unsigned long) &__syscall_stub_start; |
369 | thread_regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + UM_KERN_PAGE_SIZE - | 389 | thread_regs[REGS_SP_INDEX] = STUB_DATA + UM_KERN_PAGE_SIZE - |
370 | sizeof(void *); | 390 | sizeof(void *); |
371 | #ifdef __SIGNAL_FRAMESIZE | 391 | #ifdef __SIGNAL_FRAMESIZE |
372 | thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE; | 392 | thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE; |
@@ -378,53 +398,53 @@ __initcall(init_thread_regs); | |||
378 | 398 | ||
379 | int copy_context_skas0(unsigned long new_stack, int pid) | 399 | int copy_context_skas0(unsigned long new_stack, int pid) |
380 | { | 400 | { |
401 | struct timeval tv = { .tv_sec = 0, .tv_usec = UM_USEC_PER_SEC / UM_HZ }; | ||
381 | int err; | 402 | int err; |
382 | unsigned long current_stack = current_stub_stack(); | 403 | unsigned long current_stack = current_stub_stack(); |
383 | struct stub_data *data = (struct stub_data *) current_stack; | 404 | struct stub_data *data = (struct stub_data *) current_stack; |
384 | struct stub_data *child_data = (struct stub_data *) new_stack; | 405 | struct stub_data *child_data = (struct stub_data *) new_stack; |
385 | __u64 new_offset; | 406 | unsigned long long new_offset; |
386 | int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset); | 407 | int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset); |
387 | 408 | ||
388 | /* prepare offset and fd of child's stack as argument for parent's | 409 | /* |
410 | * prepare offset and fd of child's stack as argument for parent's | ||
389 | * and child's mmap2 calls | 411 | * and child's mmap2 calls |
390 | */ | 412 | */ |
391 | *data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset), | 413 | *data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset), |
392 | .fd = new_fd, | 414 | .fd = new_fd, |
393 | .timer = ((struct itimerval) | 415 | .timer = ((struct itimerval) |
394 | { { 0, 1000000 / hz() }, | 416 | { .it_value = tv, |
395 | { 0, 1000000 / hz() }})}); | 417 | .it_interval = tv }) }); |
418 | |||
396 | err = ptrace_setregs(pid, thread_regs); | 419 | err = ptrace_setregs(pid, thread_regs); |
397 | if(err < 0) | 420 | if (err < 0) |
398 | panic("copy_context_skas0 : PTRACE_SETREGS failed, " | 421 | panic("copy_context_skas0 : PTRACE_SETREGS failed, " |
399 | "pid = %d, errno = %d\n", pid, -err); | 422 | "pid = %d, errno = %d\n", pid, -err); |
400 | 423 | ||
401 | err = ptrace_setfpregs(pid, thread_fp_regs); | ||
402 | if(err < 0) | ||
403 | panic("copy_context_skas0 : PTRACE_SETFPREGS failed, " | ||
404 | "pid = %d, errno = %d\n", pid, -err); | ||
405 | |||
406 | /* set a well known return code for detection of child write failure */ | 424 | /* set a well known return code for detection of child write failure */ |
407 | child_data->err = 12345678; | 425 | child_data->err = 12345678; |
408 | 426 | ||
409 | /* Wait, until parent has finished its work: read child's pid from | 427 | /* |
428 | * Wait, until parent has finished its work: read child's pid from | ||
410 | * parent's stack, and check, if bad result. | 429 | * parent's stack, and check, if bad result. |
411 | */ | 430 | */ |
412 | err = ptrace(PTRACE_CONT, pid, 0, 0); | 431 | err = ptrace(PTRACE_CONT, pid, 0, 0); |
413 | if(err) | 432 | if (err) |
414 | panic("Failed to continue new process, pid = %d, " | 433 | panic("Failed to continue new process, pid = %d, " |
415 | "errno = %d\n", pid, errno); | 434 | "errno = %d\n", pid, errno); |
416 | wait_stub_done(pid); | 435 | wait_stub_done(pid); |
417 | 436 | ||
418 | pid = data->err; | 437 | pid = data->err; |
419 | if(pid < 0) | 438 | if (pid < 0) |
420 | panic("copy_context_skas0 - stub-parent reports error %d\n", | 439 | panic("copy_context_skas0 - stub-parent reports error %d\n", |
421 | -pid); | 440 | -pid); |
422 | 441 | ||
423 | /* Wait, until child has finished too: read child's result from | 442 | /* |
443 | * Wait, until child has finished too: read child's result from | ||
424 | * child's stack and check it. | 444 | * child's stack and check it. |
425 | */ | 445 | */ |
426 | wait_stub_done(pid); | 446 | wait_stub_done(pid); |
427 | if (child_data->err != UML_CONFIG_STUB_DATA) | 447 | if (child_data->err != STUB_DATA) |
428 | panic("copy_context_skas0 - stub-child reports error %ld\n", | 448 | panic("copy_context_skas0 - stub-child reports error %ld\n", |
429 | child_data->err); | 449 | child_data->err); |
430 | 450 | ||
@@ -446,7 +466,7 @@ void map_stub_pages(int fd, unsigned long code, | |||
446 | { | 466 | { |
447 | struct proc_mm_op mmop; | 467 | struct proc_mm_op mmop; |
448 | int n; | 468 | int n; |
449 | __u64 code_offset; | 469 | unsigned long long code_offset; |
450 | int code_fd = phys_mapping(to_phys((void *) &__syscall_stub_start), | 470 | int code_fd = phys_mapping(to_phys((void *) &__syscall_stub_start), |
451 | &code_offset); | 471 | &code_offset); |
452 | 472 | ||
@@ -461,16 +481,17 @@ void map_stub_pages(int fd, unsigned long code, | |||
461 | .offset = code_offset | 481 | .offset = code_offset |
462 | } } }); | 482 | } } }); |
463 | CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); | 483 | CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); |
464 | if(n != sizeof(mmop)){ | 484 | if (n != sizeof(mmop)) { |
465 | n = errno; | 485 | n = errno; |
466 | printk("mmap args - addr = 0x%lx, fd = %d, offset = %llx\n", | 486 | printk(UM_KERN_ERR "mmap args - addr = 0x%lx, fd = %d, " |
467 | code, code_fd, (unsigned long long) code_offset); | 487 | "offset = %llx\n", code, code_fd, |
488 | (unsigned long long) code_offset); | ||
468 | panic("map_stub_pages : /proc/mm map for code failed, " | 489 | panic("map_stub_pages : /proc/mm map for code failed, " |
469 | "err = %d\n", n); | 490 | "err = %d\n", n); |
470 | } | 491 | } |
471 | 492 | ||
472 | if ( stack ) { | 493 | if (stack) { |
473 | __u64 map_offset; | 494 | unsigned long long map_offset; |
474 | int map_fd = phys_mapping(to_phys((void *)stack), &map_offset); | 495 | int map_fd = phys_mapping(to_phys((void *)stack), &map_offset); |
475 | mmop = ((struct proc_mm_op) | 496 | mmop = ((struct proc_mm_op) |
476 | { .op = MM_MMAP, | 497 | { .op = MM_MMAP, |
@@ -484,7 +505,7 @@ void map_stub_pages(int fd, unsigned long code, | |||
484 | .offset = map_offset | 505 | .offset = map_offset |
485 | } } }); | 506 | } } }); |
486 | CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); | 507 | CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); |
487 | if(n != sizeof(mmop)) | 508 | if (n != sizeof(mmop)) |
488 | panic("map_stub_pages : /proc/mm map for data failed, " | 509 | panic("map_stub_pages : /proc/mm map for data failed, " |
489 | "err = %d\n", errno); | 510 | "err = %d\n", errno); |
490 | } | 511 | } |
@@ -504,7 +525,7 @@ void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) | |||
504 | 525 | ||
505 | void switch_threads(jmp_buf *me, jmp_buf *you) | 526 | void switch_threads(jmp_buf *me, jmp_buf *you) |
506 | { | 527 | { |
507 | if(UML_SETJMP(me) == 0) | 528 | if (UML_SETJMP(me) == 0) |
508 | UML_LONGJMP(you, 1); | 529 | UML_LONGJMP(you, 1); |
509 | } | 530 | } |
510 | 531 | ||
@@ -520,8 +541,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) | |||
520 | int n; | 541 | int n; |
521 | 542 | ||
522 | set_handler(SIGWINCH, (__sighandler_t) sig_handler, | 543 | set_handler(SIGWINCH, (__sighandler_t) sig_handler, |
523 | SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, | 544 | SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGVTALRM, -1); |
524 | SIGVTALRM, -1); | ||
525 | 545 | ||
526 | /* | 546 | /* |
527 | * Can't use UML_SETJMP or UML_LONGJMP here because they save | 547 | * Can't use UML_SETJMP or UML_LONGJMP here because they save |
@@ -532,7 +552,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) | |||
532 | * after returning to the jumper. | 552 | * after returning to the jumper. |
533 | */ | 553 | */ |
534 | n = setjmp(initial_jmpbuf); | 554 | n = setjmp(initial_jmpbuf); |
535 | switch(n){ | 555 | switch(n) { |
536 | case INIT_JMP_NEW_THREAD: | 556 | case INIT_JMP_NEW_THREAD: |
537 | (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler; | 557 | (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler; |
538 | (*switch_buf)[0].JB_SP = (unsigned long) stack + | 558 | (*switch_buf)[0].JB_SP = (unsigned long) stack + |
@@ -544,10 +564,10 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) | |||
544 | break; | 564 | break; |
545 | case INIT_JMP_HALT: | 565 | case INIT_JMP_HALT: |
546 | kmalloc_ok = 0; | 566 | kmalloc_ok = 0; |
547 | return(0); | 567 | return 0; |
548 | case INIT_JMP_REBOOT: | 568 | case INIT_JMP_REBOOT: |
549 | kmalloc_ok = 0; | 569 | kmalloc_ok = 0; |
550 | return(1); | 570 | return 1; |
551 | default: | 571 | default: |
552 | panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); | 572 | panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); |
553 | } | 573 | } |
@@ -563,7 +583,7 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg) | |||
563 | cb_back = &here; | 583 | cb_back = &here; |
564 | 584 | ||
565 | block_signals(); | 585 | block_signals(); |
566 | if(UML_SETJMP(&here) == 0) | 586 | if (UML_SETJMP(&here) == 0) |
567 | UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK); | 587 | UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK); |
568 | unblock_signals(); | 588 | unblock_signals(); |
569 | 589 | ||
@@ -584,16 +604,16 @@ void reboot_skas(void) | |||
584 | UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT); | 604 | UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT); |
585 | } | 605 | } |
586 | 606 | ||
587 | void switch_mm_skas(struct mm_id *mm_idp) | 607 | void __switch_mm(struct mm_id *mm_idp) |
588 | { | 608 | { |
589 | int err; | 609 | int err; |
590 | 610 | ||
591 | /* FIXME: need cpu pid in switch_mm_skas */ | 611 | /* FIXME: need cpu pid in __switch_mm */ |
592 | if(proc_mm){ | 612 | if (proc_mm) { |
593 | err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, | 613 | err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, |
594 | mm_idp->u.mm_fd); | 614 | mm_idp->u.mm_fd); |
595 | if(err) | 615 | if (err) |
596 | panic("switch_mm_skas - PTRACE_SWITCH_MM failed, " | 616 | panic("__switch_mm - PTRACE_SWITCH_MM failed, " |
597 | "errno = %d\n", errno); | 617 | "errno = %d\n", errno); |
598 | } | 618 | } |
599 | else userspace_pid[0] = mm_idp->u.pid; | 619 | else userspace_pid[0] = mm_idp->u.pid; |
diff --git a/arch/um/os-Linux/skas/trap.c b/arch/um/os-Linux/skas/trap.c index 3b600c2e63b8..3b1b9244f468 100644 --- a/arch/um/os-Linux/skas/trap.c +++ b/arch/um/os-Linux/skas/trap.c | |||
@@ -1,37 +1,43 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <signal.h> | 6 | #if 0 |
7 | #include <errno.h> | ||
8 | #include "kern_util.h" | 7 | #include "kern_util.h" |
9 | #include "as-layout.h" | ||
10 | #include "task.h" | ||
11 | #include "sigcontext.h" | ||
12 | #include "skas.h" | 8 | #include "skas.h" |
13 | #include "ptrace_user.h" | 9 | #include "ptrace_user.h" |
14 | #include "sysdep/ptrace.h" | ||
15 | #include "sysdep/ptrace_user.h" | 10 | #include "sysdep/ptrace_user.h" |
11 | #endif | ||
12 | |||
13 | #include <errno.h> | ||
14 | #include <signal.h> | ||
15 | #include "sysdep/ptrace.h" | ||
16 | #include "kern_constants.h" | ||
17 | #include "as-layout.h" | ||
16 | #include "os.h" | 18 | #include "os.h" |
19 | #include "sigcontext.h" | ||
20 | #include "task.h" | ||
17 | 21 | ||
18 | static union uml_pt_regs ksig_regs[UM_NR_CPUS]; | 22 | static struct uml_pt_regs ksig_regs[UM_NR_CPUS]; |
19 | 23 | ||
20 | void sig_handler_common_skas(int sig, void *sc_ptr) | 24 | void sig_handler_common_skas(int sig, void *sc_ptr) |
21 | { | 25 | { |
22 | struct sigcontext *sc = sc_ptr; | 26 | struct sigcontext *sc = sc_ptr; |
23 | union uml_pt_regs *r; | 27 | struct uml_pt_regs *r; |
24 | void (*handler)(int, union uml_pt_regs *); | 28 | void (*handler)(int, struct uml_pt_regs *); |
25 | int save_user, save_errno = errno; | 29 | int save_user, save_errno = errno; |
26 | 30 | ||
27 | /* This is done because to allow SIGSEGV to be delivered inside a SEGV | 31 | /* |
32 | * This is done because to allow SIGSEGV to be delivered inside a SEGV | ||
28 | * handler. This can happen in copy_user, and if SEGV is disabled, | 33 | * handler. This can happen in copy_user, and if SEGV is disabled, |
29 | * the process will die. | 34 | * the process will die. |
30 | * XXX Figure out why this is better than SA_NODEFER | 35 | * XXX Figure out why this is better than SA_NODEFER |
31 | */ | 36 | */ |
32 | if(sig == SIGSEGV) { | 37 | if (sig == SIGSEGV) { |
33 | change_sig(SIGSEGV, 1); | 38 | change_sig(SIGSEGV, 1); |
34 | /* For segfaults, we want the data from the | 39 | /* |
40 | * For segfaults, we want the data from the | ||
35 | * sigcontext. In this case, we don't want to mangle | 41 | * sigcontext. In this case, we don't want to mangle |
36 | * the process registers, so use a static set of | 42 | * the process registers, so use a static set of |
37 | * registers. For other signals, the process | 43 | * registers. For other signals, the process |
@@ -42,25 +48,22 @@ void sig_handler_common_skas(int sig, void *sc_ptr) | |||
42 | } | 48 | } |
43 | else r = TASK_REGS(get_current()); | 49 | else r = TASK_REGS(get_current()); |
44 | 50 | ||
45 | save_user = r->skas.is_user; | 51 | save_user = r->is_user; |
46 | r->skas.is_user = 0; | 52 | r->is_user = 0; |
47 | if ( sig == SIGFPE || sig == SIGSEGV || | 53 | if ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) || |
48 | sig == SIGBUS || sig == SIGILL || | 54 | (sig == SIGILL) || (sig == SIGTRAP)) |
49 | sig == SIGTRAP ) { | 55 | GET_FAULTINFO_FROM_SC(r->faultinfo, sc); |
50 | GET_FAULTINFO_FROM_SC(r->skas.faultinfo, sc); | ||
51 | } | ||
52 | 56 | ||
53 | change_sig(SIGUSR1, 1); | 57 | change_sig(SIGUSR1, 1); |
54 | 58 | ||
55 | handler = sig_info[sig]; | 59 | handler = sig_info[sig]; |
56 | 60 | ||
57 | /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */ | 61 | /* unblock SIGVTALRM, SIGIO if sig isn't IRQ signal */ |
58 | if (sig != SIGIO && sig != SIGWINCH && | 62 | if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM)) |
59 | sig != SIGVTALRM && sig != SIGALRM) | ||
60 | unblock_signals(); | 63 | unblock_signals(); |
61 | 64 | ||
62 | handler(sig, r); | 65 | handler(sig, r); |
63 | 66 | ||
64 | errno = save_errno; | 67 | errno = save_errno; |
65 | r->skas.is_user = save_user; | 68 | r->is_user = save_user; |
66 | } | 69 | } |
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 46f613975c19..7b81f6c08a5e 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c | |||
@@ -1,75 +1,65 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <pty.h> | ||
7 | #include <stdio.h> | 6 | #include <stdio.h> |
8 | #include <stddef.h> | ||
9 | #include <stdarg.h> | ||
10 | #include <stdlib.h> | 7 | #include <stdlib.h> |
11 | #include <string.h> | 8 | #include <stdarg.h> |
12 | #include <unistd.h> | 9 | #include <unistd.h> |
13 | #include <signal.h> | ||
14 | #include <sched.h> | ||
15 | #include <fcntl.h> | ||
16 | #include <errno.h> | 10 | #include <errno.h> |
17 | #include <sys/time.h> | 11 | #include <fcntl.h> |
18 | #include <sys/wait.h> | 12 | #include <sched.h> |
13 | #include <signal.h> | ||
14 | #include <string.h> | ||
19 | #include <sys/mman.h> | 15 | #include <sys/mman.h> |
20 | #include <sys/resource.h> | 16 | #include <sys/ptrace.h> |
17 | #include <sys/stat.h> | ||
18 | #include <sys/wait.h> | ||
21 | #include <asm/unistd.h> | 19 | #include <asm/unistd.h> |
22 | #include <asm/page.h> | ||
23 | #include <sys/types.h> | ||
24 | #include "kern_util.h" | ||
25 | #include "user.h" | ||
26 | #include "signal_kern.h" | ||
27 | #include "sysdep/ptrace.h" | ||
28 | #include "sysdep/sigcontext.h" | ||
29 | #include "irq_user.h" | ||
30 | #include "ptrace_user.h" | ||
31 | #include "mem_user.h" | ||
32 | #include "init.h" | 20 | #include "init.h" |
33 | #include "os.h" | ||
34 | #include "uml-config.h" | ||
35 | #include "choose-mode.h" | ||
36 | #include "mode.h" | ||
37 | #include "tempfile.h" | ||
38 | #include "kern_constants.h" | 21 | #include "kern_constants.h" |
39 | 22 | #include "os.h" | |
40 | #ifdef UML_CONFIG_MODE_SKAS | 23 | #include "mem_user.h" |
41 | #include "skas.h" | 24 | #include "ptrace_user.h" |
42 | #include "skas_ptrace.h" | ||
43 | #include "registers.h" | 25 | #include "registers.h" |
44 | #endif | 26 | #include "skas_ptrace.h" |
45 | 27 | ||
46 | static int ptrace_child(void *arg) | 28 | static int ptrace_child(void) |
47 | { | 29 | { |
48 | int ret; | 30 | int ret; |
31 | /* Calling os_getpid because some libcs cached getpid incorrectly */ | ||
49 | int pid = os_getpid(), ppid = getppid(); | 32 | int pid = os_getpid(), ppid = getppid(); |
50 | int sc_result; | 33 | int sc_result; |
51 | 34 | ||
52 | change_sig(SIGWINCH, 0); | 35 | change_sig(SIGWINCH, 0); |
53 | if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ | 36 | if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) { |
54 | perror("ptrace"); | 37 | perror("ptrace"); |
55 | os_kill_process(pid, 0); | 38 | kill(pid, SIGKILL); |
56 | } | 39 | } |
57 | kill(pid, SIGSTOP); | 40 | kill(pid, SIGSTOP); |
58 | 41 | ||
59 | /*This syscall will be intercepted by the parent. Don't call more than | 42 | /* |
60 | * once, please.*/ | 43 | * This syscall will be intercepted by the parent. Don't call more than |
44 | * once, please. | ||
45 | */ | ||
61 | sc_result = os_getpid(); | 46 | sc_result = os_getpid(); |
62 | 47 | ||
63 | if (sc_result == pid) | 48 | if (sc_result == pid) |
64 | ret = 1; /*Nothing modified by the parent, we are running | 49 | /* Nothing modified by the parent, we are running normally. */ |
65 | normally.*/ | 50 | ret = 1; |
66 | else if (sc_result == ppid) | 51 | else if (sc_result == ppid) |
67 | ret = 0; /*Expected in check_ptrace and check_sysemu when they | 52 | /* |
68 | succeed in modifying the stack frame*/ | 53 | * Expected in check_ptrace and check_sysemu when they succeed |
54 | * in modifying the stack frame | ||
55 | */ | ||
56 | ret = 0; | ||
69 | else | 57 | else |
70 | ret = 2; /*Serious trouble! This could be caused by a bug in | 58 | /* Serious trouble! This could be caused by a bug in host 2.6 |
71 | host 2.6 SKAS3/2.6 patch before release -V6, together | 59 | * SKAS3/2.6 patch before release -V6, together with a bug in |
72 | with a bug in the UML code itself.*/ | 60 | * the UML code itself. |
61 | */ | ||
62 | ret = 2; | ||
73 | _exit(ret); | 63 | _exit(ret); |
74 | } | 64 | } |
75 | 65 | ||
@@ -101,29 +91,23 @@ static void non_fatal(char *fmt, ...) | |||
101 | fflush(stdout); | 91 | fflush(stdout); |
102 | } | 92 | } |
103 | 93 | ||
104 | static int start_ptraced_child(void **stack_out) | 94 | static int start_ptraced_child(void) |
105 | { | 95 | { |
106 | void *stack; | ||
107 | unsigned long sp; | ||
108 | int pid, n, status; | 96 | int pid, n, status; |
109 | 97 | ||
110 | stack = mmap(NULL, UM_KERN_PAGE_SIZE, | 98 | pid = fork(); |
111 | PROT_READ | PROT_WRITE | PROT_EXEC, | 99 | if (pid == 0) |
112 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | 100 | ptrace_child(); |
113 | if(stack == MAP_FAILED) | 101 | else if (pid < 0) |
114 | fatal_perror("check_ptrace : mmap failed"); | 102 | fatal_perror("start_ptraced_child : fork failed"); |
115 | sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); | 103 | |
116 | pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL); | ||
117 | if(pid < 0) | ||
118 | fatal_perror("start_ptraced_child : clone failed"); | ||
119 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); | 104 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); |
120 | if(n < 0) | 105 | if (n < 0) |
121 | fatal_perror("check_ptrace : clone failed"); | 106 | fatal_perror("check_ptrace : waitpid failed"); |
122 | if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) | 107 | if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) |
123 | fatal("check_ptrace : expected SIGSTOP, got status = %d", | 108 | fatal("check_ptrace : expected SIGSTOP, got status = %d", |
124 | status); | 109 | status); |
125 | 110 | ||
126 | *stack_out = stack; | ||
127 | return pid; | 111 | return pid; |
128 | } | 112 | } |
129 | 113 | ||
@@ -133,15 +117,14 @@ static int start_ptraced_child(void **stack_out) | |||
133 | * So only for SYSEMU features we test mustpanic, while normal host features | 117 | * So only for SYSEMU features we test mustpanic, while normal host features |
134 | * must work anyway! | 118 | * must work anyway! |
135 | */ | 119 | */ |
136 | static int stop_ptraced_child(int pid, void *stack, int exitcode, | 120 | static int stop_ptraced_child(int pid, int exitcode, int mustexit) |
137 | int mustexit) | ||
138 | { | 121 | { |
139 | int status, n, ret = 0; | 122 | int status, n, ret = 0; |
140 | 123 | ||
141 | if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) | 124 | if (ptrace(PTRACE_CONT, pid, 0, 0) < 0) |
142 | fatal_perror("stop_ptraced_child : ptrace failed"); | 125 | fatal_perror("stop_ptraced_child : ptrace failed"); |
143 | CATCH_EINTR(n = waitpid(pid, &status, 0)); | 126 | CATCH_EINTR(n = waitpid(pid, &status, 0)); |
144 | if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { | 127 | if (!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { |
145 | int exit_with = WEXITSTATUS(status); | 128 | int exit_with = WEXITSTATUS(status); |
146 | if (exit_with == 2) | 129 | if (exit_with == 2) |
147 | non_fatal("check_ptrace : child exited with status 2. " | 130 | non_fatal("check_ptrace : child exited with status 2. " |
@@ -154,8 +137,6 @@ static int stop_ptraced_child(int pid, void *stack, int exitcode, | |||
154 | ret = -1; | 137 | ret = -1; |
155 | } | 138 | } |
156 | 139 | ||
157 | if(munmap(stack, UM_KERN_PAGE_SIZE) < 0) | ||
158 | fatal_perror("check_ptrace : munmap failed"); | ||
159 | return ret; | 140 | return ret; |
160 | } | 141 | } |
161 | 142 | ||
@@ -207,40 +188,39 @@ __uml_setup("nosysemu", nosysemu_cmd_param, | |||
207 | 188 | ||
208 | static void __init check_sysemu(void) | 189 | static void __init check_sysemu(void) |
209 | { | 190 | { |
210 | void *stack; | ||
211 | unsigned long regs[MAX_REG_NR]; | 191 | unsigned long regs[MAX_REG_NR]; |
212 | int pid, n, status, count=0; | 192 | int pid, n, status, count=0; |
213 | 193 | ||
214 | non_fatal("Checking syscall emulation patch for ptrace..."); | 194 | non_fatal("Checking syscall emulation patch for ptrace..."); |
215 | sysemu_supported = 0; | 195 | sysemu_supported = 0; |
216 | pid = start_ptraced_child(&stack); | 196 | pid = start_ptraced_child(); |
217 | 197 | ||
218 | if(ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0) | 198 | if (ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0) |
219 | goto fail; | 199 | goto fail; |
220 | 200 | ||
221 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); | 201 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); |
222 | if (n < 0) | 202 | if (n < 0) |
223 | fatal_perror("check_sysemu : wait failed"); | 203 | fatal_perror("check_sysemu : wait failed"); |
224 | if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) | 204 | if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) |
225 | fatal("check_sysemu : expected SIGTRAP, got status = %d", | 205 | fatal("check_sysemu : expected SIGTRAP, got status = %d", |
226 | status); | 206 | status); |
227 | 207 | ||
228 | if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) | 208 | if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) |
229 | fatal_perror("check_sysemu : PTRACE_GETREGS failed"); | 209 | fatal_perror("check_sysemu : PTRACE_GETREGS failed"); |
230 | if(PT_SYSCALL_NR(regs) != __NR_getpid){ | 210 | if (PT_SYSCALL_NR(regs) != __NR_getpid) { |
231 | non_fatal("check_sysemu got system call number %d, " | 211 | non_fatal("check_sysemu got system call number %d, " |
232 | "expected %d...", PT_SYSCALL_NR(regs), __NR_getpid); | 212 | "expected %d...", PT_SYSCALL_NR(regs), __NR_getpid); |
233 | goto fail; | 213 | goto fail; |
234 | } | 214 | } |
235 | 215 | ||
236 | n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid()); | 216 | n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid()); |
237 | if(n < 0){ | 217 | if (n < 0) { |
238 | non_fatal("check_sysemu : failed to modify system call " | 218 | non_fatal("check_sysemu : failed to modify system call " |
239 | "return"); | 219 | "return"); |
240 | goto fail; | 220 | goto fail; |
241 | } | 221 | } |
242 | 222 | ||
243 | if (stop_ptraced_child(pid, stack, 0, 0) < 0) | 223 | if (stop_ptraced_child(pid, 0, 0) < 0) |
244 | goto fail_stopped; | 224 | goto fail_stopped; |
245 | 225 | ||
246 | sysemu_supported = 1; | 226 | sysemu_supported = 1; |
@@ -248,90 +228,90 @@ static void __init check_sysemu(void) | |||
248 | set_using_sysemu(!force_sysemu_disabled); | 228 | set_using_sysemu(!force_sysemu_disabled); |
249 | 229 | ||
250 | non_fatal("Checking advanced syscall emulation patch for ptrace..."); | 230 | non_fatal("Checking advanced syscall emulation patch for ptrace..."); |
251 | pid = start_ptraced_child(&stack); | 231 | pid = start_ptraced_child(); |
252 | 232 | ||
253 | if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, | 233 | if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, |
254 | (void *) PTRACE_O_TRACESYSGOOD) < 0)) | 234 | (void *) PTRACE_O_TRACESYSGOOD) < 0)) |
255 | fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed"); | 235 | fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed"); |
256 | 236 | ||
257 | while(1){ | 237 | while (1) { |
258 | count++; | 238 | count++; |
259 | if(ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0) | 239 | if (ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0) |
260 | goto fail; | 240 | goto fail; |
261 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); | 241 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); |
262 | if(n < 0) | 242 | if (n < 0) |
263 | fatal_perror("check_ptrace : wait failed"); | 243 | fatal_perror("check_ptrace : wait failed"); |
264 | 244 | ||
265 | if(WIFSTOPPED(status) && (WSTOPSIG(status) == (SIGTRAP|0x80))){ | 245 | if (WIFSTOPPED(status) && |
246 | (WSTOPSIG(status) == (SIGTRAP|0x80))) { | ||
266 | if (!count) | 247 | if (!count) |
267 | fatal("check_ptrace : SYSEMU_SINGLESTEP " | 248 | fatal("check_ptrace : SYSEMU_SINGLESTEP " |
268 | "doesn't singlestep"); | 249 | "doesn't singlestep"); |
269 | n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, | 250 | n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, |
270 | os_getpid()); | 251 | os_getpid()); |
271 | if(n < 0) | 252 | if (n < 0) |
272 | fatal_perror("check_sysemu : failed to modify " | 253 | fatal_perror("check_sysemu : failed to modify " |
273 | "system call return"); | 254 | "system call return"); |
274 | break; | 255 | break; |
275 | } | 256 | } |
276 | else if(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) | 257 | else if (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) |
277 | count++; | 258 | count++; |
278 | else | 259 | else |
279 | fatal("check_ptrace : expected SIGTRAP or " | 260 | fatal("check_ptrace : expected SIGTRAP or " |
280 | "(SIGTRAP | 0x80), got status = %d", status); | 261 | "(SIGTRAP | 0x80), got status = %d", status); |
281 | } | 262 | } |
282 | if (stop_ptraced_child(pid, stack, 0, 0) < 0) | 263 | if (stop_ptraced_child(pid, 0, 0) < 0) |
283 | goto fail_stopped; | 264 | goto fail_stopped; |
284 | 265 | ||
285 | sysemu_supported = 2; | 266 | sysemu_supported = 2; |
286 | non_fatal("OK\n"); | 267 | non_fatal("OK\n"); |
287 | 268 | ||
288 | if ( !force_sysemu_disabled ) | 269 | if (!force_sysemu_disabled) |
289 | set_using_sysemu(sysemu_supported); | 270 | set_using_sysemu(sysemu_supported); |
290 | return; | 271 | return; |
291 | 272 | ||
292 | fail: | 273 | fail: |
293 | stop_ptraced_child(pid, stack, 1, 0); | 274 | stop_ptraced_child(pid, 1, 0); |
294 | fail_stopped: | 275 | fail_stopped: |
295 | non_fatal("missing\n"); | 276 | non_fatal("missing\n"); |
296 | } | 277 | } |
297 | 278 | ||
298 | static void __init check_ptrace(void) | 279 | static void __init check_ptrace(void) |
299 | { | 280 | { |
300 | void *stack; | ||
301 | int pid, syscall, n, status; | 281 | int pid, syscall, n, status; |
302 | 282 | ||
303 | non_fatal("Checking that ptrace can change system call numbers..."); | 283 | non_fatal("Checking that ptrace can change system call numbers..."); |
304 | pid = start_ptraced_child(&stack); | 284 | pid = start_ptraced_child(); |
305 | 285 | ||
306 | if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, | 286 | if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, |
307 | (void *) PTRACE_O_TRACESYSGOOD) < 0)) | 287 | (void *) PTRACE_O_TRACESYSGOOD) < 0)) |
308 | fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed"); | 288 | fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed"); |
309 | 289 | ||
310 | while(1){ | 290 | while (1) { |
311 | if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) | 291 | if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) |
312 | fatal_perror("check_ptrace : ptrace failed"); | 292 | fatal_perror("check_ptrace : ptrace failed"); |
313 | 293 | ||
314 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); | 294 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); |
315 | if(n < 0) | 295 | if (n < 0) |
316 | fatal_perror("check_ptrace : wait failed"); | 296 | fatal_perror("check_ptrace : wait failed"); |
317 | 297 | ||
318 | if(!WIFSTOPPED(status) || | 298 | if (!WIFSTOPPED(status) || |
319 | (WSTOPSIG(status) != (SIGTRAP | 0x80))) | 299 | (WSTOPSIG(status) != (SIGTRAP | 0x80))) |
320 | fatal("check_ptrace : expected (SIGTRAP|0x80), " | 300 | fatal("check_ptrace : expected (SIGTRAP|0x80), " |
321 | "got status = %d", status); | 301 | "got status = %d", status); |
322 | 302 | ||
323 | syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, | 303 | syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, |
324 | 0); | 304 | 0); |
325 | if(syscall == __NR_getpid){ | 305 | if (syscall == __NR_getpid) { |
326 | n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, | 306 | n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, |
327 | __NR_getppid); | 307 | __NR_getppid); |
328 | if(n < 0) | 308 | if (n < 0) |
329 | fatal_perror("check_ptrace : failed to modify " | 309 | fatal_perror("check_ptrace : failed to modify " |
330 | "system call"); | 310 | "system call"); |
331 | break; | 311 | break; |
332 | } | 312 | } |
333 | } | 313 | } |
334 | stop_ptraced_child(pid, stack, 0, 1); | 314 | stop_ptraced_child(pid, 0, 1); |
335 | non_fatal("OK\n"); | 315 | non_fatal("OK\n"); |
336 | check_sysemu(); | 316 | check_sysemu(); |
337 | } | 317 | } |
@@ -343,18 +323,18 @@ static void __init check_coredump_limit(void) | |||
343 | struct rlimit lim; | 323 | struct rlimit lim; |
344 | int err = getrlimit(RLIMIT_CORE, &lim); | 324 | int err = getrlimit(RLIMIT_CORE, &lim); |
345 | 325 | ||
346 | if(err){ | 326 | if (err) { |
347 | perror("Getting core dump limit"); | 327 | perror("Getting core dump limit"); |
348 | return; | 328 | return; |
349 | } | 329 | } |
350 | 330 | ||
351 | printf("Core dump limits :\n\tsoft - "); | 331 | printf("Core dump limits :\n\tsoft - "); |
352 | if(lim.rlim_cur == RLIM_INFINITY) | 332 | if (lim.rlim_cur == RLIM_INFINITY) |
353 | printf("NONE\n"); | 333 | printf("NONE\n"); |
354 | else printf("%lu\n", lim.rlim_cur); | 334 | else printf("%lu\n", lim.rlim_cur); |
355 | 335 | ||
356 | printf("\thard - "); | 336 | printf("\thard - "); |
357 | if(lim.rlim_max == RLIM_INFINITY) | 337 | if (lim.rlim_max == RLIM_INFINITY) |
358 | printf("NONE\n"); | 338 | printf("NONE\n"); |
359 | else printf("%lu\n", lim.rlim_max); | 339 | else printf("%lu\n", lim.rlim_max); |
360 | } | 340 | } |
@@ -408,20 +388,18 @@ __uml_setup("noptraceldt", noptraceldt_cmd_param, | |||
408 | " To support PTRACE_LDT, the host needs to be patched using\n" | 388 | " To support PTRACE_LDT, the host needs to be patched using\n" |
409 | " the current skas3 patch.\n\n"); | 389 | " the current skas3 patch.\n\n"); |
410 | 390 | ||
411 | #ifdef UML_CONFIG_MODE_SKAS | ||
412 | static inline void check_skas3_ptrace_faultinfo(void) | 391 | static inline void check_skas3_ptrace_faultinfo(void) |
413 | { | 392 | { |
414 | struct ptrace_faultinfo fi; | 393 | struct ptrace_faultinfo fi; |
415 | void *stack; | ||
416 | int pid, n; | 394 | int pid, n; |
417 | 395 | ||
418 | non_fatal(" - PTRACE_FAULTINFO..."); | 396 | non_fatal(" - PTRACE_FAULTINFO..."); |
419 | pid = start_ptraced_child(&stack); | 397 | pid = start_ptraced_child(); |
420 | 398 | ||
421 | n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); | 399 | n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); |
422 | if (n < 0) { | 400 | if (n < 0) { |
423 | ptrace_faultinfo = 0; | 401 | ptrace_faultinfo = 0; |
424 | if(errno == EIO) | 402 | if (errno == EIO) |
425 | non_fatal("not found\n"); | 403 | non_fatal("not found\n"); |
426 | else | 404 | else |
427 | perror("not found"); | 405 | perror("not found"); |
@@ -434,13 +412,12 @@ static inline void check_skas3_ptrace_faultinfo(void) | |||
434 | } | 412 | } |
435 | 413 | ||
436 | init_registers(pid); | 414 | init_registers(pid); |
437 | stop_ptraced_child(pid, stack, 1, 1); | 415 | stop_ptraced_child(pid, 1, 1); |
438 | } | 416 | } |
439 | 417 | ||
440 | static inline void check_skas3_ptrace_ldt(void) | 418 | static inline void check_skas3_ptrace_ldt(void) |
441 | { | 419 | { |
442 | #ifdef PTRACE_LDT | 420 | #ifdef PTRACE_LDT |
443 | void *stack; | ||
444 | int pid, n; | 421 | int pid, n; |
445 | unsigned char ldtbuf[40]; | 422 | unsigned char ldtbuf[40]; |
446 | struct ptrace_ldt ldt_op = (struct ptrace_ldt) { | 423 | struct ptrace_ldt ldt_op = (struct ptrace_ldt) { |
@@ -449,11 +426,11 @@ static inline void check_skas3_ptrace_ldt(void) | |||
449 | .bytecount = sizeof(ldtbuf)}; | 426 | .bytecount = sizeof(ldtbuf)}; |
450 | 427 | ||
451 | non_fatal(" - PTRACE_LDT..."); | 428 | non_fatal(" - PTRACE_LDT..."); |
452 | pid = start_ptraced_child(&stack); | 429 | pid = start_ptraced_child(); |
453 | 430 | ||
454 | n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op); | 431 | n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op); |
455 | if (n < 0) { | 432 | if (n < 0) { |
456 | if(errno == EIO) | 433 | if (errno == EIO) |
457 | non_fatal("not found\n"); | 434 | non_fatal("not found\n"); |
458 | else { | 435 | else { |
459 | perror("not found"); | 436 | perror("not found"); |
@@ -461,13 +438,13 @@ static inline void check_skas3_ptrace_ldt(void) | |||
461 | ptrace_ldt = 0; | 438 | ptrace_ldt = 0; |
462 | } | 439 | } |
463 | else { | 440 | else { |
464 | if(ptrace_ldt) | 441 | if (ptrace_ldt) |
465 | non_fatal("found\n"); | 442 | non_fatal("found\n"); |
466 | else | 443 | else |
467 | non_fatal("found, but use is disabled\n"); | 444 | non_fatal("found, but use is disabled\n"); |
468 | } | 445 | } |
469 | 446 | ||
470 | stop_ptraced_child(pid, stack, 1, 1); | 447 | stop_ptraced_child(pid, 1, 1); |
471 | #else | 448 | #else |
472 | /* PTRACE_LDT might be disabled via cmdline option. | 449 | /* PTRACE_LDT might be disabled via cmdline option. |
473 | * We want to override this, else we might use the stub | 450 | * We want to override this, else we might use the stub |
@@ -484,12 +461,9 @@ static inline void check_skas3_proc_mm(void) | |||
484 | proc_mm = 0; | 461 | proc_mm = 0; |
485 | perror("not found"); | 462 | perror("not found"); |
486 | } | 463 | } |
487 | else { | 464 | else if (!proc_mm) |
488 | if (!proc_mm) | 465 | non_fatal("found but disabled on command line\n"); |
489 | non_fatal("found but disabled on command line\n"); | 466 | else non_fatal("found\n"); |
490 | else | ||
491 | non_fatal("found\n"); | ||
492 | } | ||
493 | } | 467 | } |
494 | 468 | ||
495 | int can_do_skas(void) | 469 | int can_do_skas(void) |
@@ -500,17 +474,11 @@ int can_do_skas(void) | |||
500 | check_skas3_ptrace_faultinfo(); | 474 | check_skas3_ptrace_faultinfo(); |
501 | check_skas3_ptrace_ldt(); | 475 | check_skas3_ptrace_ldt(); |
502 | 476 | ||
503 | if(!proc_mm || !ptrace_faultinfo || !ptrace_ldt) | 477 | if (!proc_mm || !ptrace_faultinfo || !ptrace_ldt) |
504 | skas_needs_stub = 1; | 478 | skas_needs_stub = 1; |
505 | 479 | ||
506 | return 1; | 480 | return 1; |
507 | } | 481 | } |
508 | #else | ||
509 | int can_do_skas(void) | ||
510 | { | ||
511 | return 0; | ||
512 | } | ||
513 | #endif | ||
514 | 482 | ||
515 | int __init parse_iomem(char *str, int *add) | 483 | int __init parse_iomem(char *str, int *add) |
516 | { | 484 | { |
@@ -521,25 +489,25 @@ int __init parse_iomem(char *str, int *add) | |||
521 | 489 | ||
522 | driver = str; | 490 | driver = str; |
523 | file = strchr(str,','); | 491 | file = strchr(str,','); |
524 | if(file == NULL){ | 492 | if (file == NULL) { |
525 | printf("parse_iomem : failed to parse iomem\n"); | 493 | printf("parse_iomem : failed to parse iomem\n"); |
526 | goto out; | 494 | goto out; |
527 | } | 495 | } |
528 | *file = '\0'; | 496 | *file = '\0'; |
529 | file++; | 497 | file++; |
530 | fd = open(file, O_RDWR, 0); | 498 | fd = open(file, O_RDWR, 0); |
531 | if(fd < 0){ | 499 | if (fd < 0) { |
532 | os_print_error(fd, "parse_iomem - Couldn't open io file"); | 500 | perror("parse_iomem - Couldn't open io file"); |
533 | goto out; | 501 | goto out; |
534 | } | 502 | } |
535 | 503 | ||
536 | if(fstat64(fd, &buf) < 0){ | 504 | if (fstat64(fd, &buf) < 0) { |
537 | perror("parse_iomem - cannot stat_fd file"); | 505 | perror("parse_iomem - cannot stat_fd file"); |
538 | goto out_close; | 506 | goto out_close; |
539 | } | 507 | } |
540 | 508 | ||
541 | new = malloc(sizeof(*new)); | 509 | new = malloc(sizeof(*new)); |
542 | if(new == NULL){ | 510 | if (new == NULL) { |
543 | perror("Couldn't allocate iomem_region struct"); | 511 | perror("Couldn't allocate iomem_region struct"); |
544 | goto out_close; | 512 | goto out_close; |
545 | } | 513 | } |
diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile index 37806621b25d..a841262c594a 100644 --- a/arch/um/os-Linux/sys-i386/Makefile +++ b/arch/um/os-Linux/sys-i386/Makefile | |||
@@ -1,9 +1,9 @@ | |||
1 | # | 1 | # |
2 | # Copyright (C) 2000 Jeff Dike (jdike@karaya.com) | 2 | # Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | # Licensed under the GPL | 3 | # Licensed under the GPL |
4 | # | 4 | # |
5 | 5 | ||
6 | obj-$(CONFIG_MODE_SKAS) = registers.o signal.o tls.o | 6 | obj-y = registers.o signal.o tls.o |
7 | 7 | ||
8 | USER_OBJS := $(obj-y) | 8 | USER_OBJS := $(obj-y) |
9 | 9 | ||
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c index 84b44f9cd42a..d1997ca76e5c 100644 --- a/arch/um/os-Linux/sys-i386/registers.c +++ b/arch/um/os-Linux/sys-i386/registers.c | |||
@@ -1,144 +1,73 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2004 PathScale, Inc | 2 | * Copyright (C) 2004 PathScale, Inc |
3 | * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
3 | * Licensed under the GPL | 4 | * Licensed under the GPL |
4 | */ | 5 | */ |
5 | 6 | ||
6 | #include <errno.h> | 7 | #include <errno.h> |
7 | #include <string.h> | 8 | #include "kern_constants.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 "longjmp.h" | 9 | #include "longjmp.h" |
14 | #include "user.h" | 10 | #include "user.h" |
11 | #include "sysdep/ptrace_user.h" | ||
15 | 12 | ||
16 | /* These are set once at boot time and not changed thereafter */ | ||
17 | |||
18 | static unsigned long exec_regs[MAX_REG_NR]; | ||
19 | static unsigned long exec_fp_regs[HOST_FP_SIZE]; | ||
20 | static unsigned long exec_fpx_regs[HOST_XFP_SIZE]; | ||
21 | static int have_fpx_regs = 1; | ||
22 | |||
23 | void init_thread_registers(union uml_pt_regs *to) | ||
24 | { | ||
25 | memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs)); | ||
26 | memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp)); | ||
27 | if(have_fpx_regs) | ||
28 | memcpy(to->skas.xfp, exec_fpx_regs, sizeof(to->skas.xfp)); | ||
29 | } | ||
30 | |||
31 | /* XXX These need to use [GS]ETFPXREGS and copy_sc_{to,from}_user_skas needs | ||
32 | * to pass in a sufficiently large buffer | ||
33 | */ | ||
34 | int save_fp_registers(int pid, unsigned long *fp_regs) | 13 | int save_fp_registers(int pid, unsigned long *fp_regs) |
35 | { | 14 | { |
36 | if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) | 15 | if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) |
37 | return -errno; | 16 | return -errno; |
38 | return 0; | 17 | return 0; |
39 | } | 18 | } |
40 | 19 | ||
41 | int restore_fp_registers(int pid, unsigned long *fp_regs) | 20 | int restore_fp_registers(int pid, unsigned long *fp_regs) |
42 | { | 21 | { |
43 | if(ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) | 22 | if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) |
44 | return -errno; | 23 | return -errno; |
45 | return 0; | 24 | return 0; |
46 | } | 25 | } |
47 | 26 | ||
48 | static int move_registers(int pid, int int_op, union uml_pt_regs *regs, | 27 | int save_fpx_registers(int pid, unsigned long *fp_regs) |
49 | int fp_op, unsigned long *fp_regs) | ||
50 | { | 28 | { |
51 | if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) | 29 | if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0) |
52 | return -errno; | ||
53 | |||
54 | if(ptrace(fp_op, pid, 0, fp_regs) < 0) | ||
55 | return -errno; | 30 | return -errno; |
56 | |||
57 | return 0; | 31 | return 0; |
58 | } | 32 | } |
59 | 33 | ||
60 | void save_registers(int pid, union uml_pt_regs *regs) | 34 | int restore_fpx_registers(int pid, unsigned long *fp_regs) |
61 | { | 35 | { |
62 | unsigned long *fp_regs; | 36 | if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0) |
63 | int err, fp_op; | 37 | return -errno; |
64 | 38 | return 0; | |
65 | if(have_fpx_regs){ | ||
66 | fp_op = PTRACE_GETFPXREGS; | ||
67 | fp_regs = regs->skas.xfp; | ||
68 | } | ||
69 | else { | ||
70 | fp_op = PTRACE_GETFPREGS; | ||
71 | fp_regs = regs->skas.fp; | ||
72 | } | ||
73 | |||
74 | err = move_registers(pid, PTRACE_GETREGS, regs, fp_op, fp_regs); | ||
75 | if(err) | ||
76 | panic("save_registers - saving registers failed, errno = %d\n", | ||
77 | -err); | ||
78 | } | 39 | } |
79 | 40 | ||
80 | void restore_registers(int pid, union uml_pt_regs *regs) | 41 | unsigned long get_thread_reg(int reg, jmp_buf *buf) |
81 | { | 42 | { |
82 | unsigned long *fp_regs; | 43 | switch (reg) { |
83 | int err, fp_op; | 44 | case EIP: |
84 | 45 | return buf[0]->__eip; | |
85 | if(have_fpx_regs){ | 46 | case UESP: |
86 | fp_op = PTRACE_SETFPXREGS; | 47 | return buf[0]->__esp; |
87 | fp_regs = regs->skas.xfp; | 48 | case EBP: |
88 | } | 49 | return buf[0]->__ebp; |
89 | else { | 50 | default: |
90 | fp_op = PTRACE_SETFPREGS; | 51 | printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n", |
91 | fp_regs = regs->skas.fp; | 52 | reg); |
53 | return 0; | ||
92 | } | 54 | } |
93 | |||
94 | err = move_registers(pid, PTRACE_SETREGS, regs, fp_op, fp_regs); | ||
95 | if(err) | ||
96 | panic("restore_registers - saving registers failed, " | ||
97 | "errno = %d\n", -err); | ||
98 | } | 55 | } |
99 | 56 | ||
100 | void init_registers(int pid) | 57 | int have_fpx_regs = 1; |
58 | |||
59 | void arch_init_registers(int pid) | ||
101 | { | 60 | { |
61 | unsigned long fpx_regs[HOST_XFP_SIZE]; | ||
102 | int err; | 62 | int err; |
103 | 63 | ||
104 | memset(exec_regs, 0, sizeof(exec_regs)); | 64 | err = ptrace(PTRACE_GETFPXREGS, pid, 0, fpx_regs); |
105 | err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); | ||
106 | if(err) | ||
107 | panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", | ||
108 | errno); | ||
109 | |||
110 | errno = 0; | ||
111 | err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs); | ||
112 | if(!err) | 65 | if(!err) |
113 | return; | 66 | return; |
67 | |||
114 | if(errno != EIO) | 68 | if(errno != EIO) |
115 | panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", | 69 | panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", |
116 | errno); | 70 | errno); |
117 | 71 | ||
118 | have_fpx_regs = 0; | 72 | have_fpx_regs = 0; |
119 | |||
120 | err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs); | ||
121 | if(err) | ||
122 | panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", | ||
123 | errno); | ||
124 | } | ||
125 | |||
126 | void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) | ||
127 | { | ||
128 | memcpy(regs, exec_regs, sizeof(exec_regs)); | ||
129 | if(fp_regs != NULL) | ||
130 | memcpy(fp_regs, exec_fp_regs, | ||
131 | HOST_FP_SIZE * sizeof(unsigned long)); | ||
132 | } | ||
133 | |||
134 | unsigned long get_thread_reg(int reg, jmp_buf *buf) | ||
135 | { | ||
136 | switch(reg){ | ||
137 | case EIP: return buf[0]->__eip; | ||
138 | case UESP: return buf[0]->__esp; | ||
139 | case EBP: return buf[0]->__ebp; | ||
140 | default: | ||
141 | printk("get_thread_regs - unknown register %d\n", reg); | ||
142 | return 0; | ||
143 | } | ||
144 | } | 73 | } |
diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile index 7955e061a678..a42a4ef02e1e 100644 --- a/arch/um/os-Linux/sys-x86_64/Makefile +++ b/arch/um/os-Linux/sys-x86_64/Makefile | |||
@@ -1,9 +1,9 @@ | |||
1 | # | 1 | # |
2 | # Copyright (C) 2000 Jeff Dike (jdike@karaya.com) | 2 | # Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | # Licensed under the GPL | 3 | # Licensed under the GPL |
4 | # | 4 | # |
5 | 5 | ||
6 | obj-$(CONFIG_MODE_SKAS) = registers.o prctl.o signal.o | 6 | obj-y = registers.o prctl.o signal.o |
7 | 7 | ||
8 | USER_OBJS := $(obj-y) | 8 | USER_OBJS := $(obj-y) |
9 | 9 | ||
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c index 9467315b8059..9bfa789992de 100644 --- a/arch/um/os-Linux/sys-x86_64/registers.c +++ b/arch/um/os-Linux/sys-x86_64/registers.c | |||
@@ -1,23 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2004 PathScale, Inc | 2 | * Copyright (C) 2006-2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <errno.h> | 6 | #include <errno.h> |
7 | #include <sys/ptrace.h> | 7 | #include <sys/ptrace.h> |
8 | #include <string.h> | 8 | #define __FRAME_OFFSETS |
9 | #include "ptrace_user.h" | 9 | #include <asm/ptrace.h> |
10 | #include "uml-config.h" | ||
11 | #include "skas_ptregs.h" | ||
12 | #include "registers.h" | ||
13 | #include "longjmp.h" | 10 | #include "longjmp.h" |
14 | #include "user.h" | 11 | #include "user.h" |
15 | 12 | ||
16 | /* These are set once at boot time and not changed thereafter */ | ||
17 | |||
18 | static unsigned long exec_regs[MAX_REG_NR]; | ||
19 | static unsigned long exec_fp_regs[HOST_FP_SIZE]; | ||
20 | |||
21 | int save_fp_registers(int pid, unsigned long *fp_regs) | 13 | int save_fp_registers(int pid, unsigned long *fp_regs) |
22 | { | 14 | { |
23 | if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) | 15 | if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) |
@@ -32,67 +24,6 @@ int restore_fp_registers(int pid, unsigned long *fp_regs) | |||
32 | return 0; | 24 | return 0; |
33 | } | 25 | } |
34 | 26 | ||
35 | void init_thread_registers(union uml_pt_regs *to) | ||
36 | { | ||
37 | memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs)); | ||
38 | memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp)); | ||
39 | } | ||
40 | |||
41 | static int move_registers(int pid, int int_op, int fp_op, | ||
42 | union uml_pt_regs *regs) | ||
43 | { | ||
44 | if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) | ||
45 | return -errno; | ||
46 | |||
47 | if(ptrace(fp_op, pid, 0, regs->skas.fp) < 0) | ||
48 | return -errno; | ||
49 | |||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | void save_registers(int pid, union uml_pt_regs *regs) | ||
54 | { | ||
55 | int err; | ||
56 | |||
57 | err = move_registers(pid, PTRACE_GETREGS, PTRACE_GETFPREGS, regs); | ||
58 | if(err) | ||
59 | panic("save_registers - saving registers failed, errno = %d\n", | ||
60 | -err); | ||
61 | } | ||
62 | |||
63 | void restore_registers(int pid, union uml_pt_regs *regs) | ||
64 | { | ||
65 | int err; | ||
66 | |||
67 | err = move_registers(pid, PTRACE_SETREGS, PTRACE_SETFPREGS, regs); | ||
68 | if(err) | ||
69 | panic("restore_registers - saving registers failed, " | ||
70 | "errno = %d\n", -err); | ||
71 | } | ||
72 | |||
73 | void init_registers(int pid) | ||
74 | { | ||
75 | int err; | ||
76 | |||
77 | err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); | ||
78 | if(err) | ||
79 | panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", | ||
80 | errno); | ||
81 | |||
82 | err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs); | ||
83 | if(err) | ||
84 | panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", | ||
85 | errno); | ||
86 | } | ||
87 | |||
88 | void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) | ||
89 | { | ||
90 | memcpy(regs, exec_regs, sizeof(exec_regs)); | ||
91 | if(fp_regs != NULL) | ||
92 | memcpy(fp_regs, exec_fp_regs, | ||
93 | HOST_FP_SIZE * sizeof(unsigned long)); | ||
94 | } | ||
95 | |||
96 | unsigned long get_thread_reg(int reg, jmp_buf *buf) | 27 | unsigned long get_thread_reg(int reg, jmp_buf *buf) |
97 | { | 28 | { |
98 | switch(reg){ | 29 | switch(reg){ |
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index 5de169b168f6..e34e1effe0f5 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c | |||
@@ -1,101 +1,86 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdio.h> | 6 | #include <stddef.h> |
7 | #include <stdlib.h> | 7 | #include <errno.h> |
8 | #include <unistd.h> | 8 | #include <signal.h> |
9 | #include <time.h> | 9 | #include <time.h> |
10 | #include <sys/time.h> | 10 | #include <sys/time.h> |
11 | #include <signal.h> | ||
12 | #include <errno.h> | ||
13 | #include "kern_util.h" | ||
14 | #include "user.h" | ||
15 | #include "process.h" | ||
16 | #include "kern_constants.h" | 11 | #include "kern_constants.h" |
17 | #include "os.h" | 12 | #include "os.h" |
18 | #include "uml-config.h" | 13 | #include "user.h" |
19 | 14 | ||
20 | int set_interval(int is_virtual) | 15 | int set_interval(void) |
21 | { | 16 | { |
22 | int usec = 1000000/hz(); | 17 | int usec = UM_USEC_PER_SEC / UM_HZ; |
23 | int timer_type = is_virtual ? ITIMER_VIRTUAL : ITIMER_REAL; | ||
24 | struct itimerval interval = ((struct itimerval) { { 0, usec }, | 18 | struct itimerval interval = ((struct itimerval) { { 0, usec }, |
25 | { 0, usec } }); | 19 | { 0, usec } }); |
26 | 20 | ||
27 | if(setitimer(timer_type, &interval, NULL) == -1) | 21 | if (setitimer(ITIMER_VIRTUAL, &interval, NULL) == -1) |
28 | return -errno; | 22 | return -errno; |
29 | 23 | ||
30 | return 0; | 24 | return 0; |
31 | } | 25 | } |
32 | 26 | ||
33 | #ifdef UML_CONFIG_MODE_TT | 27 | int timer_one_shot(int ticks) |
34 | void enable_timer(void) | ||
35 | { | 28 | { |
36 | set_interval(1); | 29 | unsigned long usec = ticks * UM_USEC_PER_SEC / UM_HZ; |
37 | } | 30 | unsigned long sec = usec / UM_USEC_PER_SEC; |
38 | #endif | 31 | struct itimerval interval; |
39 | 32 | ||
40 | void disable_timer(void) | 33 | usec %= UM_USEC_PER_SEC; |
41 | { | 34 | interval = ((struct itimerval) { { 0, 0 }, { sec, usec } }); |
42 | struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); | 35 | |
43 | if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) || | 36 | if (setitimer(ITIMER_VIRTUAL, &interval, NULL) == -1) |
44 | (setitimer(ITIMER_REAL, &disable, NULL) < 0)) | 37 | return -errno; |
45 | printk("disnable_timer - setitimer failed, errno = %d\n", | 38 | |
46 | errno); | 39 | return 0; |
47 | /* If there are signals already queued, after unblocking ignore them */ | ||
48 | signal(SIGALRM, SIG_IGN); | ||
49 | signal(SIGVTALRM, SIG_IGN); | ||
50 | } | 40 | } |
51 | 41 | ||
52 | void switch_timers(int to_real) | 42 | /** |
43 | * timeval_to_ns - Convert timeval to nanoseconds | ||
44 | * @ts: pointer to the timeval variable to be converted | ||
45 | * | ||
46 | * Returns the scalar nanosecond representation of the timeval | ||
47 | * parameter. | ||
48 | * | ||
49 | * Ripped from linux/time.h because it's a kernel header, and thus | ||
50 | * unusable from here. | ||
51 | */ | ||
52 | static inline long long timeval_to_ns(const struct timeval *tv) | ||
53 | { | 53 | { |
54 | struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); | 54 | return ((long long) tv->tv_sec * UM_NSEC_PER_SEC) + |
55 | struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() }, | 55 | tv->tv_usec * UM_NSEC_PER_USEC; |
56 | { 0, 1000000/hz() }}); | ||
57 | int old, new; | ||
58 | |||
59 | if(to_real){ | ||
60 | old = ITIMER_VIRTUAL; | ||
61 | new = ITIMER_REAL; | ||
62 | } | ||
63 | else { | ||
64 | old = ITIMER_REAL; | ||
65 | new = ITIMER_VIRTUAL; | ||
66 | } | ||
67 | |||
68 | if((setitimer(old, &disable, NULL) < 0) || | ||
69 | (setitimer(new, &enable, NULL))) | ||
70 | printk("switch_timers - setitimer failed, errno = %d\n", | ||
71 | errno); | ||
72 | } | 56 | } |
73 | 57 | ||
74 | #ifdef UML_CONFIG_MODE_TT | 58 | long long disable_timer(void) |
75 | void uml_idle_timer(void) | ||
76 | { | 59 | { |
77 | if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR) | 60 | struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } }); |
78 | panic("Couldn't unset SIGVTALRM handler"); | 61 | |
62 | if(setitimer(ITIMER_VIRTUAL, &time, &time) < 0) | ||
63 | printk(UM_KERN_ERR "disable_timer - setitimer failed, " | ||
64 | "errno = %d\n", errno); | ||
79 | 65 | ||
80 | set_handler(SIGALRM, (__sighandler_t) alarm_handler, | 66 | return timeval_to_ns(&time.it_value); |
81 | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); | ||
82 | set_interval(0); | ||
83 | } | 67 | } |
84 | #endif | ||
85 | 68 | ||
86 | unsigned long long os_nsecs(void) | 69 | long long os_nsecs(void) |
87 | { | 70 | { |
88 | struct timeval tv; | 71 | struct timeval tv; |
89 | 72 | ||
90 | gettimeofday(&tv, NULL); | 73 | gettimeofday(&tv, NULL); |
91 | return((unsigned long long) tv.tv_sec * BILLION + tv.tv_usec * 1000); | 74 | return timeval_to_ns(&tv); |
92 | } | 75 | } |
93 | 76 | ||
94 | void idle_sleep(int secs) | 77 | extern void alarm_handler(int sig, struct sigcontext *sc); |
78 | |||
79 | void idle_sleep(unsigned long long nsecs) | ||
95 | { | 80 | { |
96 | struct timespec ts; | 81 | struct timespec ts = { .tv_sec = nsecs / UM_NSEC_PER_SEC, |
82 | .tv_nsec = nsecs % UM_NSEC_PER_SEC }; | ||
97 | 83 | ||
98 | ts.tv_sec = secs; | 84 | if (nanosleep(&ts, &ts) == 0) |
99 | ts.tv_nsec = 0; | 85 | alarm_handler(SIGVTALRM, NULL); |
100 | nanosleep(&ts, NULL); | ||
101 | } | 86 | } |
diff --git a/arch/um/os-Linux/tls.c b/arch/um/os-Linux/tls.c index 16215b990804..73277801ef14 100644 --- a/arch/um/os-Linux/tls.c +++ b/arch/um/os-Linux/tls.c | |||
@@ -1,18 +1,9 @@ | |||
1 | #include <errno.h> | 1 | #include <errno.h> |
2 | #include <unistd.h> | ||
3 | #include <sys/ptrace.h> | 2 | #include <sys/ptrace.h> |
4 | #include <sys/syscall.h> | ||
5 | #include <asm/ldt.h> | ||
6 | #include "sysdep/tls.h" | 3 | #include "sysdep/tls.h" |
7 | #include "uml-config.h" | ||
8 | 4 | ||
9 | /* TLS support - we basically rely on the host's one.*/ | 5 | /* TLS support - we basically rely on the host's one.*/ |
10 | 6 | ||
11 | /* In TT mode, this should be called only by the tracing thread, and makes sense | ||
12 | * only for PTRACE_SET_THREAD_AREA. In SKAS mode, it's used normally. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #ifndef PTRACE_GET_THREAD_AREA | 7 | #ifndef PTRACE_GET_THREAD_AREA |
17 | #define PTRACE_GET_THREAD_AREA 25 | 8 | #define PTRACE_GET_THREAD_AREA 25 |
18 | #endif | 9 | #endif |
@@ -32,8 +23,6 @@ int os_set_thread_area(user_desc_t *info, int pid) | |||
32 | return ret; | 23 | return ret; |
33 | } | 24 | } |
34 | 25 | ||
35 | #ifdef UML_CONFIG_MODE_SKAS | ||
36 | |||
37 | int os_get_thread_area(user_desc_t *info, int pid) | 26 | int os_get_thread_area(user_desc_t *info, int pid) |
38 | { | 27 | { |
39 | int ret; | 28 | int ret; |
@@ -44,32 +33,3 @@ int os_get_thread_area(user_desc_t *info, int pid) | |||
44 | ret = -errno; | 33 | ret = -errno; |
45 | return ret; | 34 | return ret; |
46 | } | 35 | } |
47 | |||
48 | #endif | ||
49 | |||
50 | #ifdef UML_CONFIG_MODE_TT | ||
51 | #include "linux/unistd.h" | ||
52 | |||
53 | int do_set_thread_area_tt(user_desc_t *info) | ||
54 | { | ||
55 | int ret; | ||
56 | |||
57 | ret = syscall(__NR_set_thread_area,info); | ||
58 | if (ret < 0) { | ||
59 | ret = -errno; | ||
60 | } | ||
61 | return ret; | ||
62 | } | ||
63 | |||
64 | int do_get_thread_area_tt(user_desc_t *info) | ||
65 | { | ||
66 | int ret; | ||
67 | |||
68 | ret = syscall(__NR_get_thread_area,info); | ||
69 | if (ret < 0) { | ||
70 | ret = -errno; | ||
71 | } | ||
72 | return ret; | ||
73 | } | ||
74 | |||
75 | #endif /* UML_CONFIG_MODE_TT */ | ||
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c index 295da657931a..2a1c9843e32e 100644 --- a/arch/um/os-Linux/trap.c +++ b/arch/um/os-Linux/trap.c | |||
@@ -1,22 +1,14 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdlib.h> | ||
7 | #include <signal.h> | 6 | #include <signal.h> |
8 | #include "kern_util.h" | ||
9 | #include "os.h" | 7 | #include "os.h" |
10 | #include "mode.h" | 8 | #include "sysdep/ptrace.h" |
11 | #include "longjmp.h" | ||
12 | |||
13 | void usr2_handler(int sig, union uml_pt_regs *regs) | ||
14 | { | ||
15 | CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0); | ||
16 | } | ||
17 | 9 | ||
18 | /* Initialized from linux_main() */ | 10 | /* Initialized from linux_main() */ |
19 | void (*sig_info[NSIG])(int, union uml_pt_regs *); | 11 | void (*sig_info[NSIG])(int, struct uml_pt_regs *); |
20 | 12 | ||
21 | void os_fill_handlinfo(struct kern_handlers h) | 13 | void os_fill_handlinfo(struct kern_handlers h) |
22 | { | 14 | { |
@@ -28,13 +20,4 @@ void os_fill_handlinfo(struct kern_handlers h) | |||
28 | sig_info[SIGSEGV] = h.page_fault; | 20 | sig_info[SIGSEGV] = h.page_fault; |
29 | sig_info[SIGIO] = h.sigio_handler; | 21 | sig_info[SIGIO] = h.sigio_handler; |
30 | sig_info[SIGVTALRM] = h.timer_handler; | 22 | sig_info[SIGVTALRM] = h.timer_handler; |
31 | sig_info[SIGALRM] = h.timer_handler; | ||
32 | sig_info[SIGUSR2] = usr2_handler; | ||
33 | } | ||
34 | |||
35 | void do_longjmp(void *b, int val) | ||
36 | { | ||
37 | jmp_buf *buf = b; | ||
38 | |||
39 | UML_LONGJMP(buf, val); | ||
40 | } | 23 | } |
diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c deleted file mode 100644 index bcf9359c4e9f..000000000000 --- a/arch/um/os-Linux/tt.c +++ /dev/null | |||
@@ -1,196 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stdio.h> | ||
7 | #include <unistd.h> | ||
8 | #include <signal.h> | ||
9 | #include <sched.h> | ||
10 | #include <errno.h> | ||
11 | #include <stdarg.h> | ||
12 | #include <stdlib.h> | ||
13 | #include <sys/time.h> | ||
14 | #include <sys/ptrace.h> | ||
15 | #include <linux/ptrace.h> | ||
16 | #include <sys/wait.h> | ||
17 | #include <sys/mman.h> | ||
18 | #include <asm/ptrace.h> | ||
19 | #include <asm/unistd.h> | ||
20 | #include <asm/page.h> | ||
21 | #include "kern_util.h" | ||
22 | #include "user.h" | ||
23 | #include "signal_kern.h" | ||
24 | #include "sysdep/ptrace.h" | ||
25 | #include "sysdep/sigcontext.h" | ||
26 | #include "irq_user.h" | ||
27 | #include "ptrace_user.h" | ||
28 | #include "init.h" | ||
29 | #include "os.h" | ||
30 | #include "uml-config.h" | ||
31 | #include "choose-mode.h" | ||
32 | #include "mode.h" | ||
33 | #include "tempfile.h" | ||
34 | #include "kern_constants.h" | ||
35 | |||
36 | int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, | ||
37 | int must_succeed) | ||
38 | { | ||
39 | int err; | ||
40 | |||
41 | err = os_protect_memory((void *) addr, len, r, w, x); | ||
42 | if(err < 0){ | ||
43 | if(must_succeed) | ||
44 | panic("protect failed, err = %d", -err); | ||
45 | else return(err); | ||
46 | } | ||
47 | return(0); | ||
48 | } | ||
49 | |||
50 | void kill_child_dead(int pid) | ||
51 | { | ||
52 | kill(pid, SIGKILL); | ||
53 | kill(pid, SIGCONT); | ||
54 | do { | ||
55 | int n; | ||
56 | CATCH_EINTR(n = waitpid(pid, NULL, 0)); | ||
57 | if (n > 0) | ||
58 | kill(pid, SIGCONT); | ||
59 | else | ||
60 | break; | ||
61 | } while(1); | ||
62 | } | ||
63 | |||
64 | void stop(void) | ||
65 | { | ||
66 | while(1) sleep(1000000); | ||
67 | } | ||
68 | |||
69 | int wait_for_stop(int pid, int sig, int cont_type, void *relay) | ||
70 | { | ||
71 | sigset_t *relay_signals = relay; | ||
72 | int status, ret; | ||
73 | |||
74 | while(1){ | ||
75 | CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED)); | ||
76 | if((ret < 0) || | ||
77 | !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){ | ||
78 | if(ret < 0){ | ||
79 | printk("wait failed, errno = %d\n", | ||
80 | errno); | ||
81 | } | ||
82 | else if(WIFEXITED(status)) | ||
83 | printk("process %d exited with status %d\n", | ||
84 | pid, WEXITSTATUS(status)); | ||
85 | else if(WIFSIGNALED(status)) | ||
86 | printk("process %d exited with signal %d\n", | ||
87 | pid, WTERMSIG(status)); | ||
88 | else if((WSTOPSIG(status) == SIGVTALRM) || | ||
89 | (WSTOPSIG(status) == SIGALRM) || | ||
90 | (WSTOPSIG(status) == SIGIO) || | ||
91 | (WSTOPSIG(status) == SIGPROF) || | ||
92 | (WSTOPSIG(status) == SIGCHLD) || | ||
93 | (WSTOPSIG(status) == SIGWINCH) || | ||
94 | (WSTOPSIG(status) == SIGINT)){ | ||
95 | ptrace(cont_type, pid, 0, WSTOPSIG(status)); | ||
96 | continue; | ||
97 | } | ||
98 | else if((relay_signals != NULL) && | ||
99 | sigismember(relay_signals, WSTOPSIG(status))){ | ||
100 | ptrace(cont_type, pid, 0, WSTOPSIG(status)); | ||
101 | continue; | ||
102 | } | ||
103 | else printk("process %d stopped with signal %d\n", | ||
104 | pid, WSTOPSIG(status)); | ||
105 | panic("wait_for_stop failed to wait for %d to stop " | ||
106 | "with %d\n", pid, sig); | ||
107 | } | ||
108 | return(status); | ||
109 | } | ||
110 | } | ||
111 | |||
112 | void forward_ipi(int fd, int pid) | ||
113 | { | ||
114 | int err; | ||
115 | |||
116 | err = os_set_owner(fd, pid); | ||
117 | if(err < 0) | ||
118 | printk("forward_ipi: set_owner failed, fd = %d, me = %d, " | ||
119 | "target = %d, err = %d\n", fd, os_getpid(), pid, -err); | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | *------------------------- | ||
124 | * only for tt mode (will be deleted in future...) | ||
125 | *------------------------- | ||
126 | */ | ||
127 | |||
128 | struct tramp { | ||
129 | int (*tramp)(void *); | ||
130 | void *tramp_data; | ||
131 | unsigned long temp_stack; | ||
132 | int flags; | ||
133 | int pid; | ||
134 | }; | ||
135 | |||
136 | /* See above for why sigkill is here */ | ||
137 | |||
138 | int sigkill = SIGKILL; | ||
139 | |||
140 | int outer_tramp(void *arg) | ||
141 | { | ||
142 | struct tramp *t; | ||
143 | int sig = sigkill; | ||
144 | |||
145 | t = arg; | ||
146 | t->pid = clone(t->tramp, (void *) t->temp_stack + UM_KERN_PAGE_SIZE/2, | ||
147 | t->flags, t->tramp_data); | ||
148 | if(t->pid > 0) wait_for_stop(t->pid, SIGSTOP, PTRACE_CONT, NULL); | ||
149 | kill(os_getpid(), sig); | ||
150 | _exit(0); | ||
151 | } | ||
152 | |||
153 | int start_fork_tramp(void *thread_arg, unsigned long temp_stack, | ||
154 | int clone_flags, int (*tramp)(void *)) | ||
155 | { | ||
156 | struct tramp arg; | ||
157 | unsigned long sp; | ||
158 | int new_pid, status, err; | ||
159 | |||
160 | /* The trampoline will run on the temporary stack */ | ||
161 | sp = stack_sp(temp_stack); | ||
162 | |||
163 | clone_flags |= CLONE_FILES | SIGCHLD; | ||
164 | |||
165 | arg.tramp = tramp; | ||
166 | arg.tramp_data = thread_arg; | ||
167 | arg.temp_stack = temp_stack; | ||
168 | arg.flags = clone_flags; | ||
169 | |||
170 | /* Start the process and wait for it to kill itself */ | ||
171 | new_pid = clone(outer_tramp, (void *) sp, clone_flags, &arg); | ||
172 | if(new_pid < 0) | ||
173 | return(new_pid); | ||
174 | |||
175 | CATCH_EINTR(err = waitpid(new_pid, &status, 0)); | ||
176 | if(err < 0) | ||
177 | panic("Waiting for outer trampoline failed - errno = %d", | ||
178 | errno); | ||
179 | |||
180 | if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL)) | ||
181 | panic("outer trampoline didn't exit with SIGKILL, " | ||
182 | "status = %d", status); | ||
183 | |||
184 | return(arg.pid); | ||
185 | } | ||
186 | |||
187 | void forward_pending_sigio(int target) | ||
188 | { | ||
189 | sigset_t sigs; | ||
190 | |||
191 | if(sigpending(&sigs)) | ||
192 | panic("forward_pending_sigio : sigpending failed"); | ||
193 | if(sigismember(&sigs, SIGIO)) | ||
194 | kill(target, SIGIO); | ||
195 | } | ||
196 | |||
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c index bbb73a650370..8d27b6d1df91 100644 --- a/arch/um/os-Linux/uaccess.c +++ b/arch/um/os-Linux/uaccess.c | |||
@@ -8,7 +8,7 @@ | |||
8 | #include "longjmp.h" | 8 | #include "longjmp.h" |
9 | 9 | ||
10 | unsigned long __do_user_copy(void *to, const void *from, int n, | 10 | unsigned long __do_user_copy(void *to, const void *from, int n, |
11 | void **fault_addr, void **fault_catcher, | 11 | void **fault_addr, jmp_buf **fault_catcher, |
12 | void (*op)(void *to, const void *from, | 12 | void (*op)(void *to, const void *from, |
13 | int n), int *faulted_out) | 13 | int n), int *faulted_out) |
14 | { | 14 | { |
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c index b462863f7172..106fa8641553 100644 --- a/arch/um/os-Linux/umid.c +++ b/arch/um/os-Linux/umid.c | |||
@@ -1,17 +1,21 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
1 | #include <stdio.h> | 6 | #include <stdio.h> |
2 | #include <unistd.h> | ||
3 | #include <stdlib.h> | 7 | #include <stdlib.h> |
4 | #include <string.h> | 8 | #include <dirent.h> |
5 | #include <errno.h> | 9 | #include <errno.h> |
10 | #include <fcntl.h> | ||
6 | #include <signal.h> | 11 | #include <signal.h> |
7 | #include <dirent.h> | 12 | #include <string.h> |
8 | #include <sys/fcntl.h> | 13 | #include <unistd.h> |
9 | #include <sys/stat.h> | 14 | #include <sys/stat.h> |
10 | #include <sys/param.h> | ||
11 | #include "init.h" | 15 | #include "init.h" |
16 | #include "kern_constants.h" | ||
12 | #include "os.h" | 17 | #include "os.h" |
13 | #include "user.h" | 18 | #include "user.h" |
14 | #include "mode.h" | ||
15 | 19 | ||
16 | #define UML_DIR "~/.uml/" | 20 | #define UML_DIR "~/.uml/" |
17 | 21 | ||
@@ -28,13 +32,13 @@ static int __init make_uml_dir(void) | |||
28 | char dir[512] = { '\0' }; | 32 | char dir[512] = { '\0' }; |
29 | int len, err; | 33 | int len, err; |
30 | 34 | ||
31 | if(*uml_dir == '~'){ | 35 | if (*uml_dir == '~') { |
32 | char *home = getenv("HOME"); | 36 | char *home = getenv("HOME"); |
33 | 37 | ||
34 | err = -ENOENT; | 38 | err = -ENOENT; |
35 | if(home == NULL){ | 39 | if (home == NULL) { |
36 | printk("make_uml_dir : no value in environment for " | 40 | printk(UM_KERN_ERR "make_uml_dir : no value in " |
37 | "$HOME\n"); | 41 | "environment for $HOME\n"); |
38 | goto err; | 42 | goto err; |
39 | } | 43 | } |
40 | strlcpy(dir, home, sizeof(dir)); | 44 | strlcpy(dir, home, sizeof(dir)); |
@@ -53,7 +57,7 @@ static int __init make_uml_dir(void) | |||
53 | } | 57 | } |
54 | strcpy(uml_dir, dir); | 58 | strcpy(uml_dir, dir); |
55 | 59 | ||
56 | if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){ | 60 | if ((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)) { |
57 | printf("Failed to mkdir '%s': %s\n", uml_dir, strerror(errno)); | 61 | printf("Failed to mkdir '%s': %s\n", uml_dir, strerror(errno)); |
58 | err = -errno; | 62 | err = -errno; |
59 | goto err_free; | 63 | goto err_free; |
@@ -70,8 +74,8 @@ err: | |||
70 | /* | 74 | /* |
71 | * Unlinks the files contained in @dir and then removes @dir. | 75 | * Unlinks the files contained in @dir and then removes @dir. |
72 | * Doesn't handle directory trees, so it's not like rm -rf, but almost such. We | 76 | * Doesn't handle directory trees, so it's not like rm -rf, but almost such. We |
73 | * ignore ENOENT errors for anything (they happen, strangely enough - possibly due | 77 | * ignore ENOENT errors for anything (they happen, strangely enough - possibly |
74 | * to races between multiple dying UML threads). | 78 | * due to races between multiple dying UML threads). |
75 | */ | 79 | */ |
76 | static int remove_files_and_dir(char *dir) | 80 | static int remove_files_and_dir(char *dir) |
77 | { | 81 | { |
@@ -116,7 +120,8 @@ out: | |||
116 | return ret; | 120 | return ret; |
117 | } | 121 | } |
118 | 122 | ||
119 | /* This says that there isn't already a user of the specified directory even if | 123 | /* |
124 | * This says that there isn't already a user of the specified directory even if | ||
120 | * there are errors during the checking. This is because if these errors | 125 | * there are errors during the checking. This is because if these errors |
121 | * happen, the directory is unusable by the pre-existing UML, so we might as | 126 | * happen, the directory is unusable by the pre-existing UML, so we might as |
122 | * well take it over. This could happen either by | 127 | * well take it over. This could happen either by |
@@ -134,44 +139,45 @@ static inline int is_umdir_used(char *dir) | |||
134 | int dead, fd, p, n, err; | 139 | int dead, fd, p, n, err; |
135 | 140 | ||
136 | n = snprintf(file, sizeof(file), "%s/pid", dir); | 141 | n = snprintf(file, sizeof(file), "%s/pid", dir); |
137 | if(n >= sizeof(file)){ | 142 | if (n >= sizeof(file)) { |
138 | printk("is_umdir_used - pid filename too long\n"); | 143 | printk(UM_KERN_ERR "is_umdir_used - pid filename too long\n"); |
139 | err = -E2BIG; | 144 | err = -E2BIG; |
140 | goto out; | 145 | goto out; |
141 | } | 146 | } |
142 | 147 | ||
143 | dead = 0; | 148 | dead = 0; |
144 | fd = open(file, O_RDONLY); | 149 | fd = open(file, O_RDONLY); |
145 | if(fd < 0) { | 150 | if (fd < 0) { |
146 | fd = -errno; | 151 | fd = -errno; |
147 | if(fd != -ENOENT){ | 152 | if (fd != -ENOENT) { |
148 | printk("is_umdir_used : couldn't open pid file '%s', " | 153 | printk(UM_KERN_ERR "is_umdir_used : couldn't open pid " |
149 | "err = %d\n", file, -fd); | 154 | "file '%s', err = %d\n", file, -fd); |
150 | } | 155 | } |
151 | goto out; | 156 | goto out; |
152 | } | 157 | } |
153 | 158 | ||
154 | err = 0; | 159 | err = 0; |
155 | n = read(fd, pid, sizeof(pid)); | 160 | n = read(fd, pid, sizeof(pid)); |
156 | if(n < 0){ | 161 | if (n < 0) { |
157 | printk("is_umdir_used : couldn't read pid file '%s', " | 162 | printk(UM_KERN_ERR "is_umdir_used : couldn't read pid file " |
158 | "err = %d\n", file, errno); | 163 | "'%s', err = %d\n", file, errno); |
159 | goto out_close; | 164 | goto out_close; |
160 | } else if(n == 0){ | 165 | } else if (n == 0) { |
161 | printk("is_umdir_used : couldn't read pid file '%s', " | 166 | printk(UM_KERN_ERR "is_umdir_used : couldn't read pid file " |
162 | "0-byte read\n", file); | 167 | "'%s', 0-byte read\n", file); |
163 | goto out_close; | 168 | goto out_close; |
164 | } | 169 | } |
165 | 170 | ||
166 | p = strtoul(pid, &end, 0); | 171 | p = strtoul(pid, &end, 0); |
167 | if(end == pid){ | 172 | if (end == pid) { |
168 | printk("is_umdir_used : couldn't parse pid file '%s', " | 173 | printk(UM_KERN_ERR "is_umdir_used : couldn't parse pid file " |
169 | "errno = %d\n", file, errno); | 174 | "'%s', errno = %d\n", file, errno); |
170 | goto out_close; | 175 | goto out_close; |
171 | } | 176 | } |
172 | 177 | ||
173 | if((kill(p, 0) == 0) || (errno != ESRCH)){ | 178 | if ((kill(p, 0) == 0) || (errno != ESRCH)) { |
174 | printk("umid \"%s\" is already in use by pid %d\n", umid, p); | 179 | printk(UM_KERN_ERR "umid \"%s\" is already in use by pid %d\n", |
180 | umid, p); | ||
175 | return 1; | 181 | return 1; |
176 | } | 182 | } |
177 | 183 | ||
@@ -195,8 +201,8 @@ static int umdir_take_if_dead(char *dir) | |||
195 | 201 | ||
196 | ret = remove_files_and_dir(dir); | 202 | ret = remove_files_and_dir(dir); |
197 | if (ret) { | 203 | if (ret) { |
198 | printk("is_umdir_used - remove_files_and_dir failed with " | 204 | printk(UM_KERN_ERR "is_umdir_used - remove_files_and_dir " |
199 | "err = %d\n", ret); | 205 | "failed with err = %d\n", ret); |
200 | } | 206 | } |
201 | return ret; | 207 | return ret; |
202 | } | 208 | } |
@@ -207,27 +213,28 @@ static void __init create_pid_file(void) | |||
207 | char pid[sizeof("nnnnn\0")]; | 213 | char pid[sizeof("nnnnn\0")]; |
208 | int fd, n; | 214 | int fd, n; |
209 | 215 | ||
210 | if(umid_file_name("pid", file, sizeof(file))) | 216 | if (umid_file_name("pid", file, sizeof(file))) |
211 | return; | 217 | return; |
212 | 218 | ||
213 | fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644); | 219 | fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644); |
214 | if(fd < 0){ | 220 | if (fd < 0) { |
215 | printk("Open of machine pid file \"%s\" failed: %s\n", | 221 | printk(UM_KERN_ERR "Open of machine pid file \"%s\" failed: " |
216 | file, strerror(errno)); | 222 | "%s\n", file, strerror(errno)); |
217 | return; | 223 | return; |
218 | } | 224 | } |
219 | 225 | ||
220 | snprintf(pid, sizeof(pid), "%d\n", getpid()); | 226 | snprintf(pid, sizeof(pid), "%d\n", getpid()); |
221 | n = write(fd, pid, strlen(pid)); | 227 | n = write(fd, pid, strlen(pid)); |
222 | if(n != strlen(pid)) | 228 | if (n != strlen(pid)) |
223 | printk("Write of pid file failed - err = %d\n", errno); | 229 | printk(UM_KERN_ERR "Write of pid file failed - err = %d\n", |
230 | errno); | ||
224 | 231 | ||
225 | close(fd); | 232 | close(fd); |
226 | } | 233 | } |
227 | 234 | ||
228 | int __init set_umid(char *name) | 235 | int __init set_umid(char *name) |
229 | { | 236 | { |
230 | if(strlen(name) > UMID_LEN - 1) | 237 | if (strlen(name) > UMID_LEN - 1) |
231 | return -E2BIG; | 238 | return -E2BIG; |
232 | 239 | ||
233 | strlcpy(umid, name, sizeof(umid)); | 240 | strlcpy(umid, name, sizeof(umid)); |
@@ -243,18 +250,18 @@ int __init make_umid(void) | |||
243 | int fd, err; | 250 | int fd, err; |
244 | char tmp[256]; | 251 | char tmp[256]; |
245 | 252 | ||
246 | if(umid_setup) | 253 | if (umid_setup) |
247 | return 0; | 254 | return 0; |
248 | 255 | ||
249 | make_uml_dir(); | 256 | make_uml_dir(); |
250 | 257 | ||
251 | if(*umid == '\0'){ | 258 | if (*umid == '\0') { |
252 | strlcpy(tmp, uml_dir, sizeof(tmp)); | 259 | strlcpy(tmp, uml_dir, sizeof(tmp)); |
253 | strlcat(tmp, "XXXXXX", sizeof(tmp)); | 260 | strlcat(tmp, "XXXXXX", sizeof(tmp)); |
254 | fd = mkstemp(tmp); | 261 | fd = mkstemp(tmp); |
255 | if(fd < 0){ | 262 | if (fd < 0) { |
256 | printk("make_umid - mkstemp(%s) failed: %s\n", | 263 | printk(UM_KERN_ERR "make_umid - mkstemp(%s) failed: " |
257 | tmp, strerror(errno)); | 264 | "%s\n", tmp, strerror(errno)); |
258 | err = -errno; | 265 | err = -errno; |
259 | goto err; | 266 | goto err; |
260 | } | 267 | } |
@@ -263,11 +270,12 @@ int __init make_umid(void) | |||
263 | 270 | ||
264 | set_umid(&tmp[strlen(uml_dir)]); | 271 | set_umid(&tmp[strlen(uml_dir)]); |
265 | 272 | ||
266 | /* There's a nice tiny little race between this unlink and | 273 | /* |
274 | * There's a nice tiny little race between this unlink and | ||
267 | * the mkdir below. It'd be nice if there were a mkstemp | 275 | * the mkdir below. It'd be nice if there were a mkstemp |
268 | * for directories. | 276 | * for directories. |
269 | */ | 277 | */ |
270 | if(unlink(tmp)){ | 278 | if (unlink(tmp)) { |
271 | err = -errno; | 279 | err = -errno; |
272 | goto err; | 280 | goto err; |
273 | } | 281 | } |
@@ -275,9 +283,9 @@ int __init make_umid(void) | |||
275 | 283 | ||
276 | snprintf(tmp, sizeof(tmp), "%s%s", uml_dir, umid); | 284 | snprintf(tmp, sizeof(tmp), "%s%s", uml_dir, umid); |
277 | err = mkdir(tmp, 0777); | 285 | err = mkdir(tmp, 0777); |
278 | if(err < 0){ | 286 | if (err < 0) { |
279 | err = -errno; | 287 | err = -errno; |
280 | if(err != -EEXIST) | 288 | if (err != -EEXIST) |
281 | goto err; | 289 | goto err; |
282 | 290 | ||
283 | if (umdir_take_if_dead(tmp) < 0) | 291 | if (umdir_take_if_dead(tmp) < 0) |
@@ -285,9 +293,10 @@ int __init make_umid(void) | |||
285 | 293 | ||
286 | err = mkdir(tmp, 0777); | 294 | err = mkdir(tmp, 0777); |
287 | } | 295 | } |
288 | if(err){ | 296 | if (err) { |
289 | err = -errno; | 297 | err = -errno; |
290 | printk("Failed to create '%s' - err = %d\n", umid, -errno); | 298 | printk(UM_KERN_ERR "Failed to create '%s' - err = %d\n", umid, |
299 | errno); | ||
291 | goto err; | 300 | goto err; |
292 | } | 301 | } |
293 | 302 | ||
@@ -302,14 +311,15 @@ int __init make_umid(void) | |||
302 | 311 | ||
303 | static int __init make_umid_init(void) | 312 | static int __init make_umid_init(void) |
304 | { | 313 | { |
305 | if(!make_umid()) | 314 | if (!make_umid()) |
306 | return 0; | 315 | return 0; |
307 | 316 | ||
308 | /* If initializing with the given umid failed, then try again with | 317 | /* |
318 | * If initializing with the given umid failed, then try again with | ||
309 | * a random one. | 319 | * a random one. |
310 | */ | 320 | */ |
311 | printk("Failed to initialize umid \"%s\", trying with a random umid\n", | 321 | printk(UM_KERN_ERR "Failed to initialize umid \"%s\", trying with a " |
312 | umid); | 322 | "random umid\n", umid); |
313 | *umid = '\0'; | 323 | *umid = '\0'; |
314 | make_umid(); | 324 | make_umid(); |
315 | 325 | ||
@@ -323,12 +333,12 @@ int __init umid_file_name(char *name, char *buf, int len) | |||
323 | int n, err; | 333 | int n, err; |
324 | 334 | ||
325 | err = make_umid(); | 335 | err = make_umid(); |
326 | if(err) | 336 | if (err) |
327 | return err; | 337 | return err; |
328 | 338 | ||
329 | n = snprintf(buf, len, "%s%s/%s", uml_dir, umid, name); | 339 | n = snprintf(buf, len, "%s%s/%s", uml_dir, umid, name); |
330 | if(n >= len){ | 340 | if (n >= len) { |
331 | printk("umid_file_name : buffer too short\n"); | 341 | printk(UM_KERN_ERR "umid_file_name : buffer too short\n"); |
332 | return -E2BIG; | 342 | return -E2BIG; |
333 | } | 343 | } |
334 | 344 | ||
@@ -342,21 +352,22 @@ char *get_umid(void) | |||
342 | 352 | ||
343 | static int __init set_uml_dir(char *name, int *add) | 353 | static int __init set_uml_dir(char *name, int *add) |
344 | { | 354 | { |
345 | if(*name == '\0'){ | 355 | if (*name == '\0') { |
346 | printf("uml_dir can't be an empty string\n"); | 356 | printf("uml_dir can't be an empty string\n"); |
347 | return 0; | 357 | return 0; |
348 | } | 358 | } |
349 | 359 | ||
350 | if(name[strlen(name) - 1] == '/'){ | 360 | if (name[strlen(name) - 1] == '/') { |
351 | uml_dir = name; | 361 | uml_dir = name; |
352 | return 0; | 362 | return 0; |
353 | } | 363 | } |
354 | 364 | ||
355 | uml_dir = malloc(strlen(name) + 2); | 365 | uml_dir = malloc(strlen(name) + 2); |
356 | if(uml_dir == NULL){ | 366 | if (uml_dir == NULL) { |
357 | printf("Failed to malloc uml_dir - error = %d\n", errno); | 367 | printf("Failed to malloc uml_dir - error = %d\n", errno); |
358 | 368 | ||
359 | /* Return 0 here because do_initcalls doesn't look at | 369 | /* |
370 | * Return 0 here because do_initcalls doesn't look at | ||
360 | * the return value. | 371 | * the return value. |
361 | */ | 372 | */ |
362 | return 0; | 373 | return 0; |
@@ -377,7 +388,7 @@ static void remove_umid_dir(void) | |||
377 | 388 | ||
378 | sprintf(dir, "%s%s", uml_dir, umid); | 389 | sprintf(dir, "%s%s", uml_dir, umid); |
379 | err = remove_files_and_dir(dir); | 390 | err = remove_files_and_dir(dir); |
380 | if(err) | 391 | if (err) |
381 | printf("remove_umid_dir - remove_files_and_dir failed with " | 392 | printf("remove_umid_dir - remove_files_and_dir failed with " |
382 | "err = %d\n", err); | 393 | "err = %d\n", err); |
383 | } | 394 | } |
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c index 7cbcf484e13d..ef095436a78c 100644 --- a/arch/um/os-Linux/util.c +++ b/arch/um/os-Linux/util.c | |||
@@ -105,6 +105,44 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...) | |||
105 | 105 | ||
106 | void os_dump_core(void) | 106 | void os_dump_core(void) |
107 | { | 107 | { |
108 | int pid; | ||
109 | |||
108 | signal(SIGSEGV, SIG_DFL); | 110 | signal(SIGSEGV, SIG_DFL); |
111 | |||
112 | /* | ||
113 | * We are about to SIGTERM this entire process group to ensure that | ||
114 | * nothing is around to run after the kernel exits. The | ||
115 | * kernel wants to abort, not die through SIGTERM, so we | ||
116 | * ignore it here. | ||
117 | */ | ||
118 | |||
119 | signal(SIGTERM, SIG_IGN); | ||
120 | kill(0, SIGTERM); | ||
121 | /* | ||
122 | * Most of the other processes associated with this UML are | ||
123 | * likely sTopped, so give them a SIGCONT so they see the | ||
124 | * SIGTERM. | ||
125 | */ | ||
126 | kill(0, SIGCONT); | ||
127 | |||
128 | /* | ||
129 | * Now, having sent signals to everyone but us, make sure they | ||
130 | * die by ptrace. Processes can survive what's been done to | ||
131 | * them so far - the mechanism I understand is receiving a | ||
132 | * SIGSEGV and segfaulting immediately upon return. There is | ||
133 | * always a SIGSEGV pending, and (I'm guessing) signals are | ||
134 | * processed in numeric order so the SIGTERM (signal 15 vs | ||
135 | * SIGSEGV being signal 11) is never handled. | ||
136 | * | ||
137 | * Run a waitpid loop until we get some kind of error. | ||
138 | * Hopefully, it's ECHILD, but there's not a lot we can do if | ||
139 | * it's something else. Tell os_kill_ptraced_process not to | ||
140 | * wait for the child to report its death because there's | ||
141 | * nothing reasonable to do if that fails. | ||
142 | */ | ||
143 | |||
144 | while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) | ||
145 | os_kill_ptraced_process(pid, 0); | ||
146 | |||
109 | abort(); | 147 | abort(); |
110 | } | 148 | } |
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules index bf23dd3e24d0..61107b68e05b 100644 --- a/arch/um/scripts/Makefile.rules +++ b/arch/um/scripts/Makefile.rules | |||
@@ -21,7 +21,7 @@ $(UNPROFILE_OBJS:.o=.%): \ | |||
21 | $(UNPROFILE_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \ | 21 | $(UNPROFILE_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \ |
22 | -Dunix -D__unix__ -D__$(SUBARCH)__ $(CF) | 22 | -Dunix -D__unix__ -D__$(SUBARCH)__ $(CF) |
23 | 23 | ||
24 | # The stubs and unmap.o can't try to call mcount or update basic block data | 24 | # The stubs can't try to call mcount or update basic block data |
25 | define unprofile | 25 | define unprofile |
26 | $(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1))) | 26 | $(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1))) |
27 | endef | 27 | endef |
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index a4618b6b85b9..964dc1a04c37 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile | |||
@@ -1,23 +1,21 @@ | |||
1 | # | ||
2 | # Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
3 | # | ||
4 | |||
1 | obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ | 5 | obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ |
2 | ptrace_user.o setjmp.o signal.o sigcontext.o syscalls.o sysrq.o \ | 6 | ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \ |
3 | sys_call_table.o tls.o | 7 | sys_call_table.o tls.o |
4 | 8 | ||
5 | obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o | ||
6 | |||
7 | subarch-obj-y = lib/bitops_32.o lib/semaphore_32.o lib/string_32.o | 9 | subarch-obj-y = lib/bitops_32.o lib/semaphore_32.o lib/string_32.o |
8 | subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o | 10 | subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o |
9 | subarch-obj-$(CONFIG_MODULES) += kernel/module_32.o | 11 | subarch-obj-$(CONFIG_MODULES) += kernel/module_32.o |
10 | 12 | ||
11 | USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o | 13 | USER_OBJS := bugs.o ptrace_user.o fault.o |
12 | 14 | ||
13 | USER_OBJS += user-offsets.s | 15 | USER_OBJS += user-offsets.s |
14 | extra-y += user-offsets.s | 16 | extra-y += user-offsets.s |
15 | 17 | ||
16 | extra-$(CONFIG_MODE_TT) += unmap.o | ||
17 | |||
18 | UNPROFILE_OBJS := stub_segv.o | 18 | UNPROFILE_OBJS := stub_segv.o |
19 | CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING) | 19 | CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING) |
20 | 20 | ||
21 | include arch/um/scripts/Makefile.rules | 21 | include arch/um/scripts/Makefile.rules |
22 | |||
23 | $(obj)/unmap.%: _c_flags = $(call unprofile,$(CFLAGS)) | ||
diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c index 0393e44813e7..806895d73bcc 100644 --- a/arch/um/sys-i386/bugs.c +++ b/arch/um/sys-i386/bugs.c | |||
@@ -1,18 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <unistd.h> | ||
7 | #include <errno.h> | 6 | #include <errno.h> |
7 | #include <signal.h> | ||
8 | #include <string.h> | 8 | #include <string.h> |
9 | #include <sys/signal.h> | 9 | #include "kern_constants.h" |
10 | #include <asm/ldt.h> | ||
11 | #include "kern_util.h" | ||
12 | #include "user.h" | ||
13 | #include "sysdep/ptrace.h" | ||
14 | #include "task.h" | ||
15 | #include "os.h" | 10 | #include "os.h" |
11 | #include "task.h" | ||
12 | #include "user.h" | ||
16 | 13 | ||
17 | #define MAXTOKEN 64 | 14 | #define MAXTOKEN 64 |
18 | 15 | ||
@@ -30,18 +27,20 @@ static char token(int fd, char *buf, int len, char stop) | |||
30 | do { | 27 | do { |
31 | n = os_read_file(fd, ptr, sizeof(*ptr)); | 28 | n = os_read_file(fd, ptr, sizeof(*ptr)); |
32 | c = *ptr++; | 29 | c = *ptr++; |
33 | if(n != sizeof(*ptr)){ | 30 | if (n != sizeof(*ptr)) { |
34 | if(n == 0) | 31 | if (n == 0) |
35 | return 0; | 32 | return 0; |
36 | printk("Reading /proc/cpuinfo failed, err = %d\n", -n); | 33 | printk(UM_KERN_ERR "Reading /proc/cpuinfo failed, " |
37 | if(n < 0) | 34 | "err = %d\n", -n); |
35 | if (n < 0) | ||
38 | return n; | 36 | return n; |
39 | else return -EIO; | 37 | else return -EIO; |
40 | } | 38 | } |
41 | } while((c != '\n') && (c != stop) && (ptr < end)); | 39 | } while ((c != '\n') && (c != stop) && (ptr < end)); |
42 | 40 | ||
43 | if(ptr == end){ | 41 | if (ptr == end) { |
44 | printk("Failed to find '%c' in /proc/cpuinfo\n", stop); | 42 | printk(UM_KERN_ERR "Failed to find '%c' in /proc/cpuinfo\n", |
43 | stop); | ||
45 | return -1; | 44 | return -1; |
46 | } | 45 | } |
47 | *(ptr - 1) = '\0'; | 46 | *(ptr - 1) = '\0'; |
@@ -54,26 +53,27 @@ static int find_cpuinfo_line(int fd, char *key, char *scratch, int len) | |||
54 | char c; | 53 | char c; |
55 | 54 | ||
56 | scratch[len - 1] = '\0'; | 55 | scratch[len - 1] = '\0'; |
57 | while(1){ | 56 | while (1) { |
58 | c = token(fd, scratch, len - 1, ':'); | 57 | c = token(fd, scratch, len - 1, ':'); |
59 | if(c <= 0) | 58 | if (c <= 0) |
60 | return 0; | 59 | return 0; |
61 | else if(c != ':'){ | 60 | else if (c != ':') { |
62 | printk("Failed to find ':' in /proc/cpuinfo\n"); | 61 | printk(UM_KERN_ERR "Failed to find ':' in " |
62 | "/proc/cpuinfo\n"); | ||
63 | return 0; | 63 | return 0; |
64 | } | 64 | } |
65 | 65 | ||
66 | if(!strncmp(scratch, key, strlen(key))) | 66 | if (!strncmp(scratch, key, strlen(key))) |
67 | return 1; | 67 | return 1; |
68 | 68 | ||
69 | do { | 69 | do { |
70 | n = os_read_file(fd, &c, sizeof(c)); | 70 | n = os_read_file(fd, &c, sizeof(c)); |
71 | if(n != sizeof(c)){ | 71 | if (n != sizeof(c)) { |
72 | printk("Failed to find newline in " | 72 | printk(UM_KERN_ERR "Failed to find newline in " |
73 | "/proc/cpuinfo, err = %d\n", -n); | 73 | "/proc/cpuinfo, err = %d\n", -n); |
74 | return 0; | 74 | return 0; |
75 | } | 75 | } |
76 | } while(c != '\n'); | 76 | } while (c != '\n'); |
77 | } | 77 | } |
78 | return 0; | 78 | return 0; |
79 | } | 79 | } |
@@ -83,46 +83,50 @@ static int check_cpu_flag(char *feature, int *have_it) | |||
83 | char buf[MAXTOKEN], c; | 83 | char buf[MAXTOKEN], c; |
84 | int fd, len = ARRAY_SIZE(buf); | 84 | int fd, len = ARRAY_SIZE(buf); |
85 | 85 | ||
86 | printk("Checking for host processor %s support...", feature); | 86 | printk(UM_KERN_INFO "Checking for host processor %s support...", |
87 | feature); | ||
87 | fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); | 88 | fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); |
88 | if(fd < 0){ | 89 | if (fd < 0) { |
89 | printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd); | 90 | printk(UM_KERN_ERR "Couldn't open /proc/cpuinfo, err = %d\n", |
91 | -fd); | ||
90 | return 0; | 92 | return 0; |
91 | } | 93 | } |
92 | 94 | ||
93 | *have_it = 0; | 95 | *have_it = 0; |
94 | if(!find_cpuinfo_line(fd, "flags", buf, ARRAY_SIZE(buf))) | 96 | if (!find_cpuinfo_line(fd, "flags", buf, ARRAY_SIZE(buf))) |
95 | goto out; | 97 | goto out; |
96 | 98 | ||
97 | c = token(fd, buf, len - 1, ' '); | 99 | c = token(fd, buf, len - 1, ' '); |
98 | if(c < 0) | 100 | if (c < 0) |
99 | goto out; | 101 | goto out; |
100 | else if(c != ' '){ | 102 | else if (c != ' ') { |
101 | printk("Failed to find ' ' in /proc/cpuinfo\n"); | 103 | printk(UM_KERN_ERR "Failed to find ' ' in /proc/cpuinfo\n"); |
102 | goto out; | 104 | goto out; |
103 | } | 105 | } |
104 | 106 | ||
105 | while(1){ | 107 | while (1) { |
106 | c = token(fd, buf, len - 1, ' '); | 108 | c = token(fd, buf, len - 1, ' '); |
107 | if(c < 0) | 109 | if (c < 0) |
108 | goto out; | 110 | goto out; |
109 | else if(c == '\n') break; | 111 | else if (c == '\n') |
112 | break; | ||
110 | 113 | ||
111 | if(!strcmp(buf, feature)){ | 114 | if (!strcmp(buf, feature)) { |
112 | *have_it = 1; | 115 | *have_it = 1; |
113 | goto out; | 116 | goto out; |
114 | } | 117 | } |
115 | } | 118 | } |
116 | out: | 119 | out: |
117 | if(*have_it == 0) | 120 | if (*have_it == 0) |
118 | printk("No\n"); | 121 | printk("No\n"); |
119 | else if(*have_it == 1) | 122 | else if (*have_it == 1) |
120 | printk("Yes\n"); | 123 | printk("Yes\n"); |
121 | os_close_file(fd); | 124 | os_close_file(fd); |
122 | return 1; | 125 | return 1; |
123 | } | 126 | } |
124 | 127 | ||
125 | #if 0 /* This doesn't work in tt mode, plus it's causing compilation problems | 128 | #if 0 /* |
129 | * This doesn't work in tt mode, plus it's causing compilation problems | ||
126 | * for some people. | 130 | * for some people. |
127 | */ | 131 | */ |
128 | static void disable_lcall(void) | 132 | static void disable_lcall(void) |
@@ -135,8 +139,9 @@ static void disable_lcall(void) | |||
135 | ldt.base_addr = 0; | 139 | ldt.base_addr = 0; |
136 | ldt.limit = 0; | 140 | ldt.limit = 0; |
137 | err = modify_ldt(1, &ldt, sizeof(ldt)); | 141 | err = modify_ldt(1, &ldt, sizeof(ldt)); |
138 | if(err) | 142 | if (err) |
139 | printk("Failed to disable lcall7 - errno = %d\n", errno); | 143 | printk(UM_KERN_ERR "Failed to disable lcall7 - errno = %d\n", |
144 | errno); | ||
140 | } | 145 | } |
141 | #endif | 146 | #endif |
142 | 147 | ||
@@ -151,40 +156,41 @@ void arch_check_bugs(void) | |||
151 | { | 156 | { |
152 | int have_it; | 157 | int have_it; |
153 | 158 | ||
154 | if(os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0){ | 159 | if (os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0) { |
155 | printk("/proc/cpuinfo not available - skipping CPU capability " | 160 | printk(UM_KERN_ERR "/proc/cpuinfo not available - skipping CPU " |
156 | "checks\n"); | 161 | "capability checks\n"); |
157 | return; | 162 | return; |
158 | } | 163 | } |
159 | if(check_cpu_flag("cmov", &have_it)) | 164 | if (check_cpu_flag("cmov", &have_it)) |
160 | host_has_cmov = have_it; | 165 | host_has_cmov = have_it; |
161 | if(check_cpu_flag("xmm", &have_it)) | 166 | if (check_cpu_flag("xmm", &have_it)) |
162 | host_has_xmm = have_it; | 167 | host_has_xmm = have_it; |
163 | } | 168 | } |
164 | 169 | ||
165 | int arch_handle_signal(int sig, union uml_pt_regs *regs) | 170 | int arch_handle_signal(int sig, struct uml_pt_regs *regs) |
166 | { | 171 | { |
167 | unsigned char tmp[2]; | 172 | unsigned char tmp[2]; |
168 | 173 | ||
169 | /* This is testing for a cmov (0x0f 0x4x) instruction causing a | 174 | /* |
175 | * This is testing for a cmov (0x0f 0x4x) instruction causing a | ||
170 | * SIGILL in init. | 176 | * SIGILL in init. |
171 | */ | 177 | */ |
172 | if((sig != SIGILL) || (TASK_PID(get_current()) != 1)) | 178 | if ((sig != SIGILL) || (TASK_PID(get_current()) != 1)) |
173 | return 0; | 179 | return 0; |
174 | 180 | ||
175 | if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) | 181 | if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) |
176 | panic("SIGILL in init, could not read instructions!\n"); | 182 | panic("SIGILL in init, could not read instructions!\n"); |
177 | if((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40)) | 183 | if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40)) |
178 | return 0; | 184 | return 0; |
179 | 185 | ||
180 | if(host_has_cmov == 0) | 186 | if (host_has_cmov == 0) |
181 | panic("SIGILL caused by cmov, which this processor doesn't " | 187 | panic("SIGILL caused by cmov, which this processor doesn't " |
182 | "implement, boot a filesystem compiled for older " | 188 | "implement, boot a filesystem compiled for older " |
183 | "processors"); | 189 | "processors"); |
184 | else if(host_has_cmov == 1) | 190 | else if (host_has_cmov == 1) |
185 | panic("SIGILL caused by cmov, which this processor claims to " | 191 | panic("SIGILL caused by cmov, which this processor claims to " |
186 | "implement"); | 192 | "implement"); |
187 | else if(host_has_cmov == -1) | 193 | else if (host_has_cmov == -1) |
188 | panic("SIGILL caused by cmov, couldn't tell if this processor " | 194 | panic("SIGILL caused by cmov, couldn't tell if this processor " |
189 | "implements it, boot a filesystem compiled for older " | 195 | "implements it, boot a filesystem compiled for older " |
190 | "processors"); | 196 | "processors"); |
diff --git a/arch/um/sys-i386/fault.c b/arch/um/sys-i386/fault.c index 745b4fd49e9f..d670f68532f4 100644 --- a/arch/um/sys-i386/fault.c +++ b/arch/um/sys-i386/fault.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -15,14 +15,14 @@ struct exception_table_entry | |||
15 | const struct exception_table_entry *search_exception_tables(unsigned long add); | 15 | const struct exception_table_entry *search_exception_tables(unsigned long add); |
16 | 16 | ||
17 | /* Compare this to arch/i386/mm/extable.c:fixup_exception() */ | 17 | /* Compare this to arch/i386/mm/extable.c:fixup_exception() */ |
18 | int arch_fixup(unsigned long address, union uml_pt_regs *regs) | 18 | int arch_fixup(unsigned long address, struct uml_pt_regs *regs) |
19 | { | 19 | { |
20 | const struct exception_table_entry *fixup; | 20 | const struct exception_table_entry *fixup; |
21 | 21 | ||
22 | fixup = search_exception_tables(address); | 22 | fixup = search_exception_tables(address); |
23 | if(fixup != 0){ | 23 | if (fixup != 0) { |
24 | UPT_IP(regs) = fixup->fixup; | 24 | UPT_IP(regs) = fixup->fixup; |
25 | return(1); | 25 | return 1; |
26 | } | 26 | } |
27 | return(0); | 27 | return 0; |
28 | } | 28 | } |
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index a939a7ef0227..67c0958eb984 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c | |||
@@ -1,106 +1,30 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/sched.h" | 6 | #include "linux/mm.h" |
7 | #include "linux/slab.h" | ||
8 | #include "linux/types.h" | ||
9 | #include "linux/errno.h" | ||
10 | #include "linux/spinlock.h" | ||
11 | #include "asm/uaccess.h" | ||
12 | #include "asm/smp.h" | ||
13 | #include "asm/ldt.h" | ||
14 | #include "asm/unistd.h" | 7 | #include "asm/unistd.h" |
15 | #include "choose-mode.h" | ||
16 | #include "kern.h" | ||
17 | #include "mode_kern.h" | ||
18 | #include "os.h" | 8 | #include "os.h" |
19 | 9 | #include "proc_mm.h" | |
20 | extern int modify_ldt(int func, void *ptr, unsigned long bytecount); | ||
21 | |||
22 | #ifdef CONFIG_MODE_TT | ||
23 | |||
24 | static long do_modify_ldt_tt(int func, void __user *ptr, | ||
25 | unsigned long bytecount) | ||
26 | { | ||
27 | struct user_desc info; | ||
28 | int res = 0; | ||
29 | void *buf = NULL; | ||
30 | void *p = NULL; /* What we pass to host. */ | ||
31 | |||
32 | switch(func){ | ||
33 | case 1: | ||
34 | case 0x11: /* write_ldt */ | ||
35 | /* Do this check now to avoid overflows. */ | ||
36 | if (bytecount != sizeof(struct user_desc)) { | ||
37 | res = -EINVAL; | ||
38 | goto out; | ||
39 | } | ||
40 | |||
41 | if(copy_from_user(&info, ptr, sizeof(info))) { | ||
42 | res = -EFAULT; | ||
43 | goto out; | ||
44 | } | ||
45 | |||
46 | p = &info; | ||
47 | break; | ||
48 | case 0: | ||
49 | case 2: /* read_ldt */ | ||
50 | |||
51 | /* The use of info avoids kmalloc on the write case, not on the | ||
52 | * read one. */ | ||
53 | buf = kmalloc(bytecount, GFP_KERNEL); | ||
54 | if (!buf) { | ||
55 | res = -ENOMEM; | ||
56 | goto out; | ||
57 | } | ||
58 | p = buf; | ||
59 | break; | ||
60 | default: | ||
61 | res = -ENOSYS; | ||
62 | goto out; | ||
63 | } | ||
64 | |||
65 | res = modify_ldt(func, p, bytecount); | ||
66 | if(res < 0) | ||
67 | goto out; | ||
68 | |||
69 | switch(func){ | ||
70 | case 0: | ||
71 | case 2: | ||
72 | /* Modify_ldt was for reading and returned the number of read | ||
73 | * bytes.*/ | ||
74 | if(copy_to_user(ptr, p, res)) | ||
75 | res = -EFAULT; | ||
76 | break; | ||
77 | } | ||
78 | |||
79 | out: | ||
80 | kfree(buf); | ||
81 | return res; | ||
82 | } | ||
83 | |||
84 | #endif | ||
85 | |||
86 | #ifdef CONFIG_MODE_SKAS | ||
87 | |||
88 | #include "skas.h" | 10 | #include "skas.h" |
89 | #include "skas_ptrace.h" | 11 | #include "skas_ptrace.h" |
90 | #include "asm/mmu_context.h" | 12 | #include "sysdep/tls.h" |
91 | #include "proc_mm.h" | 13 | |
14 | extern int modify_ldt(int func, void *ptr, unsigned long bytecount); | ||
92 | 15 | ||
93 | long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, | 16 | long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, |
94 | void **addr, int done) | 17 | void **addr, int done) |
95 | { | 18 | { |
96 | long res; | 19 | long res; |
97 | 20 | ||
98 | if(proc_mm){ | 21 | if (proc_mm) { |
99 | /* This is a special handling for the case, that the mm to | 22 | /* |
23 | * This is a special handling for the case, that the mm to | ||
100 | * modify isn't current->active_mm. | 24 | * modify isn't current->active_mm. |
101 | * If this is called directly by modify_ldt, | 25 | * If this is called directly by modify_ldt, |
102 | * (current->active_mm->context.skas.u == mm_idp) | 26 | * (current->active_mm->context.skas.u == mm_idp) |
103 | * will be true. So no call to switch_mm_skas(mm_idp) is done. | 27 | * will be true. So no call to __switch_mm(mm_idp) is done. |
104 | * If this is called in case of init_new_ldt or PTRACE_LDT, | 28 | * If this is called in case of init_new_ldt or PTRACE_LDT, |
105 | * mm_idp won't belong to current->active_mm, but child->mm. | 29 | * mm_idp won't belong to current->active_mm, but child->mm. |
106 | * So we need to switch child's mm into our userspace, then | 30 | * So we need to switch child's mm into our userspace, then |
@@ -108,12 +32,12 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, | |||
108 | * | 32 | * |
109 | * Note: I'm unsure: should interrupts be disabled here? | 33 | * Note: I'm unsure: should interrupts be disabled here? |
110 | */ | 34 | */ |
111 | if(!current->active_mm || current->active_mm == &init_mm || | 35 | if (!current->active_mm || current->active_mm == &init_mm || |
112 | mm_idp != ¤t->active_mm->context.skas.id) | 36 | mm_idp != ¤t->active_mm->context.id) |
113 | switch_mm_skas(mm_idp); | 37 | __switch_mm(mm_idp); |
114 | } | 38 | } |
115 | 39 | ||
116 | if(ptrace_ldt) { | 40 | if (ptrace_ldt) { |
117 | struct ptrace_ldt ldt_op = (struct ptrace_ldt) { | 41 | struct ptrace_ldt ldt_op = (struct ptrace_ldt) { |
118 | .func = func, | 42 | .func = func, |
119 | .ptr = desc, | 43 | .ptr = desc, |
@@ -121,7 +45,7 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, | |||
121 | u32 cpu; | 45 | u32 cpu; |
122 | int pid; | 46 | int pid; |
123 | 47 | ||
124 | if(!proc_mm) | 48 | if (!proc_mm) |
125 | pid = mm_idp->u.pid; | 49 | pid = mm_idp->u.pid; |
126 | else { | 50 | else { |
127 | cpu = get_cpu(); | 51 | cpu = get_cpu(); |
@@ -130,7 +54,7 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, | |||
130 | 54 | ||
131 | res = os_ptrace_ldt(pid, 0, (unsigned long) &ldt_op); | 55 | res = os_ptrace_ldt(pid, 0, (unsigned long) &ldt_op); |
132 | 56 | ||
133 | if(proc_mm) | 57 | if (proc_mm) |
134 | put_cpu(); | 58 | put_cpu(); |
135 | } | 59 | } |
136 | else { | 60 | else { |
@@ -139,7 +63,7 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, | |||
139 | (sizeof(*desc) + sizeof(long) - 1) & | 63 | (sizeof(*desc) + sizeof(long) - 1) & |
140 | ~(sizeof(long) - 1), | 64 | ~(sizeof(long) - 1), |
141 | addr, &stub_addr); | 65 | addr, &stub_addr); |
142 | if(!res){ | 66 | if (!res) { |
143 | unsigned long args[] = { func, | 67 | unsigned long args[] = { func, |
144 | (unsigned long)stub_addr, | 68 | (unsigned long)stub_addr, |
145 | sizeof(*desc), | 69 | sizeof(*desc), |
@@ -149,13 +73,14 @@ long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, | |||
149 | } | 73 | } |
150 | } | 74 | } |
151 | 75 | ||
152 | if(proc_mm){ | 76 | if (proc_mm) { |
153 | /* This is the second part of special handling, that makes | 77 | /* |
78 | * This is the second part of special handling, that makes | ||
154 | * PTRACE_LDT possible to implement. | 79 | * PTRACE_LDT possible to implement. |
155 | */ | 80 | */ |
156 | if(current->active_mm && current->active_mm != &init_mm && | 81 | if (current->active_mm && current->active_mm != &init_mm && |
157 | mm_idp != ¤t->active_mm->context.skas.id) | 82 | mm_idp != ¤t->active_mm->context.id) |
158 | switch_mm_skas(¤t->active_mm->context.skas.id); | 83 | __switch_mm(¤t->active_mm->context.id); |
159 | } | 84 | } |
160 | 85 | ||
161 | return res; | 86 | return res; |
@@ -170,21 +95,22 @@ static long read_ldt_from_host(void __user * ptr, unsigned long bytecount) | |||
170 | .ptr = kmalloc(bytecount, GFP_KERNEL)}; | 95 | .ptr = kmalloc(bytecount, GFP_KERNEL)}; |
171 | u32 cpu; | 96 | u32 cpu; |
172 | 97 | ||
173 | if(ptrace_ldt.ptr == NULL) | 98 | if (ptrace_ldt.ptr == NULL) |
174 | return -ENOMEM; | 99 | return -ENOMEM; |
175 | 100 | ||
176 | /* This is called from sys_modify_ldt only, so userspace_pid gives | 101 | /* |
102 | * This is called from sys_modify_ldt only, so userspace_pid gives | ||
177 | * us the right number | 103 | * us the right number |
178 | */ | 104 | */ |
179 | 105 | ||
180 | cpu = get_cpu(); | 106 | cpu = get_cpu(); |
181 | res = os_ptrace_ldt(userspace_pid[cpu], 0, (unsigned long) &ptrace_ldt); | 107 | res = os_ptrace_ldt(userspace_pid[cpu], 0, (unsigned long) &ptrace_ldt); |
182 | put_cpu(); | 108 | put_cpu(); |
183 | if(res < 0) | 109 | if (res < 0) |
184 | goto out; | 110 | goto out; |
185 | 111 | ||
186 | n = copy_to_user(ptr, ptrace_ldt.ptr, res); | 112 | n = copy_to_user(ptr, ptrace_ldt.ptr, res); |
187 | if(n != 0) | 113 | if (n != 0) |
188 | res = -EFAULT; | 114 | res = -EFAULT; |
189 | 115 | ||
190 | out: | 116 | out: |
@@ -209,35 +135,34 @@ static int read_ldt(void __user * ptr, unsigned long bytecount) | |||
209 | { | 135 | { |
210 | int i, err = 0; | 136 | int i, err = 0; |
211 | unsigned long size; | 137 | unsigned long size; |
212 | uml_ldt_t * ldt = ¤t->mm->context.skas.ldt; | 138 | uml_ldt_t * ldt = ¤t->mm->context.ldt; |
213 | 139 | ||
214 | if(!ldt->entry_count) | 140 | if (!ldt->entry_count) |
215 | goto out; | 141 | goto out; |
216 | if(bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES) | 142 | if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES) |
217 | bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES; | 143 | bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES; |
218 | err = bytecount; | 144 | err = bytecount; |
219 | 145 | ||
220 | if(ptrace_ldt){ | 146 | if (ptrace_ldt) |
221 | return read_ldt_from_host(ptr, bytecount); | 147 | return read_ldt_from_host(ptr, bytecount); |
222 | } | ||
223 | 148 | ||
224 | down(&ldt->semaphore); | 149 | down(&ldt->semaphore); |
225 | if(ldt->entry_count <= LDT_DIRECT_ENTRIES){ | 150 | if (ldt->entry_count <= LDT_DIRECT_ENTRIES) { |
226 | size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES; | 151 | size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES; |
227 | if(size > bytecount) | 152 | if (size > bytecount) |
228 | size = bytecount; | 153 | size = bytecount; |
229 | if(copy_to_user(ptr, ldt->u.entries, size)) | 154 | if (copy_to_user(ptr, ldt->u.entries, size)) |
230 | err = -EFAULT; | 155 | err = -EFAULT; |
231 | bytecount -= size; | 156 | bytecount -= size; |
232 | ptr += size; | 157 | ptr += size; |
233 | } | 158 | } |
234 | else { | 159 | else { |
235 | for(i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount; | 160 | for (i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount; |
236 | i++){ | 161 | i++) { |
237 | size = PAGE_SIZE; | 162 | size = PAGE_SIZE; |
238 | if(size > bytecount) | 163 | if (size > bytecount) |
239 | size = bytecount; | 164 | size = bytecount; |
240 | if(copy_to_user(ptr, ldt->u.pages[i], size)){ | 165 | if (copy_to_user(ptr, ldt->u.pages[i], size)) { |
241 | err = -EFAULT; | 166 | err = -EFAULT; |
242 | break; | 167 | break; |
243 | } | 168 | } |
@@ -247,10 +172,10 @@ static int read_ldt(void __user * ptr, unsigned long bytecount) | |||
247 | } | 172 | } |
248 | up(&ldt->semaphore); | 173 | up(&ldt->semaphore); |
249 | 174 | ||
250 | if(bytecount == 0 || err == -EFAULT) | 175 | if (bytecount == 0 || err == -EFAULT) |
251 | goto out; | 176 | goto out; |
252 | 177 | ||
253 | if(clear_user(ptr, bytecount)) | 178 | if (clear_user(ptr, bytecount)) |
254 | err = -EFAULT; | 179 | err = -EFAULT; |
255 | 180 | ||
256 | out: | 181 | out: |
@@ -261,15 +186,16 @@ static int read_default_ldt(void __user * ptr, unsigned long bytecount) | |||
261 | { | 186 | { |
262 | int err; | 187 | int err; |
263 | 188 | ||
264 | if(bytecount > 5*LDT_ENTRY_SIZE) | 189 | if (bytecount > 5*LDT_ENTRY_SIZE) |
265 | bytecount = 5*LDT_ENTRY_SIZE; | 190 | bytecount = 5*LDT_ENTRY_SIZE; |
266 | 191 | ||
267 | err = bytecount; | 192 | err = bytecount; |
268 | /* UML doesn't support lcall7 and lcall27. | 193 | /* |
194 | * UML doesn't support lcall7 and lcall27. | ||
269 | * So, we don't really have a default ldt, but emulate | 195 | * So, we don't really have a default ldt, but emulate |
270 | * an empty ldt of common host default ldt size. | 196 | * an empty ldt of common host default ldt size. |
271 | */ | 197 | */ |
272 | if(clear_user(ptr, bytecount)) | 198 | if (clear_user(ptr, bytecount)) |
273 | err = -EFAULT; | 199 | err = -EFAULT; |
274 | 200 | ||
275 | return err; | 201 | return err; |
@@ -277,60 +203,60 @@ static int read_default_ldt(void __user * ptr, unsigned long bytecount) | |||
277 | 203 | ||
278 | static int write_ldt(void __user * ptr, unsigned long bytecount, int func) | 204 | static int write_ldt(void __user * ptr, unsigned long bytecount, int func) |
279 | { | 205 | { |
280 | uml_ldt_t * ldt = ¤t->mm->context.skas.ldt; | 206 | uml_ldt_t * ldt = ¤t->mm->context.ldt; |
281 | struct mm_id * mm_idp = ¤t->mm->context.skas.id; | 207 | struct mm_id * mm_idp = ¤t->mm->context.id; |
282 | int i, err; | 208 | int i, err; |
283 | struct user_desc ldt_info; | 209 | struct user_desc ldt_info; |
284 | struct ldt_entry entry0, *ldt_p; | 210 | struct ldt_entry entry0, *ldt_p; |
285 | void *addr = NULL; | 211 | void *addr = NULL; |
286 | 212 | ||
287 | err = -EINVAL; | 213 | err = -EINVAL; |
288 | if(bytecount != sizeof(ldt_info)) | 214 | if (bytecount != sizeof(ldt_info)) |
289 | goto out; | 215 | goto out; |
290 | err = -EFAULT; | 216 | err = -EFAULT; |
291 | if(copy_from_user(&ldt_info, ptr, sizeof(ldt_info))) | 217 | if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info))) |
292 | goto out; | 218 | goto out; |
293 | 219 | ||
294 | err = -EINVAL; | 220 | err = -EINVAL; |
295 | if(ldt_info.entry_number >= LDT_ENTRIES) | 221 | if (ldt_info.entry_number >= LDT_ENTRIES) |
296 | goto out; | 222 | goto out; |
297 | if(ldt_info.contents == 3){ | 223 | if (ldt_info.contents == 3) { |
298 | if (func == 1) | 224 | if (func == 1) |
299 | goto out; | 225 | goto out; |
300 | if (ldt_info.seg_not_present == 0) | 226 | if (ldt_info.seg_not_present == 0) |
301 | goto out; | 227 | goto out; |
302 | } | 228 | } |
303 | 229 | ||
304 | if(!ptrace_ldt) | 230 | if (!ptrace_ldt) |
305 | down(&ldt->semaphore); | 231 | down(&ldt->semaphore); |
306 | 232 | ||
307 | err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1); | 233 | err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1); |
308 | if(err) | 234 | if (err) |
309 | goto out_unlock; | 235 | goto out_unlock; |
310 | else if(ptrace_ldt) { | 236 | else if (ptrace_ldt) { |
311 | /* With PTRACE_LDT available, this is used as a flag only */ | 237 | /* With PTRACE_LDT available, this is used as a flag only */ |
312 | ldt->entry_count = 1; | 238 | ldt->entry_count = 1; |
313 | goto out; | 239 | goto out; |
314 | } | 240 | } |
315 | 241 | ||
316 | if(ldt_info.entry_number >= ldt->entry_count && | 242 | if (ldt_info.entry_number >= ldt->entry_count && |
317 | ldt_info.entry_number >= LDT_DIRECT_ENTRIES){ | 243 | ldt_info.entry_number >= LDT_DIRECT_ENTRIES) { |
318 | for(i=ldt->entry_count/LDT_ENTRIES_PER_PAGE; | 244 | for (i=ldt->entry_count/LDT_ENTRIES_PER_PAGE; |
319 | i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number; | 245 | i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number; |
320 | i++){ | 246 | i++) { |
321 | if(i == 0) | 247 | if (i == 0) |
322 | memcpy(&entry0, ldt->u.entries, | 248 | memcpy(&entry0, ldt->u.entries, |
323 | sizeof(entry0)); | 249 | sizeof(entry0)); |
324 | ldt->u.pages[i] = (struct ldt_entry *) | 250 | ldt->u.pages[i] = (struct ldt_entry *) |
325 | __get_free_page(GFP_KERNEL|__GFP_ZERO); | 251 | __get_free_page(GFP_KERNEL|__GFP_ZERO); |
326 | if(!ldt->u.pages[i]){ | 252 | if (!ldt->u.pages[i]) { |
327 | err = -ENOMEM; | 253 | err = -ENOMEM; |
328 | /* Undo the change in host */ | 254 | /* Undo the change in host */ |
329 | memset(&ldt_info, 0, sizeof(ldt_info)); | 255 | memset(&ldt_info, 0, sizeof(ldt_info)); |
330 | write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1); | 256 | write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1); |
331 | goto out_unlock; | 257 | goto out_unlock; |
332 | } | 258 | } |
333 | if(i == 0) { | 259 | if (i == 0) { |
334 | memcpy(ldt->u.pages[0], &entry0, | 260 | memcpy(ldt->u.pages[0], &entry0, |
335 | sizeof(entry0)); | 261 | sizeof(entry0)); |
336 | memcpy(ldt->u.pages[0]+1, ldt->u.entries+1, | 262 | memcpy(ldt->u.pages[0]+1, ldt->u.entries+1, |
@@ -339,17 +265,17 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func) | |||
339 | ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE; | 265 | ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE; |
340 | } | 266 | } |
341 | } | 267 | } |
342 | if(ldt->entry_count <= ldt_info.entry_number) | 268 | if (ldt->entry_count <= ldt_info.entry_number) |
343 | ldt->entry_count = ldt_info.entry_number + 1; | 269 | ldt->entry_count = ldt_info.entry_number + 1; |
344 | 270 | ||
345 | if(ldt->entry_count <= LDT_DIRECT_ENTRIES) | 271 | if (ldt->entry_count <= LDT_DIRECT_ENTRIES) |
346 | ldt_p = ldt->u.entries + ldt_info.entry_number; | 272 | ldt_p = ldt->u.entries + ldt_info.entry_number; |
347 | else | 273 | else |
348 | ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] + | 274 | ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] + |
349 | ldt_info.entry_number%LDT_ENTRIES_PER_PAGE; | 275 | ldt_info.entry_number%LDT_ENTRIES_PER_PAGE; |
350 | 276 | ||
351 | if(ldt_info.base_addr == 0 && ldt_info.limit == 0 && | 277 | if (ldt_info.base_addr == 0 && ldt_info.limit == 0 && |
352 | (func == 1 || LDT_empty(&ldt_info))){ | 278 | (func == 1 || LDT_empty(&ldt_info))) { |
353 | ldt_p->a = 0; | 279 | ldt_p->a = 0; |
354 | ldt_p->b = 0; | 280 | ldt_p->b = 0; |
355 | } | 281 | } |
@@ -400,7 +326,7 @@ static void ldt_get_host_info(void) | |||
400 | 326 | ||
401 | spin_lock(&host_ldt_lock); | 327 | spin_lock(&host_ldt_lock); |
402 | 328 | ||
403 | if(host_ldt_entries != NULL){ | 329 | if (host_ldt_entries != NULL) { |
404 | spin_unlock(&host_ldt_lock); | 330 | spin_unlock(&host_ldt_lock); |
405 | return; | 331 | return; |
406 | } | 332 | } |
@@ -408,49 +334,49 @@ static void ldt_get_host_info(void) | |||
408 | 334 | ||
409 | spin_unlock(&host_ldt_lock); | 335 | spin_unlock(&host_ldt_lock); |
410 | 336 | ||
411 | for(i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++); | 337 | for (i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++) |
338 | ; | ||
412 | 339 | ||
413 | ldt = (struct ldt_entry *) | 340 | ldt = (struct ldt_entry *) |
414 | __get_free_pages(GFP_KERNEL|__GFP_ZERO, order); | 341 | __get_free_pages(GFP_KERNEL|__GFP_ZERO, order); |
415 | if(ldt == NULL) { | 342 | if (ldt == NULL) { |
416 | printk("ldt_get_host_info: couldn't allocate buffer for host " | 343 | printk(KERN_ERR "ldt_get_host_info: couldn't allocate buffer " |
417 | "ldt\n"); | 344 | "for host ldt\n"); |
418 | return; | 345 | return; |
419 | } | 346 | } |
420 | 347 | ||
421 | ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE); | 348 | ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE); |
422 | if(ret < 0) { | 349 | if (ret < 0) { |
423 | printk("ldt_get_host_info: couldn't read host ldt\n"); | 350 | printk(KERN_ERR "ldt_get_host_info: couldn't read host ldt\n"); |
424 | goto out_free; | 351 | goto out_free; |
425 | } | 352 | } |
426 | if(ret == 0) { | 353 | if (ret == 0) { |
427 | /* default_ldt is active, simply write an empty entry 0 */ | 354 | /* default_ldt is active, simply write an empty entry 0 */ |
428 | host_ldt_entries = dummy_list; | 355 | host_ldt_entries = dummy_list; |
429 | goto out_free; | 356 | goto out_free; |
430 | } | 357 | } |
431 | 358 | ||
432 | for(i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++){ | 359 | for (i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++) { |
433 | if(ldt[i].a != 0 || ldt[i].b != 0) | 360 | if (ldt[i].a != 0 || ldt[i].b != 0) |
434 | size++; | 361 | size++; |
435 | } | 362 | } |
436 | 363 | ||
437 | if(size < ARRAY_SIZE(dummy_list)) | 364 | if (size < ARRAY_SIZE(dummy_list)) |
438 | host_ldt_entries = dummy_list; | 365 | host_ldt_entries = dummy_list; |
439 | else { | 366 | else { |
440 | size = (size + 1) * sizeof(dummy_list[0]); | 367 | size = (size + 1) * sizeof(dummy_list[0]); |
441 | tmp = kmalloc(size, GFP_KERNEL); | 368 | tmp = kmalloc(size, GFP_KERNEL); |
442 | if(tmp == NULL) { | 369 | if (tmp == NULL) { |
443 | printk("ldt_get_host_info: couldn't allocate host ldt " | 370 | printk(KERN_ERR "ldt_get_host_info: couldn't allocate " |
444 | "list\n"); | 371 | "host ldt list\n"); |
445 | goto out_free; | 372 | goto out_free; |
446 | } | 373 | } |
447 | host_ldt_entries = tmp; | 374 | host_ldt_entries = tmp; |
448 | } | 375 | } |
449 | 376 | ||
450 | for(i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++){ | 377 | for (i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++) { |
451 | if(ldt[i].a != 0 || ldt[i].b != 0) { | 378 | if (ldt[i].a != 0 || ldt[i].b != 0) |
452 | host_ldt_entries[k++] = i; | 379 | host_ldt_entries[k++] = i; |
453 | } | ||
454 | } | 380 | } |
455 | host_ldt_entries[k] = -1; | 381 | host_ldt_entries[k] = -1; |
456 | 382 | ||
@@ -458,8 +384,7 @@ out_free: | |||
458 | free_pages((unsigned long)ldt, order); | 384 | free_pages((unsigned long)ldt, order); |
459 | } | 385 | } |
460 | 386 | ||
461 | long init_new_ldt(struct mmu_context_skas * new_mm, | 387 | long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm) |
462 | struct mmu_context_skas * from_mm) | ||
463 | { | 388 | { |
464 | struct user_desc desc; | 389 | struct user_desc desc; |
465 | short * num_p; | 390 | short * num_p; |
@@ -469,15 +394,15 @@ long init_new_ldt(struct mmu_context_skas * new_mm, | |||
469 | struct proc_mm_op copy; | 394 | struct proc_mm_op copy; |
470 | 395 | ||
471 | 396 | ||
472 | if(!ptrace_ldt) | 397 | if (!ptrace_ldt) |
473 | init_MUTEX(&new_mm->ldt.semaphore); | 398 | init_MUTEX(&new_mm->ldt.semaphore); |
474 | 399 | ||
475 | if(!from_mm){ | 400 | if (!from_mm) { |
476 | memset(&desc, 0, sizeof(desc)); | 401 | memset(&desc, 0, sizeof(desc)); |
477 | /* | 402 | /* |
478 | * We have to initialize a clean ldt. | 403 | * We have to initialize a clean ldt. |
479 | */ | 404 | */ |
480 | if(proc_mm) { | 405 | if (proc_mm) { |
481 | /* | 406 | /* |
482 | * If the new mm was created using proc_mm, host's | 407 | * If the new mm was created using proc_mm, host's |
483 | * default-ldt currently is assigned, which normally | 408 | * default-ldt currently is assigned, which normally |
@@ -485,8 +410,7 @@ long init_new_ldt(struct mmu_context_skas * new_mm, | |||
485 | * To remove these gates, we simply write an empty | 410 | * To remove these gates, we simply write an empty |
486 | * entry as number 0 to the host. | 411 | * entry as number 0 to the host. |
487 | */ | 412 | */ |
488 | err = write_ldt_entry(&new_mm->id, 1, &desc, | 413 | err = write_ldt_entry(&new_mm->id, 1, &desc, &addr, 1); |
489 | &addr, 1); | ||
490 | } | 414 | } |
491 | else{ | 415 | else{ |
492 | /* | 416 | /* |
@@ -495,11 +419,11 @@ long init_new_ldt(struct mmu_context_skas * new_mm, | |||
495 | * will be reset in the following loop | 419 | * will be reset in the following loop |
496 | */ | 420 | */ |
497 | ldt_get_host_info(); | 421 | ldt_get_host_info(); |
498 | for(num_p=host_ldt_entries; *num_p != -1; num_p++){ | 422 | for (num_p=host_ldt_entries; *num_p != -1; num_p++) { |
499 | desc.entry_number = *num_p; | 423 | desc.entry_number = *num_p; |
500 | err = write_ldt_entry(&new_mm->id, 1, &desc, | 424 | err = write_ldt_entry(&new_mm->id, 1, &desc, |
501 | &addr, *(num_p + 1) == -1); | 425 | &addr, *(num_p + 1) == -1); |
502 | if(err) | 426 | if (err) |
503 | break; | 427 | break; |
504 | } | 428 | } |
505 | } | 429 | } |
@@ -508,8 +432,9 @@ long init_new_ldt(struct mmu_context_skas * new_mm, | |||
508 | goto out; | 432 | goto out; |
509 | } | 433 | } |
510 | 434 | ||
511 | if(proc_mm){ | 435 | if (proc_mm) { |
512 | /* We have a valid from_mm, so we now have to copy the LDT of | 436 | /* |
437 | * We have a valid from_mm, so we now have to copy the LDT of | ||
513 | * from_mm to new_mm, because using proc_mm an new mm with | 438 | * from_mm to new_mm, because using proc_mm an new mm with |
514 | * an empty/default LDT was created in new_mm() | 439 | * an empty/default LDT was created in new_mm() |
515 | */ | 440 | */ |
@@ -518,27 +443,27 @@ long init_new_ldt(struct mmu_context_skas * new_mm, | |||
518 | { .copy_segments = | 443 | { .copy_segments = |
519 | from_mm->id.u.mm_fd } } ); | 444 | from_mm->id.u.mm_fd } } ); |
520 | i = os_write_file(new_mm->id.u.mm_fd, ©, sizeof(copy)); | 445 | i = os_write_file(new_mm->id.u.mm_fd, ©, sizeof(copy)); |
521 | if(i != sizeof(copy)) | 446 | if (i != sizeof(copy)) |
522 | printk("new_mm : /proc/mm copy_segments failed, " | 447 | printk(KERN_ERR "new_mm : /proc/mm copy_segments " |
523 | "err = %d\n", -i); | 448 | "failed, err = %d\n", -i); |
524 | } | 449 | } |
525 | 450 | ||
526 | if(!ptrace_ldt) { | 451 | if (!ptrace_ldt) { |
527 | /* Our local LDT is used to supply the data for | 452 | /* |
453 | * Our local LDT is used to supply the data for | ||
528 | * modify_ldt(READLDT), if PTRACE_LDT isn't available, | 454 | * modify_ldt(READLDT), if PTRACE_LDT isn't available, |
529 | * i.e., we have to use the stub for modify_ldt, which | 455 | * i.e., we have to use the stub for modify_ldt, which |
530 | * can't handle the big read buffer of up to 64kB. | 456 | * can't handle the big read buffer of up to 64kB. |
531 | */ | 457 | */ |
532 | down(&from_mm->ldt.semaphore); | 458 | down(&from_mm->ldt.semaphore); |
533 | if(from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES){ | 459 | if (from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES) |
534 | memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries, | 460 | memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries, |
535 | sizeof(new_mm->ldt.u.entries)); | 461 | sizeof(new_mm->ldt.u.entries)); |
536 | } | 462 | else { |
537 | else{ | ||
538 | i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; | 463 | i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; |
539 | while(i-->0){ | 464 | while (i-->0) { |
540 | page = __get_free_page(GFP_KERNEL|__GFP_ZERO); | 465 | page = __get_free_page(GFP_KERNEL|__GFP_ZERO); |
541 | if (!page){ | 466 | if (!page) { |
542 | err = -ENOMEM; | 467 | err = -ENOMEM; |
543 | break; | 468 | break; |
544 | } | 469 | } |
@@ -557,22 +482,19 @@ long init_new_ldt(struct mmu_context_skas * new_mm, | |||
557 | } | 482 | } |
558 | 483 | ||
559 | 484 | ||
560 | void free_ldt(struct mmu_context_skas * mm) | 485 | void free_ldt(struct mm_context *mm) |
561 | { | 486 | { |
562 | int i; | 487 | int i; |
563 | 488 | ||
564 | if(!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES){ | 489 | if (!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES) { |
565 | i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; | 490 | i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; |
566 | while(i-- > 0){ | 491 | while (i-- > 0) |
567 | free_page((long )mm->ldt.u.pages[i]); | 492 | free_page((long) mm->ldt.u.pages[i]); |
568 | } | ||
569 | } | 493 | } |
570 | mm->ldt.entry_count = 0; | 494 | mm->ldt.entry_count = 0; |
571 | } | 495 | } |
572 | #endif | ||
573 | 496 | ||
574 | int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) | 497 | int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) |
575 | { | 498 | { |
576 | return CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func, | 499 | return do_modify_ldt_skas(func, ptr, bytecount); |
577 | ptr, bytecount); | ||
578 | } | 500 | } |
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c index 28bf01150323..9657c89fdf31 100644 --- a/arch/um/sys-i386/ptrace.c +++ b/arch/um/sys-i386/ptrace.c | |||
@@ -1,35 +1,26 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/compiler.h> | ||
7 | #include "linux/sched.h" | ||
8 | #include "linux/mm.h" | 6 | #include "linux/mm.h" |
9 | #include "asm/elf.h" | 7 | #include "linux/sched.h" |
10 | #include "asm/ptrace.h" | ||
11 | #include "asm/uaccess.h" | 8 | #include "asm/uaccess.h" |
12 | #include "asm/unistd.h" | 9 | #include "skas.h" |
13 | #include "sysdep/ptrace.h" | ||
14 | #include "sysdep/sigcontext.h" | ||
15 | #include "sysdep/sc.h" | ||
16 | 10 | ||
17 | void arch_switch_to_tt(struct task_struct *from, struct task_struct *to) | 11 | extern int arch_switch_tls(struct task_struct *from, struct task_struct *to); |
18 | { | ||
19 | update_debugregs(to->thread.arch.debugregs_seq); | ||
20 | arch_switch_tls_tt(from, to); | ||
21 | } | ||
22 | 12 | ||
23 | void arch_switch_to_skas(struct task_struct *from, struct task_struct *to) | 13 | void arch_switch_to(struct task_struct *from, struct task_struct *to) |
24 | { | 14 | { |
25 | int err = arch_switch_tls_skas(from, to); | 15 | int err = arch_switch_tls(from, to); |
26 | if (!err) | 16 | if (!err) |
27 | return; | 17 | return; |
28 | 18 | ||
29 | if (err != -EINVAL) | 19 | if (err != -EINVAL) |
30 | printk(KERN_WARNING "arch_switch_tls_skas failed, errno %d, not EINVAL\n", -err); | 20 | printk(KERN_WARNING "arch_switch_tls failed, errno %d, " |
21 | "not EINVAL\n", -err); | ||
31 | else | 22 | else |
32 | printk(KERN_WARNING "arch_switch_tls_skas failed, errno = EINVAL\n"); | 23 | printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n"); |
33 | } | 24 | } |
34 | 25 | ||
35 | int is_syscall(unsigned long addr) | 26 | int is_syscall(unsigned long addr) |
@@ -38,21 +29,21 @@ int is_syscall(unsigned long addr) | |||
38 | int n; | 29 | int n; |
39 | 30 | ||
40 | n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); | 31 | n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); |
41 | if(n){ | 32 | if (n) { |
42 | /* access_process_vm() grants access to vsyscall and stub, | 33 | /* access_process_vm() grants access to vsyscall and stub, |
43 | * while copy_from_user doesn't. Maybe access_process_vm is | 34 | * while copy_from_user doesn't. Maybe access_process_vm is |
44 | * slow, but that doesn't matter, since it will be called only | 35 | * slow, but that doesn't matter, since it will be called only |
45 | * in case of singlestepping, if copy_from_user failed. | 36 | * in case of singlestepping, if copy_from_user failed. |
46 | */ | 37 | */ |
47 | n = access_process_vm(current, addr, &instr, sizeof(instr), 0); | 38 | n = access_process_vm(current, addr, &instr, sizeof(instr), 0); |
48 | if(n != sizeof(instr)) { | 39 | if (n != sizeof(instr)) { |
49 | printk("is_syscall : failed to read instruction from " | 40 | printk(KERN_ERR "is_syscall : failed to read " |
50 | "0x%lx\n", addr); | 41 | "instruction from 0x%lx\n", addr); |
51 | return(1); | 42 | return 1; |
52 | } | 43 | } |
53 | } | 44 | } |
54 | /* int 0x80 or sysenter */ | 45 | /* int 0x80 or sysenter */ |
55 | return((instr == 0x80cd) || (instr == 0x340f)); | 46 | return (instr == 0x80cd) || (instr == 0x340f); |
56 | } | 47 | } |
57 | 48 | ||
58 | /* determines which flags the user has access to. */ | 49 | /* determines which flags the user has access to. */ |
@@ -96,21 +87,21 @@ int putreg(struct task_struct *child, int regno, unsigned long value) | |||
96 | 87 | ||
97 | int poke_user(struct task_struct *child, long addr, long data) | 88 | int poke_user(struct task_struct *child, long addr, long data) |
98 | { | 89 | { |
99 | if ((addr & 3) || addr < 0) | 90 | if ((addr & 3) || addr < 0) |
100 | return -EIO; | 91 | return -EIO; |
101 | |||
102 | if (addr < MAX_REG_OFFSET) | ||
103 | return putreg(child, addr, data); | ||
104 | 92 | ||
105 | else if((addr >= offsetof(struct user, u_debugreg[0])) && | 93 | if (addr < MAX_REG_OFFSET) |
106 | (addr <= offsetof(struct user, u_debugreg[7]))){ | 94 | return putreg(child, addr, data); |
107 | addr -= offsetof(struct user, u_debugreg[0]); | 95 | else if ((addr >= offsetof(struct user, u_debugreg[0])) && |
108 | addr = addr >> 2; | 96 | (addr <= offsetof(struct user, u_debugreg[7]))) { |
109 | if((addr == 4) || (addr == 5)) return -EIO; | 97 | addr -= offsetof(struct user, u_debugreg[0]); |
110 | child->thread.arch.debugregs[addr] = data; | 98 | addr = addr >> 2; |
111 | return 0; | 99 | if ((addr == 4) || (addr == 5)) |
112 | } | 100 | return -EIO; |
113 | return -EIO; | 101 | child->thread.arch.debugregs[addr] = data; |
102 | return 0; | ||
103 | } | ||
104 | return -EIO; | ||
114 | } | 105 | } |
115 | 106 | ||
116 | unsigned long getreg(struct task_struct *child, int regno) | 107 | unsigned long getreg(struct task_struct *child, int regno) |
@@ -133,20 +124,20 @@ unsigned long getreg(struct task_struct *child, int regno) | |||
133 | return retval; | 124 | return retval; |
134 | } | 125 | } |
135 | 126 | ||
127 | /* read the word at location addr in the USER area. */ | ||
136 | int peek_user(struct task_struct *child, long addr, long data) | 128 | int peek_user(struct task_struct *child, long addr, long data) |
137 | { | 129 | { |
138 | /* read the word at location addr in the USER area. */ | ||
139 | unsigned long tmp; | 130 | unsigned long tmp; |
140 | 131 | ||
141 | if ((addr & 3) || addr < 0) | 132 | if ((addr & 3) || addr < 0) |
142 | return -EIO; | 133 | return -EIO; |
143 | 134 | ||
144 | tmp = 0; /* Default return condition */ | 135 | tmp = 0; /* Default return condition */ |
145 | if(addr < MAX_REG_OFFSET){ | 136 | if (addr < MAX_REG_OFFSET) { |
146 | tmp = getreg(child, addr); | 137 | tmp = getreg(child, addr); |
147 | } | 138 | } |
148 | else if((addr >= offsetof(struct user, u_debugreg[0])) && | 139 | else if ((addr >= offsetof(struct user, u_debugreg[0])) && |
149 | (addr <= offsetof(struct user, u_debugreg[7]))){ | 140 | (addr <= offsetof(struct user, u_debugreg[7]))) { |
150 | addr -= offsetof(struct user, u_debugreg[0]); | 141 | addr -= offsetof(struct user, u_debugreg[0]); |
151 | addr = addr >> 2; | 142 | addr = addr >> 2; |
152 | tmp = child->thread.arch.debugregs[addr]; | 143 | tmp = child->thread.arch.debugregs[addr]; |
@@ -154,277 +145,68 @@ int peek_user(struct task_struct *child, long addr, long data) | |||
154 | return put_user(tmp, (unsigned long __user *) data); | 145 | return put_user(tmp, (unsigned long __user *) data); |
155 | } | 146 | } |
156 | 147 | ||
157 | struct i387_fxsave_struct { | 148 | int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) |
158 | unsigned short cwd; | ||
159 | unsigned short swd; | ||
160 | unsigned short twd; | ||
161 | unsigned short fop; | ||
162 | long fip; | ||
163 | long fcs; | ||
164 | long foo; | ||
165 | long fos; | ||
166 | long mxcsr; | ||
167 | long reserved; | ||
168 | long st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ | ||
169 | long xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ | ||
170 | long padding[56]; | ||
171 | }; | ||
172 | |||
173 | /* | ||
174 | * FPU tag word conversions. | ||
175 | */ | ||
176 | |||
177 | static inline unsigned short twd_i387_to_fxsr( unsigned short twd ) | ||
178 | { | 149 | { |
179 | unsigned int tmp; /* to avoid 16 bit prefixes in the code */ | 150 | int err, n, cpu = ((struct thread_info *) child->stack)->cpu; |
180 | 151 | long fpregs[HOST_FP_SIZE]; | |
181 | /* Transform each pair of bits into 01 (valid) or 00 (empty) */ | ||
182 | tmp = ~twd; | ||
183 | tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ | ||
184 | /* and move the valid bits to the lower byte. */ | ||
185 | tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ | ||
186 | tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ | ||
187 | tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ | ||
188 | return tmp; | ||
189 | } | ||
190 | 152 | ||
191 | static inline unsigned long twd_fxsr_to_i387( struct i387_fxsave_struct *fxsave ) | 153 | BUG_ON(sizeof(*buf) != sizeof(fpregs)); |
192 | { | 154 | err = save_fp_registers(userspace_pid[cpu], fpregs); |
193 | struct _fpxreg *st = NULL; | 155 | if (err) |
194 | unsigned long twd = (unsigned long) fxsave->twd; | 156 | return err; |
195 | unsigned long tag; | ||
196 | unsigned long ret = 0xffff0000; | ||
197 | int i; | ||
198 | 157 | ||
199 | #define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16); | 158 | n = copy_to_user((void *) buf, fpregs, sizeof(fpregs)); |
159 | if(n > 0) | ||
160 | return -EFAULT; | ||
200 | 161 | ||
201 | for ( i = 0 ; i < 8 ; i++ ) { | 162 | return n; |
202 | if ( twd & 0x1 ) { | ||
203 | st = (struct _fpxreg *) FPREG_ADDR( fxsave, i ); | ||
204 | |||
205 | switch ( st->exponent & 0x7fff ) { | ||
206 | case 0x7fff: | ||
207 | tag = 2; /* Special */ | ||
208 | break; | ||
209 | case 0x0000: | ||
210 | if ( !st->significand[0] && | ||
211 | !st->significand[1] && | ||
212 | !st->significand[2] && | ||
213 | !st->significand[3] ) { | ||
214 | tag = 1; /* Zero */ | ||
215 | } else { | ||
216 | tag = 2; /* Special */ | ||
217 | } | ||
218 | break; | ||
219 | default: | ||
220 | if ( st->significand[3] & 0x8000 ) { | ||
221 | tag = 0; /* Valid */ | ||
222 | } else { | ||
223 | tag = 2; /* Special */ | ||
224 | } | ||
225 | break; | ||
226 | } | ||
227 | } else { | ||
228 | tag = 3; /* Empty */ | ||
229 | } | ||
230 | ret |= (tag << (2 * i)); | ||
231 | twd = twd >> 1; | ||
232 | } | ||
233 | return ret; | ||
234 | } | 163 | } |
235 | 164 | ||
236 | /* | 165 | int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) |
237 | * FXSR floating point environment conversions. | ||
238 | */ | ||
239 | |||
240 | #ifdef CONFIG_MODE_TT | ||
241 | static inline int convert_fxsr_to_user_tt(struct _fpstate __user *buf, | ||
242 | struct pt_regs *regs) | ||
243 | { | 166 | { |
244 | struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); | 167 | int n, cpu = ((struct thread_info *) child->stack)->cpu; |
245 | unsigned long env[7]; | 168 | long fpregs[HOST_FP_SIZE]; |
246 | struct _fpreg __user *to; | ||
247 | struct _fpxreg *from; | ||
248 | int i; | ||
249 | 169 | ||
250 | env[0] = (unsigned long)fxsave->cwd | 0xffff0000; | 170 | BUG_ON(sizeof(*buf) != sizeof(fpregs)); |
251 | env[1] = (unsigned long)fxsave->swd | 0xffff0000; | 171 | n = copy_from_user(fpregs, (void *) buf, sizeof(fpregs)); |
252 | env[2] = twd_fxsr_to_i387(fxsave); | 172 | if (n > 0) |
253 | env[3] = fxsave->fip; | 173 | return -EFAULT; |
254 | env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16); | ||
255 | env[5] = fxsave->foo; | ||
256 | env[6] = fxsave->fos; | ||
257 | 174 | ||
258 | if ( __copy_to_user( buf, env, 7 * sizeof(unsigned long) ) ) | 175 | return restore_fp_registers(userspace_pid[cpu], fpregs); |
259 | return 1; | ||
260 | |||
261 | to = &buf->_st[0]; | ||
262 | from = (struct _fpxreg *) &fxsave->st_space[0]; | ||
263 | for ( i = 0 ; i < 8 ; i++, to++, from++ ) { | ||
264 | if ( __copy_to_user( to, from, sizeof(*to) ) ) | ||
265 | return 1; | ||
266 | } | ||
267 | return 0; | ||
268 | } | 176 | } |
269 | #endif | ||
270 | 177 | ||
271 | static inline int convert_fxsr_to_user(struct _fpstate __user *buf, | 178 | int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) |
272 | struct pt_regs *regs) | ||
273 | { | 179 | { |
274 | return(CHOOSE_MODE(convert_fxsr_to_user_tt(buf, regs), 0)); | 180 | int err, n, cpu = ((struct thread_info *) child->stack)->cpu; |
275 | } | 181 | long fpregs[HOST_XFP_SIZE]; |
276 | 182 | ||
277 | #ifdef CONFIG_MODE_TT | 183 | BUG_ON(sizeof(*buf) != sizeof(fpregs)); |
278 | static inline int convert_fxsr_from_user_tt(struct pt_regs *regs, | 184 | err = save_fpx_registers(userspace_pid[cpu], fpregs); |
279 | struct _fpstate __user *buf) | 185 | if (err) |
280 | { | 186 | return err; |
281 | struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); | ||
282 | unsigned long env[7]; | ||
283 | struct _fpxreg *to; | ||
284 | struct _fpreg __user *from; | ||
285 | int i; | ||
286 | |||
287 | if ( __copy_from_user( env, buf, 7 * sizeof(long) ) ) | ||
288 | return 1; | ||
289 | 187 | ||
290 | fxsave->cwd = (unsigned short)(env[0] & 0xffff); | 188 | n = copy_to_user((void *) buf, fpregs, sizeof(fpregs)); |
291 | fxsave->swd = (unsigned short)(env[1] & 0xffff); | 189 | if(n > 0) |
292 | fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff)); | 190 | return -EFAULT; |
293 | fxsave->fip = env[3]; | ||
294 | fxsave->fop = (unsigned short)((env[4] & 0xffff0000) >> 16); | ||
295 | fxsave->fcs = (env[4] & 0xffff); | ||
296 | fxsave->foo = env[5]; | ||
297 | fxsave->fos = env[6]; | ||
298 | 191 | ||
299 | to = (struct _fpxreg *) &fxsave->st_space[0]; | 192 | return n; |
300 | from = &buf->_st[0]; | ||
301 | for ( i = 0 ; i < 8 ; i++, to++, from++ ) { | ||
302 | if ( __copy_from_user( to, from, sizeof(*from) ) ) | ||
303 | return 1; | ||
304 | } | ||
305 | return 0; | ||
306 | } | ||
307 | #endif | ||
308 | |||
309 | static inline int convert_fxsr_from_user(struct pt_regs *regs, | ||
310 | struct _fpstate __user *buf) | ||
311 | { | ||
312 | return(CHOOSE_MODE(convert_fxsr_from_user_tt(regs, buf), 0)); | ||
313 | } | ||
314 | |||
315 | int get_fpregs(unsigned long buf, struct task_struct *child) | ||
316 | { | ||
317 | int err; | ||
318 | |||
319 | err = convert_fxsr_to_user((struct _fpstate __user *) buf, | ||
320 | &child->thread.regs); | ||
321 | if(err) return(-EFAULT); | ||
322 | else return(0); | ||
323 | } | ||
324 | |||
325 | int set_fpregs(unsigned long buf, struct task_struct *child) | ||
326 | { | ||
327 | int err; | ||
328 | |||
329 | err = convert_fxsr_from_user(&child->thread.regs, | ||
330 | (struct _fpstate __user *) buf); | ||
331 | if(err) return(-EFAULT); | ||
332 | else return(0); | ||
333 | } | ||
334 | |||
335 | #ifdef CONFIG_MODE_TT | ||
336 | int get_fpxregs_tt(unsigned long buf, struct task_struct *tsk) | ||
337 | { | ||
338 | struct pt_regs *regs = &tsk->thread.regs; | ||
339 | struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); | ||
340 | int err; | ||
341 | |||
342 | err = __copy_to_user((void __user *) buf, fxsave, | ||
343 | sizeof(struct user_fxsr_struct)); | ||
344 | if(err) return -EFAULT; | ||
345 | else return 0; | ||
346 | } | ||
347 | #endif | ||
348 | |||
349 | int get_fpxregs(unsigned long buf, struct task_struct *tsk) | ||
350 | { | ||
351 | return(CHOOSE_MODE(get_fpxregs_tt(buf, tsk), 0)); | ||
352 | } | ||
353 | |||
354 | #ifdef CONFIG_MODE_TT | ||
355 | int set_fpxregs_tt(unsigned long buf, struct task_struct *tsk) | ||
356 | { | ||
357 | struct pt_regs *regs = &tsk->thread.regs; | ||
358 | struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); | ||
359 | int err; | ||
360 | |||
361 | err = __copy_from_user(fxsave, (void __user *) buf, | ||
362 | sizeof(struct user_fxsr_struct) ); | ||
363 | if(err) return -EFAULT; | ||
364 | else return 0; | ||
365 | } | ||
366 | #endif | ||
367 | |||
368 | int set_fpxregs(unsigned long buf, struct task_struct *tsk) | ||
369 | { | ||
370 | return(CHOOSE_MODE(set_fpxregs_tt(buf, tsk), 0)); | ||
371 | } | ||
372 | |||
373 | #ifdef notdef | ||
374 | int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) | ||
375 | { | ||
376 | fpu->cwd = (((SC_FP_CW(PT_REGS_SC(regs)) & 0xffff) << 16) | | ||
377 | (SC_FP_SW(PT_REGS_SC(regs)) & 0xffff)); | ||
378 | fpu->swd = SC_FP_CSSEL(PT_REGS_SC(regs)) & 0xffff; | ||
379 | fpu->twd = SC_FP_IPOFF(PT_REGS_SC(regs)); | ||
380 | fpu->fip = SC_FP_CSSEL(PT_REGS_SC(regs)) & 0xffff; | ||
381 | fpu->fcs = SC_FP_DATAOFF(PT_REGS_SC(regs)); | ||
382 | fpu->foo = SC_FP_DATASEL(PT_REGS_SC(regs)); | ||
383 | fpu->fos = 0; | ||
384 | memcpy(fpu->st_space, (void *) SC_FP_ST(PT_REGS_SC(regs)), | ||
385 | sizeof(fpu->st_space)); | ||
386 | return(1); | ||
387 | } | 193 | } |
388 | #endif | ||
389 | 194 | ||
390 | #ifdef CONFIG_MODE_TT | 195 | int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) |
391 | static inline void copy_fpu_fxsave_tt(struct pt_regs *regs, | ||
392 | struct user_i387_struct *buf) | ||
393 | { | 196 | { |
394 | struct i387_fxsave_struct *fpu = SC_FXSR_ENV(PT_REGS_SC(regs)); | 197 | int n, cpu = ((struct thread_info *) child->stack)->cpu; |
395 | unsigned short *to; | 198 | long fpregs[HOST_XFP_SIZE]; |
396 | unsigned short *from; | ||
397 | int i; | ||
398 | 199 | ||
399 | memcpy( buf, fpu, 7 * sizeof(long) ); | 200 | BUG_ON(sizeof(*buf) != sizeof(fpregs)); |
201 | n = copy_from_user(fpregs, (void *) buf, sizeof(fpregs)); | ||
202 | if (n > 0) | ||
203 | return -EFAULT; | ||
400 | 204 | ||
401 | to = (unsigned short *) &buf->st_space[0]; | 205 | return restore_fpx_registers(userspace_pid[cpu], fpregs); |
402 | from = (unsigned short *) &fpu->st_space[0]; | ||
403 | for ( i = 0 ; i < 8 ; i++, to += 5, from += 8 ) { | ||
404 | memcpy( to, from, 5 * sizeof(unsigned short) ); | ||
405 | } | ||
406 | } | 206 | } |
407 | #endif | ||
408 | 207 | ||
409 | static inline void copy_fpu_fxsave(struct pt_regs *regs, | 208 | long subarch_ptrace(struct task_struct *child, long request, long addr, |
410 | struct user_i387_struct *buf) | 209 | long data) |
411 | { | 210 | { |
412 | (void) CHOOSE_MODE(copy_fpu_fxsave_tt(regs, buf), 0); | 211 | return -EIO; |
413 | } | 212 | } |
414 | |||
415 | int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu ) | ||
416 | { | ||
417 | copy_fpu_fxsave(regs, (struct user_i387_struct *) fpu); | ||
418 | return(1); | ||
419 | } | ||
420 | |||
421 | /* | ||
422 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
423 | * Emacs will notice this stuff at the end of the file and automatically | ||
424 | * adjust the settings for this buffer only. This must remain at the end | ||
425 | * of the file. | ||
426 | * --------------------------------------------------------------------------- | ||
427 | * Local variables: | ||
428 | * c-file-style: "linux" | ||
429 | * End: | ||
430 | */ | ||
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c index 40ff0c831bd0..5cf97bc229b9 100644 --- a/arch/um/sys-i386/ptrace_user.c +++ b/arch/um/sys-i386/ptrace_user.c | |||
@@ -1,20 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdio.h> | ||
7 | #include <stddef.h> | ||
8 | #include <errno.h> | 6 | #include <errno.h> |
9 | #include <unistd.h> | 7 | #include <sys/ptrace.h> |
10 | #include "ptrace_user.h" | ||
11 | /* Grr, asm/user.h includes asm/ptrace.h, so has to follow ptrace_user.h */ | ||
12 | #include <asm/user.h> | ||
13 | #include "kern_util.h" | ||
14 | #include "sysdep/thread.h" | ||
15 | #include "user.h" | ||
16 | #include "os.h" | ||
17 | #include "uml-config.h" | ||
18 | 8 | ||
19 | int ptrace_getregs(long pid, unsigned long *regs_out) | 9 | int ptrace_getregs(long pid, unsigned long *regs_out) |
20 | { | 10 | { |
@@ -43,89 +33,3 @@ int ptrace_setfpregs(long pid, unsigned long *regs) | |||
43 | return -errno; | 33 | return -errno; |
44 | return 0; | 34 | return 0; |
45 | } | 35 | } |
46 | |||
47 | #ifdef UML_CONFIG_MODE_TT | ||
48 | |||
49 | static void write_debugregs(int pid, unsigned long *regs) | ||
50 | { | ||
51 | struct user *dummy; | ||
52 | int nregs, i; | ||
53 | |||
54 | dummy = NULL; | ||
55 | nregs = ARRAY_SIZE(dummy->u_debugreg); | ||
56 | for(i = 0; i < nregs; i++){ | ||
57 | if((i == 4) || (i == 5)) continue; | ||
58 | if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i], | ||
59 | regs[i]) < 0) | ||
60 | printk("write_debugregs - ptrace failed on " | ||
61 | "register %d, value = 0x%lx, errno = %d\n", i, | ||
62 | regs[i], errno); | ||
63 | } | ||
64 | } | ||
65 | |||
66 | static void read_debugregs(int pid, unsigned long *regs) | ||
67 | { | ||
68 | struct user *dummy; | ||
69 | int nregs, i; | ||
70 | |||
71 | dummy = NULL; | ||
72 | nregs = ARRAY_SIZE(dummy->u_debugreg); | ||
73 | for(i = 0; i < nregs; i++){ | ||
74 | regs[i] = ptrace(PTRACE_PEEKUSR, pid, | ||
75 | &dummy->u_debugreg[i], 0); | ||
76 | } | ||
77 | } | ||
78 | |||
79 | /* Accessed only by the tracing thread */ | ||
80 | static unsigned long kernel_debugregs[8] = { [ 0 ... 7 ] = 0 }; | ||
81 | |||
82 | void arch_enter_kernel(void *task, int pid) | ||
83 | { | ||
84 | read_debugregs(pid, TASK_DEBUGREGS(task)); | ||
85 | write_debugregs(pid, kernel_debugregs); | ||
86 | } | ||
87 | |||
88 | void arch_leave_kernel(void *task, int pid) | ||
89 | { | ||
90 | read_debugregs(pid, kernel_debugregs); | ||
91 | write_debugregs(pid, TASK_DEBUGREGS(task)); | ||
92 | } | ||
93 | |||
94 | #ifdef UML_CONFIG_PT_PROXY | ||
95 | /* Accessed only by the tracing thread */ | ||
96 | static int debugregs_seq; | ||
97 | |||
98 | /* Only called by the ptrace proxy */ | ||
99 | void ptrace_pokeuser(unsigned long addr, unsigned long data) | ||
100 | { | ||
101 | if((addr < offsetof(struct user, u_debugreg[0])) || | ||
102 | (addr > offsetof(struct user, u_debugreg[7]))) | ||
103 | return; | ||
104 | addr -= offsetof(struct user, u_debugreg[0]); | ||
105 | addr = addr >> 2; | ||
106 | if(kernel_debugregs[addr] == data) return; | ||
107 | |||
108 | kernel_debugregs[addr] = data; | ||
109 | debugregs_seq++; | ||
110 | } | ||
111 | |||
112 | static void update_debugregs_cb(void *arg) | ||
113 | { | ||
114 | int pid = *((int *) arg); | ||
115 | |||
116 | write_debugregs(pid, kernel_debugregs); | ||
117 | } | ||
118 | |||
119 | /* Optimized out in its header when not defined */ | ||
120 | void update_debugregs(int seq) | ||
121 | { | ||
122 | int me; | ||
123 | |||
124 | if(seq == debugregs_seq) return; | ||
125 | |||
126 | me = os_getpid(); | ||
127 | initial_thread_cb(update_debugregs_cb, &me); | ||
128 | } | ||
129 | #endif | ||
130 | |||
131 | #endif | ||
diff --git a/arch/um/sys-i386/sigcontext.c b/arch/um/sys-i386/sigcontext.c deleted file mode 100644 index 467d489c31cd..000000000000 --- a/arch/um/sys-i386/sigcontext.c +++ /dev/null | |||
@@ -1,71 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stddef.h> | ||
7 | #include <string.h> | ||
8 | #include <asm/ptrace.h> | ||
9 | #include <asm/sigcontext.h> | ||
10 | #include "sysdep/ptrace.h" | ||
11 | #include "kern_util.h" | ||
12 | |||
13 | void sc_to_sc(void *to_ptr, void *from_ptr) | ||
14 | { | ||
15 | struct sigcontext *to = to_ptr, *from = from_ptr; | ||
16 | |||
17 | memcpy(to, from, sizeof(*to) + sizeof(struct _fpstate)); | ||
18 | if(from->fpstate != NULL) | ||
19 | to->fpstate = (struct _fpstate *) (to + 1); | ||
20 | } | ||
21 | |||
22 | unsigned long *sc_sigmask(void *sc_ptr) | ||
23 | { | ||
24 | struct sigcontext *sc = sc_ptr; | ||
25 | return &sc->oldmask; | ||
26 | } | ||
27 | |||
28 | int sc_get_fpregs(unsigned long buf, void *sc_ptr) | ||
29 | { | ||
30 | struct sigcontext *sc = sc_ptr; | ||
31 | struct _fpstate *from = sc->fpstate, *to = (struct _fpstate *) buf; | ||
32 | int err = 0; | ||
33 | |||
34 | if(from == NULL){ | ||
35 | err |= clear_user_proc(&to->cw, sizeof(to->cw)); | ||
36 | err |= clear_user_proc(&to->sw, sizeof(to->sw)); | ||
37 | err |= clear_user_proc(&to->tag, sizeof(to->tag)); | ||
38 | err |= clear_user_proc(&to->ipoff, sizeof(to->ipoff)); | ||
39 | err |= clear_user_proc(&to->cssel, sizeof(to->cssel)); | ||
40 | err |= clear_user_proc(&to->dataoff, sizeof(to->dataoff)); | ||
41 | err |= clear_user_proc(&to->datasel, sizeof(to->datasel)); | ||
42 | err |= clear_user_proc(&to->_st, sizeof(to->_st)); | ||
43 | } | ||
44 | else { | ||
45 | err |= copy_to_user_proc(&to->cw, &from->cw, sizeof(to->cw)); | ||
46 | err |= copy_to_user_proc(&to->sw, &from->sw, sizeof(to->sw)); | ||
47 | err |= copy_to_user_proc(&to->tag, &from->tag, | ||
48 | sizeof(to->tag)); | ||
49 | err |= copy_to_user_proc(&to->ipoff, &from->ipoff, | ||
50 | sizeof(to->ipoff)); | ||
51 | err |= copy_to_user_proc(&to->cssel,& from->cssel, | ||
52 | sizeof(to->cssel)); | ||
53 | err |= copy_to_user_proc(&to->dataoff, &from->dataoff, | ||
54 | sizeof(to->dataoff)); | ||
55 | err |= copy_to_user_proc(&to->datasel, &from->datasel, | ||
56 | sizeof(to->datasel)); | ||
57 | err |= copy_to_user_proc(to->_st, from->_st, sizeof(to->_st)); | ||
58 | } | ||
59 | return(err); | ||
60 | } | ||
61 | |||
62 | /* | ||
63 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
64 | * Emacs will notice this stuff at the end of the file and automatically | ||
65 | * adjust the settings for this buffer only. This must remain at the end | ||
66 | * of the file. | ||
67 | * --------------------------------------------------------------------------- | ||
68 | * Local variables: | ||
69 | * c-file-style: "linux" | ||
70 | * End: | ||
71 | */ | ||
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c index 1cbf95f6858a..0147227ce18d 100644 --- a/arch/um/sys-i386/signal.c +++ b/arch/um/sys-i386/signal.c | |||
@@ -1,189 +1,293 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/signal.h" | ||
7 | #include "linux/ptrace.h" | 6 | #include "linux/ptrace.h" |
8 | #include "asm/current.h" | ||
9 | #include "asm/ucontext.h" | ||
10 | #include "asm/uaccess.h" | ||
11 | #include "asm/unistd.h" | 7 | #include "asm/unistd.h" |
8 | #include "asm/uaccess.h" | ||
9 | #include "asm/ucontext.h" | ||
12 | #include "frame_kern.h" | 10 | #include "frame_kern.h" |
13 | #include "sigcontext.h" | ||
14 | #include "registers.h" | ||
15 | #include "mode.h" | ||
16 | |||
17 | #ifdef CONFIG_MODE_SKAS | ||
18 | |||
19 | #include "skas.h" | 11 | #include "skas.h" |
20 | 12 | ||
21 | void copy_sc(union uml_pt_regs *regs, void *from) | 13 | void copy_sc(struct uml_pt_regs *regs, void *from) |
22 | { | 14 | { |
23 | struct sigcontext *sc = from; | 15 | struct sigcontext *sc = from; |
24 | 16 | ||
25 | REGS_GS(regs->skas.regs) = sc->gs; | 17 | REGS_GS(regs->gp) = sc->gs; |
26 | REGS_FS(regs->skas.regs) = sc->fs; | 18 | REGS_FS(regs->gp) = sc->fs; |
27 | REGS_ES(regs->skas.regs) = sc->es; | 19 | REGS_ES(regs->gp) = sc->es; |
28 | REGS_DS(regs->skas.regs) = sc->ds; | 20 | REGS_DS(regs->gp) = sc->ds; |
29 | REGS_EDI(regs->skas.regs) = sc->edi; | 21 | REGS_EDI(regs->gp) = sc->edi; |
30 | REGS_ESI(regs->skas.regs) = sc->esi; | 22 | REGS_ESI(regs->gp) = sc->esi; |
31 | REGS_EBP(regs->skas.regs) = sc->ebp; | 23 | REGS_EBP(regs->gp) = sc->ebp; |
32 | REGS_SP(regs->skas.regs) = sc->esp; | 24 | REGS_SP(regs->gp) = sc->esp; |
33 | REGS_EBX(regs->skas.regs) = sc->ebx; | 25 | REGS_EBX(regs->gp) = sc->ebx; |
34 | REGS_EDX(regs->skas.regs) = sc->edx; | 26 | REGS_EDX(regs->gp) = sc->edx; |
35 | REGS_ECX(regs->skas.regs) = sc->ecx; | 27 | REGS_ECX(regs->gp) = sc->ecx; |
36 | REGS_EAX(regs->skas.regs) = sc->eax; | 28 | REGS_EAX(regs->gp) = sc->eax; |
37 | REGS_IP(regs->skas.regs) = sc->eip; | 29 | REGS_IP(regs->gp) = sc->eip; |
38 | REGS_CS(regs->skas.regs) = sc->cs; | 30 | REGS_CS(regs->gp) = sc->cs; |
39 | REGS_EFLAGS(regs->skas.regs) = sc->eflags; | 31 | REGS_EFLAGS(regs->gp) = sc->eflags; |
40 | REGS_SS(regs->skas.regs) = sc->ss; | 32 | REGS_SS(regs->gp) = sc->ss; |
41 | } | 33 | } |
42 | 34 | ||
43 | static int copy_sc_from_user_skas(struct pt_regs *regs, | 35 | /* |
44 | struct sigcontext __user *from) | 36 | * FPU tag word conversions. |
37 | */ | ||
38 | |||
39 | static inline unsigned short twd_i387_to_fxsr(unsigned short twd) | ||
45 | { | 40 | { |
46 | struct sigcontext sc; | 41 | unsigned int tmp; /* to avoid 16 bit prefixes in the code */ |
47 | unsigned long fpregs[HOST_FP_SIZE]; | 42 | |
48 | int err; | 43 | /* Transform each pair of bits into 01 (valid) or 00 (empty) */ |
44 | tmp = ~twd; | ||
45 | tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ | ||
46 | /* and move the valid bits to the lower byte. */ | ||
47 | tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ | ||
48 | tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ | ||
49 | tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ | ||
50 | return tmp; | ||
51 | } | ||
49 | 52 | ||
50 | err = copy_from_user(&sc, from, sizeof(sc)); | 53 | static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave) |
51 | err |= copy_from_user(fpregs, sc.fpstate, sizeof(fpregs)); | 54 | { |
52 | if(err) | 55 | struct _fpxreg *st = NULL; |
53 | return err; | 56 | unsigned long twd = (unsigned long) fxsave->twd; |
57 | unsigned long tag; | ||
58 | unsigned long ret = 0xffff0000; | ||
59 | int i; | ||
60 | |||
61 | #define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16); | ||
62 | |||
63 | for (i = 0; i < 8; i++) { | ||
64 | if (twd & 0x1) { | ||
65 | st = (struct _fpxreg *) FPREG_ADDR(fxsave, i); | ||
66 | |||
67 | switch (st->exponent & 0x7fff) { | ||
68 | case 0x7fff: | ||
69 | tag = 2; /* Special */ | ||
70 | break; | ||
71 | case 0x0000: | ||
72 | if ( !st->significand[0] && | ||
73 | !st->significand[1] && | ||
74 | !st->significand[2] && | ||
75 | !st->significand[3] ) { | ||
76 | tag = 1; /* Zero */ | ||
77 | } else { | ||
78 | tag = 2; /* Special */ | ||
79 | } | ||
80 | break; | ||
81 | default: | ||
82 | if (st->significand[3] & 0x8000) { | ||
83 | tag = 0; /* Valid */ | ||
84 | } else { | ||
85 | tag = 2; /* Special */ | ||
86 | } | ||
87 | break; | ||
88 | } | ||
89 | } else { | ||
90 | tag = 3; /* Empty */ | ||
91 | } | ||
92 | ret |= (tag << (2 * i)); | ||
93 | twd = twd >> 1; | ||
94 | } | ||
95 | return ret; | ||
96 | } | ||
54 | 97 | ||
55 | copy_sc(®s->regs, &sc); | 98 | static int convert_fxsr_to_user(struct _fpstate __user *buf, |
99 | struct user_fxsr_struct *fxsave) | ||
100 | { | ||
101 | unsigned long env[7]; | ||
102 | struct _fpreg __user *to; | ||
103 | struct _fpxreg *from; | ||
104 | int i; | ||
105 | |||
106 | env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul; | ||
107 | env[1] = (unsigned long)fxsave->swd | 0xffff0000ul; | ||
108 | env[2] = twd_fxsr_to_i387(fxsave); | ||
109 | env[3] = fxsave->fip; | ||
110 | env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16); | ||
111 | env[5] = fxsave->foo; | ||
112 | env[6] = fxsave->fos; | ||
113 | |||
114 | if (__copy_to_user(buf, env, 7 * sizeof(unsigned long))) | ||
115 | return 1; | ||
56 | 116 | ||
57 | err = restore_fp_registers(userspace_pid[0], fpregs); | 117 | to = &buf->_st[0]; |
58 | if(err < 0) { | 118 | from = (struct _fpxreg *) &fxsave->st_space[0]; |
59 | printk("copy_sc_from_user_skas - PTRACE_SETFPREGS failed, " | 119 | for (i = 0; i < 8; i++, to++, from++) { |
60 | "errno = %d\n", -err); | 120 | unsigned long __user *t = (unsigned long __user *)to; |
61 | return err; | 121 | unsigned long *f = (unsigned long *)from; |
62 | } | ||
63 | 122 | ||
123 | if (__put_user(*f, t) || | ||
124 | __put_user(*(f + 1), t + 1) || | ||
125 | __put_user(from->exponent, &to->exponent)) | ||
126 | return 1; | ||
127 | } | ||
64 | return 0; | 128 | return 0; |
65 | } | 129 | } |
66 | 130 | ||
67 | int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *to_fp, | 131 | static int convert_fxsr_from_user(struct user_fxsr_struct *fxsave, |
68 | struct pt_regs *regs, unsigned long sp) | 132 | struct _fpstate __user *buf) |
69 | { | 133 | { |
70 | struct sigcontext sc; | 134 | unsigned long env[7]; |
71 | unsigned long fpregs[HOST_FP_SIZE]; | 135 | struct _fpxreg *to; |
72 | struct faultinfo * fi = ¤t->thread.arch.faultinfo; | 136 | struct _fpreg __user *from; |
73 | int err; | 137 | int i; |
74 | 138 | ||
75 | sc.gs = REGS_GS(regs->regs.skas.regs); | 139 | if (copy_from_user( env, buf, 7 * sizeof(long))) |
76 | sc.fs = REGS_FS(regs->regs.skas.regs); | ||
77 | sc.es = REGS_ES(regs->regs.skas.regs); | ||
78 | sc.ds = REGS_DS(regs->regs.skas.regs); | ||
79 | sc.edi = REGS_EDI(regs->regs.skas.regs); | ||
80 | sc.esi = REGS_ESI(regs->regs.skas.regs); | ||
81 | sc.ebp = REGS_EBP(regs->regs.skas.regs); | ||
82 | sc.esp = sp; | ||
83 | sc.ebx = REGS_EBX(regs->regs.skas.regs); | ||
84 | sc.edx = REGS_EDX(regs->regs.skas.regs); | ||
85 | sc.ecx = REGS_ECX(regs->regs.skas.regs); | ||
86 | sc.eax = REGS_EAX(regs->regs.skas.regs); | ||
87 | sc.eip = REGS_IP(regs->regs.skas.regs); | ||
88 | sc.cs = REGS_CS(regs->regs.skas.regs); | ||
89 | sc.eflags = REGS_EFLAGS(regs->regs.skas.regs); | ||
90 | sc.esp_at_signal = regs->regs.skas.regs[UESP]; | ||
91 | sc.ss = regs->regs.skas.regs[SS]; | ||
92 | sc.cr2 = fi->cr2; | ||
93 | sc.err = fi->error_code; | ||
94 | sc.trapno = fi->trap_no; | ||
95 | |||
96 | err = save_fp_registers(userspace_pid[0], fpregs); | ||
97 | if(err < 0){ | ||
98 | printk("copy_sc_to_user_skas - PTRACE_GETFPREGS failed, " | ||
99 | "errno = %d\n", err); | ||
100 | return 1; | 140 | return 1; |
101 | } | ||
102 | to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1)); | ||
103 | sc.fpstate = to_fp; | ||
104 | 141 | ||
105 | if(err) | 142 | fxsave->cwd = (unsigned short)(env[0] & 0xffff); |
106 | return err; | 143 | fxsave->swd = (unsigned short)(env[1] & 0xffff); |
107 | 144 | fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff)); | |
108 | return copy_to_user(to, &sc, sizeof(sc)) || | 145 | fxsave->fip = env[3]; |
109 | copy_to_user(to_fp, fpregs, sizeof(fpregs)); | 146 | fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16); |
147 | fxsave->fcs = (env[4] & 0xffff); | ||
148 | fxsave->foo = env[5]; | ||
149 | fxsave->fos = env[6]; | ||
150 | |||
151 | to = (struct _fpxreg *) &fxsave->st_space[0]; | ||
152 | from = &buf->_st[0]; | ||
153 | for (i = 0; i < 8; i++, to++, from++) { | ||
154 | unsigned long *t = (unsigned long *)to; | ||
155 | unsigned long __user *f = (unsigned long __user *)from; | ||
156 | |||
157 | if (__get_user(*t, f) || | ||
158 | __get_user(*(t + 1), f + 1) || | ||
159 | __get_user(to->exponent, &from->exponent)) | ||
160 | return 1; | ||
161 | } | ||
162 | return 0; | ||
110 | } | 163 | } |
111 | #endif | ||
112 | 164 | ||
113 | #ifdef CONFIG_MODE_TT | 165 | extern int have_fpx_regs; |
114 | 166 | ||
115 | /* These copy a sigcontext to/from userspace. They copy the fpstate pointer, | 167 | static int copy_sc_from_user(struct pt_regs *regs, |
116 | * blowing away the old, good one. So, that value is saved, and then restored | 168 | struct sigcontext __user *from) |
117 | * after the sigcontext copy. In copy_from, the variable holding the saved | ||
118 | * fpstate pointer, and the sigcontext that it should be restored to are both | ||
119 | * in the kernel, so we can just restore using an assignment. In copy_to, the | ||
120 | * saved pointer is in the kernel, but the sigcontext is in userspace, so we | ||
121 | * copy_to_user it. | ||
122 | */ | ||
123 | int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from, | ||
124 | int fpsize) | ||
125 | { | 169 | { |
126 | struct _fpstate *to_fp; | 170 | struct sigcontext sc; |
127 | struct _fpstate __user *from_fp; | ||
128 | unsigned long sigs; | ||
129 | int err; | 171 | int err; |
130 | 172 | ||
131 | to_fp = to->fpstate; | 173 | err = copy_from_user(&sc, from, sizeof(sc)); |
132 | sigs = to->oldmask; | 174 | if (err) |
133 | err = copy_from_user(to, from, sizeof(*to)); | 175 | return err; |
134 | from_fp = to->fpstate; | 176 | |
135 | to->oldmask = sigs; | 177 | copy_sc(®s->regs, &sc); |
136 | to->fpstate = to_fp; | 178 | if (have_fpx_regs) { |
137 | if(to_fp != NULL) | 179 | struct user_fxsr_struct fpx; |
138 | err |= copy_from_user(to_fp, from_fp, fpsize); | 180 | |
139 | return err; | 181 | err = copy_from_user(&fpx, &sc.fpstate->_fxsr_env[0], |
182 | sizeof(struct user_fxsr_struct)); | ||
183 | if (err) | ||
184 | return 1; | ||
185 | |||
186 | err = convert_fxsr_from_user(&fpx, sc.fpstate); | ||
187 | if (err) | ||
188 | return 1; | ||
189 | |||
190 | err = restore_fpx_registers(userspace_pid[current_thread->cpu], | ||
191 | (unsigned long *) &fpx); | ||
192 | if (err < 0) { | ||
193 | printk(KERN_ERR "copy_sc_from_user - " | ||
194 | "restore_fpx_registers failed, errno = %d\n", | ||
195 | -err); | ||
196 | return 1; | ||
197 | } | ||
198 | } | ||
199 | else { | ||
200 | struct user_i387_struct fp; | ||
201 | |||
202 | err = copy_from_user(&fp, sc.fpstate, | ||
203 | sizeof(struct user_i387_struct)); | ||
204 | if (err) | ||
205 | return 1; | ||
206 | |||
207 | err = restore_fp_registers(userspace_pid[current_thread->cpu], | ||
208 | (unsigned long *) &fp); | ||
209 | if (err < 0) { | ||
210 | printk(KERN_ERR "copy_sc_from_user - " | ||
211 | "restore_fp_registers failed, errno = %d\n", | ||
212 | -err); | ||
213 | return 1; | ||
214 | } | ||
215 | } | ||
216 | |||
217 | return 0; | ||
140 | } | 218 | } |
141 | 219 | ||
142 | int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp, | 220 | static int copy_sc_to_user(struct sigcontext __user *to, |
143 | struct sigcontext *from, int fpsize, unsigned long sp) | 221 | struct _fpstate __user *to_fp, struct pt_regs *regs, |
222 | unsigned long sp) | ||
144 | { | 223 | { |
145 | struct _fpstate __user *to_fp; | 224 | struct sigcontext sc; |
146 | struct _fpstate *from_fp; | 225 | struct faultinfo * fi = ¤t->thread.arch.faultinfo; |
147 | int err; | 226 | int err; |
148 | 227 | ||
149 | to_fp = (fp ? fp : (struct _fpstate __user *) (to + 1)); | 228 | sc.gs = REGS_GS(regs->regs.gp); |
150 | from_fp = from->fpstate; | 229 | sc.fs = REGS_FS(regs->regs.gp); |
151 | err = copy_to_user(to, from, sizeof(*to)); | 230 | sc.es = REGS_ES(regs->regs.gp); |
231 | sc.ds = REGS_DS(regs->regs.gp); | ||
232 | sc.edi = REGS_EDI(regs->regs.gp); | ||
233 | sc.esi = REGS_ESI(regs->regs.gp); | ||
234 | sc.ebp = REGS_EBP(regs->regs.gp); | ||
235 | sc.esp = sp; | ||
236 | sc.ebx = REGS_EBX(regs->regs.gp); | ||
237 | sc.edx = REGS_EDX(regs->regs.gp); | ||
238 | sc.ecx = REGS_ECX(regs->regs.gp); | ||
239 | sc.eax = REGS_EAX(regs->regs.gp); | ||
240 | sc.eip = REGS_IP(regs->regs.gp); | ||
241 | sc.cs = REGS_CS(regs->regs.gp); | ||
242 | sc.eflags = REGS_EFLAGS(regs->regs.gp); | ||
243 | sc.esp_at_signal = regs->regs.gp[UESP]; | ||
244 | sc.ss = regs->regs.gp[SS]; | ||
245 | sc.cr2 = fi->cr2; | ||
246 | sc.err = fi->error_code; | ||
247 | sc.trapno = fi->trap_no; | ||
152 | 248 | ||
153 | /* The SP in the sigcontext is the updated one for the signal | 249 | to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1)); |
154 | * delivery. The sp passed in is the original, and this needs | 250 | sc.fpstate = to_fp; |
155 | * to be restored, so we stick it in separately. | ||
156 | */ | ||
157 | err |= copy_to_user(&SC_SP(to), &sp, sizeof(sp)); | ||
158 | 251 | ||
159 | if(from_fp != NULL){ | 252 | if (have_fpx_regs) { |
160 | err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate)); | 253 | struct user_fxsr_struct fpx; |
161 | err |= copy_to_user(to_fp, from_fp, fpsize); | 254 | |
255 | err = save_fpx_registers(userspace_pid[current_thread->cpu], | ||
256 | (unsigned long *) &fpx); | ||
257 | if (err < 0){ | ||
258 | printk(KERN_ERR "copy_sc_to_user - save_fpx_registers " | ||
259 | "failed, errno = %d\n", err); | ||
260 | return 1; | ||
261 | } | ||
262 | |||
263 | err = convert_fxsr_to_user(to_fp, &fpx); | ||
264 | if (err) | ||
265 | return 1; | ||
266 | |||
267 | err |= __put_user(fpx.swd, &to_fp->status); | ||
268 | err |= __put_user(X86_FXSR_MAGIC, &to_fp->magic); | ||
269 | if (err) | ||
270 | return 1; | ||
271 | |||
272 | if (copy_to_user(&to_fp->_fxsr_env[0], &fpx, | ||
273 | sizeof(struct user_fxsr_struct))) | ||
274 | return 1; | ||
162 | } | 275 | } |
163 | return err; | 276 | else { |
164 | } | 277 | struct user_i387_struct fp; |
165 | #endif | ||
166 | |||
167 | static int copy_sc_from_user(struct pt_regs *to, void __user *from) | ||
168 | { | ||
169 | int ret; | ||
170 | 278 | ||
171 | ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, | 279 | err = save_fp_registers(userspace_pid[current_thread->cpu], |
172 | sizeof(struct _fpstate)), | 280 | (unsigned long *) &fp); |
173 | copy_sc_from_user_skas(to, from)); | 281 | if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct))) |
174 | return ret; | 282 | return 1; |
175 | } | 283 | } |
176 | 284 | ||
177 | static int copy_sc_to_user(struct sigcontext __user *to, struct _fpstate __user *fp, | 285 | return copy_to_user(to, &sc, sizeof(sc)); |
178 | struct pt_regs *from, unsigned long sp) | ||
179 | { | ||
180 | return CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), | ||
181 | sizeof(*fp), sp), | ||
182 | copy_sc_to_user_skas(to, fp, from, sp)); | ||
183 | } | 286 | } |
184 | 287 | ||
185 | static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __user *fp, | 288 | static int copy_ucontext_to_user(struct ucontext __user *uc, |
186 | sigset_t *set, unsigned long sp) | 289 | struct _fpstate __user *fp, sigset_t *set, |
290 | unsigned long sp) | ||
187 | { | 291 | { |
188 | int err = 0; | 292 | int err = 0; |
189 | 293 | ||
@@ -233,7 +337,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, | |||
233 | return 1; | 337 | return 1; |
234 | 338 | ||
235 | restorer = frame->retcode; | 339 | restorer = frame->retcode; |
236 | if(ka->sa.sa_flags & SA_RESTORER) | 340 | if (ka->sa.sa_flags & SA_RESTORER) |
237 | restorer = ka->sa.sa_restorer; | 341 | restorer = ka->sa.sa_restorer; |
238 | 342 | ||
239 | /* Update SP now because the page fault handler refuses to extend | 343 | /* Update SP now because the page fault handler refuses to extend |
@@ -265,7 +369,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, | |||
265 | err |= __put_user(__NR_sigreturn, (int __user *)(frame->retcode+2)); | 369 | err |= __put_user(__NR_sigreturn, (int __user *)(frame->retcode+2)); |
266 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); | 370 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); |
267 | 371 | ||
268 | if(err) | 372 | if (err) |
269 | goto err; | 373 | goto err; |
270 | 374 | ||
271 | PT_REGS_SP(regs) = (unsigned long) frame; | 375 | PT_REGS_SP(regs) = (unsigned long) frame; |
@@ -298,7 +402,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
298 | return 1; | 402 | return 1; |
299 | 403 | ||
300 | restorer = frame->retcode; | 404 | restorer = frame->retcode; |
301 | if(ka->sa.sa_flags & SA_RESTORER) | 405 | if (ka->sa.sa_flags & SA_RESTORER) |
302 | restorer = ka->sa.sa_restorer; | 406 | restorer = ka->sa.sa_restorer; |
303 | 407 | ||
304 | /* See comment above about why this is here */ | 408 | /* See comment above about why this is here */ |
@@ -323,7 +427,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
323 | err |= __put_user(__NR_rt_sigreturn, (int __user *)(frame->retcode+1)); | 427 | err |= __put_user(__NR_rt_sigreturn, (int __user *)(frame->retcode+1)); |
324 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); | 428 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); |
325 | 429 | ||
326 | if(err) | 430 | if (err) |
327 | goto err; | 431 | goto err; |
328 | 432 | ||
329 | PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; | 433 | PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; |
@@ -350,8 +454,8 @@ long sys_sigreturn(struct pt_regs regs) | |||
350 | unsigned long __user *extramask = frame->extramask; | 454 | unsigned long __user *extramask = frame->extramask; |
351 | int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); | 455 | int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); |
352 | 456 | ||
353 | if(copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) || | 457 | if (copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) || |
354 | copy_from_user(&set.sig[1], extramask, sig_size)) | 458 | copy_from_user(&set.sig[1], extramask, sig_size)) |
355 | goto segfault; | 459 | goto segfault; |
356 | 460 | ||
357 | sigdelsetmask(&set, ~_BLOCKABLE); | 461 | sigdelsetmask(&set, ~_BLOCKABLE); |
@@ -361,7 +465,7 @@ long sys_sigreturn(struct pt_regs regs) | |||
361 | recalc_sigpending(); | 465 | recalc_sigpending(); |
362 | spin_unlock_irq(¤t->sighand->siglock); | 466 | spin_unlock_irq(¤t->sighand->siglock); |
363 | 467 | ||
364 | if(copy_sc_from_user(¤t->thread.regs, sc)) | 468 | if (copy_sc_from_user(¤t->thread.regs, sc)) |
365 | goto segfault; | 469 | goto segfault; |
366 | 470 | ||
367 | /* Avoid ERESTART handling */ | 471 | /* Avoid ERESTART handling */ |
@@ -376,12 +480,13 @@ long sys_sigreturn(struct pt_regs regs) | |||
376 | long sys_rt_sigreturn(struct pt_regs regs) | 480 | long sys_rt_sigreturn(struct pt_regs regs) |
377 | { | 481 | { |
378 | unsigned long sp = PT_REGS_SP(¤t->thread.regs); | 482 | unsigned long sp = PT_REGS_SP(¤t->thread.regs); |
379 | struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (sp - 4); | 483 | struct rt_sigframe __user *frame = |
484 | (struct rt_sigframe __user *) (sp - 4); | ||
380 | sigset_t set; | 485 | sigset_t set; |
381 | struct ucontext __user *uc = &frame->uc; | 486 | struct ucontext __user *uc = &frame->uc; |
382 | int sig_size = _NSIG_WORDS * sizeof(unsigned long); | 487 | int sig_size = _NSIG_WORDS * sizeof(unsigned long); |
383 | 488 | ||
384 | if(copy_from_user(&set, &uc->uc_sigmask, sig_size)) | 489 | if (copy_from_user(&set, &uc->uc_sigmask, sig_size)) |
385 | goto segfault; | 490 | goto segfault; |
386 | 491 | ||
387 | sigdelsetmask(&set, ~_BLOCKABLE); | 492 | sigdelsetmask(&set, ~_BLOCKABLE); |
@@ -391,7 +496,7 @@ long sys_rt_sigreturn(struct pt_regs regs) | |||
391 | recalc_sigpending(); | 496 | recalc_sigpending(); |
392 | spin_unlock_irq(¤t->sighand->siglock); | 497 | spin_unlock_irq(¤t->sighand->siglock); |
393 | 498 | ||
394 | if(copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext)) | 499 | if (copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext)) |
395 | goto segfault; | 500 | goto segfault; |
396 | 501 | ||
397 | /* Avoid ERESTART handling */ | 502 | /* Avoid ERESTART handling */ |
diff --git a/arch/um/sys-i386/stub.S b/arch/um/sys-i386/stub.S index 6a70d9ab5c29..e730772c401b 100644 --- a/arch/um/sys-i386/stub.S +++ b/arch/um/sys-i386/stub.S | |||
@@ -1,4 +1,5 @@ | |||
1 | #include "uml-config.h" | 1 | #include "uml-config.h" |
2 | #include "as-layout.h" | ||
2 | 3 | ||
3 | .globl syscall_stub | 4 | .globl syscall_stub |
4 | .section .__syscall_stub, "x" | 5 | .section .__syscall_stub, "x" |
@@ -6,7 +7,7 @@ | |||
6 | .globl batch_syscall_stub | 7 | .globl batch_syscall_stub |
7 | batch_syscall_stub: | 8 | batch_syscall_stub: |
8 | /* load pointer to first operation */ | 9 | /* load pointer to first operation */ |
9 | mov $(UML_CONFIG_STUB_DATA+8), %esp | 10 | mov $(ASM_STUB_DATA+8), %esp |
10 | 11 | ||
11 | again: | 12 | again: |
12 | /* load length of additional data */ | 13 | /* load length of additional data */ |
@@ -14,12 +15,12 @@ again: | |||
14 | 15 | ||
15 | /* if(length == 0) : end of list */ | 16 | /* if(length == 0) : end of list */ |
16 | /* write possible 0 to header */ | 17 | /* write possible 0 to header */ |
17 | mov %eax, UML_CONFIG_STUB_DATA+4 | 18 | mov %eax, ASM_STUB_DATA+4 |
18 | cmpl $0, %eax | 19 | cmpl $0, %eax |
19 | jz done | 20 | jz done |
20 | 21 | ||
21 | /* save current pointer */ | 22 | /* save current pointer */ |
22 | mov %esp, UML_CONFIG_STUB_DATA+4 | 23 | mov %esp, ASM_STUB_DATA+4 |
23 | 24 | ||
24 | /* skip additional data */ | 25 | /* skip additional data */ |
25 | add %eax, %esp | 26 | add %eax, %esp |
@@ -45,7 +46,7 @@ again: | |||
45 | 46 | ||
46 | done: | 47 | done: |
47 | /* save return value */ | 48 | /* save return value */ |
48 | mov %eax, UML_CONFIG_STUB_DATA | 49 | mov %eax, ASM_STUB_DATA |
49 | 50 | ||
50 | /* stop */ | 51 | /* stop */ |
51 | int3 | 52 | int3 |
diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c index 2355dc19c46c..b3999cb76bfd 100644 --- a/arch/um/sys-i386/stub_segv.c +++ b/arch/um/sys-i386/stub_segv.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <signal.h> | 6 | #include <signal.h> |
7 | #include <sys/select.h> /* The only way I can see to get sigset_t */ | 7 | #include <sys/select.h> /* The only way I can see to get sigset_t */ |
8 | #include <asm/unistd.h> | 8 | #include <asm/unistd.h> |
9 | #include "as-layout.h" | ||
9 | #include "uml-config.h" | 10 | #include "uml-config.h" |
10 | #include "sysdep/stub.h" | 11 | #include "sysdep/stub.h" |
11 | #include "sysdep/sigcontext.h" | 12 | #include "sysdep/sigcontext.h" |
@@ -17,8 +18,7 @@ stub_segv_handler(int sig) | |||
17 | struct sigcontext *sc = (struct sigcontext *) (&sig + 1); | 18 | struct sigcontext *sc = (struct sigcontext *) (&sig + 1); |
18 | int pid; | 19 | int pid; |
19 | 20 | ||
20 | GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), | 21 | GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), sc); |
21 | sc); | ||
22 | 22 | ||
23 | pid = stub_syscall0(__NR_getpid); | 23 | pid = stub_syscall0(__NR_getpid); |
24 | stub_syscall2(__NR_kill, pid, SIGUSR1); | 24 | stub_syscall2(__NR_kill, pid, SIGUSR1); |
diff --git a/arch/um/sys-i386/tls.c b/arch/um/sys-i386/tls.c index fea8e5e15cc4..b02266ab5c55 100644 --- a/arch/um/sys-i386/tls.c +++ b/arch/um/sys-i386/tls.c | |||
@@ -3,25 +3,12 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/kernel.h" | 6 | #include "linux/percpu.h" |
7 | #include "linux/sched.h" | 7 | #include "linux/sched.h" |
8 | #include "linux/slab.h" | ||
9 | #include "linux/types.h" | ||
10 | #include "asm/uaccess.h" | 8 | #include "asm/uaccess.h" |
11 | #include "asm/ptrace.h" | ||
12 | #include "asm/segment.h" | ||
13 | #include "asm/smp.h" | ||
14 | #include "asm/desc.h" | ||
15 | #include "choose-mode.h" | ||
16 | #include "kern.h" | ||
17 | #include "kern_util.h" | ||
18 | #include "mode_kern.h" | ||
19 | #include "os.h" | 9 | #include "os.h" |
20 | #include "mode.h" | ||
21 | |||
22 | #ifdef CONFIG_MODE_SKAS | ||
23 | #include "skas.h" | 10 | #include "skas.h" |
24 | #endif | 11 | #include "sysdep/tls.h" |
25 | 12 | ||
26 | /* | 13 | /* |
27 | * If needed we can detect when it's uninitialized. | 14 | * If needed we can detect when it's uninitialized. |
@@ -31,8 +18,7 @@ | |||
31 | static int host_supports_tls = -1; | 18 | static int host_supports_tls = -1; |
32 | int host_gdt_entry_tls_min; | 19 | int host_gdt_entry_tls_min; |
33 | 20 | ||
34 | #ifdef CONFIG_MODE_SKAS | 21 | int do_set_thread_area(struct user_desc *info) |
35 | int do_set_thread_area_skas(struct user_desc *info) | ||
36 | { | 22 | { |
37 | int ret; | 23 | int ret; |
38 | u32 cpu; | 24 | u32 cpu; |
@@ -43,7 +29,7 @@ int do_set_thread_area_skas(struct user_desc *info) | |||
43 | return ret; | 29 | return ret; |
44 | } | 30 | } |
45 | 31 | ||
46 | int do_get_thread_area_skas(struct user_desc *info) | 32 | int do_get_thread_area(struct user_desc *info) |
47 | { | 33 | { |
48 | int ret; | 34 | int ret; |
49 | u32 cpu; | 35 | u32 cpu; |
@@ -53,7 +39,6 @@ int do_get_thread_area_skas(struct user_desc *info) | |||
53 | put_cpu(); | 39 | put_cpu(); |
54 | return ret; | 40 | return ret; |
55 | } | 41 | } |
56 | #endif | ||
57 | 42 | ||
58 | /* | 43 | /* |
59 | * sys_get_thread_area: get a yet unused TLS descriptor index. | 44 | * sys_get_thread_area: get a yet unused TLS descriptor index. |
@@ -82,7 +67,8 @@ static inline void clear_user_desc(struct user_desc* info) | |||
82 | /* Postcondition: LDT_empty(info) returns true. */ | 67 | /* Postcondition: LDT_empty(info) returns true. */ |
83 | memset(info, 0, sizeof(*info)); | 68 | memset(info, 0, sizeof(*info)); |
84 | 69 | ||
85 | /* Check the LDT_empty or the i386 sys_get_thread_area code - we obtain | 70 | /* |
71 | * Check the LDT_empty or the i386 sys_get_thread_area code - we obtain | ||
86 | * indeed an empty user_desc. | 72 | * indeed an empty user_desc. |
87 | */ | 73 | */ |
88 | info->read_exec_only = 1; | 74 | info->read_exec_only = 1; |
@@ -97,10 +83,13 @@ static int load_TLS(int flags, struct task_struct *to) | |||
97 | int idx; | 83 | int idx; |
98 | 84 | ||
99 | for (idx = GDT_ENTRY_TLS_MIN; idx < GDT_ENTRY_TLS_MAX; idx++) { | 85 | for (idx = GDT_ENTRY_TLS_MIN; idx < GDT_ENTRY_TLS_MAX; idx++) { |
100 | struct uml_tls_struct* curr = &to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN]; | 86 | struct uml_tls_struct* curr = |
87 | &to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN]; | ||
101 | 88 | ||
102 | /* Actually, now if it wasn't flushed it gets cleared and | 89 | /* |
103 | * flushed to the host, which will clear it.*/ | 90 | * Actually, now if it wasn't flushed it gets cleared and |
91 | * flushed to the host, which will clear it. | ||
92 | */ | ||
104 | if (!curr->present) { | 93 | if (!curr->present) { |
105 | if (!curr->flushed) { | 94 | if (!curr->flushed) { |
106 | clear_user_desc(&curr->tls); | 95 | clear_user_desc(&curr->tls); |
@@ -124,7 +113,8 @@ out: | |||
124 | return ret; | 113 | return ret; |
125 | } | 114 | } |
126 | 115 | ||
127 | /* Verify if we need to do a flush for the new process, i.e. if there are any | 116 | /* |
117 | * Verify if we need to do a flush for the new process, i.e. if there are any | ||
128 | * present desc's, only if they haven't been flushed. | 118 | * present desc's, only if they haven't been flushed. |
129 | */ | 119 | */ |
130 | static inline int needs_TLS_update(struct task_struct *task) | 120 | static inline int needs_TLS_update(struct task_struct *task) |
@@ -133,10 +123,13 @@ static inline int needs_TLS_update(struct task_struct *task) | |||
133 | int ret = 0; | 123 | int ret = 0; |
134 | 124 | ||
135 | for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) { | 125 | for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) { |
136 | struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN]; | 126 | struct uml_tls_struct* curr = |
127 | &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN]; | ||
137 | 128 | ||
138 | /* Can't test curr->present, we may need to clear a descriptor | 129 | /* |
139 | * which had a value. */ | 130 | * Can't test curr->present, we may need to clear a descriptor |
131 | * which had a value. | ||
132 | */ | ||
140 | if (curr->flushed) | 133 | if (curr->flushed) |
141 | continue; | 134 | continue; |
142 | ret = 1; | 135 | ret = 1; |
@@ -145,7 +138,8 @@ static inline int needs_TLS_update(struct task_struct *task) | |||
145 | return ret; | 138 | return ret; |
146 | } | 139 | } |
147 | 140 | ||
148 | /* On a newly forked process, the TLS descriptors haven't yet been flushed. So | 141 | /* |
142 | * On a newly forked process, the TLS descriptors haven't yet been flushed. So | ||
149 | * we mark them as such and the first switch_to will do the job. | 143 | * we mark them as such and the first switch_to will do the job. |
150 | */ | 144 | */ |
151 | void clear_flushed_tls(struct task_struct *task) | 145 | void clear_flushed_tls(struct task_struct *task) |
@@ -153,10 +147,13 @@ void clear_flushed_tls(struct task_struct *task) | |||
153 | int i; | 147 | int i; |
154 | 148 | ||
155 | for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) { | 149 | for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) { |
156 | struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN]; | 150 | struct uml_tls_struct* curr = |
151 | &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN]; | ||
157 | 152 | ||
158 | /* Still correct to do this, if it wasn't present on the host it | 153 | /* |
159 | * will remain as flushed as it was. */ | 154 | * Still correct to do this, if it wasn't present on the host it |
155 | * will remain as flushed as it was. | ||
156 | */ | ||
160 | if (!curr->present) | 157 | if (!curr->present) |
161 | continue; | 158 | continue; |
162 | 159 | ||
@@ -164,40 +161,33 @@ void clear_flushed_tls(struct task_struct *task) | |||
164 | } | 161 | } |
165 | } | 162 | } |
166 | 163 | ||
167 | /* In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a | 164 | /* |
165 | * In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a | ||
168 | * common host process. So this is needed in SKAS0 too. | 166 | * common host process. So this is needed in SKAS0 too. |
169 | * | 167 | * |
170 | * However, if each thread had a different host process (and this was discussed | 168 | * However, if each thread had a different host process (and this was discussed |
171 | * for SMP support) this won't be needed. | 169 | * for SMP support) this won't be needed. |
172 | * | 170 | * |
173 | * And this will not need be used when (and if) we'll add support to the host | 171 | * And this will not need be used when (and if) we'll add support to the host |
174 | * SKAS patch. */ | 172 | * SKAS patch. |
173 | */ | ||
175 | 174 | ||
176 | int arch_switch_tls_skas(struct task_struct *from, struct task_struct *to) | 175 | int arch_switch_tls(struct task_struct *from, struct task_struct *to) |
177 | { | 176 | { |
178 | if (!host_supports_tls) | 177 | if (!host_supports_tls) |
179 | return 0; | 178 | return 0; |
180 | 179 | ||
181 | /* We have no need whatsoever to switch TLS for kernel threads; beyond | 180 | /* |
181 | * We have no need whatsoever to switch TLS for kernel threads; beyond | ||
182 | * that, that would also result in us calling os_set_thread_area with | 182 | * that, that would also result in us calling os_set_thread_area with |
183 | * userspace_pid[cpu] == 0, which gives an error. */ | 183 | * userspace_pid[cpu] == 0, which gives an error. |
184 | */ | ||
184 | if (likely(to->mm)) | 185 | if (likely(to->mm)) |
185 | return load_TLS(O_FORCE, to); | 186 | return load_TLS(O_FORCE, to); |
186 | 187 | ||
187 | return 0; | 188 | return 0; |
188 | } | 189 | } |
189 | 190 | ||
190 | int arch_switch_tls_tt(struct task_struct *from, struct task_struct *to) | ||
191 | { | ||
192 | if (!host_supports_tls) | ||
193 | return 0; | ||
194 | |||
195 | if (needs_TLS_update(to)) | ||
196 | return load_TLS(0, to); | ||
197 | |||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static int set_tls_entry(struct task_struct* task, struct user_desc *info, | 191 | static int set_tls_entry(struct task_struct* task, struct user_desc *info, |
202 | int idx, int flushed) | 192 | int idx, int flushed) |
203 | { | 193 | { |
@@ -251,17 +241,20 @@ static int get_tls_entry(struct task_struct* task, struct user_desc *info, int i | |||
251 | *info = t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls; | 241 | *info = t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls; |
252 | 242 | ||
253 | out: | 243 | out: |
254 | /* Temporary debugging check, to make sure that things have been | 244 | /* |
245 | * Temporary debugging check, to make sure that things have been | ||
255 | * flushed. This could be triggered if load_TLS() failed. | 246 | * flushed. This could be triggered if load_TLS() failed. |
256 | */ | 247 | */ |
257 | if (unlikely(task == current && !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) { | 248 | if (unlikely(task == current && |
249 | !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) { | ||
258 | printk(KERN_ERR "get_tls_entry: task with pid %d got here " | 250 | printk(KERN_ERR "get_tls_entry: task with pid %d got here " |
259 | "without flushed TLS.", current->pid); | 251 | "without flushed TLS.", current->pid); |
260 | } | 252 | } |
261 | 253 | ||
262 | return 0; | 254 | return 0; |
263 | clear: | 255 | clear: |
264 | /* When the TLS entry has not been set, the values read to user in the | 256 | /* |
257 | * When the TLS entry has not been set, the values read to user in the | ||
265 | * tls_array are 0 (because it's cleared at boot, see | 258 | * tls_array are 0 (because it's cleared at boot, see |
266 | * arch/i386/kernel/head.S:cpu_gdt_table). Emulate that. | 259 | * arch/i386/kernel/head.S:cpu_gdt_table). Emulate that. |
267 | */ | 260 | */ |
@@ -293,7 +286,7 @@ asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc) | |||
293 | return -EFAULT; | 286 | return -EFAULT; |
294 | } | 287 | } |
295 | 288 | ||
296 | ret = CHOOSE_MODE_PROC(do_set_thread_area_tt, do_set_thread_area_skas, &info); | 289 | ret = do_set_thread_area(&info); |
297 | if (ret) | 290 | if (ret) |
298 | return ret; | 291 | return ret; |
299 | return set_tls_entry(current, &info, idx, 1); | 292 | return set_tls_entry(current, &info, idx, 1); |
@@ -363,8 +356,10 @@ out: | |||
363 | } | 356 | } |
364 | 357 | ||
365 | 358 | ||
366 | /* XXX: This part is probably common to i386 and x86-64. Don't create a common | 359 | /* |
367 | * file for now, do that when implementing x86-64 support.*/ | 360 | * XXX: This part is probably common to i386 and x86-64. Don't create a common |
361 | * file for now, do that when implementing x86-64 support. | ||
362 | */ | ||
368 | static int __init __setup_host_supports_tls(void) | 363 | static int __init __setup_host_supports_tls(void) |
369 | { | 364 | { |
370 | check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min); | 365 | check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min); |
diff --git a/arch/um/sys-i386/unmap.c b/arch/um/sys-i386/unmap.c deleted file mode 100644 index 1b0ad0e4adcd..000000000000 --- a/arch/um/sys-i386/unmap.c +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <linux/mman.h> | ||
7 | #include <asm/unistd.h> | ||
8 | |||
9 | static int errno; | ||
10 | |||
11 | static inline _syscall2(int,munmap,void *,start,size_t,len) | ||
12 | static inline _syscall6(void *,mmap2,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset) | ||
13 | int switcheroo(int fd, int prot, void *from, void *to, int size) | ||
14 | { | ||
15 | if(munmap(to, size) < 0){ | ||
16 | return(-1); | ||
17 | } | ||
18 | if(mmap2(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1 ){ | ||
19 | return(-1); | ||
20 | } | ||
21 | if(munmap(from, size) < 0){ | ||
22 | return(-1); | ||
23 | } | ||
24 | return(0); | ||
25 | } | ||
diff --git a/arch/um/sys-i386/user-offsets.c b/arch/um/sys-i386/user-offsets.c index 29118cf5ff25..514241526a1b 100644 --- a/arch/um/sys-i386/user-offsets.c +++ b/arch/um/sys-i386/user-offsets.c | |||
@@ -2,9 +2,9 @@ | |||
2 | #include <stddef.h> | 2 | #include <stddef.h> |
3 | #include <signal.h> | 3 | #include <signal.h> |
4 | #include <sys/poll.h> | 4 | #include <sys/poll.h> |
5 | #include <sys/user.h> | ||
5 | #include <sys/mman.h> | 6 | #include <sys/mman.h> |
6 | #include <asm/ptrace.h> | 7 | #include <asm/ptrace.h> |
7 | #include <asm/user.h> | ||
8 | 8 | ||
9 | #define DEFINE(sym, val) \ | 9 | #define DEFINE(sym, val) \ |
10 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) | 10 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) |
@@ -48,8 +48,8 @@ void foo(void) | |||
48 | OFFSET(HOST_SC_FP_ST, _fpstate, _st); | 48 | OFFSET(HOST_SC_FP_ST, _fpstate, _st); |
49 | OFFSET(HOST_SC_FXSR_ENV, _fpstate, _fxsr_env); | 49 | OFFSET(HOST_SC_FXSR_ENV, _fpstate, _fxsr_env); |
50 | 50 | ||
51 | DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_i387_struct)); | 51 | DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_fpregs_struct)); |
52 | DEFINE_LONGS(HOST_XFP_SIZE, sizeof(struct user_fxsr_struct)); | 52 | DEFINE_LONGS(HOST_XFP_SIZE, sizeof(struct user_fpxregs_struct)); |
53 | 53 | ||
54 | DEFINE(HOST_IP, EIP); | 54 | DEFINE(HOST_IP, EIP); |
55 | DEFINE(HOST_SP, UESP); | 55 | DEFINE(HOST_SP, UESP); |
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index ea8185d85404..3c22de532088 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile | |||
@@ -5,10 +5,9 @@ | |||
5 | # | 5 | # |
6 | 6 | ||
7 | obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ | 7 | obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ |
8 | setjmp.o sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o \ | 8 | setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \ |
9 | ksyms.o tls.o | 9 | sysrq.o ksyms.o tls.o |
10 | 10 | ||
11 | obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o | ||
12 | obj-$(CONFIG_MODULES) += um_module.o | 11 | obj-$(CONFIG_MODULES) += um_module.o |
13 | 12 | ||
14 | subarch-obj-y = lib/bitops_64.o lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o | 13 | subarch-obj-y = lib/bitops_64.o lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o |
@@ -16,16 +15,12 @@ subarch-obj-$(CONFIG_MODULES) += kernel/module_64.o | |||
16 | 15 | ||
17 | ldt-y = ../sys-i386/ldt.o | 16 | ldt-y = ../sys-i386/ldt.o |
18 | 17 | ||
19 | USER_OBJS := ptrace_user.o sigcontext.o | 18 | USER_OBJS := ptrace_user.o |
20 | 19 | ||
21 | USER_OBJS += user-offsets.s | 20 | USER_OBJS += user-offsets.s |
22 | extra-y += user-offsets.s | 21 | extra-y += user-offsets.s |
23 | 22 | ||
24 | extra-$(CONFIG_MODE_TT) += unmap.o | ||
25 | |||
26 | UNPROFILE_OBJS := stub_segv.o | 23 | UNPROFILE_OBJS := stub_segv.o |
27 | CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING) | 24 | CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING) |
28 | 25 | ||
29 | include arch/um/scripts/Makefile.rules | 26 | include arch/um/scripts/Makefile.rules |
30 | |||
31 | $(obj)/unmap.%: _c_flags = $(call unprofile,$(CFLAGS)) | ||
diff --git a/arch/um/sys-x86_64/bugs.c b/arch/um/sys-x86_64/bugs.c index 095478890371..506b6765bbcb 100644 --- a/arch/um/sys-x86_64/bugs.c +++ b/arch/um/sys-x86_64/bugs.c | |||
@@ -14,7 +14,7 @@ void arch_check_bugs(void) | |||
14 | { | 14 | { |
15 | } | 15 | } |
16 | 16 | ||
17 | int arch_handle_signal(int sig, union uml_pt_regs *regs) | 17 | int arch_handle_signal(int sig, struct uml_pt_regs *regs) |
18 | { | 18 | { |
19 | return 0; | 19 | return 0; |
20 | } | 20 | } |
diff --git a/arch/um/sys-x86_64/fault.c b/arch/um/sys-x86_64/fault.c index 4636b1465b6c..ce85117fc64e 100644 --- a/arch/um/sys-x86_64/fault.c +++ b/arch/um/sys-x86_64/fault.c | |||
@@ -14,14 +14,15 @@ struct exception_table_entry | |||
14 | }; | 14 | }; |
15 | 15 | ||
16 | const struct exception_table_entry *search_exception_tables(unsigned long add); | 16 | const struct exception_table_entry *search_exception_tables(unsigned long add); |
17 | int arch_fixup(unsigned long address, union uml_pt_regs *regs) | 17 | |
18 | int arch_fixup(unsigned long address, struct uml_pt_regs *regs) | ||
18 | { | 19 | { |
19 | const struct exception_table_entry *fixup; | 20 | const struct exception_table_entry *fixup; |
20 | 21 | ||
21 | fixup = search_exception_tables(address); | 22 | fixup = search_exception_tables(address); |
22 | if(fixup != 0){ | 23 | if (fixup != 0) { |
23 | UPT_IP(regs) = fixup->fixup; | 24 | UPT_IP(regs) = fixup->fixup; |
24 | return(1); | 25 | return 1; |
25 | } | 26 | } |
26 | return(0); | 27 | return 0; |
27 | } | 28 | } |
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c index 1970d78aa528..a3cfeed17af4 100644 --- a/arch/um/sys-x86_64/ptrace.c +++ b/arch/um/sys-x86_64/ptrace.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 2003 PathScale, Inc. | 2 | * Copyright 2003 PathScale, Inc. |
3 | * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
3 | * | 4 | * |
4 | * Licensed under the GPL | 5 | * Licensed under the GPL |
5 | */ | 6 | */ |
@@ -12,17 +13,10 @@ | |||
12 | #include <asm/uaccess.h> | 13 | #include <asm/uaccess.h> |
13 | #include <asm/elf.h> | 14 | #include <asm/elf.h> |
14 | 15 | ||
15 | /* XXX x86_64 */ | 16 | /* |
16 | unsigned long not_ss; | 17 | * determines which flags the user has access to. |
17 | unsigned long not_ds; | 18 | * 1 = access 0 = no access |
18 | unsigned long not_es; | 19 | */ |
19 | |||
20 | #define SC_SS(r) (not_ss) | ||
21 | #define SC_DS(r) (not_ds) | ||
22 | #define SC_ES(r) (not_es) | ||
23 | |||
24 | /* determines which flags the user has access to. */ | ||
25 | /* 1 = access 0 = no access */ | ||
26 | #define FLAG_MASK 0x44dd5UL | 20 | #define FLAG_MASK 0x44dd5UL |
27 | 21 | ||
28 | int putreg(struct task_struct *child, int regno, unsigned long value) | 22 | int putreg(struct task_struct *child, int regno, unsigned long value) |
@@ -66,20 +60,21 @@ int putreg(struct task_struct *child, int regno, unsigned long value) | |||
66 | 60 | ||
67 | int poke_user(struct task_struct *child, long addr, long data) | 61 | int poke_user(struct task_struct *child, long addr, long data) |
68 | { | 62 | { |
69 | if ((addr & 3) || addr < 0) | 63 | if ((addr & 3) || addr < 0) |
70 | return -EIO; | 64 | return -EIO; |
71 | 65 | ||
72 | if (addr < MAX_REG_OFFSET) | 66 | if (addr < MAX_REG_OFFSET) |
73 | return putreg(child, addr, data); | 67 | return putreg(child, addr, data); |
74 | else if((addr >= offsetof(struct user, u_debugreg[0])) && | 68 | else if ((addr >= offsetof(struct user, u_debugreg[0])) && |
75 | (addr <= offsetof(struct user, u_debugreg[7]))){ | 69 | (addr <= offsetof(struct user, u_debugreg[7]))){ |
76 | addr -= offsetof(struct user, u_debugreg[0]); | 70 | addr -= offsetof(struct user, u_debugreg[0]); |
77 | addr = addr >> 2; | 71 | addr = addr >> 2; |
78 | if((addr == 4) || (addr == 5)) return -EIO; | 72 | if ((addr == 4) || (addr == 5)) |
79 | child->thread.arch.debugregs[addr] = data; | 73 | return -EIO; |
80 | return 0; | 74 | child->thread.arch.debugregs[addr] = data; |
81 | } | 75 | return 0; |
82 | return -EIO; | 76 | } |
77 | return -EIO; | ||
83 | } | 78 | } |
84 | 79 | ||
85 | unsigned long getreg(struct task_struct *child, int regno) | 80 | unsigned long getreg(struct task_struct *child, int regno) |
@@ -107,29 +102,22 @@ unsigned long getreg(struct task_struct *child, int regno) | |||
107 | int peek_user(struct task_struct *child, long addr, long data) | 102 | int peek_user(struct task_struct *child, long addr, long data) |
108 | { | 103 | { |
109 | /* read the word at location addr in the USER area. */ | 104 | /* read the word at location addr in the USER area. */ |
110 | unsigned long tmp; | 105 | unsigned long tmp; |
111 | |||
112 | if ((addr & 3) || addr < 0) | ||
113 | return -EIO; | ||
114 | |||
115 | tmp = 0; /* Default return condition */ | ||
116 | if(addr < MAX_REG_OFFSET){ | ||
117 | tmp = getreg(child, addr); | ||
118 | } | ||
119 | else if((addr >= offsetof(struct user, u_debugreg[0])) && | ||
120 | (addr <= offsetof(struct user, u_debugreg[7]))){ | ||
121 | addr -= offsetof(struct user, u_debugreg[0]); | ||
122 | addr = addr >> 2; | ||
123 | tmp = child->thread.arch.debugregs[addr]; | ||
124 | } | ||
125 | return put_user(tmp, (unsigned long *) data); | ||
126 | } | ||
127 | 106 | ||
128 | void arch_switch(void) | 107 | if ((addr & 3) || addr < 0) |
129 | { | 108 | return -EIO; |
130 | /* XXX | 109 | |
131 | printk("arch_switch\n"); | 110 | tmp = 0; /* Default return condition */ |
132 | */ | 111 | if (addr < MAX_REG_OFFSET){ |
112 | tmp = getreg(child, addr); | ||
113 | } | ||
114 | else if ((addr >= offsetof(struct user, u_debugreg[0])) && | ||
115 | (addr <= offsetof(struct user, u_debugreg[7]))){ | ||
116 | addr -= offsetof(struct user, u_debugreg[0]); | ||
117 | addr = addr >> 2; | ||
118 | tmp = child->thread.arch.debugregs[addr]; | ||
119 | } | ||
120 | return put_user(tmp, (unsigned long *) data); | ||
133 | } | 121 | } |
134 | 122 | ||
135 | /* XXX Mostly copied from sys-i386 */ | 123 | /* XXX Mostly copied from sys-i386 */ |
@@ -139,54 +127,68 @@ int is_syscall(unsigned long addr) | |||
139 | int n; | 127 | int n; |
140 | 128 | ||
141 | n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); | 129 | n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); |
142 | if(n){ | 130 | if (n){ |
143 | /* access_process_vm() grants access to vsyscall and stub, | 131 | /* access_process_vm() grants access to vsyscall and stub, |
144 | * while copy_from_user doesn't. Maybe access_process_vm is | 132 | * while copy_from_user doesn't. Maybe access_process_vm is |
145 | * slow, but that doesn't matter, since it will be called only | 133 | * slow, but that doesn't matter, since it will be called only |
146 | * in case of singlestepping, if copy_from_user failed. | 134 | * in case of singlestepping, if copy_from_user failed. |
147 | */ | 135 | */ |
148 | n = access_process_vm(current, addr, &instr, sizeof(instr), 0); | 136 | n = access_process_vm(current, addr, &instr, sizeof(instr), 0); |
149 | if(n != sizeof(instr)) { | 137 | if (n != sizeof(instr)) { |
150 | printk("is_syscall : failed to read instruction from " | 138 | printk("is_syscall : failed to read instruction from " |
151 | "0x%lx\n", addr); | 139 | "0x%lx\n", addr); |
152 | return(1); | 140 | return 1; |
153 | } | 141 | } |
154 | } | 142 | } |
155 | /* sysenter */ | 143 | /* sysenter */ |
156 | return(instr == 0x050f); | 144 | return instr == 0x050f; |
157 | } | 145 | } |
158 | 146 | ||
159 | int get_fpregs(unsigned long buf, struct task_struct *child) | 147 | int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) |
160 | { | 148 | { |
161 | panic("get_fpregs"); | 149 | int err, n, cpu = ((struct thread_info *) child->stack)->cpu; |
162 | return(0); | 150 | long fpregs[HOST_FP_SIZE]; |
163 | } | ||
164 | 151 | ||
165 | int set_fpregs(unsigned long buf, struct task_struct *child) | 152 | BUG_ON(sizeof(*buf) != sizeof(fpregs)); |
166 | { | 153 | err = save_fp_registers(userspace_pid[cpu], fpregs); |
167 | panic("set_fpregs"); | 154 | if (err) |
168 | return(0); | 155 | return err; |
156 | |||
157 | n = copy_to_user((void *) buf, fpregs, sizeof(fpregs)); | ||
158 | if(n > 0) | ||
159 | return -EFAULT; | ||
160 | |||
161 | return n; | ||
169 | } | 162 | } |
170 | 163 | ||
171 | int get_fpxregs(unsigned long buf, struct task_struct *tsk) | 164 | int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) |
172 | { | 165 | { |
173 | panic("get_fpxregs"); | 166 | int n, cpu = ((struct thread_info *) child->stack)->cpu; |
174 | return(0); | 167 | long fpregs[HOST_FP_SIZE]; |
168 | |||
169 | BUG_ON(sizeof(*buf) != sizeof(fpregs)); | ||
170 | n = copy_from_user(fpregs, (void *) buf, sizeof(fpregs)); | ||
171 | if (n > 0) | ||
172 | return -EFAULT; | ||
173 | |||
174 | return restore_fp_registers(userspace_pid[cpu], fpregs); | ||
175 | } | 175 | } |
176 | 176 | ||
177 | int set_fpxregs(unsigned long buf, struct task_struct *tsk) | 177 | long subarch_ptrace(struct task_struct *child, long request, long addr, |
178 | long data) | ||
178 | { | 179 | { |
179 | panic("set_fxpregs"); | 180 | int ret = -EIO; |
180 | return(0); | ||
181 | } | ||
182 | 181 | ||
183 | /* | 182 | switch (request) { |
184 | * Overrides for Emacs so that we follow Linus's tabbing style. | 183 | case PTRACE_GETFPXREGS: /* Get the child FPU state. */ |
185 | * Emacs will notice this stuff at the end of the file and automatically | 184 | ret = get_fpregs((struct user_i387_struct __user *) data, |
186 | * adjust the settings for this buffer only. This must remain at the end | 185 | child); |
187 | * of the file. | 186 | break; |
188 | * --------------------------------------------------------------------------- | 187 | case PTRACE_SETFPXREGS: /* Set the child FPU state. */ |
189 | * Local variables: | 188 | ret = set_fpregs((struct user_i387_struct __user *) data, |
190 | * c-file-style: "linux" | 189 | child); |
191 | * End: | 190 | break; |
192 | */ | 191 | } |
192 | |||
193 | return ret; | ||
194 | } | ||
diff --git a/arch/um/sys-x86_64/sigcontext.c b/arch/um/sys-x86_64/sigcontext.c deleted file mode 100644 index c88e64def6f2..000000000000 --- a/arch/um/sys-x86_64/sigcontext.c +++ /dev/null | |||
@@ -1,39 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2003 PathScale, Inc. | ||
3 | * | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include <stdio.h> | ||
8 | #include <string.h> | ||
9 | #include <signal.h> | ||
10 | #include "user.h" | ||
11 | |||
12 | void sc_to_sc(void *to_ptr, void *from_ptr) | ||
13 | { | ||
14 | struct sigcontext *to = to_ptr, *from = from_ptr; | ||
15 | int size = sizeof(*to); /* + sizeof(struct _fpstate); */ | ||
16 | |||
17 | memcpy(to, from, size); | ||
18 | if(from->fpstate != NULL) | ||
19 | to->fpstate = (struct _fpstate *) (to + 1); | ||
20 | |||
21 | to->fpstate = NULL; | ||
22 | } | ||
23 | |||
24 | unsigned long *sc_sigmask(void *sc_ptr) | ||
25 | { | ||
26 | struct sigcontext *sc = sc_ptr; | ||
27 | |||
28 | return(&sc->oldmask); | ||
29 | } | ||
30 | |||
31 | /* Overrides for Emacs so that we follow Linus's tabbing style. | ||
32 | * Emacs will notice this stuff at the end of the file and automatically | ||
33 | * adjust the settings for this buffer only. This must remain at the end | ||
34 | * of the file. | ||
35 | * --------------------------------------------------------------------------- | ||
36 | * Local variables: | ||
37 | * c-file-style: "linux" | ||
38 | * End: | ||
39 | */ | ||
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c index fe8ec04d35bb..1778d33808f4 100644 --- a/arch/um/sys-x86_64/signal.c +++ b/arch/um/sys-x86_64/signal.c | |||
@@ -1,111 +1,121 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2003 PathScale, Inc. | 2 | * Copyright (C) 2003 PathScale, Inc. |
3 | * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
3 | * Licensed under the GPL | 4 | * Licensed under the GPL |
4 | */ | 5 | */ |
5 | 6 | ||
6 | #include "linux/stddef.h" | ||
7 | #include "linux/errno.h" | ||
8 | #include "linux/personality.h" | 7 | #include "linux/personality.h" |
9 | #include "linux/ptrace.h" | 8 | #include "linux/ptrace.h" |
10 | #include "asm/current.h" | 9 | #include "asm/unistd.h" |
11 | #include "asm/uaccess.h" | 10 | #include "asm/uaccess.h" |
12 | #include "asm/sigcontext.h" | 11 | #include "asm/ucontext.h" |
13 | #include "asm/ptrace.h" | ||
14 | #include "asm/arch/ucontext.h" | ||
15 | #include "choose-mode.h" | ||
16 | #include "sysdep/ptrace.h" | ||
17 | #include "frame_kern.h" | 12 | #include "frame_kern.h" |
18 | |||
19 | #ifdef CONFIG_MODE_SKAS | ||
20 | |||
21 | #include "skas.h" | 13 | #include "skas.h" |
22 | 14 | ||
23 | void copy_sc(union uml_pt_regs *regs, void *from) | 15 | void copy_sc(struct uml_pt_regs *regs, void *from) |
24 | { | 16 | { |
25 | struct sigcontext *sc = from; | 17 | struct sigcontext *sc = from; |
26 | 18 | ||
27 | #define GETREG(regs, regno, sc, regname) \ | 19 | #define GETREG(regs, regno, sc, regname) \ |
28 | (regs)->skas.regs[(regno) / sizeof(unsigned long)] = (sc)->regname | 20 | (regs)->gp[(regno) / sizeof(unsigned long)] = (sc)->regname |
29 | 21 | ||
30 | GETREG(regs, R8, sc, r8); | 22 | GETREG(regs, R8, sc, r8); |
31 | GETREG(regs, R9, sc, r9); | 23 | GETREG(regs, R9, sc, r9); |
32 | GETREG(regs, R10, sc, r10); | 24 | GETREG(regs, R10, sc, r10); |
33 | GETREG(regs, R11, sc, r11); | 25 | GETREG(regs, R11, sc, r11); |
34 | GETREG(regs, R12, sc, r12); | 26 | GETREG(regs, R12, sc, r12); |
35 | GETREG(regs, R13, sc, r13); | 27 | GETREG(regs, R13, sc, r13); |
36 | GETREG(regs, R14, sc, r14); | 28 | GETREG(regs, R14, sc, r14); |
37 | GETREG(regs, R15, sc, r15); | 29 | GETREG(regs, R15, sc, r15); |
38 | GETREG(regs, RDI, sc, rdi); | 30 | GETREG(regs, RDI, sc, rdi); |
39 | GETREG(regs, RSI, sc, rsi); | 31 | GETREG(regs, RSI, sc, rsi); |
40 | GETREG(regs, RBP, sc, rbp); | 32 | GETREG(regs, RBP, sc, rbp); |
41 | GETREG(regs, RBX, sc, rbx); | 33 | GETREG(regs, RBX, sc, rbx); |
42 | GETREG(regs, RDX, sc, rdx); | 34 | GETREG(regs, RDX, sc, rdx); |
43 | GETREG(regs, RAX, sc, rax); | 35 | GETREG(regs, RAX, sc, rax); |
44 | GETREG(regs, RCX, sc, rcx); | 36 | GETREG(regs, RCX, sc, rcx); |
45 | GETREG(regs, RSP, sc, rsp); | 37 | GETREG(regs, RSP, sc, rsp); |
46 | GETREG(regs, RIP, sc, rip); | 38 | GETREG(regs, RIP, sc, rip); |
47 | GETREG(regs, EFLAGS, sc, eflags); | 39 | GETREG(regs, EFLAGS, sc, eflags); |
48 | GETREG(regs, CS, sc, cs); | 40 | GETREG(regs, CS, sc, cs); |
49 | 41 | ||
50 | #undef GETREG | 42 | #undef GETREG |
51 | } | 43 | } |
52 | 44 | ||
53 | static int copy_sc_from_user_skas(struct pt_regs *regs, | 45 | static int copy_sc_from_user(struct pt_regs *regs, |
54 | struct sigcontext __user *from) | 46 | struct sigcontext __user *from, |
47 | struct _fpstate __user *fpp) | ||
55 | { | 48 | { |
56 | int err = 0; | 49 | struct user_i387_struct fp; |
57 | 50 | int err = 0; | |
58 | #define GETREG(regs, regno, sc, regname) \ | 51 | |
59 | __get_user((regs)->regs.skas.regs[(regno) / sizeof(unsigned long)], \ | 52 | #define GETREG(regs, regno, sc, regname) \ |
60 | &(sc)->regname) | 53 | __get_user((regs)->regs.gp[(regno) / sizeof(unsigned long)], \ |
61 | 54 | &(sc)->regname) | |
62 | err |= GETREG(regs, R8, from, r8); | 55 | |
63 | err |= GETREG(regs, R9, from, r9); | 56 | err |= GETREG(regs, R8, from, r8); |
64 | err |= GETREG(regs, R10, from, r10); | 57 | err |= GETREG(regs, R9, from, r9); |
65 | err |= GETREG(regs, R11, from, r11); | 58 | err |= GETREG(regs, R10, from, r10); |
66 | err |= GETREG(regs, R12, from, r12); | 59 | err |= GETREG(regs, R11, from, r11); |
67 | err |= GETREG(regs, R13, from, r13); | 60 | err |= GETREG(regs, R12, from, r12); |
68 | err |= GETREG(regs, R14, from, r14); | 61 | err |= GETREG(regs, R13, from, r13); |
69 | err |= GETREG(regs, R15, from, r15); | 62 | err |= GETREG(regs, R14, from, r14); |
70 | err |= GETREG(regs, RDI, from, rdi); | 63 | err |= GETREG(regs, R15, from, r15); |
71 | err |= GETREG(regs, RSI, from, rsi); | 64 | err |= GETREG(regs, RDI, from, rdi); |
72 | err |= GETREG(regs, RBP, from, rbp); | 65 | err |= GETREG(regs, RSI, from, rsi); |
73 | err |= GETREG(regs, RBX, from, rbx); | 66 | err |= GETREG(regs, RBP, from, rbp); |
74 | err |= GETREG(regs, RDX, from, rdx); | 67 | err |= GETREG(regs, RBX, from, rbx); |
75 | err |= GETREG(regs, RAX, from, rax); | 68 | err |= GETREG(regs, RDX, from, rdx); |
76 | err |= GETREG(regs, RCX, from, rcx); | 69 | err |= GETREG(regs, RAX, from, rax); |
77 | err |= GETREG(regs, RSP, from, rsp); | 70 | err |= GETREG(regs, RCX, from, rcx); |
78 | err |= GETREG(regs, RIP, from, rip); | 71 | err |= GETREG(regs, RSP, from, rsp); |
79 | err |= GETREG(regs, EFLAGS, from, eflags); | 72 | err |= GETREG(regs, RIP, from, rip); |
80 | err |= GETREG(regs, CS, from, cs); | 73 | err |= GETREG(regs, EFLAGS, from, eflags); |
74 | err |= GETREG(regs, CS, from, cs); | ||
75 | if (err) | ||
76 | return 1; | ||
81 | 77 | ||
82 | #undef GETREG | 78 | #undef GETREG |
83 | 79 | ||
84 | return err; | 80 | err = copy_from_user(&fp, fpp, sizeof(struct user_i387_struct)); |
81 | if (err) | ||
82 | return 1; | ||
83 | |||
84 | err = restore_fp_registers(userspace_pid[current_thread->cpu], | ||
85 | (unsigned long *) &fp); | ||
86 | if (err < 0) { | ||
87 | printk(KERN_ERR "copy_sc_from_user - " | ||
88 | "restore_fp_registers failed, errno = %d\n", | ||
89 | -err); | ||
90 | return 1; | ||
91 | } | ||
92 | |||
93 | return 0; | ||
85 | } | 94 | } |
86 | 95 | ||
87 | int copy_sc_to_user_skas(struct sigcontext __user *to, | 96 | static int copy_sc_to_user(struct sigcontext __user *to, |
88 | struct _fpstate __user *to_fp, | 97 | struct _fpstate __user *to_fp, struct pt_regs *regs, |
89 | struct pt_regs *regs, unsigned long mask, | 98 | unsigned long mask, unsigned long sp) |
90 | unsigned long sp) | ||
91 | { | 99 | { |
92 | struct faultinfo * fi = ¤t->thread.arch.faultinfo; | 100 | struct faultinfo * fi = ¤t->thread.arch.faultinfo; |
101 | struct user_i387_struct fp; | ||
93 | int err = 0; | 102 | int err = 0; |
94 | 103 | ||
95 | err |= __put_user(0, &to->gs); | 104 | err |= __put_user(0, &to->gs); |
96 | err |= __put_user(0, &to->fs); | 105 | err |= __put_user(0, &to->fs); |
97 | 106 | ||
98 | #define PUTREG(regs, regno, sc, regname) \ | 107 | #define PUTREG(regs, regno, sc, regname) \ |
99 | __put_user((regs)->regs.skas.regs[(regno) / sizeof(unsigned long)], \ | 108 | __put_user((regs)->regs.gp[(regno) / sizeof(unsigned long)], \ |
100 | &(sc)->regname) | 109 | &(sc)->regname) |
101 | 110 | ||
102 | err |= PUTREG(regs, RDI, to, rdi); | 111 | err |= PUTREG(regs, RDI, to, rdi); |
103 | err |= PUTREG(regs, RSI, to, rsi); | 112 | err |= PUTREG(regs, RSI, to, rsi); |
104 | err |= PUTREG(regs, RBP, to, rbp); | 113 | err |= PUTREG(regs, RBP, to, rbp); |
105 | /* Must use orignal RSP, which is passed in, rather than what's in | 114 | /* |
106 | * the pt_regs, because that's already been updated to point at the | 115 | * Must use orignal RSP, which is passed in, rather than what's in |
107 | * signal frame. | 116 | * the pt_regs, because that's already been updated to point at the |
108 | */ | 117 | * signal frame. |
118 | */ | ||
109 | err |= __put_user(sp, &to->rsp); | 119 | err |= __put_user(sp, &to->rsp); |
110 | err |= PUTREG(regs, RBX, to, rbx); | 120 | err |= PUTREG(regs, RBX, to, rbx); |
111 | err |= PUTREG(regs, RDX, to, rdx); | 121 | err |= PUTREG(regs, RDX, to, rdx); |
@@ -121,91 +131,38 @@ int copy_sc_to_user_skas(struct sigcontext __user *to, | |||
121 | err |= PUTREG(regs, R15, to, r15); | 131 | err |= PUTREG(regs, R15, to, r15); |
122 | err |= PUTREG(regs, CS, to, cs); /* XXX x86_64 doesn't do this */ | 132 | err |= PUTREG(regs, CS, to, cs); /* XXX x86_64 doesn't do this */ |
123 | 133 | ||
124 | err |= __put_user(fi->cr2, &to->cr2); | 134 | err |= __put_user(fi->cr2, &to->cr2); |
125 | err |= __put_user(fi->error_code, &to->err); | 135 | err |= __put_user(fi->error_code, &to->err); |
126 | err |= __put_user(fi->trap_no, &to->trapno); | 136 | err |= __put_user(fi->trap_no, &to->trapno); |
127 | 137 | ||
128 | err |= PUTREG(regs, RIP, to, rip); | 138 | err |= PUTREG(regs, RIP, to, rip); |
129 | err |= PUTREG(regs, EFLAGS, to, eflags); | 139 | err |= PUTREG(regs, EFLAGS, to, eflags); |
130 | #undef PUTREG | 140 | #undef PUTREG |
131 | 141 | ||
132 | err |= __put_user(mask, &to->oldmask); | 142 | err |= __put_user(mask, &to->oldmask); |
133 | 143 | if (err) | |
134 | return(err); | 144 | return 1; |
135 | } | 145 | |
136 | 146 | err = save_fp_registers(userspace_pid[current_thread->cpu], | |
137 | #endif | 147 | (unsigned long *) &fp); |
138 | 148 | if (err < 0) { | |
139 | #ifdef CONFIG_MODE_TT | 149 | printk(KERN_ERR "copy_sc_from_user - restore_fp_registers " |
140 | int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from, | 150 | "failed, errno = %d\n", -err); |
141 | int fpsize) | 151 | return 1; |
142 | { | ||
143 | struct _fpstate *to_fp; | ||
144 | struct _fpstate __user *from_fp; | ||
145 | unsigned long sigs; | ||
146 | int err; | ||
147 | |||
148 | to_fp = to->fpstate; | ||
149 | sigs = to->oldmask; | ||
150 | err = copy_from_user(to, from, sizeof(*to)); | ||
151 | from_fp = to->fpstate; | ||
152 | to->fpstate = to_fp; | ||
153 | to->oldmask = sigs; | ||
154 | if(to_fp != NULL) | ||
155 | err |= copy_from_user(to_fp, from_fp, fpsize); | ||
156 | return(err); | ||
157 | } | ||
158 | |||
159 | int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp, | ||
160 | struct sigcontext *from, int fpsize, unsigned long sp) | ||
161 | { | ||
162 | struct _fpstate __user *to_fp; | ||
163 | struct _fpstate *from_fp; | ||
164 | int err; | ||
165 | |||
166 | to_fp = (fp ? fp : (struct _fpstate __user *) (to + 1)); | ||
167 | from_fp = from->fpstate; | ||
168 | err = copy_to_user(to, from, sizeof(*to)); | ||
169 | /* The SP in the sigcontext is the updated one for the signal | ||
170 | * delivery. The sp passed in is the original, and this needs | ||
171 | * to be restored, so we stick it in separately. | ||
172 | */ | ||
173 | err |= copy_to_user(&SC_SP(to), &sp, sizeof(sp)); | ||
174 | |||
175 | if(from_fp != NULL){ | ||
176 | err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate)); | ||
177 | err |= copy_to_user(to_fp, from_fp, fpsize); | ||
178 | } | 152 | } |
179 | return err; | ||
180 | } | ||
181 | 153 | ||
182 | #endif | 154 | if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct))) |
183 | 155 | return 1; | |
184 | static int copy_sc_from_user(struct pt_regs *to, void __user *from) | ||
185 | { | ||
186 | int ret; | ||
187 | |||
188 | ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, | ||
189 | sizeof(struct _fpstate)), | ||
190 | copy_sc_from_user_skas(to, from)); | ||
191 | return(ret); | ||
192 | } | ||
193 | 156 | ||
194 | static int copy_sc_to_user(struct sigcontext __user *to, | 157 | return err; |
195 | struct _fpstate __user *fp, | ||
196 | struct pt_regs *from, unsigned long mask, | ||
197 | unsigned long sp) | ||
198 | { | ||
199 | return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), | ||
200 | sizeof(*fp), sp), | ||
201 | copy_sc_to_user_skas(to, fp, from, mask, sp))); | ||
202 | } | 158 | } |
203 | 159 | ||
204 | struct rt_sigframe | 160 | struct rt_sigframe |
205 | { | 161 | { |
206 | char __user *pretcode; | 162 | char __user *pretcode; |
207 | struct ucontext uc; | 163 | struct ucontext uc; |
208 | struct siginfo info; | 164 | struct siginfo info; |
165 | struct _fpstate fpstate; | ||
209 | }; | 166 | }; |
210 | 167 | ||
211 | #define round_down(m, n) (((m) / (n)) * (n)) | 168 | #define round_down(m, n) (((m) / (n)) * (n)) |
@@ -215,7 +172,6 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
215 | siginfo_t *info, sigset_t *set) | 172 | siginfo_t *info, sigset_t *set) |
216 | { | 173 | { |
217 | struct rt_sigframe __user *frame; | 174 | struct rt_sigframe __user *frame; |
218 | struct _fpstate __user *fp = NULL; | ||
219 | unsigned long save_sp = PT_REGS_RSP(regs); | 175 | unsigned long save_sp = PT_REGS_RSP(regs); |
220 | int err = 0; | 176 | int err = 0; |
221 | struct task_struct *me = current; | 177 | struct task_struct *me = current; |
@@ -223,15 +179,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
223 | frame = (struct rt_sigframe __user *) | 179 | frame = (struct rt_sigframe __user *) |
224 | round_down(stack_top - sizeof(struct rt_sigframe), 16); | 180 | round_down(stack_top - sizeof(struct rt_sigframe), 16); |
225 | /* Subtract 128 for a red zone and 8 for proper alignment */ | 181 | /* Subtract 128 for a red zone and 8 for proper alignment */ |
226 | frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8); | 182 | frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8); |
227 | |||
228 | if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) | ||
229 | goto out; | ||
230 | 183 | ||
231 | #if 0 /* XXX */ | ||
232 | if (save_i387(fp) < 0) | ||
233 | err |= -1; | ||
234 | #endif | ||
235 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 184 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
236 | goto out; | 185 | goto out; |
237 | 186 | ||
@@ -241,7 +190,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
241 | goto out; | 190 | goto out; |
242 | } | 191 | } |
243 | 192 | ||
244 | /* Update SP now because the page fault handler refuses to extend | 193 | /* |
194 | * Update SP now because the page fault handler refuses to extend | ||
245 | * the stack if the faulting address is too far below the current | 195 | * the stack if the faulting address is too far below the current |
246 | * SP, which frame now certainly is. If there's an error, the original | 196 | * SP, which frame now certainly is. If there's an error, the original |
247 | * value is restored on the way out. | 197 | * value is restored on the way out. |
@@ -258,9 +208,9 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
258 | err |= __put_user(sas_ss_flags(save_sp), | 208 | err |= __put_user(sas_ss_flags(save_sp), |
259 | &frame->uc.uc_stack.ss_flags); | 209 | &frame->uc.uc_stack.ss_flags); |
260 | err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); | 210 | err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); |
261 | err |= copy_sc_to_user(&frame->uc.uc_mcontext, fp, regs, set->sig[0], | 211 | err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs, |
262 | save_sp); | 212 | set->sig[0], save_sp); |
263 | err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); | 213 | err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate); |
264 | if (sizeof(*set) == 16) { | 214 | if (sizeof(*set) == 16) { |
265 | __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); | 215 | __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); |
266 | __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); | 216 | __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); |
@@ -269,8 +219,10 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
269 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, | 219 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, |
270 | sizeof(*set)); | 220 | sizeof(*set)); |
271 | 221 | ||
272 | /* Set up to return from userspace. If provided, use a stub | 222 | /* |
273 | already in userspace. */ | 223 | * Set up to return from userspace. If provided, use a stub |
224 | * already in userspace. | ||
225 | */ | ||
274 | /* x86-64 should always use SA_RESTORER. */ | 226 | /* x86-64 should always use SA_RESTORER. */ |
275 | if (ka->sa.sa_flags & SA_RESTORER) | 227 | if (ka->sa.sa_flags & SA_RESTORER) |
276 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | 228 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); |
@@ -292,8 +244,10 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
292 | /* In case the signal handler was declared without prototypes */ | 244 | /* In case the signal handler was declared without prototypes */ |
293 | PT_REGS_RAX(regs) = 0; | 245 | PT_REGS_RAX(regs) = 0; |
294 | 246 | ||
295 | /* This also works for non SA_SIGINFO handlers because they expect the | 247 | /* |
296 | next argument after the signal number on the stack. */ | 248 | * This also works for non SA_SIGINFO handlers because they expect the |
249 | * next argument after the signal number on the stack. | ||
250 | */ | ||
297 | PT_REGS_RSI(regs) = (unsigned long) &frame->info; | 251 | PT_REGS_RSI(regs) = (unsigned long) &frame->info; |
298 | PT_REGS_RDX(regs) = (unsigned long) &frame->uc; | 252 | PT_REGS_RDX(regs) = (unsigned long) &frame->uc; |
299 | PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler; | 253 | PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler; |
@@ -313,7 +267,7 @@ long sys_rt_sigreturn(struct pt_regs *regs) | |||
313 | struct ucontext __user *uc = &frame->uc; | 267 | struct ucontext __user *uc = &frame->uc; |
314 | sigset_t set; | 268 | sigset_t set; |
315 | 269 | ||
316 | if(copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) | 270 | if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) |
317 | goto segfault; | 271 | goto segfault; |
318 | 272 | ||
319 | sigdelsetmask(&set, ~_BLOCKABLE); | 273 | sigdelsetmask(&set, ~_BLOCKABLE); |
@@ -323,24 +277,15 @@ long sys_rt_sigreturn(struct pt_regs *regs) | |||
323 | recalc_sigpending(); | 277 | recalc_sigpending(); |
324 | spin_unlock_irq(¤t->sighand->siglock); | 278 | spin_unlock_irq(¤t->sighand->siglock); |
325 | 279 | ||
326 | if(copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext)) | 280 | if (copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext, |
281 | &frame->fpstate)) | ||
327 | goto segfault; | 282 | goto segfault; |
328 | 283 | ||
329 | /* Avoid ERESTART handling */ | 284 | /* Avoid ERESTART handling */ |
330 | PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; | 285 | PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; |
331 | return(PT_REGS_SYSCALL_RET(¤t->thread.regs)); | 286 | return PT_REGS_SYSCALL_RET(¤t->thread.regs); |
332 | 287 | ||
333 | segfault: | 288 | segfault: |
334 | force_sig(SIGSEGV, current); | 289 | force_sig(SIGSEGV, current); |
335 | return 0; | 290 | return 0; |
336 | } | 291 | } |
337 | /* | ||
338 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
339 | * Emacs will notice this stuff at the end of the file and automatically | ||
340 | * adjust the settings for this buffer only. This must remain at the end | ||
341 | * of the file. | ||
342 | * --------------------------------------------------------------------------- | ||
343 | * Local variables: | ||
344 | * c-file-style: "linux" | ||
345 | * End: | ||
346 | */ | ||
diff --git a/arch/um/sys-x86_64/stub.S b/arch/um/sys-x86_64/stub.S index 03c279735784..4afe204a6af7 100644 --- a/arch/um/sys-x86_64/stub.S +++ b/arch/um/sys-x86_64/stub.S | |||
@@ -1,4 +1,5 @@ | |||
1 | #include "uml-config.h" | 1 | #include "uml-config.h" |
2 | #include "as-layout.h" | ||
2 | 3 | ||
3 | .globl syscall_stub | 4 | .globl syscall_stub |
4 | .section .__syscall_stub, "x" | 5 | .section .__syscall_stub, "x" |
@@ -7,18 +8,18 @@ syscall_stub: | |||
7 | /* We don't have 64-bit constants, so this constructs the address | 8 | /* We don't have 64-bit constants, so this constructs the address |
8 | * we need. | 9 | * we need. |
9 | */ | 10 | */ |
10 | movq $(UML_CONFIG_STUB_DATA >> 32), %rbx | 11 | movq $(ASM_STUB_DATA >> 32), %rbx |
11 | salq $32, %rbx | 12 | salq $32, %rbx |
12 | movq $(UML_CONFIG_STUB_DATA & 0xffffffff), %rcx | 13 | movq $(ASM_STUB_DATA & 0xffffffff), %rcx |
13 | or %rcx, %rbx | 14 | or %rcx, %rbx |
14 | movq %rax, (%rbx) | 15 | movq %rax, (%rbx) |
15 | int3 | 16 | int3 |
16 | 17 | ||
17 | .globl batch_syscall_stub | 18 | .globl batch_syscall_stub |
18 | batch_syscall_stub: | 19 | batch_syscall_stub: |
19 | mov $(UML_CONFIG_STUB_DATA >> 32), %rbx | 20 | mov $(ASM_STUB_DATA >> 32), %rbx |
20 | sal $32, %rbx | 21 | sal $32, %rbx |
21 | mov $(UML_CONFIG_STUB_DATA & 0xffffffff), %rax | 22 | mov $(ASM_STUB_DATA & 0xffffffff), %rax |
22 | or %rax, %rbx | 23 | or %rax, %rbx |
23 | /* load pointer to first operation */ | 24 | /* load pointer to first operation */ |
24 | mov %rbx, %rsp | 25 | mov %rbx, %rsp |
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c index 652fa34c2cd3..3afb590f0072 100644 --- a/arch/um/sys-x86_64/stub_segv.c +++ b/arch/um/sys-x86_64/stub_segv.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <stddef.h> | 6 | #include <stddef.h> |
7 | #include <signal.h> | 7 | #include <signal.h> |
8 | #include <asm/unistd.h> | 8 | #include <asm/unistd.h> |
9 | #include "as-layout.h" | ||
9 | #include "uml-config.h" | 10 | #include "uml-config.h" |
10 | #include "sysdep/sigcontext.h" | 11 | #include "sysdep/sigcontext.h" |
11 | #include "sysdep/faultinfo.h" | 12 | #include "sysdep/faultinfo.h" |
@@ -33,7 +34,7 @@ stub_segv_handler(int sig) | |||
33 | int pid; | 34 | int pid; |
34 | 35 | ||
35 | __asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :); | 36 | __asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :); |
36 | GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), | 37 | GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), |
37 | &uc->uc_mcontext); | 38 | &uc->uc_mcontext); |
38 | 39 | ||
39 | pid = stub_syscall0(__NR_getpid); | 40 | pid = stub_syscall0(__NR_getpid); |
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c index b3f6350cac44..86f6b18410ee 100644 --- a/arch/um/sys-x86_64/syscalls.c +++ b/arch/um/sys-x86_64/syscalls.c | |||
@@ -1,70 +1,36 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | ||
2 | * Copyright 2003 PathScale, Inc. | 3 | * Copyright 2003 PathScale, Inc. |
3 | * | 4 | * |
4 | * Licensed under the GPL | 5 | * Licensed under the GPL |
5 | */ | 6 | */ |
6 | 7 | ||
7 | #include "linux/linkage.h" | 8 | #include "linux/linkage.h" |
8 | #include "linux/slab.h" | ||
9 | #include "linux/shm.h" | ||
10 | #include "linux/utsname.h" | ||
11 | #include "linux/personality.h" | 9 | #include "linux/personality.h" |
12 | #include "asm/uaccess.h" | 10 | #include "linux/utsname.h" |
13 | #define __FRAME_OFFSETS | ||
14 | #include "asm/ptrace.h" | ||
15 | #include "asm/unistd.h" | ||
16 | #include "asm/prctl.h" /* XXX This should get the constants from libc */ | 11 | #include "asm/prctl.h" /* XXX This should get the constants from libc */ |
17 | #include "choose-mode.h" | 12 | #include "asm/uaccess.h" |
18 | #include "kern.h" | ||
19 | #include "os.h" | 13 | #include "os.h" |
20 | 14 | ||
21 | asmlinkage long sys_uname64(struct new_utsname __user * name) | 15 | asmlinkage long sys_uname64(struct new_utsname __user * name) |
22 | { | 16 | { |
23 | int err; | 17 | int err; |
18 | |||
24 | down_read(&uts_sem); | 19 | down_read(&uts_sem); |
25 | err = copy_to_user(name, utsname(), sizeof (*name)); | 20 | err = copy_to_user(name, utsname(), sizeof (*name)); |
26 | up_read(&uts_sem); | 21 | up_read(&uts_sem); |
22 | |||
27 | if (personality(current->personality) == PER_LINUX32) | 23 | if (personality(current->personality) == PER_LINUX32) |
28 | err |= copy_to_user(&name->machine, "i686", 5); | 24 | err |= copy_to_user(&name->machine, "i686", 5); |
29 | return err ? -EFAULT : 0; | ||
30 | } | ||
31 | |||
32 | #ifdef CONFIG_MODE_TT | ||
33 | extern long arch_prctl(int code, unsigned long addr); | ||
34 | |||
35 | static long arch_prctl_tt(int code, unsigned long addr) | ||
36 | { | ||
37 | unsigned long tmp; | ||
38 | long ret; | ||
39 | |||
40 | switch(code){ | ||
41 | case ARCH_SET_GS: | ||
42 | case ARCH_SET_FS: | ||
43 | ret = arch_prctl(code, addr); | ||
44 | break; | ||
45 | case ARCH_GET_FS: | ||
46 | case ARCH_GET_GS: | ||
47 | ret = arch_prctl(code, (unsigned long) &tmp); | ||
48 | if(!ret) | ||
49 | ret = put_user(tmp, (long __user *)addr); | ||
50 | break; | ||
51 | default: | ||
52 | ret = -EINVAL; | ||
53 | break; | ||
54 | } | ||
55 | 25 | ||
56 | return(ret); | 26 | return err ? -EFAULT : 0; |
57 | } | 27 | } |
58 | #endif | ||
59 | |||
60 | #ifdef CONFIG_MODE_SKAS | ||
61 | 28 | ||
62 | long arch_prctl_skas(struct task_struct *task, int code, | 29 | long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) |
63 | unsigned long __user *addr) | ||
64 | { | 30 | { |
65 | unsigned long *ptr = addr, tmp; | 31 | unsigned long *ptr = addr, tmp; |
66 | long ret; | 32 | long ret; |
67 | int pid = task->mm->context.skas.id.u.pid; | 33 | int pid = task->mm->context.id.u.pid; |
68 | 34 | ||
69 | /* | 35 | /* |
70 | * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to | 36 | * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to |
@@ -79,52 +45,50 @@ long arch_prctl_skas(struct task_struct *task, int code, | |||
79 | * arch_prctl is run on the host, then the registers are read | 45 | * arch_prctl is run on the host, then the registers are read |
80 | * back. | 46 | * back. |
81 | */ | 47 | */ |
82 | switch(code){ | 48 | switch (code) { |
83 | case ARCH_SET_FS: | 49 | case ARCH_SET_FS: |
84 | case ARCH_SET_GS: | 50 | case ARCH_SET_GS: |
85 | restore_registers(pid, ¤t->thread.regs.regs); | 51 | restore_registers(pid, ¤t->thread.regs.regs); |
86 | break; | 52 | break; |
87 | case ARCH_GET_FS: | 53 | case ARCH_GET_FS: |
88 | case ARCH_GET_GS: | 54 | case ARCH_GET_GS: |
89 | /* | 55 | /* |
90 | * With these two, we read to a local pointer and | 56 | * With these two, we read to a local pointer and |
91 | * put_user it to the userspace pointer that we were | 57 | * put_user it to the userspace pointer that we were |
92 | * given. If addr isn't valid (because it hasn't been | 58 | * given. If addr isn't valid (because it hasn't been |
93 | * faulted in or is just bogus), we want put_user to | 59 | * faulted in or is just bogus), we want put_user to |
94 | * fault it in (or return -EFAULT) instead of having | 60 | * fault it in (or return -EFAULT) instead of having |
95 | * the host return -EFAULT. | 61 | * the host return -EFAULT. |
96 | */ | 62 | */ |
97 | ptr = &tmp; | 63 | ptr = &tmp; |
98 | } | 64 | } |
99 | 65 | ||
100 | ret = os_arch_prctl(pid, code, ptr); | 66 | ret = os_arch_prctl(pid, code, ptr); |
101 | if(ret) | 67 | if (ret) |
102 | return ret; | 68 | return ret; |
103 | 69 | ||
104 | switch(code){ | 70 | switch (code) { |
105 | case ARCH_SET_FS: | 71 | case ARCH_SET_FS: |
106 | current->thread.arch.fs = (unsigned long) ptr; | 72 | current->thread.arch.fs = (unsigned long) ptr; |
107 | save_registers(pid, ¤t->thread.regs.regs); | 73 | save_registers(pid, ¤t->thread.regs.regs); |
108 | break; | 74 | break; |
109 | case ARCH_SET_GS: | 75 | case ARCH_SET_GS: |
110 | save_registers(pid, ¤t->thread.regs.regs); | 76 | save_registers(pid, ¤t->thread.regs.regs); |
111 | break; | 77 | break; |
112 | case ARCH_GET_FS: | 78 | case ARCH_GET_FS: |
113 | ret = put_user(tmp, addr); | 79 | ret = put_user(tmp, addr); |
114 | break; | 80 | break; |
115 | case ARCH_GET_GS: | 81 | case ARCH_GET_GS: |
116 | ret = put_user(tmp, addr); | 82 | ret = put_user(tmp, addr); |
117 | break; | 83 | break; |
118 | } | 84 | } |
119 | 85 | ||
120 | return ret; | 86 | return ret; |
121 | } | 87 | } |
122 | #endif | ||
123 | 88 | ||
124 | long sys_arch_prctl(int code, unsigned long addr) | 89 | long sys_arch_prctl(int code, unsigned long addr) |
125 | { | 90 | { |
126 | return CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, current, code, | 91 | return arch_prctl(current, code, (unsigned long __user *) addr); |
127 | (unsigned long __user *) addr); | ||
128 | } | 92 | } |
129 | 93 | ||
130 | long sys_clone(unsigned long clone_flags, unsigned long newsp, | 94 | long sys_clone(unsigned long clone_flags, unsigned long newsp, |
@@ -141,10 +105,10 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp, | |||
141 | return ret; | 105 | return ret; |
142 | } | 106 | } |
143 | 107 | ||
144 | void arch_switch_to_skas(struct task_struct *from, struct task_struct *to) | 108 | void arch_switch_to(struct task_struct *from, struct task_struct *to) |
145 | { | 109 | { |
146 | if((to->thread.arch.fs == 0) || (to->mm == NULL)) | 110 | if ((to->thread.arch.fs == 0) || (to->mm == NULL)) |
147 | return; | 111 | return; |
148 | 112 | ||
149 | arch_prctl_skas(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs); | 113 | arch_prctl(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs); |
150 | } | 114 | } |
diff --git a/arch/um/sys-x86_64/tls.c b/arch/um/sys-x86_64/tls.c index febbc94be25f..f7ba46200ecd 100644 --- a/arch/um/sys-x86_64/tls.c +++ b/arch/um/sys-x86_64/tls.c | |||
@@ -11,7 +11,7 @@ int arch_copy_tls(struct task_struct *t) | |||
11 | * (which is argument 5, child_tid, of clone) so it can be set | 11 | * (which is argument 5, child_tid, of clone) so it can be set |
12 | * during context switches. | 12 | * during context switches. |
13 | */ | 13 | */ |
14 | t->thread.arch.fs = t->thread.regs.regs.skas.regs[R8 / sizeof(long)]; | 14 | t->thread.arch.fs = t->thread.regs.regs.gp[R8 / sizeof(long)]; |
15 | 15 | ||
16 | return 0; | 16 | return 0; |
17 | } | 17 | } |
diff --git a/arch/um/sys-x86_64/unmap.c b/arch/um/sys-x86_64/unmap.c deleted file mode 100644 index f4a4bffd8a18..000000000000 --- a/arch/um/sys-x86_64/unmap.c +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <linux/mman.h> | ||
7 | #include <asm/unistd.h> | ||
8 | |||
9 | static int errno; | ||
10 | |||
11 | static inline _syscall2(int,munmap,void *,start,size_t,len) | ||
12 | static inline _syscall6(void *,mmap,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset) | ||
13 | int switcheroo(int fd, int prot, void *from, void *to, int size) | ||
14 | { | ||
15 | if(munmap(to, size) < 0){ | ||
16 | return(-1); | ||
17 | } | ||
18 | if(mmap(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1){ | ||
19 | return(-1); | ||
20 | } | ||
21 | if(munmap(from, size) < 0){ | ||
22 | return(-1); | ||
23 | } | ||
24 | return(0); | ||
25 | } | ||
diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c index 0d5fd764c21f..f1ef2a8dfbc6 100644 --- a/arch/um/sys-x86_64/user-offsets.c +++ b/arch/um/sys-x86_64/user-offsets.c | |||
@@ -3,17 +3,10 @@ | |||
3 | #include <signal.h> | 3 | #include <signal.h> |
4 | #include <sys/poll.h> | 4 | #include <sys/poll.h> |
5 | #include <sys/mman.h> | 5 | #include <sys/mman.h> |
6 | #include <sys/user.h> | ||
6 | #define __FRAME_OFFSETS | 7 | #define __FRAME_OFFSETS |
7 | #include <asm/ptrace.h> | 8 | #include <asm/ptrace.h> |
8 | #include <asm/types.h> | 9 | #include <asm/types.h> |
9 | /* For some reason, x86_64 defines u64 and u32 only in <pci/types.h>, which I | ||
10 | * refuse to include here, even though they're used throughout the headers. | ||
11 | * These are used in asm/user.h, and that include can't be avoided because of | ||
12 | * the sizeof(struct user_regs_struct) below. | ||
13 | */ | ||
14 | typedef __u64 u64; | ||
15 | typedef __u32 u32; | ||
16 | #include <asm/user.h> | ||
17 | 10 | ||
18 | #define DEFINE(sym, val) \ | 11 | #define DEFINE(sym, val) \ |
19 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) | 12 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) |