Commit 5793a2d5 authored by Jeff Dike's avatar Jeff Dike

This is the merge of the initial 2.4 SMP support.

Locking was added where necessary.
All processors take timer interrupts, but only CPU 0 calls the timer
IRQ.  The others just call update_process_times to keep the
accounting straight.
The timer interrupt is blocked along with the other signals.
parent e856ba4a
...@@ -155,6 +155,8 @@ static void tracer_winch_handler(int sig) ...@@ -155,6 +155,8 @@ static void tracer_winch_handler(int sig)
errno); errno);
} }
/* Called only by the tracing thread during initialization */
void setup_tracer_winch(void) void setup_tracer_winch(void)
{ {
int err; int err;
......
...@@ -51,8 +51,8 @@ ...@@ -51,8 +51,8 @@
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* Locked by the BKL in harddog_open and harddog_release */
static int timer_alive; static int timer_alive;
static int harddog_in_fd = -1; static int harddog_in_fd = -1;
static int harddog_out_fd = -1; static int harddog_out_fd = -1;
...@@ -67,6 +67,7 @@ static int harddog_open(struct inode *inode, struct file *file) ...@@ -67,6 +67,7 @@ static int harddog_open(struct inode *inode, struct file *file)
int err; int err;
char *sock = NULL; char *sock = NULL;
lock_kernel();
if(timer_alive) if(timer_alive)
return -EBUSY; return -EBUSY;
#ifdef CONFIG_HARDDOG_NOWAYOUT #ifdef CONFIG_HARDDOG_NOWAYOUT
...@@ -80,6 +81,7 @@ static int harddog_open(struct inode *inode, struct file *file) ...@@ -80,6 +81,7 @@ static int harddog_open(struct inode *inode, struct file *file)
if(err) return(err); if(err) return(err);
timer_alive = 1; timer_alive = 1;
unlock_kernel();
return 0; return 0;
} }
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "init.h" #include "init.h"
#include "hostaudio.h" #include "hostaudio.h"
/* Only changed from linux_main at boot time */
char *dsp = HOSTAUDIO_DEV_DSP; char *dsp = HOSTAUDIO_DEV_DSP;
char *mixer = HOSTAUDIO_DEV_MIXER; char *mixer = HOSTAUDIO_DEV_MIXER;
......
...@@ -99,19 +99,27 @@ int line_write(struct line *lines, struct tty_struct *tty, const char *buf, ...@@ -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; i = minor(tty->device) - tty->driver.minor_start;
line = &lines[i]; line = &lines[i];
down(&line->sem);
if(line->head != line->tail){ if(line->head != line->tail){
local_irq_save(flags); local_irq_save(flags);
buffer_data(line, buf, len); buffer_data(line, buf, len);
err = flush_buffer(line); err = flush_buffer(line);
local_irq_restore(flags); local_irq_restore(flags);
if(err <= 0) return(len); if(err <= 0)
goto out;
} }
else { else {
n = write_chan(&line->chan_list, buf, len, n = write_chan(&line->chan_list, buf, len,
line->driver->write_irq); line->driver->write_irq);
if(n < 0) return(n); if(n < 0){
if(n < len) buffer_data(line, buf + n, len - n); len = n;
goto out;
}
if(n < len)
buffer_data(line, buf + n, len - n);
} }
out:
up(&line->sem);
return(len); return(len);
} }
...@@ -249,6 +257,7 @@ void line_close(struct line *lines, struct tty_struct *tty) ...@@ -249,6 +257,7 @@ void line_close(struct line *lines, struct tty_struct *tty)
else n = minor(tty->device) - tty->driver.minor_start; else n = minor(tty->device) - tty->driver.minor_start;
line = &lines[n]; line = &lines[n];
down(&line->sem);
line->count--; line->count--;
/* I don't like this, but I can't think of anything better. What's /* 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) ...@@ -261,6 +270,7 @@ void line_close(struct line *lines, struct tty_struct *tty)
line->tty = NULL; line->tty = NULL;
if(line->count == 0) if(line->count == 0)
line_disable(line, -1); line_disable(line, -1);
up(&line->sem);
} }
void close_lines(struct line *lines, int nlines) void close_lines(struct line *lines, int nlines)
...@@ -408,16 +418,18 @@ void winch_interrupt(int irq, void *data, struct pt_regs *unused) ...@@ -408,16 +418,18 @@ void winch_interrupt(int irq, void *data, struct pt_regs *unused)
reactivate_fd(winch->fd, WINCH_IRQ); reactivate_fd(winch->fd, WINCH_IRQ);
} }
DECLARE_MUTEX(winch_handler_sem);
LIST_HEAD(winch_handlers); LIST_HEAD(winch_handlers);
void register_winch_irq(int fd, int tty_fd, int pid, void *line) void register_winch_irq(int fd, int tty_fd, int pid, void *line)
{ {
struct winch *winch; struct winch *winch;
down(&winch_handler_sem);
winch = kmalloc(sizeof(*winch), GFP_KERNEL); winch = kmalloc(sizeof(*winch), GFP_KERNEL);
if(winch == NULL){ if(winch == NULL){
printk("register_winch_irq - kmalloc failed\n"); printk("register_winch_irq - kmalloc failed\n");
return; goto out;
} }
*winch = ((struct winch) { list : LIST_HEAD_INIT(winch->list), *winch = ((struct winch) { list : LIST_HEAD_INIT(winch->list),
fd : fd, fd : fd,
...@@ -429,6 +441,8 @@ void register_winch_irq(int fd, int tty_fd, int pid, void *line) ...@@ -429,6 +441,8 @@ void register_winch_irq(int fd, int tty_fd, int pid, void *line)
SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
"winch", winch) < 0) "winch", winch) < 0)
printk("register_winch_irq - failed to register IRQ\n"); printk("register_winch_irq - failed to register IRQ\n");
out:
up(&winch_handler_sem);
} }
static void winch_cleanup(void) static void winch_cleanup(void)
......
...@@ -40,6 +40,11 @@ static struct notifier_block reboot_notifier = { ...@@ -40,6 +40,11 @@ static struct notifier_block reboot_notifier = {
priority: 0, 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); LIST_HEAD(mc_requests);
void mc_work_proc(void *unused) void mc_work_proc(void *unused)
...@@ -49,12 +54,12 @@ void mc_work_proc(void *unused) ...@@ -49,12 +54,12 @@ void mc_work_proc(void *unused)
int done; int done;
do { do {
save_flags(flags); local_save_flags(flags);
req = list_entry(mc_requests.next, struct mconsole_entry, req = list_entry(mc_requests.next, struct mconsole_entry,
list); list);
list_del(&req->list); list_del(&req->list);
done = list_empty(&mc_requests); done = list_empty(&mc_requests);
restore_flags(flags); local_irq_restore(flags);
req->request.cmd->handler(&req->request); req->request.cmd->handler(&req->request);
kfree(req); kfree(req);
} while(!done); } while(!done);
...@@ -152,6 +157,8 @@ void mconsole_stop(struct mc_request *req) ...@@ -152,6 +157,8 @@ void mconsole_stop(struct mc_request *req)
mconsole_reply(req, "", 0, 0); mconsole_reply(req, "", 0, 0);
} }
/* This list is populated by __initcall routines. */
LIST_HEAD(mconsole_devices); LIST_HEAD(mconsole_devices);
void mconsole_register_dev(struct mc_device *new) void mconsole_register_dev(struct mc_device *new)
...@@ -224,7 +231,10 @@ void mconsole_sysrq(struct mc_request *req) ...@@ -224,7 +231,10 @@ void mconsole_sysrq(struct mc_request *req)
} }
#endif #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) int mconsole_init(void)
{ {
...@@ -301,6 +311,18 @@ static int create_proc_mconsole(void) ...@@ -301,6 +311,18 @@ static int create_proc_mconsole(void)
return(0); return(0);
} }
static spinlock_t notify_spinlock = SPIN_LOCK_UNLOCKED;
void lock_notify(void)
{
spin_lock(&notify_spinlock);
}
void unlock_notify(void)
{
spin_unlock(&notify_spinlock);
}
__initcall(create_proc_mconsole); __initcall(create_proc_mconsole);
#define NOTIFY "=notify:" #define NOTIFY "=notify:"
......
...@@ -30,6 +30,7 @@ static struct mconsole_command commands[] = { ...@@ -30,6 +30,7 @@ static struct mconsole_command commands[] = {
{ "go", mconsole_go, 1 }, { "go", mconsole_go, 1 },
}; };
/* Initialized in mconsole_init, which is an initcall */
char mconsole_socket_name[256]; char mconsole_socket_name[256];
int mconsole_reply_v0(struct mc_request *req, char *reply) 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) ...@@ -162,16 +163,21 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len)
{ {
struct sockaddr_un target; struct sockaddr_un target;
struct mconsole_notify packet; struct mconsole_notify packet;
int n, err; int n, err = 0;
lock_notify();
if(notify_sock < 0){ if(notify_sock < 0){
notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0); notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0);
if(notify_sock < 0){ if(notify_sock < 0){
printk("mconsole_notify - socket failed, errno = %d\n", printk("mconsole_notify - socket failed, errno = %d\n",
errno); errno);
return(-errno); err = -errno;
} }
} }
unlock_notify();
if(err)
return(err);
target.sun_family = AF_UNIX; target.sun_family = AF_UNIX;
strcpy(target.sun_path, sock_name); strcpy(target.sun_path, sock_name);
......
...@@ -15,13 +15,14 @@ ...@@ -15,13 +15,14 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/smplock.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include "mem_user.h" #include "mem_user.h"
#include "user_util.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 mmapper_size;
static unsigned long p_buf = 0; static unsigned long p_buf = 0;
static char *v_buf = NULL; static char *v_buf = NULL;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "init.h" #include "init.h"
#include "irq_user.h" #include "irq_user.h"
static spinlock_t opened_lock = SPIN_LOCK_UNLOCKED;
LIST_HEAD(opened); LIST_HEAD(opened);
static int uml_net_rx(struct net_device *dev) static int uml_net_rx(struct net_device *dev)
...@@ -118,7 +119,9 @@ static int uml_net_open(struct net_device *dev) ...@@ -118,7 +119,9 @@ static int uml_net_open(struct net_device *dev)
lp->tl.data = (unsigned long) &lp->user; lp->tl.data = (unsigned long) &lp->user;
netif_start_queue(dev); netif_start_queue(dev);
spin_lock(&opened_lock);
list_add(&lp->list, &opened); list_add(&lp->list, &opened);
spin_unlock(&opened_lock);
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
out: out:
spin_unlock(&lp->lock); spin_unlock(&lp->lock);
...@@ -135,8 +138,10 @@ static int uml_net_close(struct net_device *dev) ...@@ -135,8 +138,10 @@ static int uml_net_close(struct net_device *dev)
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
lp->fd = -1; lp->fd = -1;
spin_lock(&opened_lock);
list_del(&lp->list); list_del(&lp->list);
spin_unlock(&opened_lock);
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
spin_unlock(&lp->lock); spin_unlock(&lp->lock);
return 0; return 0;
...@@ -245,6 +250,7 @@ void uml_net_user_timer_expire(unsigned long _conn) ...@@ -245,6 +250,7 @@ void uml_net_user_timer_expire(unsigned long _conn)
#endif #endif
} }
static spinlock_t devices_lock = SPIN_LOCK_UNLOCKED;
static struct list_head devices = LIST_HEAD_INIT(devices); static struct list_head devices = LIST_HEAD_INIT(devices);
static int eth_configure(int n, void *init, char *mac, static int eth_configure(int n, void *init, char *mac,
...@@ -261,7 +267,10 @@ 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); return(1);
} }
spin_lock(&devices_lock);
list_add(&device->list, &devices); list_add(&device->list, &devices);
spin_unlock(&devices_lock);
device->index = n; device->index = n;
size = transport->private_size + sizeof(struct uml_net_private) + size = transport->private_size + sizeof(struct uml_net_private) +
...@@ -373,12 +382,16 @@ static struct uml_net *find_device(int n) ...@@ -373,12 +382,16 @@ static struct uml_net *find_device(int n)
struct uml_net *device; struct uml_net *device;
struct list_head *ele; struct list_head *ele;
spin_lock(&devices_lock);
list_for_each(ele, &devices){ list_for_each(ele, &devices){
device = list_entry(ele, struct uml_net, list); device = list_entry(ele, struct uml_net, list);
if(device->index == n) 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) static int eth_parse(char *str, int *index_out, char **str_out)
...@@ -418,8 +431,12 @@ struct eth_init { ...@@ -418,8 +431,12 @@ struct eth_init {
int index; int index;
}; };
/* Filled in at boot time. Will need locking if the transports become
* modular.
*/
struct list_head transports = LIST_HEAD_INIT(transports); 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); struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line);
static int check_transport(struct transport *transport, char *eth, int n, static int check_transport(struct transport *transport, char *eth, int n,
......
...@@ -62,8 +62,6 @@ static void pipe_interrupt(int irq, void *data, struct pt_regs *regs) ...@@ -62,8 +62,6 @@ static void pipe_interrupt(int irq, void *data, struct pt_regs *regs)
up(&conn->port->sem); up(&conn->port->sem);
} }
struct list_head ports = LIST_HEAD_INIT(ports);
static void port_interrupt(int irq, void *data, struct pt_regs *regs) static void port_interrupt(int irq, void *data, struct pt_regs *regs)
{ {
struct port_list *port = data; struct port_list *port = data;
...@@ -107,6 +105,9 @@ static void port_interrupt(int irq, void *data, struct pt_regs *regs) ...@@ -107,6 +105,9 @@ static void port_interrupt(int irq, void *data, struct pt_regs *regs)
reactivate_fd(port->fd, ACCEPT_IRQ); reactivate_fd(port->fd, ACCEPT_IRQ);
} }
DECLARE_MUTEX(ports_sem);
struct list_head ports = LIST_HEAD_INIT(ports);
void *port_data(int port_num) void *port_data(int port_num)
{ {
struct list_head *ele; struct list_head *ele;
...@@ -114,6 +115,7 @@ void *port_data(int port_num) ...@@ -114,6 +115,7 @@ void *port_data(int port_num)
struct port_dev *dev; struct port_dev *dev;
int fd; int fd;
down(&ports_sem);
list_for_each(ele, &ports){ list_for_each(ele, &ports){
port = list_entry(ele, struct port_list, list); port = list_entry(ele, struct port_list, list);
if(port->port == port_num) goto found; if(port->port == port_num) goto found;
...@@ -121,7 +123,7 @@ void *port_data(int port_num) ...@@ -121,7 +123,7 @@ void *port_data(int port_num)
port = kmalloc(sizeof(struct port_list), GFP_KERNEL); port = kmalloc(sizeof(struct port_list), GFP_KERNEL);
if(port == NULL){ if(port == NULL){
printk(KERN_ERR "Allocation of port list failed\n"); printk(KERN_ERR "Allocation of port list failed\n");
return(NULL); goto out;
} }
fd = port_listen_fd(port_num); fd = port_listen_fd(port_num);
...@@ -151,18 +153,21 @@ void *port_data(int port_num) ...@@ -151,18 +153,21 @@ void *port_data(int port_num)
dev = kmalloc(sizeof(struct port_dev), GFP_KERNEL); dev = kmalloc(sizeof(struct port_dev), GFP_KERNEL);
if(dev == NULL){ if(dev == NULL){
printk(KERN_ERR "Allocation of port device entry failed\n"); printk(KERN_ERR "Allocation of port device entry failed\n");
return(NULL); goto out;
} }
*dev = ((struct port_dev) { port : port, *dev = ((struct port_dev) { port : port,
fd : -1, fd : -1,
helper_pid : -1 }); helper_pid : -1 });
up(&ports_sem);
return(dev); return(dev);
out_free: out_free:
kfree(port); kfree(port);
out_close: out_close:
os_close_file(fd); os_close_file(fd);
out:
up(&ports_sem);
return(NULL); return(NULL);
} }
......
...@@ -58,7 +58,10 @@ static struct line_driver driver = { ...@@ -58,7 +58,10 @@ static struct line_driver driver = {
symlink_to : "tts", 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) }; { [0 ... NR_PORTS - 1] = LINE_INIT(CONFIG_SSL_CHAN, &driver) };
static struct lines lines = LINES_INIT(NR_PORTS); static struct lines lines = LINES_INIT(NR_PORTS);
......
...@@ -32,8 +32,14 @@ ...@@ -32,8 +32,14 @@
#define MAX_TTYS (8) #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 struct tty_driver console_driver;
static int console_refcount = 0;
static struct chan_ops init_console_ops = { static struct chan_ops init_console_ops = {
init : NULL, init : NULL,
open : NULL, open : NULL,
...@@ -88,6 +94,9 @@ static struct line_driver driver = { ...@@ -88,6 +94,9 @@ static struct line_driver driver = {
static struct lines console_lines = LINES_INIT(MAX_TTYS); 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), struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver),
[ 1 ... MAX_TTYS - 1 ] = [ 1 ... MAX_TTYS - 1 ] =
LINE_INIT(CONFIG_CON_CHAN, &driver) }; LINE_INIT(CONFIG_CON_CHAN, &driver) };
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "linux/vmalloc.h" #include "linux/vmalloc.h"
#include "linux/blkpg.h" #include "linux/blkpg.h"
#include "linux/genhd.h" #include "linux/genhd.h"
#include "linux/spinlock.h"
#include "asm/segment.h" #include "asm/segment.h"
#include "asm/uaccess.h" #include "asm/uaccess.h"
#include "asm/irq.h" #include "asm/irq.h"
...@@ -41,7 +42,9 @@ ...@@ -41,7 +42,9 @@
#include "2_5compat.h" #include "2_5compat.h"
#include "os.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 void (*do_ubd)(void);
static int ubd_open(struct inode * inode, struct file * filp); static int ubd_open(struct inode * inode, struct file * filp);
...@@ -62,9 +65,12 @@ static struct block_device_operations ubd_blops = { ...@@ -62,9 +65,12 @@ static struct block_device_operations ubd_blops = {
.revalidate = ubd_revalidate, .revalidate = ubd_revalidate,
}; };
/* Protected by the queue_lock */
static request_queue_t *ubd_queue; static request_queue_t *ubd_queue;
/* Protected by ubd_lock */
static int fake_major = 0; static int fake_major = 0;
static struct gendisk *ubd_gendisk[MAX_DEV]; static struct gendisk *ubd_gendisk[MAX_DEV];
static struct gendisk *fake_gendisk[MAX_DEV]; static struct gendisk *fake_gendisk[MAX_DEV];
...@@ -74,6 +80,9 @@ 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 }) #define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 0, .c = 0 })
#endif #endif
/* Not protected - changed only in ubd_setup_common and then only to
* to enable O_SYNC.
*/
static struct openflags global_openflags = OPEN_FLAGS; static struct openflags global_openflags = OPEN_FLAGS;
struct cow { struct cow {
...@@ -170,7 +179,9 @@ static void make_ide_entries(char *dev_name) ...@@ -170,7 +179,9 @@ static void make_ide_entries(char *dev_name)
char name[64]; char name[64];
if(!fake_ide) return; if(!fake_ide) return;
if(proc_ide_root == NULL) make_proc_ide(); if(proc_ide_root == NULL) make_proc_ide();
dir = proc_mkdir(dev_name, proc_ide); dir = proc_mkdir(dev_name, proc_ide);
ent = create_proc_entry("media", S_IFREG|S_IRUGO, dir); ent = create_proc_entry("media", S_IFREG|S_IRUGO, dir);
if(!ent) return; if(!ent) return;
...@@ -199,7 +210,7 @@ static int ubd_setup_common(char *str, int *index_out) ...@@ -199,7 +210,7 @@ static int ubd_setup_common(char *str, int *index_out)
{ {
struct openflags flags = global_openflags; struct openflags flags = global_openflags;
char *backing_file; char *backing_file;
int n; int n, err;
if(index_out) *index_out = -1; if(index_out) *index_out = -1;
n = *str++; n = *str++;
...@@ -224,12 +235,22 @@ static int ubd_setup_common(char *str, int *index_out) ...@@ -224,12 +235,22 @@ static int ubd_setup_common(char *str, int *index_out)
return(1); 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; fake_major_allowed = 0;
printk(KERN_INFO "Setting extra ubd major number to %d\n", printk(KERN_INFO "Setting extra ubd major number to %d\n",
major); major);
return(0); err = 0;
out1:
spin_unlock(&ubd_lock);
return(err);
} }
if(n < '0'){ if(n < '0'){
...@@ -247,9 +268,12 @@ static int ubd_setup_common(char *str, int *index_out) ...@@ -247,9 +268,12 @@ static int ubd_setup_common(char *str, int *index_out)
return(1); return(1);
} }
err = 1;
spin_lock(&ubd_lock);
if(ubd_dev[n].file != NULL){ if(ubd_dev[n].file != NULL){
printk(KERN_ERR "ubd_setup : device already configured\n"); printk(KERN_ERR "ubd_setup : device already configured\n");
return(1); goto out2;
} }
if(index_out) *index_out = n; if(index_out) *index_out = n;
...@@ -264,8 +288,10 @@ static int ubd_setup_common(char *str, int *index_out) ...@@ -264,8 +288,10 @@ static int ubd_setup_common(char *str, int *index_out)
} }
if(*str++ != '='){ if(*str++ != '='){
printk(KERN_ERR "ubd_setup : Expected '='\n"); printk(KERN_ERR "ubd_setup : Expected '='\n");
return(1); goto out2;
} }
err = 0;
backing_file = strchr(str, ','); backing_file = strchr(str, ',');
if(backing_file){ if(backing_file){
*backing_file = '\0'; *backing_file = '\0';
...@@ -276,7 +302,9 @@ static int ubd_setup_common(char *str, int *index_out) ...@@ -276,7 +302,9 @@ static int ubd_setup_common(char *str, int *index_out)
ubd_dev[n].is_dir = 1; ubd_dev[n].is_dir = 1;
ubd_dev[n].cow.file = backing_file; ubd_dev[n].cow.file = backing_file;
ubd_dev[n].boot_openflags = flags; ubd_dev[n].boot_openflags = flags;
return(0); out2:
spin_unlock(&ubd_lock);
return(err);
} }
static int ubd_setup(char *str) static int ubd_setup(char *str)
...@@ -317,8 +345,12 @@ __uml_help(fakehd, ...@@ -317,8 +345,12 @@ __uml_help(fakehd,
static void do_ubd_request(request_queue_t * q); static void do_ubd_request(request_queue_t * q);
/* Only changed by ubd_init, which is an initcall. */
int thread_fd = -1; int thread_fd = -1;
/* Changed by ubd_handler, which is serialized because interrupts only
* happen on CPU 0.
*/
int intr_count = 0; int intr_count = 0;
static void ubd_finish(int error) static void ubd_finish(int error)
...@@ -326,7 +358,9 @@ static void ubd_finish(int error) ...@@ -326,7 +358,9 @@ static void ubd_finish(int error)
int nsect; int nsect;
if(error){ if(error){
spin_lock(&ubd_io_lock);
end_request(CURRENT, 0); end_request(CURRENT, 0);
spin_unlock(&ubd_io_lock);
return; return;
} }
nsect = CURRENT->current_nr_sectors; nsect = CURRENT->current_nr_sectors;
...@@ -335,7 +369,9 @@ static void ubd_finish(int error) ...@@ -335,7 +369,9 @@ static void ubd_finish(int error)
CURRENT->errors = 0; CURRENT->errors = 0;
CURRENT->nr_sectors -= nsect; CURRENT->nr_sectors -= nsect;
CURRENT->current_nr_sectors = 0; CURRENT->current_nr_sectors = 0;
spin_lock(&ubd_io_lock);
end_request(CURRENT, 1); end_request(CURRENT, 1);
spin_unlock(&ubd_io_lock);
} }
static void ubd_handler(void) static void ubd_handler(void)
...@@ -349,9 +385,9 @@ static void ubd_handler(void) ...@@ -349,9 +385,9 @@ static void ubd_handler(void)
if(n != sizeof(req)){ if(n != sizeof(req)){
printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, " printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, "
"errno = %d\n", os_getpid(), -n); "errno = %d\n", os_getpid(), -n);
spin_lock(&ubd_lock); spin_lock(&ubd_io_lock);
end_request(CURRENT, 0); end_request(CURRENT, 0);
spin_unlock(&ubd_lock); spin_unlock(&ubd_io_lock);
return; return;
} }
...@@ -359,11 +395,9 @@ static void ubd_handler(void) ...@@ -359,11 +395,9 @@ static void ubd_handler(void)
(req.length != (CURRENT->current_nr_sectors) << 9)) (req.length != (CURRENT->current_nr_sectors) << 9))
panic("I/O op mismatch"); panic("I/O op mismatch");
spin_lock(&ubd_lock);
ubd_finish(req.error); ubd_finish(req.error);
reactivate_fd(thread_fd, UBD_IRQ); reactivate_fd(thread_fd, UBD_IRQ);
do_ubd_request(ubd_queue); do_ubd_request(ubd_queue);
spin_unlock(&ubd_lock);
} }
static void ubd_intr(int irq, void *dev, struct pt_regs *unused) static void ubd_intr(int irq, void *dev, struct pt_regs *unused)
...@@ -371,6 +405,7 @@ static void ubd_intr(int irq, void *dev, struct pt_regs *unused) ...@@ -371,6 +405,7 @@ static void ubd_intr(int irq, void *dev, struct pt_regs *unused)
ubd_handler(); ubd_handler();
} }
/* Only changed by ubd_init, which is an initcall. */
static int io_pid = -1; static int io_pid = -1;
void kill_io_thread(void) void kill_io_thread(void)
...@@ -390,6 +425,7 @@ static int ubd_file_size(struct ubd *dev, __u64 *size_out) ...@@ -390,6 +425,7 @@ static int ubd_file_size(struct ubd *dev, __u64 *size_out)
return(os_file_size(file, 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_dir_handle;
devfs_handle_t ubd_fake_dir_handle; devfs_handle_t ubd_fake_dir_handle;
...@@ -402,7 +438,7 @@ static int ubd_add(int n) ...@@ -402,7 +438,7 @@ static int ubd_add(int n)
u64 size; u64 size;
if (!dev->file) if (!dev->file)
return -1; goto out;
disk = alloc_disk(); disk = alloc_disk();
if (!disk) if (!disk)
...@@ -443,23 +479,32 @@ static int ubd_add(int n) ...@@ -443,23 +479,32 @@ static int ubd_add(int n)
MAJOR_NR, n << UBD_SHIFT, MAJOR_NR, n << UBD_SHIFT,
S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |S_IWGRP, S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |S_IWGRP,
&ubd_blops, NULL); &ubd_blops, NULL);
add_disk(disk); if(real == NULL)
goto out;
ubd_dev[n].real = real;
if (fake_major) { if (fake_major) {
fake = devfs_register(ubd_fake_dir_handle, name, fake = devfs_register(ubd_fake_dir_handle, name,
DEVFS_FL_REMOVABLE, fake_major, DEVFS_FL_REMOVABLE, fake_major,
n << UBD_SHIFT, n << UBD_SHIFT,
S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP | S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |
S_IWGRP, &ubd_blops, NULL); S_IWGRP, &ubd_blops, NULL);
add_disk(fake_disk); if(fake == NULL)
if(fake == NULL) return(-1); goto out_unregister;
ubd_dev[n].fake = fake; ubd_dev[n].fake = fake;
add_disk(fake_disk);
} }
if(real == NULL) return(-1); add_disk(disk);
ubd_dev[n].real = real;
make_ide_entries(disk->disk_name); make_ide_entries(disk->disk_name);
return(0); return(0);
out_unregister:
devfs_unregister(real);
ubd_dev[n].real = NULL;
out:
return(-1);
} }
static int ubd_config(char *str) static int ubd_config(char *str)
...@@ -478,24 +523,29 @@ static int ubd_config(char *str) ...@@ -478,24 +523,29 @@ static int ubd_config(char *str)
} }
if(n == -1) return(0); if(n == -1) return(0);
spin_lock(&ubd_lock);
err = ubd_add(n); err = ubd_add(n);
if(err){ if(err)
ubd_dev[n].file = NULL; ubd_dev[n].file = NULL;
return(err); spin_unlock(&ubd_lock);
}
return(0); return(err);
} }
static int ubd_remove(char *str) static int ubd_remove(char *str)
{ {
struct ubd *dev; struct ubd *dev;
int n; int n, err;
if(!isdigit(*str)) return(-1); if(!isdigit(*str))
return(-1);
n = *str - '0'; n = *str - '0';
if(n > MAX_DEV) return(-1); if(n > MAX_DEV)
return(-1);
dev = &ubd_dev[n]; dev = &ubd_dev[n];
err = 0;
spin_lock(&ubd_lock);
del_gendisk(ubd_gendisk[n]); del_gendisk(ubd_gendisk[n]);
put_disk(ubd_gendisk[n]); put_disk(ubd_gendisk[n]);
ubd_gendisk[n] = NULL; ubd_gendisk[n] = NULL;
...@@ -504,12 +554,20 @@ static int ubd_remove(char *str) ...@@ -504,12 +554,20 @@ static int ubd_remove(char *str)
put_disk(fake_gendisk[n]); put_disk(fake_gendisk[n]);
fake_gendisk[n] = NULL; fake_gendisk[n] = NULL;
} }
if(dev->file == NULL) return(0); if(dev->file == NULL)
if(dev->count > 0) return(-1); goto out;
if(dev->real != NULL) devfs_unregister(dev->real); err = -1;
if(dev->fake != NULL) devfs_unregister(dev->fake); 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); *dev = ((struct ubd) DEFAULT_UBD);
return(0); err = 0;
out:
spin_unlock(&ubd_lock);
return(err);
} }
static struct mc_device ubd_mc = { static struct mc_device ubd_mc = {
...@@ -541,7 +599,7 @@ int ubd_init(void) ...@@ -541,7 +599,7 @@ int ubd_init(void)
return -1; return -1;
} }
ubd_queue = BLK_DEFAULT_QUEUE(MAJOR_NR); 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); elevator_init(ubd_queue, &elevator_noop);
if(fake_major != 0){ if(fake_major != 0){
char name[sizeof("ubd_nnn\0")]; char name[sizeof("ubd_nnn\0")];
...@@ -644,22 +702,23 @@ static int ubd_open_dev(struct ubd *dev) ...@@ -644,22 +702,23 @@ static int ubd_open_dev(struct ubd *dev)
} }
return(0); return(0);
error: error:
close_fd(dev->fd); os_close_file(dev->fd);
return(err); return(err);
} }
static int ubd_open(struct inode *inode, struct file *filp) static int ubd_open(struct inode *inode, struct file *filp)
{ {
struct ubd *dev; struct ubd *dev;
int n, offset, err; int n, offset, err = 0;
n = DEVICE_NR(inode->i_rdev); n = DEVICE_NR(inode->i_rdev);
dev = &ubd_dev[n]; dev = &ubd_dev[n];
if(n > MAX_DEV) if(n > MAX_DEV)
return -ENODEV; return -ENODEV;
offset = n << UBD_SHIFT; offset = n << UBD_SHIFT;
if(dev->is_dir == 1) if(dev->is_dir == 1)
return(0); goto out;
if(dev->count == 0){ if(dev->count == 0){
dev->openflags = dev->boot_openflags; dev->openflags = dev->boot_openflags;
...@@ -668,16 +727,16 @@ static int ubd_open(struct inode *inode, struct file *filp) ...@@ -668,16 +727,16 @@ static int ubd_open(struct inode *inode, struct file *filp)
if(err){ if(err){
printk(KERN_ERR "ubd%d: Can't open \"%s\": " printk(KERN_ERR "ubd%d: Can't open \"%s\": "
"errno = %d\n", n, dev->file, -err); "errno = %d\n", n, dev->file, -err);
return(err); goto out;
} }
if(err) return(err);
} }
dev->count++; dev->count++;
if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){ if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){
if(--dev->count == 0) ubd_close(dev); 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) static int ubd_release(struct inode * inode, struct file * file)
...@@ -752,13 +811,17 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) ...@@ -752,13 +811,17 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
if(dev->is_dir){ if(dev->is_dir){
strcpy(req->buffer, "HOSTFS:"); strcpy(req->buffer, "HOSTFS:");
strcat(req->buffer, dev->file); strcat(req->buffer, dev->file);
spin_lock(&ubd_io_lock);
end_request(req, 1); end_request(req, 1);
spin_unlock(&ubd_io_lock);
return(1); return(1);
} }
if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
printk("Write attempted on readonly ubd device %d\n", n); printk("Write attempted on readonly ubd device %d\n", n);
spin_lock(&ubd_io_lock);
end_request(req, 0); end_request(req, 0);
spin_unlock(&ubd_io_lock);
return(1); return(1);
} }
...@@ -892,8 +955,11 @@ static int ubd_revalidate(kdev_t rdev) ...@@ -892,8 +955,11 @@ static int ubd_revalidate(kdev_t rdev)
n = minor(rdev) >> UBD_SHIFT; n = minor(rdev) >> UBD_SHIFT;
dev = &ubd_dev[n]; dev = &ubd_dev[n];
err = 0;
spin_lock(&ubd_lock);
if(dev->is_dir) if(dev->is_dir)
return(0); goto out;
err = ubd_file_size(dev, &size); err = ubd_file_size(dev, &size);
if (!err) { if (!err) {
...@@ -902,7 +968,8 @@ static int ubd_revalidate(kdev_t rdev) ...@@ -902,7 +968,8 @@ static int ubd_revalidate(kdev_t rdev)
set_capacity(fake_gendisk[n], size / 512); set_capacity(fake_gendisk[n], size / 512);
dev->size = size; dev->size = size;
} }
spin_unlock(&ubd_lock);
out:
return err; return err;
} }
......
...@@ -533,8 +533,12 @@ void do_io(struct io_thread_req *req) ...@@ -533,8 +533,12 @@ void do_io(struct io_thread_req *req)
return; return;
} }
/* Changed in start_io_thread, which is serialized by being called only
* from ubd_init, which is an initcall.
*/
int kernel_fd = -1; int kernel_fd = -1;
/* Only changed by the io thread */
int io_count = 0; int io_count = 0;
int io_thread(void *arg) int io_thread(void *arg)
......
...@@ -44,6 +44,7 @@ void *xterm_init(char *str, int device, struct chan_opts *opts) ...@@ -44,6 +44,7 @@ void *xterm_init(char *str, int device, struct chan_opts *opts)
return(data); return(data);
} }
/* Only changed by xterm_setup, which is a setup */
static char *terminal_emulator = "xterm"; static char *terminal_emulator = "xterm";
static char *title_switch = "-T"; static char *title_switch = "-T";
static char *exec_switch = "-e"; static char *exec_switch = "-e";
......
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
next : NULL \ next : NULL \
} }
#define INIT_QUEUE(queue, request, lock) blk_init_queue(queue, request, lock)
#define INIT_HARDSECT(arr, maj, sizes) #define INIT_HARDSECT(arr, maj, sizes)
#define SET_PRI(task) do ; while(0) #define SET_PRI(task) do ; while(0)
......
...@@ -18,7 +18,9 @@ extern void forward_interrupts(int pid); ...@@ -18,7 +18,9 @@ extern void forward_interrupts(int pid);
extern void init_irq_signals(int on_sigstack); extern void init_irq_signals(int on_sigstack);
extern void forward_ipi(int fd, int pid); extern void forward_ipi(int fd, int pid);
extern void free_irq_later(int irq, void *dev_id); 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 #endif
/* /*
......
...@@ -50,12 +50,8 @@ extern int pid_to_processor_id(int pid); ...@@ -50,12 +50,8 @@ extern int pid_to_processor_id(int pid);
extern void block_signals(void); extern void block_signals(void);
extern void unblock_signals(void); extern void unblock_signals(void);
extern void deliver_signals(void *t); extern void deliver_signals(void *t);
extern void lock_syscall(void); extern int next_syscall_index(int max);
extern void unlock_syscall(void); extern int next_trap_index(int max);
extern void lock_trap(void);
extern void unlock_trap(void);
extern void lock_pid(void);
extern void unlock_pid(void);
extern void default_idle(void); extern void default_idle(void);
extern void finish_fork(void); extern void finish_fork(void);
extern void paging_init(void); extern void paging_init(void);
...@@ -121,7 +117,7 @@ extern void arch_switch(void); ...@@ -121,7 +117,7 @@ extern void arch_switch(void);
extern int is_valid_pid(int pid); extern int is_valid_pid(int pid);
extern void free_irq(unsigned int, void *); extern void free_irq(unsigned int, void *);
extern int um_in_interrupt(void); extern int um_in_interrupt(void);
extern int cpu(void);
#endif #endif
/* /*
......
...@@ -77,6 +77,8 @@ extern int mconsole_get_request(int fd, struct mc_request *req); ...@@ -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, extern int mconsole_notify(char *sock_name, int type, const void *data,
int len); int len);
extern char *mconsole_notify_socket(void); extern char *mconsole_notify_socket(void);
extern void lock_notify(void);
extern void unlock_notify(void);
#endif #endif
......
...@@ -11,6 +11,8 @@ extern int register_sigio_fd(int fd); ...@@ -11,6 +11,8 @@ extern int register_sigio_fd(int fd);
extern int read_sigio_fd(int fd); extern int read_sigio_fd(int fd);
extern int add_sigio_fd(int fd, int read); extern int add_sigio_fd(int fd, int read);
extern int ignore_sigio_fd(int fd); extern int ignore_sigio_fd(int fd);
extern void sigio_lock(void);
extern void sigio_unlock(void);
#endif #endif
......
...@@ -7,11 +7,11 @@ ...@@ -7,11 +7,11 @@
#define __TIME_USER_H__ #define __TIME_USER_H__
extern void timer(void); 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 switch_timers(int to_real);
extern void user_time_init(void); extern void user_time_init(void);
extern void set_timers(int set_signal);
extern void idle_sleep(int secs); extern void idle_sleep(int secs);
extern void enable_timer(void);
extern void time_lock(void);
extern void time_unlock(void);
#endif #endif
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "tlb.h" #include "tlb.h"
#include "2_5compat.h" #include "2_5compat.h"
#include "os.h" #include "os.h"
#include "time_user.h"
/* See comment above fork_tramp for why sigstop is defined and used like /* See comment above fork_tramp for why sigstop is defined and used like
* this * this
...@@ -28,7 +29,6 @@ static int exec_tramp(void *sig_stack) ...@@ -28,7 +29,6 @@ static int exec_tramp(void *sig_stack)
{ {
int sig = sigstop; int sig = sigstop;
block_signals();
init_new_thread(sig_stack, NULL); init_new_thread(sig_stack, NULL);
kill(os_getpid(), sig); kill(os_getpid(), sig);
return(0); return(0);
...@@ -62,6 +62,7 @@ void flush_thread(void) ...@@ -62,6 +62,7 @@ void flush_thread(void)
unprotect_stack((unsigned long) current->thread_info); unprotect_stack((unsigned long) current->thread_info);
os_usr1_process(os_getpid()); os_usr1_process(os_getpid());
enable_timer();
free_page(stack); free_page(stack);
protect(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); protect(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
task_protections((unsigned long) current->thread_info); task_protections((unsigned long) current->thread_info);
......
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
#include "linux/proc_fs.h" #include "linux/proc_fs.h"
#include "asm/uaccess.h" #include "asm/uaccess.h"
/* If read and write race, the read will still atomically read a valid
* value.
*/
int uml_exitcode = 0; int uml_exitcode = 0;
static int read_proc_exitcode(char *page, char **start, off_t off, static int read_proc_exitcode(char *page, char **start, off_t off,
......
...@@ -130,6 +130,7 @@ static void child_common(void *sp, int size, sighandler_t handler, int flags) ...@@ -130,6 +130,7 @@ static void child_common(void *sp, int size, sighandler_t handler, int flags)
os_stop_process(os_getpid()); os_stop_process(os_getpid());
} }
/* Changed only during early boot */
struct sc_frame signal_frame_sc; struct sc_frame signal_frame_sc;
struct sc_frame_raw { struct sc_frame_raw {
...@@ -142,6 +143,7 @@ struct sc_frame_raw { ...@@ -142,6 +143,7 @@ struct sc_frame_raw {
struct arch_frame_data_raw arch; struct arch_frame_data_raw arch;
}; };
/* Changed only during early boot */
static struct sc_frame_raw *raw_sc = NULL; static struct sc_frame_raw *raw_sc = NULL;
static void sc_handler(int sig, struct sigcontext sc) static void sc_handler(int sig, struct sigcontext sc)
...@@ -163,6 +165,7 @@ static int sc_child(void *arg) ...@@ -163,6 +165,7 @@ static int sc_child(void *arg)
return(-1); return(-1);
} }
/* Changed only during early boot */
struct si_frame signal_frame_si; struct si_frame signal_frame_si;
struct si_frame_raw { struct si_frame_raw {
...@@ -175,6 +178,7 @@ struct si_frame_raw { ...@@ -175,6 +178,7 @@ struct si_frame_raw {
unsigned long sp; unsigned long sp;
}; };
/* Changed only during early boot */
static struct si_frame_raw *raw_si = NULL; static struct si_frame_raw *raw_si = NULL;
static void si_handler(int sig, siginfo_t *si) static void si_handler(int sig, siginfo_t *si)
......
...@@ -22,6 +22,7 @@ struct helper_data { ...@@ -22,6 +22,7 @@ struct helper_data {
int fd; int fd;
}; };
/* Debugging aid, changed only from gdb */
int helper_pause = 0; int helper_pause = 0;
static void helper_hup(int sig) static void helper_hup(int sig)
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "init.h" #include "init.h"
#include "os.h" #include "os.h"
/* Changed by uml_initrd_setup, which is a setup */
static char *initrd __initdata = NULL; static char *initrd __initdata = NULL;
static int __init read_initrd(void) static int __init read_initrd(void)
......
...@@ -78,6 +78,7 @@ struct hw_interrupt_type no_irq_type = { ...@@ -78,6 +78,7 @@ struct hw_interrupt_type no_irq_type = {
end_none end_none
}; };
/* Not changed */
volatile unsigned long irq_err_count; volatile unsigned long irq_err_count;
/* /*
...@@ -87,6 +88,7 @@ volatile unsigned long irq_err_count; ...@@ -87,6 +88,7 @@ volatile unsigned long irq_err_count;
int get_irq_list(char *buf) int get_irq_list(char *buf)
{ {
int i, j; int i, j;
unsigned long flags;
struct irqaction * action; struct irqaction * action;
char *p = buf; char *p = buf;
...@@ -96,9 +98,10 @@ int get_irq_list(char *buf) ...@@ -96,9 +98,10 @@ int get_irq_list(char *buf)
*p++ = '\n'; *p++ = '\n';
for (i = 0 ; i < NR_IRQS ; i++) { for (i = 0 ; i < NR_IRQS ; i++) {
spin_lock_irqsave(&irq_desc[i].lock, flags);
action = irq_desc[i].action; action = irq_desc[i].action;
if (!action) if (!action)
continue; goto end;
p += sprintf(p, "%3d: ",i); p += sprintf(p, "%3d: ",i);
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
p += sprintf(p, "%10u ", kstat_irqs(i)); p += sprintf(p, "%10u ", kstat_irqs(i));
...@@ -113,6 +116,8 @@ int get_irq_list(char *buf) ...@@ -113,6 +116,8 @@ int get_irq_list(char *buf)
for (action=action->next; action; action = action->next) for (action=action->next; action; action = action->next)
p += sprintf(p, ", %s", action->name); p += sprintf(p, ", %s", action->name);
*p++ = '\n'; *p++ = '\n';
end:
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
} }
p += sprintf(p, "\n"); p += sprintf(p, "\n");
#ifdef notdef #ifdef notdef
...@@ -548,11 +553,15 @@ void free_irq(unsigned int irq, void *dev_id) ...@@ -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 * root_irq_dir;
static struct proc_dir_entry * irq_dir [NR_IRQS]; static struct proc_dir_entry * irq_dir [NR_IRQS];
static struct proc_dir_entry * smp_affinity_entry [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 #define HEX_DIGITS 8
...@@ -679,6 +688,7 @@ static void register_irq_proc (unsigned int irq) ...@@ -679,6 +688,7 @@ static void register_irq_proc (unsigned int irq)
smp_affinity_entry[irq] = entry; smp_affinity_entry[irq] = entry;
} }
/* Read and written as a long */
unsigned long prof_cpu_mask = -1; unsigned long prof_cpu_mask = -1;
void __init init_irq_proc (void) void __init init_irq_proc (void)
...@@ -704,6 +714,21 @@ void __init init_irq_proc (void) ...@@ -704,6 +714,21 @@ void __init init_irq_proc (void)
register_irq_proc(i); 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) unsigned long probe_irq_on(void)
{ {
return(0); return(0);
......
...@@ -111,40 +111,20 @@ static void maybe_sigio_broken(int fd, int type) ...@@ -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) int activate_fd(int irq, int fd, int type, void *dev_id)
{ {
struct irq_fd *new_fd; struct pollfd *tmp_pfd;
int pid, retval, events, err; 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)); new_fd = um_kmalloc(sizeof(*new_fd));
err = -ENOMEM; err = -ENOMEM;
if(new_fd == NULL) return(err); if(new_fd == NULL)
pollfds_num++; goto out;
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(type == IRQ_READ) events = POLLIN | POLLPRI; if(type == IRQ_READ) events = POLLIN | POLLPRI;
else events = POLLOUT; else events = POLLOUT;
...@@ -158,29 +138,90 @@ int activate_fd(int irq, int fd, int type, void *dev_id) ...@@ -158,29 +138,90 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
current_events: 0, current_events: 0,
freed : 0 } ); freed : 0 } );
*last_irq_ptr = new_fd; /* Critical section - locked by a spinlock because this stuff can
last_irq_ptr = &new_fd->next; * 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_free;
}
}
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; if(type == IRQ_WRITE) events = 0;
pollfds[pollfds_num - 1] = ((struct pollfd) { fd : fd, pollfds[pollfds_num] = ((struct pollfd) { fd : fd,
events : events, events : events,
revents : 0 }); 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); maybe_sigio_broken(fd, type);
return(0); return(0);
out_irq: out_unlock:
irq_unlock(flags);
out_free:
kfree(new_fd); kfree(new_fd);
out:
return(err); return(err);
} }
static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg) static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
{ {
struct irq_fd **prev; struct irq_fd **prev;
unsigned long flags;
int i = 0; int i = 0;
flags = irq_lock();
prev = &active_fds; prev = &active_fds;
while(*prev != NULL){ while(*prev != NULL){
if((*test)(*prev, arg)){ if((*test)(*prev, arg)){
...@@ -190,7 +231,7 @@ static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *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 " printk("free_irq_by_cb - mismatch between "
"active_fds and pollfds, fd %d vs %d\n", "active_fds and pollfds, fd %d vs %d\n",
(*prev)->fd, pollfds[i].fd); (*prev)->fd, pollfds[i].fd);
return; goto out;
} }
memcpy(&pollfds[i], &pollfds[i + 1], memcpy(&pollfds[i], &pollfds[i + 1],
(pollfds_num - i - 1) * sizeof(pollfds[0])); (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) ...@@ -206,6 +247,8 @@ static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
prev = &(*prev)->next; prev = &(*prev)->next;
i++; i++;
} }
out:
irq_unlock(flags);
} }
struct irq_and_dev { struct irq_and_dev {
...@@ -242,29 +285,33 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out) ...@@ -242,29 +285,33 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
{ {
struct irq_fd *irq; struct irq_fd *irq;
int i = 0; int i = 0;
for(irq=active_fds; irq != NULL; irq = irq->next){ for(irq=active_fds; irq != NULL; irq = irq->next){
if((irq->fd == fd) && (irq->irq == irqnum)) break; if((irq->fd == fd) && (irq->irq == irqnum)) break;
i++; i++;
} }
if(irq == NULL){ if(irq == NULL){
printk("find_irq_by_fd doesn't have descriptor %d\n", fd); 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)){ if((pollfds[i].fd != -1) && (pollfds[i].fd != fd)){
printk("find_irq_by_fd - mismatch between active_fds and " printk("find_irq_by_fd - mismatch between active_fds and "
"pollfds, fd %d vs %d, need %d\n", irq->fd, "pollfds, fd %d vs %d, need %d\n", irq->fd,
pollfds[i].fd, fd); pollfds[i].fd, fd);
return(NULL); irq = NULL;
goto out;
} }
*index_out = i; *index_out = i;
out:
return(irq); return(irq);
} }
void free_irq_later(int irq, void *dev_id) void free_irq_later(int irq, void *dev_id)
{ {
struct irq_fd *irq_fd; struct irq_fd *irq_fd;
unsigned long flags;
flags = irq_lock();
for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){ for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
if((irq_fd->irq == irq) && (irq_fd->id == dev_id)) if((irq_fd->irq == irq) && (irq_fd->id == dev_id))
break; break;
...@@ -272,30 +319,48 @@ void free_irq_later(int irq, void *dev_id) ...@@ -272,30 +319,48 @@ void free_irq_later(int irq, void *dev_id)
if(irq_fd == NULL){ if(irq_fd == NULL){
printk("free_irq_later found no irq, irq = %d, " printk("free_irq_later found no irq, irq = %d, "
"dev_id = 0x%p\n", irq, dev_id); "dev_id = 0x%p\n", irq, dev_id);
return; goto out;
} }
irq_fd->freed = 1; irq_fd->freed = 1;
out:
irq_unlock(flags);
} }
void reactivate_fd(int fd, int irqnum) void reactivate_fd(int fd, int irqnum)
{ {
struct irq_fd *irq; struct irq_fd *irq;
unsigned long flags;
int i; int i;
flags = irq_lock();
irq = find_irq_by_fd(fd, irqnum, &i); irq = find_irq_by_fd(fd, irqnum, &i);
if(irq == NULL) return; if(irq == NULL)
goto out;
pollfds[i].fd = irq->fd; 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); maybe_sigio_broken(fd, irq->type);
out:
irq_unlock(flags);
} }
void deactivate_fd(int fd, int irqnum) void deactivate_fd(int fd, int irqnum)
{ {
struct irq_fd *irq; struct irq_fd *irq;
unsigned long flags;
int i; int i;
flags = irq_lock();
irq = find_irq_by_fd(fd, irqnum, &i); irq = find_irq_by_fd(fd, irqnum, &i);
if(irq == NULL) return; if(irq == NULL)
goto out;
pollfds[i].fd = -1; pollfds[i].fd = -1;
out:
irq_unlock(flags);
} }
void forward_ipi(int fd, int pid) void forward_ipi(int fd, int pid)
...@@ -313,7 +378,9 @@ void forward_ipi(int fd, int pid) ...@@ -313,7 +378,9 @@ void forward_ipi(int fd, int pid)
void forward_interrupts(int pid) void forward_interrupts(int pid)
{ {
struct irq_fd *irq; struct irq_fd *irq;
unsigned long flags;
flags = irq_lock();
for(irq=active_fds;irq != NULL;irq = irq->next){ for(irq=active_fds;irq != NULL;irq = irq->next){
if(fcntl(irq->fd, F_SETOWN, pid) < 0){ if(fcntl(irq->fd, F_SETOWN, pid) < 0){
int save_errno = errno; int save_errno = errno;
...@@ -328,6 +395,7 @@ void forward_interrupts(int pid) ...@@ -328,6 +395,7 @@ void forward_interrupts(int pid)
} }
irq->pid = pid; irq->pid = pid;
} }
irq_unlock(flags);
} }
void init_irq_signals(int on_sigstack) void init_irq_signals(int on_sigstack)
...@@ -339,10 +407,10 @@ 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; if(timer_irq_inited) h = (__sighandler_t) alarm_handler;
else h = boot_timer_handler; else h = boot_timer_handler;
set_handler(SIGVTALRM, h, flags | SA_NODEFER | SA_RESTART, set_handler(SIGVTALRM, h, flags | SA_RESTART,
SIGUSR1, SIGIO, SIGWINCH, -1); SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1);
set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART, set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART,
SIGUSR1, SIGIO, SIGWINCH, -1); SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
signal(SIGWINCH, SIG_IGN); signal(SIGWINCH, SIG_IGN);
} }
......
...@@ -26,33 +26,32 @@ ...@@ -26,33 +26,32 @@
#include "kern.h" #include "kern.h"
#include "init.h" #include "init.h"
/* Changed during early boot */
pgd_t swapper_pg_dir[1024];
unsigned long high_physmem; unsigned long high_physmem;
unsigned long low_physmem;
unsigned long vm_start; unsigned long vm_start;
unsigned long vm_end; unsigned long vm_end;
unsigned long highmem; unsigned long highmem;
pgd_t swapper_pg_dir[1024];
unsigned long *empty_zero_page = NULL; unsigned long *empty_zero_page = NULL;
unsigned long *empty_bad_page = NULL; unsigned long *empty_bad_page = NULL;
/* Not modified */
const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n"; const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
extern char __init_begin, __init_end; extern char __init_begin, __init_end;
extern long physmem_size; extern long physmem_size;
/* Not changed by UML */
mmu_gather_t mmu_gathers[NR_CPUS]; mmu_gather_t mmu_gathers[NR_CPUS];
/* Changed during early boot */
int kmalloc_ok = 0; int kmalloc_ok = 0;
#define NREGIONS (phys_region_index(0xffffffff) - phys_region_index(0x0) + 1) #define NREGIONS (phys_region_index(0xffffffff) - phys_region_index(0x0) + 1)
struct mem_region *regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] = NULL }; struct mem_region *regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] = NULL };
#define REGION_SIZE ((0xffffffff & ~REGION_MASK) + 1) #define REGION_SIZE ((0xffffffff & ~REGION_MASK) + 1)
/* Changed during early boot */
static unsigned long brk_end; static unsigned long brk_end;
static void map_cb(void *unused) static void map_cb(void *unused)
...@@ -108,6 +107,7 @@ void mem_init(void) ...@@ -108,6 +107,7 @@ void mem_init(void)
} }
#if CONFIG_HIGHMEM #if CONFIG_HIGHMEM
/* Changed during early boot */
pte_t *kmap_pte; pte_t *kmap_pte;
pgprot_t kmap_prot; pgprot_t kmap_prot;
...@@ -187,18 +187,22 @@ int init_maps(struct mem_region *region) ...@@ -187,18 +187,22 @@ int init_maps(struct mem_region *region)
return(0); return(0);
} }
DECLARE_MUTEX(regions_sem);
static int setup_one_range(int fd, char *driver, unsigned long start, static int setup_one_range(int fd, char *driver, unsigned long start,
unsigned long pfn, int len, unsigned long pfn, int len,
struct mem_region *region) struct mem_region *region)
{ {
int i; int i;
down(&regions_sem);
for(i = 0; i < NREGIONS; i++){ for(i = 0; i < NREGIONS; i++){
if(regions[i] == NULL) break; if(regions[i] == NULL) break;
} }
if(i == NREGIONS){ if(i == NREGIONS){
printk("setup_range : no free regions\n"); printk("setup_range : no free regions\n");
return(-1); i = -1;
goto out;
} }
if(fd == -1) if(fd == -1)
...@@ -216,6 +220,8 @@ static int setup_one_range(int fd, char *driver, unsigned long start, ...@@ -216,6 +220,8 @@ static int setup_one_range(int fd, char *driver, unsigned long start,
len : len, len : len,
fd : fd } ); fd : fd } );
regions[i] = region; regions[i] = region;
out:
up(&regions_sem);
return(i); return(i);
} }
...@@ -373,7 +379,8 @@ void show_mem(void) ...@@ -373,7 +379,8 @@ void show_mem(void)
printk("%d pages swap cached\n", cached); 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) unsigned long get_kmem_end(void)
{ {
...@@ -428,8 +435,10 @@ struct page *arch_validate(struct page *page, int mask, int order) ...@@ -428,8 +435,10 @@ struct page *arch_validate(struct page *page, int mask, int order)
goto again; goto again;
} }
DECLARE_MUTEX(vm_reserved_sem);
static struct list_head vm_reserved = LIST_HEAD_INIT(vm_reserved); 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 = { static struct vm_reserved head = {
list : LIST_HEAD_INIT(head.list), list : LIST_HEAD_INIT(head.list),
start : 0, start : 0,
...@@ -455,7 +464,9 @@ int reserve_vm(unsigned long start, unsigned long end, void *e) ...@@ -455,7 +464,9 @@ int reserve_vm(unsigned long start, unsigned long end, void *e)
{ {
struct vm_reserved *entry = e, *reserved, *prev; struct vm_reserved *entry = e, *reserved, *prev;
struct list_head *ele; struct list_head *ele;
int err;
down(&vm_reserved_sem);
list_for_each(ele, &vm_reserved){ list_for_each(ele, &vm_reserved){
reserved = list_entry(ele, struct vm_reserved, list); reserved = list_entry(ele, struct vm_reserved, list);
if(reserved->start >= end) goto found; if(reserved->start >= end) goto found;
...@@ -469,13 +480,17 @@ int reserve_vm(unsigned long start, unsigned long end, void *e) ...@@ -469,13 +480,17 @@ int reserve_vm(unsigned long start, unsigned long end, void *e)
entry = kmalloc(sizeof(*entry), GFP_KERNEL); entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if(entry == NULL){ if(entry == NULL){
printk("reserve_vm : Failed to allocate entry\n"); printk("reserve_vm : Failed to allocate entry\n");
return(-ENOMEM); err = -ENOMEM;
goto out;
} }
*entry = ((struct vm_reserved) *entry = ((struct vm_reserved)
{ list : LIST_HEAD_INIT(entry->list), { list : LIST_HEAD_INIT(entry->list),
start : start, start : start,
end : end }); end : end });
list_add(&entry->list, &prev->list); list_add(&entry->list, &prev->list);
err = 0;
out:
up(&vm_reserved_sem);
return(0); return(0);
} }
...@@ -486,6 +501,7 @@ unsigned long get_vm(unsigned long len) ...@@ -486,6 +501,7 @@ unsigned long get_vm(unsigned long len)
unsigned long start; unsigned long start;
int err; int err;
down(&vm_reserved_sem);
list_for_each(ele, &vm_reserved){ list_for_each(ele, &vm_reserved){
this = list_entry(ele, struct vm_reserved, list); this = list_entry(ele, struct vm_reserved, list);
next = list_entry(ele->next, struct vm_reserved, list); next = list_entry(ele->next, struct vm_reserved, list);
...@@ -493,8 +509,10 @@ unsigned long get_vm(unsigned long len) ...@@ -493,8 +509,10 @@ unsigned long get_vm(unsigned long len)
(this->end + len + PAGE_SIZE <= next->start)) (this->end + len + PAGE_SIZE <= next->start))
goto found; goto found;
} }
up(&vm_reserved_sem);
return(0); return(0);
found: found:
up(&vm_reserved_sem);
start = (unsigned long) ROUND_UP(this->end) + PAGE_SIZE; start = (unsigned long) ROUND_UP(this->end) + PAGE_SIZE;
err = reserve_vm(start, start + len, NULL); err = reserve_vm(start, start + len, NULL);
if(err) return(0); if(err) return(0);
...@@ -533,7 +551,11 @@ struct iomem { ...@@ -533,7 +551,11 @@ struct iomem {
unsigned long size; 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, { name : NULL,
fd : -1, fd : -1,
size : 0 } }; size : 0 } };
...@@ -569,6 +591,7 @@ __initcall(setup_iomem); ...@@ -569,6 +591,7 @@ __initcall(setup_iomem);
#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) #define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
/* Changed during early boot */
static struct mem_region physmem_region; static struct mem_region physmem_region;
static struct vm_reserved physmem_reserved; static struct vm_reserved physmem_reserved;
......
...@@ -46,10 +46,9 @@ ...@@ -46,10 +46,9 @@
#include "mem_user.h" #include "mem_user.h"
#include "init.h" #include "init.h"
#include "os.h" #include "os.h"
#include "tempfile.h"
struct mem_region physmem_region; extern struct mem_region physmem_region;
struct mem_region *mem_list = &physmem_region;
#define TEMPNAME_TEMPLATE "vm_file-XXXXXX" #define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
......
...@@ -48,23 +48,23 @@ void init_new_thread(void *sig_stack, void (*usr1_handler)(int)) ...@@ -48,23 +48,23 @@ void init_new_thread(void *sig_stack, void (*usr1_handler)(int))
flags = SA_ONSTACK; flags = SA_ONSTACK;
} }
set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags, 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, 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, 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, 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, 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, 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, set_handler(SIGUSR2, (__sighandler_t) sig_handler,
SA_NOMASK | flags, -1); SA_NOMASK | flags, -1);
if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1); if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1);
signal(SIGCHLD, SIG_IGN); signal(SIGCHLD, SIG_IGN);
signal(SIGHUP, SIG_IGN); signal(SIGHUP, SIG_IGN);
set_timers(1); /* XXX A bit of a race here */
init_irq_signals(sig_stack != NULL); init_irq_signals(sig_stack != NULL);
} }
......
...@@ -41,6 +41,10 @@ ...@@ -41,6 +41,10 @@
#include "2_5compat.h" #include "2_5compat.h"
#include "os.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 cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
struct task_struct *get_task(int pid, int require) struct task_struct *get_task(int pid, int require)
...@@ -86,7 +90,7 @@ int pid_to_processor_id(int pid) ...@@ -86,7 +90,7 @@ int pid_to_processor_id(int pid)
{ {
int i; int i;
for(i = 0; i < num_online_cpus(); i++){ for(i = 0; i < ncpus; i++){
if(cpu_tasks[i].pid == pid) return(i); if(cpu_tasks[i].pid == pid) return(i);
} }
return(-1); return(-1);
...@@ -152,12 +156,19 @@ static void new_thread_handler(int sig) ...@@ -152,12 +156,19 @@ static void new_thread_handler(int sig)
current->thread.regs.regs.sc = (void *) (&sig + 1); current->thread.regs.regs.sc = (void *) (&sig + 1);
suspend_new_thread(current->thread.switch_pipe[0]); 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); free_page(current->thread.temp_stack);
set_cmdline("(kernel thread)"); set_cmdline("(kernel thread)");
force_flush_all(); force_flush_all();
current->thread.prev_sched = NULL; current->thread.prev_sched = NULL;
change_sig(SIGUSR1, 1); change_sig(SIGUSR1, 1);
change_sig(SIGVTALRM, 1);
change_sig(SIGPROF, 1);
unblock_signals(); unblock_signals();
if(!run_kernel_thread(fn, arg, &current->thread.jmp)) if(!run_kernel_thread(fn, arg, &current->thread.jmp))
do_exit(0); do_exit(0);
...@@ -165,7 +176,9 @@ static void new_thread_handler(int sig) ...@@ -165,7 +176,9 @@ static void new_thread_handler(int sig)
static int new_thread_proc(void *stack) 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); init_new_thread(stack, new_thread_handler);
os_usr1_process(os_getpid()); os_usr1_process(os_getpid());
return(0); return(0);
...@@ -204,6 +217,9 @@ void *switch_to(void *prev, void *next, void *last) ...@@ -204,6 +217,9 @@ void *switch_to(void *prev, void *next, void *last)
unsigned long flags; unsigned long flags;
int vtalrm, alrm, prof, err, cpu; int vtalrm, alrm, prof, err, cpu;
char c; char c;
/* jailing and SMP are incompatible, so this doesn't need to be
* made per-cpu
*/
static int reading; static int reading;
from = prev; from = prev;
...@@ -298,13 +314,14 @@ void exit_thread(void) ...@@ -298,13 +314,14 @@ void exit_thread(void)
* onto the signal frame. * onto the signal frame.
*/ */
extern int hit_me;
void finish_fork_handler(int sig) void finish_fork_handler(int sig)
{ {
current->thread.regs.regs.sc = (void *) (&sig + 1); current->thread.regs.regs.sc = (void *) (&sig + 1);
suspend_new_thread(current->thread.switch_pipe[0]); suspend_new_thread(current->thread.switch_pipe[0]);
schedule_tail(NULL);
enable_timer();
change_sig(SIGVTALRM, 1);
force_flush_all(); force_flush_all();
if(current->mm != current->parent->mm) if(current->mm != current->parent->mm)
protect(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); protect(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
...@@ -313,7 +330,6 @@ void finish_fork_handler(int sig) ...@@ -313,7 +330,6 @@ void finish_fork_handler(int sig)
current->thread.prev_sched = NULL; current->thread.prev_sched = NULL;
free_page(current->thread.temp_stack); free_page(current->thread.temp_stack);
block_signals();
change_sig(SIGUSR1, 0); change_sig(SIGUSR1, 0);
set_user_mode(current); set_user_mode(current);
} }
...@@ -339,7 +355,9 @@ int fork_tramp(void *stack) ...@@ -339,7 +355,9 @@ int fork_tramp(void *stack)
{ {
int sig = sigusr1; int sig = sigusr1;
block_signals(); change_sig(SIGIO, 0);
change_sig(SIGVTALRM, 0);
change_sig(SIGPROF, 0);
init_new_thread(stack, finish_fork_handler); init_new_thread(stack, finish_fork_handler);
kill(os_getpid(), sig); kill(os_getpid(), sig);
...@@ -474,7 +492,7 @@ int current_pid(void) ...@@ -474,7 +492,7 @@ int current_pid(void)
void default_idle(void) void default_idle(void)
{ {
if(current->thread_info->cpu == 0) idle_timer(); idle_timer();
atomic_inc(&init_mm.mm_count); atomic_inc(&init_mm.mm_count);
current->mm = &init_mm; current->mm = &init_mm;
...@@ -644,6 +662,7 @@ char *uml_strdup(char *string) ...@@ -644,6 +662,7 @@ char *uml_strdup(char *string)
return(new); return(new);
} }
/* Changed by jail_setup, which is a setup */
int jail = 0; int jail = 0;
int __init jail_setup(char *line, int *add) int __init jail_setup(char *line, int *add)
...@@ -708,17 +727,14 @@ static void mprotect_kernel_mem(int w) ...@@ -708,17 +727,14 @@ static void mprotect_kernel_mem(int w)
mprotect_kernel_vm(w); mprotect_kernel_vm(w);
} }
int jail_timer_off = 0; /* No SMP problems since jailing and SMP are incompatible */
void unprotect_kernel_mem(void) void unprotect_kernel_mem(void)
{ {
mprotect_kernel_mem(1); mprotect_kernel_mem(1);
jail_timer_off = 0;
} }
void protect_kernel_mem(void) void protect_kernel_mem(void)
{ {
jail_timer_off = 1;
mprotect_kernel_mem(0); mprotect_kernel_mem(0);
} }
...@@ -749,9 +765,11 @@ void set_thread_sc(void *sc) ...@@ -749,9 +765,11 @@ void set_thread_sc(void *sc)
int smp_sigio_handler(void) int smp_sigio_handler(void)
{ {
int cpu = current->thread_info->cpu;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
IPI_handler(hard_smp_processor_id()); IPI_handler(cpu);
if (hard_smp_processor_id() != 0) return(1); if(cpu != 0)
return(1);
#endif #endif
return(0); return(0);
} }
...@@ -761,6 +779,11 @@ int um_in_interrupt(void) ...@@ -761,6 +779,11 @@ int um_in_interrupt(void)
return(in_interrupt()); return(in_interrupt());
} }
int cpu(void)
{
return(current->thread_info->cpu);
}
/* /*
* Overrides for Emacs so that we follow Linus's tabbing style. * Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically * Emacs will notice this stuff at the end of the file and automatically
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "sigio.h" #include "sigio.h"
#include "irq_user.h" #include "irq_user.h"
/* Protected by sigio_lock() called from write_sigio_workaround */
static int sigio_irq_fd = -1; static int sigio_irq_fd = -1;
void sigio_interrupt(int irq, void *data, struct pt_regs *unused) void sigio_interrupt(int irq, void *data, struct pt_regs *unused)
...@@ -31,6 +32,18 @@ int write_sigio_irq(int fd) ...@@ -31,6 +32,18 @@ int write_sigio_irq(int fd)
return(0); 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. * Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically * Emacs will notice this stuff at the end of the file and automatically
......
...@@ -21,9 +21,11 @@ ...@@ -21,9 +21,11 @@
#include "helper.h" #include "helper.h"
#include "os.h" #include "os.h"
/* Changed during early boot */
int pty_output_sigio = 0; int pty_output_sigio = 0;
int pty_close_sigio = 0; int pty_close_sigio = 0;
/* Used as a flag during SIGIO testing early in boot */
static int got_sigio = 0; static int got_sigio = 0;
void __init handler(int sig) void __init handler(int sig)
...@@ -151,7 +153,15 @@ void __init check_sigio(void) ...@@ -151,7 +153,15 @@ void __init check_sigio(void)
check_one_sigio(tty_close); check_one_sigio(tty_close);
} }
/* Protected by sigio_lock(), also used by sigio_cleanup, which is an
* exitcall.
*/
static int write_sigio_pid = -1; 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 write_sigio_fds[2] = { -1, -1 };
static int sigio_private[2] = { -1, -1 }; static int sigio_private[2] = { -1, -1 };
...@@ -161,6 +171,9 @@ struct pollfds { ...@@ -161,6 +171,9 @@ struct pollfds {
int used; int used;
}; };
/* Protected by sigio_lock(). Used by the sigio thread, but the UML thread
* synchronizes with it.
*/
struct pollfds current_poll = { struct pollfds current_poll = {
poll : NULL, poll : NULL,
size : 0, size : 0,
...@@ -217,8 +230,6 @@ static int write_sigio_thread(void *unused) ...@@ -217,8 +230,6 @@ static int write_sigio_thread(void *unused)
} }
} }
/* XXX SMP locking needed here too */
static int need_poll(int n) static int need_poll(int n)
{ {
if(n <= next_poll.size){ if(n <= next_poll.size){
...@@ -260,25 +271,31 @@ static void update_thread(void) ...@@ -260,25 +271,31 @@ static void update_thread(void)
set_signals(flags); set_signals(flags);
return; return;
fail: fail:
sigio_lock();
if(write_sigio_pid != -1) kill(write_sigio_pid, SIGKILL); if(write_sigio_pid != -1) kill(write_sigio_pid, SIGKILL);
write_sigio_pid = -1; write_sigio_pid = -1;
close(sigio_private[0]); close(sigio_private[0]);
close(sigio_private[1]); close(sigio_private[1]);
close(write_sigio_fds[0]); close(write_sigio_fds[0]);
close(write_sigio_fds[1]); close(write_sigio_fds[1]);
sigio_unlock();
set_signals(flags); set_signals(flags);
} }
int add_sigio_fd(int fd, int read) 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++) sigio_lock();
if(current_poll.poll[i].fd == fd) return(0); for(i = 0; i < current_poll.used; i++){
if(current_poll.poll[i].fd == fd)
goto out;
}
n = current_poll.used + 1; n = current_poll.used + 1;
err = need_poll(n); err = need_poll(n);
if(err) return(err); if(err)
goto out;
for(i = 0; i < current_poll.used; i++) for(i = 0; i < current_poll.used; i++)
next_poll.poll[i] = current_poll.poll[i]; next_poll.poll[i] = current_poll.poll[i];
...@@ -290,21 +307,26 @@ int add_sigio_fd(int fd, int read) ...@@ -290,21 +307,26 @@ int add_sigio_fd(int fd, int read)
events : events, events : events,
revents : 0 }); revents : 0 });
update_thread(); update_thread();
return(0); out:
sigio_unlock();
return(err);
} }
int ignore_sigio_fd(int fd) int ignore_sigio_fd(int fd)
{ {
struct pollfd *p; struct pollfd *p;
int err, i, n = 0; int err = 0, i, n = 0;
sigio_lock();
for(i = 0; i < current_poll.used; i++){ for(i = 0; i < current_poll.used; i++){
if(current_poll.poll[i].fd == fd) break; 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); err = need_poll(current_poll.used - 1);
if(err) return(err); if(err)
goto out;
for(i = 0; i < current_poll.used; i++){ for(i = 0; i < current_poll.used; i++){
p = &current_poll.poll[i]; p = &current_poll.poll[i];
...@@ -312,11 +334,14 @@ int ignore_sigio_fd(int fd) ...@@ -312,11 +334,14 @@ int ignore_sigio_fd(int fd)
} }
if(n == i){ if(n == i){
printk("ignore_sigio_fd : fd %d not found\n", fd); printk("ignore_sigio_fd : fd %d not found\n", fd);
return(-1); err = -1;
goto out;
} }
update_thread(); update_thread();
return(0); out:
sigio_unlock();
return(err);
} }
static int setup_initial_poll(int fd) static int setup_initial_poll(int fd)
...@@ -342,14 +367,15 @@ void write_sigio_workaround(void) ...@@ -342,14 +367,15 @@ void write_sigio_workaround(void)
unsigned long stack; unsigned long stack;
int err; 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); err = os_pipe(write_sigio_fds, 1, 1);
if(err){ if(err){
printk("write_sigio_workaround - os_pipe 1 failed, " printk("write_sigio_workaround - os_pipe 1 failed, "
"errno = %d\n", -err); "errno = %d\n", -err);
return; goto out;
} }
err = os_pipe(sigio_private, 1, 1); err = os_pipe(sigio_private, 1, 1);
if(err){ if(err){
...@@ -368,6 +394,8 @@ void write_sigio_workaround(void) ...@@ -368,6 +394,8 @@ void write_sigio_workaround(void)
if(write_sigio_irq(write_sigio_fds[0])) if(write_sigio_irq(write_sigio_fds[0]))
goto out_kill; goto out_kill;
out:
sigio_unlock();
return; return;
out_kill: out_kill:
...@@ -379,6 +407,7 @@ void write_sigio_workaround(void) ...@@ -379,6 +407,7 @@ void write_sigio_workaround(void)
out_close1: out_close1:
close(write_sigio_fds[0]); close(write_sigio_fds[0]);
close(write_sigio_fds[1]); close(write_sigio_fds[1]);
sigio_unlock();
} }
int read_sigio_fd(int fd) int read_sigio_fd(int fd)
......
...@@ -19,8 +19,6 @@ ...@@ -19,8 +19,6 @@
#include "sysdep/sigcontext.h" #include "sysdep/sigcontext.h"
#include "sigcontext.h" #include "sigcontext.h"
extern int kern_timer_on;
void set_sigstack(void *sig_stack, int size) void set_sigstack(void *sig_stack, int size)
{ {
stack_t stack; stack_t stack;
...@@ -65,12 +63,8 @@ static void change_signals(int type) ...@@ -65,12 +63,8 @@ static void change_signals(int type)
sigset_t mask; sigset_t mask;
sigemptyset(&mask); sigemptyset(&mask);
if(type == SIG_BLOCK) kern_timer_on = 0; sigaddset(&mask, SIGVTALRM);
else { sigaddset(&mask, SIGALRM);
kern_timer_on = 1;
sigaddset(&mask, SIGVTALRM);
sigaddset(&mask, SIGALRM);
}
sigaddset(&mask, SIGIO); sigaddset(&mask, SIGIO);
sigaddset(&mask, SIGPROF); sigaddset(&mask, SIGPROF);
if(sigprocmask(type, &mask, NULL) < 0) if(sigprocmask(type, &mask, NULL) < 0)
...@@ -97,7 +91,6 @@ static int disable_mask(sigset_t *mask) ...@@ -97,7 +91,6 @@ static int disable_mask(sigset_t *mask)
sigs = sigismember(mask, SIGIO) ? 1 << SIGIO_BIT : 0; sigs = sigismember(mask, SIGIO) ? 1 << SIGIO_BIT : 0;
sigs |= sigismember(mask, SIGVTALRM) ? 1 << SIGVTALRM_BIT : 0; sigs |= sigismember(mask, SIGVTALRM) ? 1 << SIGVTALRM_BIT : 0;
sigs |= sigismember(mask, SIGALRM) ? 1 << SIGVTALRM_BIT : 0; sigs |= sigismember(mask, SIGALRM) ? 1 << SIGVTALRM_BIT : 0;
if(!kern_timer_on) sigs |= 1 << SIGVTALRM_BIT;
return(sigs); return(sigs);
} }
...@@ -116,21 +109,27 @@ int set_signals(int disable) ...@@ -116,21 +109,27 @@ int set_signals(int disable)
int ret; int ret;
sigemptyset(&mask); sigemptyset(&mask);
if(!(disable & (1 << SIGIO_BIT))) sigaddset(&mask, SIGIO); if(!(disable & (1 << SIGIO_BIT)))
sigaddset(&mask, SIGIO);
if(!(disable & (1 << SIGVTALRM_BIT))){ if(!(disable & (1 << SIGVTALRM_BIT))){
kern_timer_on = 1;
sigaddset(&mask, SIGVTALRM); sigaddset(&mask, SIGVTALRM);
sigaddset(&mask, SIGALRM); sigaddset(&mask, SIGALRM);
} }
if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0) if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
panic("Failed to enable signals"); panic("Failed to enable signals");
ret = disable_mask(&mask); ret = disable_mask(&mask);
sigemptyset(&mask); sigemptyset(&mask);
if(disable & (1 << SIGIO_BIT)) sigaddset(&mask, SIGIO); if(disable & (1 << SIGIO_BIT))
if(disable & (1 << SIGVTALRM_BIT)) sigaddset(&mask, SIGIO);
kern_timer_on = 0; if(disable & (1 << SIGVTALRM_BIT)){
sigaddset(&mask, SIGVTALRM);
sigaddset(&mask, SIGALRM);
}
if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0) if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0)
panic("Failed to block signals"); panic("Failed to block signals");
return(ret); return(ret);
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include "linux/config.h" #include "linux/config.h"
/* CPU online map */ /* CPU online map, set by smp_boot_cpus */
unsigned long cpu_online_map = 1; unsigned long cpu_online_map = 1;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
...@@ -21,25 +21,32 @@ unsigned long cpu_online_map = 1; ...@@ -21,25 +21,32 @@ unsigned long cpu_online_map = 1;
#include "user_util.h" #include "user_util.h"
#include "kern_util.h" #include "kern_util.h"
#include "kern.h" #include "kern.h"
#include "irq_user.h"
#include "os.h" #include "os.h"
/* The 'big kernel lock' */ /* Per CPU bogomips and other parameters
spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED; * The only piece used here is the ipi pipe, which is set before SMP is
* started and never changed.
/* Per CPU bogomips and other parameters */ */
struct cpuinfo_um cpu_data[NR_CPUS]; struct cpuinfo_um cpu_data[NR_CPUS];
spinlock_t um_bh_lock = SPIN_LOCK_UNLOCKED; spinlock_t um_bh_lock = SPIN_LOCK_UNLOCKED;
atomic_t global_bh_count; atomic_t global_bh_count;
/* Not used by UML */
unsigned char global_irq_holder = NO_PROC_ID; unsigned char global_irq_holder = NO_PROC_ID;
unsigned volatile long global_irq_lock; unsigned volatile long global_irq_lock;
/* Set when the idlers are all forked */ /* Set when the idlers are all forked */
int smp_threads_ready = 0; int smp_threads_ready = 0;
/* A statistic, can be a little off */
int num_reschedules_sent = 0; int num_reschedules_sent = 0;
/* Small, random number, never changed */
unsigned long cache_decay_ticks = 5;
void smp_send_reschedule(int cpu) void smp_send_reschedule(int cpu)
{ {
write(cpu_data[cpu].ipi_pipe[1], "R", 1); write(cpu_data[cpu].ipi_pipe[1], "R", 1);
...@@ -83,30 +90,24 @@ void synchronize_bh(void) ...@@ -83,30 +90,24 @@ void synchronize_bh(void)
void smp_send_stop(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; static volatile unsigned long smp_callin_map = 0;
void smp_commence(void) static int idle_proc(void *cpup)
{ {
printk("All CPUs are go!\n"); int cpu = (int) cpup, err;
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);
cpu = current->processor;
err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1); err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1);
if(err) if(err)
panic("CPU#%d failed to create IPI pipe, errno = %d", cpu, panic("CPU#%d failed to create IPI pipe, errno = %d", cpu,
...@@ -115,46 +116,41 @@ static int idle_proc(void *unused) ...@@ -115,46 +116,41 @@ static int idle_proc(void *unused)
activate_ipi(cpu_data[cpu].ipi_pipe[0], current->thread.extern_pid); activate_ipi(cpu_data[cpu].ipi_pipe[0], current->thread.extern_pid);
wmb(); wmb();
if (test_and_set_bit(current->processor, &smp_callin_map)) { if (test_and_set_bit(cpu, &smp_callin_map)) {
printk("huh, CPU#%d already present??\n", current->processor); printk("huh, CPU#%d already present??\n", cpu);
BUG(); BUG();
} }
while (!atomic_read(&smp_commenced)) while (!test_bit(cpu, &smp_commenced_mask))
cpu_relax(); cpu_relax();
init_idle(); set_bit(cpu, &cpu_online_map);
default_idle(); default_idle();
return(0); return(0);
} }
int inited_cpus = 1; static struct task_struct *idle_thread(int cpu)
static int idle_thread(int (*fn)(void *), int cpu)
{ {
struct task_struct *p; struct task_struct *new_task;
int pid;
unsigned char c; unsigned char c;
current->thread.request.u.thread.proc = fn; current->thread.request.u.thread.proc = idle_proc;
current->thread.request.u.thread.arg = NULL; current->thread.request.u.thread.arg = (void *) cpu;
p = do_fork(CLONE_VM | CLONE_PID, 0, NULL, 0); new_task = do_fork(CLONE_VM | CLONE_IDLETASK, 0, NULL, 0, NULL);
if(IS_ERR(p)) panic("do_fork failed in idle_thread"); if(IS_ERR(new_task)) panic("do_fork failed in idle_thread");
cpu_tasks[cpu].pid = p->thread.extern_pid; cpu_tasks[cpu] = ((struct cpu_task)
cpu_tasks[cpu].task = p; { .pid = new_task->thread.extern_pid,
inited_cpus++; .task = new_task } );
init_tasks[cpu] = p; write(new_task->thread.switch_pipe[1], &c, sizeof(c));
p->processor = cpu; return(new_task);
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);
} }
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, &cpu_online_map);
set_bit(0, &smp_callin_map); set_bit(0, &smp_callin_map);
...@@ -164,46 +160,32 @@ void smp_boot_cpus(void) ...@@ -164,46 +160,32 @@ void smp_boot_cpus(void)
activate_ipi(cpu_data[0].ipi_pipe[0], current->thread.extern_pid); activate_ipi(cpu_data[0].ipi_pipe[0], current->thread.extern_pid);
if(ncpus < 1){ for(cpu = 1; cpu < ncpus; cpu++){
printk(KERN_INFO "ncpus set to 1\n"); printk("Booting processor %d...\n", cpu);
ncpus = 1;
} idle = idle_thread(cpu);
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);
pid = idle_thread(idle_proc, i); init_idle(idle, cpu);
printk(KERN_INFO "\t#%d - idle thread pid = %d.. ", unhash_process(idle);
i, pid);
waittime = 200000000; waittime = 200000000;
while (waittime-- && !test_bit(i, &smp_callin_map)) while (waittime-- && !test_bit(cpu, &smp_callin_map))
cpu_relax(); cpu_relax();
if (test_bit(i, &smp_callin_map)) if (test_bit(cpu, &smp_callin_map))
printk("online\n"); printk("done\n");
else { else printk("failed\n");
printk("failed\n");
clear_bit(i, &cpu_online_map);
}
}
} }
} }
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) int setup_profiling_timer(unsigned int multiplier)
{ {
printk(KERN_INFO "setup_profiling_timer\n"); printk(KERN_INFO "setup_profiling_timer\n");
...@@ -225,7 +207,13 @@ void IPI_handler(int cpu) ...@@ -225,7 +207,13 @@ void IPI_handler(int cpu)
break; break;
case 'R': case 'R':
current->need_resched = 1; set_tsk_need_resched(current);
break;
case 'S':
printk("CPU#%d stopping\n", cpu);
while(1)
pause();
break; break;
default: default:
...@@ -269,7 +257,8 @@ int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic, ...@@ -269,7 +257,8 @@ int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic,
info = _info; info = _info;
for (i=0;i<NR_CPUS;i++) 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); write(cpu_data[i].ipi_pipe[1], "C", 1);
while (atomic_read(&scf_started) != cpus) while (atomic_read(&scf_started) != cpus)
......
...@@ -384,6 +384,7 @@ static int check_bogosity(struct pt_regs *regs) ...@@ -384,6 +384,7 @@ static int check_bogosity(struct pt_regs *regs)
return(0); return(0);
} }
/* Unlocked, I don't care if this is a bit off */
int nsyscalls = 0; int nsyscalls = 0;
extern syscall_handler_t *sys_call_table[]; extern syscall_handler_t *sys_call_table[];
...@@ -417,14 +418,18 @@ long execute_syscall(void *r) ...@@ -417,14 +418,18 @@ long execute_syscall(void *r)
spinlock_t syscall_lock = SPIN_LOCK_UNLOCKED; spinlock_t syscall_lock = SPIN_LOCK_UNLOCKED;
void lock_syscall(void) static int syscall_index = 0;
{
spin_lock(&syscall_lock);
}
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); spin_unlock(&syscall_lock);
return(ret);
} }
/* /*
......
...@@ -34,21 +34,14 @@ struct { ...@@ -34,21 +34,14 @@ struct {
struct timeval end; struct timeval end;
} syscall_record[1024]; } syscall_record[1024];
int syscall_index = 0;
extern int kern_timer_on;
void syscall_handler(int sig, struct uml_pt_regs *regs) void syscall_handler(int sig, struct uml_pt_regs *regs)
{ {
void *sc; void *sc;
long result; long result;
int index, syscall; int index, max, syscall;
lock_syscall(); max = sizeof(syscall_record)/sizeof(syscall_record[0]);
if(syscall_index == 1024) syscall_index = 0; index = next_syscall_index(max);
index = syscall_index;
syscall_index++;
unlock_syscall();
syscall = regs->syscall; syscall = regs->syscall;
sc = regs->sc; sc = regs->sc;
......
...@@ -14,33 +14,15 @@ ...@@ -14,33 +14,15 @@
#include "user.h" #include "user.h"
#include "process.h" #include "process.h"
#include "signal_user.h" #include "signal_user.h"
#include "time_user.h"
extern struct timeval xtime; extern struct timeval xtime;
void timer_handler(int sig, struct uml_pt_regs *regs)
{
timer_irq(regs);
}
void timer(void) void timer(void)
{ {
gettimeofday(&xtime, NULL); 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) static void set_interval(int timer_type)
{ {
struct itimerval interval; struct itimerval interval;
...@@ -53,6 +35,15 @@ static void set_interval(int timer_type) ...@@ -53,6 +35,15 @@ static void set_interval(int timer_type)
panic("setitimer failed - errno = %d\n", errno); 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) void switch_timers(int to_real)
{ {
struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
...@@ -79,8 +70,9 @@ void idle_timer(void) ...@@ -79,8 +70,9 @@ void idle_timer(void)
{ {
if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR) if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
panic("Couldn't unset SIGVTALRM handler"); panic("Couldn't unset SIGVTALRM handler");
set_handler(SIGALRM, (__sighandler_t) alarm_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); set_interval(ITIMER_REAL);
} }
...@@ -98,28 +90,24 @@ void time_init(void) ...@@ -98,28 +90,24 @@ void time_init(void)
set_interval(ITIMER_VIRTUAL); 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 }; struct timeval local_offset = { 0, 0 };
void do_gettimeofday(struct timeval *tv) void do_gettimeofday(struct timeval *tv)
{ {
time_lock();
gettimeofday(tv, NULL); gettimeofday(tv, NULL);
timeradd(tv, &local_offset, tv); timeradd(tv, &local_offset, tv);
time_unlock();
} }
void do_settimeofday(struct timeval *tv) void do_settimeofday(struct timeval *tv)
{ {
struct timeval now; struct timeval now;
time_lock();
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
timersub(tv, &now, &local_offset); timersub(tv, &now, &local_offset);
time_unlock();
} }
void idle_sleep(int secs) void idle_sleep(int secs)
......
...@@ -27,21 +27,21 @@ int hz(void) ...@@ -27,21 +27,21 @@ int hz(void)
return(HZ); return(HZ);
} }
/* Changed at early boot */
int timer_irq_inited = 0; int timer_irq_inited = 0;
/* kern_timer_on and missed_ticks are modified after kernel memory has been /* missed_ticks will be modified after kernel memory has been
* write-protected, so this puts it in a section which will be left * write-protected, so this puts it in a section which will be left
* write-enabled. * write-enabled.
*/ */
int __attribute__ ((__section__ (".unprotected"))) kern_timer_on = 0; int __attribute__ ((__section__ (".unprotected"))) missed_ticks[NR_CPUS];
int __attribute__ ((__section__ (".unprotected"))) missed_ticks = 0;
void timer_irq(struct uml_pt_regs *regs) 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; if(!timer_irq_inited) return;
missed_ticks = 0; missed_ticks[cpu] = 0;
while(ticks--) do_IRQ(TIMER_IRQ, regs); while(ticks--) do_IRQ(TIMER_IRQ, regs);
} }
...@@ -116,6 +116,27 @@ void __const_udelay(um_udelay_t usecs) ...@@ -116,6 +116,27 @@ void __const_udelay(um_udelay_t usecs)
for(i=0;i<n;i++) ; 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 __init timer_init(void)
{ {
int err; int err;
......
...@@ -171,14 +171,18 @@ void trap_init(void) ...@@ -171,14 +171,18 @@ void trap_init(void)
spinlock_t trap_lock = SPIN_LOCK_UNLOCKED; spinlock_t trap_lock = SPIN_LOCK_UNLOCKED;
void lock_trap(void) static int trap_index = 0;
{
spin_lock(&trap_lock);
}
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); spin_unlock(&trap_lock);
return(ret);
} }
extern int debugger_pid; extern int debugger_pid;
...@@ -209,6 +213,7 @@ static struct chan_opts opts = { ...@@ -209,6 +213,7 @@ static struct chan_opts opts = {
tramp_stack : 0, tramp_stack : 0,
}; };
/* Accessed by the tracing thread, which automatically serializes access */
static void *xterm_data; static void *xterm_data;
static int xterm_fd; static int xterm_fd;
......
...@@ -70,10 +70,10 @@ void kill_child_dead(int pid) ...@@ -70,10 +70,10 @@ void kill_child_dead(int pid)
while(waitpid(pid, NULL, 0) > 0) kill(pid, SIGCONT); while(waitpid(pid, NULL, 0) > 0) kill(pid, SIGCONT);
} }
/* Changed early in boot, and then only read */
int debug = 0; int debug = 0;
int debug_stop = 1; int debug_stop = 1;
int debug_parent = 0; int debug_parent = 0;
int honeypot = 0; int honeypot = 0;
static int signal_tramp(void *arg) static int signal_tramp(void *arg)
...@@ -90,7 +90,6 @@ static int signal_tramp(void *arg) ...@@ -90,7 +90,6 @@ static int signal_tramp(void *arg)
signal(SIGUSR1, SIG_IGN); signal(SIGUSR1, SIG_IGN);
change_sig(SIGCHLD, 0); change_sig(SIGCHLD, 0);
signal(SIGSEGV, (__sighandler_t) sig_handler); signal(SIGSEGV, (__sighandler_t) sig_handler);
set_timers(0);
set_cmdline("(idle thread)"); set_cmdline("(idle thread)");
set_init_pid(os_getpid()); set_init_pid(os_getpid());
proc = arg; proc = arg;
...@@ -142,33 +141,20 @@ static void sleeping_process_signal(int pid, int sig) ...@@ -142,33 +141,20 @@ static void sleeping_process_signal(int pid, int sig)
} }
} }
#ifdef CONFIG_SMP /* Accessed only by the tracing thread */
#error need to make these arrays
#endif
int debugger_pid = -1; int debugger_pid = -1;
int debugger_parent = -1; int debugger_parent = -1;
int debugger_fd = -1; int debugger_fd = -1;
int gdb_pid = -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 { struct {
int pid; int pid;
int signal; int signal;
unsigned long addr; unsigned long addr;
struct timeval time; struct timeval time;
} signal_record[1024]; } signal_record[1024][32];
int signal_index = 0; int signal_index[32];
int nsignals = 0; int nsignals = 0;
int debug_trace = 0; int debug_trace = 0;
extern int io_nsignals, io_count, intr_count; extern int io_nsignals, io_count, intr_count;
...@@ -259,36 +245,36 @@ int signals(int (*init_proc)(void *), void *sp) ...@@ -259,36 +245,36 @@ int signals(int (*init_proc)(void *), void *sp)
if(WIFEXITED(status)) ; if(WIFEXITED(status)) ;
#ifdef notdef #ifdef notdef
{ {
printk("Child %d exited with status %d\n", pid, printf("Child %d exited with status %d\n", pid,
WEXITSTATUS(status)); WEXITSTATUS(status));
} }
#endif #endif
else if(WIFSIGNALED(status)){ else if(WIFSIGNALED(status)){
sig = WTERMSIG(status); sig = WTERMSIG(status);
if(sig != 9){ if(sig != 9){
printk("Child %d exited with signal %d\n", pid, printf("Child %d exited with signal %d\n", pid,
sig); sig);
} }
} }
else if(WIFSTOPPED(status)){ else if(WIFSTOPPED(status)){
proc_id = pid_to_processor_id(pid);
sig = WSTOPSIG(status); sig = WSTOPSIG(status);
if(signal_index == 1024){ if(signal_index[proc_id] == 1024){
signal_index = 0; signal_index[proc_id] = 0;
last_index = 1023; last_index = 1023;
} }
else last_index = signal_index - 1; else last_index = signal_index[proc_id] - 1;
if(((sig == SIGPROF) || (sig == SIGVTALRM) || if(((sig == SIGPROF) || (sig == SIGVTALRM) ||
(sig == SIGALRM)) && (sig == SIGALRM)) &&
(signal_record[last_index].signal == sig) && (signal_record[proc_id][last_index].signal == sig)&&
(signal_record[last_index].pid == pid)) (signal_record[proc_id][last_index].pid == pid))
signal_index = last_index; signal_index[proc_id] = last_index;
signal_record[signal_index].pid = pid; signal_record[proc_id][signal_index[proc_id]].pid = pid;
gettimeofday(&signal_record[signal_index].time, NULL); gettimeofday(&signal_record[proc_id][signal_index[proc_id]].time, NULL);
eip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0); eip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0);
signal_record[signal_index].addr = eip; signal_record[proc_id][signal_index[proc_id]].addr = eip;
signal_record[signal_index++].signal = sig; signal_record[proc_id][signal_index[proc_id]++].signal = sig;
proc_id = pid_to_processor_id(pid);
if(proc_id == -1){ if(proc_id == -1){
sleeping_process_signal(pid, sig); sleeping_process_signal(pid, sig);
continue; continue;
...@@ -413,22 +399,30 @@ __uml_setup("honeypot", uml_honeypot_setup, ...@@ -413,22 +399,30 @@ __uml_setup("honeypot", uml_honeypot_setup,
" UML. This implies 'jail'.\n\n" " UML. This implies 'jail'.\n\n"
); );
/* Unlocked - don't care if this is a bit off */
int nsegfaults = 0; 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) void segv_handler(int sig, struct uml_pt_regs *regs)
{ {
struct sigcontext *context = regs->sc; struct sigcontext *context = regs->sc;
int index; int index, max;
if(regs->is_user && !SEGV_IS_FIXABLE(context)){ if(regs->is_user && !SEGV_IS_FIXABLE(context)){
bad_segv(SC_FAULT_ADDR(context), SC_IP(context), bad_segv(SC_FAULT_ADDR(context), SC_IP(context),
SC_FAULT_WRITE(context)); SC_FAULT_WRITE(context));
return; return;
} }
lock_trap(); max = sizeof(segfault_record)/sizeof(segfault_record[0]);
index = segfault_index++; index = next_trap_index(max);
if(segfault_index == 1024) segfault_index = 0;
unlock_trap();
nsegfaults++; nsegfaults++;
segfault_record[index].address = SC_FAULT_ADDR(context); segfault_record[index].address = SC_FAULT_ADDR(context);
segfault_record[index].pid = os_getpid(); segfault_record[index].pid = os_getpid();
...@@ -439,8 +433,6 @@ void segv_handler(int sig, struct uml_pt_regs *regs) ...@@ -439,8 +433,6 @@ void segv_handler(int sig, struct uml_pt_regs *regs)
regs->is_user, context); regs->is_user, context);
} }
extern int kern_timer_on;
struct signal_info { struct signal_info {
void (*handler)(int, struct uml_pt_regs *); void (*handler)(int, struct uml_pt_regs *);
int is_irq; int is_irq;
...@@ -471,7 +463,7 @@ void sig_handler_common(int sig, struct sigcontext *sc) ...@@ -471,7 +463,7 @@ void sig_handler_common(int sig, struct sigcontext *sc)
{ {
struct uml_pt_regs save_regs, *r; struct uml_pt_regs save_regs, *r;
struct signal_info *info; struct signal_info *info;
int save_errno = errno, save_timer = kern_timer_on, is_user; int save_errno = errno, is_user;
unprotect_kernel_mem(); unprotect_kernel_mem();
...@@ -488,7 +480,6 @@ void sig_handler_common(int sig, struct sigcontext *sc) ...@@ -488,7 +480,6 @@ void sig_handler_common(int sig, struct sigcontext *sc)
(*info->handler)(sig, r); (*info->handler)(sig, r);
kern_timer_on = save_timer;
if(is_user){ if(is_user){
interrupt_end(); interrupt_end();
block_signals(); block_signals();
...@@ -505,19 +496,15 @@ void sig_handler(int sig, struct sigcontext sc) ...@@ -505,19 +496,15 @@ void sig_handler(int sig, struct sigcontext sc)
sig_handler_common(sig, &sc); sig_handler_common(sig, &sc);
} }
extern int timer_irq_inited, missed_ticks; extern int timer_irq_inited, missed_ticks[];
extern int jail_timer_off;
void alarm_handler(int sig, struct sigcontext sc) void alarm_handler(int sig, struct sigcontext sc)
{ {
int user; int user;
if(!timer_irq_inited) return; if(!timer_irq_inited) return;
missed_ticks++; missed_ticks[cpu()]++;
user = user_context(SC_SP(&sc)); user = user_context(SC_SP(&sc));
if(!user && !kern_timer_on) return;
if(!user && jail_timer_off) return;
if(sig == SIGALRM) if(sig == SIGALRM)
switch_timers(0); switch_timers(0);
......
...@@ -17,8 +17,8 @@ ...@@ -17,8 +17,8 @@
#define TTY_LOG_DIR "./" #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; static int tty_log_fd = -1;
#define TTY_LOG_OPEN 1 #define TTY_LOG_OPEN 1
......
...@@ -37,6 +37,11 @@ ...@@ -37,6 +37,11 @@
#define DEFAULT_COMMAND_LINE "root=6200" #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) unsigned long thread_saved_pc(struct task_struct *task)
{ {
return(os_process_pc(task->thread.extern_pid)); return(os_process_pc(task->thread.extern_pid));
...@@ -119,6 +124,7 @@ static int start_kernel_proc(void *unused) ...@@ -119,6 +124,7 @@ static int start_kernel_proc(void *unused)
#define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000) #define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000)
#define START (TOP - SIZE) #define START (TOP - SIZE)
/* Set in main */
unsigned long host_task_size; unsigned long host_task_size;
unsigned long task_size; unsigned long task_size;
...@@ -129,17 +135,21 @@ void set_task_sizes(int arg) ...@@ -129,17 +135,21 @@ void set_task_sizes(int arg)
task_size = START; task_size = START;
} }
/* Set in early boot */
unsigned long uml_physmem; unsigned long uml_physmem;
unsigned long uml_reserved; unsigned long uml_reserved;
unsigned long start_vm; unsigned long start_vm;
unsigned long end_vm; unsigned long end_vm;
int ncpus = 1; 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_begin = NULL;
static char *argv1_end = NULL; static char *argv1_end = NULL;
/* Set in early boot */
static int have_root __initdata = 0; static int have_root __initdata = 0;
long physmem_size = 32 * 1024 * 1024; long physmem_size = 32 * 1024 * 1024;
...@@ -258,8 +268,9 @@ static void __init uml_postsetup(void) ...@@ -258,8 +268,9 @@ static void __init uml_postsetup(void)
} }
extern int debug_trace; extern int debug_trace;
unsigned long brk_start;
/* Set during early boot */
unsigned long brk_start;
static struct vm_reserved kernel_vm_reserved; static struct vm_reserved kernel_vm_reserved;
#define MIN_VMALLOC (32 * 1024 * 1024) #define MIN_VMALLOC (32 * 1024 * 1024)
...@@ -365,18 +376,6 @@ void __init check_bugs(void) ...@@ -365,18 +376,6 @@ void __init check_bugs(void)
check_sigio(); 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. * Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically * Emacs will notice this stuff at the end of the file and automatically
......
...@@ -21,9 +21,13 @@ ...@@ -21,9 +21,13 @@
#define UMID_LEN 64 #define UMID_LEN 64
#define UML_DIR "~/.uml/" #define UML_DIR "~/.uml/"
/* Changed by set_umid and make_umid, which are run early in boot */
static char umid[UMID_LEN] = { 0 }; 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; static char *uml_dir = UML_DIR;
/* Changed by set_umid */
static int umid_is_random = 1; static int umid_is_random = 1;
static int umid_inited = 0; static int umid_inited = 0;
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#define COMMAND_LINE_SIZE _POSIX_ARG_MAX #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 saved_command_line[COMMAND_LINE_SIZE] = { 0 };
char command_line[COMMAND_LINE_SIZE] = { 0 }; char command_line[COMMAND_LINE_SIZE] = { 0 };
......
...@@ -18,15 +18,22 @@ ...@@ -18,15 +18,22 @@
#include "user.h" #include "user.h"
#include "init.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; unsigned long stacksizelim;
/* Set in main */
char *linux_prog; char *linux_prog;
#define PGD_BOUND (4 * 1024 * 1024) #define PGD_BOUND (4 * 1024 * 1024)
#define STACKSIZE (8 * 1024 * 1024) #define STACKSIZE (8 * 1024 * 1024)
#define THREAD_NAME_LEN (256) #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) static void set_stklim(void)
{ {
...@@ -129,7 +136,8 @@ int main(int argc, char **argv, char **envp) ...@@ -129,7 +136,8 @@ int main(int argc, char **argv, char **envp)
return(uml_exitcode); return(uml_exitcode);
} }
int allocating_monbuf = 0; /* Changed in __wrap___monstartup and __wrap_malloc very early */
static int allocating_monbuf = 0;
#ifdef PROFILING #ifdef PROFILING
extern void __real___monstartup (unsigned long, unsigned long); extern void __real___monstartup (unsigned long, unsigned long);
...@@ -146,6 +154,7 @@ void __wrap___monstartup (unsigned long lowpc, unsigned long highpc) ...@@ -146,6 +154,7 @@ void __wrap___monstartup (unsigned long lowpc, unsigned long highpc)
extern void *__real_malloc(int); extern void *__real_malloc(int);
extern unsigned long host_task_size; extern unsigned long host_task_size;
/* Set in __wrap_malloc early */
static void *gmon_buf = NULL; static void *gmon_buf = NULL;
void *__wrap_malloc(int size) void *__wrap_malloc(int size)
......
...@@ -122,6 +122,7 @@ int debugger_syscall(debugger_state *debugger, pid_t child) ...@@ -122,6 +122,7 @@ int debugger_syscall(debugger_state *debugger, pid_t child)
return(0); return(0);
} }
/* Used by the tracing thread */
static debugger_state parent; static debugger_state parent;
static int parent_syscall(debugger_state *debugger, int pid); static int parent_syscall(debugger_state *debugger, int pid);
...@@ -174,10 +175,7 @@ void debugger_cancelled_return(debugger_state *debugger, int result) ...@@ -174,10 +175,7 @@ void debugger_cancelled_return(debugger_state *debugger, int result)
syscall_continue(debugger->pid); syscall_continue(debugger->pid);
} }
#ifdef CONFIG_SMP /* Used by the tracing thread */
#error need to make these arrays
#endif
static debugger_state debugger; static debugger_state debugger;
static debugee_state debugee; static debugee_state debugee;
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#define MAXTOKEN 64 #define MAXTOKEN 64
/* Set during early boot */
int cpu_has_cmov = 1; int cpu_has_cmov = 1;
int cpu_has_xmm = 0; int cpu_has_xmm = 0;
......
...@@ -59,6 +59,7 @@ static void read_debugregs(int pid, unsigned long *regs) ...@@ -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 unsigned long kernel_debugregs[8] = { [ 0 ... 7 ] = 0 };
static int debugregs_seq = 0; static int debugregs_seq = 0;
......
...@@ -2,9 +2,6 @@ ...@@ -2,9 +2,6 @@
#include "linux/stddef.h" // for NULL #include "linux/stddef.h" // for NULL
#include "linux/elf.h" // for AT_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 /* The following function nicked from arch/ppc/kernel/process.c and
* adapted slightly */ * adapted slightly */
/* /*
......
...@@ -67,6 +67,9 @@ SECTIONS ...@@ -67,6 +67,9 @@ SECTIONS
__setup_start = .; __setup_start = .;
.setup.init : { *(.setup.init) } .setup.init : { *(.setup.init) }
__setup_end = .; __setup_end = .;
__per_cpu_start = . ;
.data.percpu : { *(.data.percpu) }
__per_cpu_end = . ;
__initcall_start = .; __initcall_start = .;
.initcall.init : { .initcall.init : {
*(.initcall1.init) *(.initcall1.init)
......
#ifndef __UM_CACHE_H #ifndef __UM_CACHE_H
#define __UM_CACHE_H #define __UM_CACHE_H
/* These are x86 numbers */
#define L1_CACHE_SHIFT 5 #define L1_CACHE_SHIFT 5
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
#define L1_CACHE_SHIFT_MAX 7 /* largest L1 which this arch supports */
#endif #endif
...@@ -6,15 +6,30 @@ extern unsigned long cpu_online_map; ...@@ -6,15 +6,30 @@ extern unsigned long cpu_online_map;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
#include "linux/config.h" #include "linux/config.h"
#include "linux/bitops.h"
#include "asm/current.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_logical_map(n) (n)
#define cpu_number_map(n) (n) #define cpu_number_map(n) (n)
#define PROC_CHANGE_PENALTY 15 /* Pick a number, any number */ #define PROC_CHANGE_PENALTY 15 /* Pick a number, any number */
extern int hard_smp_processor_id(void); extern int hard_smp_processor_id(void);
#define NO_PROC_ID -1 #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
#endif #endif
...@@ -64,10 +64,14 @@ static inline struct thread_info *current_thread_info(void) ...@@ -64,10 +64,14 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */ #define TIF_SYSCALL_TRACE 0 /* syscall trace active */
#define TIF_SIGPENDING 1 /* signal pending */ #define TIF_SIGPENDING 1 /* signal pending */
#define TIF_NEED_RESCHED 2 /* rescheduling necessary */ #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_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment