Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
46356545
Commit
46356545
authored
Oct 15, 2002
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge UML update
parents
0789ed0a
1171e981
Changes
55
Hide whitespace changes
Inline
Side-by-side
Showing
55 changed files
with
767 additions
and
396 deletions
+767
-396
arch/um/config.in
arch/um/config.in
+5
-0
arch/um/drivers/chan_user.c
arch/um/drivers/chan_user.c
+2
-0
arch/um/drivers/harddog_kern.c
arch/um/drivers/harddog_kern.c
+3
-1
arch/um/drivers/hostaudio_kern.c
arch/um/drivers/hostaudio_kern.c
+1
-0
arch/um/drivers/line.c
arch/um/drivers/line.c
+18
-4
arch/um/drivers/mconsole_kern.c
arch/um/drivers/mconsole_kern.c
+25
-3
arch/um/drivers/mconsole_user.c
arch/um/drivers/mconsole_user.c
+8
-2
arch/um/drivers/mmapper_kern.c
arch/um/drivers/mmapper_kern.c
+2
-1
arch/um/drivers/net_kern.c
arch/um/drivers/net_kern.c
+20
-3
arch/um/drivers/port_kern.c
arch/um/drivers/port_kern.c
+9
-4
arch/um/drivers/ssl.c
arch/um/drivers/ssl.c
+4
-1
arch/um/drivers/stdio_console.c
arch/um/drivers/stdio_console.c
+9
-0
arch/um/drivers/ubd_kern.c
arch/um/drivers/ubd_kern.c
+105
-40
arch/um/drivers/ubd_user.c
arch/um/drivers/ubd_user.c
+4
-0
arch/um/drivers/xterm.c
arch/um/drivers/xterm.c
+1
-0
arch/um/include/2_5compat.h
arch/um/include/2_5compat.h
+0
-2
arch/um/include/irq_user.h
arch/um/include/irq_user.h
+3
-1
arch/um/include/kern_util.h
arch/um/include/kern_util.h
+3
-7
arch/um/include/mconsole.h
arch/um/include/mconsole.h
+2
-0
arch/um/include/sigio.h
arch/um/include/sigio.h
+2
-0
arch/um/include/time_user.h
arch/um/include/time_user.h
+3
-3
arch/um/kernel/exec_kern.c
arch/um/kernel/exec_kern.c
+2
-1
arch/um/kernel/exitcode.c
arch/um/kernel/exitcode.c
+3
-0
arch/um/kernel/frame.c
arch/um/kernel/frame.c
+4
-0
arch/um/kernel/helper.c
arch/um/kernel/helper.c
+1
-0
arch/um/kernel/initrd_kern.c
arch/um/kernel/initrd_kern.c
+1
-0
arch/um/kernel/irq.c
arch/um/kernel/irq.c
+27
-2
arch/um/kernel/irq_user.c
arch/um/kernel/irq_user.c
+115
-47
arch/um/kernel/mem.c
arch/um/kernel/mem.c
+34
-11
arch/um/kernel/mem_user.c
arch/um/kernel/mem_user.c
+2
-3
arch/um/kernel/process.c
arch/um/kernel/process.c
+7
-7
arch/um/kernel/process_kern.c
arch/um/kernel/process_kern.c
+39
-14
arch/um/kernel/sigio_kern.c
arch/um/kernel/sigio_kern.c
+13
-0
arch/um/kernel/sigio_user.c
arch/um/kernel/sigio_user.c
+44
-15
arch/um/kernel/signal_user.c
arch/um/kernel/signal_user.c
+13
-14
arch/um/kernel/smp.c
arch/um/kernel/smp.c
+73
-84
arch/um/kernel/syscall_kern.c
arch/um/kernel/syscall_kern.c
+10
-5
arch/um/kernel/syscall_user.c
arch/um/kernel/syscall_user.c
+3
-10
arch/um/kernel/time.c
arch/um/kernel/time.c
+16
-28
arch/um/kernel/time_kern.c
arch/um/kernel/time_kern.c
+26
-5
arch/um/kernel/trap_kern.c
arch/um/kernel/trap_kern.c
+10
-5
arch/um/kernel/trap_user.c
arch/um/kernel/trap_user.c
+33
-46
arch/um/kernel/tty_log.c
arch/um/kernel/tty_log.c
+2
-2
arch/um/kernel/um_arch.c
arch/um/kernel/um_arch.c
+14
-15
arch/um/kernel/umid.c
arch/um/kernel/umid.c
+4
-0
arch/um/kernel/user_util.c
arch/um/kernel/user_util.c
+1
-0
arch/um/main.c
arch/um/main.c
+11
-2
arch/um/ptproxy/proxy.c
arch/um/ptproxy/proxy.c
+2
-4
arch/um/sys-i386/bugs.c
arch/um/sys-i386/bugs.c
+1
-0
arch/um/sys-i386/ptrace_user.c
arch/um/sys-i386/ptrace_user.c
+1
-0
arch/um/sys-ppc/miscthings.c
arch/um/sys-ppc/miscthings.c
+0
-3
arch/um/uml.lds.S
arch/um/uml.lds.S
+3
-0
include/asm-um/cache.h
include/asm-um/cache.h
+3
-0
include/asm-um/smp.h
include/asm-um/smp.h
+16
-1
include/asm-um/thread_info.h
include/asm-um/thread_info.h
+4
-0
No files found.
arch/um/config.in
View file @
46356545
...
...
@@ -28,8 +28,13 @@ tristate 'Host filesystem' CONFIG_HOSTFS
bool 'Management console' CONFIG_MCONSOLE
dep_bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ $CONFIG_MCONSOLE
bool '2G/2G host address space split' CONFIG_HOST_2G_2G
bool 'Symmetric multi-processing support' CONFIG_UML_SMP
define_bool CONFIG_SMP $CONFIG_UML_SMP
if [ "$CONFIG_SMP" = "y" ]; then
int 'Maximum number of CPUs (2-32)' CONFIG_NR_CPUS 32
fi
int 'Nesting level' CONFIG_NEST_LEVEL 0
int 'Kernel address space size (in .5G units)' CONFIG_KERNEL_HALF_GIGS 1
bool 'Highmem support' CONFIG_HIGHMEM
...
...
arch/um/drivers/chan_user.c
View file @
46356545
...
...
@@ -155,6 +155,8 @@ static void tracer_winch_handler(int sig)
errno
);
}
/* Called only by the tracing thread during initialization */
void
setup_tracer_winch
(
void
)
{
int
err
;
...
...
arch/um/drivers/harddog_kern.c
View file @
46356545
...
...
@@ -51,8 +51,8 @@
MODULE_LICENSE
(
"GPL"
);
/* Locked by the BKL in harddog_open and harddog_release */
static
int
timer_alive
;
static
int
harddog_in_fd
=
-
1
;
static
int
harddog_out_fd
=
-
1
;
...
...
@@ -67,6 +67,7 @@ static int harddog_open(struct inode *inode, struct file *file)
int
err
;
char
*
sock
=
NULL
;
lock_kernel
();
if
(
timer_alive
)
return
-
EBUSY
;
#ifdef CONFIG_HARDDOG_NOWAYOUT
...
...
@@ -80,6 +81,7 @@ static int harddog_open(struct inode *inode, struct file *file)
if
(
err
)
return
(
err
);
timer_alive
=
1
;
unlock_kernel
();
return
0
;
}
...
...
arch/um/drivers/hostaudio_kern.c
View file @
46356545
...
...
@@ -15,6 +15,7 @@
#include "init.h"
#include "hostaudio.h"
/* Only changed from linux_main at boot time */
char
*
dsp
=
HOSTAUDIO_DEV_DSP
;
char
*
mixer
=
HOSTAUDIO_DEV_MIXER
;
...
...
arch/um/drivers/line.c
View file @
46356545
...
...
@@ -99,19 +99,27 @@ int line_write(struct line *lines, struct tty_struct *tty, const char *buf,
i
=
minor
(
tty
->
device
)
-
tty
->
driver
.
minor_start
;
line
=
&
lines
[
i
];
down
(
&
line
->
sem
);
if
(
line
->
head
!=
line
->
tail
){
local_irq_save
(
flags
);
buffer_data
(
line
,
buf
,
len
);
err
=
flush_buffer
(
line
);
local_irq_restore
(
flags
);
if
(
err
<=
0
)
return
(
len
);
if
(
err
<=
0
)
goto
out
;
}
else
{
n
=
write_chan
(
&
line
->
chan_list
,
buf
,
len
,
line
->
driver
->
write_irq
);
if
(
n
<
0
)
return
(
n
);
if
(
n
<
len
)
buffer_data
(
line
,
buf
+
n
,
len
-
n
);
if
(
n
<
0
){
len
=
n
;
goto
out
;
}
if
(
n
<
len
)
buffer_data
(
line
,
buf
+
n
,
len
-
n
);
}
out:
up
(
&
line
->
sem
);
return
(
len
);
}
...
...
@@ -249,6 +257,7 @@ void line_close(struct line *lines, struct tty_struct *tty)
else
n
=
minor
(
tty
->
device
)
-
tty
->
driver
.
minor_start
;
line
=
&
lines
[
n
];
down
(
&
line
->
sem
);
line
->
count
--
;
/* I don't like this, but I can't think of anything better. What's
...
...
@@ -261,6 +270,7 @@ void line_close(struct line *lines, struct tty_struct *tty)
line
->
tty
=
NULL
;
if
(
line
->
count
==
0
)
line_disable
(
line
,
-
1
);
up
(
&
line
->
sem
);
}
void
close_lines
(
struct
line
*
lines
,
int
nlines
)
...
...
@@ -406,16 +416,18 @@ void winch_interrupt(int irq, void *data, struct pt_regs *unused)
reactivate_fd
(
winch
->
fd
,
WINCH_IRQ
);
}
DECLARE_MUTEX
(
winch_handler_sem
);
LIST_HEAD
(
winch_handlers
);
void
register_winch_irq
(
int
fd
,
int
tty_fd
,
int
pid
,
void
*
line
)
{
struct
winch
*
winch
;
down
(
&
winch_handler_sem
);
winch
=
kmalloc
(
sizeof
(
*
winch
),
GFP_KERNEL
);
if
(
winch
==
NULL
){
printk
(
"register_winch_irq - kmalloc failed
\n
"
);
return
;
goto
out
;
}
*
winch
=
((
struct
winch
)
{
list
:
LIST_HEAD_INIT
(
winch
->
list
),
fd
:
fd
,
...
...
@@ -427,6 +439,8 @@ void register_winch_irq(int fd, int tty_fd, int pid, void *line)
SA_INTERRUPT
|
SA_SHIRQ
|
SA_SAMPLE_RANDOM
,
"winch"
,
winch
)
<
0
)
printk
(
"register_winch_irq - failed to register IRQ
\n
"
);
out:
up
(
&
winch_handler_sem
);
}
static
void
winch_cleanup
(
void
)
...
...
arch/um/drivers/mconsole_kern.c
View file @
46356545
...
...
@@ -40,6 +40,11 @@ static struct notifier_block reboot_notifier = {
priority:
0
,
};
/* Safe without explicit locking for now. Tasklets provide their own
* locking, and the interrupt handler is safe because it can't interrupt
* itself and it can only happen on CPU 0.
*/
LIST_HEAD
(
mc_requests
);
void
mc_work_proc
(
void
*
unused
)
...
...
@@ -49,12 +54,12 @@ void mc_work_proc(void *unused)
int
done
;
do
{
save_flags
(
flags
);
local_
save_flags
(
flags
);
req
=
list_entry
(
mc_requests
.
next
,
struct
mconsole_entry
,
list
);
list_del
(
&
req
->
list
);
done
=
list_empty
(
&
mc_requests
);
restore_flags
(
flags
);
local_irq_restore
(
flags
);
req
->
request
.
cmd
->
handler
(
&
req
->
request
);
kfree
(
req
);
}
while
(
!
done
);
...
...
@@ -152,6 +157,8 @@ void mconsole_stop(struct mc_request *req)
mconsole_reply(req, "", 0, 0);
}
/* This list is populated by __initcall routines. */
LIST_HEAD(mconsole_devices);
void mconsole_register_dev(struct mc_device *new)
...
...
@@ -224,7 +231,10 @@ void mconsole_sysrq(struct mc_request *req)
}
#endif
static char *notify_socket = NULL;
/* Changed by mconsole_setup, which is __setup, and called before SMP is
* active.
*/
static char *notify_socket = NULL;
int mconsole_init(void)
{
...
...
@@ -301,6 +311,18 @@ static int create_proc_mconsole(void)
return(0);
}
static spinlock_t notify_spinlock = SPIN_LOCK_UNLOCKED;
void lock_notify(void)
{
spin_lock(¬ify_spinlock);
}
void unlock_notify(void)
{
spin_unlock(¬ify_spinlock);
}
__initcall(create_proc_mconsole);
#define NOTIFY "
=
notify
:
"
...
...
arch/um/drivers/mconsole_user.c
View file @
46356545
...
...
@@ -30,6 +30,7 @@ static struct mconsole_command commands[] = {
{
"go"
,
mconsole_go
,
1
},
};
/* Initialized in mconsole_init, which is an initcall */
char
mconsole_socket_name
[
256
];
int
mconsole_reply_v0
(
struct
mc_request
*
req
,
char
*
reply
)
...
...
@@ -162,16 +163,21 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len)
{
struct
sockaddr_un
target
;
struct
mconsole_notify
packet
;
int
n
,
err
;
int
n
,
err
=
0
;
lock_notify
();
if
(
notify_sock
<
0
){
notify_sock
=
socket
(
PF_UNIX
,
SOCK_DGRAM
,
0
);
if
(
notify_sock
<
0
){
printk
(
"mconsole_notify - socket failed, errno = %d
\n
"
,
errno
);
return
(
-
errno
)
;
err
=
-
errno
;
}
}
unlock_notify
();
if
(
err
)
return
(
err
);
target
.
sun_family
=
AF_UNIX
;
strcpy
(
target
.
sun_path
,
sock_name
);
...
...
arch/um/drivers/mmapper_kern.c
View file @
46356545
...
...
@@ -15,13 +15,14 @@
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/smplock.h>
#include <asm/pgtable.h>
#include "mem_user.h"
#include "user_util.h"
/* These are set in mmapper_init, which is called at boot time */
static
unsigned
long
mmapper_size
;
static
unsigned
long
p_buf
=
0
;
static
char
*
v_buf
=
NULL
;
...
...
arch/um/drivers/net_kern.c
View file @
46356545
...
...
@@ -27,6 +27,7 @@
#include "init.h"
#include "irq_user.h"
static
spinlock_t
opened_lock
=
SPIN_LOCK_UNLOCKED
;
LIST_HEAD
(
opened
);
static
int
uml_net_rx
(
struct
net_device
*
dev
)
...
...
@@ -118,7 +119,9 @@ static int uml_net_open(struct net_device *dev)
lp
->
tl
.
data
=
(
unsigned
long
)
&
lp
->
user
;
netif_start_queue
(
dev
);
spin_lock
(
&
opened_lock
);
list_add
(
&
lp
->
list
,
&
opened
);
spin_unlock
(
&
opened_lock
);
MOD_INC_USE_COUNT
;
out:
spin_unlock
(
&
lp
->
lock
);
...
...
@@ -135,8 +138,10 @@ static int uml_net_close(struct net_device *dev)
free_irq
(
dev
->
irq
,
dev
);
if
(
lp
->
close
!=
NULL
)
(
*
lp
->
close
)(
lp
->
fd
,
&
lp
->
user
);
lp
->
fd
=
-
1
;
spin_lock
(
&
opened_lock
);
list_del
(
&
lp
->
list
);
spin_unlock
(
&
opened_lock
);
MOD_DEC_USE_COUNT
;
spin_unlock
(
&
lp
->
lock
);
return
0
;
...
...
@@ -245,6 +250,7 @@ void uml_net_user_timer_expire(unsigned long _conn)
#endif
}
static
spinlock_t
devices_lock
=
SPIN_LOCK_UNLOCKED
;
static
struct
list_head
devices
=
LIST_HEAD_INIT
(
devices
);
static
int
eth_configure
(
int
n
,
void
*
init
,
char
*
mac
,
...
...
@@ -261,7 +267,10 @@ static int eth_configure(int n, void *init, char *mac,
return
(
1
);
}
spin_lock
(
&
devices_lock
);
list_add
(
&
device
->
list
,
&
devices
);
spin_unlock
(
&
devices_lock
);
device
->
index
=
n
;
size
=
transport
->
private_size
+
sizeof
(
struct
uml_net_private
)
+
...
...
@@ -373,12 +382,16 @@ static struct uml_net *find_device(int n)
struct
uml_net
*
device
;
struct
list_head
*
ele
;
spin_lock
(
&
devices_lock
);
list_for_each
(
ele
,
&
devices
){
device
=
list_entry
(
ele
,
struct
uml_net
,
list
);
if
(
device
->
index
==
n
)
return
(
device
)
;
goto
out
;
}
return
(
NULL
);
device
=
NULL
;
out:
spin_unlock
(
&
devices_lock
);
return
(
device
);
}
static
int
eth_parse
(
char
*
str
,
int
*
index_out
,
char
**
str_out
)
...
...
@@ -418,8 +431,12 @@ struct eth_init {
int
index
;
};
/* Filled in at boot time. Will need locking if the transports become
* modular.
*/
struct
list_head
transports
=
LIST_HEAD_INIT
(
transports
);
/* Filled in during early boot */
struct
list_head
eth_cmd_line
=
LIST_HEAD_INIT
(
eth_cmd_line
);
static
int
check_transport
(
struct
transport
*
transport
,
char
*
eth
,
int
n
,
...
...
arch/um/drivers/port_kern.c
View file @
46356545
...
...
@@ -62,8 +62,6 @@ static void pipe_interrupt(int irq, void *data, struct pt_regs *regs)
up
(
&
conn
->
port
->
sem
);
}
struct
list_head
ports
=
LIST_HEAD_INIT
(
ports
);
static
void
port_interrupt
(
int
irq
,
void
*
data
,
struct
pt_regs
*
regs
)
{
struct
port_list
*
port
=
data
;
...
...
@@ -107,6 +105,9 @@ static void port_interrupt(int irq, void *data, struct pt_regs *regs)
reactivate_fd
(
port
->
fd
,
ACCEPT_IRQ
);
}
DECLARE_MUTEX
(
ports_sem
);
struct
list_head
ports
=
LIST_HEAD_INIT
(
ports
);
void
*
port_data
(
int
port_num
)
{
struct
list_head
*
ele
;
...
...
@@ -114,6 +115,7 @@ void *port_data(int port_num)
struct
port_dev
*
dev
;
int
fd
;
down
(
&
ports_sem
);
list_for_each
(
ele
,
&
ports
){
port
=
list_entry
(
ele
,
struct
port_list
,
list
);
if
(
port
->
port
==
port_num
)
goto
found
;
...
...
@@ -121,7 +123,7 @@ void *port_data(int port_num)
port
=
kmalloc
(
sizeof
(
struct
port_list
),
GFP_KERNEL
);
if
(
port
==
NULL
){
printk
(
KERN_ERR
"Allocation of port list failed
\n
"
);
return
(
NULL
)
;
goto
out
;
}
fd
=
port_listen_fd
(
port_num
);
...
...
@@ -151,18 +153,21 @@ void *port_data(int port_num)
dev
=
kmalloc
(
sizeof
(
struct
port_dev
),
GFP_KERNEL
);
if
(
dev
==
NULL
){
printk
(
KERN_ERR
"Allocation of port device entry failed
\n
"
);
return
(
NULL
)
;
goto
out
;
}
*
dev
=
((
struct
port_dev
)
{
port
:
port
,
fd
:
-
1
,
helper_pid
:
-
1
});
up
(
&
ports_sem
);
return
(
dev
);
out_free:
kfree
(
port
);
out_close:
os_close_file
(
fd
);
out:
up
(
&
ports_sem
);
return
(
NULL
);
}
...
...
arch/um/drivers/ssl.c
View file @
46356545
...
...
@@ -61,7 +61,10 @@ static struct line_driver driver = {
symlink_to
:
"tts"
,
};
static
struct
line
serial_lines
[
NR_PORTS
]
=
/* The array is initialized by line_init, which is an initcall. The
* individual elements are protected by individual semaphores.
*/
static
struct
line
serial_lines
[
NR_PORTS
]
=
{
[
0
...
NR_PORTS
-
1
]
=
LINE_INIT
(
CONFIG_SSL_CHAN
,
&
driver
)
};
static
struct
lines
lines
=
LINES_INIT
(
NR_PORTS
);
...
...
arch/um/drivers/stdio_console.c
View file @
46356545
...
...
@@ -32,8 +32,14 @@
#define MAX_TTYS (8)
/* Referenced only by tty_driver below - presumably it's locked correctly
* by the tty driver.
*/
static
struct
tty_driver
console_driver
;
static
int
console_refcount
=
0
;
static
struct
chan_ops
init_console_ops
=
{
init
:
NULL
,
open
:
NULL
,
...
...
@@ -88,6 +94,9 @@ static struct line_driver driver = {
static
struct
lines
console_lines
=
LINES_INIT
(
MAX_TTYS
);
/* The array is initialized by line_init, which is an initcall. The
* individual elements are protected by individual semaphores.
*/
struct
line
vts
[
MAX_TTYS
]
=
{
LINE_INIT
(
CONFIG_CON_ZERO_CHAN
,
&
driver
),
[
1
...
MAX_TTYS
-
1
]
=
LINE_INIT
(
CONFIG_CON_CHAN
,
&
driver
)
};
...
...
arch/um/drivers/ubd_kern.c
View file @
46356545
...
...
@@ -25,6 +25,7 @@
#include "linux/vmalloc.h"
#include "linux/blkpg.h"
#include "linux/genhd.h"
#include "linux/spinlock.h"
#include "asm/segment.h"
#include "asm/uaccess.h"
#include "asm/irq.h"
...
...
@@ -41,7 +42,9 @@
#include "2_5compat.h"
#include "os.h"
static
spinlock_t
ubd_lock
;
static
spinlock_t
ubd_io_lock
=
SPIN_LOCK_UNLOCKED
;
static
spinlock_t
ubd_lock
=
SPIN_LOCK_UNLOCKED
;
static
void
(
*
do_ubd
)(
void
);
static
int
ubd_open
(
struct
inode
*
inode
,
struct
file
*
filp
);
...
...
@@ -62,9 +65,12 @@ static struct block_device_operations ubd_blops = {
.
revalidate
=
ubd_revalidate
,
};
/* Protected by the queue_lock */
static
request_queue_t
*
ubd_queue
;
/* Protected by ubd_lock */
static
int
fake_major
=
0
;
static
struct
gendisk
*
ubd_gendisk
[
MAX_DEV
];
static
struct
gendisk
*
fake_gendisk
[
MAX_DEV
];
...
...
@@ -74,6 +80,9 @@ static struct gendisk *fake_gendisk[MAX_DEV];
#define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 0, .c = 0 })
#endif
/* Not protected - changed only in ubd_setup_common and then only to
* to enable O_SYNC.
*/
static
struct
openflags
global_openflags
=
OPEN_FLAGS
;
struct
cow
{
...
...
@@ -164,7 +173,9 @@ static void make_ide_entries(char *dev_name)
char
name
[
64
];
if
(
!
fake_ide
)
return
;
if
(
proc_ide_root
==
NULL
)
make_proc_ide
();
dir
=
proc_mkdir
(
dev_name
,
proc_ide
);
ent
=
create_proc_entry
(
"media"
,
S_IFREG
|
S_IRUGO
,
dir
);
if
(
!
ent
)
return
;
...
...
@@ -193,7 +204,7 @@ static int ubd_setup_common(char *str, int *index_out)
{
struct
openflags
flags
=
global_openflags
;
char
*
backing_file
;
int
n
;
int
n
,
err
;
if
(
index_out
)
*
index_out
=
-
1
;
n
=
*
str
++
;
...
...
@@ -218,12 +229,22 @@ static int ubd_setup_common(char *str, int *index_out)
return
(
1
);
}
fake_major
=
major
;
err
=
1
;
spin_lock
(
&
ubd_lock
);
if
(
!
fake_major_allowed
){
printk
(
KERN_ERR
"Can't assign a fake major twice
\n
"
);
goto
out1
;
}
fake_major
=
major
;
fake_major_allowed
=
0
;
printk
(
KERN_INFO
"Setting extra ubd major number to %d
\n
"
,
major
);
return
(
0
);
err
=
0
;
out1:
spin_unlock
(
&
ubd_lock
);
return
(
err
);
}
if
(
n
<
'0'
){
...
...
@@ -241,9 +262,12 @@ static int ubd_setup_common(char *str, int *index_out)
return
(
1
);
}
err
=
1
;
spin_lock
(
&
ubd_lock
);
if
(
ubd_dev
[
n
].
file
!=
NULL
){
printk
(
KERN_ERR
"ubd_setup : device already configured
\n
"
);
return
(
1
)
;
goto
out2
;
}
if
(
index_out
)
*
index_out
=
n
;
...
...
@@ -258,8 +282,10 @@ static int ubd_setup_common(char *str, int *index_out)
}
if
(
*
str
++
!=
'='
){
printk
(
KERN_ERR
"ubd_setup : Expected '='
\n
"
);
return
(
1
)
;
goto
out2
;
}
err
=
0
;
backing_file
=
strchr
(
str
,
','
);
if
(
backing_file
){
*
backing_file
=
'\0'
;
...
...
@@ -270,7 +296,9 @@ static int ubd_setup_common(char *str, int *index_out)
ubd_dev
[
n
].
is_dir
=
1
;
ubd_dev
[
n
].
cow
.
file
=
backing_file
;
ubd_dev
[
n
].
boot_openflags
=
flags
;
return
(
0
);
out2:
spin_unlock
(
&
ubd_lock
);
return
(
err
);
}
static
int
ubd_setup
(
char
*
str
)
...
...
@@ -311,8 +339,12 @@ __uml_help(fakehd,
static
void
do_ubd_request
(
request_queue_t
*
q
);
/* Only changed by ubd_init, which is an initcall. */
int
thread_fd
=
-
1
;
/* Changed by ubd_handler, which is serialized because interrupts only
* happen on CPU 0.
*/
int
intr_count
=
0
;
static
void
ubd_finish
(
int
error
)
...
...
@@ -320,7 +352,9 @@ static void ubd_finish(int error)
int
nsect
;
if
(
error
){
spin_lock
(
&
ubd_io_lock
);
end_request
(
CURRENT
,
0
);
spin_unlock
(
&
ubd_io_lock
);
return
;
}
nsect
=
CURRENT
->
current_nr_sectors
;
...
...
@@ -329,7 +363,9 @@ static void ubd_finish(int error)
CURRENT
->
errors
=
0
;
CURRENT
->
nr_sectors
-=
nsect
;
CURRENT
->
current_nr_sectors
=
0
;
spin_lock
(
&
ubd_io_lock
);
end_request
(
CURRENT
,
1
);
spin_unlock
(
&
ubd_io_lock
);
}
static
void
ubd_handler
(
void
)
...
...
@@ -343,9 +379,9 @@ static void ubd_handler(void)
if
(
n
!=
sizeof
(
req
)){
printk
(
KERN_ERR
"Pid %d - spurious interrupt in ubd_handler, "
"errno = %d
\n
"
,
os_getpid
(),
-
n
);
spin_lock
(
&
ubd_lock
);
spin_lock
(
&
ubd_
io_
lock
);
end_request
(
CURRENT
,
0
);
spin_unlock
(
&
ubd_lock
);
spin_unlock
(
&
ubd_
io_
lock
);
return
;
}
...
...
@@ -353,11 +389,9 @@ static void ubd_handler(void)
(
req
.
length
!=
(
CURRENT
->
current_nr_sectors
)
<<
9
))
panic
(
"I/O op mismatch"
);
spin_lock
(
&
ubd_lock
);
ubd_finish
(
req
.
error
);
reactivate_fd
(
thread_fd
,
UBD_IRQ
);
do_ubd_request
(
ubd_queue
);
spin_unlock
(
&
ubd_lock
);
}
static
void
ubd_intr
(
int
irq
,
void
*
dev
,
struct
pt_regs
*
unused
)
...
...
@@ -365,6 +399,7 @@ static void ubd_intr(int irq, void *dev, struct pt_regs *unused)
ubd_handler
();
}
/* Only changed by ubd_init, which is an initcall. */
static
int
io_pid
=
-
1
;
void
kill_io_thread
(
void
)
...
...
@@ -382,6 +417,7 @@ static int ubd_file_size(struct ubd *dev, __u64 *size_out)
return
(
os_file_size
(
file
,
size_out
));
}
/* Initialized in an initcall, and unchanged thereafter */
devfs_handle_t
ubd_dir_handle
;
devfs_handle_t
ubd_fake_dir_handle
;
...
...
@@ -394,7 +430,7 @@ static int ubd_add(int n)
u64
size
;
if
(
!
dev
->
file
)
return
-
1
;
goto
out
;
disk
=
alloc_disk
(
1
<<
UBD_SHIFT
);
if
(
!
disk
)
...
...
@@ -433,23 +469,32 @@ static int ubd_add(int n)
MAJOR_NR
,
n
<<
UBD_SHIFT
,
S_IFBLK
|
S_IRUSR
|
S_IWUSR
|
S_IRGRP
|
S_IWGRP
,
&
ubd_blops
,
NULL
);
add_disk
(
disk
);
if
(
real
==
NULL
)
goto
out
;
ubd_dev
[
n
].
real
=
real
;
if
(
fake_major
)
{
fake
=
devfs_register
(
ubd_fake_dir_handle
,
name
,
DEVFS_FL_REMOVABLE
,
fake_major
,
n
<<
UBD_SHIFT
,
S_IFBLK
|
S_IRUSR
|
S_IWUSR
|
S_IRGRP
|
S_IWGRP
,
&
ubd_blops
,
NULL
);
add_disk
(
fake_disk
);
if
(
fake
==
NULL
)
return
(
-
1
);
if
(
fake
==
NULL
)
goto
out_unregister
;
ubd_dev
[
n
].
fake
=
fake
;
add_disk
(
fake_disk
);
}
if
(
real
==
NULL
)
return
(
-
1
);
ubd_dev
[
n
].
real
=
real
;
add_disk
(
disk
);
make_ide_entries
(
disk
->
disk_name
);
return
(
0
);
out_unregister:
devfs_unregister
(
real
);
ubd_dev
[
n
].
real
=
NULL
;
out:
return
(
-
1
);
}
static
int
ubd_config
(
char
*
str
)
...
...
@@ -468,24 +513,29 @@ static int ubd_config(char *str)
}
if
(
n
==
-
1
)
return
(
0
);
spin_lock
(
&
ubd_lock
);
err
=
ubd_add
(
n
);
if
(
err
)
{
if
(
err
)
ubd_dev
[
n
].
file
=
NULL
;
return
(
err
);
}
spin_unlock
(
&
ubd_lock
);
return
(
0
);
return
(
err
);
}
static
int
ubd_remove
(
char
*
str
)
{
struct
ubd
*
dev
;
int
n
;
int
n
,
err
;
if
(
!
isdigit
(
*
str
))
return
(
-
1
);
if
(
!
isdigit
(
*
str
))
return
(
-
1
);
n
=
*
str
-
'0'
;
if
(
n
>
MAX_DEV
)
return
(
-
1
);
if
(
n
>
MAX_DEV
)
return
(
-
1
);
dev
=
&
ubd_dev
[
n
];
err
=
0
;
spin_lock
(
&
ubd_lock
);
del_gendisk
(
ubd_gendisk
[
n
]);
put_disk
(
ubd_gendisk
[
n
]);
ubd_gendisk
[
n
]
=
NULL
;
...
...
@@ -494,12 +544,20 @@ static int ubd_remove(char *str)
put_disk
(
fake_gendisk
[
n
]);
fake_gendisk
[
n
]
=
NULL
;
}
if
(
dev
->
file
==
NULL
)
return
(
0
);
if
(
dev
->
count
>
0
)
return
(
-
1
);
if
(
dev
->
real
!=
NULL
)
devfs_unregister
(
dev
->
real
);
if
(
dev
->
fake
!=
NULL
)
devfs_unregister
(
dev
->
fake
);
if
(
dev
->
file
==
NULL
)
goto
out
;
err
=
-
1
;
if
(
dev
->
count
>
0
)
goto
out
;
if
(
dev
->
real
!=
NULL
)
devfs_unregister
(
dev
->
real
);
if
(
dev
->
fake
!=
NULL
)
devfs_unregister
(
dev
->
fake
);
*
dev
=
((
struct
ubd
)
DEFAULT_UBD
);
return
(
0
);
err
=
0
;
out:
spin_unlock
(
&
ubd_lock
);
return
(
err
);
}
static
struct
mc_device
ubd_mc
=
{
...
...
@@ -531,7 +589,7 @@ int ubd_init(void)
return
-
1
;
}
ubd_queue
=
BLK_DEFAULT_QUEUE
(
MAJOR_NR
);
INIT_QUEUE
(
ubd_queue
,
do_ubd_request
,
&
ubd
_lock
);
blk_init_queue
(
ubd_queue
,
do_ubd_request
,
&
ubd_io
_lock
);
elevator_init
(
ubd_queue
,
&
elevator_noop
);
if
(
fake_major
!=
0
){
char
name
[
sizeof
(
"ubd_nnn
\0
"
)];
...
...
@@ -634,7 +692,7 @@ static int ubd_open_dev(struct ubd *dev)
}
return
(
0
);
error:
close_fd
(
dev
->
fd
);
os_close_file
(
dev
->
fd
);
return
(
err
);
}
...
...
@@ -643,9 +701,8 @@ static int ubd_open(struct inode *inode, struct file *filp)
int
n
=
DEVICE_NR
(
inode
->
i_rdev
);
struct
ubd
*
dev
=
&
ubd_dev
[
n
];
int
err
;
if
(
dev
->
is_dir
==
1
)
return
(
0
)
;
goto
out
;
if
(
dev
->
count
==
0
){
dev
->
openflags
=
dev
->
boot_openflags
;
...
...
@@ -654,16 +711,16 @@ static int ubd_open(struct inode *inode, struct file *filp)
if
(
err
){
printk
(
KERN_ERR
"ubd%d: Can't open
\"
%s
\"
: "
"errno = %d
\n
"
,
n
,
dev
->
file
,
-
err
);
return
(
err
)
;
goto
out
;
}
if
(
err
)
return
(
err
);
}
dev
->
count
++
;
if
((
filp
->
f_mode
&
FMODE_WRITE
)
&&
!
dev
->
openflags
.
w
){
if
(
--
dev
->
count
==
0
)
ubd_close
(
dev
);
return
-
EROFS
;
err
=
-
EROFS
;
}
return
(
0
);
out:
return
(
err
);
}
static
int
ubd_release
(
struct
inode
*
inode
,
struct
file
*
file
)
...
...
@@ -726,13 +783,17 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
if
(
dev
->
is_dir
){
strcpy
(
req
->
buffer
,
"HOSTFS:"
);
strcat
(
req
->
buffer
,
dev
->
file
);
spin_lock
(
&
ubd_io_lock
);
end_request
(
req
,
1
);
spin_unlock
(
&
ubd_io_lock
);
return
(
1
);
}
if
((
rq_data_dir
(
req
)
==
WRITE
)
&&
!
dev
->
openflags
.
w
){
printk
(
"Write attempted on readonly ubd device %d
\n
"
,
n
);
spin_lock
(
&
ubd_io_lock
);
end_request
(
req
,
0
);
spin_unlock
(
&
ubd_io_lock
);
return
(
1
);
}
...
...
@@ -872,8 +933,11 @@ static int ubd_revalidate(kdev_t rdev)
n
=
minor
(
rdev
)
>>
UBD_SHIFT
;
dev
=
&
ubd_dev
[
n
];
err
=
0
;
spin_lock
(
&
ubd_lock
);
if
(
dev
->
is_dir
)
return
(
0
)
;
goto
out
;
err
=
ubd_file_size
(
dev
,
&
size
);
if
(
!
err
)
{
...
...
@@ -882,7 +946,8 @@ static int ubd_revalidate(kdev_t rdev)
set_capacity
(
fake_gendisk
[
n
],
size
/
512
);
dev
->
size
=
size
;
}
out:
spin_unlock
(
&
ubd_lock
);
return
err
;
}
...
...
arch/um/drivers/ubd_user.c
View file @
46356545
...
...
@@ -533,8 +533,12 @@ void do_io(struct io_thread_req *req)
return
;
}
/* Changed in start_io_thread, which is serialized by being called only
* from ubd_init, which is an initcall.
*/
int
kernel_fd
=
-
1
;
/* Only changed by the io thread */
int
io_count
=
0
;
int
io_thread
(
void
*
arg
)
...
...
arch/um/drivers/xterm.c
View file @
46356545
...
...
@@ -44,6 +44,7 @@ void *xterm_init(char *str, int device, struct chan_opts *opts)
return
(
data
);
}
/* Only changed by xterm_setup, which is a setup */
static
char
*
terminal_emulator
=
"xterm"
;
static
char
*
title_switch
=
"-T"
;
static
char
*
exec_switch
=
"-e"
;
...
...
arch/um/include/2_5compat.h
View file @
46356545
...
...
@@ -20,8 +20,6 @@
next : NULL \
}
#define INIT_QUEUE(queue, request, lock) blk_init_queue(queue, request, lock)
#define INIT_HARDSECT(arr, maj, sizes)
#define SET_PRI(task) do ; while(0)
...
...
arch/um/include/irq_user.h
View file @
46356545
...
...
@@ -18,7 +18,9 @@ extern void forward_interrupts(int pid);
extern
void
init_irq_signals
(
int
on_sigstack
);
extern
void
forward_ipi
(
int
fd
,
int
pid
);
extern
void
free_irq_later
(
int
irq
,
void
*
dev_id
);
extern
int
activate_ipi
(
int
fd
,
int
pid
);
extern
unsigned
long
irq_lock
(
void
);
extern
void
irq_unlock
(
unsigned
long
flags
);
#endif
/*
...
...
arch/um/include/kern_util.h
View file @
46356545
...
...
@@ -50,12 +50,8 @@ extern int pid_to_processor_id(int pid);
extern
void
block_signals
(
void
);
extern
void
unblock_signals
(
void
);
extern
void
deliver_signals
(
void
*
t
);
extern
void
lock_syscall
(
void
);
extern
void
unlock_syscall
(
void
);
extern
void
lock_trap
(
void
);
extern
void
unlock_trap
(
void
);
extern
void
lock_pid
(
void
);
extern
void
unlock_pid
(
void
);
extern
int
next_syscall_index
(
int
max
);
extern
int
next_trap_index
(
int
max
);
extern
void
default_idle
(
void
);
extern
void
finish_fork
(
void
);
extern
void
paging_init
(
void
);
...
...
@@ -121,7 +117,7 @@ extern void arch_switch(void);
extern
int
is_valid_pid
(
int
pid
);
extern
void
free_irq
(
unsigned
int
,
void
*
);
extern
int
um_in_interrupt
(
void
);
extern
int
cpu
(
void
);
#endif
/*
...
...
arch/um/include/mconsole.h
View file @
46356545
...
...
@@ -77,6 +77,8 @@ extern int mconsole_get_request(int fd, struct mc_request *req);
extern
int
mconsole_notify
(
char
*
sock_name
,
int
type
,
const
void
*
data
,
int
len
);
extern
char
*
mconsole_notify_socket
(
void
);
extern
void
lock_notify
(
void
);
extern
void
unlock_notify
(
void
);
#endif
...
...
arch/um/include/sigio.h
View file @
46356545
...
...
@@ -11,6 +11,8 @@ extern int register_sigio_fd(int fd);
extern
int
read_sigio_fd
(
int
fd
);
extern
int
add_sigio_fd
(
int
fd
,
int
read
);
extern
int
ignore_sigio_fd
(
int
fd
);
extern
void
sigio_lock
(
void
);
extern
void
sigio_unlock
(
void
);
#endif
...
...
arch/um/include/time_user.h
View file @
46356545
...
...
@@ -7,11 +7,11 @@
#define __TIME_USER_H__
extern
void
timer
(
void
);
extern
void
get_profile_timer
(
void
);
extern
void
disable_profile_timer
(
void
);
extern
void
switch_timers
(
int
to_real
);
extern
void
user_time_init
(
void
);
extern
void
set_timers
(
int
set_signal
);
extern
void
idle_sleep
(
int
secs
);
extern
void
enable_timer
(
void
);
extern
void
time_lock
(
void
);
extern
void
time_unlock
(
void
);
#endif
arch/um/kernel/exec_kern.c
View file @
46356545
...
...
@@ -17,6 +17,7 @@
#include "tlb.h"
#include "2_5compat.h"
#include "os.h"
#include "time_user.h"
/* See comment above fork_tramp for why sigstop is defined and used like
* this
...
...
@@ -28,7 +29,6 @@ static int exec_tramp(void *sig_stack)
{
int
sig
=
sigstop
;
block_signals
();
init_new_thread
(
sig_stack
,
NULL
);
kill
(
os_getpid
(),
sig
);
return
(
0
);
...
...
@@ -62,6 +62,7 @@ void flush_thread(void)
unprotect_stack
((
unsigned
long
)
current
->
thread_info
);
os_usr1_process
(
os_getpid
());
enable_timer
();
free_page
(
stack
);
protect
(
uml_reserved
,
high_physmem
-
uml_reserved
,
1
,
1
,
0
,
1
);
task_protections
((
unsigned
long
)
current
->
thread_info
);
...
...
arch/um/kernel/exitcode.c
View file @
46356545
...
...
@@ -8,6 +8,9 @@
#include "linux/proc_fs.h"
#include "asm/uaccess.h"
/* If read and write race, the read will still atomically read a valid
* value.
*/
int
uml_exitcode
=
0
;
static
int
read_proc_exitcode
(
char
*
page
,
char
**
start
,
off_t
off
,
...
...
arch/um/kernel/frame.c
View file @
46356545
...
...
@@ -130,6 +130,7 @@ static void child_common(void *sp, int size, sighandler_t handler, int flags)
os_stop_process
(
os_getpid
());
}
/* Changed only during early boot */
struct
sc_frame
signal_frame_sc
;
struct
sc_frame_raw
{
...
...
@@ -142,6 +143,7 @@ struct sc_frame_raw {
struct
arch_frame_data_raw
arch
;
};
/* Changed only during early boot */
static
struct
sc_frame_raw
*
raw_sc
=
NULL
;
static
void
sc_handler
(
int
sig
,
struct
sigcontext
sc
)
...
...
@@ -163,6 +165,7 @@ static int sc_child(void *arg)
return
(
-
1
);
}
/* Changed only during early boot */
struct
si_frame
signal_frame_si
;
struct
si_frame_raw
{
...
...
@@ -175,6 +178,7 @@ struct si_frame_raw {
unsigned
long
sp
;
};
/* Changed only during early boot */
static
struct
si_frame_raw
*
raw_si
=
NULL
;
static
void
si_handler
(
int
sig
,
siginfo_t
*
si
)
...
...
arch/um/kernel/helper.c
View file @
46356545
...
...
@@ -22,6 +22,7 @@ struct helper_data {
int
fd
;
};
/* Debugging aid, changed only from gdb */
int
helper_pause
=
0
;
static
void
helper_hup
(
int
sig
)
...
...
arch/um/kernel/initrd_kern.c
View file @
46356545
...
...
@@ -13,6 +13,7 @@
#include "init.h"
#include "os.h"
/* Changed by uml_initrd_setup, which is a setup */
static
char
*
initrd
__initdata
=
NULL
;
static
int
__init
read_initrd
(
void
)
...
...
arch/um/kernel/irq.c
View file @
46356545
...
...
@@ -78,6 +78,7 @@ struct hw_interrupt_type no_irq_type = {
end_none
};
/* Not changed */
volatile
unsigned
long
irq_err_count
;
/*
...
...
@@ -87,6 +88,7 @@ volatile unsigned long irq_err_count;
int
get_irq_list
(
char
*
buf
)
{
int
i
,
j
;
unsigned
long
flags
;
struct
irqaction
*
action
;
char
*
p
=
buf
;
...
...
@@ -96,9 +98,10 @@ int get_irq_list(char *buf)
*
p
++
=
'\n'
;
for
(
i
=
0
;
i
<
NR_IRQS
;
i
++
)
{
spin_lock_irqsave
(
&
irq_desc
[
i
].
lock
,
flags
);
action
=
irq_desc
[
i
].
action
;
if
(
!
action
)
continue
;
goto
end
;
p
+=
sprintf
(
p
,
"%3d: "
,
i
);
#ifndef CONFIG_SMP
p
+=
sprintf
(
p
,
"%10u "
,
kstat_irqs
(
i
));
...
...
@@ -113,6 +116,8 @@ int get_irq_list(char *buf)
for
(
action
=
action
->
next
;
action
;
action
=
action
->
next
)
p
+=
sprintf
(
p
,
", %s"
,
action
->
name
);
*
p
++
=
'\n'
;
end:
spin_unlock_irqrestore
(
&
irq_desc
[
i
].
lock
,
flags
);
}
p
+=
sprintf
(
p
,
"
\n
"
);
#ifdef notdef
...
...
@@ -548,11 +553,15 @@ void free_irq(unsigned int irq, void *dev_id)
}
}
/* These are initialized by sysctl_init, which is called from init/main.c */
static
struct
proc_dir_entry
*
root_irq_dir
;
static
struct
proc_dir_entry
*
irq_dir
[
NR_IRQS
];
static
struct
proc_dir_entry
*
smp_affinity_entry
[
NR_IRQS
];
unsigned
long
irq_affinity
[
NR_IRQS
]
=
{
[
0
...
NR_IRQS
-
1
]
=
~
0UL
};
/* These are read and written as longs, so a read won't see a partial write
* even during a race.
*/
static
unsigned
long
irq_affinity
[
NR_IRQS
]
=
{
[
0
...
NR_IRQS
-
1
]
=
~
0UL
};
#define HEX_DIGITS 8
...
...
@@ -679,6 +688,7 @@ static void register_irq_proc (unsigned int irq)
smp_affinity_entry
[
irq
]
=
entry
;
}
/* Read and written as a long */
unsigned
long
prof_cpu_mask
=
-
1
;
void
__init
init_irq_proc
(
void
)
...
...
@@ -704,6 +714,21 @@ void __init init_irq_proc (void)
register_irq_proc
(
i
);
}
static
spinlock_t
irq_spinlock
=
SPIN_LOCK_UNLOCKED
;
unsigned
long
irq_lock
(
void
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
irq_spinlock
,
flags
);
return
(
flags
);
}
void
irq_unlock
(
unsigned
long
flags
)
{
spin_unlock_irqrestore
(
&
irq_spinlock
,
flags
);
}
unsigned
long
probe_irq_on
(
void
)
{
return
(
0
);
...
...
arch/um/kernel/irq_user.c
View file @
46356545
...
...
@@ -111,40 +111,20 @@ static void maybe_sigio_broken(int fd, int type)
int
activate_fd
(
int
irq
,
int
fd
,
int
type
,
void
*
dev_id
)
{
struct
irq_fd
*
new_fd
;
int
pid
,
retval
,
events
,
err
;
struct
pollfd
*
tmp_pfd
;
struct
irq_fd
*
new_fd
,
*
irq_fd
;
unsigned
long
flags
;
int
pid
,
events
,
err
,
n
,
size
;
pid
=
os_getpid
();
err
=
os_set_fd_async
(
fd
,
pid
);
if
(
err
<
0
)
goto
out
;
for
(
new_fd
=
active_fds
;
new_fd
;
new_fd
=
new_fd
->
next
){
if
((
new_fd
->
fd
==
fd
)
&&
(
new_fd
->
type
==
type
)){
printk
(
"Registering fd %d twice
\n
"
,
fd
);
printk
(
"Irqs : %d, %d
\n
"
,
new_fd
->
irq
,
irq
);
printk
(
"Ids : 0x%x, 0x%x
\n
"
,
new_fd
->
id
,
dev_id
);
return
(
-
EIO
);
}
}
pid
=
cpu_tasks
[
0
].
pid
;
if
((
retval
=
os_set_fd_async
(
fd
,
pid
))
!=
0
)
return
(
retval
);
new_fd
=
um_kmalloc
(
sizeof
(
*
new_fd
));
err
=
-
ENOMEM
;
if
(
new_fd
==
NULL
)
return
(
err
);
pollfds_num
++
;
if
(
pollfds_num
>
pollfds_size
){
struct
pollfd
*
tmp_pfd
;
tmp_pfd
=
um_kmalloc
(
pollfds_num
*
sizeof
(
pollfds
[
0
]));
if
(
tmp_pfd
==
NULL
){
pollfds_num
--
;
goto
out_irq
;
}
if
(
pollfds
!=
NULL
){
memcpy
(
tmp_pfd
,
pollfds
,
sizeof
(
pollfds
[
0
])
*
pollfds_size
);
kfree
(
pollfds
);
}
pollfds
=
tmp_pfd
;
pollfds_size
=
pollfds_num
;
}
if
(
new_fd
==
NULL
)
goto
out
;
if
(
type
==
IRQ_READ
)
events
=
POLLIN
|
POLLPRI
;
else
events
=
POLLOUT
;
...
...
@@ -158,29 +138,90 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
current_events:
0
,
freed
:
0
}
);
*
last_irq_ptr
=
new_fd
;
last_irq_ptr
=
&
new_fd
->
next
;
/* Critical section - locked by a spinlock because this stuff can
* be changed from interrupt handlers. The stuff above is done
* outside the lock because it allocates memory.
*/
/* Actually, it only looks like it can be called from interrupt
* context. The culprit is reactivate_fd, which calls
* maybe_sigio_broken, which calls write_sigio_workaround,
* which calls activate_fd. However, write_sigio_workaround should
* only be called once, at boot time. That would make it clear that
* this is called only from process context, and can be locked with
* a semaphore.
*/
flags
=
irq_lock
();
for
(
irq_fd
=
active_fds
;
irq_fd
!=
NULL
;
irq_fd
=
irq_fd
->
next
){
if
((
irq_fd
->
fd
==
fd
)
&&
(
irq_fd
->
type
==
type
)){
printk
(
"Registering fd %d twice
\n
"
,
fd
);
printk
(
"Irqs : %d, %d
\n
"
,
irq_fd
->
irq
,
irq
);
printk
(
"Ids : 0x%x, 0x%x
\n
"
,
irq_fd
->
id
,
dev_id
);
goto
out_unlock
;
}
}
n
=
pollfds_num
;
if
(
n
==
pollfds_size
){
while
(
1
){
/* Here we have to drop the lock in order to call
* kmalloc, which might sleep. If something else
* came in and changed the pollfds array, we free
* the buffer and try again.
*/
irq_unlock
(
flags
);
size
=
(
pollfds_num
+
1
)
*
sizeof
(
pollfds
[
0
]);
tmp_pfd
=
um_kmalloc
(
size
);
flags
=
irq_lock
();
if
(
tmp_pfd
==
NULL
)
goto
out_unlock
;
if
(
n
==
pollfds_size
)
break
;
kfree
(
tmp_pfd
);
}
if
(
pollfds
!=
NULL
){
memcpy
(
tmp_pfd
,
pollfds
,
sizeof
(
pollfds
[
0
])
*
pollfds_size
);
kfree
(
pollfds
);
}
pollfds
=
tmp_pfd
;
pollfds_size
++
;
}
if
(
type
==
IRQ_WRITE
)
events
=
0
;
pollfds
[
pollfds_num
-
1
]
=
((
struct
pollfd
)
{
fd
:
fd
,
events
:
events
,
revents
:
0
});
pollfds
[
pollfds_num
]
=
((
struct
pollfd
)
{
fd
:
fd
,
events
:
events
,
revents
:
0
});
pollfds_num
++
;
*
last_irq_ptr
=
new_fd
;
last_irq_ptr
=
&
new_fd
->
next
;
irq_unlock
(
flags
);
/* This calls activate_fd, so it has to be outside the critical
* section.
*/
maybe_sigio_broken
(
fd
,
type
);
return
(
0
);
out_irq:
out_unlock:
irq_unlock
(
flags
);
out_free:
kfree
(
new_fd
);
out:
return
(
err
);
}
static
void
free_irq_by_cb
(
int
(
*
test
)(
struct
irq_fd
*
,
void
*
),
void
*
arg
)
{
struct
irq_fd
**
prev
;
unsigned
long
flags
;
int
i
=
0
;
flags
=
irq_lock
();
prev
=
&
active_fds
;
while
(
*
prev
!=
NULL
){
if
((
*
test
)(
*
prev
,
arg
)){
...
...
@@ -190,7 +231,7 @@ static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
printk
(
"free_irq_by_cb - mismatch between "
"active_fds and pollfds, fd %d vs %d
\n
"
,
(
*
prev
)
->
fd
,
pollfds
[
i
].
fd
);
return
;
goto
out
;
}
memcpy
(
&
pollfds
[
i
],
&
pollfds
[
i
+
1
],
(
pollfds_num
-
i
-
1
)
*
sizeof
(
pollfds
[
0
]));
...
...
@@ -206,6 +247,8 @@ static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
prev
=
&
(
*
prev
)
->
next
;
i
++
;
}
out:
irq_unlock
(
flags
);
}
struct
irq_and_dev
{
...
...
@@ -242,29 +285,33 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
{
struct
irq_fd
*
irq
;
int
i
=
0
;
for
(
irq
=
active_fds
;
irq
!=
NULL
;
irq
=
irq
->
next
){
if
((
irq
->
fd
==
fd
)
&&
(
irq
->
irq
==
irqnum
))
break
;
i
++
;
}
if
(
irq
==
NULL
){
printk
(
"find_irq_by_fd doesn't have descriptor %d
\n
"
,
fd
);
return
(
NULL
)
;
goto
out
;
}
if
((
pollfds
[
i
].
fd
!=
-
1
)
&&
(
pollfds
[
i
].
fd
!=
fd
)){
printk
(
"find_irq_by_fd - mismatch between active_fds and "
"pollfds, fd %d vs %d, need %d
\n
"
,
irq
->
fd
,
pollfds
[
i
].
fd
,
fd
);
return
(
NULL
);
irq
=
NULL
;
goto
out
;
}
*
index_out
=
i
;
out:
return
(
irq
);
}
void
free_irq_later
(
int
irq
,
void
*
dev_id
)
{
struct
irq_fd
*
irq_fd
;
unsigned
long
flags
;
flags
=
irq_lock
();
for
(
irq_fd
=
active_fds
;
irq_fd
!=
NULL
;
irq_fd
=
irq_fd
->
next
){
if
((
irq_fd
->
irq
==
irq
)
&&
(
irq_fd
->
id
==
dev_id
))
break
;
...
...
@@ -272,30 +319,48 @@ void free_irq_later(int irq, void *dev_id)
if
(
irq_fd
==
NULL
){
printk
(
"free_irq_later found no irq, irq = %d, "
"dev_id = 0x%p
\n
"
,
irq
,
dev_id
);
return
;
goto
out
;
}
irq_fd
->
freed
=
1
;
out:
irq_unlock
(
flags
);
}
void
reactivate_fd
(
int
fd
,
int
irqnum
)
{
struct
irq_fd
*
irq
;
unsigned
long
flags
;
int
i
;
flags
=
irq_lock
();
irq
=
find_irq_by_fd
(
fd
,
irqnum
,
&
i
);
if
(
irq
==
NULL
)
return
;
if
(
irq
==
NULL
){
irq_unlock
(
flags
);
return
;
}
pollfds
[
i
].
fd
=
irq
->
fd
;
irq_unlock
(
flags
);
/* This calls activate_fd, so it has to be outside the critical
* section.
*/
maybe_sigio_broken
(
fd
,
irq
->
type
);
}
void
deactivate_fd
(
int
fd
,
int
irqnum
)
{
struct
irq_fd
*
irq
;
unsigned
long
flags
;
int
i
;
flags
=
irq_lock
();
irq
=
find_irq_by_fd
(
fd
,
irqnum
,
&
i
);
if
(
irq
==
NULL
)
return
;
if
(
irq
==
NULL
)
goto
out
;
pollfds
[
i
].
fd
=
-
1
;
out:
irq_unlock
(
flags
);
}
void
forward_ipi
(
int
fd
,
int
pid
)
...
...
@@ -313,7 +378,9 @@ void forward_ipi(int fd, int pid)
void
forward_interrupts
(
int
pid
)
{
struct
irq_fd
*
irq
;
unsigned
long
flags
;
flags
=
irq_lock
();
for
(
irq
=
active_fds
;
irq
!=
NULL
;
irq
=
irq
->
next
){
if
(
fcntl
(
irq
->
fd
,
F_SETOWN
,
pid
)
<
0
){
int
save_errno
=
errno
;
...
...
@@ -328,6 +395,7 @@ void forward_interrupts(int pid)
}
irq
->
pid
=
pid
;
}
irq_unlock
(
flags
);
}
void
init_irq_signals
(
int
on_sigstack
)
...
...
@@ -339,10 +407,10 @@ void init_irq_signals(int on_sigstack)
if
(
timer_irq_inited
)
h
=
(
__sighandler_t
)
alarm_handler
;
else
h
=
boot_timer_handler
;
set_handler
(
SIGVTALRM
,
h
,
flags
|
SA_
NODEFER
|
SA_
RESTART
,
SIGUSR1
,
SIGIO
,
SIGWINCH
,
-
1
);
set_handler
(
SIGVTALRM
,
h
,
flags
|
SA_RESTART
,
SIGUSR1
,
SIGIO
,
SIGWINCH
,
SIGALRM
,
-
1
);
set_handler
(
SIGIO
,
(
__sighandler_t
)
sig_handler
,
flags
|
SA_RESTART
,
SIGUSR1
,
SIGIO
,
SIGWINCH
,
-
1
);
SIGUSR1
,
SIGIO
,
SIGWINCH
,
SIGALRM
,
SIGVTALRM
,
-
1
);
signal
(
SIGWINCH
,
SIG_IGN
);
}
...
...
arch/um/kernel/mem.c
View file @
46356545
...
...
@@ -26,33 +26,32 @@
#include "kern.h"
#include "init.h"
/* Changed during early boot */
pgd_t
swapper_pg_dir
[
1024
];
unsigned
long
high_physmem
;
unsigned
long
low_physmem
;
unsigned
long
vm_start
;
unsigned
long
vm_end
;
unsigned
long
highmem
;
pgd_t
swapper_pg_dir
[
1024
];
unsigned
long
*
empty_zero_page
=
NULL
;
unsigned
long
*
empty_bad_page
=
NULL
;
/* Not modified */
const
char
bad_pmd_string
[]
=
"Bad pmd in pte_alloc: %08lx
\n
"
;
extern
char
__init_begin
,
__init_end
;
extern
long
physmem_size
;
/* Not changed by UML */
mmu_gather_t
mmu_gathers
[
NR_CPUS
];
/* Changed during early boot */
int
kmalloc_ok
=
0
;
#define NREGIONS (phys_region_index(0xffffffff) - phys_region_index(0x0) + 1)
struct
mem_region
*
regions
[
NREGIONS
]
=
{
[
0
...
NREGIONS
-
1
]
=
NULL
};
#define REGION_SIZE ((0xffffffff & ~REGION_MASK) + 1)
/* Changed during early boot */
static
unsigned
long
brk_end
;
static
void
map_cb
(
void
*
unused
)
...
...
@@ -108,6 +107,7 @@ void mem_init(void)
}
#if CONFIG_HIGHMEM
/* Changed during early boot */
pte_t
*
kmap_pte
;
pgprot_t
kmap_prot
;
...
...
@@ -187,18 +187,22 @@ int init_maps(struct mem_region *region)
return
(
0
);
}
DECLARE_MUTEX
(
regions_sem
);
static
int
setup_one_range
(
int
fd
,
char
*
driver
,
unsigned
long
start
,
unsigned
long
pfn
,
int
len
,
struct
mem_region
*
region
)
{
int
i
;
down
(
&
regions_sem
);
for
(
i
=
0
;
i
<
NREGIONS
;
i
++
){
if
(
regions
[
i
]
==
NULL
)
break
;
}
if
(
i
==
NREGIONS
){
printk
(
"setup_range : no free regions
\n
"
);
return
(
-
1
);
i
=
-
1
;
goto
out
;
}
if
(
fd
==
-
1
)
...
...
@@ -216,6 +220,8 @@ static int setup_one_range(int fd, char *driver, unsigned long start,
len
:
len
,
fd
:
fd
}
);
regions
[
i
]
=
region
;
out:
up
(
&
regions_sem
);
return
(
i
);
}
...
...
@@ -373,7 +379,8 @@ void show_mem(void)
printk
(
"%d pages swap cached
\n
"
,
cached
);
}
unsigned
long
kmem_top
=
0
;
/* Changed during early boot */
static
unsigned
long
kmem_top
=
0
;
unsigned
long
get_kmem_end
(
void
)
{
...
...
@@ -428,8 +435,10 @@ struct page *arch_validate(struct page *page, int mask, int order)
goto
again
;
}
DECLARE_MUTEX
(
vm_reserved_sem
);
static
struct
list_head
vm_reserved
=
LIST_HEAD_INIT
(
vm_reserved
);
/* Static structures, linked in to the list in early boot */
static
struct
vm_reserved
head
=
{
list
:
LIST_HEAD_INIT
(
head
.
list
),
start
:
0
,
...
...
@@ -455,7 +464,9 @@ int reserve_vm(unsigned long start, unsigned long end, void *e)
{
struct
vm_reserved
*
entry
=
e
,
*
reserved
,
*
prev
;
struct
list_head
*
ele
;
int
err
;
down
(
&
vm_reserved_sem
);
list_for_each
(
ele
,
&
vm_reserved
){
reserved
=
list_entry
(
ele
,
struct
vm_reserved
,
list
);
if
(
reserved
->
start
>=
end
)
goto
found
;
...
...
@@ -469,13 +480,17 @@ int reserve_vm(unsigned long start, unsigned long end, void *e)
entry
=
kmalloc
(
sizeof
(
*
entry
),
GFP_KERNEL
);
if
(
entry
==
NULL
){
printk
(
"reserve_vm : Failed to allocate entry
\n
"
);
return
(
-
ENOMEM
);
err
=
-
ENOMEM
;
goto
out
;
}
*
entry
=
((
struct
vm_reserved
)
{
list
:
LIST_HEAD_INIT
(
entry
->
list
),
start
:
start
,
end
:
end
});
list_add
(
&
entry
->
list
,
&
prev
->
list
);
err
=
0
;
out:
up
(
&
vm_reserved_sem
);
return
(
0
);
}
...
...
@@ -486,6 +501,7 @@ unsigned long get_vm(unsigned long len)
unsigned
long
start
;
int
err
;
down
(
&
vm_reserved_sem
);
list_for_each
(
ele
,
&
vm_reserved
){
this
=
list_entry
(
ele
,
struct
vm_reserved
,
list
);
next
=
list_entry
(
ele
->
next
,
struct
vm_reserved
,
list
);
...
...
@@ -493,8 +509,10 @@ unsigned long get_vm(unsigned long len)
(
this
->
end
+
len
+
PAGE_SIZE
<=
next
->
start
))
goto
found
;
}
up
(
&
vm_reserved_sem
);
return
(
0
);
found:
up
(
&
vm_reserved_sem
);
start
=
(
unsigned
long
)
ROUND_UP
(
this
->
end
)
+
PAGE_SIZE
;
err
=
reserve_vm
(
start
,
start
+
len
,
NULL
);
if
(
err
)
return
(
0
);
...
...
@@ -533,7 +551,11 @@ struct iomem {
unsigned
long
size
;
};
struct
iomem
iomem_regions
[
NREGIONS
]
=
{
[
0
...
NREGIONS
-
1
]
=
/* iomem regions can only be added on the command line at the moment.
* Locking will be needed when they can be added via mconsole.
*/
struct
iomem
iomem_regions
[
NREGIONS
]
=
{
[
0
...
NREGIONS
-
1
]
=
{
name
:
NULL
,
fd
:
-
1
,
size
:
0
}
};
...
...
@@ -569,6 +591,7 @@ __initcall(setup_iomem);
#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
/* Changed during early boot */
static
struct
mem_region
physmem_region
;
static
struct
vm_reserved
physmem_reserved
;
...
...
arch/um/kernel/mem_user.c
View file @
46356545
...
...
@@ -46,10 +46,9 @@
#include "mem_user.h"
#include "init.h"
#include "os.h"
#include "tempfile.h"
struct
mem_region
physmem_region
;
struct
mem_region
*
mem_list
=
&
physmem_region
;
extern
struct
mem_region
physmem_region
;
#define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
...
...
arch/um/kernel/process.c
View file @
46356545
...
...
@@ -48,23 +48,23 @@ void init_new_thread(void *sig_stack, void (*usr1_handler)(int))
flags
=
SA_ONSTACK
;
}
set_handler
(
SIGSEGV
,
(
__sighandler_t
)
sig_handler
,
flags
,
SIGUSR1
,
SIGIO
,
SIGWINCH
,
-
1
);
SIGUSR1
,
SIGIO
,
SIGWINCH
,
SIGALRM
,
SIGVTALRM
,
-
1
);
set_handler
(
SIGTRAP
,
(
__sighandler_t
)
sig_handler
,
flags
,
SIGUSR1
,
SIGIO
,
SIGWINCH
,
-
1
);
SIGUSR1
,
SIGIO
,
SIGWINCH
,
SIGALRM
,
SIGVTALRM
,
-
1
);
set_handler
(
SIGFPE
,
(
__sighandler_t
)
sig_handler
,
flags
,
SIGUSR1
,
SIGIO
,
SIGWINCH
,
-
1
);
SIGUSR1
,
SIGIO
,
SIGWINCH
,
SIGALRM
,
SIGVTALRM
,
-
1
);
set_handler
(
SIGILL
,
(
__sighandler_t
)
sig_handler
,
flags
,
SIGUSR1
,
SIGIO
,
SIGWINCH
,
-
1
);
SIGUSR1
,
SIGIO
,
SIGWINCH
,
SIGALRM
,
SIGVTALRM
,
-
1
);
set_handler
(
SIGBUS
,
(
__sighandler_t
)
sig_handler
,
flags
,
SIGUSR1
,
SIGIO
,
SIGWINCH
,
-
1
);
SIGUSR1
,
SIGIO
,
SIGWINCH
,
SIGALRM
,
SIGVTALRM
,
-
1
);
set_handler
(
SIGWINCH
,
(
__sighandler_t
)
sig_handler
,
flags
,
SIGUSR1
,
SIGIO
,
SIGWINCH
,
-
1
);
SIGUSR1
,
SIGIO
,
SIGWINCH
,
SIGALRM
,
SIGVTALRM
,
-
1
);
set_handler
(
SIGUSR2
,
(
__sighandler_t
)
sig_handler
,
SA_NOMASK
|
flags
,
-
1
);
if
(
usr1_handler
)
set_handler
(
SIGUSR1
,
usr1_handler
,
flags
,
-
1
);
signal
(
SIGCHLD
,
SIG_IGN
);
signal
(
SIGHUP
,
SIG_IGN
);
set_timers
(
1
);
/* XXX A bit of a race here */
init_irq_signals
(
sig_stack
!=
NULL
);
}
...
...
arch/um/kernel/process_kern.c
View file @
46356545
...
...
@@ -41,6 +41,10 @@
#include "2_5compat.h"
#include "os.h"
/* This is a per-cpu array. A processor only modifies its entry and it only
* cares about its entry, so it's OK if another processor is modifying its
* entry.
*/
struct
cpu_task
cpu_tasks
[
NR_CPUS
]
=
{
[
0
...
NR_CPUS
-
1
]
=
{
-
1
,
NULL
}
};
struct
task_struct
*
get_task
(
int
pid
,
int
require
)
...
...
@@ -86,7 +90,7 @@ int pid_to_processor_id(int pid)
{
int
i
;
for
(
i
=
0
;
i
<
n
um_online_cpus
()
;
i
++
){
for
(
i
=
0
;
i
<
n
cpus
;
i
++
){
if
(
cpu_tasks
[
i
].
pid
==
pid
)
return
(
i
);
}
return
(
-
1
);
...
...
@@ -152,12 +156,19 @@ static void new_thread_handler(int sig)
current
->
thread
.
regs
.
regs
.
sc
=
(
void
*
)
(
&
sig
+
1
);
suspend_new_thread
(
current
->
thread
.
switch_pipe
[
0
]);
block_signals
();
#ifdef CONFIG_SMP
schedule_tail
(
NULL
);
#endif
enable_timer
();
free_page
(
current
->
thread
.
temp_stack
);
set_cmdline
(
"(kernel thread)"
);
force_flush_all
();
current
->
thread
.
prev_sched
=
NULL
;
change_sig
(
SIGUSR1
,
1
);
change_sig
(
SIGVTALRM
,
1
);
change_sig
(
SIGPROF
,
1
);
unblock_signals
();
if
(
!
run_kernel_thread
(
fn
,
arg
,
&
current
->
thread
.
jmp
))
do_exit
(
0
);
...
...
@@ -165,7 +176,9 @@ static void new_thread_handler(int sig)
static
int
new_thread_proc
(
void
*
stack
)
{
block_signals
();
change_sig
(
SIGIO
,
0
);
change_sig
(
SIGVTALRM
,
0
);
change_sig
(
SIGPROF
,
0
);
init_new_thread
(
stack
,
new_thread_handler
);
os_usr1_process
(
os_getpid
());
return
(
0
);
...
...
@@ -204,6 +217,9 @@ void *switch_to(void *prev, void *next, void *last)
unsigned
long
flags
;
int
vtalrm
,
alrm
,
prof
,
err
,
cpu
;
char
c
;
/* jailing and SMP are incompatible, so this doesn't need to be
* made per-cpu
*/
static
int
reading
;
from
=
prev
;
...
...
@@ -298,13 +314,16 @@ void exit_thread(void)
* onto the signal frame.
*/
extern
int
hit_me
;
void
finish_fork_handler
(
int
sig
)
{
current
->
thread
.
regs
.
regs
.
sc
=
(
void
*
)
(
&
sig
+
1
);
suspend_new_thread
(
current
->
thread
.
switch_pipe
[
0
]);
#ifdef CONFIG_SMP
schedule_tail
(
NULL
);
#endif
enable_timer
();
change_sig
(
SIGVTALRM
,
1
);
force_flush_all
();
if
(
current
->
mm
!=
current
->
parent
->
mm
)
protect
(
uml_reserved
,
high_physmem
-
uml_reserved
,
1
,
1
,
0
,
1
);
...
...
@@ -313,7 +332,6 @@ void finish_fork_handler(int sig)
current
->
thread
.
prev_sched
=
NULL
;
free_page
(
current
->
thread
.
temp_stack
);
block_signals
();
change_sig
(
SIGUSR1
,
0
);
set_user_mode
(
current
);
}
...
...
@@ -339,7 +357,9 @@ int fork_tramp(void *stack)
{
int
sig
=
sigusr1
;
block_signals
();
change_sig
(
SIGIO
,
0
);
change_sig
(
SIGVTALRM
,
0
);
change_sig
(
SIGPROF
,
0
);
init_new_thread
(
stack
,
finish_fork_handler
);
kill
(
os_getpid
(),
sig
);
...
...
@@ -474,7 +494,7 @@ int current_pid(void)
void
default_idle
(
void
)
{
if
(
current
->
thread_info
->
cpu
==
0
)
idle_timer
();
idle_timer
();
atomic_inc
(
&
init_mm
.
mm_count
);
current
->
mm
=
&
init_mm
;
...
...
@@ -644,6 +664,7 @@ char *uml_strdup(char *string)
return
(
new
);
}
/* Changed by jail_setup, which is a setup */
int
jail
=
0
;
int
__init
jail_setup
(
char
*
line
,
int
*
add
)
...
...
@@ -708,17 +729,14 @@ static void mprotect_kernel_mem(int w)
mprotect_kernel_vm
(
w
);
}
int
jail_timer_off
=
0
;
/* No SMP problems since jailing and SMP are incompatible */
void
unprotect_kernel_mem
(
void
)
{
mprotect_kernel_mem
(
1
);
jail_timer_off
=
0
;
}
void
protect_kernel_mem
(
void
)
{
jail_timer_off
=
1
;
mprotect_kernel_mem
(
0
);
}
...
...
@@ -749,9 +767,11 @@ void set_thread_sc(void *sc)
int
smp_sigio_handler
(
void
)
{
int
cpu
=
current
->
thread_info
->
cpu
;
#ifdef CONFIG_SMP
IPI_handler
(
hard_smp_processor_id
());
if
(
hard_smp_processor_id
()
!=
0
)
return
(
1
);
IPI_handler
(
cpu
);
if
(
cpu
!=
0
)
return
(
1
);
#endif
return
(
0
);
}
...
...
@@ -761,6 +781,11 @@ int um_in_interrupt(void)
return
(
in_interrupt
());
}
int
cpu
(
void
)
{
return
(
current
->
thread_info
->
cpu
);
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
...
...
arch/um/kernel/sigio_kern.c
View file @
46356545
...
...
@@ -11,6 +11,7 @@
#include "sigio.h"
#include "irq_user.h"
/* Protected by sigio_lock() called from write_sigio_workaround */
static
int
sigio_irq_fd
=
-
1
;
void
sigio_interrupt
(
int
irq
,
void
*
data
,
struct
pt_regs
*
unused
)
...
...
@@ -31,6 +32,18 @@ int write_sigio_irq(int fd)
return
(
0
);
}
static
spinlock_t
sigio_spinlock
=
SPIN_LOCK_UNLOCKED
;
void
sigio_lock
(
void
)
{
spin_lock
(
&
sigio_spinlock
);
}
void
sigio_unlock
(
void
)
{
spin_unlock
(
&
sigio_spinlock
);
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
...
...
arch/um/kernel/sigio_user.c
View file @
46356545
...
...
@@ -21,9 +21,11 @@
#include "helper.h"
#include "os.h"
/* Changed during early boot */
int
pty_output_sigio
=
0
;
int
pty_close_sigio
=
0
;
/* Used as a flag during SIGIO testing early in boot */
static
int
got_sigio
=
0
;
void
__init
handler
(
int
sig
)
...
...
@@ -151,7 +153,15 @@ void __init check_sigio(void)
check_one_sigio
(
tty_close
);
}
/* Protected by sigio_lock(), also used by sigio_cleanup, which is an
* exitcall.
*/
static
int
write_sigio_pid
=
-
1
;
/* These arrays are initialized before the sigio thread is started, and
* the descriptors closed after it is killed. So, it can't see them change.
* On the UML side, they are changed under the sigio_lock.
*/
static
int
write_sigio_fds
[
2
]
=
{
-
1
,
-
1
};
static
int
sigio_private
[
2
]
=
{
-
1
,
-
1
};
...
...
@@ -161,6 +171,9 @@ struct pollfds {
int
used
;
};
/* Protected by sigio_lock(). Used by the sigio thread, but the UML thread
* synchronizes with it.
*/
struct
pollfds
current_poll
=
{
poll
:
NULL
,
size
:
0
,
...
...
@@ -217,8 +230,6 @@ static int write_sigio_thread(void *unused)
}
}
/* XXX SMP locking needed here too */
static
int
need_poll
(
int
n
)
{
if
(
n
<=
next_poll
.
size
){
...
...
@@ -260,25 +271,31 @@ static void update_thread(void)
set_signals
(
flags
);
return
;
fail:
sigio_lock
();
if
(
write_sigio_pid
!=
-
1
)
kill
(
write_sigio_pid
,
SIGKILL
);
write_sigio_pid
=
-
1
;
close
(
sigio_private
[
0
]);
close
(
sigio_private
[
1
]);
close
(
write_sigio_fds
[
0
]);
close
(
write_sigio_fds
[
1
]);
sigio_unlock
();
set_signals
(
flags
);
}
int
add_sigio_fd
(
int
fd
,
int
read
)
{
int
err
,
i
,
n
,
events
;
int
err
=
0
,
i
,
n
,
events
;
for
(
i
=
0
;
i
<
current_poll
.
used
;
i
++
)
if
(
current_poll
.
poll
[
i
].
fd
==
fd
)
return
(
0
);
sigio_lock
();
for
(
i
=
0
;
i
<
current_poll
.
used
;
i
++
){
if
(
current_poll
.
poll
[
i
].
fd
==
fd
)
goto
out
;
}
n
=
current_poll
.
used
+
1
;
err
=
need_poll
(
n
);
if
(
err
)
return
(
err
);
if
(
err
)
goto
out
;
for
(
i
=
0
;
i
<
current_poll
.
used
;
i
++
)
next_poll
.
poll
[
i
]
=
current_poll
.
poll
[
i
];
...
...
@@ -290,21 +307,26 @@ int add_sigio_fd(int fd, int read)
events
:
events
,
revents
:
0
});
update_thread
();
return
(
0
);
out:
sigio_unlock
();
return
(
err
);
}
int
ignore_sigio_fd
(
int
fd
)
{
struct
pollfd
*
p
;
int
err
,
i
,
n
=
0
;
int
err
=
0
,
i
,
n
=
0
;
sigio_lock
();
for
(
i
=
0
;
i
<
current_poll
.
used
;
i
++
){
if
(
current_poll
.
poll
[
i
].
fd
==
fd
)
break
;
}
if
(
i
==
current_poll
.
used
)
return
(
0
);
if
(
i
==
current_poll
.
used
)
goto
out
;
err
=
need_poll
(
current_poll
.
used
-
1
);
if
(
err
)
return
(
err
);
if
(
err
)
goto
out
;
for
(
i
=
0
;
i
<
current_poll
.
used
;
i
++
){
p
=
&
current_poll
.
poll
[
i
];
...
...
@@ -312,11 +334,14 @@ int ignore_sigio_fd(int fd)
}
if
(
n
==
i
){
printk
(
"ignore_sigio_fd : fd %d not found
\n
"
,
fd
);
return
(
-
1
);
err
=
-
1
;
goto
out
;
}
update_thread
();
return
(
0
);
out:
sigio_unlock
();
return
(
err
);
}
static
int
setup_initial_poll
(
int
fd
)
...
...
@@ -342,14 +367,15 @@ void write_sigio_workaround(void)
unsigned
long
stack
;
int
err
;
if
(
write_sigio_pid
!=
-
1
)
return
;
sigio_lock
();
if
(
write_sigio_pid
!=
-
1
)
goto
out
;
/* XXX This needs SMP locking */
err
=
os_pipe
(
write_sigio_fds
,
1
,
1
);
if
(
err
){
printk
(
"write_sigio_workaround - os_pipe 1 failed, "
"errno = %d
\n
"
,
-
err
);
return
;
goto
out
;
}
err
=
os_pipe
(
sigio_private
,
1
,
1
);
if
(
err
){
...
...
@@ -368,6 +394,8 @@ void write_sigio_workaround(void)
if
(
write_sigio_irq
(
write_sigio_fds
[
0
]))
goto
out_kill
;
out:
sigio_unlock
();
return
;
out_kill:
...
...
@@ -379,6 +407,7 @@ void write_sigio_workaround(void)
out_close1:
close
(
write_sigio_fds
[
0
]);
close
(
write_sigio_fds
[
1
]);
sigio_unlock
();
}
int
read_sigio_fd
(
int
fd
)
...
...
arch/um/kernel/signal_user.c
View file @
46356545
...
...
@@ -19,8 +19,6 @@
#include "sysdep/sigcontext.h"
#include "sigcontext.h"
extern
int
kern_timer_on
;
void
set_sigstack
(
void
*
sig_stack
,
int
size
)
{
stack_t
stack
;
...
...
@@ -65,12 +63,8 @@ static void change_signals(int type)
sigset_t
mask
;
sigemptyset
(
&
mask
);
if
(
type
==
SIG_BLOCK
)
kern_timer_on
=
0
;
else
{
kern_timer_on
=
1
;
sigaddset
(
&
mask
,
SIGVTALRM
);
sigaddset
(
&
mask
,
SIGALRM
);
}
sigaddset
(
&
mask
,
SIGVTALRM
);
sigaddset
(
&
mask
,
SIGALRM
);
sigaddset
(
&
mask
,
SIGIO
);
sigaddset
(
&
mask
,
SIGPROF
);
if
(
sigprocmask
(
type
,
&
mask
,
NULL
)
<
0
)
...
...
@@ -97,7 +91,6 @@ static int disable_mask(sigset_t *mask)
sigs
=
sigismember
(
mask
,
SIGIO
)
?
1
<<
SIGIO_BIT
:
0
;
sigs
|=
sigismember
(
mask
,
SIGVTALRM
)
?
1
<<
SIGVTALRM_BIT
:
0
;
sigs
|=
sigismember
(
mask
,
SIGALRM
)
?
1
<<
SIGVTALRM_BIT
:
0
;
if
(
!
kern_timer_on
)
sigs
|=
1
<<
SIGVTALRM_BIT
;
return
(
sigs
);
}
...
...
@@ -116,21 +109,27 @@ int set_signals(int disable)
int
ret
;
sigemptyset
(
&
mask
);
if
(
!
(
disable
&
(
1
<<
SIGIO_BIT
)))
sigaddset
(
&
mask
,
SIGIO
);
if
(
!
(
disable
&
(
1
<<
SIGIO_BIT
)))
sigaddset
(
&
mask
,
SIGIO
);
if
(
!
(
disable
&
(
1
<<
SIGVTALRM_BIT
))){
kern_timer_on
=
1
;
sigaddset
(
&
mask
,
SIGVTALRM
);
sigaddset
(
&
mask
,
SIGALRM
);
}
if
(
sigprocmask
(
SIG_UNBLOCK
,
&
mask
,
&
mask
)
<
0
)
panic
(
"Failed to enable signals"
);
ret
=
disable_mask
(
&
mask
);
sigemptyset
(
&
mask
);
if
(
disable
&
(
1
<<
SIGIO_BIT
))
sigaddset
(
&
mask
,
SIGIO
);
if
(
disable
&
(
1
<<
SIGVTALRM_BIT
))
kern_timer_on
=
0
;
if
(
disable
&
(
1
<<
SIGIO_BIT
))
sigaddset
(
&
mask
,
SIGIO
);
if
(
disable
&
(
1
<<
SIGVTALRM_BIT
)){
sigaddset
(
&
mask
,
SIGVTALRM
);
sigaddset
(
&
mask
,
SIGALRM
);
}
if
(
sigprocmask
(
SIG_BLOCK
,
&
mask
,
NULL
)
<
0
)
panic
(
"Failed to block signals"
);
return
(
ret
);
}
...
...
arch/um/kernel/smp.c
View file @
46356545
...
...
@@ -5,7 +5,7 @@
#include "linux/config.h"
/* CPU online map */
/* CPU online map
, set by smp_boot_cpus
*/
unsigned
long
cpu_online_map
=
1
;
#ifdef CONFIG_SMP
...
...
@@ -21,25 +21,32 @@ unsigned long cpu_online_map = 1;
#include "user_util.h"
#include "kern_util.h"
#include "kern.h"
#include "irq_user.h"
#include "os.h"
/*
The 'big kernel lock' */
spinlock_t
kernel_flag
__cacheline_aligned_in_smp
=
SPIN_LOCK_UNLOCKED
;
/* Per CPU bogomips and other parameters
*/
/*
Per CPU bogomips and other parameters
* The only piece used here is the ipi pipe, which is set before SMP is
* started and never changed.
*/
struct
cpuinfo_um
cpu_data
[
NR_CPUS
];
spinlock_t
um_bh_lock
=
SPIN_LOCK_UNLOCKED
;
atomic_t
global_bh_count
;
/* Not used by UML */
unsigned
char
global_irq_holder
=
NO_PROC_ID
;
unsigned
volatile
long
global_irq_lock
;
/* Set when the idlers are all forked */
int
smp_threads_ready
=
0
;
/* A statistic, can be a little off */
int
num_reschedules_sent
=
0
;
/* Small, random number, never changed */
unsigned
long
cache_decay_ticks
=
5
;
void
smp_send_reschedule
(
int
cpu
)
{
write
(
cpu_data
[
cpu
].
ipi_pipe
[
1
],
"R"
,
1
);
...
...
@@ -83,30 +90,24 @@ void synchronize_bh(void)
void
smp_send_stop
(
void
)
{
printk
(
KERN_INFO
"Stopping all CPUs
\n
"
);
}
int
i
;
printk
(
KERN_INFO
"Stopping all CPUs..."
);
for
(
i
=
0
;
i
<
num_online_cpus
();
i
++
){
if
(
i
==
current
->
thread_info
->
cpu
)
continue
;
write
(
cpu_data
[
i
].
ipi_pipe
[
1
],
"S"
,
1
);
}
printk
(
"done
\n
"
);
}
static
atomic_t
smp_commenced
=
ATOMIC_INIT
(
0
)
;
static
unsigned
long
smp_commenced_mask
;
static
volatile
unsigned
long
smp_callin_map
=
0
;
void
smp_commence
(
void
)
static
int
idle_proc
(
void
*
cpup
)
{
printk
(
"All CPUs are go!
\n
"
);
wmb
();
atomic_set
(
&
smp_commenced
,
1
);
}
static
int
idle_proc
(
void
*
unused
)
{
int
cpu
,
err
;
set_current
(
current
);
del_from_runqueue
(
current
);
unhash_process
(
current
);
int
cpu
=
(
int
)
cpup
,
err
;
cpu
=
current
->
processor
;
err
=
os_pipe
(
cpu_data
[
cpu
].
ipi_pipe
,
1
,
1
);
if
(
err
)
panic
(
"CPU#%d failed to create IPI pipe, errno = %d"
,
cpu
,
...
...
@@ -115,46 +116,41 @@ static int idle_proc(void *unused)
activate_ipi
(
cpu_data
[
cpu
].
ipi_pipe
[
0
],
current
->
thread
.
extern_pid
);
wmb
();
if
(
test_and_set_bit
(
c
urrent
->
processor
,
&
smp_callin_map
))
{
printk
(
"huh, CPU#%d already present??
\n
"
,
c
urrent
->
processor
);
if
(
test_and_set_bit
(
c
pu
,
&
smp_callin_map
))
{
printk
(
"huh, CPU#%d already present??
\n
"
,
c
pu
);
BUG
();
}
while
(
!
atomic_read
(
&
smp_commenced
))
while
(
!
test_bit
(
cpu
,
&
smp_commenced_mask
))
cpu_relax
();
init_idle
(
);
set_bit
(
cpu
,
&
cpu_online_map
);
default_idle
();
return
(
0
);
}
int
inited_cpus
=
1
;
static
int
idle_thread
(
int
(
*
fn
)(
void
*
),
int
cpu
)
static
struct
task_struct
*
idle_thread
(
int
cpu
)
{
struct
task_struct
*
p
;
int
pid
;
struct
task_struct
*
new_task
;
unsigned
char
c
;
current
->
thread
.
request
.
u
.
thread
.
proc
=
fn
;
current
->
thread
.
request
.
u
.
thread
.
arg
=
NULL
;
p
=
do_fork
(
CLONE_VM
|
CLONE_PID
,
0
,
NULL
,
0
);
if
(
IS_ERR
(
p
))
panic
(
"do_fork failed in idle_thread"
);
cpu_tasks
[
cpu
].
pid
=
p
->
thread
.
extern_pid
;
cpu_tasks
[
cpu
].
task
=
p
;
inited_cpus
++
;
init_tasks
[
cpu
]
=
p
;
p
->
processor
=
cpu
;
p
->
cpus_allowed
=
1
<<
cpu
;
p
->
cpus_runnable
=
p
->
cpus_allowed
;
write
(
p
->
thread
.
switch_pipe
[
1
],
&
c
,
sizeof
(
c
));
return
(
p
->
thread
.
extern_pid
);
current
->
thread
.
request
.
u
.
thread
.
proc
=
idle_proc
;
current
->
thread
.
request
.
u
.
thread
.
arg
=
(
void
*
)
cpu
;
new_task
=
do_fork
(
CLONE_VM
|
CLONE_IDLETASK
,
0
,
NULL
,
0
,
NULL
);
if
(
IS_ERR
(
new_task
))
panic
(
"do_fork failed in idle_thread"
);
cpu_tasks
[
cpu
]
=
((
struct
cpu_task
)
{
.
pid
=
new_task
->
thread
.
extern_pid
,
.
task
=
new_task
}
);
write
(
new_task
->
thread
.
switch_pipe
[
1
],
&
c
,
sizeof
(
c
));
return
(
new_task
);
}
void
smp_
boot_cpus
(
void
)
void
smp_
prepare_cpus
(
unsigned
int
maxcpus
)
{
int
err
;
struct
task_struct
*
idle
;
unsigned
long
waittime
;
int
err
,
cpu
;
set_bit
(
0
,
&
cpu_online_map
);
set_bit
(
0
,
&
smp_callin_map
);
...
...
@@ -164,46 +160,32 @@ void smp_boot_cpus(void)
activate_ipi
(
cpu_data
[
0
].
ipi_pipe
[
0
],
current
->
thread
.
extern_pid
);
if
(
ncpus
<
1
){
printk
(
KERN_INFO
"ncpus set to 1
\n
"
);
ncpus
=
1
;
}
else
if
(
ncpus
>
NR_CPUS
){
printk
(
KERN_INFO
"ncpus can't be greater than NR_CPUS, set to %d
\n
"
,
NR_CPUS
);
ncpus
=
NR_CPUS
;
}
if
(
ncpus
>
1
){
int
i
,
pid
;
printk
(
KERN_INFO
"Starting up other processors:
\n
"
);
for
(
i
=
1
;
i
<
ncpus
;
i
++
){
int
waittime
;
/* Do this early, for hard_smp_processor_id() */
cpu_tasks
[
i
].
pid
=
-
1
;
set_bit
(
i
,
&
cpu_online_map
);
for
(
cpu
=
1
;
cpu
<
ncpus
;
cpu
++
){
printk
(
"Booting processor %d...
\n
"
,
cpu
);
idle
=
idle_thread
(
cpu
);
pid
=
idle_thread
(
idle_proc
,
i
);
printk
(
KERN_INFO
"
\t
#%d - idle thread pid = %d.. "
,
i
,
pid
);
init_idle
(
idle
,
cpu
);
unhash_process
(
idle
);
waittime
=
200000000
;
while
(
waittime
--
&&
!
test_bit
(
i
,
&
smp_callin_map
))
cpu_relax
();
waittime
=
200000000
;
while
(
waittime
--
&&
!
test_bit
(
cpu
,
&
smp_callin_map
))
cpu_relax
();
if
(
test_bit
(
i
,
&
smp_callin_map
))
printk
(
"online
\n
"
);
else
{
printk
(
"failed
\n
"
);
clear_bit
(
i
,
&
cpu_online_map
);
}
}
if
(
test_bit
(
cpu
,
&
smp_callin_map
))
printk
(
"done
\n
"
);
else
printk
(
"failed
\n
"
);
}
}
int
__cpu_up
(
unsigned
int
cpu
)
{
set_bit
(
cpu
,
&
smp_commenced_mask
);
while
(
!
test_bit
(
cpu
,
&
cpu_online_map
))
mb
();
return
(
0
);
}
int
setup_profiling_timer
(
unsigned
int
multiplier
)
{
printk
(
KERN_INFO
"setup_profiling_timer
\n
"
);
...
...
@@ -225,7 +207,13 @@ void IPI_handler(int cpu)
break
;
case
'R'
:
current
->
need_resched
=
1
;
set_tsk_need_resched
(
current
);
break
;
case
'S'
:
printk
(
"CPU#%d stopping
\n
"
,
cpu
);
while
(
1
)
pause
();
break
;
default:
...
...
@@ -269,7 +257,8 @@ int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic,
info
=
_info
;
for
(
i
=
0
;
i
<
NR_CPUS
;
i
++
)
if
(
i
!=
current
->
processor
&&
test_bit
(
i
,
&
cpu_online_map
))
if
((
i
!=
current
->
thread_info
->
cpu
)
&&
test_bit
(
i
,
&
cpu_online_map
))
write
(
cpu_data
[
i
].
ipi_pipe
[
1
],
"C"
,
1
);
while
(
atomic_read
(
&
scf_started
)
!=
cpus
)
...
...
arch/um/kernel/syscall_kern.c
View file @
46356545
...
...
@@ -384,6 +384,7 @@ static int check_bogosity(struct pt_regs *regs)
return
(
0
);
}
/* Unlocked, I don't care if this is a bit off */
int
nsyscalls
=
0
;
extern
syscall_handler_t
*
sys_call_table
[];
...
...
@@ -417,14 +418,18 @@ long execute_syscall(void *r)
spinlock_t
syscall_lock
=
SPIN_LOCK_UNLOCKED
;
void
lock_syscall
(
void
)
{
spin_lock
(
&
syscall_lock
);
}
static
int
syscall_index
=
0
;
void
unlock_syscall
(
void
)
int
next_syscall_index
(
int
limit
)
{
int
ret
;
spin_lock
(
&
syscall_lock
);
ret
=
syscall_index
;
if
(
++
syscall_index
==
limit
)
syscall_index
=
0
;
spin_unlock
(
&
syscall_lock
);
return
(
ret
);
}
/*
...
...
arch/um/kernel/syscall_user.c
View file @
46356545
...
...
@@ -34,21 +34,14 @@ struct {
struct
timeval
end
;
}
syscall_record
[
1024
];
int
syscall_index
=
0
;
extern
int
kern_timer_on
;
void
syscall_handler
(
int
sig
,
struct
uml_pt_regs
*
regs
)
{
void
*
sc
;
long
result
;
int
index
,
syscall
;
int
index
,
max
,
syscall
;
lock_syscall
();
if
(
syscall_index
==
1024
)
syscall_index
=
0
;
index
=
syscall_index
;
syscall_index
++
;
unlock_syscall
();
max
=
sizeof
(
syscall_record
)
/
sizeof
(
syscall_record
[
0
]);
index
=
next_syscall_index
(
max
);
syscall
=
regs
->
syscall
;
sc
=
regs
->
sc
;
...
...
arch/um/kernel/time.c
View file @
46356545
...
...
@@ -14,33 +14,15 @@
#include "user.h"
#include "process.h"
#include "signal_user.h"
#include "time_user.h"
extern
struct
timeval
xtime
;
void
timer_handler
(
int
sig
,
struct
uml_pt_regs
*
regs
)
{
timer_irq
(
regs
);
}
void
timer
(
void
)
{
gettimeofday
(
&
xtime
,
NULL
);
}
static
struct
itimerval
profile_interval
;
void
get_profile_timer
(
void
)
{
getitimer
(
ITIMER_PROF
,
&
profile_interval
);
profile_interval
.
it_value
=
profile_interval
.
it_interval
;
}
void
disable_profile_timer
(
void
)
{
struct
itimerval
interval
=
((
struct
itimerval
)
{
{
0
,
0
},
{
0
,
0
}});
setitimer
(
ITIMER_PROF
,
&
interval
,
NULL
);
}
static
void
set_interval
(
int
timer_type
)
{
struct
itimerval
interval
;
...
...
@@ -53,6 +35,15 @@ static void set_interval(int timer_type)
panic
(
"setitimer failed - errno = %d
\n
"
,
errno
);
}
void
enable_timer
(
void
)
{
struct
itimerval
enable
=
((
struct
itimerval
)
{
{
0
,
1000000
/
hz
()
},
{
0
,
1000000
/
hz
()
}});
if
(
setitimer
(
ITIMER_VIRTUAL
,
&
enable
,
NULL
))
printk
(
"enable_timer - setitimer failed, errno = %d
\n
"
,
errno
);
}
void
switch_timers
(
int
to_real
)
{
struct
itimerval
disable
=
((
struct
itimerval
)
{
{
0
,
0
},
{
0
,
0
}});
...
...
@@ -79,8 +70,9 @@ void idle_timer(void)
{
if
(
signal
(
SIGVTALRM
,
SIG_IGN
)
==
SIG_ERR
)
panic
(
"Couldn't unset SIGVTALRM handler"
);
set_handler
(
SIGALRM
,
(
__sighandler_t
)
alarm_handler
,
SA_
NODEFER
|
SA_RESTART
,
SIGUSR1
,
SIGIO
,
SIGWINCH
,
-
1
);
SA_
RESTART
,
SIGUSR1
,
SIGIO
,
SIGWINCH
,
SIGVTALRM
,
-
1
);
set_interval
(
ITIMER_REAL
);
}
...
...
@@ -98,28 +90,24 @@ void time_init(void)
set_interval
(
ITIMER_VIRTUAL
);
}
void
set_timers
(
int
set_signal
)
{
if
(
set_signal
)
set_interval
(
ITIMER_VIRTUAL
);
if
(
setitimer
(
ITIMER_PROF
,
&
profile_interval
,
NULL
)
==
-
1
)
panic
(
"setitimer ITIMER_PROF failed - errno = %d
\n
"
,
errno
);
}
struct
timeval
local_offset
=
{
0
,
0
};
void
do_gettimeofday
(
struct
timeval
*
tv
)
{
time_lock
();
gettimeofday
(
tv
,
NULL
);
timeradd
(
tv
,
&
local_offset
,
tv
);
time_unlock
();
}
void
do_settimeofday
(
struct
timeval
*
tv
)
{
struct
timeval
now
;
time_lock
();
gettimeofday
(
&
now
,
NULL
);
timersub
(
tv
,
&
now
,
&
local_offset
);
time_unlock
();
}
void
idle_sleep
(
int
secs
)
...
...
arch/um/kernel/time_kern.c
View file @
46356545
...
...
@@ -27,21 +27,21 @@ int hz(void)
return
(
HZ
);
}
/* Changed at early boot */
int
timer_irq_inited
=
0
;
/*
kern_timer_on and missed_ticks ar
e modified after kernel memory has been
/*
missed_ticks will b
e modified after kernel memory has been
* write-protected, so this puts it in a section which will be left
* write-enabled.
*/
int
__attribute__
((
__section__
(
".unprotected"
)))
kern_timer_on
=
0
;
int
__attribute__
((
__section__
(
".unprotected"
)))
missed_ticks
=
0
;
int
__attribute__
((
__section__
(
".unprotected"
)))
missed_ticks
[
NR_CPUS
];
void
timer_irq
(
struct
uml_pt_regs
*
regs
)
{
int
ticks
=
missed_ticks
;
int
cpu
=
current
->
thread_info
->
cpu
,
ticks
=
missed_ticks
[
cpu
]
;
if
(
!
timer_irq_inited
)
return
;
missed_ticks
=
0
;
missed_ticks
[
cpu
]
=
0
;
while
(
ticks
--
)
do_IRQ
(
TIMER_IRQ
,
regs
);
}
...
...
@@ -117,6 +117,27 @@ void __const_udelay(um_udelay_t usecs)
for
(
i
=
0
;
i
<
n
;
i
++
)
;
}
void
timer_handler
(
int
sig
,
struct
uml_pt_regs
*
regs
)
{
#ifdef CONFIG_SMP
update_process_times
(
user_context
(
UPT_SP
(
regs
)));
#endif
if
(
current
->
thread_info
->
cpu
==
0
)
timer_irq
(
regs
);
}
static
spinlock_t
timer_spinlock
=
SPIN_LOCK_UNLOCKED
;
void
time_lock
(
void
)
{
spin_lock
(
&
timer_spinlock
);
}
void
time_unlock
(
void
)
{
spin_unlock
(
&
timer_spinlock
);
}
int
__init
timer_init
(
void
)
{
int
err
;
...
...
arch/um/kernel/trap_kern.c
View file @
46356545
...
...
@@ -171,14 +171,18 @@ void trap_init(void)
spinlock_t
trap_lock
=
SPIN_LOCK_UNLOCKED
;
void
lock_trap
(
void
)
{
spin_lock
(
&
trap_lock
);
}
static
int
trap_index
=
0
;
void
unlock_trap
(
void
)
int
next_trap_index
(
int
limit
)
{
int
ret
;
spin_lock
(
&
trap_lock
);
ret
=
trap_index
;
if
(
++
trap_index
==
limit
)
trap_index
=
0
;
spin_unlock
(
&
trap_lock
);
return
(
ret
);
}
extern
int
debugger_pid
;
...
...
@@ -209,6 +213,7 @@ static struct chan_opts opts = {
tramp_stack
:
0
,
};
/* Accessed by the tracing thread, which automatically serializes access */
static
void
*
xterm_data
;
static
int
xterm_fd
;
...
...
arch/um/kernel/trap_user.c
View file @
46356545
...
...
@@ -70,10 +70,10 @@ void kill_child_dead(int pid)
while
(
waitpid
(
pid
,
NULL
,
0
)
>
0
)
kill
(
pid
,
SIGCONT
);
}
/* Changed early in boot, and then only read */
int
debug
=
0
;
int
debug_stop
=
1
;
int
debug_parent
=
0
;
int
honeypot
=
0
;
static
int
signal_tramp
(
void
*
arg
)
...
...
@@ -90,7 +90,6 @@ static int signal_tramp(void *arg)
signal
(
SIGUSR1
,
SIG_IGN
);
change_sig
(
SIGCHLD
,
0
);
signal
(
SIGSEGV
,
(
__sighandler_t
)
sig_handler
);
set_timers
(
0
);
set_cmdline
(
"(idle thread)"
);
set_init_pid
(
os_getpid
());
proc
=
arg
;
...
...
@@ -143,33 +142,20 @@ static void sleeping_process_signal(int pid, int sig)
}
}
#ifdef CONFIG_SMP
#error need to make these arrays
#endif
/* Accessed only by the tracing thread */
int
debugger_pid
=
-
1
;
int
debugger_parent
=
-
1
;
int
debugger_fd
=
-
1
;
int
gdb_pid
=
-
1
;
struct
{
unsigned
long
address
;
int
is_write
;
int
pid
;
unsigned
long
sp
;
int
is_user
;
}
segfault_record
[
1024
];
int
segfault_index
=
0
;
struct
{
int
pid
;
int
signal
;
unsigned
long
addr
;
struct
timeval
time
;
}
signal_record
[
1024
];
}
signal_record
[
1024
]
[
32
]
;
int
signal_index
=
0
;
int
signal_index
[
32
]
;
int
nsignals
=
0
;
int
debug_trace
=
0
;
extern
int
io_nsignals
,
io_count
,
intr_count
;
...
...
@@ -260,36 +246,36 @@ int signals(int (*init_proc)(void *), void *sp)
if
(
WIFEXITED
(
status
))
;
#ifdef notdef
{
print
k
(
"Child %d exited with status %d
\n
"
,
pid
,
print
f
(
"Child %d exited with status %d
\n
"
,
pid
,
WEXITSTATUS
(
status
));
}
#endif
else
if
(
WIFSIGNALED
(
status
)){
sig
=
WTERMSIG
(
status
);
if
(
sig
!=
9
){
print
k
(
"Child %d exited with signal %d
\n
"
,
pid
,
print
f
(
"Child %d exited with signal %d
\n
"
,
pid
,
sig
);
}
}
else
if
(
WIFSTOPPED
(
status
)){
proc_id
=
pid_to_processor_id
(
pid
);
sig
=
WSTOPSIG
(
status
);
if
(
signal_index
==
1024
){
signal_index
=
0
;
if
(
signal_index
[
proc_id
]
==
1024
){
signal_index
[
proc_id
]
=
0
;
last_index
=
1023
;
}
else
last_index
=
signal_index
-
1
;
else
last_index
=
signal_index
[
proc_id
]
-
1
;
if
(((
sig
==
SIGPROF
)
||
(
sig
==
SIGVTALRM
)
||
(
sig
==
SIGALRM
))
&&
(
signal_record
[
last_index
].
signal
==
sig
)
&&
(
signal_record
[
last_index
].
pid
==
pid
))
signal_index
=
last_index
;
signal_record
[
signal_index
].
pid
=
pid
;
gettimeofday
(
&
signal_record
[
signal_index
].
time
,
NULL
);
(
signal_record
[
proc_id
][
last_index
].
signal
==
sig
)
&&
(
signal_record
[
proc_id
][
last_index
].
pid
==
pid
))
signal_index
[
proc_id
]
=
last_index
;
signal_record
[
proc_id
][
signal_index
[
proc_id
]
].
pid
=
pid
;
gettimeofday
(
&
signal_record
[
proc_id
][
signal_index
[
proc_id
]
].
time
,
NULL
);
eip
=
ptrace
(
PTRACE_PEEKUSER
,
pid
,
PT_IP_OFFSET
,
0
);
signal_record
[
signal_index
].
addr
=
eip
;
signal_record
[
signal_index
++
].
signal
=
sig
;
signal_record
[
proc_id
][
signal_index
[
proc_id
]
].
addr
=
eip
;
signal_record
[
proc_id
][
signal_index
[
proc_id
]
++
].
signal
=
sig
;
proc_id
=
pid_to_processor_id
(
pid
);
if
(
proc_id
==
-
1
){
sleeping_process_signal
(
pid
,
sig
);
continue
;
...
...
@@ -414,22 +400,30 @@ __uml_setup("honeypot", uml_honeypot_setup,
" UML. This implies 'jail'.
\n\n
"
);
/* Unlocked - don't care if this is a bit off */
int
nsegfaults
=
0
;
struct
{
unsigned
long
address
;
int
is_write
;
int
pid
;
unsigned
long
sp
;
int
is_user
;
}
segfault_record
[
1024
];
void
segv_handler
(
int
sig
,
struct
uml_pt_regs
*
regs
)
{
struct
sigcontext
*
context
=
regs
->
sc
;
int
index
;
int
index
,
max
;
if
(
regs
->
is_user
&&
!
SEGV_IS_FIXABLE
(
context
)){
bad_segv
(
SC_FAULT_ADDR
(
context
),
SC_IP
(
context
),
SC_FAULT_WRITE
(
context
));
return
;
}
lock_trap
();
index
=
segfault_index
++
;
if
(
segfault_index
==
1024
)
segfault_index
=
0
;
unlock_trap
();
max
=
sizeof
(
segfault_record
)
/
sizeof
(
segfault_record
[
0
]);
index
=
next_trap_index
(
max
);
nsegfaults
++
;
segfault_record
[
index
].
address
=
SC_FAULT_ADDR
(
context
);
segfault_record
[
index
].
pid
=
os_getpid
();
...
...
@@ -440,8 +434,6 @@ void segv_handler(int sig, struct uml_pt_regs *regs)
regs
->
is_user
,
context
);
}
extern
int
kern_timer_on
;
struct
signal_info
{
void
(
*
handler
)(
int
,
struct
uml_pt_regs
*
);
int
is_irq
;
...
...
@@ -472,7 +464,7 @@ void sig_handler_common(int sig, struct sigcontext *sc)
{
struct
uml_pt_regs
save_regs
,
*
r
;
struct
signal_info
*
info
;
int
save_errno
=
errno
,
save_timer
=
kern_timer_on
,
is_user
;
int
save_errno
=
errno
,
is_user
;
unprotect_kernel_mem
();
...
...
@@ -489,7 +481,6 @@ void sig_handler_common(int sig, struct sigcontext *sc)
(
*
info
->
handler
)(
sig
,
r
);
kern_timer_on
=
save_timer
;
if
(
is_user
){
interrupt_end
();
block_signals
();
...
...
@@ -506,19 +497,15 @@ void sig_handler(int sig, struct sigcontext sc)
sig_handler_common
(
sig
,
&
sc
);
}
extern
int
timer_irq_inited
,
missed_ticks
;
extern
int
jail_timer_off
;
extern
int
timer_irq_inited
,
missed_ticks
[];
void
alarm_handler
(
int
sig
,
struct
sigcontext
sc
)
{
int
user
;
if
(
!
timer_irq_inited
)
return
;
missed_ticks
++
;
missed_ticks
[
cpu
()]
++
;
user
=
user_context
(
SC_SP
(
&
sc
));
if
(
!
user
&&
!
kern_timer_on
)
return
;
if
(
!
user
&&
jail_timer_off
)
return
;
if
(
sig
==
SIGALRM
)
switch_timers
(
0
);
...
...
arch/um/kernel/tty_log.c
View file @
46356545
...
...
@@ -17,8 +17,8 @@
#define TTY_LOG_DIR "./"
char
*
tty_log_dir
=
TTY_LOG_DIR
;
/* Set early in boot and then unchanged */
static
char
*
tty_log_dir
=
TTY_LOG_DIR
;
static
int
tty_log_fd
=
-
1
;
#define TTY_LOG_OPEN 1
...
...
arch/um/kernel/um_arch.c
View file @
46356545
...
...
@@ -37,6 +37,11 @@
#define DEFAULT_COMMAND_LINE "root=6200"
struct
cpuinfo_um
boot_cpu_data
=
{
.
loops_per_jiffy
=
0
,
.
ipi_pipe
=
{
-
1
,
-
1
}
};
unsigned
long
thread_saved_pc
(
struct
task_struct
*
task
)
{
return
(
os_process_pc
(
task
->
thread
.
extern_pid
));
...
...
@@ -119,6 +124,7 @@ static int start_kernel_proc(void *unused)
#define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000)
#define START (TOP - SIZE)
/* Set in main */
unsigned
long
host_task_size
;
unsigned
long
task_size
;
...
...
@@ -129,17 +135,21 @@ void set_task_sizes(int arg)
task_size
=
START
;
}
/* Set in early boot */
unsigned
long
uml_physmem
;
unsigned
long
uml_reserved
;
unsigned
long
start_vm
;
unsigned
long
end_vm
;
int
ncpus
=
1
;
/* Pointer set in linux_main, the array itself is private to each thread,
* and changed at address space creation time so this poses no concurrency
* problems.
*/
static
char
*
argv1_begin
=
NULL
;
static
char
*
argv1_end
=
NULL
;
/* Set in early boot */
static
int
have_root
__initdata
=
0
;
long
physmem_size
=
32
*
1024
*
1024
;
...
...
@@ -258,8 +268,9 @@ static void __init uml_postsetup(void)
}
extern
int
debug_trace
;
unsigned
long
brk_start
;
/* Set during early boot */
unsigned
long
brk_start
;
static
struct
vm_reserved
kernel_vm_reserved
;
#define MIN_VMALLOC (32 * 1024 * 1024)
...
...
@@ -366,18 +377,6 @@ void __init check_bugs(void)
check_sigio
();
}
spinlock_t
pid_lock
=
SPIN_LOCK_UNLOCKED
;
void
lock_pid
(
void
)
{
spin_lock
(
&
pid_lock
);
}
void
unlock_pid
(
void
)
{
spin_unlock
(
&
pid_lock
);
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
...
...
arch/um/kernel/umid.c
View file @
46356545
...
...
@@ -21,9 +21,13 @@
#define UMID_LEN 64
#define UML_DIR "~/.uml/"
/* Changed by set_umid and make_umid, which are run early in boot */
static
char
umid
[
UMID_LEN
]
=
{
0
};
/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */
static
char
*
uml_dir
=
UML_DIR
;
/* Changed by set_umid */
static
int
umid_is_random
=
1
;
static
int
umid_inited
=
0
;
...
...
arch/um/kernel/user_util.c
View file @
46356545
...
...
@@ -32,6 +32,7 @@
#define COMMAND_LINE_SIZE _POSIX_ARG_MAX
/* Changed in linux_main and setup_arch, which run before SMP is started */
char
saved_command_line
[
COMMAND_LINE_SIZE
]
=
{
0
};
char
command_line
[
COMMAND_LINE_SIZE
]
=
{
0
};
...
...
arch/um/main.c
View file @
46356545
...
...
@@ -18,15 +18,22 @@
#include "user.h"
#include "init.h"
/* Set in set_stklim, which is called from main and __wrap_malloc.
* __wrap_malloc only calls it if main hasn't started.
*/
unsigned
long
stacksizelim
;
/* Set in main */
char
*
linux_prog
;
#define PGD_BOUND (4 * 1024 * 1024)
#define STACKSIZE (8 * 1024 * 1024)
#define THREAD_NAME_LEN (256)
char
padding
[
THREAD_NAME_LEN
]
=
{
[
0
...
THREAD_NAME_LEN
-
2
]
=
' '
,
'\0'
};
/* Never changed */
static
char
padding
[
THREAD_NAME_LEN
]
=
{
[
0
...
THREAD_NAME_LEN
-
2
]
=
' '
,
'\0'
};
static
void
set_stklim
(
void
)
{
...
...
@@ -129,7 +136,8 @@ int main(int argc, char **argv, char **envp)
return
(
uml_exitcode
);
}
int
allocating_monbuf
=
0
;
/* Changed in __wrap___monstartup and __wrap_malloc very early */
static
int
allocating_monbuf
=
0
;
#ifdef PROFILING
extern
void
__real___monstartup
(
unsigned
long
,
unsigned
long
);
...
...
@@ -146,6 +154,7 @@ void __wrap___monstartup (unsigned long lowpc, unsigned long highpc)
extern
void
*
__real_malloc
(
int
);
extern
unsigned
long
host_task_size
;
/* Set in __wrap_malloc early */
static
void
*
gmon_buf
=
NULL
;
void
*
__wrap_malloc
(
int
size
)
...
...
arch/um/ptproxy/proxy.c
View file @
46356545
...
...
@@ -123,6 +123,7 @@ int debugger_syscall(debugger_state *debugger, pid_t child)
return
(
0
);
}
/* Used by the tracing thread */
static
debugger_state
parent
;
static
int
parent_syscall
(
debugger_state
*
debugger
,
int
pid
);
...
...
@@ -175,10 +176,7 @@ void debugger_cancelled_return(debugger_state *debugger, int result)
syscall_continue
(
debugger
->
pid
);
}
#ifdef CONFIG_SMP
#error need to make these arrays
#endif
/* Used by the tracing thread */
static
debugger_state
debugger
;
static
debugee_state
debugee
;
...
...
arch/um/sys-i386/bugs.c
View file @
46356545
...
...
@@ -15,6 +15,7 @@
#define MAXTOKEN 64
/* Set during early boot */
int
cpu_has_cmov
=
1
;
int
cpu_has_xmm
=
0
;
...
...
arch/um/sys-i386/ptrace_user.c
View file @
46356545
...
...
@@ -59,6 +59,7 @@ static void read_debugregs(int pid, unsigned long *regs)
}
}
/* Accessed only by the tracing thread */
static
unsigned
long
kernel_debugregs
[
8
]
=
{
[
0
...
7
]
=
0
};
static
int
debugregs_seq
=
0
;
...
...
arch/um/sys-ppc/miscthings.c
View file @
46356545
...
...
@@ -2,9 +2,6 @@
#include "linux/stddef.h" // for NULL
#include "linux/elf.h" // for AT_NULL
/* unsigned int local_bh_count[NR_CPUS]; */
unsigned
long
isa_io_base
=
0
;
/* The following function nicked from arch/ppc/kernel/process.c and
* adapted slightly */
/*
...
...
arch/um/uml.lds.S
View file @
46356545
...
...
@@ -67,6 +67,9 @@ SECTIONS
__setup_start
=
.
;
.
setup.init
:
{
*(
.
setup
.
init
)
}
__setup_end
=
.
;
__per_cpu_start
=
.
;
.
data.percpu
:
{
*(
.
data
.
percpu
)
}
__per_cpu_end
=
.
;
__initcall_start
=
.
;
.
initcall.init
:
{
*(.
initcall1.init
)
...
...
include/asm-um/cache.h
View file @
46356545
#ifndef __UM_CACHE_H
#define __UM_CACHE_H
/* These are x86 numbers */
#define L1_CACHE_SHIFT 5
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
#define L1_CACHE_SHIFT_MAX 7
/* largest L1 which this arch supports */
#endif
include/asm-um/smp.h
View file @
46356545
...
...
@@ -6,15 +6,30 @@ extern unsigned long cpu_online_map;
#ifdef CONFIG_SMP
#include "linux/config.h"
#include "linux/bitops.h"
#include "asm/current.h"
#define smp_processor_id() (current->
processor
)
#define smp_processor_id() (current->
thread_info->cpu
)
#define cpu_logical_map(n) (n)
#define cpu_number_map(n) (n)
#define PROC_CHANGE_PENALTY 15
/* Pick a number, any number */
extern
int
hard_smp_processor_id
(
void
);
#define NO_PROC_ID -1
#define cpu_online(cpu) (cpu_online_map & (1<<(cpu)))
extern
int
ncpus
;
#define cpu_possible(cpu) (cpu < ncpus)
extern
inline
unsigned
int
num_online_cpus
(
void
)
{
return
(
hweight32
(
cpu_online_map
));
}
extern
inline
void
smp_cpus_done
(
unsigned
int
maxcpus
)
{
}
#endif
#endif
include/asm-um/thread_info.h
View file @
46356545
...
...
@@ -64,10 +64,14 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SYSCALL_TRACE 0
/* syscall trace active */
#define TIF_SIGPENDING 1
/* signal pending */
#define TIF_NEED_RESCHED 2
/* rescheduling necessary */
#define TIF_POLLING_NRFLAG 3
/* true if poll_idle() is polling
* TIF_NEED_RESCHED
*/
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#endif
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment