aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/Kconfig244
-rw-r--r--arch/um/Kconfig.char141
-rw-r--r--arch/um/Kconfig.debug47
-rw-r--r--arch/um/Kconfig.i38614
-rw-r--r--arch/um/Kconfig.net22
-rw-r--r--arch/um/Kconfig.x86_6414
-rw-r--r--arch/um/Makefile35
-rw-r--r--arch/um/Makefile-i3866
-rw-r--r--arch/um/defconfig11
-rw-r--r--arch/um/drivers/Makefile11
-rw-r--r--arch/um/drivers/chan_kern.c211
-rw-r--r--arch/um/drivers/chan_user.c211
-rw-r--r--arch/um/drivers/cow_user.c133
-rw-r--r--arch/um/drivers/daemon.h20
-rw-r--r--arch/um/drivers/daemon_kern.c34
-rw-r--r--arch/um/drivers/daemon_user.c92
-rw-r--r--arch/um/drivers/fd.c69
-rw-r--r--arch/um/drivers/harddog_kern.c2
-rw-r--r--arch/um/drivers/harddog_user.c58
-rw-r--r--arch/um/drivers/hostaudio_kern.c118
-rw-r--r--arch/um/drivers/line.c237
-rw-r--r--arch/um/drivers/mcast.h16
-rw-r--r--arch/um/drivers/mcast_kern.c56
-rw-r--r--arch/um/drivers/mcast_user.c73
-rw-r--r--arch/um/drivers/mconsole_kern.c289
-rw-r--r--arch/um/drivers/mconsole_user.c119
-rw-r--r--arch/um/drivers/mmapper_kern.c64
-rw-r--r--arch/um/drivers/net_kern.c278
-rw-r--r--arch/um/drivers/net_user.c126
-rw-r--r--arch/um/drivers/null.c28
-rw-r--r--arch/um/drivers/pcap_kern.c38
-rw-r--r--arch/um/drivers/pcap_user.c58
-rw-r--r--arch/um/drivers/port_kern.c86
-rw-r--r--arch/um/drivers/port_user.c73
-rw-r--r--arch/um/drivers/pty.c30
-rw-r--r--arch/um/drivers/slip_kern.c38
-rw-r--r--arch/um/drivers/slip_user.c129
-rw-r--r--arch/um/drivers/slirp_kern.c59
-rw-r--r--arch/um/drivers/slirp_user.c74
-rw-r--r--arch/um/drivers/tty.c37
-rw-r--r--arch/um/drivers/ubd_kern.c2
-rw-r--r--arch/um/drivers/vde.h32
-rw-r--r--arch/um/drivers/vde_kern.c129
-rw-r--r--arch/um/drivers/vde_user.c127
-rw-r--r--arch/um/drivers/xterm.c28
-rw-r--r--arch/um/include/arch.h4
-rw-r--r--arch/um/include/as-layout.h27
-rw-r--r--arch/um/include/choose-mode.h38
-rw-r--r--arch/um/include/common-offsets.h10
-rw-r--r--arch/um/include/irq_user.h10
-rw-r--r--arch/um/include/kern_util.h30
-rw-r--r--arch/um/include/mconsole.h15
-rw-r--r--arch/um/include/mem.h21
-rw-r--r--arch/um/include/mode.h30
-rw-r--r--arch/um/include/mode_kern.h17
-rw-r--r--arch/um/include/net_kern.h13
-rw-r--r--arch/um/include/net_user.h4
-rw-r--r--arch/um/include/os.h69
-rw-r--r--arch/um/include/registers.h10
-rw-r--r--arch/um/include/skas/mmu-skas.h23
-rw-r--r--arch/um/include/skas/mode-skas.h9
-rw-r--r--arch/um/include/skas/mode_kern_skas.h41
-rw-r--r--arch/um/include/skas/skas.h5
-rw-r--r--arch/um/include/skas/uaccess-skas.h21
-rw-r--r--arch/um/include/sysdep-i386/kernel-offsets.h1
-rw-r--r--arch/um/include/sysdep-i386/ptrace.h133
-rw-r--r--arch/um/include/sysdep-i386/sigcontext.h30
-rw-r--r--arch/um/include/sysdep-i386/stub.h14
-rw-r--r--arch/um/include/sysdep-i386/thread.h11
-rw-r--r--arch/um/include/sysdep-x86_64/ptrace.h277
-rw-r--r--arch/um/include/sysdep-x86_64/sigcontext.h28
-rw-r--r--arch/um/include/sysdep-x86_64/stub.h13
-rw-r--r--arch/um/include/sysdep-x86_64/thread.h10
-rw-r--r--arch/um/include/task.h2
-rw-r--r--arch/um/include/tlb.h27
-rw-r--r--arch/um/include/tt/debug.h18
-rw-r--r--arch/um/include/tt/mmu-tt.h12
-rw-r--r--arch/um/include/tt/mode-tt.h23
-rw-r--r--arch/um/include/tt/mode_kern_tt.h40
-rw-r--r--arch/um/include/tt/tt.h37
-rw-r--r--arch/um/include/tt/uaccess-tt.h46
-rw-r--r--arch/um/include/um_mmu.h40
-rw-r--r--arch/um/include/um_uaccess.h64
-rw-r--r--arch/um/include/uml_uaccess.h24
-rw-r--r--arch/um/include/user.h8
-rw-r--r--arch/um/kernel/Makefile7
-rw-r--r--arch/um/kernel/dyn.lds.S2
-rw-r--r--arch/um/kernel/exec.c58
-rw-r--r--arch/um/kernel/init_task.c13
-rw-r--r--arch/um/kernel/irq.c113
-rw-r--r--arch/um/kernel/ksyms.c41
-rw-r--r--arch/um/kernel/mem.c2
-rw-r--r--arch/um/kernel/physmem.c69
-rw-r--r--arch/um/kernel/process.c226
-rw-r--r--arch/um/kernel/ptrace.c141
-rw-r--r--arch/um/kernel/reboot.c57
-rw-r--r--arch/um/kernel/signal.c59
-rw-r--r--arch/um/kernel/skas/Makefile4
-rw-r--r--arch/um/kernel/skas/clone.c6
-rw-r--r--arch/um/kernel/skas/exec.c40
-rw-r--r--arch/um/kernel/skas/mem.c22
-rw-r--r--arch/um/kernel/skas/mmu.c81
-rw-r--r--arch/um/kernel/skas/process.c187
-rw-r--r--arch/um/kernel/skas/syscall.c21
-rw-r--r--arch/um/kernel/skas/tlb.c164
-rw-r--r--arch/um/kernel/skas/uaccess.c146
-rw-r--r--arch/um/kernel/smp.c36
-rw-r--r--arch/um/kernel/syscall.c40
-rw-r--r--arch/um/kernel/time.c223
-rw-r--r--arch/um/kernel/tlb.c418
-rw-r--r--arch/um/kernel/trap.c129
-rw-r--r--arch/um/kernel/tt/Makefile14
-rw-r--r--arch/um/kernel/tt/exec_kern.c84
-rw-r--r--arch/um/kernel/tt/exec_user.c56
-rw-r--r--arch/um/kernel/tt/gdb.c280
-rw-r--r--arch/um/kernel/tt/gdb_kern.c40
-rw-r--r--arch/um/kernel/tt/include/mode-tt.h34
-rw-r--r--arch/um/kernel/tt/ksyms.c29
-rw-r--r--arch/um/kernel/tt/mem.c34
-rw-r--r--arch/um/kernel/tt/mem_user.c49
-rw-r--r--arch/um/kernel/tt/process_kern.c461
-rw-r--r--arch/um/kernel/tt/ptproxy/Makefile10
-rw-r--r--arch/um/kernel/tt/ptproxy/proxy.c377
-rw-r--r--arch/um/kernel/tt/ptproxy/ptproxy.h61
-rw-r--r--arch/um/kernel/tt/ptproxy/ptrace.c237
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.c70
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.h25
-rw-r--r--arch/um/kernel/tt/ptproxy/wait.c85
-rw-r--r--arch/um/kernel/tt/ptproxy/wait.h15
-rw-r--r--arch/um/kernel/tt/syscall_kern.c46
-rw-r--r--arch/um/kernel/tt/syscall_user.c60
-rw-r--r--arch/um/kernel/tt/tlb.c120
-rw-r--r--arch/um/kernel/tt/tracer.c461
-rw-r--r--arch/um/kernel/tt/trap_user.c70
-rw-r--r--arch/um/kernel/tt/uaccess.c73
-rw-r--r--arch/um/kernel/tt/uaccess_user.c105
-rw-r--r--arch/um/kernel/uaccess.c2
-rw-r--r--arch/um/kernel/um_arch.c217
-rw-r--r--arch/um/kernel/uml.lds.S7
-rw-r--r--arch/um/os-Linux/Makefile15
-rw-r--r--arch/um/os-Linux/aio.c122
-rw-r--r--arch/um/os-Linux/drivers/etap.h16
-rw-r--r--arch/um/os-Linux/drivers/ethertap_kern.c52
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c132
-rw-r--r--arch/um/os-Linux/drivers/tuntap.h13
-rw-r--r--arch/um/os-Linux/drivers/tuntap_kern.c35
-rw-r--r--arch/um/os-Linux/drivers/tuntap_user.c102
-rw-r--r--arch/um/os-Linux/file.c130
-rw-r--r--arch/um/os-Linux/helper.c8
-rw-r--r--arch/um/os-Linux/irq.c6
-rw-r--r--arch/um/os-Linux/main.c120
-rw-r--r--arch/um/os-Linux/mem.c6
-rw-r--r--arch/um/os-Linux/process.c175
-rw-r--r--arch/um/os-Linux/registers.c57
-rw-r--r--arch/um/os-Linux/signal.c131
-rw-r--r--arch/um/os-Linux/skas/mem.c109
-rw-r--r--arch/um/os-Linux/skas/process.c316
-rw-r--r--arch/um/os-Linux/skas/trap.c51
-rw-r--r--arch/um/os-Linux/start_up.c218
-rw-r--r--arch/um/os-Linux/sys-i386/Makefile4
-rw-r--r--arch/um/os-Linux/sys-i386/registers.c129
-rw-r--r--arch/um/os-Linux/sys-x86_64/Makefile4
-rw-r--r--arch/um/os-Linux/sys-x86_64/registers.c75
-rw-r--r--arch/um/os-Linux/time.c111
-rw-r--r--arch/um/os-Linux/tls.c40
-rw-r--r--arch/um/os-Linux/trap.c23
-rw-r--r--arch/um/os-Linux/tt.c196
-rw-r--r--arch/um/os-Linux/uaccess.c2
-rw-r--r--arch/um/os-Linux/umid.c137
-rw-r--r--arch/um/os-Linux/util.c38
-rw-r--r--arch/um/scripts/Makefile.rules2
-rw-r--r--arch/um/sys-i386/Makefile14
-rw-r--r--arch/um/sys-i386/bugs.c108
-rw-r--r--arch/um/sys-i386/fault.c10
-rw-r--r--arch/um/sys-i386/ldt.c306
-rw-r--r--arch/um/sys-i386/ptrace.c368
-rw-r--r--arch/um/sys-i386/ptrace_user.c100
-rw-r--r--arch/um/sys-i386/sigcontext.c71
-rw-r--r--arch/um/sys-i386/signal.c409
-rw-r--r--arch/um/sys-i386/stub.S9
-rw-r--r--arch/um/sys-i386/stub_segv.c4
-rw-r--r--arch/um/sys-i386/tls.c101
-rw-r--r--arch/um/sys-i386/unmap.c25
-rw-r--r--arch/um/sys-i386/user-offsets.c6
-rw-r--r--arch/um/sys-x86_64/Makefile11
-rw-r--r--arch/um/sys-x86_64/bugs.c2
-rw-r--r--arch/um/sys-x86_64/fault.c9
-rw-r--r--arch/um/sys-x86_64/ptrace.c154
-rw-r--r--arch/um/sys-x86_64/sigcontext.c39
-rw-r--r--arch/um/sys-x86_64/signal.c297
-rw-r--r--arch/um/sys-x86_64/stub.S9
-rw-r--r--arch/um/sys-x86_64/stub_segv.c3
-rw-r--r--arch/um/sys-x86_64/syscalls.c108
-rw-r--r--arch/um/sys-x86_64/tls.c4
-rw-r--r--arch/um/sys-x86_64/unmap.c25
-rw-r--r--arch/um/sys-x86_64/user-offsets.c9
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
58config GENERIC_TIME
59 bool
60 default y
61
62config 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
59config IRQ_RELEASE_METHOD 67config IRQ_RELEASE_METHOD
60 bool 68 bool
@@ -62,63 +70,25 @@ config IRQ_RELEASE_METHOD
62 70
63menu "UML-specific options" 71menu "UML-specific options"
64 72
65config 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
77config STATIC_LINK 73config 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
92config 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
102config 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
115source "arch/um/Kconfig.arch" 84source "arch/um/Kconfig.arch"
116source "mm/Kconfig" 85source "mm/Kconfig"
86source "kernel/time/Kconfig"
117 87
118config LD_SCRIPT_STATIC 88config 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
123config LD_SCRIPT_DYN 93config LD_SCRIPT_DYN
124 bool 94 bool
@@ -128,18 +98,18 @@ config LD_SCRIPT_DYN
128config NET 98config 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
145source "fs/Kconfig.binfmt" 115source "fs/Kconfig.binfmt"
@@ -147,99 +117,99 @@ source "fs/Kconfig.binfmt"
147config HOSTFS 117config 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
168config HPPFS 138config 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
183config MCONSOLE 153config 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
200config MAGIC_SYSRQ 170config 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
219config SMP 189config 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
244config NR_CPUS 214config 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
266config HIGHMEM 231config 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
278config KERNEL_STACK_ORDER 243config 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
288config 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
299endmenu 253endmenu
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
10config STDIO_CONSOLE 10config STDIO_CONSOLE
11 bool 11 bool
@@ -14,60 +14,58 @@ config STDIO_CONSOLE
14config SSL 14config 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
26config NULL_CHAN 26config 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
33config PORT_CHAN 33config 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
43config PTY_CHAN 43config 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
53config TTY_CHAN 53config 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
62config XTERM_CHAN 62config 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
72config NOCONFIG_CHAN 70config 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
86config CON_CHAN 84config 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
98config SSL_CHAN 96config 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
110config UNIX98_PTYS 108config 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
132config LEGACY_PTYS 130config 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
196config UML_SOUND 194config 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
204config SOUND 202config SOUND
205 tristate 203 tristate
@@ -217,22 +215,21 @@ config HW_RANDOM
217config UML_RANDOM 215config 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
231config MMAPPER 229config 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
237endmenu 235endmenu
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
3source "lib/Kconfig.debug" 3source "lib/Kconfig.debug"
4 4
5config 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
16config 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
24config GPROF 5config 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
37config GCOV 18config 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
50config DEBUG_STACK_USAGE 31config 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
68config STUB_CODE
69 hex
70 default 0xbfffe000 if !HOST_VMSPLIT_2G
71 default 0x7fffe000 if HOST_VMSPLIT_2G
72
73config STUB_DATA
74 hex
75 default 0xbffff000 if !HOST_VMSPLIT_2G
76 default 0x7ffff000 if HOST_VMSPLIT_2G
77
78config STUB_START
79 hex
80 default STUB_CODE
81
82config ARCH_HAS_SC_SIGNALS 68config 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
111config 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
111config UML_NET_MCAST 133config 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
18config TOP_ADDR 18config TOP_ADDR
19 hex 19 hex
20 default 0x80000000 20 default 0x7fc0000000
21 21
22config 3_LEVEL_PGTABLES 22config 3_LEVEL_PGTABLES
23 bool 23 bool
24 default y 24 default y
25 25
26config STUB_CODE
27 hex
28 default 0x7fbfffe000
29
30config STUB_DATA
31 hex
32 default 0x7fbffff000
33
34config STUB_START
35 hex
36 default STUB_CODE
37
38config ARCH_HAS_SC_SIGNALS 26config 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))
31ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \ 31ARCH_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
34um-modes-$(CONFIG_MODE_TT) += tt 34MODE_INCLUDE += -I$(srctree)/$(ARCH_DIR)/include/skas
35um-modes-$(CONFIG_MODE_SKAS) += skas
36 35
37MODE_INCLUDE += $(foreach mode,$(um-modes-y),\ 36include $(srctree)/$(ARCH_DIR)/Makefile-skas
38 -I$(srctree)/$(ARCH_DIR)/include/$(mode))
39
40MAKEFILES-INCL += $(foreach mode,$(um-modes-y),\
41 $(srctree)/$(ARCH_DIR)/Makefile-$(mode))
42
43ifneq ($(MAKEFILES-INCL),)
44 include $(MAKEFILES-INCL)
45endif
46 37
47ARCH_INCLUDE := -I$(ARCH_DIR)/include 38ARCH_INCLUDE := -I$(ARCH_DIR)/include
48ifneq ($(KBUILD_SRC),) 39ifneq ($(KBUILD_SRC),)
@@ -60,7 +51,8 @@ SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH)
60 51
61CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ 52CFLAGS += $(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
65AFLAGS += $(ARCH_INCLUDE) 57AFLAGS += $(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
90CONFIG_NEST_LEVEL ?= 0 82CONFIG_NEST_LEVEL ?= 0
91CONFIG_KERNEL_HALF_GIGS ?= 0
92 83
93SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000) 84SIZE = ($(CONFIG_NEST_LEVEL) * 0x20000000)
94 85
95PHONY += linux 86PHONY += 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
126CPP_MODE-$(CONFIG_MODE_TT) := -DMODE_TT
127CONFIG_KERNEL_STACK_ORDER ?= 2 117CONFIG_KERNEL_STACK_ORDER ?= 2
128STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] ) 118STACK_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) ] )
132endif 122endif
133 123
134CPPFLAGS_vmlinux.lds = -U$(SUBARCH) \ 124CPPFLAGS_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.
141LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc 128LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
142 129
143CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) 130CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS)
@@ -150,8 +137,8 @@ define cmd_vmlinux__
150 FORCE ,$^) ; rm -f linux 137 FORCE ,$^) ; rm -f linux
151endef 138endef
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.
155CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/include/uml-config.h \ 142CLEAN_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
3TOP_ADDR := $(CONFIG_TOP_ADDR) 3TOP_ADDR := $(CONFIG_TOP_ADDR)
4 4
5ifeq ($(CONFIG_MODE_SKAS),y) 5START := 0x8048000
6 ifneq ($(CONFIG_MODE_TT),y)
7 START := 0x8048000
8 endif
9endif
10 6
11LDFLAGS += -m elf_i386 7LDFLAGS += -m elf_i386
12ELF_ARCH := $(SUBARCH) 8ELF_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
17CONFIG_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
62CONFIG_TOP_ADDR=0xc0000000 60CONFIG_TOP_ADDR=0xc0000000
63# CONFIG_3_LEVEL_PGTABLES is not set 61# CONFIG_3_LEVEL_PGTABLES is not set
64CONFIG_STUB_CODE=0xbfffe000
65CONFIG_STUB_DATA=0xbffff000
66CONFIG_STUB_START=0xbfffe000
67CONFIG_ARCH_HAS_SC_SIGNALS=y 62CONFIG_ARCH_HAS_SC_SIGNALS=y
68CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y 63CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y
69CONFIG_GENERIC_HWEIGHT=y 64CONFIG_GENERIC_HWEIGHT=y
@@ -75,6 +70,9 @@ CONFIG_FLATMEM=y
75CONFIG_FLAT_NODE_MEM_MAP=y 70CONFIG_FLAT_NODE_MEM_MAP=y
76# CONFIG_SPARSEMEM_STATIC is not set 71# CONFIG_SPARSEMEM_STATIC is not set
77CONFIG_SPLIT_PTLOCK_CPUS=4 72CONFIG_SPLIT_PTLOCK_CPUS=4
73CONFIG_TICK_ONESHOT=y
74CONFIG_NO_HZ=y
75CONFIG_HIGH_RES_TIMERS=y
78CONFIG_LD_SCRIPT_DYN=y 76CONFIG_LD_SCRIPT_DYN=y
79CONFIG_NET=y 77CONFIG_NET=y
80CONFIG_BINFMT_ELF=y 78CONFIG_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
84CONFIG_MCONSOLE=y 82CONFIG_MCONSOLE=y
85# CONFIG_MAGIC_SYSRQ is not set 83CONFIG_MAGIC_SYSRQ=y
86CONFIG_NEST_LEVEL=0 84CONFIG_NEST_LEVEL=0
87# CONFIG_HIGHMEM is not set 85# CONFIG_HIGHMEM is not set
88CONFIG_KERNEL_STACK_ORDER=0 86CONFIG_KERNEL_STACK_ORDER=0
89CONFIG_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
20LDFLAGS_pcap.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libpcap.a) 20LDFLAGS_pcap.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libpcap.a)
21 21
22targets := pcap_kern.o pcap_user.o 22LDFLAGS_vde.o := -r $(shell $(CC) $(CFLAGS) -print-file-name=libvdeplug.a)
23
24targets := 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
37obj-$(CONFIG_UML_NET_SLIP) += slip.o slip_common.o 43obj-$(CONFIG_UML_NET_SLIP) += slip.o slip_common.o
38obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o 44obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o
39obj-$(CONFIG_UML_NET_DAEMON) += daemon.o 45obj-$(CONFIG_UML_NET_DAEMON) += daemon.o
46obj-$(CONFIG_UML_NET_VDE) += vde.o
40obj-$(CONFIG_UML_NET_MCAST) += mcast.o 47obj-$(CONFIG_UML_NET_MCAST) += mcast.o
41obj-$(CONFIG_UML_NET_PCAP) += pcap.o 48obj-$(CONFIG_UML_NET_PCAP) += pcap.o
42obj-$(CONFIG_UML_NET) += net.o 49obj-$(CONFIG_UML_NET) += net.o
@@ -54,6 +61,6 @@ obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o
54obj-$(CONFIG_UML_RANDOM) += random.o 61obj-$(CONFIG_UML_RANDOM) += random.o
55 62
56# pcap_user.o must be added explicitly. 63# pcap_user.o must be added explicitly.
57USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o pcap_user.o 64USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o pcap_user.o vde_user.o
58 65
59include arch/um/scripts/Makefile.rules 66include 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
22static void *not_configged_init(char *str, int device, 13static 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,
30static int not_configged_open(int input, int output, int primary, void *data, 21static 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
38static void not_configged_close(int fd, void *data) 29static 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
44static int not_configged_read(int fd, char *c_out, void *data) 35static 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
51static int not_configged_write(int fd, const char *buf, int len, void *data) 42static 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
58static int not_configged_console_write(int fd, const char *buf, int len) 49static 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)
65static int not_configged_window_size(int fd, void *data, unsigned short *rows, 56static 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
73static void not_configged_free(void *data) 64static 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
92void generic_close(int fd, void *unused)
93{
94 os_close_file(fd);
95}
96
97int 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
112int generic_write(int fd, const char *buf, int n, void *unused)
113{
114 return os_write_file(fd, buf, n);
115}
116
117int 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
135void generic_free(void *data)
136{
137 kfree(data);
138}
139
140static void tty_receive_char(struct tty_struct *tty, char ch) 83static 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
18void generic_close(int fd, void *unused)
19{
20 close(fd);
21}
22
23int 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
39int 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
53int 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
70void generic_free(void *data)
71{
72 kfree(data);
73}
22 74
23int generic_console_write(int fd, const char *buf, int n) 75int 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;
47error: 103error:
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
189int write_cow_header(char *cow_file, int fd, char *backing_file, 193int 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
260int file_reader(__u64 offset, char *buf, int len, void *arg) 265int 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
395int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, 399int 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
21extern const struct net_user_info daemon_user_info; 24extern const struct net_user_info daemon_user_info;
22 25
23extern int daemon_user_write(int fd, void *buf, int len, 26extern 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
16struct daemon_init { 14struct 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
44static int daemon_read(int fd, struct sk_buff **skb, 42static 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
53static int daemon_write(int fd, struct sk_buff **skb, 48static 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
60static const struct net_kern_info daemon_kern_info = { 54static 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
85static struct transport daemon_transport = { 79static 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
23enum request_type { REQ_NEW_CONTROL }; 22enum 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
184static int daemon_set_mtu(int mtu, void *data)
185{
186 return mtu;
187}
188
189const struct net_user_info daemon_user_info = { 185const 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
16struct fd_chan { 17struct 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
47static int fd_open(int input, int output, int primary, void *d, char **dev_out) 52static 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
66static void fd_close(int fd, void *d) 71static 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
80const struct chan_ops fd_ops = { 86const 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
15struct dog_data { 12struct 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
34int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) 31int 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
110void stop_watchdog(int in_fd, int out_fd) 107void 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
116int ping_watchdog(int fd) 113int 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;
44static int set_dsp(char *name, int *add) 43static 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);
52static int set_mixer(char *name, int *add) 51static 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
94out: 93out:
95 kfree(kbuf); 94 kfree(kbuf);
96 return(err); 95 return err;
97} 96}
98 97
99static ssize_t hostaudio_write(struct file *file, const char __user *buffer, 98static 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
128static unsigned int hostaudio_poll(struct file *file, 127static 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
140static int hostaudio_ioctl(struct inode *inode, struct file *file, 139static 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
183static int hostaudio_open(struct inode *inode, struct file *file) 182static 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
210static int hostaudio_release(struct inode *inode, struct file *file) 211static 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
225static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file, 226static 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
237static int hostmixer_open_mixdev(struct inode *inode, struct file *file) 238static 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
266static int hostmixer_release(struct inode *inode, struct file *file) 270static 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 */
205void line_flush_chars(struct tty_struct *tty) 200void 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,
655int line_id(char **str, int *start_out, int *end_out) 651int 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
670int line_remove(struct line *lines, unsigned int num, int n, char **error_out) 666int 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
8struct mcast_data { 11struct mcast_data {
@@ -18,13 +21,4 @@ extern const struct net_user_info mcast_user_info;
18extern int mcast_user_write(int fd, void *buf, int len, 21extern 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
23struct mcast_init { 19struct 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
49static int mcast_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) 42static 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
57static int mcast_write(int fd, struct sk_buff **skb, 48static 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
64static const struct net_kern_info mcast_kern_info = { 54static 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
114static struct transport mcast_transport = { 104static 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
29static struct sockaddr_in *new_addr(char *addr, unsigned short port) 23static 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
152int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri) 148int 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
159static int mcast_set_mtu(int mtu, void *data)
160{
161 return mtu;
162}
163
164const struct net_user_info mcast_user_info = { 155const 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
38static int do_unlink_socket(struct notifier_block *notifier, 29static 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
103void mconsole_version(struct mc_request *req) 93void 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
502static int __init mem_mc_init(void) 493static 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 {
640static DEFINE_SPINLOCK(client_lock); 632static DEFINE_SPINLOCK(client_lock);
641static LIST_HEAD(clients); 633static LIST_HEAD(clients);
642static char console_buf[MCONSOLE_MAX_DATA]; 634static char console_buf[MCONSOLE_MAX_DATA];
643static int console_index = 0;
644 635
645static void console_write(struct console *console, const char *string, 636static 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
710static void sysrq_proc(void *arg) 697static 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
740static void stack_proc(void *arg) 726static 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 */
753static void do_stack_trace(struct mc_request *req) 740void 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
786void 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 */
799static char *notify_socket = NULL; 780static 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
866static int create_proc_mconsole(void) 848static 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
883static DEFINE_SPINLOCK(notify_spinlock); 867static 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
899static int mconsole_setup(char *str) 883static 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
931static struct notifier_block panic_exit_notifier = { 916static 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
946char *mconsole_notify_socket(void) 931char *mconsole_notify_socket(void)
947{ 932{
948 return(notify_socket); 933 return notify_socket;
949} 934}
950 935
951EXPORT_SYMBOL(mconsole_notify_socket); 936EXPORT_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
21static struct mconsole_command commands[] = { 17static 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
45int mconsole_reply_v0(struct mc_request *req, char *reply) 42int 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
64static struct mconsole_command *mconsole_parse(struct mc_request *req) 61static 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
132int mconsole_reply_len(struct mc_request *req, const char *str, int total, 129int 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
169int mconsole_reply(struct mc_request *req, const char *str, int err, int more) 168int 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 */
21static unsigned long mmapper_size; 23static unsigned long mmapper_size;
22static unsigned long p_buf = 0; 24static unsigned long p_buf;
23static char *v_buf = NULL; 25static char *v_buf;
24 26
25static ssize_t 27static ssize_t mmapper_read(struct file *file, char __user *buf, size_t count,
26mmapper_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
31static ssize_t 33static ssize_t mmapper_write(struct file *file, const char __user *buf,
32mmapper_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
46static int 48static int mmapper_ioctl(struct inode *inode, struct file *file,
47mmapper_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
53static int 54static int mmapper_mmap(struct file *file, struct vm_area_struct *vma)
54mmapper_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;
72out: 74out:
73 return ret; 75 return ret;
74} 76}
75 77
76static int 78static int mmapper_open(struct inode *inode, struct file *file)
77mmapper_open(struct inode *inode, struct file *file)
78{ 79{
79 return 0; 80 return 0;
80} 81}
81 82
82static int 83static int mmapper_release(struct inode *inode, struct file *file)
83mmapper_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 */
99static struct miscdevice mmapper_dev = { 101static 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
137MODULE_AUTHOR("Greg Lonnon <glonnon@ridgerun.com>"); 139MODULE_AUTHOR("Greg Lonnon <glonnon@ridgerun.com>");
138MODULE_DESCRIPTION("DSPLinux simulator mmapper driver"); 140MODULE_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
32static inline void set_ether_mac(struct net_device *dev, unsigned char *addr) 27static 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)
39static DEFINE_SPINLOCK(opened_lock); 34static DEFINE_SPINLOCK(opened_lock);
40static LIST_HEAD(opened); 35static 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 */
45static DEFINE_SPINLOCK(drop_lock);
46static struct sk_buff *drop_skb;
47static int drop_max;
48
49static 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;
71out:
72 spin_unlock_irqrestore(&drop_lock, flags);
73
74 return err;
75}
76
42static int uml_net_rx(struct net_device *dev) 77static 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;
151out_close: 189out_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;
154out: 192out:
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
219static void uml_net_set_multicast_list(struct net_device *dev) 257static 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
244static int uml_net_change_mtu(struct net_device *dev, int new_mtu) 284static 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
264static void uml_net_get_drvinfo(struct net_device *dev, 291static 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, &eth_cmd_line){ 618 list_for_each_safe(ele, next, &eth_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
681static int net_id(char **str, int *start_out, int *end_out) 712static 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
696static int net_remove(int n, char **error_out) 727static 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
813struct 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
826void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, 844void 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
863void *get_output_buffer(int *len_out) 881void *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
893unsigned short eth_protocol(struct sk_buff *skb) 911unsigned 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
23int tap_open_common(void *dev, char *gate_addr) 20int 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
86err: 88err:
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
93int net_read(int fd, void *buf, int len) 97int 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
14static void *null_init(char *str, int device, const struct chan_opts *opts) 15static 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
19static int null_open(int input, int output, int primary, void *d, 20static 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
26static int null_read(int fd, char *c_out, void *unused) 31static int null_read(int fd, char *c_out, void *unused)
27{ 32{
28 return(-ENODEV); 33 return -ENODEV;
29} 34}
30 35
31static void null_free(void *data) 36static 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
13struct pcap_init { 11struct 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
36static int pcap_read(int fd, struct sk_buff **skb, 34static 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
48static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) 41static 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
82static void pcap_remove(void *data) 84static 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
98static void handler(u_char *data, const struct pcap_pkthdr *header, 100static 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
23struct port_list { 15struct 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)
81static int port_accept(struct port_list *port) 73static 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
132static DECLARE_MUTEX(ports_sem); 123static DECLARE_MUTEX(ports_sem);
133static LIST_HEAD(ports); 124static LIST_HEAD(ports);
134 125
135void port_work_proc(struct work_struct *unused) 126static 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
23struct port_chan { 19struct 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
172int port_connection(int fd, int *socket, int *pid_out) 169int 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
20struct pty_chan { 20struct 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
75out_close:
76 close(fd);
77 return err;
74} 78}
75 79
76static int getmaster(char *line) 80static 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
11struct slip_init { 12struct slip_init {
@@ -43,21 +44,19 @@ void slip_init(struct net_device *dev, void *data)
43 44
44static unsigned short slip_protocol(struct sk_buff *skbuff) 45static 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
49static int slip_read(int fd, struct sk_buff **skb, 50static 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
56static int slip_write(int fd, struct sk_buff **skb, 56static 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
63const struct net_kern_info slip_kern_info = { 62const 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
82static struct transport slip_transport = { 80static 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
20static int slip_user_init(void *data, void *dev) 21static 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
57struct slip_pre_exec_data { 59struct 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
72static int slip_tramp(char **argv, int fd) 76static 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
117out_free: 123out_free:
118 kfree(output); 124 kfree(output);
119 return err; 125 return err;
120 126
121out_close: 127out_close:
122 os_close_file(fds[0]); 128 close(fds[0]);
123 os_close_file(fds[1]); 129 close(fds[1]);
124out: 130out:
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;
183out_close2: 193out_close2:
184 os_close_file(sfd); 194 close(sfd);
185out_close: 195out_close:
186 os_close_file(mfd); 196 close(mfd);
187out: 197out:
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
223static int slip_set_mtu(int mtu, void *data)
224{
225 return(mtu);
226}
227
228static void slip_add_addr(unsigned char *addr, unsigned char *netmask, 233static 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
11struct slirp_init { 14struct 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
48static unsigned short slirp_protocol(struct sk_buff *skbuff) 50static 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
53static int slirp_read(int fd, struct sk_buff **skb, 55static 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
60static int slirp_write(int fd, struct sk_buff **skb, 61static 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
67const struct net_kern_info slirp_kern_info = { 67const 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
106static struct transport slirp_transport = { 107static 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
17static int slirp_user_init(void *data, void *dev) 16static 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
38static int slirp_tramp(char **argv, int fd) 39static 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
50static int slirp_open(void *data) 51static 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];
72out: 73out:
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
124static int slirp_set_mtu(int mtu, void *data)
125{
126 return(mtu);
127}
128
129const struct net_user_info slirp_user_info = { 127const 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
15struct tty_chan { 15struct 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
9struct vde_data {
10 char *vde_switch;
11 char *descr;
12 void *args;
13 void *conn;
14 void *dev;
15};
16
17struct vde_init {
18 char *vde_switch;
19 char *descr;
20 int port;
21 char *group;
22 int mode;
23};
24
25extern const struct net_user_info vde_user_info;
26
27extern void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init);
28
29extern int vde_user_read(void *conn, void *buf, int len);
30extern 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
16static 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
39static 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
51static 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
63static 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
70static 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
113static 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
123static int register_vde(void)
124{
125 register_transport(&vde_transport);
126 return 0;
127}
128
129late_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
15static 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
39static 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
50static 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
66const 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
77void 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
98int 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
118int 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
19struct xterm_chan { 20struct 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,
195static void xterm_close(int fd, void *d) 198static 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
210static void xterm_free(void *d)
211{
212 free(d);
213}
214
215const struct chan_ops xterm_ops = { 213const 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
11extern void arch_check_bugs(void); 11extern void arch_check_bugs(void);
12extern int arch_fixup(unsigned long address, union uml_pt_regs *regs); 12extern int arch_fixup(unsigned long address, struct uml_pt_regs *regs);
13extern int arch_handle_signal(int sig, union uml_pt_regs *regs); 13extern 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
11struct cpu_task { 33struct cpu_task {
@@ -28,8 +50,9 @@ extern unsigned long _unprotected_end;
28extern unsigned long brk_start; 50extern unsigned long brk_start;
29 51
30extern int linux_main(int argc, char **argv); 52extern int linux_main(int argc, char **argv);
31extern void set_cmdline(char *cmd);
32 53
33extern void (*sig_info[])(int, union uml_pt_regs *); 54extern 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
14extern int mode_tt;
15static 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
3DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE); 3DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
4#ifdef CONFIG_MODE_TT
5OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
6#endif
7 4
8OFFSET(HOST_TASK_REGS, task_struct, thread.regs); 5OFFSET(HOST_TASK_REGS, task_struct, thread.regs);
9OFFSET(HOST_TASK_PID, task_struct, pid); 6OFFSET(HOST_TASK_PID, task_struct, pid);
10 7
11DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE); 8DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE);
12DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK); 9DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK);
10DEFINE(UM_KERN_PAGE_SHIFT, PAGE_SHIFT);
13DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC); 11DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC);
14 12
15DEFINE_STR(UM_KERN_EMERG, KERN_EMERG); 13DEFINE_STR(UM_KERN_EMERG, KERN_EMERG);
@@ -34,3 +32,9 @@ DEFINE(UM_GFP_ATOMIC, GFP_ATOMIC);
34DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx)); 32DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
35 33
36DEFINE(UM_THREAD_SIZE, THREAD_SIZE); 34DEFINE(UM_THREAD_SIZE, THREAD_SIZE);
35
36DEFINE(UM_HZ, HZ);
37
38DEFINE(UM_USEC_PER_SEC, USEC_PER_SEC);
39DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC);
40DEFINE(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
11struct irq_fd { 11struct irq_fd {
12 struct irq_fd *next; 12 struct irq_fd *next;
@@ -21,7 +21,7 @@ struct irq_fd {
21 21
22enum { IRQ_READ, IRQ_WRITE }; 22enum { IRQ_READ, IRQ_WRITE };
23 23
24extern void sigio_handler(int sig, union uml_pt_regs *regs); 24extern void sigio_handler(int sig, struct uml_pt_regs *regs);
25extern int activate_fd(int irq, int fd, int type, void *dev_id); 25extern int activate_fd(int irq, int fd, int type, void *dev_id);
26extern void free_irq_by_irq_and_dev(unsigned int irq, void *dev_id); 26extern void free_irq_by_irq_and_dev(unsigned int irq, void *dev_id);
27extern void free_irq_by_fd(int fd); 27extern void free_irq_by_fd(int fd);
@@ -30,8 +30,4 @@ extern void deactivate_fd(int fd, int irqnum);
30extern int deactivate_all_fds(void); 30extern int deactivate_all_fds(void);
31extern int activate_ipi(int fd, int pid); 31extern int activate_ipi(int fd, int pid);
32 32
33#ifdef CONFIG_MODE_TT
34extern 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
13typedef void (*kern_hndl)(int, union uml_pt_regs *); 12typedef void (*kern_hndl)(int, struct uml_pt_regs *);
14 13
15struct kern_handlers { 14struct 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
36extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg); 35extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg);
37#ifdef UML_CONFIG_MODE_TT
38extern unsigned long stack_sp(unsigned long page);
39#endif
40extern int kernel_thread_proc(void *data); 36extern int kernel_thread_proc(void *data);
41extern void syscall_segv(int sig); 37extern void syscall_segv(int sig);
42extern int current_pid(void); 38extern int current_pid(void);
@@ -44,7 +40,7 @@ extern unsigned long alloc_stack(int order, int atomic);
44extern int do_signal(void); 40extern int do_signal(void);
45extern int is_stack_fault(unsigned long sp); 41extern int is_stack_fault(unsigned long sp);
46extern unsigned long segv(struct faultinfo fi, unsigned long ip, 42extern 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);
48extern int handle_page_fault(unsigned long address, unsigned long ip, 44extern 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);
50extern void syscall_ready(void); 46extern void syscall_ready(void);
@@ -57,7 +53,7 @@ extern int need_finish_fork(void);
57extern void free_stack(unsigned long stack, int order); 53extern void free_stack(unsigned long stack, int order);
58extern void add_input_request(int op, void (*proc)(int), void *arg); 54extern void add_input_request(int op, void (*proc)(int), void *arg);
59extern char *current_cmd(void); 55extern char *current_cmd(void);
60extern void timer_handler(int sig, union uml_pt_regs *regs); 56extern void timer_handler(int sig, struct uml_pt_regs *regs);
61extern int set_signals(int enable); 57extern int set_signals(int enable);
62extern int pid_to_processor_id(int pid); 58extern int pid_to_processor_id(int pid);
63extern void deliver_signals(void *t); 59extern void deliver_signals(void *t);
@@ -67,9 +63,8 @@ extern void finish_fork(void);
67extern void paging_init(void); 63extern void paging_init(void);
68extern void init_flush_vm(void); 64extern void init_flush_vm(void);
69extern void *syscall_sp(void *t); 65extern void *syscall_sp(void *t);
70extern void syscall_trace(union uml_pt_regs *regs, int entryexit); 66extern void syscall_trace(struct uml_pt_regs *regs, int entryexit);
71extern int hz(void); 67extern unsigned int do_IRQ(int irq, struct uml_pt_regs *regs);
72extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs);
73extern void interrupt_end(void); 68extern void interrupt_end(void);
74extern void initial_thread_cb(void (*proc)(void *), void *arg); 69extern void initial_thread_cb(void (*proc)(void *), void *arg);
75extern int debugger_signal(int status, int pid); 70extern int debugger_signal(int status, int pid);
@@ -79,10 +74,9 @@ extern int init_ptrace_proxy(int idle_pid, int startup, int stop);
79extern int init_parent_proxy(int pid); 74extern int init_parent_proxy(int pid);
80extern int singlestepping(void *t); 75extern int singlestepping(void *t);
81extern void check_stack_overflow(void *ptr); 76extern void check_stack_overflow(void *ptr);
82extern void relay_signal(int sig, union uml_pt_regs *regs); 77extern void relay_signal(int sig, struct uml_pt_regs *regs);
83extern int user_context(unsigned long sp); 78extern int user_context(unsigned long sp);
84extern void timer_irq(union uml_pt_regs *regs); 79extern void timer_irq(struct uml_pt_regs *regs);
85extern void unprotect_stack(unsigned long stack);
86extern void do_uml_exitcalls(void); 80extern void do_uml_exitcalls(void);
87extern int attach_debugger(int idle_pid, int pid, int stop); 81extern int attach_debugger(int idle_pid, int pid, int stop);
88extern int config_gdb(char *str); 82extern 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. */
115extern int __cant_sleep(void); 109extern int __cant_sleep(void);
116extern void sigio_handler(int sig, union uml_pt_regs *regs); 110extern void sigio_handler(int sig, struct uml_pt_regs *regs);
117 111extern void copy_sc(struct uml_pt_regs *regs, void *from);
118extern void copy_sc(union uml_pt_regs *regs, void *from);
119
120extern unsigned long to_irq_stack(unsigned long *mask_out); 112extern unsigned long to_irq_stack(unsigned long *mask_out);
121unsigned long from_irq_stack(int nested); 113unsigned long from_irq_stack(int nested);
122 114extern 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
69extern char mconsole_socket_name[]; 69extern char mconsole_socket_name[];
@@ -96,14 +96,3 @@ extern void lock_notify(void);
96extern void unlock_notify(void); 96extern 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" 9extern int phys_mapping(unsigned long phys, unsigned long long *offset_out);
10
11extern int phys_mapping(unsigned long phys, __u64 *offset_out);
12extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w);
13extern int is_remapped(void *virt);
14extern int physmem_remove_mapping(void *virt);
15extern void physmem_forget_descriptor(int fd);
16 10
17extern unsigned long uml_physmem; 11extern unsigned long uml_physmem;
18static inline unsigned long to_phys(void *virt) 12static 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
46struct net_kern_info { 46struct 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
53struct transport { 53struct transport {
@@ -62,7 +62,6 @@ struct transport {
62 62
63extern struct net_device *ether_init(int); 63extern struct net_device *ether_init(int);
64extern unsigned short ether_protocol(struct sk_buff *); 64extern unsigned short ether_protocol(struct sk_buff *);
65extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra);
66extern int tap_setup_common(char *str, char *type, char **dev_name, 65extern 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);
68extern void register_transport(struct transport *new); 67extern 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
27extern void ether_user_init(void *data, void *dev); 27extern 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)
130extern int os_stat_file(const char *file_name, struct uml_stat *buf); 128extern int os_stat_file(const char *file_name, struct uml_stat *buf);
131extern int os_stat_fd(const int fd, struct uml_stat *buf); 129extern int os_stat_fd(const int fd, struct uml_stat *buf);
132extern int os_access(const char *file, int mode); 130extern int os_access(const char *file, int mode);
133extern void os_print_error(int error, const char* str);
134extern int os_get_exec_close(int fd, int *close_on_exec); 131extern int os_get_exec_close(int fd, int *close_on_exec);
135extern int os_set_exec_close(int fd, int close_on_exec); 132extern int os_set_exec_close(int fd);
136extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg); 133extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg);
137extern int os_window_size(int fd, int *rows, int *cols);
138extern int os_new_tty_pgrp(int fd, int pid);
139extern int os_get_ifname(int fd, char *namebuf); 134extern int os_get_ifname(int fd, char *namebuf);
140extern int os_set_slip(int fd); 135extern int os_set_slip(int fd);
141extern int os_set_owner(int fd, int pid); 136extern int os_set_owner(int fd, int pid);
142extern int os_mode_fd(int fd, int mode); 137extern int os_mode_fd(int fd, int mode);
143 138
144extern int os_seek_file(int fd, __u64 offset); 139extern int os_seek_file(int fd, unsigned long long offset);
145extern int os_open_file(char *file, struct openflags flags, int mode); 140extern int os_open_file(char *file, struct openflags flags, int mode);
146extern int os_read_file(int fd, void *buf, int len); 141extern int os_read_file(int fd, void *buf, int len);
147extern int os_write_file(int fd, const void *buf, int count); 142extern 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 */
189extern int create_mem_file(unsigned long long len); 180extern int create_mem_file(unsigned long long len);
@@ -194,20 +185,13 @@ extern int os_process_parent(int pid);
194extern void os_stop_process(int pid); 185extern void os_stop_process(int pid);
195extern void os_kill_process(int pid, int reap_child); 186extern void os_kill_process(int pid, int reap_child);
196extern void os_kill_ptraced_process(int pid, int reap_child); 187extern void os_kill_ptraced_process(int pid, int reap_child);
197#ifdef UML_CONFIG_MODE_TT
198extern void os_usr1_process(int pid);
199#endif
200extern long os_ptrace_ldt(long pid, long addr, long data); 188extern long os_ptrace_ldt(long pid, long addr, long data);
201 189
202extern int os_getpid(void); 190extern int os_getpid(void);
203extern int os_getpgrp(void); 191extern int os_getpgrp(void);
204 192
205#ifdef UML_CONFIG_MODE_TT
206extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int));
207extern void stop(void);
208#endif
209extern void init_new_thread_signals(void); 193extern void init_new_thread_signals(void);
210extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr); 194extern int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr);
211 195
212extern int os_map_memory(void *virt, int fd, unsigned long long off, 196extern 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);
218extern int can_drop_memory(void); 202extern int can_drop_memory(void);
219extern void os_flush_stdout(void); 203extern void os_flush_stdout(void);
220 204
221/* tt.c
222 * for tt mode only (will be deleted in future...)
223 */
224extern void forward_ipi(int fd, int pid);
225extern void kill_child_dead(int pid);
226extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
227extern int protect_memory(unsigned long addr, unsigned long len,
228 int r, int w, int x, int must_succeed);
229extern void forward_pending_sigio(int target);
230extern int start_fork_tramp(void *arg, unsigned long temp_stack,
231 int clone_flags, int (*tramp)(void *));
232
233/* uaccess.c */ 205/* uaccess.c */
234extern unsigned long __do_user_copy(void *to, const void *from, int n, 206extern 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);
255extern char *get_umid(void); 227extern char *get_umid(void);
256 228
257/* signal.c */ 229/* signal.c */
230extern void timer_init(void);
258extern void set_sigstack(void *sig_stack, int size); 231extern void set_sigstack(void *sig_stack, int size);
259extern void remove_sigstack(void); 232extern void remove_sigstack(void);
260extern void set_handler(int sig, void (*handler)(int), int flags, ...); 233extern 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 */
268extern void os_fill_handlinfo(struct kern_handlers h); 241extern void os_fill_handlinfo(struct kern_handlers h);
269extern void do_longjmp(void *p, int val);
270 242
271/* util.c */ 243/* util.c */
272extern void stack_protections(unsigned long address); 244extern void stack_protections(unsigned long address);
@@ -277,17 +249,12 @@ extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
277extern void os_dump_core(void); 249extern void os_dump_core(void);
278 250
279/* time.c */ 251/* time.c */
280#define BILLION (1000 * 1000 * 1000) 252extern void idle_sleep(unsigned long long nsecs);
281 253extern int set_interval(void);
282extern void switch_timers(int to_real); 254extern int timer_one_shot(int ticks);
283extern void idle_sleep(int secs); 255extern long long disable_timer(void);
284extern int set_interval(int is_virtual);
285#ifdef CONFIG_MODE_TT
286extern void enable_timer(void);
287#endif
288extern void disable_timer(void);
289extern void uml_idle_timer(void); 256extern void uml_idle_timer(void);
290extern unsigned long long os_nsecs(void); 257extern long long os_nsecs(void);
291 258
292/* skas/mem.c */ 259/* skas/mem.c */
293extern long run_syscall_stub(struct mm_id * mm_idp, 260extern long run_syscall_stub(struct mm_id * mm_idp,
@@ -308,7 +275,9 @@ extern int protect(struct mm_id * mm_idp, unsigned long addr,
308extern int is_skas_winch(int pid, int fd, void *data); 275extern int is_skas_winch(int pid, int fd, void *data);
309extern int start_userspace(unsigned long stub_stack); 276extern int start_userspace(unsigned long stub_stack);
310extern int copy_context_skas0(unsigned long stack, int pid); 277extern int copy_context_skas0(unsigned long stack, int pid);
311extern void userspace(union uml_pt_regs *regs); 278extern void save_registers(int pid, struct uml_pt_regs *regs);
279extern void restore_registers(int pid, struct uml_pt_regs *regs);
280extern void userspace(struct uml_pt_regs *regs);
312extern void map_stub_pages(int fd, unsigned long code, 281extern void map_stub_pages(int fd, unsigned long code,
313 unsigned long data, unsigned long stack); 282 unsigned long data, unsigned long stack);
314extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)); 283extern 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
12extern void init_thread_registers(union uml_pt_regs *to); 12extern void init_thread_registers(struct uml_pt_regs *to);
13extern int save_fp_registers(int pid, unsigned long *fp_regs); 13extern int save_fp_registers(int pid, unsigned long *fp_regs);
14extern int restore_fp_registers(int pid, unsigned long *fp_regs); 14extern int restore_fp_registers(int pid, unsigned long *fp_regs);
15extern void save_registers(int pid, union uml_pt_regs *regs); 15extern int save_fpx_registers(int pid, unsigned long *fp_regs);
16extern void restore_registers(int pid, union uml_pt_regs *regs); 16extern int restore_fpx_registers(int pid, unsigned long *fp_regs);
17extern void save_registers(int pid, struct uml_pt_regs *regs);
18extern void restore_registers(int pid, struct uml_pt_regs *regs);
17extern void init_registers(int pid); 19extern void init_registers(int pid);
18extern void get_safe_registers(unsigned long * regs, unsigned long * fp_regs); 20extern void get_safe_registers(unsigned long *regs);
19extern unsigned long get_thread_reg(int reg, jmp_buf *buf); 21extern 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
12struct 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
21extern 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
11extern unsigned long exec_regs[];
12extern unsigned long exec_fp_regs[];
13extern unsigned long exec_fpx_regs[];
14extern int have_fpx_regs;
15
16extern void kill_off_processes_skas(void); 9extern 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
13extern void flush_thread_skas(void);
14extern void switch_to_skas(void *prev, void *next);
15extern void start_thread_skas(struct pt_regs *regs, unsigned long eip,
16 unsigned long esp);
17extern 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);
20extern void release_thread_skas(struct task_struct *task);
21extern void init_idle_skas(void);
22extern void flush_tlb_kernel_range_skas(unsigned long start,
23 unsigned long end);
24extern void flush_tlb_kernel_vm_skas(void);
25extern void __flush_tlb_one_skas(unsigned long addr);
26extern void flush_tlb_range_skas(struct vm_area_struct *vma,
27 unsigned long start, unsigned long end);
28extern void flush_tlb_mm_skas(struct mm_struct *mm);
29extern void force_flush_all_skas(void);
30extern long execute_syscall_skas(void *r);
31extern void before_mem_skas(unsigned long unused);
32extern unsigned long set_task_sizes_skas(unsigned long *task_size_out);
33extern int start_uml_skas(void);
34extern int external_pid_skas(struct task_struct *task);
35extern int thread_pid_skas(struct task_struct *task);
36extern 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
12extern int userspace_pid[]; 11extern int userspace_pid[];
@@ -15,7 +14,7 @@ extern int skas_needs_stub;
15 14
16extern int user_thread(unsigned long stack, int flags); 15extern int user_thread(unsigned long stack, int flags);
17extern void new_thread_handler(void); 16extern void new_thread_handler(void);
18extern void handle_syscall(union uml_pt_regs *regs); 17extern void handle_syscall(struct uml_pt_regs *regs);
19extern int new_mm(unsigned long stack); 18extern int new_mm(unsigned long stack);
20extern void get_skas_faultinfo(int pid, struct faultinfo * fi); 19extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
21extern long execute_syscall_skas(void *r); 20extern 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
14extern int copy_from_user_skas(void *to, const void __user *from, int n);
15extern int copy_to_user_skas(void __user *to, const void *from, int n);
16extern int strncpy_from_user_skas(char *dst, const char __user *src, int count);
17extern int __clear_user_skas(void __user *mem, int len);
18extern int clear_user_skas(void __user *mem, int len);
19extern 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
18void foo(void) 18void 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
18extern void update_debugregs(int seq);
19#else
20static inline void update_debugregs(int seq) {} 16static 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);
31int get_using_sysemu(void); 25int get_using_sysemu(void);
32extern int sysemu_supported; 26extern 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
68union uml_pt_regs { 55struct 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
90extern 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
135extern int user_context(unsigned long sp); 89extern 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
140struct syscall_args { 93struct 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 169extern 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
39extern unsigned long *sc_sigmask(void *sc_ptr);
40extern 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
24static inline long stub_syscall0(long syscall) 24static 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 87struct 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;
96union 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)
119extern 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
159extern int user_context(unsigned long sp); 129extern 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) \ 236static 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
39extern 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
11struct 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
33extern void force_flush_all(void); 11extern void force_flush_all(void);
34extern 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 **));
39extern int flush_tlb_kernel_range_common(unsigned long start, 12extern 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
10extern int debugger_proxy(int status, pid_t pid);
11extern void child_proxy(pid_t pid, int status);
12extern void init_proxy (pid_t pid, int waiting, int status);
13extern int start_debugger(char *prog, int startup, int stop, int *debugger_fd);
14extern void fake_child_exit(void);
15extern int gdb_config(char *str);
16extern 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
9struct mmu_context_tt {
10};
11
12#endif
diff --git a/arch/um/include/tt/mode-tt.h b/arch/um/include/tt/mode-tt.h
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
11enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
12
13extern int tracing_pid;
14
15extern int tracer(int (*init_proc)(void *), void *sp);
16extern void sig_handler_common_tt(int sig, void *sc);
17extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
18extern void reboot_tt(void);
19extern void halt_tt(void);
20extern int is_tracer_winch(int pid, int fd, void *data);
21extern void kill_off_processes_tt(void);
22
23#endif
diff --git a/arch/um/include/tt/mode_kern_tt.h b/arch/um/include/tt/mode_kern_tt.h
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
14extern void switch_to_tt(void *prev, void *next);
15extern void flush_thread_tt(void);
16extern void start_thread_tt(struct pt_regs *regs, unsigned long eip,
17 unsigned long esp);
18extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
19 unsigned long stack_top, struct task_struct *p,
20 struct pt_regs *regs);
21extern void release_thread_tt(struct task_struct *task);
22extern void initial_thread_cb_tt(void (*proc)(void *), void *arg);
23extern void init_idle_tt(void);
24extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end);
25extern void flush_tlb_kernel_vm_tt(void);
26extern void __flush_tlb_one_tt(unsigned long addr);
27extern void flush_tlb_range_tt(struct vm_area_struct *vma,
28 unsigned long start, unsigned long end);
29extern void flush_tlb_mm_tt(struct mm_struct *mm);
30extern void force_flush_all_tt(void);
31extern long execute_syscall_tt(void *r);
32extern void before_mem_tt(unsigned long brk_start);
33extern unsigned long set_task_sizes_tt(unsigned long *task_size_out);
34extern int start_uml_tt(void);
35extern int external_pid_tt(struct task_struct *task);
36extern 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
11extern int gdb_pid;
12extern int debug;
13extern int debug_stop;
14extern int debug_trace;
15
16extern int honeypot;
17
18extern int fork_tramp(void *sig_stack);
19extern int do_proc_op(void *t, int proc_id);
20extern int tracer(int (*init_proc)(void *), void *sp);
21extern void attach_process(int pid);
22extern void tracer_panic(char *format, ...)
23 __attribute__ ((format (printf, 1, 2)));
24extern void set_init_pid(int pid);
25extern int set_user_mode(void *task);
26extern void set_tracing(void *t, int tracing);
27extern int is_tracing(void *task);
28extern void syscall_handler(int sig, union uml_pt_regs *regs);
29extern void exit_kernel(int pid, void *task);
30extern void do_syscall(void *task, int pid, int local_using_sysemu);
31extern void do_sigtrap(void *task);
32extern int is_valid_pid(int pid);
33extern void remap_data(void *segment_start, void *segment_end, int w);
34extern 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
19extern unsigned long end_vm;
20extern 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
30extern int __do_copy_from_user(void *to, const void *from, int n,
31 void **fault_addr, void **fault_catcher);
32extern int __do_strncpy_from_user(char *dst, const char *src, size_t n,
33 void **fault_addr, void **fault_catcher);
34extern int __do_clear_user(void *mem, size_t len, void **fault_addr,
35 void **fault_catcher);
36extern int __do_strnlen_user(const char *str, unsigned long n,
37 void **fault_addr, void **fault_catcher);
38
39extern int copy_from_user_tt(void *to, const void __user *from, int n);
40extern int copy_to_user_tt(void __user *to, const void *from, int n);
41extern int strncpy_from_user_tt(char *dst, const char __user *src, int count);
42extern int __clear_user_tt(void __user *mem, int len);
43extern int clear_user_tt(void __user *mem, int len);
44extern 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 13typedef 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 22extern void __switch_mm(struct mm_id * mm_idp);
17#include "mmu-skas.h"
18#endif
19 23
20typedef union mm_context { 24/* Avoid tangled inclusion with asm/ldt.h */
21#ifdef UML_CONFIG_MODE_TT 25extern long init_new_ldt(struct mm_context *to_mm, struct mm_context *from_mm);
22 struct mmu_context_tt tt; 26extern 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
41static inline int copy_from_user(void *to, const void __user *from, int n) 30extern int copy_from_user(void *to, const void __user *from, int n);
42{ 31extern 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
47static inline int copy_to_user(void __user *to, const void *from, int n) 33extern 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, 35extern 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
72static inline int strncpy_from_user(char *dst, const char __user *src, int count) 56extern 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 */
89static inline int __clear_user(void *mem, int len) 69extern 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 */
104static inline int clear_user(void __user *mem, int len) 81extern 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 */
120static inline int strnlen_user(const void __user *str, long len) 94extern 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
9extern int __do_copy_to_user(void *to, const void *from, int n,
10 void **fault_addr, void **fault_catcher);
11void __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
22extern void panic(const char *fmt, ...) 24extern 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 :=
9obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \ 9obj-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
14obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o 14obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
15obj-$(CONFIG_GPROF) += gprof_syms.o 15obj-$(CONFIG_GPROF) += gprof_syms.o
16obj-$(CONFIG_GCOV) += gmon_syms.o 16obj-$(CONFIG_GCOV) += gmon_syms.o
17 17
18obj-$(CONFIG_MODE_TT) += tt/
19obj-$(CONFIG_MODE_SKAS) += skas/
20
21USER_OBJS := config.o 18USER_OBJS := config.o
22 19
23include arch/um/scripts/Makefile.rules 20include 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
24void flush_thread(void) 19void 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(&current->thread.arch); 25 arch_flush_thread(&current->thread.arch);
27 CHOOSE_MODE(flush_thread_tt(), flush_thread_skas()); 26
27 ret = unmap(&current->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(&current->mm->context.id);
28} 35}
29 36
30void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) 37void 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);
39static long execve1(char *file, char __user * __user *argv, 48static 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, &current->thread.regs); 61 error = do_execve(file, argv, env, &current->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(&current->thread.regs.regs); 66 SUBARCH_EXECVE1(&current->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
65long um_execve(char *file, char __user *__user *argv, char __user *__user *env) 73long 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
75long sys_execve(char __user *file, char __user *__user *argv, 83long 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
17static struct fs_struct init_fs = INIT_FS; 13static struct fs_struct init_fs = INIT_FS;
18struct mm_struct init_mm = INIT_MM(init_mm); 14struct mm_struct init_mm = INIT_MM(init_mm);
@@ -46,8 +42,3 @@ union thread_union init_thread_union
46union thread_union cpu0_irqstack 42union 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
50void 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');
72skip: 54skip:
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
92extern void free_irqs(void); 73extern void free_irqs(void);
93 74
94void sigio_handler(int sig, union uml_pt_regs *regs) 75void 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
343void 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 */
371unsigned int do_IRQ(int irq, union uml_pt_regs *regs) 333unsigned 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,
396EXPORT_SYMBOL(um_request_irq); 358EXPORT_SYMBOL(um_request_irq);
397EXPORT_SYMBOL(reactivate_fd); 359EXPORT_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 */
401static void dummy(unsigned int irq) 365static 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);
34EXPORT_SYMBOL(high_physmem); 27EXPORT_SYMBOL(high_physmem);
35EXPORT_SYMBOL(empty_zero_page); 28EXPORT_SYMBOL(empty_zero_page);
36EXPORT_SYMBOL(um_virt_to_phys); 29EXPORT_SYMBOL(um_virt_to_phys);
37EXPORT_SYMBOL(mode_tt);
38EXPORT_SYMBOL(handle_page_fault); 30EXPORT_SYMBOL(handle_page_fault);
39EXPORT_SYMBOL(find_iomem); 31EXPORT_SYMBOL(find_iomem);
40 32
41#ifdef CONFIG_MODE_TT 33EXPORT_SYMBOL(strnlen_user);
42EXPORT_SYMBOL(stop); 34EXPORT_SYMBOL(strncpy_from_user);
43EXPORT_SYMBOL(strncpy_from_user_tt); 35EXPORT_SYMBOL(copy_to_user);
44EXPORT_SYMBOL(copy_from_user_tt); 36EXPORT_SYMBOL(copy_from_user);
45EXPORT_SYMBOL(copy_to_user_tt); 37EXPORT_SYMBOL(clear_user);
46#endif
47
48#ifdef CONFIG_MODE_SKAS
49EXPORT_SYMBOL(strnlen_user_skas);
50EXPORT_SYMBOL(strncpy_from_user_skas);
51EXPORT_SYMBOL(copy_to_user_skas);
52EXPORT_SYMBOL(copy_from_user_skas);
53EXPORT_SYMBOL(clear_user_skas);
54#endif
55EXPORT_SYMBOL(uml_strdup); 38EXPORT_SYMBOL(uml_strdup);
56 39
57EXPORT_SYMBOL(os_stat_fd); 40EXPORT_SYMBOL(os_stat_fd);
58EXPORT_SYMBOL(os_stat_file); 41EXPORT_SYMBOL(os_stat_file);
59EXPORT_SYMBOL(os_access); 42EXPORT_SYMBOL(os_access);
60EXPORT_SYMBOL(os_print_error);
61EXPORT_SYMBOL(os_get_exec_close); 43EXPORT_SYMBOL(os_get_exec_close);
62EXPORT_SYMBOL(os_set_exec_close); 44EXPORT_SYMBOL(os_set_exec_close);
63EXPORT_SYMBOL(os_getpid); 45EXPORT_SYMBOL(os_getpid);
@@ -85,9 +67,6 @@ EXPORT_SYMBOL(run_helper);
85EXPORT_SYMBOL(start_thread); 67EXPORT_SYMBOL(start_thread);
86EXPORT_SYMBOL(dump_thread); 68EXPORT_SYMBOL(dump_thread);
87 69
88EXPORT_SYMBOL(do_gettimeofday);
89EXPORT_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
24static int physmem_fd = -1; 16static 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
69unsigned long get_kmem_end(void) 61unsigned 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
125int phys_mapping(unsigned long phys, __u64 *offset_out) 120int 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
56static inline int external_pid(struct task_struct *task) 33static 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
61int pid_to_processor_id(int pid) 39int 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
86extern void arch_switch_to(struct task_struct *from, struct task_struct *to);
87
108void *_switch_to(void *prev, void *next, void *last) 88void *_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
129void interrupt_end(void) 114void 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
137void release_thread(struct task_struct *task)
138{
139 CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task));
140}
141
142void exit_thread(void) 122void exit_thread(void)
143{ 123{
144 unprotect_stack((unsigned long) current_thread);
145} 124}
146 125
147void *get_current(void) 126void *get_current(void)
@@ -149,28 +128,99 @@ void *get_current(void)
149 return current; 128 return current;
150} 129}
151 130
131extern 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 */
137void 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, &current->thread.exec_buf);
154 if (n == 1) {
155 /* Handle any immediate reschedules or signals */
156 interrupt_end();
157 userspace(&current->thread.regs.regs);
158 }
159 else do_exit(0);
160}
161
162/* Called magically, see new_thread_handler above */
163void 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(&current->thread.regs.regs);
184}
185
152int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, 186int 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, &regs->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(&current->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
173out:
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
188unsigned long stack_sp(unsigned long page)
189{
190 return page + PAGE_SIZE - sizeof(void *);
191}
192#endif
193
194void default_idle(void) 236void 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
212void cpu_idle(void) 257void 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
217void *um_virt_to_phys(struct task_struct *task, unsigned long addr, 263void *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
344static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data) 390static 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
364int __init make_proc_sysemu(void) 412int __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
23static inline void set_singlestepping(struct task_struct *child, int on) 15static 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 */
39void ptrace_disable(struct task_struct *child) 31void ptrace_disable(struct task_struct *child)
40{ 32{
41 set_singlestepping(child,0); 33 set_singlestepping(child,0);
42} 34}
43 35
44extern int peek_user(struct task_struct * child, long addr, long data); 36extern 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
247void send_sigtrap(struct task_struct *tsk, union uml_pt_regs *regs, 228void 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 */
266void syscall_trace(union uml_pt_regs *regs, int entryexit) 248void 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
15void (*pm_power_off)(void); 10void (*pm_power_off)(void);
16 11
17#ifdef CONFIG_SMP
18static 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
33static void kill_off_processes(void) 12static 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
41void uml_cleanup(void) 34void 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
48void machine_restart(char * __unused) 41void 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
54void machine_power_off(void) 47void 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
60void machine_halt(void) 53void 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
28EXPORT_SYMBOL(block_signals); 16EXPORT_SYMBOL(block_signals);
29EXPORT_SYMBOL(unblock_signals); 17EXPORT_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(&current->sighand->siglock); 70 spin_lock_irq(&current->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(&current->sighand->siglock); 76 spin_lock_irq(&current->sighand->siglock);
89 sigorsets(&current->blocked, &current->blocked, 77 sigorsets(&current->blocked, &current->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(&current->blocked, signr); 80 sigaddset(&current->blocked, signr);
93 recalc_sigpending(); 81 recalc_sigpending();
94 spin_unlock_irq(&current->sighand->siglock); 82 spin_unlock_irq(&current->sighand->siglock);
@@ -109,14 +97,16 @@ static int kern_do_signal(struct pt_regs *regs)
109 else 97 else
110 oldset = &current->blocked; 98 oldset = &current->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(&current->thread.regs)); 143 is_syscall(PT_REGS_IP(&current->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, &current->saved_sigmask, NULL); 151 sigprocmask(SIG_SETMASK, &current->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
6obj-y := clone.o exec.o mem.o mmu.o process.o syscall.o tlb.o uaccess.o 6obj-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 @@
21void __attribute__ ((__section__ (".__syscall_stub"))) 22void __attribute__ ((__section__ (".__syscall_stub")))
22stub_clone_handler(void) 23stub_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
18void 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(&current->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(&current->mm->context.skas.id);
32}
33
34void 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
11unsigned 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
74int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) 68int 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 = &current->mm->context.skas; 101 from_mm = &current->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
140void destroy_context_skas(struct mm_struct *mm) 135void 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
24void 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
44extern 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 */
49void 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, &current->thread.exec_buf);
65 if(n == 1){
66 /* Handle any immediate reschedules or signals */
67 interrupt_end();
68 userspace(&current->thread.regs.regs);
69 }
70 else do_exit(0);
71}
72
73void release_thread_skas(struct task_struct *task)
74{
75}
76
77/* Called magically, see new_thread_handler above */
78void 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(&current->thread.regs.regs);
97}
98
99int 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, &regs->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(&current->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
126int new_mm(unsigned long stack) 12int 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
140void init_idle_skas(void)
141{
142 cpu_tasks[current_thread->cpu].pid = os_getpid();
143 default_idle();
144} 24}
145 25
146extern void start_kernel(void); 26extern 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
164extern int userspace_pid[]; 44extern int userspace_pid[];
165 45
166extern char cpu0_irqstack[]; 46extern char cpu0_irqstack[];
167 47
168int __init start_uml_skas(void) 48int __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
183int 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
189int 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
195void 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
218unsigned long current_stub_stack(void) 63unsigned 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
16void handle_syscall(union uml_pt_regs *r) 12void 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
19static 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
52extern int proc_mm;
53
54static 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
63void __flush_tlb_one_skas(unsigned long addr)
64{
65 flush_tlb_kernel_range_common(addr, addr + PAGE_SIZE);
66}
67
68void 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
76void 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
90void 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
101void 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
160kill:
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
42static int do_op_one_page(unsigned long addr, int len, int is_write, 38static 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
62static void do_buffer_op(void *jmpbuf, void *arg_ptr) 59static 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
133static int copy_chunk_from_user(unsigned long from, int len, void *arg) 130static 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
142int copy_from_user_skas(void *to, const void __user *from, int n) 139int 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
154static int copy_chunk_to_user(unsigned long to, int len, void *arg) 151static 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
163int copy_to_user_skas(void __user *to, const void *from, int n) 160int 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
175static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) 172static 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
189int strncpy_from_user_skas(char *dst, const char __user *src, int count) 186int 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
209static int clear_chunk(unsigned long addr, int len, void *unused) 206static 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
215int __clear_user_skas(void __user *mem, int len) 212int __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
220int clear_user_skas(void __user *mem, int len) 217int 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
231static int strnlen_chunk(unsigned long str, int len, void *arg) 228static 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
243int strnlen_user_skas(const void __user *str, int len) 240int 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
67static cpumask_t smp_commenced_mask = CPU_MASK_NONE; 67static 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)
95static struct task_struct *idle_thread(int cpu) 95static 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 */
27int nsyscalls = 0; 17int nsyscalls = 0;
@@ -34,7 +24,7 @@ long sys_fork(void)
34 ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs), 24 ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
35 &current->thread.regs, 0, NULL, NULL); 25 &current->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
40long sys_vfork(void) 30long sys_vfork(void)
@@ -46,7 +36,7 @@ long sys_vfork(void)
46 UPT_SP(&current->thread.regs.regs), 36 UPT_SP(&current->thread.regs.regs),
47 &current->thread.regs, 0, NULL, NULL); 37 &current->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 */
93long sys_pipe(unsigned long __user * fildes) 83long 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
24int 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 */
32unsigned long long sched_clock(void) 18unsigned 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 23void timer_handler(int sig, struct uml_pt_regs *regs)
38static unsigned long long prev_nsecs[NR_CPUS]; 24{
39static 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
42void timer_irq(union uml_pt_regs *regs) 32static 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 */ 51static int itimer_next_event(unsigned long delta,
72static DEFINE_SPINLOCK(timer_spinlock); 52 struct clock_event_device *evt)
73static unsigned long long local_offset = 0;
74
75static 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
88irqreturn_t um_timer(int irq, void *dev) 57static 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
68static 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
111static void register_timer(void) 75static cycle_t itimer_read(void)
76{
77 return os_nsecs();
78}
79
80static 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
90static 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
126extern void (*late_time_init)(void); 112extern void (*late_time_init)(void);
127 113
128void time_init(void) 114void __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
139void 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
158static 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
171int 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
178void 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
15struct 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
51static 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
19static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, 84static 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
57static int add_munmap(unsigned long addr, unsigned long len, 119static 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
87static int add_mprotect(unsigned long addr, unsigned long len, 146static 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
121static inline int update_pte_range(pmd_t *pmd, unsigned long addr, 177static 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
161static inline int update_pmd_range(pud_t *pud, unsigned long addr, 210static 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
191static inline int update_pud_range(pgd_t *pgd, unsigned long addr, 232static 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
221void fix_range_common(struct mm_struct *mm, unsigned long start_addr, 254void 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
371void 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
431kill:
432 printk(KERN_ERR "Failed to flush page for address 0x%lx\n", address);
433 force_sig(SIGKILL, current);
343} 434}
344 435
345pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) 436pgd_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
350pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address) 441pud_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
355pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address) 446pmd_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
360pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) 451pte_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
365pte_t *addr_pte(struct task_struct *task, unsigned long addr) 456pte_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
374void flush_tlb_all(void) 465void flush_tlb_all(void)
@@ -378,35 +469,58 @@ void flush_tlb_all(void)
378 469
379void flush_tlb_kernel_range(unsigned long start, unsigned long end) 470void 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
385void flush_tlb_kernel_vm(void) 475void 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
391void __flush_tlb_one(unsigned long addr) 480void __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
485static 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
396void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, 494void 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
403void flush_tlb_mm(struct mm_struct *mm) 502void 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
408void force_flush_all(void) 517void 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 */
38int handle_page_fault(unsigned long address, unsigned long ip, 22int 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
69good_area: 55good_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:
114out: 101out:
115 up_read(&mm->mmap_sem); 102 up_read(&mm->mmap_sem);
116out_nosemaphore: 103out_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
144static void segv_handler(int sig, union uml_pt_regs *regs) 131static 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 */
161unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, 148unsigned 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
226void relay_signal(int sig, union uml_pt_regs *regs) 217void 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
242static void bus_handler(int sig, union uml_pt_regs *regs) 233static 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
249static void winch(int sig, union uml_pt_regs *regs) 240static 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
6obj-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
10obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/
11
12USER_OBJS := gdb.o tracer.o
13
14include 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
20static 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
28void 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
65void 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
18void 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
24extern int debugger_pid;
25extern int debugger_fd;
26extern int debugger_parent;
27
28int detach(int pid, int sig)
29{
30 return(ptrace(PTRACE_DETACH, pid, 0, sig));
31}
32
33int 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
42int cont(int pid)
43{
44 return(ptrace(PTRACE_CONT, pid, 0, 0));
45}
46
47#ifdef UML_CONFIG_PT_PROXY
48
49int debugger_signal(int status, pid_t pid)
50{
51 return(debugger_proxy(status, pid));
52}
53
54void child_signal(pid_t pid, int status)
55{
56 child_proxy(pid, status);
57}
58
59static void gdb_announce(char *dev_name, int dev)
60{
61 printf("gdb assigned device '%s'\n", dev_name);
62}
63
64static 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 */
73static void *xterm_data;
74static int xterm_fd;
75
76extern void *xterm_init(char *, int, struct chan_opts *);
77extern int xterm_open(int, int, int, void *, char **);
78extern void xterm_close(int, void *);
79
80int 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
90static 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
105static void exit_debugger(void)
106{
107 initial_thread_cb(exit_debugger_cb, NULL);
108}
109
110__uml_exitcall(exit_debugger);
111
112struct gdb_data {
113 char *str;
114 int err;
115};
116
117extern char *linux_prog;
118
119static 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
143int 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
153void remove_gdb_cb(void *unused)
154{
155 exit_debugger_cb(NULL);
156}
157
158int gdb_remove(int unused, char **error_out)
159{
160 initial_thread_cb(remove_gdb_cb, NULL);
161 return 0;
162}
163
164void 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
174int 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
188int 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 */
203static 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
214static 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
229int debugger_signal(int status, pid_t pid){ return(0); }
230void child_signal(pid_t pid, int status){ }
231int 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
238void signal_usr1(int sig)
239{
240 printf("debug requested when CONFIG_PT_PROXY is off\n");
241}
242
243int 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
250int config_gdb(char *str)
251{
252 return(-1);
253}
254
255int remove_gdb(void)
256{
257 return(-1);
258}
259
260int init_parent_proxy(int pid)
261{
262 return(-1);
263}
264
265void 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
11extern int gdb_config(char *str, char **error_out);
12extern int gdb_remove(int n, char **error_out);
13
14static 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
21int 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
11enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
12
13extern int tracing_pid;
14
15extern int tracer(int (*init_proc)(void *), void *sp);
16extern void sig_handler_common_tt(int sig, void *sc);
17extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
18extern void reboot_tt(void);
19extern void halt_tt(void);
20extern int is_tracer_winch(int pid, int fd, void *data);
21extern void kill_off_processes_tt(void);
22
23#endif
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
10EXPORT_SYMBOL(__do_copy_from_user);
11EXPORT_SYMBOL(__do_copy_to_user);
12EXPORT_SYMBOL(__do_strncpy_from_user);
13EXPORT_SYMBOL(__do_strnlen_user);
14EXPORT_SYMBOL(__do_clear_user);
15EXPORT_SYMBOL(clear_user_tt);
16
17EXPORT_SYMBOL(tracing_pid);
18EXPORT_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
14void 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
25unsigned 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
16void 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
27void 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
93void 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
111void 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
122void schedule_tail(struct task_struct *prev);
123
124static 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(&current->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(&current->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, &current->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
163static 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
196void finish_fork_handler(int sig)
197{
198 UPT_SC(&current->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
220int 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
231int 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(&regs->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
290void reboot_tt(void)
291{
292 current->thread.request.op = OP_REBOOT;
293 os_usr1_process(os_getpid());
294 change_sig(SIGUSR1, 1);
295}
296
297void halt_tt(void)
298{
299 current->thread.request.op = OP_HALT;
300 os_usr1_process(os_getpid());
301 change_sig(SIGUSR1, 1);
302}
303
304void 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
318void 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
334int 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
370void init_idle_tt(void)
371{
372 default_idle();
373}
374
375extern void start_kernel(void);
376
377static 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
394void set_tracing(void *task, int tracing)
395{
396 ((struct task_struct *) task)->thread.mode.tt.tracing = tracing;
397}
398
399int is_tracing(void *t)
400{
401 return (((struct task_struct *) t)->thread.mode.tt.tracing);
402}
403
404int 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
416void 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
427int 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
438int external_pid_tt(struct task_struct *task)
439{
440 return(task->thread.mode.tt.extern_pid);
441}
442
443int thread_pid_tt(struct task_struct *task)
444{
445 return(task->thread.mode.tt.extern_pid);
446}
447
448int 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
6obj-y = proxy.o ptrace.o sysdep.o wait.o
7
8USER_OBJS := $(obj-y)
9
10include 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/**********************************************************************
2proxy.c
3
4Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
5terms and conditions.
6
7Jeff 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
33static 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
72int 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 */
127static debugger_state parent;
128static int parent_syscall(debugger_state *debugger, int pid);
129
130int 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
143int 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
150static 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
169int 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
176void 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 */
184static debugger_state debugger;
185static debugee_state debugee;
186
187void 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
206int 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
244void 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
263void 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
274void 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
299char gdb_init_string[] =
300"att 1 \n\
301b panic \n\
302b stop \n\
303handle SIGWINCH nostop noprint pass \n\
304";
305
306int 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/**********************************************************************
2ptproxy.h
3
4Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
5terms and conditions.
6**********************************************************************/
7
8#ifndef __PTPROXY_H
9#define __PTPROXY_H
10
11#include <sys/types.h>
12
13typedef struct debugger debugger_state;
14typedef struct debugee debugee_state;
15
16struct 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
29struct 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
43extern int debugger_syscall(debugger_state *debugger, pid_t pid);
44extern int debugger_normal_return (debugger_state *debugger, pid_t unused);
45
46extern long proxy_ptrace (struct debugger *, int, pid_t, long, long, pid_t,
47 int *strace_out);
48extern 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/**********************************************************************
2ptrace.c
3
4Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
5terms and conditions.
6
7Jeff 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
24long 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/**********************************************************************
2sysdep.c
3
4Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
5terms 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
19int 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
30void 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
42void syscall_set_result(pid_t pid, long result)
43{
44 ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result);
45}
46
47void syscall_continue(pid_t pid)
48{
49 ptrace(PTRACE_SYSCALL, pid, 0, 0);
50}
51
52int 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/**********************************************************************
2sysdep.h
3
4Copyright (C) 1999 Lars Brinkhoff.
5Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
6See the file COPYING for licensing terms and conditions.
7**********************************************************************/
8
9extern int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3,
10 long *arg4, long *arg5);
11extern void syscall_cancel (pid_t pid, long result);
12extern void syscall_set_result (pid_t pid, long result);
13extern void syscall_continue (pid_t pid);
14extern 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/**********************************************************************
2wait.c
3
4Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
5terms 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
20int 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
48int parent_wait_return(struct debugger *debugger, pid_t unused)
49{
50 return(debugger_normal_return(debugger, -1));
51}
52
53int 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/**********************************************************************
2wait.h
3
4Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
5terms and conditions.
6**********************************************************************/
7
8#ifndef __PTPROXY_WAIT_H
9#define __PTPROXY_WAIT_H
10
11extern int proxy_wait_return(struct debugger *debugger, pid_t unused);
12extern int real_wait_return(struct debugger *debugger);
13extern 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
19void syscall_handler_tt(int sig, struct pt_regs *regs)
20{
21 void *sc;
22 long result;
23 int syscall;
24
25 sc = UPT_SC(&regs->regs);
26 SC_START_SYSCALL(sc);
27
28 syscall = UPT_SYSCALL_NR(&regs->regs);
29 syscall_trace(&regs->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(&regs->regs) = sc;
42
43 SC_SET_SYSCALL_RETURN(sc, result);
44
45 syscall_trace(&regs->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
18void do_sigtrap(void *task)
19{
20 UPT_SYSCALL_NR(TASK_REGS(task)) = -1;
21}
22
23void 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
19static 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
57static 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
68atomic_t vmchange_seq = ATOMIC_INIT(1);
69
70void 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
76void flush_tlb_kernel_vm_tt(void)
77{
78 flush_tlb_kernel_range(start_vm, end_vm);
79}
80
81void __flush_tlb_one_tt(unsigned long addr)
82{
83 flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
84}
85
86void 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
101void 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
116void 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
31static int tracer_winch[2];
32
33int 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
42static 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
54static 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
66void 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
78void 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
89static 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 */
100int debug = 0;
101int debug_stop = 1;
102int debug_parent = 0;
103int honeypot = 0;
104
105static 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
126static 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 */
163int debugger_pid = -1;
164int debugger_parent = -1;
165int debugger_fd = -1;
166int gdb_pid = -1;
167
168struct {
169 int pid;
170 int signal;
171 unsigned long addr;
172 struct timeval time;
173} signal_record[1024][32];
174
175int signal_index[32];
176int nsignals = 0;
177int debug_trace = 0;
178
179extern void signal_usr1(int sig);
180
181int tracing_pid = -1;
182
183int 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
410static 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
439static 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
16void 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
9int 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, &current->thread.fault_addr,
15 &current->thread.fault_catcher));
16}
17
18int 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, &current->thread.fault_addr,
24 &current->thread.fault_catcher));
25}
26
27int 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 &current->thread.fault_addr,
36 &current->thread.fault_catcher);
37 if(n < 0) return(-EFAULT);
38 return(n);
39}
40
41int __clear_user_tt(void __user *mem, int len)
42{
43 return(__do_clear_user(mem, len,
44 &current->thread.fault_addr,
45 &current->thread.fault_catcher));
46}
47
48int 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, &current->thread.fault_addr,
54 &current->thread.fault_catcher));
55}
56
57int strnlen_user_tt(const void __user *str, int len)
58{
59 return(__do_strnlen_user(str, len,
60 &current->thread.fault_addr,
61 &current->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
14int __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
36static void __do_strncpy(void *dst, const void *src, int count)
37{
38 strncpy(dst, src, count);
39}
40
41int __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
56static void __do_clear(void *to, const void *from, int n)
57{
58 memset(to, 0, n);
59}
60
61int __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
76int __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
20int __do_copy_to_user(void *to, const void *from, int n, 20int __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
71unsigned long thread_saved_pc(struct task_struct *task) 49unsigned 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 */
133int ncpus = 1; 111int 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 */
140static char *argv1_begin = NULL;
141static char *argv1_end = NULL;
142#endif
143
144/* Set in early boot */ 113/* Set in early boot */
145static int have_root __initdata = 0; 114static 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 */
148long long physmem_size = 32 * 1024 * 1024; 117long long physmem_size = 32 * 1024 * 1024;
149 118
150void set_cmdline(char *cmd) 119static 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
172static 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
206static int __init no_skas_debug_setup(char *line, int *add) 151static 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
223static int __init uml_ncpus_setup(char *line, int *add) 165static 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
239static int force_tt = 0;
240
241#if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS)
242#define DEFAULT_TT 0
243
244static 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
255static 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
266static 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
283int mode_tt = DEFAULT_TT;
284
285static int __init Usage(char *line, int *add) 181static 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
340extern char __binary_start; 235extern char __binary_start;
341 236
237static 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
342int __init linux_main(int argc, char **argv) 251int __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
468extern int uml_exitcode; 361extern 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
6obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \ 6obj-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
10obj-$(CONFIG_MODE_SKAS) += skas/
11
12obj-$(CONFIG_MODE_TT) += tt.o
13user-objs-$(CONFIG_MODE_TT) += tt.o
14 9
15obj-$(CONFIG_TTY_LOG) += tty_log.o 10obj-$(CONFIG_TTY_LOG) += tty_log.o
16user-objs-$(CONFIG_TTY_LOG) += tty_log.o 11user-objs-$(CONFIG_TTY_LOG) += tty_log.o
17 12
18USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \ 13USER_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
22CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) 17CFLAGS_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
19struct aio_thread_req { 18struct 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
224out_close_pipe: 228out_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;
229out: 233out:
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
8struct ethertap_data { 11struct ethertap_data {
@@ -15,13 +18,4 @@ struct ethertap_data {
15 18
16extern const struct net_user_info ethertap_user_info; 19extern 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
15struct ethertap_init { 14struct 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
40static int etap_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) 39static 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
54static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) 53static 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
68const struct net_kern_info ethertap_kern_info = { 59const 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
93static struct transport ethertap_transport = { 84static struct transport ethertap_transport = {
@@ -97,6 +88,7 @@ static struct transport ethertap_transport = {
97 .user = &ethertap_user_info, 88 .user = &ethertap_user_info,
98 .kern = &ethertap_kern_info, 89 .kern = &ethertap_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
102static int register_ethertap(void) 94static 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
94static int etap_tramp(char *dev, char *gate, int control_me, 93static 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
195out_close_control:
196 close(control_fds[0]);
197 close(control_fds[1]);
198out_close_data:
199 close(data_fds[0]);
200 close(data_fds[1]);
201 return err;
188} 202}
189 203
190static void etap_close(int fd, void *data) 204static 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
203static int etap_set_mtu(int mtu, void *data)
204{
205 return mtu;
206}
207
208static void etap_add_addr(unsigned char *addr, unsigned char *netmask, 225static 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
219static void etap_del_addr(unsigned char *addr, unsigned char *netmask, 236static 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 {
19extern const struct net_user_info tuntap_user_info; 19extern 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
16struct tuntap_init { 13struct 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
41static int tuntap_read(int fd, struct sk_buff **skb, 38static 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
50static int tuntap_write(int fd, struct sk_buff **skb, 44static 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
56const struct net_kern_info tuntap_kern_info = { 49const 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
77static struct transport tuntap_transport = { 70static 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
26static int tuntap_user_init(void *data, void *dev) 21static 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
68static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, 63static 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
206static int tuntap_set_mtu(int mtu, void *data)
207{
208 return mtu;
209}
210
211const struct net_user_info tuntap_user_info = { 207const 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
85void 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) */
93int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg) 86int 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
104int 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
117int 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 */
129int os_get_ifname(int fd, char* namebuf) 98int 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
223int os_open_file(char *file, struct openflags flags, int mode) 192int 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
250int os_connect_socket(char *name) 219int 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
283int os_seek_file(int fd, __u64 offset) 252int 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
346int os_file_modtime(char *file, unsigned long *modtime) 317int 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
361int os_get_exec_close(int fd, int* close_on_exec) 332int 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
376int os_set_exec_close(int fd, int close_on_exec) 345int 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
392int os_pipe(int *fds, int stream, int close_on_exec) 356int 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
420int os_set_fd_async(int fd, int owner) 384int 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 */
30char *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
228extern void *__real_malloc(int); 190extern void *__real_malloc(int);
229 191
230void *__wrap_malloc(int size) 192void *__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 @@
32unsigned long os_process_pc(int pid) 29unsigned 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)
99void os_kill_process(int pid, int reap_child) 100void 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
137void 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
173int os_protect_memory(void *addr, unsigned long len, int r, int w, int x) 166int 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
183int os_unmap_memory(void *addr, int len) 177int 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
243void 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
266void init_new_thread_signals(void) 238void 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
286int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) 255int 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
15static unsigned long exec_regs[MAX_REG_NR];
16
17void init_thread_registers(struct uml_pt_regs *to)
18{
19 memcpy(to->gp, exec_regs, sizeof(to->gp));
20}
21
22void 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
32void 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
42void 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
54void 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
62static void real_alarm_handler(int sig, struct sigcontext *sc) 54static 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(&regs, sc); 59 copy_sc(&regs, sc);
71 regs.skas.is_user = 0; 60 regs.is_user = 0;
72 unblock_signals(); 61 unblock_signals();
73 timer_handler(sig, &regs); 62 timer_handler(SIGVTALRM, &regs);
74
75 if(sig == SIGALRM)
76 switch_timers(1);
77} 63}
78 64
79void alarm_handler(int sig, struct sigcontext *sc) 65void 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
81void timer_init(void)
82{
83 set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
84 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, -1);
85}
86
98void set_sigstack(void *sig_stack, int size) 87void 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
160extern void hard_handler(int sig); 150extern 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
200void block_signals(void) 190void 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)
276int set_signals(int enable) 269int 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
30extern unsigned long batch_syscall_stub, __syscall_stub_start; 25extern unsigned long batch_syscall_stub, __syscall_stub_start;
31 26
@@ -34,7 +29,7 @@ extern void wait_stub_done(int pid);
34static inline unsigned long *check_init_stack(struct mm_id * mm_idp, 29static 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
46static int __init init_syscall_regs(void) 41static 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
299void 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
39int is_skas_winch(int pid, int fd, void *data) 29int 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
48static int ptrace_dump_regs(int pid) 38static 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
94bad_wait: 83bad_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
134static void handle_segv(int pid, union uml_pt_regs * regs) 125static void handle_segv(int pid, struct uml_pt_regs * regs)
135{ 126{
136 get_skas_faultinfo(pid, &regs->skas.faultinfo); 127 get_skas_faultinfo(pid, &regs->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/*
141static 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 */
135static 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
289void userspace(union uml_pt_regs *regs) 288void 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, &regs->skas.faultinfo); 331 !ptrace_faultinfo) {
332 get_skas_faultinfo(pid,
333 &regs->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
359static unsigned long thread_regs[MAX_REG_NR]; 380static unsigned long thread_regs[MAX_REG_NR];
360static unsigned long thread_fp_regs[HOST_FP_SIZE];
361 381
362static int __init init_thread_regs(void) 382static 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
379int copy_context_skas0(unsigned long new_stack, int pid) 399int 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
505void switch_threads(jmp_buf *me, jmp_buf *you) 526void 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
587void switch_mm_skas(struct mm_id *mm_idp) 607void __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
18static union uml_pt_regs ksig_regs[UM_NR_CPUS]; 22static struct uml_pt_regs ksig_regs[UM_NR_CPUS];
19 23
20void sig_handler_common_skas(int sig, void *sc_ptr) 24void 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
46static int ptrace_child(void *arg) 28static 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
104static int start_ptraced_child(void **stack_out) 94static 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 */
136static int stop_ptraced_child(int pid, void *stack, int exitcode, 120static 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
208static void __init check_sysemu(void) 189static 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
292fail: 273fail:
293 stop_ptraced_child(pid, stack, 1, 0); 274 stop_ptraced_child(pid, 1, 0);
294fail_stopped: 275fail_stopped:
295 non_fatal("missing\n"); 276 non_fatal("missing\n");
296} 277}
297 278
298static void __init check_ptrace(void) 279static 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
412static inline void check_skas3_ptrace_faultinfo(void) 391static 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
440static inline void check_skas3_ptrace_ldt(void) 418static 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
495int can_do_skas(void) 469int 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
509int can_do_skas(void)
510{
511 return 0;
512}
513#endif
514 482
515int __init parse_iomem(char *str, int *add) 483int __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
6obj-$(CONFIG_MODE_SKAS) = registers.o signal.o tls.o 6obj-y = registers.o signal.o tls.o
7 7
8USER_OBJS := $(obj-y) 8USER_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
18static unsigned long exec_regs[MAX_REG_NR];
19static unsigned long exec_fp_regs[HOST_FP_SIZE];
20static unsigned long exec_fpx_regs[HOST_XFP_SIZE];
21static int have_fpx_regs = 1;
22
23void 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 */
34int save_fp_registers(int pid, unsigned long *fp_regs) 13int 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
41int restore_fp_registers(int pid, unsigned long *fp_regs) 20int 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
48static int move_registers(int pid, int int_op, union uml_pt_regs *regs, 27int 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
60void save_registers(int pid, union uml_pt_regs *regs) 34int 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
80void restore_registers(int pid, union uml_pt_regs *regs) 41unsigned 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
100void init_registers(int pid) 57int have_fpx_regs = 1;
58
59void 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
126void 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
134unsigned 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
6obj-$(CONFIG_MODE_SKAS) = registers.o prctl.o signal.o 6obj-y = registers.o prctl.o signal.o
7 7
8USER_OBJS := $(obj-y) 8USER_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
18static unsigned long exec_regs[MAX_REG_NR];
19static unsigned long exec_fp_regs[HOST_FP_SIZE];
20
21int save_fp_registers(int pid, unsigned long *fp_regs) 13int 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
35void 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
41static 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
53void 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
63void 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
73void 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
88void 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
96unsigned long get_thread_reg(int reg, jmp_buf *buf) 27unsigned 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
20int set_interval(int is_virtual) 15int 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 27int timer_one_shot(int ticks)
34void 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
40void 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
52void 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 */
52static 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 58long long disable_timer(void)
75void 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
86unsigned long long os_nsecs(void) 69long 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
94void idle_sleep(int secs) 77extern void alarm_handler(int sig, struct sigcontext *sc);
78
79void 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
37int os_get_thread_area(user_desc_t *info, int pid) 26int 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
53int 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
64int 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
13void 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() */
19void (*sig_info[NSIG])(int, union uml_pt_regs *); 11void (*sig_info[NSIG])(int, struct uml_pt_regs *);
20 12
21void os_fill_handlinfo(struct kern_handlers h) 13void 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
35void 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
36int 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
50void 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
64void stop(void)
65{
66 while(1) sleep(1000000);
67}
68
69int 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
112void 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
128struct 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
138int sigkill = SIGKILL;
139
140int 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
153int 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
187void 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
10unsigned long __do_user_copy(void *to, const void *from, int n, 10unsigned 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 */
76static int remove_files_and_dir(char *dir) 80static 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
228int __init set_umid(char *name) 235int __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
303static int __init make_umid_init(void) 312static 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
343static int __init set_uml_dir(char *name, int *add) 353static 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
106void os_dump_core(void) 106void 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
25define unprofile 25define unprofile
26 $(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1))) 26 $(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
27endef 27endef
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
1obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ 5obj-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
5obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
6
7subarch-obj-y = lib/bitops_32.o lib/semaphore_32.o lib/string_32.o 9subarch-obj-y = lib/bitops_32.o lib/semaphore_32.o lib/string_32.o
8subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o 10subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o
9subarch-obj-$(CONFIG_MODULES) += kernel/module_32.o 11subarch-obj-$(CONFIG_MODULES) += kernel/module_32.o
10 12
11USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o 13USER_OBJS := bugs.o ptrace_user.o fault.o
12 14
13USER_OBJS += user-offsets.s 15USER_OBJS += user-offsets.s
14extra-y += user-offsets.s 16extra-y += user-offsets.s
15 17
16extra-$(CONFIG_MODE_TT) += unmap.o
17
18UNPROFILE_OBJS := stub_segv.o 18UNPROFILE_OBJS := stub_segv.o
19CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING) 19CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
20 20
21include arch/um/scripts/Makefile.rules 21include 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 */
128static void disable_lcall(void) 132static 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
165int arch_handle_signal(int sig, union uml_pt_regs *regs) 170int 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
15const struct exception_table_entry *search_exception_tables(unsigned long add); 15const 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() */
18int arch_fixup(unsigned long address, union uml_pt_regs *regs) 18int 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"
20extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
21
22#ifdef CONFIG_MODE_TT
23
24static 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
79out:
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
14extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
92 15
93long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, 16long 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 != &current->active_mm->context.skas.id) 36 mm_idp != &current->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 != &current->active_mm->context.skas.id) 82 mm_idp != &current->active_mm->context.id)
158 switch_mm_skas(&current->active_mm->context.skas.id); 83 __switch_mm(&current->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 = &current->mm->context.skas.ldt; 138 uml_ldt_t * ldt = &current->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
256out: 181out:
@@ -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
278static int write_ldt(void __user * ptr, unsigned long bytecount, int func) 204static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
279{ 205{
280 uml_ldt_t * ldt = &current->mm->context.skas.ldt; 206 uml_ldt_t * ldt = &current->mm->context.ldt;
281 struct mm_id * mm_idp = &current->mm->context.skas.id; 207 struct mm_id * mm_idp = &current->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
461long init_new_ldt(struct mmu_context_skas * new_mm, 387long 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, &copy, sizeof(copy)); 445 i = os_write_file(new_mm->id.u.mm_fd, &copy, 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
560void free_ldt(struct mmu_context_skas * mm) 485void 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
574int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) 497int 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
17void arch_switch_to_tt(struct task_struct *from, struct task_struct *to) 11extern 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
23void arch_switch_to_skas(struct task_struct *from, struct task_struct *to) 13void 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
35int is_syscall(unsigned long addr) 26int 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
97int poke_user(struct task_struct *child, long addr, long data) 88int 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
116unsigned long getreg(struct task_struct *child, int regno) 107unsigned 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. */
136int peek_user(struct task_struct *child, long addr, long data) 128int 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
157struct i387_fxsave_struct { 148int 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
177static 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
191static 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/* 165int 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
241static 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
271static inline int convert_fxsr_to_user(struct _fpstate __user *buf, 178int 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));
278static 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
309static 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
315int 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
325int 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
336int 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
349int 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
355int 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
368int 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
374int 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 195int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
391static 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
409static inline void copy_fpu_fxsave(struct pt_regs *regs, 208long 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
415int 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
19int ptrace_getregs(long pid, unsigned long *regs_out) 9int 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
49static 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
66static 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 */
80static unsigned long kernel_debugregs[8] = { [ 0 ... 7 ] = 0 };
81
82void arch_enter_kernel(void *task, int pid)
83{
84 read_debugregs(pid, TASK_DEBUGREGS(task));
85 write_debugregs(pid, kernel_debugregs);
86}
87
88void 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 */
96static int debugregs_seq;
97
98/* Only called by the ptrace proxy */
99void 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
112static 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 */
120void 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
13void 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
22unsigned long *sc_sigmask(void *sc_ptr)
23{
24 struct sigcontext *sc = sc_ptr;
25 return &sc->oldmask;
26}
27
28int 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
21void copy_sc(union uml_pt_regs *regs, void *from) 13void 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
43static int copy_sc_from_user_skas(struct pt_regs *regs, 35/*
44 struct sigcontext __user *from) 36 * FPU tag word conversions.
37 */
38
39static 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)); 53static 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(&regs->regs, &sc); 98static 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
67int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *to_fp, 131static 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 = &current->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 165extern int have_fpx_regs;
114 166
115/* These copy a sigcontext to/from userspace. They copy the fpstate pointer, 167static 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 */
123int 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(&regs->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
142int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp, 220static 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 = &current->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
167static 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
177static 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
185static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __user *fp, 288static 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(&current->sighand->siglock); 466 spin_unlock_irq(&current->sighand->siglock);
363 467
364 if(copy_sc_from_user(&current->thread.regs, sc)) 468 if (copy_sc_from_user(&current->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)
376long sys_rt_sigreturn(struct pt_regs regs) 480long sys_rt_sigreturn(struct pt_regs regs)
377{ 481{
378 unsigned long sp = PT_REGS_SP(&current->thread.regs); 482 unsigned long sp = PT_REGS_SP(&current->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(&current->sighand->siglock); 497 spin_unlock_irq(&current->sighand->siglock);
393 498
394 if(copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext)) 499 if (copy_sc_from_user(&current->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
7batch_syscall_stub: 8batch_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
11again: 12again:
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
46done: 47done:
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 @@
31static int host_supports_tls = -1; 18static int host_supports_tls = -1;
32int host_gdt_entry_tls_min; 19int host_gdt_entry_tls_min;
33 20
34#ifdef CONFIG_MODE_SKAS 21int do_set_thread_area(struct user_desc *info)
35int 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
46int do_get_thread_area_skas(struct user_desc *info) 32int 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 */
130static inline int needs_TLS_update(struct task_struct *task) 120static 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 */
151void clear_flushed_tls(struct task_struct *task) 145void 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
176int arch_switch_tls_skas(struct task_struct *from, struct task_struct *to) 175int 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
190int 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
201static int set_tls_entry(struct task_struct* task, struct user_desc *info, 191static 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
253out: 243out:
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;
263clear: 255clear:
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 */
368static int __init __setup_host_supports_tls(void) 363static 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
9static int errno;
10
11static inline _syscall2(int,munmap,void *,start,size_t,len)
12static inline _syscall6(void *,mmap2,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset)
13int 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
7obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ 7obj-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
11obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
12obj-$(CONFIG_MODULES) += um_module.o 11obj-$(CONFIG_MODULES) += um_module.o
13 12
14subarch-obj-y = lib/bitops_64.o lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o 13subarch-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
17ldt-y = ../sys-i386/ldt.o 16ldt-y = ../sys-i386/ldt.o
18 17
19USER_OBJS := ptrace_user.o sigcontext.o 18USER_OBJS := ptrace_user.o
20 19
21USER_OBJS += user-offsets.s 20USER_OBJS += user-offsets.s
22extra-y += user-offsets.s 21extra-y += user-offsets.s
23 22
24extra-$(CONFIG_MODE_TT) += unmap.o
25
26UNPROFILE_OBJS := stub_segv.o 23UNPROFILE_OBJS := stub_segv.o
27CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING) 24CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
28 25
29include arch/um/scripts/Makefile.rules 26include 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
17int arch_handle_signal(int sig, union uml_pt_regs *regs) 17int 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
16const struct exception_table_entry *search_exception_tables(unsigned long add); 16const struct exception_table_entry *search_exception_tables(unsigned long add);
17int arch_fixup(unsigned long address, union uml_pt_regs *regs) 17
18int 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/*
16unsigned long not_ss; 17 * determines which flags the user has access to.
17unsigned long not_ds; 18 * 1 = access 0 = no access
18unsigned 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
28int putreg(struct task_struct *child, int regno, unsigned long value) 22int 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
67int poke_user(struct task_struct *child, long addr, long data) 61int 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
85unsigned long getreg(struct task_struct *child, int regno) 80unsigned long getreg(struct task_struct *child, int regno)
@@ -107,29 +102,22 @@ unsigned long getreg(struct task_struct *child, int regno)
107int peek_user(struct task_struct *child, long addr, long data) 102int 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
128void 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
159int get_fpregs(unsigned long buf, struct task_struct *child) 147int 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
165int 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
171int get_fpxregs(unsigned long buf, struct task_struct *tsk) 164int 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
177int set_fpxregs(unsigned long buf, struct task_struct *tsk) 177long 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
12void 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
24unsigned 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
23void copy_sc(union uml_pt_regs *regs, void *from) 15void 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
53static int copy_sc_from_user_skas(struct pt_regs *regs, 45static 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
87int copy_sc_to_user_skas(struct sigcontext __user *to, 96static 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 = &current->thread.arch.faultinfo; 100 struct faultinfo * fi = &current->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 "
140int 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
159int 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;
184static 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
194static 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
204struct rt_sigframe 160struct 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(&current->sighand->siglock); 278 spin_unlock_irq(&current->sighand->siglock);
325 279
326 if(copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext)) 280 if (copy_sc_from_user(&current->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(&current->thread.regs) = -1; 285 PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
331 return(PT_REGS_SYSCALL_RET(&current->thread.regs)); 286 return PT_REGS_SYSCALL_RET(&current->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
18batch_syscall_stub: 19batch_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
21asmlinkage long sys_uname64(struct new_utsname __user * name) 15asmlinkage 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
33extern long arch_prctl(int code, unsigned long addr);
34
35static 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
62long arch_prctl_skas(struct task_struct *task, int code, 29long 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, &current->thread.regs.regs); 51 restore_registers(pid, &current->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, &current->thread.regs.regs); 73 save_registers(pid, &current->thread.regs.regs);
108 break; 74 break;
109 case ARCH_SET_GS: 75 case ARCH_SET_GS:
110 save_registers(pid, &current->thread.regs.regs); 76 save_registers(pid, &current->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
124long sys_arch_prctl(int code, unsigned long addr) 89long 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
130long sys_clone(unsigned long clone_flags, unsigned long newsp, 94long 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
144void arch_switch_to_skas(struct task_struct *from, struct task_struct *to) 108void 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
9static int errno;
10
11static inline _syscall2(int,munmap,void *,start,size_t,len)
12static inline _syscall6(void *,mmap,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset)
13int 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 */
14typedef __u64 u64;
15typedef __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))