Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 574009c1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus:
  [MIPS] signal: do not inline handle_signal()
  [MIPS] signal: do not use save_static_function() anymore
  [MIPS] signal32: no need to save c0_status register in setup_sigcontext32()
  [MIPS] signal32: reduce {setup,restore}_sigcontext32 sizes
  [MIPS] signal: factorize debug code
  [MIPS] signal: test return value of install_sigtramp()
  [MIPS] signal32: remove duplicate code
  [MIPS] signal: clean up sigframe structure
  [MIPS] signal: do not inline functions in signal-common.h
  [MIPS] signals: reduce {setup,restore}_sigcontext sizes
  [MIPS] Fix warning in get_user when fetching pointer object from userspace.
  [MIPS] Fix eth2 platform device id for jaguar_atx and ocelot_3 platforms
  [MIPS] JMR3927 and RBTX49x7 support little endian
  [MIPS] RBTX49x7: declare prom_getcmdline()
  [MIPS] RTLX: Sprinkle device model code into code to make udev happier.
  [MIPS] VPE: Sprinkle device model code into code to make udev happier.
parents a727fea9 e692eb30
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -757,6 +757,7 @@ config TOSHIBA_JMR3927
	select SWAP_IO_SPACE
	select SYS_HAS_CPU_TX39XX
	select SYS_SUPPORTS_32BIT_KERNEL
	select SYS_SUPPORTS_LITTLE_ENDIAN
	select SYS_SUPPORTS_BIG_ENDIAN
	select TOSHIBA_BOARDS

@@ -771,6 +772,7 @@ config TOSHIBA_RBTX4927
	select SYS_HAS_CPU_TX49XX
	select SYS_SUPPORTS_32BIT_KERNEL
	select SYS_SUPPORTS_64BIT_KERNEL
	select SYS_SUPPORTS_LITTLE_ENDIAN
	select SYS_SUPPORTS_BIG_ENDIAN
	select TOSHIBA_BOARDS
	select GENERIC_HARDIRQS_NO__DO_IRQ
+0 −1
Original line number Diff line number Diff line
@@ -249,7 +249,6 @@ void output_sc_defines(void)
	offset("#define SC_MDHI       ", struct sigcontext, sc_mdhi);
	offset("#define SC_MDLO       ", struct sigcontext, sc_mdlo);
	offset("#define SC_PC         ", struct sigcontext, sc_pc);
	offset("#define SC_STATUS     ", struct sigcontext, sc_status);
	offset("#define SC_FPC_CSR    ", struct sigcontext, sc_fpc_csr);
	offset("#define SC_FPC_EIR    ", struct sigcontext, sc_fpc_eir);
	offset("#define SC_HI1        ", struct sigcontext, sc_hi1);
+19 −0
Original line number Diff line number Diff line
@@ -3,9 +3,11 @@
 * Copyright (C) 2005 Mips Technologies, Inc
 */

#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/cpumask.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/security.h>

@@ -453,3 +455,20 @@ void mt_cflush_release(void)
#endif /* CONFIG_MIPS_MT_SMTC */
	/* FILL IN VSMP and AP/SP VERSIONS HERE */
}

struct class *mt_class;

static int __init mt_init(void)
{
	struct class *mtc;

	mtc = class_create(THIS_MODULE, "mt");
	if (IS_ERR(mtc))
		return PTR_ERR(mtc);

	mt_class = mtc;

	return 0;
}

subsys_initcall(mt_init);
+22 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
 *
 */

#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
@@ -34,6 +35,7 @@
#include <linux/sched.h>
#include <linux/wait.h>
#include <asm/mipsmtregs.h>
#include <asm/mips_mt.h>
#include <asm/cacheflush.h>
#include <asm/atomic.h>
#include <asm/cpu.h>
@@ -498,7 +500,8 @@ static char register_chrdev_failed[] __initdata =

static int rtlx_module_init(void)
{
	int i;
	struct device *dev;
	int i, err;

	major = register_chrdev(0, module_name, &rtlx_fops);
	if (major < 0) {
@@ -511,6 +514,13 @@ static int rtlx_module_init(void)
		init_waitqueue_head(&channel_wqs[i].rt_queue);
		init_waitqueue_head(&channel_wqs[i].lx_queue);
		channel_wqs[i].in_open = 0;

		dev = device_create(mt_class, NULL, MKDEV(major, i),
		                    "%s%d", module_name, i);
		if (IS_ERR(dev)) {
			err = PTR_ERR(dev);
			goto out_chrdev;
		}
	}

	/* set up notifiers */
@@ -525,10 +535,21 @@ static int rtlx_module_init(void)
	setup_irq(rtlx_irq_num, &rtlx_irq);

	return 0;

out_chrdev:
	for (i = 0; i < RTLX_CHANNELS; i++)
		device_destroy(mt_class, MKDEV(major, i));

	return err;
}

static void __exit rtlx_module_exit(void)
{
	int i;

	for (i = 0; i < RTLX_CHANNELS; i++)
		device_destroy(mt_class, MKDEV(major, i));

	unregister_chrdev(major, module_name);
}

+41 −153
Original line number Diff line number Diff line
@@ -8,169 +8,57 @@
 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
 */

#ifndef __SIGNAL_COMMON_H
#define __SIGNAL_COMMON_H

static inline int
setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
{
	int err = 0;
/* #define DEBUG_SIG */

	err |= __put_user(regs->cp0_epc, &sc->sc_pc);

#define save_gp_reg(i) do {						\
	err |= __put_user(regs->regs[i], &sc->sc_regs[i]);		\
} while(0)
	__put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
	save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
	save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
	save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
	save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
	save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
	save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
	save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
	save_gp_reg(31);
#undef save_gp_reg

	err |= __put_user(regs->hi, &sc->sc_mdhi);
	err |= __put_user(regs->lo, &sc->sc_mdlo);
	if (cpu_has_dsp) {
		err |= __put_user(mfhi1(), &sc->sc_hi1);
		err |= __put_user(mflo1(), &sc->sc_lo1);
		err |= __put_user(mfhi2(), &sc->sc_hi2);
		err |= __put_user(mflo2(), &sc->sc_lo2);
		err |= __put_user(mfhi3(), &sc->sc_hi3);
		err |= __put_user(mflo3(), &sc->sc_lo3);
		err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
	}

	err |= __put_user(!!used_math(), &sc->sc_used_math);

	if (!used_math())
		goto out;
#ifdef DEBUG_SIG
#  define DEBUGP(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ##args)
#else
#  define DEBUGP(fmt, args...)
#endif

/*
	 * Save FPU state to signal context.  Signal handler will "inherit"
	 * current FPU state.
 * Horribly complicated - with the bloody RM9000 workarounds enabled
 * the signal trampolines is moving to the end of the structure so we can
 * increase the alignment without breaking software compatibility.
 */
	preempt_disable();

	if (!is_fpu_owner()) {
		own_fpu();
		restore_fp(current);
	}
	err |= save_fp_context(sc);

	preempt_enable();

out:
	return err;
}

static inline int
restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
{
	unsigned int used_math;
	unsigned long treg;
	int err = 0;

	/* Always make any pending restarted system calls return -EINTR */
	current_thread_info()->restart_block.fn = do_no_restart_syscall;

	err |= __get_user(regs->cp0_epc, &sc->sc_pc);
	err |= __get_user(regs->hi, &sc->sc_mdhi);
	err |= __get_user(regs->lo, &sc->sc_mdlo);
	if (cpu_has_dsp) {
		err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
		err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
		err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
		err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
		err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
		err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
		err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
	}

#define restore_gp_reg(i) do {						\
	err |= __get_user(regs->regs[i], &sc->sc_regs[i]);		\
} while(0)
	restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
	restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
	restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
	restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
	restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
	restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
	restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
	restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
	restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
	restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
	restore_gp_reg(31);
#undef restore_gp_reg
#if ICACHE_REFILLS_WORKAROUND_WAR == 0

	err |= __get_user(used_math, &sc->sc_used_math);
	conditional_used_math(used_math);
struct sigframe {
	u32 sf_ass[4];		/* argument save space for o32 */
	u32 sf_code[2];		/* signal trampoline */
	struct sigcontext sf_sc;
	sigset_t sf_mask;
};

	preempt_disable();
#else  /* ICACHE_REFILLS_WORKAROUND_WAR */

	if (used_math()) {
		/* restore fpu context if we have used it before */
		own_fpu();
		err |= restore_fp_context(sc);
	} else {
		/* signal handler may have used FPU.  Give it up. */
		lose_fpu();
	}
struct sigframe {
	u32 sf_ass[4];			/* argument save space for o32 */
	u32 sf_pad[2];
	struct sigcontext sf_sc;	/* hw context */
	sigset_t sf_mask;
	u32 sf_code[8] ____cacheline_aligned;	/* signal trampoline */
};

	preempt_enable();

	return err;
}
#endif	/* !ICACHE_REFILLS_WORKAROUND_WAR */

/*
 * Determine which stack to use..
 * handle hardware context
 */
static inline void __user *
get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
{
	unsigned long sp;

	/* Default to using normal stack */
	sp = regs->regs[29];
extern int setup_sigcontext(struct pt_regs *, struct sigcontext __user *);
extern int restore_sigcontext(struct pt_regs *, struct sigcontext __user *);

/*
	 * FPU emulator may have it's own trampoline active just
	 * above the user stack, 16-bytes before the next lowest
	 * 16 byte boundary.  Try to avoid trashing it.
 * Determine which stack to use..
 */
	sp -= 32;

	/* This is the X/Open sanctioned signal stack switching.  */
	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
		sp = current->sas_ss_sp + current->sas_ss_size;

	return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK));
}

static inline int install_sigtramp(unsigned int __user *tramp,
	unsigned int syscall)
{
	int err;

extern void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
				 size_t frame_size);
/*
	 * Set up the return code ...
	 *
	 *         li      v0, __NR__foo_sigreturn
	 *         syscall
 * install trampoline code to get back from the sig handler
 */
extern int install_sigtramp(unsigned int __user *tramp, unsigned int syscall);

	err = __put_user(0x24020000 + syscall, tramp + 0);
	err |= __put_user(0x0000000c          , tramp + 1);
	if (ICACHE_REFILLS_WORKAROUND_WAR) {
		err |= __put_user(0, tramp + 2);
		err |= __put_user(0, tramp + 3);
		err |= __put_user(0, tramp + 4);
		err |= __put_user(0, tramp + 5);
		err |= __put_user(0, tramp + 6);
		err |= __put_user(0, tramp + 7);
	}
	flush_cache_sigtramp((unsigned long) tramp);

	return err;
}
#endif	/* __SIGNAL_COMMON_H */
Loading