Merge branch 'linus' into timers/nohz

This commit is contained in:
Ingo Molnar
2008-07-18 19:53:16 +02:00
4958 changed files with 298069 additions and 304351 deletions

View File

@@ -20,9 +20,6 @@ obj-$(CONFIG_CSRC_R4K) += csrc-r4k.o
obj-$(CONFIG_CSRC_SB1250) += csrc-sb1250.o
obj-$(CONFIG_SYNC_R4K) += sync-r4k.o
binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \
irix5sys.o sysirix.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_MODULES) += mips_ksyms.o module.o
@@ -30,7 +27,6 @@ obj-$(CONFIG_CPU_LOONGSON2) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_MIPS32) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_MIPS64) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o
obj-$(CONFIG_CPU_R4000) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R4300) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R4X00) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R5000) += r4k_fpu.o r4k_switch.o
@@ -64,14 +60,13 @@ obj-$(CONFIG_I8259) += i8259.o
obj-$(CONFIG_IRQ_CPU) += irq_cpu.o
obj-$(CONFIG_IRQ_CPU_RM7K) += irq-rm7000.o
obj-$(CONFIG_IRQ_CPU_RM9K) += irq-rm9000.o
obj-$(CONFIG_MIPS_BOARDS_GEN) += irq-msc01.o
obj-$(CONFIG_MIPS_MSC) += irq-msc01.o
obj-$(CONFIG_IRQ_TXX9) += irq_txx9.o
obj-$(CONFIG_IRQ_GT641XX) += irq-gt641xx.o
obj-$(CONFIG_IRQ_GIC) += irq-gic.o
obj-$(CONFIG_32BIT) += scall32-o32.o
obj-$(CONFIG_64BIT) += scall64-64.o
obj-$(CONFIG_BINFMT_IRIX) += binfmt_irix.o
obj-$(CONFIG_MIPS32_COMPAT) += linux32.o ptrace32.o signal32.o
obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o
obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o

View File

@@ -161,6 +161,9 @@ void __init txx9_tmr_init(unsigned long baseaddr)
struct txx9_tmr_reg __iomem *tmrptr;
tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
/* Start once to make CounterResetEnable effective */
__raw_writel(TXx9_TMTCR_CRE | TXx9_TMTCR_TCE, &tmrptr->tcr);
/* Stop and reset the counter */
__raw_writel(TXx9_TMTCR_CRE, &tmrptr->tcr);
__raw_writel(0, &tmrptr->tisr);
__raw_writel(0xffffffff, &tmrptr->cpra);

View File

@@ -10,6 +10,8 @@
#include <linux/console.h>
#include <linux/init.h>
#include <asm/setup.h>
extern void prom_putchar(char);
static void __init

View File

@@ -47,23 +47,25 @@ static void txx9_gpio_set(struct gpio_chip *chip, unsigned int offset,
static int txx9_gpio_dir_in(struct gpio_chip *chip, unsigned int offset)
{
spin_lock_irq(&txx9_gpio_lock);
unsigned long flags;
spin_lock_irqsave(&txx9_gpio_lock, flags);
__raw_writel(__raw_readl(&txx9_pioptr->dir) & ~(1 << offset),
&txx9_pioptr->dir);
mmiowb();
spin_unlock_irq(&txx9_gpio_lock);
spin_unlock_irqrestore(&txx9_gpio_lock, flags);
return 0;
}
static int txx9_gpio_dir_out(struct gpio_chip *chip, unsigned int offset,
int value)
{
spin_lock_irq(&txx9_gpio_lock);
unsigned long flags;
spin_lock_irqsave(&txx9_gpio_lock, flags);
txx9_gpio_set_raw(offset, value);
__raw_writel(__raw_readl(&txx9_pioptr->dir) | (1 << offset),
&txx9_pioptr->dir);
mmiowb();
spin_unlock_irq(&txx9_gpio_lock);
spin_unlock_irqrestore(&txx9_gpio_lock, flags);
return 0;
}

View File

@@ -80,7 +80,7 @@ static int pit_next_event(unsigned long delta, struct clock_event_device *evt)
* registered. This mechanism replaces the previous #ifdef LOCAL_APIC -
* !using_apic_timer decisions in do_timer_interrupt_hook()
*/
struct clock_event_device pit_clockevent = {
static struct clock_event_device pit_clockevent = {
.name = "pit",
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.set_mode = init_pit_timer,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,78 +0,0 @@
/*
* Support the inventory interface for IRIX binaries
* This is invoked before the mm layer is working, so we do not
* use the linked lists for the inventory yet.
*
* Miguel de Icaza, 1997.
*/
#include <linux/mm.h>
#include <asm/inventory.h>
#include <asm/uaccess.h>
#define MAX_INVENTORY 50
int inventory_items = 0;
static inventory_t inventory [MAX_INVENTORY];
void add_to_inventory(int class, int type, int controller, int unit, int state)
{
inventory_t *ni = &inventory [inventory_items];
if (inventory_items == MAX_INVENTORY)
return;
ni->inv_class = class;
ni->inv_type = type;
ni->inv_controller = controller;
ni->inv_unit = unit;
ni->inv_state = state;
ni->inv_next = ni;
inventory_items++;
}
int dump_inventory_to_user(void __user *userbuf, int size)
{
inventory_t *inv = &inventory [0];
inventory_t __user *user = userbuf;
int v;
if (!access_ok(VERIFY_WRITE, userbuf, size))
return -EFAULT;
for (v = 0; v < inventory_items; v++){
inv = &inventory [v];
if (copy_to_user (user, inv, sizeof (inventory_t)))
return -EFAULT;
user++;
}
return inventory_items * sizeof(inventory_t);
}
int __init init_inventory(void)
{
/*
* gross hack while we put the right bits all over the kernel
* most likely this will not let just anyone run the X server
* until we put the right values all over the place
*/
add_to_inventory(10, 3, 0, 0, 16400);
add_to_inventory(1, 1, 150, -1, 12);
add_to_inventory(1, 3, 0, 0, 8976);
add_to_inventory(1, 2, 0, 0, 8976);
add_to_inventory(4, 8, 0, 0, 2);
add_to_inventory(5, 5, 0, 0, 1);
add_to_inventory(3, 3, 0, 0, 32768);
add_to_inventory(3, 4, 0, 0, 32768);
add_to_inventory(3, 8, 0, 0, 524288);
add_to_inventory(3, 9, 0, 0, 64);
add_to_inventory(3, 1, 0, 0, 67108864);
add_to_inventory(12, 3, 0, 0, 16);
add_to_inventory(8, 7, 17, 0, 16777472);
add_to_inventory(8, 0, 0, 0, 1);
add_to_inventory(2, 1, 0, 13, 2);
add_to_inventory(2, 2, 0, 2, 0);
add_to_inventory(2, 2, 0, 1, 0);
add_to_inventory(7, 14, 0, 0, 6);
return 0;
}

View File

@@ -1,213 +0,0 @@
/*
* irixioctl.c: A fucking mess...
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
*/
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/sockios.h>
#include <linux/syscalls.h>
#include <linux/tty.h>
#include <linux/file.h>
#include <linux/rcupdate.h>
#include <asm/uaccess.h>
#include <asm/ioctl.h>
#include <asm/ioctls.h>
#undef DEBUG_IOCTLS
#undef DEBUG_MISSING_IOCTL
struct irix_termios {
tcflag_t c_iflag, c_oflag, c_cflag, c_lflag;
cc_t c_cc[NCCS];
};
asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg)
{
struct tty_struct *tp, *rtp;
mm_segment_t old_fs;
int i, error = 0;
#ifdef DEBUG_IOCTLS
printk("[%s:%d] irix_ioctl(%d, ", current->comm, current->pid, fd);
#endif
switch(cmd) {
case 0x00005401:
#ifdef DEBUG_IOCTLS
printk("TCGETA, %08lx) ", arg);
#endif
error = sys_ioctl(fd, TCGETA, arg);
break;
case 0x0000540d: {
struct termios kt;
struct irix_termios __user *it =
(struct irix_termios __user *) arg;
#ifdef DEBUG_IOCTLS
printk("TCGETS, %08lx) ", arg);
#endif
if (!access_ok(VERIFY_WRITE, it, sizeof(*it))) {
error = -EFAULT;
break;
}
old_fs = get_fs(); set_fs(get_ds());
error = sys_ioctl(fd, TCGETS, (unsigned long) &kt);
set_fs(old_fs);
if (error)
break;
error = __put_user(kt.c_iflag, &it->c_iflag);
error |= __put_user(kt.c_oflag, &it->c_oflag);
error |= __put_user(kt.c_cflag, &it->c_cflag);
error |= __put_user(kt.c_lflag, &it->c_lflag);
for (i = 0; i < NCCS; i++)
error |= __put_user(kt.c_cc[i], &it->c_cc[i]);
break;
}
case 0x0000540e: {
struct termios kt;
struct irix_termios *it = (struct irix_termios *) arg;
#ifdef DEBUG_IOCTLS
printk("TCSETS, %08lx) ", arg);
#endif
if (!access_ok(VERIFY_READ, it, sizeof(*it))) {
error = -EFAULT;
break;
}
old_fs = get_fs(); set_fs(get_ds());
error = sys_ioctl(fd, TCGETS, (unsigned long) &kt);
set_fs(old_fs);
if (error)
break;
error = __get_user(kt.c_iflag, &it->c_iflag);
error |= __get_user(kt.c_oflag, &it->c_oflag);
error |= __get_user(kt.c_cflag, &it->c_cflag);
error |= __get_user(kt.c_lflag, &it->c_lflag);
for (i = 0; i < NCCS; i++)
error |= __get_user(kt.c_cc[i], &it->c_cc[i]);
if (error)
break;
old_fs = get_fs(); set_fs(get_ds());
error = sys_ioctl(fd, TCSETS, (unsigned long) &kt);
set_fs(old_fs);
break;
}
case 0x0000540f:
#ifdef DEBUG_IOCTLS
printk("TCSETSW, %08lx) ", arg);
#endif
error = sys_ioctl(fd, TCSETSW, arg);
break;
case 0x00005471:
#ifdef DEBUG_IOCTLS
printk("TIOCNOTTY, %08lx) ", arg);
#endif
error = sys_ioctl(fd, TIOCNOTTY, arg);
break;
case 0x00007416: {
pid_t pid;
#ifdef DEBUG_IOCTLS
printk("TIOCGSID, %08lx) ", arg);
#endif
old_fs = get_fs(); set_fs(get_ds());
error = sys_ioctl(fd, TIOCGSID, (unsigned long)&pid);
set_fs(old_fs);
if (!error)
error = put_user(pid, (unsigned long __user *) arg);
break;
}
case 0x746e:
/* TIOCSTART, same effect as hitting ^Q */
#ifdef DEBUG_IOCTLS
printk("TIOCSTART, %08lx) ", arg);
#endif
error = sys_ioctl(fd, TCXONC, TCOON);
break;
case 0x20006968:
#ifdef DEBUG_IOCTLS
printk("SIOCGETLABEL, %08lx) ", arg);
#endif
error = -ENOPKG;
break;
case 0x40047477:
#ifdef DEBUG_IOCTLS
printk("TIOCGPGRP, %08lx) ", arg);
#endif
error = sys_ioctl(fd, TIOCGPGRP, arg);
#ifdef DEBUG_IOCTLS
printk("arg=%d ", *(int *)arg);
#endif
break;
case 0x40087468:
#ifdef DEBUG_IOCTLS
printk("TIOCGWINSZ, %08lx) ", arg);
#endif
error = sys_ioctl(fd, TIOCGWINSZ, arg);
break;
case 0x8004667e:
error = sys_ioctl(fd, FIONBIO, arg);
break;
case 0x80047476:
error = sys_ioctl(fd, TIOCSPGRP, arg);
break;
case 0x8020690c:
error = sys_ioctl(fd, SIOCSIFADDR, arg);
break;
case 0x80206910:
error = sys_ioctl(fd, SIOCSIFFLAGS, arg);
break;
case 0xc0206911:
error = sys_ioctl(fd, SIOCGIFFLAGS, arg);
break;
case 0xc020691b:
error = sys_ioctl(fd, SIOCGIFMETRIC, arg);
break;
default: {
#ifdef DEBUG_MISSING_IOCTL
char *msg = "Unimplemented IOCTL cmd tell linux-mips@linux-mips.org\n";
#ifdef DEBUG_IOCTLS
printk("UNIMP_IOCTL, %08lx)\n", arg);
#endif
old_fs = get_fs(); set_fs(get_ds());
sys_write(2, msg, strlen(msg));
set_fs(old_fs);
printk("[%s:%d] Does unimplemented IRIX ioctl cmd %08lx\n",
current->comm, current->pid, cmd);
do_exit(255);
#else
error = sys_ioctl(fd, cmd, arg);
#endif
}
};
#ifdef DEBUG_IOCTLS
printk("error=%d\n", error);
#endif
return error;
}

View File

@@ -1,888 +0,0 @@
/*
* irixsig.c: WHEEE, IRIX signals! YOW, am I compatible or what?!?!
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
* Copyright (C) 1997 - 2000 Ralf Baechle (ralf@gnu.org)
* Copyright (C) 2000 Silicon Graphics, Inc.
*/
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/smp.h>
#include <linux/time.h>
#include <linux/ptrace.h>
#include <linux/resource.h>
#include <asm/ptrace.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#undef DEBUG_SIG
#define _S(nr) (1<<((nr)-1))
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
#define _IRIX_NSIG 128
#define _IRIX_NSIG_BPW BITS_PER_LONG
#define _IRIX_NSIG_WORDS (_IRIX_NSIG / _IRIX_NSIG_BPW)
typedef struct {
unsigned long sig[_IRIX_NSIG_WORDS];
} irix_sigset_t;
struct sigctx_irix5 {
u32 rmask, cp0_status;
u64 pc;
u64 regs[32];
u64 fpregs[32];
u32 usedfp, fpcsr, fpeir, sstk_flags;
u64 hi, lo;
u64 cp0_cause, cp0_badvaddr, _unused0;
irix_sigset_t sigset;
u64 weird_fpu_thing;
u64 _unused1[31];
};
#ifdef DEBUG_SIG
/* Debugging */
static inline void dump_irix5_sigctx(struct sigctx_irix5 *c)
{
int i;
printk("misc: rmask[%08lx] status[%08lx] pc[%08lx]\n",
(unsigned long) c->rmask,
(unsigned long) c->cp0_status,
(unsigned long) c->pc);
printk("regs: ");
for(i = 0; i < 16; i++)
printk("[%d]<%08lx> ", i, (unsigned long) c->regs[i]);
printk("\nregs: ");
for(i = 16; i < 32; i++)
printk("[%d]<%08lx> ", i, (unsigned long) c->regs[i]);
printk("\nfpregs: ");
for(i = 0; i < 16; i++)
printk("[%d]<%08lx> ", i, (unsigned long) c->fpregs[i]);
printk("\nfpregs: ");
for(i = 16; i < 32; i++)
printk("[%d]<%08lx> ", i, (unsigned long) c->fpregs[i]);
printk("misc: usedfp[%d] fpcsr[%08lx] fpeir[%08lx] stk_flgs[%08lx]\n",
(int) c->usedfp, (unsigned long) c->fpcsr,
(unsigned long) c->fpeir, (unsigned long) c->sstk_flags);
printk("misc: hi[%08lx] lo[%08lx] cause[%08lx] badvaddr[%08lx]\n",
(unsigned long) c->hi, (unsigned long) c->lo,
(unsigned long) c->cp0_cause, (unsigned long) c->cp0_badvaddr);
printk("misc: sigset<0>[%08lx] sigset<1>[%08lx] sigset<2>[%08lx] "
"sigset<3>[%08lx]\n", (unsigned long) c->sigset.sig[0],
(unsigned long) c->sigset.sig[1],
(unsigned long) c->sigset.sig[2],
(unsigned long) c->sigset.sig[3]);
}
#endif
static int setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs,
int signr, sigset_t *oldmask)
{
struct sigctx_irix5 __user *ctx;
unsigned long sp;
int error, i;
sp = regs->regs[29];
sp -= sizeof(struct sigctx_irix5);
sp &= ~(0xf);
ctx = (struct sigctx_irix5 __user *) sp;
if (!access_ok(VERIFY_WRITE, ctx, sizeof(*ctx)))
goto segv_and_exit;
error = __put_user(0, &ctx->weird_fpu_thing);
error |= __put_user(~(0x00000001), &ctx->rmask);
error |= __put_user(0, &ctx->regs[0]);
for(i = 1; i < 32; i++)
error |= __put_user((u64) regs->regs[i], &ctx->regs[i]);
error |= __put_user((u64) regs->hi, &ctx->hi);
error |= __put_user((u64) regs->lo, &ctx->lo);
error |= __put_user((u64) regs->cp0_epc, &ctx->pc);
error |= __put_user(!!used_math(), &ctx->usedfp);
error |= __put_user((u64) regs->cp0_cause, &ctx->cp0_cause);
error |= __put_user((u64) regs->cp0_badvaddr, &ctx->cp0_badvaddr);
error |= __put_user(0, &ctx->sstk_flags); /* XXX sigstack unimp... todo... */
error |= __copy_to_user(&ctx->sigset, oldmask, sizeof(irix_sigset_t)) ? -EFAULT : 0;
if (error)
goto segv_and_exit;
#ifdef DEBUG_SIG
dump_irix5_sigctx(ctx);
#endif
regs->regs[4] = (unsigned long) signr;
regs->regs[5] = 0; /* XXX sigcode XXX */
regs->regs[6] = regs->regs[29] = sp;
regs->regs[7] = (unsigned long) ka->sa.sa_handler;
regs->regs[25] = regs->cp0_epc = (unsigned long) ka->sa_restorer;
return 1;
segv_and_exit:
force_sigsegv(signr, current);
return 0;
}
static int inline
setup_irix_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
int signr, sigset_t *oldmask, siginfo_t *info)
{
printk("Aiee: setup_tr_frame wants to be written");
do_exit(SIGSEGV);
}
static inline int handle_signal(unsigned long sig, siginfo_t *info,
struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs)
{
int ret;
switch(regs->regs[0]) {
case ERESTARTNOHAND:
regs->regs[2] = EINTR;
break;
case ERESTARTSYS:
if(!(ka->sa.sa_flags & SA_RESTART)) {
regs->regs[2] = EINTR;
break;
}
/* fallthrough */
case ERESTARTNOINTR: /* Userland will reload $v0. */
regs->cp0_epc -= 8;
}
regs->regs[0] = 0; /* Don't deal with this again. */
if (ka->sa.sa_flags & SA_SIGINFO)
ret = setup_irix_rt_frame(ka, regs, sig, oldset, info);
else
ret = setup_irix_frame(ka, regs, sig, oldset);
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked, sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
return ret;
}
void do_irix_signal(struct pt_regs *regs)
{
struct k_sigaction ka;
siginfo_t info;
int signr;
sigset_t *oldset;
/*
* We want the common case to go fast, which is why we may in certain
* cases get here from kernel mode. Just return without doing anything
* if so.
*/
if (!user_mode(regs))
return;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
/* Whee! Actually deliver the signal. */
if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
/* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return;
}
/*
* Who's code doesn't conform to the restartable syscall convention
* dies here!!! The li instruction, a single machine instruction,
* must directly be followed by the syscall instruction.
*/
if (regs->regs[0]) {
if (regs->regs[2] == ERESTARTNOHAND ||
regs->regs[2] == ERESTARTSYS ||
regs->regs[2] == ERESTARTNOINTR) {
regs->cp0_epc -= 8;
}
if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
regs->regs[2] = __NR_restart_syscall;
regs->regs[7] = regs->regs[26];
regs->cp0_epc -= 4;
}
regs->regs[0] = 0; /* Don't deal with this again. */
}
/*
* If there's no signal to deliver, we just put the saved sigmask
* back
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
}
asmlinkage void
irix_sigreturn(struct pt_regs *regs)
{
struct sigctx_irix5 __user *context, *magic;
unsigned long umask, mask;
u64 *fregs;
u32 usedfp;
int error, sig, i, base = 0;
sigset_t blocked;
/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
if (regs->regs[2] == 1000)
base = 1;
context = (struct sigctx_irix5 __user *) regs->regs[base + 4];
magic = (struct sigctx_irix5 __user *) regs->regs[base + 5];
sig = (int) regs->regs[base + 6];
#ifdef DEBUG_SIG
printk("[%s:%d] IRIX sigreturn(scp[%p],ucp[%p],sig[%d])\n",
current->comm, current->pid, context, magic, sig);
#endif
if (!context)
context = magic;
if (!access_ok(VERIFY_READ, context, sizeof(struct sigctx_irix5)))
goto badframe;
#ifdef DEBUG_SIG
dump_irix5_sigctx(context);
#endif
error = __get_user(regs->cp0_epc, &context->pc);
error |= __get_user(umask, &context->rmask);
mask = 2;
for (i = 1; i < 32; i++, mask <<= 1) {
if (umask & mask)
error |= __get_user(regs->regs[i], &context->regs[i]);
}
error |= __get_user(regs->hi, &context->hi);
error |= __get_user(regs->lo, &context->lo);
error |= __get_user(usedfp, &context->usedfp);
if ((umask & 1) && usedfp) {
fregs = (u64 *) &current->thread.fpu;
for(i = 0; i < 32; i++)
error |= __get_user(fregs[i], &context->fpregs[i]);
error |= __get_user(current->thread.fpu.fcr31, &context->fpcsr);
}
/* XXX do sigstack crapola here... XXX */
error |= __copy_from_user(&blocked, &context->sigset, sizeof(blocked)) ? -EFAULT : 0;
if (error)
goto badframe;
sigdelsetmask(&blocked, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock);
current->blocked = blocked;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
/*
* Don't let your children do this ...
*/
__asm__ __volatile__(
"move\t$29,%0\n\t"
"j\tsyscall_exit"
:/* no outputs */
:"r" (&regs));
/* Unreached */
badframe:
force_sig(SIGSEGV, current);
}
struct sigact_irix5 {
int flags;
void (*handler)(int);
u32 sigset[4];
int _unused0[2];
};
#define SIG_SETMASK32 256 /* Goodie from SGI for BSD compatibility:
set only the low 32 bit of the sigset. */
#ifdef DEBUG_SIG
static inline void dump_sigact_irix5(struct sigact_irix5 *p)
{
printk("<f[%d] hndlr[%08lx] msk[%08lx]>", p->flags,
(unsigned long) p->handler,
(unsigned long) p->sigset[0]);
}
#endif
asmlinkage int
irix_sigaction(int sig, const struct sigaction __user *act,
struct sigaction __user *oact, void __user *trampoline)
{
struct k_sigaction new_ka, old_ka;
int ret;
#ifdef DEBUG_SIG
printk(" (%d,%s,%s,%08lx) ", sig, (!new ? "0" : "NEW"),
(!old ? "0" : "OLD"), trampoline);
if(new) {
dump_sigact_irix5(new); printk(" ");
}
#endif
if (act) {
sigset_t mask;
int err;
if (!access_ok(VERIFY_READ, act, sizeof(*act)))
return -EFAULT;
err = __get_user(new_ka.sa.sa_handler, &act->sa_handler);
err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
err |= __copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t)) ? -EFAULT : 0;
if (err)
return err;
/*
* Hmmm... methinks IRIX libc always passes a valid trampoline
* value for all invocations of sigaction. Will have to
* investigate. POSIX POSIX, die die die...
*/
new_ka.sa_restorer = trampoline;
}
/* XXX Implement SIG_SETMASK32 for IRIX compatibility */
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
int err;
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
return -EFAULT;
err = __put_user(old_ka.sa.sa_handler, &oact->sa_handler);
err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
err |= __copy_to_user(&oact->sa_mask, &old_ka.sa.sa_mask,
sizeof(sigset_t)) ? -EFAULT : 0;
if (err)
return -EFAULT;
}
return ret;
}
asmlinkage int irix_sigpending(irix_sigset_t __user *set)
{
return do_sigpending(set, sizeof(*set));
}
asmlinkage int irix_sigprocmask(int how, irix_sigset_t __user *new,
irix_sigset_t __user *old)
{
sigset_t oldbits, newbits;
if (new) {
if (!access_ok(VERIFY_READ, new, sizeof(*new)))
return -EFAULT;
if (__copy_from_user(&newbits, new, sizeof(unsigned long)*4))
return -EFAULT;
sigdelsetmask(&newbits, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock);
oldbits = current->blocked;
switch(how) {
case 1:
sigorsets(&newbits, &oldbits, &newbits);
break;
case 2:
sigandsets(&newbits, &oldbits, &newbits);
break;
case 3:
break;
case 256:
siginitset(&newbits, newbits.sig[0]);
break;
default:
spin_unlock_irq(&current->sighand->siglock);
return -EINVAL;
}
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
if (old)
return copy_to_user(old, &current->blocked,
sizeof(unsigned long)*4) ? -EFAULT : 0;
return 0;
}
asmlinkage int irix_sigsuspend(struct pt_regs *regs)
{
sigset_t newset;
sigset_t __user *uset;
uset = (sigset_t __user *) regs->regs[4];
if (copy_from_user(&newset, uset, sizeof(sigset_t)))
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock);
current->saved_sigmask = current->blocked;
current->blocked = newset;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
current->state = TASK_INTERRUPTIBLE;
schedule();
set_thread_flag(TIF_RESTORE_SIGMASK);
return -ERESTARTNOHAND;
}
/* hate hate hate... */
struct irix5_siginfo {
int sig, code, error;
union {
char unused[128 - (3 * 4)]; /* Safety net. */
struct {
int pid;
union {
int uid;
struct {
int utime, status, stime;
} child;
} procdata;
} procinfo;
unsigned long fault_addr;
struct {
int fd;
long band;
} fileinfo;
unsigned long sigval;
} stuff;
};
asmlinkage int irix_sigpoll_sys(unsigned long __user *set,
struct irix5_siginfo __user *info, struct timespec __user *tp)
{
long expire = MAX_SCHEDULE_TIMEOUT;
sigset_t kset;
int i, sig, error, timeo = 0;
struct timespec ktp;
#ifdef DEBUG_SIG
printk("[%s:%d] irix_sigpoll_sys(%p,%p,%p)\n",
current->comm, current->pid, set, info, tp);
#endif
/* Must always specify the signal set. */
if (!set)
return -EINVAL;
if (copy_from_user(&kset, set, sizeof(set)))
return -EFAULT;
if (info && clear_user(info, sizeof(*info))) {
error = -EFAULT;
goto out;
}
if (tp) {
if (copy_from_user(&ktp, tp, sizeof(*tp)))
return -EFAULT;
if (!ktp.tv_sec && !ktp.tv_nsec)
return -EINVAL;
expire = timespec_to_jiffies(&ktp) +
(ktp.tv_sec || ktp.tv_nsec);
}
while(1) {
long tmp = 0;
expire = schedule_timeout_interruptible(expire);
for (i=0; i < _IRIX_NSIG_WORDS; i++)
tmp |= (current->pending.signal.sig[i] & kset.sig[i]);
if (tmp)
break;
if (!expire) {
timeo = 1;
break;
}
if (signal_pending(current))
return -EINTR;
}
if (timeo)
return -EAGAIN;
for (sig = 1; i <= 65 /* IRIX_NSIG */; sig++) {
if (sigismember (&kset, sig))
continue;
if (sigismember (&current->pending.signal, sig)) {
/* XXX need more than this... */
if (info)
return copy_to_user(&info->sig, &sig, sizeof(sig));
return 0;
}
}
/* Should not get here, but do something sane if we do. */
error = -EINTR;
out:
return error;
}
/* This is here because of irix5_siginfo definition. */
#define IRIX_P_PID 0
#define IRIX_P_PGID 2
#define IRIX_P_ALL 7
#define W_EXITED 1
#define W_TRAPPED 2
#define W_STOPPED 4
#define W_CONT 8
#define W_NOHANG 64
#define W_MASK (W_EXITED | W_TRAPPED | W_STOPPED | W_CONT | W_NOHANG)
asmlinkage int irix_waitsys(int type, int upid,
struct irix5_siginfo __user *info, int options,
struct rusage __user *ru)
{
struct pid *pid = NULL;
int flag, retval;
DECLARE_WAITQUEUE(wait, current);
struct task_struct *tsk;
struct task_struct *p;
struct list_head *_p;
if (!info)
return -EINVAL;
if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
return -EFAULT;
if (ru)
if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru)))
return -EFAULT;
if (options & ~W_MASK)
return -EINVAL;
if (type != IRIX_P_PID && type != IRIX_P_PGID && type != IRIX_P_ALL)
return -EINVAL;
if (type != IRIX_P_ALL)
pid = find_get_pid(upid);
add_wait_queue(&current->signal->wait_chldexit, &wait);
repeat:
flag = 0;
current->state = TASK_INTERRUPTIBLE;
read_lock(&tasklist_lock);
tsk = current;
list_for_each(_p, &tsk->children) {
p = list_entry(_p, struct task_struct, sibling);
if ((type == IRIX_P_PID) && task_pid(p) != pid)
continue;
if ((type == IRIX_P_PGID) && task_pgrp(p) != pid)
continue;
if ((p->exit_signal != SIGCHLD))
continue;
flag = 1;
switch (p->state) {
case TASK_STOPPED:
if (!p->exit_code)
continue;
if (!(options & (W_TRAPPED|W_STOPPED)) &&
!(p->ptrace & PT_PTRACED))
continue;
read_unlock(&tasklist_lock);
/* move to end of parent's list to avoid starvation */
write_lock_irq(&tasklist_lock);
remove_parent(p);
add_parent(p);
write_unlock_irq(&tasklist_lock);
retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;
if (retval)
goto end_waitsys;
retval = __put_user(SIGCHLD, &info->sig);
retval |= __put_user(0, &info->code);
retval |= __put_user(task_pid_vnr(p), &info->stuff.procinfo.pid);
retval |= __put_user((p->exit_code >> 8) & 0xff,
&info->stuff.procinfo.procdata.child.status);
retval |= __put_user(p->utime, &info->stuff.procinfo.procdata.child.utime);
retval |= __put_user(p->stime, &info->stuff.procinfo.procdata.child.stime);
if (retval)
goto end_waitsys;
p->exit_code = 0;
goto end_waitsys;
case EXIT_ZOMBIE:
current->signal->cutime += p->utime + p->signal->cutime;
current->signal->cstime += p->stime + p->signal->cstime;
if (ru != NULL)
getrusage(p, RUSAGE_BOTH, ru);
retval = __put_user(SIGCHLD, &info->sig);
retval |= __put_user(1, &info->code); /* CLD_EXITED */
retval |= __put_user(task_pid_vnr(p), &info->stuff.procinfo.pid);
retval |= __put_user((p->exit_code >> 8) & 0xff,
&info->stuff.procinfo.procdata.child.status);
retval |= __put_user(p->utime,
&info->stuff.procinfo.procdata.child.utime);
retval |= __put_user(p->stime,
&info->stuff.procinfo.procdata.child.stime);
if (retval)
goto end_waitsys;
if (p->real_parent != p->parent) {
write_lock_irq(&tasklist_lock);
remove_parent(p);
p->parent = p->real_parent;
add_parent(p);
do_notify_parent(p, SIGCHLD);
write_unlock_irq(&tasklist_lock);
} else
release_task(p);
goto end_waitsys;
default:
continue;
}
tsk = next_thread(tsk);
}
read_unlock(&tasklist_lock);
if (flag) {
retval = 0;
if (options & W_NOHANG)
goto end_waitsys;
retval = -ERESTARTSYS;
if (signal_pending(current))
goto end_waitsys;
current->state = TASK_INTERRUPTIBLE;
schedule();
goto repeat;
}
retval = -ECHILD;
end_waitsys:
current->state = TASK_RUNNING;
remove_wait_queue(&current->signal->wait_chldexit, &wait);
put_pid(pid);
return retval;
}
struct irix5_context {
u32 flags;
u32 link;
u32 sigmask[4];
struct { u32 sp, size, flags; } stack;
int regs[36];
u32 fpregs[32];
u32 fpcsr;
u32 _unused0;
u32 _unused1[47];
u32 weird_graphics_thing;
};
asmlinkage int irix_getcontext(struct pt_regs *regs)
{
int error, i, base = 0;
struct irix5_context __user *ctx;
unsigned long flags;
if (regs->regs[2] == 1000)
base = 1;
ctx = (struct irix5_context __user *) regs->regs[base + 4];
#ifdef DEBUG_SIG
printk("[%s:%d] irix_getcontext(%p)\n",
current->comm, current->pid, ctx);
#endif
if (!access_ok(VERIFY_WRITE, ctx, sizeof(*ctx)))
return -EFAULT;
error = __put_user(current->thread.irix_oldctx, &ctx->link);
error |= __copy_to_user(&ctx->sigmask, &current->blocked, sizeof(irix_sigset_t)) ? -EFAULT : 0;
/* XXX Do sigstack stuff someday... */
error |= __put_user(0, &ctx->stack.sp);
error |= __put_user(0, &ctx->stack.size);
error |= __put_user(0, &ctx->stack.flags);
error |= __put_user(0, &ctx->weird_graphics_thing);
error |= __put_user(0, &ctx->regs[0]);
for (i = 1; i < 32; i++)
error |= __put_user(regs->regs[i], &ctx->regs[i]);
error |= __put_user(regs->lo, &ctx->regs[32]);
error |= __put_user(regs->hi, &ctx->regs[33]);
error |= __put_user(regs->cp0_cause, &ctx->regs[34]);
error |= __put_user(regs->cp0_epc, &ctx->regs[35]);
flags = 0x0f;
if (!used_math()) {
flags &= ~(0x08);
} else {
/* XXX wheee... */
printk("Wheee, no code for saving IRIX FPU context yet.\n");
}
error |= __put_user(flags, &ctx->flags);
return error;
}
asmlinkage void irix_setcontext(struct pt_regs *regs)
{
struct irix5_context __user *ctx;
int err, base = 0;
u32 flags;
if (regs->regs[2] == 1000)
base = 1;
ctx = (struct irix5_context __user *) regs->regs[base + 4];
#ifdef DEBUG_SIG
printk("[%s:%d] irix_setcontext(%p)\n",
current->comm, current->pid, ctx);
#endif
if (!access_ok(VERIFY_READ, ctx, sizeof(*ctx)))
goto segv_and_exit;
err = __get_user(flags, &ctx->flags);
if (flags & 0x02) {
/* XXX sigstack garbage, todo... */
printk("Wheee, cannot do sigstack stuff in setcontext\n");
}
if (flags & 0x04) {
int i;
/* XXX extra control block stuff... todo... */
for (i = 1; i < 32; i++)
err |= __get_user(regs->regs[i], &ctx->regs[i]);
err |= __get_user(regs->lo, &ctx->regs[32]);
err |= __get_user(regs->hi, &ctx->regs[33]);
err |= __get_user(regs->cp0_epc, &ctx->regs[35]);
}
if (flags & 0x08)
/* XXX fpu context, blah... */
printk(KERN_ERR "Wheee, cannot restore FPU context yet...\n");
err |= __get_user(current->thread.irix_oldctx, &ctx->link);
if (err)
goto segv_and_exit;
/*
* Don't let your children do this ...
*/
__asm__ __volatile__(
"move\t$29,%0\n\t"
"j\tsyscall_exit"
:/* no outputs */
:"r" (&regs));
/* Unreached */
segv_and_exit:
force_sigsegv(SIGSEGV, current);
}
struct irix_sigstack {
unsigned long sp;
int status;
};
asmlinkage int irix_sigstack(struct irix_sigstack __user *new,
struct irix_sigstack __user *old)
{
#ifdef DEBUG_SIG
printk("[%s:%d] irix_sigstack(%p,%p)\n",
current->comm, current->pid, new, old);
#endif
if (new) {
if (!access_ok(VERIFY_READ, new, sizeof(*new)))
return -EFAULT;
}
if (old) {
if (!access_ok(VERIFY_WRITE, old, sizeof(*old)))
return -EFAULT;
}
return 0;
}
struct irix_sigaltstack { unsigned long sp; int size; int status; };
asmlinkage int irix_sigaltstack(struct irix_sigaltstack __user *new,
struct irix_sigaltstack __user *old)
{
#ifdef DEBUG_SIG
printk("[%s:%d] irix_sigaltstack(%p,%p)\n",
current->comm, current->pid, new, old);
#endif
if (new)
if (!access_ok(VERIFY_READ, new, sizeof(*new)))
return -EFAULT;
if (old) {
if (!access_ok(VERIFY_WRITE, old, sizeof(*old)))
return -EFAULT;
}
return 0;
}
struct irix_procset {
int cmd, ltype, lid, rtype, rid;
};
asmlinkage int irix_sigsendset(struct irix_procset __user *pset, int sig)
{
if (!access_ok(VERIFY_READ, pset, sizeof(*pset)))
return -EFAULT;
#ifdef DEBUG_SIG
printk("[%s:%d] irix_sigsendset([%d,%d,%d,%d,%d],%d)\n",
current->comm, current->pid,
pset->cmd, pset->ltype, pset->lid, pset->rtype, pset->rid,
sig);
#endif
return -EINVAL;
}

View File

@@ -49,7 +49,7 @@ static void local_rm9k_perfcounter_irq_startup(void *args)
static unsigned int rm9k_perfcounter_irq_startup(unsigned int irq)
{
on_each_cpu(local_rm9k_perfcounter_irq_startup, (void *) irq, 0, 1);
on_each_cpu(local_rm9k_perfcounter_irq_startup, (void *) irq, 1);
return 0;
}
@@ -66,7 +66,7 @@ static void local_rm9k_perfcounter_irq_shutdown(void *args)
static void rm9k_perfcounter_irq_shutdown(unsigned int irq)
{
on_each_cpu(local_rm9k_perfcounter_irq_shutdown, (void *) irq, 0, 1);
on_each_cpu(local_rm9k_perfcounter_irq_shutdown, (void *) irq, 1);
}
static struct irq_chip rm9k_irq_controller = {

View File

@@ -44,8 +44,6 @@ again:
return irq;
}
EXPORT_SYMBOL_GPL(allocate_irqno);
/*
* Allocate the 16 legacy interrupts for i8259 devices. This happens early
* in the kernel initialization so treating allocation failure as BUG() is
@@ -66,8 +64,6 @@ void free_irqno(unsigned int irq)
smp_mb__after_clear_bit();
}
EXPORT_SYMBOL_GPL(free_irqno);
/*
* 'what should we do if we get a hw irq event on an illegal vector'.
* each architecture has to answer this themselves.

View File

@@ -4,7 +4,6 @@
*/
#include <linux/device.h>
#include <linux/kallsyms.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/module.h>
@@ -84,9 +83,9 @@ void mips_mt_regdump(unsigned long mvpctl)
read_vpe_c0_vpeconf0());
printk(" VPE%d.Status : %08lx\n",
i, read_vpe_c0_status());
printk(" VPE%d.EPC : %08lx ",
i, read_vpe_c0_epc());
print_symbol("%s\n", read_vpe_c0_epc());
printk(" VPE%d.EPC : %08lx %pS\n",
i, read_vpe_c0_epc(),
(void *) read_vpe_c0_epc());
printk(" VPE%d.Cause : %08lx\n",
i, read_vpe_c0_cause());
printk(" VPE%d.Config7 : %08lx\n",
@@ -111,8 +110,8 @@ void mips_mt_regdump(unsigned long mvpctl)
}
printk(" TCStatus : %08lx\n", tcstatval);
printk(" TCBind : %08lx\n", read_tc_c0_tcbind());
printk(" TCRestart : %08lx ", read_tc_c0_tcrestart());
print_symbol("%s\n", read_tc_c0_tcrestart());
printk(" TCRestart : %08lx %pS\n",
read_tc_c0_tcrestart(), (void *) read_tc_c0_tcrestart());
printk(" TCHalt : %08lx\n", haltval);
printk(" TCContext : %08lx\n", read_tc_c0_tccontext());
if (!haltval)

View File

@@ -125,13 +125,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
*childregs = *regs;
childregs->regs[7] = 0; /* Clear error flag */
#if defined(CONFIG_BINFMT_IRIX)
if (current->personality != PER_LINUX) {
/* Under IRIX things are a little different. */
childregs->regs[3] = 1;
regs->regs[3] = 0;
}
#endif
childregs->regs[2] = 0; /* Child gets zero as return value */
regs->regs[2] = p->pid;

View File

@@ -28,6 +28,7 @@
#include <linux/vmalloc.h>
#include <linux/elf.h>
#include <linux/seq_file.h>
#include <linux/smp_lock.h>
#include <linux/syscalls.h>
#include <linux/moduleloader.h>
#include <linux/interrupt.h>
@@ -392,8 +393,12 @@ out:
static int file_open(struct inode *inode, struct file *filp)
{
int minor = iminor(inode);
int err;
return rtlx_open(minor, (filp->f_flags & O_NONBLOCK) ? 0 : 1);
lock_kernel();
err = rtlx_open(minor, (filp->f_flags & O_NONBLOCK) ? 0 : 1);
unlock_kernel();
return err;
}
static int file_release(struct inode *inode, struct file *filp)

View File

@@ -34,12 +34,8 @@ NESTED(handle_sys, PT_SIZE, sp)
lw t1, PT_EPC(sp) # skip syscall on return
#if defined(CONFIG_BINFMT_IRIX)
sltiu t0, v0, MAX_SYSCALL_NO + 1 # check syscall number
#else
subu v0, v0, __NR_O32_Linux # check syscall number
sltiu t0, v0, __NR_O32_Linux_syscalls + 1
#endif
addiu t1, 4 # skip to next instruction
sw t1, PT_EPC(sp)
beqz t0, illegal_syscall
@@ -264,22 +260,14 @@ bad_alignment:
END(sys_sysmips)
LEAF(sys_syscall)
#if defined(CONFIG_BINFMT_IRIX)
sltiu v0, a0, MAX_SYSCALL_NO + 1 # check syscall number
#else
subu t0, a0, __NR_O32_Linux # check syscall number
sltiu v0, t0, __NR_O32_Linux_syscalls + 1
#endif
sll t1, t0, 3
beqz v0, einval
lw t2, sys_call_table(t1) # syscall routine
#if defined(CONFIG_BINFMT_IRIX)
li v1, 4000 # nr of sys_syscall
#else
li v1, 4000 - __NR_O32_Linux # index of sys_syscall
#endif
beq t0, v1, einval # do not recurse
/* Some syscalls like execve get their arguments from struct pt_regs
@@ -324,13 +312,6 @@ einval: li v0, -EINVAL
.endm
.macro syscalltable
#if defined(CONFIG_BINFMT_IRIX)
mille sys_ni_syscall 0 /* 0 - 999 SVR4 flavour */
mille sys_ni_syscall 0 /* 1000 - 1999 32-bit IRIX */
mille sys_ni_syscall 0 /* 2000 - 2999 BSD43 flavour */
mille sys_ni_syscall 0 /* 3000 - 3999 POSIX flavour */
#endif
sys sys_syscall 8 /* 4000 */
sys sys_exit 1
sys sys_fork 0

View File

@@ -68,13 +68,6 @@ static char command_line[CL_SIZE];
const unsigned long mips_io_port_base __read_mostly = -1;
EXPORT_SYMBOL(mips_io_port_base);
/*
* isa_slot_offset is the address where E(ISA) busaddress 0 is mapped
* for the processor.
*/
unsigned long isa_slot_offset;
EXPORT_SYMBOL(isa_slot_offset);
static struct resource code_resource = { .name = "Kernel code", };
static struct resource data_resource = { .name = "Kernel data", };
@@ -557,11 +550,7 @@ void __init setup_arch(char **cmdline_p)
prom_init();
#ifdef CONFIG_EARLY_PRINTK
{
extern void setup_early_printk(void);
setup_early_printk();
}
setup_early_printk();
#endif
cpu_report();
check_bugs_early();

View File

@@ -131,145 +131,28 @@ asmlinkage __cpuinit void start_secondary(void)
cpu_idle();
}
DEFINE_SPINLOCK(smp_call_lock);
struct call_data_struct *call_data;
void arch_send_call_function_ipi(cpumask_t mask)
{
mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION);
}
/*
* Run a function on all other CPUs.
*
* <mask> cpuset_t of all processors to run the function on.
* <func> The function to run. This must be fast and non-blocking.
* <info> An arbitrary pointer to pass to the function.
* <retry> If true, keep retrying until ready.
* <wait> If true, wait until function has completed on other CPUs.
* [RETURNS] 0 on success, else a negative status code.
*
* Does not return until remote CPUs are nearly ready to execute <func>
* or are or have executed.
*
* You must not call this function with disabled interrupts or from a
* hardware interrupt handler or from a bottom half handler:
*
* CPU A CPU B
* Disable interrupts
* smp_call_function()
* Take call_lock
* Send IPIs
* Wait for all cpus to acknowledge IPI
* CPU A has not responded, spin waiting
* for cpu A to respond, holding call_lock
* smp_call_function()
* Spin waiting for call_lock
* Deadlock Deadlock
* We reuse the same vector for the single IPI
*/
int smp_call_function_mask(cpumask_t mask, void (*func) (void *info),
void *info, int retry, int wait)
void arch_send_call_function_single_ipi(int cpu)
{
struct call_data_struct data;
int cpu = smp_processor_id();
int cpus;
/*
* Can die spectacularly if this CPU isn't yet marked online
*/
BUG_ON(!cpu_online(cpu));
cpu_clear(cpu, mask);
cpus = cpus_weight(mask);
if (!cpus)
return 0;
/* Can deadlock when called with interrupts disabled */
WARN_ON(irqs_disabled());
data.func = func;
data.info = info;
atomic_set(&data.started, 0);
data.wait = wait;
if (wait)
atomic_set(&data.finished, 0);
spin_lock(&smp_call_lock);
call_data = &data;
smp_mb();
/* Send a message to all other CPUs and wait for them to respond */
mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION);
/* Wait for response */
/* FIXME: lock-up detection, backtrace on lock-up */
while (atomic_read(&data.started) != cpus)
barrier();
if (wait)
while (atomic_read(&data.finished) != cpus)
barrier();
call_data = NULL;
spin_unlock(&smp_call_lock);
return 0;
}
int smp_call_function(void (*func) (void *info), void *info, int retry,
int wait)
{
return smp_call_function_mask(cpu_online_map, func, info, retry, wait);
mp_ops->send_ipi_mask(cpumask_of_cpu(cpu), SMP_CALL_FUNCTION);
}
/*
* Call into both interrupt handlers, as we share the IPI for them
*/
void smp_call_function_interrupt(void)
{
void (*func) (void *info) = call_data->func;
void *info = call_data->info;
int wait = call_data->wait;
/*
* Notify initiating CPU that I've grabbed the data and am
* about to execute the function.
*/
smp_mb();
atomic_inc(&call_data->started);
/*
* At this point the info structure may be out of scope unless wait==1.
*/
irq_enter();
(*func)(info);
generic_smp_call_function_single_interrupt();
generic_smp_call_function_interrupt();
irq_exit();
if (wait) {
smp_mb();
atomic_inc(&call_data->finished);
}
}
int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
int retry, int wait)
{
int ret, me;
/*
* Can die spectacularly if this CPU isn't yet marked online
*/
if (!cpu_online(cpu))
return 0;
me = get_cpu();
BUG_ON(!cpu_online(me));
if (cpu == me) {
local_irq_disable();
func(info);
local_irq_enable();
put_cpu();
return 0;
}
ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, retry,
wait);
put_cpu();
return 0;
}
static void stop_this_cpu(void *dummy)
@@ -284,7 +167,7 @@ static void stop_this_cpu(void *dummy)
void smp_send_stop(void)
{
smp_call_function(stop_this_cpu, NULL, 1, 0);
smp_call_function(stop_this_cpu, NULL, 0);
}
void __init smp_cpus_done(unsigned int max_cpus)
@@ -363,7 +246,7 @@ static void flush_tlb_all_ipi(void *info)
void flush_tlb_all(void)
{
on_each_cpu(flush_tlb_all_ipi, NULL, 1, 1);
on_each_cpu(flush_tlb_all_ipi, NULL, 1);
}
static void flush_tlb_mm_ipi(void *mm)
@@ -383,7 +266,7 @@ static void flush_tlb_mm_ipi(void *mm)
static inline void smp_on_other_tlbs(void (*func) (void *info), void *info)
{
#ifndef CONFIG_MIPS_MT_SMTC
smp_call_function(func, info, 1, 1);
smp_call_function(func, info, 1);
#endif
}
@@ -483,7 +366,7 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end)
.addr2 = end,
};
on_each_cpu(flush_tlb_kernel_range_ipi, &fd, 1, 1);
on_each_cpu(flush_tlb_kernel_range_ipi, &fd, 1);
}
static void flush_tlb_page_ipi(void *info)

View File

@@ -877,7 +877,6 @@ static void ipi_resched_interrupt(void)
/* Return from interrupt should be enough to cause scheduler check */
}
static void ipi_call_interrupt(void)
{
/* Invoke generic function invocation code in smp.c */

View File

@@ -73,3 +73,4 @@ void save_stack_trace(struct stack_trace *trace)
prepare_frametrace(regs);
save_context_stack(trace, regs);
}
EXPORT_SYMBOL_GPL(save_stack_trace);

File diff suppressed because it is too large Load Diff

View File

@@ -71,7 +71,6 @@ extern asmlinkage void handle_reserved(void);
extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
struct mips_fpu_struct *ctx, int has_fpu);
void (*board_watchpoint_handler)(struct pt_regs *regs);
void (*board_be_init)(void);
int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
void (*board_nmi_handler_setup)(void);
@@ -88,15 +87,17 @@ static void show_raw_backtrace(unsigned long reg29)
#ifdef CONFIG_KALLSYMS
printk("\n");
#endif
#define IS_KVA01(a) ((((unsigned int)a) & 0xc0000000) == 0x80000000)
if (IS_KVA01(sp)) {
while (!kstack_end(sp)) {
addr = *sp++;
if (__kernel_text_address(addr))
print_ip_sym(addr);
while (!kstack_end(sp)) {
unsigned long __user *p =
(unsigned long __user *)(unsigned long)sp++;
if (__get_user(addr, p)) {
printk(" (Bad stack address)");
break;
}
printk("\n");
if (__kernel_text_address(addr))
print_ip_sym(addr);
}
printk("\n");
}
#ifdef CONFIG_KALLSYMS
@@ -247,11 +248,11 @@ static void __show_regs(const struct pt_regs *regs)
/*
* Saved cp0 registers
*/
printk("epc : %0*lx ", field, regs->cp0_epc);
print_symbol("%s ", regs->cp0_epc);
printk("epc : %0*lx %pS\n", field, regs->cp0_epc,
(void *) regs->cp0_epc);
printk(" %s\n", print_tainted());
printk("ra : %0*lx ", field, regs->regs[31]);
print_symbol("%s\n", regs->regs[31]);
printk("ra : %0*lx %pS\n", field, regs->regs[31],
(void *) regs->regs[31]);
printk("Status: %08x ", (uint32_t) regs->cp0_status);
@@ -890,11 +891,6 @@ asmlinkage void do_mdmx(struct pt_regs *regs)
asmlinkage void do_watch(struct pt_regs *regs)
{
if (board_watchpoint_handler) {
(*board_watchpoint_handler)(regs);
return;
}
/*
* We use the watch exception where available to detect stack
* overflows.

View File

@@ -38,6 +38,7 @@
#include <linux/vmalloc.h>
#include <linux/elf.h>
#include <linux/seq_file.h>
#include <linux/smp_lock.h>
#include <linux/syscalls.h>
#include <linux/moduleloader.h>
#include <linux/interrupt.h>
@@ -1050,17 +1051,20 @@ static int vpe_open(struct inode *inode, struct file *filp)
enum vpe_state state;
struct vpe_notifications *not;
struct vpe *v;
int ret;
int ret, err = 0;
lock_kernel();
if (minor != iminor(inode)) {
/* assume only 1 device at the moment. */
printk(KERN_WARNING "VPE loader: only vpe1 is supported\n");
return -ENODEV;
err = -ENODEV;
goto out;
}
if ((v = get_vpe(tclimit)) == NULL) {
printk(KERN_WARNING "VPE loader: unable to get vpe\n");
return -ENODEV;
err = -ENODEV;
goto out;
}
state = xchg(&v->state, VPE_STATE_INUSE);
@@ -1100,6 +1104,8 @@ static int vpe_open(struct inode *inode, struct file *filp)
v->shared_ptr = NULL;
v->__start = 0;
out:
unlock_kernel();
return 0;
}